diff -Nru libwoodstox-java-4.1.3/build.xml libwoodstox-java-5.1.0/build.xml --- libwoodstox-java-4.1.3/build.xml 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/build.xml 1970-01-01 00:00:00.000000000 +0000 @@ -1,533 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff -Nru libwoodstox-java-4.1.3/debian/changelog libwoodstox-java-5.1.0/debian/changelog --- libwoodstox-java-4.1.3/debian/changelog 2012-06-22 13:42:41.000000000 +0000 +++ libwoodstox-java-5.1.0/debian/changelog 2019-02-19 15:26:16.000000000 +0000 @@ -1,3 +1,53 @@ +libwoodstox-java (1:5.1.0-2~18.04) bionic; urgency=medium + + * Provide Java EE modules and APIs removed from OpenJDK 11. LP: #1784196. + * No-change backport from 18.10. + + -- Matthias Klose Tue, 19 Feb 2019 16:26:16 +0100 + +libwoodstox-java (1:5.1.0-2) unstable; urgency=medium + + * Team upload. + * Removed the build dependency on libstax-java + * Standards-Version updated to 4.2.1 + * Simplified debian/rules + + -- Emmanuel Bourg Thu, 06 Sep 2018 17:23:02 +0200 + +libwoodstox-java (1:5.1.0-1) unstable; urgency=medium + + * New upstream release. + + Update dependencies accordingly. + * Update Vcs-* after moving to salsa. + * Update to debhelper 11. + * Bump Standards-Version to 4.1.4. + * Create compatibility symbolic links for woodstox-core-lgpl.jar and + woodstox-core-asl.jar. + + -- Giovanni Mascellani Sat, 23 Jun 2018 16:09:36 +0200 + +libwoodstox-java (1:5.0.3-2) experimental; urgency=medium + + * Install POM relocations for backward compatibility. + * Fix insufficient dependency. + + -- Giovanni Mascellani Fri, 03 Nov 2017 16:10:16 +0100 + +libwoodstox-java (1:5.0.3-1) experimental; urgency=medium + + * Move the package to git. + + Update Vcs-* fields accordingly. + * Update project homepage and debian/watch URL. + * New upstream release. + + The distinction between -lgpl and -asl artifacts has vanished (closes: + #786550). + * Remove traces of tarball sanitizer, which is not required anymore. + * Switch build system to dh 10. + * Update debian/copyright. + * Bump Standards-Version to 4.1.1 (no changes required). + + -- Giovanni Mascellani Fri, 03 Nov 2017 14:52:36 +0100 + libwoodstox-java (1:4.1.3-1) unstable; urgency=low * New upstream release. @@ -73,7 +123,7 @@ libwoodstox-java (1:3.9.2.dfsg-1ubuntu1) intrepid; urgency=low - * remove java specific dependencies and icedtea-java7-jre NBS (LP: #203636) + * remove java specific dependencies and icedtea-java7-jre NBS (LP: #203636) -- Didier Roche Sat, 30 Aug 2008 10:36:00 +0200 diff -Nru libwoodstox-java-4.1.3/debian/compat libwoodstox-java-5.1.0/debian/compat --- libwoodstox-java-4.1.3/debian/compat 2007-12-29 14:06:53.000000000 +0000 +++ libwoodstox-java-5.1.0/debian/compat 2018-09-06 15:17:06.000000000 +0000 @@ -1 +1 @@ -5 +11 diff -Nru libwoodstox-java-4.1.3/debian/control libwoodstox-java-5.1.0/debian/control --- libwoodstox-java-4.1.3/debian/control 2012-05-20 10:39:27.000000000 +0000 +++ libwoodstox-java-5.1.0/debian/control 2018-09-06 15:19:58.000000000 +0000 @@ -3,23 +3,35 @@ Priority: optional Maintainer: Debian Java Maintainers Uploaders: Giovanni Mascellani -Build-Depends-Indep: ant, ant-optional, ant-contrib, default-jdk, junit4, - libmsv-java, libstax2-api-java, librelaxng-datatype-java, - libknopflerfish-osgi-framework-java, libstax-java -Build-Depends: cdbs, debhelper (>= 5), maven-repo-helper (>= 1.4) -Standards-Version: 3.9.3 -Homepage: http://woodstox.codehaus.org/ -Vcs-Svn: svn://svn.debian.org/svn/pkg-java/packages/trunk/libwoodstox-java/ -Vcs-Browser: http://svn.debian.org/wsvn/pkg-java/packages/trunk/libwoodstox-java/ +Build-Depends: + debhelper (>= 11), + default-jdk, + junit4, + libknopflerfish-osgi-framework-java, + libmaven-bundle-plugin-java, + libmaven-compiler-plugin-java, + libmaven-javadoc-plugin-java, + libmsv-java, + librelaxng-datatype-java, + libstax2-api-java (>= 4.1), + maven-debian-helper +Standards-Version: 4.2.1 +Vcs-Browser: https://salsa.debian.org/java-team/libwoodstox-java +Vcs-Git: https://salsa.debian.org/java-team/libwoodstox-java.git +Homepage: https://github.com/FasterXML/woodstox Package: libwoodstox-java Architecture: all -Depends: ${misc:Depends}, libmsv-java, libstax2-api-java, - librelaxng-datatype-java, libknopflerfish-osgi-framework-java, - libstax-java +Depends: + libknopflerfish-osgi-framework-java, + libmsv-java, + librelaxng-datatype-java, + libstax2-api-java (>= 4.1), + ${maven:Depends}, + ${misc:Depends} Description: High-performance XML processor Woodstox is a high-performance, validating, namespace-aware, StAX-compliant (JSR-173), open source XML-processor written in Java. XML processor means that it handles both input (parsing) and output (writing, serialization), as well as supporting tasks such - as validation. + as validation. diff -Nru libwoodstox-java-4.1.3/debian/copyright libwoodstox-java-5.1.0/debian/copyright --- libwoodstox-java-4.1.3/debian/copyright 2012-05-20 10:39:27.000000000 +0000 +++ libwoodstox-java-5.1.0/debian/copyright 2018-09-06 15:17:06.000000000 +0000 @@ -1,24 +1,26 @@ -Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ +Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ Upstream-Name: Woodstox -Upstream-Contact: Tatu Saloranta -Source: http://wiki.fasterxml.com/WoodstoxDownload +Upstream-Contact: Tatu Saloranta +Source: https://github.com/FasterXML/woodstox Files: * -Copyright: © 2004-2011, Tatu Saloranta -License: LGPL-2.1+ or Apache-2.0 -Comment: There is no files explicitly stating the license for upstream files. - Anyway, the licenses are clearly stated on the download page (see above) - and in the woodstox-core tarball, that is distributed along with - this package. +Copyright: © 2004-2018, Tatu Saloranta + © 2010-2018, FasterXML.com +License: Apache-2.0 + On Debian systems, a copy of the Apache license version 2.0 is + available in '/usr/share/common-licenses/Apache-2.0'. +Comment: While not stated explicitly in the sources contained in this + package, the licensing information is reported in the upstream wiki + page at https://github.com/FasterXML/woodstox/wiki. -Files: test/org/codehaus/stax/test/stream/TestProcInstrRead.java +Files: src/test/java/org/codehaus/stax/test/stream/TestProcInstrRead.java Copyright: © 2003, Richard Tobin License: free May be freely redistributed provided copyright notice is retained. Files: debian/* Copyright: © 2007, Vincent Fourmond - © 2011-2012, Giovanni Mascellani + © 2011-2018, Giovanni Mascellani License: GPL-2+ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -38,29 +40,3 @@ is available in '/usr/share/common-licenses/GPL-2'. Comment: This packaging is based on that of libwoodstox-java, by Vincent Fourmond. - -License: LGPL-2.1+ - This copy of Woodstox XML processor is licensed under the - Lesser General Public License (LGPL), version 2.1 ("the License"). - See the License for details about distribution rights, and the - specific rights regarding derivate works. - . - You may obtain a copy of the License at: - . - http://www.gnu.org/licenses/licenses.html - . - On Debian systems, a copy of the GNU Lesser General Public License - version 2.1 is available in '/usr/share/common-licenses/LGPL-2.1'. - -License: Apache-2.0 - This copy of Woodstox XML processor is licensed under the - Apache (Software) License, version 2.0 ("the License"). - See the License for details about distribution rights, and the - specific rights regarding derivate works. - . - You may obtain a copy of the License at: - . - http://www.apache.org/licenses/ - . - On Debian systems, a copy of the Apache license version 2.0 is available - in '/usr/share/common-licenses/Apache-2.0'. diff -Nru libwoodstox-java-4.1.3/debian/docs libwoodstox-java-5.1.0/debian/docs --- libwoodstox-java-4.1.3/debian/docs 2011-08-21 08:55:42.000000000 +0000 +++ libwoodstox-java-5.1.0/debian/docs 1970-01-01 00:00:00.000000000 +0000 @@ -1,11 +0,0 @@ -release-notes/COMPATIBILITY -release-notes/FAAQ -release-notes/CREDITS -release-notes/STAX2.txt -release-notes/stax-compatibility.txt -release-notes/xml-compatibility.txt -release-notes/IMPL_DETAILS -release-notes/USAGE -release-notes/VERSION -release-notes/PERF -release-notes/README diff -Nru libwoodstox-java-4.1.3/debian/libwoodstox-java.links libwoodstox-java-5.1.0/debian/libwoodstox-java.links --- libwoodstox-java-4.1.3/debian/libwoodstox-java.links 2012-01-11 13:41:58.000000000 +0000 +++ libwoodstox-java-5.1.0/debian/libwoodstox-java.links 2018-09-06 15:17:45.000000000 +0000 @@ -1 +1,2 @@ -usr/share/java/woodstox-core-lgpl.jar usr/share/java/wstx-lgpl.jar +usr/share/java/woodstox-core.jar usr/share/java/woodstox-core-asl.jar +usr/share/java/woodstox-core.jar usr/share/java/woodstox-core-lgpl.jar diff -Nru libwoodstox-java-4.1.3/debian/libwoodstox-java.poms libwoodstox-java-5.1.0/debian/libwoodstox-java.poms --- libwoodstox-java-4.1.3/debian/libwoodstox-java.poms 2011-08-21 08:59:10.000000000 +0000 +++ libwoodstox-java-5.1.0/debian/libwoodstox-java.poms 2018-09-06 15:17:06.000000000 +0000 @@ -1 +1 @@ -woodstox-core-lgpl.patched.pom --has-package-version --artifact=dist/woodstox-core.jar --java-lib +pom.xml --no-parent --relocate=org.codehaus.woodstox:woodstox-core-lgpl,org.codehaus.woodstox:woodstox-core-asl diff -Nru libwoodstox-java-4.1.3/debian/maven.rules libwoodstox-java-5.1.0/debian/maven.rules --- libwoodstox-java-4.1.3/debian/maven.rules 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/debian/maven.rules 2018-09-06 15:17:06.000000000 +0000 @@ -0,0 +1,4 @@ +s/javax.xml.stream/stax/ stax-api * s/.*/debian/ * * +s/net.java.dev.msv/com.sun.msv.datatype.xsd/ xsdlib * s/.*/debian/ * * +s/org.apache.felix/org.osgi/ org.osgi.core * s/.*/debian/ * * +junit junit * s/.*/4.x/ * * diff -Nru libwoodstox-java-4.1.3/debian/orig-tar.sh libwoodstox-java-5.1.0/debian/orig-tar.sh --- libwoodstox-java-4.1.3/debian/orig-tar.sh 2010-05-08 10:44:00.000000000 +0000 +++ libwoodstox-java-5.1.0/debian/orig-tar.sh 1970-01-01 00:00:00.000000000 +0000 @@ -1,18 +0,0 @@ -#!/bin/sh -e - -# called by uscan with '--upstream-version' - -TAR=../libwoodstox-java_$2.orig.tar.gz -DIR=woodstox-$2 - -# clean up the upstream tarball -tar -x -z -f $TAR -tar -c -z -f $TAR --exclude '*.jar' $DIR -rm -rf $DIR - -# move to directory 'tarballs' -if [ -r .svn/deb-layout ]; then - . .svn/deb-layout - mv $TAR $origDir - echo "moved $TAR to $origDir" -fi diff -Nru libwoodstox-java-4.1.3/debian/patches/0001-Fix-interface-mismatch-between-woodstox-and-osgi.patch libwoodstox-java-5.1.0/debian/patches/0001-Fix-interface-mismatch-between-woodstox-and-osgi.patch --- libwoodstox-java-4.1.3/debian/patches/0001-Fix-interface-mismatch-between-woodstox-and-osgi.patch 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/debian/patches/0001-Fix-interface-mismatch-between-woodstox-and-osgi.patch 2018-09-06 15:17:06.000000000 +0000 @@ -0,0 +1,45 @@ +From: Giovanni Mascellani +Date: Sat, 10 Sep 2016 17:58:31 +0200 +Subject: Fix interface mismatch between woodstox and osgi. + +In registerService() recent osgi versions expect properties to be +passed as a Dictionary object , while woodstox tries to +pass a Properties object, which implements Dictionary (which actually contains elements of type ). + +In this patch the Java type checker is forced to accept this code +by converting the object to an intermediate Hashtable type, without +specifying generic types. +--- + src/main/java/com/ctc/wstx/osgi/WstxBundleActivator.java | 8 +++++--- + 1 file changed, 5 insertions(+), 3 deletions(-) + +diff --git a/src/main/java/com/ctc/wstx/osgi/WstxBundleActivator.java b/src/main/java/com/ctc/wstx/osgi/WstxBundleActivator.java +index 0ad8402..37d9cb9 100644 +--- a/src/main/java/com/ctc/wstx/osgi/WstxBundleActivator.java ++++ b/src/main/java/com/ctc/wstx/osgi/WstxBundleActivator.java +@@ -1,5 +1,7 @@ + package com.ctc.wstx.osgi; + ++import java.util.Hashtable; ++ + import org.osgi.framework.BundleActivator; + import org.osgi.framework.BundleContext; + +@@ -27,13 +29,13 @@ public class WstxBundleActivator + public void start(BundleContext ctxt) + { + InputFactoryProviderImpl inputP = new InputFactoryProviderImpl(); +- ctxt.registerService(Stax2InputFactoryProvider.class.getName(), inputP, inputP.getProperties()); ++ ctxt.registerService(Stax2InputFactoryProvider.class.getName(), inputP, new Hashtable(inputP.getProperties())); + OutputFactoryProviderImpl outputP = new OutputFactoryProviderImpl(); +- ctxt.registerService(Stax2OutputFactoryProvider.class.getName(), outputP, outputP.getProperties()); ++ ctxt.registerService(Stax2OutputFactoryProvider.class.getName(), outputP, new Hashtable(outputP.getProperties())); + ValidationSchemaFactoryProviderImpl[] impls = ValidationSchemaFactoryProviderImpl.createAll(); + for (int i = 0, len = impls.length; i < len; ++i) { + ValidationSchemaFactoryProviderImpl impl = impls[i]; +- ctxt.registerService(Stax2ValidationSchemaFactoryProvider.class.getName(), impl, impl.getProperties()); ++ ctxt.registerService(Stax2ValidationSchemaFactoryProvider.class.getName(), impl, new Hashtable(impl.getProperties())); + } + } + diff -Nru libwoodstox-java-4.1.3/debian/patches/0002-Fix-a-test.patch libwoodstox-java-5.1.0/debian/patches/0002-Fix-a-test.patch --- libwoodstox-java-4.1.3/debian/patches/0002-Fix-a-test.patch 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/debian/patches/0002-Fix-a-test.patch 2018-09-06 15:17:06.000000000 +0000 @@ -0,0 +1,26 @@ +From: Giovanni Mascellani +Date: Sat, 10 Sep 2016 18:37:27 +0200 +Subject: Fix a test. + +A woodstox test depends on an error string being returned in English, +so is broken when a different locale is set. + +This patch tests the exception class name instead of its message, +which does not depend on the locale. +--- + src/test/java/wstxtest/sax/TestEntityResolver.java | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/test/java/wstxtest/sax/TestEntityResolver.java b/src/test/java/wstxtest/sax/TestEntityResolver.java +index 1b3e890..bd294dc 100644 +--- a/src/test/java/wstxtest/sax/TestEntityResolver.java ++++ b/src/test/java/wstxtest/sax/TestEntityResolver.java +@@ -38,7 +38,7 @@ public class TestEntityResolver + try { + sp.parse(new InputSource(new StringReader(XML)), h); + } catch (SAXException e) { +- verifyException(e, "No such file or directory"); ++ verifyException(e, "java.io.FileNotFoundException"); + } + + // And then with dummy resolver; should work ok now diff -Nru libwoodstox-java-4.1.3/debian/patches/10-fix-build.xml libwoodstox-java-5.1.0/debian/patches/10-fix-build.xml --- libwoodstox-java-4.1.3/debian/patches/10-fix-build.xml 2011-08-21 08:42:04.000000000 +0000 +++ libwoodstox-java-5.1.0/debian/patches/10-fix-build.xml 1970-01-01 00:00:00.000000000 +0000 @@ -1,87 +0,0 @@ -From: Giovanni Mascellani -Subject: Fix build.xml -Last-Update: 2011-08-21 -Forwarded: not-needed - -This patch fixed build.xml file. It does these changes: - * Put in the classpath libraries from Debian packages, instead - of the bundled JARs; - * Use Debian-distributed JAR for stax2-api instead of assuming - to have copy of the code in the compilation tree; - * Reduce the dist target to only things needed for Debian. - -Index: libwoodstox-java/build.xml -=================================================================== ---- libwoodstox-java.orig/build.xml 2011-08-21 10:34:06.000000000 +0200 -+++ libwoodstox-java/build.xml 2011-08-21 10:36:01.000000000 +0200 -@@ -57,14 +57,13 @@ - - - -- -- -- -- -- -- -+ -+ -+ -+ -+ -+ -+ - - - -@@ -102,11 +101,6 @@ - - - -- -- -- -- -- - - - -@@ -208,7 +202,7 @@ - - - -- -+ - -- -+ - - diff -Nru libwoodstox-java-4.1.3/debian/patches/20-testsuite-enable libwoodstox-java-5.1.0/debian/patches/20-testsuite-enable --- libwoodstox-java-4.1.3/debian/patches/20-testsuite-enable 2012-01-11 12:35:50.000000000 +0000 +++ libwoodstox-java-5.1.0/debian/patches/20-testsuite-enable 1970-01-01 00:00:00.000000000 +0000 @@ -1,40 +0,0 @@ -From: Thierry Carrez -Subject: Enable test suite -Last-Update: 2012-10-11 -Forwarded: not-needed - -Enable test suite, but don't fail even if some test goes wrong. - -Index: libwoodstox-java/build.xml -=================================================================== ---- libwoodstox-java.orig/build.xml 2011-08-21 11:00:48.000000000 +0200 -+++ libwoodstox-java/build.xml 2011-08-21 11:26:23.000000000 +0200 -@@ -476,7 +476,6 @@ - - - -- - - - -@@ -494,9 +493,7 @@ - - - -- - -- - - - -@@ -522,10 +519,8 @@ - - - -- - - -- - - - diff -Nru libwoodstox-java-4.1.3/debian/patches/series libwoodstox-java-5.1.0/debian/patches/series --- libwoodstox-java-4.1.3/debian/patches/series 2012-01-11 12:35:50.000000000 +0000 +++ libwoodstox-java-5.1.0/debian/patches/series 2018-09-06 15:17:06.000000000 +0000 @@ -1,2 +1,2 @@ -10-fix-build.xml -20-testsuite-enable +0001-Fix-interface-mismatch-between-woodstox-and-osgi.patch +0002-Fix-a-test.patch diff -Nru libwoodstox-java-4.1.3/debian/rules libwoodstox-java-5.1.0/debian/rules --- libwoodstox-java-4.1.3/debian/rules 2012-01-14 10:55:18.000000000 +0000 +++ libwoodstox-java-5.1.0/debian/rules 2018-09-06 15:19:08.000000000 +0000 @@ -1,30 +1,4 @@ #!/usr/bin/make -f -include /usr/share/cdbs/1/rules/debhelper.mk -include /usr/share/cdbs/1/class/ant.mk - -JAVA_HOME := /usr/lib/jvm/default-java -ANT_HOME := /usr/share/ant -DEB_ANT_COMPILER := modern -DEB_JARS := ant-nodeps junit ant-junit ant-trax -DEB_ANT_BUILD_TARGET := debiandist -DEB_BUILDDIR := . -DEB_ANT_BUILDFILE := build.xml -DEB_ANT_CLEAN_TARGET := clean -DEB_ANT_CHECK_TARGET := test - -clean:: - -rm -Rf build doc test dist woodstox-core-lgpl.patched.pom - mh_clean - -configure/libwoodstox-java:: - # Patch the POM to include the correct version number - cp src/maven/woodstox-core-lgpl.pom woodstox-core-lgpl.patched.pom - sed -i woodstox-core-lgpl.patched.pom -e 's/@VERSION@/$(DEB_UPSTREAM_VERSION)/g' - sed -i woodstox-core-lgpl.patched.pom -e 's/javax.xml.stream/stax/' - -install/libwoodstox-java:: - mh_install -plibwoodstox-java - -get-orig-source: - uscan --download-version $(DEB_UPSTREAM_VERSION) --force-download --rename +%: + dh $@ diff -Nru libwoodstox-java-4.1.3/debian/watch libwoodstox-java-5.1.0/debian/watch --- libwoodstox-java-4.1.3/debian/watch 2011-08-15 13:37:23.000000000 +0000 +++ libwoodstox-java-5.1.0/debian/watch 2018-09-06 15:17:06.000000000 +0000 @@ -1,5 +1,2 @@ -# The watchfile for libwoodstox version=3 -opts=dversionmangle=s/\.dfsg// \ - http://wiki.fasterxml.com/WoodstoxDownload .*/woodstox-core-src-([[:digit:].]+)\.tar\.gz \ - debian debian/orig-tar.sh +https://github.com/FasterXML/woodstox/releases .*/woodstox-core-(\d\S*)\.tar\.gz diff -Nru libwoodstox-java-4.1.3/.gitignore libwoodstox-java-5.1.0/.gitignore --- libwoodstox-java-4.1.3/.gitignore 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/.gitignore 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,24 @@ +# use glob syntax. +syntax: glob +*.class +*~ +*.bak +*.off +*.old +*.java.orig +.DS_Store + +# building +/target + +# Eclipse +.classpath +.project +.settings + +# IDEA +*.iml +*.ipr +*.iws +/.idea/ +/bin/ diff -Nru libwoodstox-java-4.1.3/LICENSE libwoodstox-java-5.1.0/LICENSE --- libwoodstox-java-4.1.3/LICENSE 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/LICENSE 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,202 @@ + + 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 -Nru libwoodstox-java-4.1.3/pom.xml libwoodstox-java-5.1.0/pom.xml --- libwoodstox-java-4.1.3/pom.xml 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/pom.xml 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,198 @@ + + + 4.0.0 + + com.fasterxml + oss-parent + 33 + + + com.fasterxml.woodstox + woodstox-core + 5.1.0 + bundle + Woodstox + + Woodstox is a high-performance XML processor that + implements Stax (JSR-173), SAX2 and Stax2 APIs + + + + cowtowncoder + Tatu Saloranta + tatu@fasterxml.com + + + + FasterXML + http://fasterxml.com + + https://github.com/FasterXML/woodstox + + https://github.com/FasterXML/woodstox/issues + + + scm:git:git@github.com:FasterXML/woodstox.git + scm:git:git@github.com:FasterXML/woodstox.git + https://github.com/FasterXML/woodstox + woodstox-core-5.1.0 + + + + 2013.6.1 + + 1.6 + 1.6 + + + com.ctc.wstx.*;version=${project.version} + + + com.ctc.wstx + + + + + The Apache License, Version 2.0 + http://www.apache.org/licenses/LICENSE-2.0.txt + repo + + + + + + maven-compiler-plugin + + 1.6 + 1.6 + + + + + maven-surefire-plugin + + + failing/*.java + **/Abstract*.java + **/Base*.java + **/*$*.java + + + **/*Test.java + **/Test*.java + + + + + org.apache.felix + maven-bundle-plugin + true + + + ${jdk.module.name} + + + + + + + + + org.codehaus.woodstox + stax2-api + + 4.1 + + + + + + + + net.java.dev.msv + msv-core + ${version.msv} + provided + true + + + net.java.dev.msv + msv-rngconverter + ${version.msv} + provided + true + + + net.java.dev.msv + xsdlib + ${version.msv} + provided + true + + + + + org.apache.felix + org.osgi.core + 1.4.0 + true + provided + + + + + + junit + junit + 4.12 + test + + + + + + + maven-javadoc-plugin + + private + true + true + ${project.name} ${project.version} API + ${project.name} ${project.version} API + + + + maven-surefire-report-plugin + + + + + diff -Nru libwoodstox-java-4.1.3/README.md libwoodstox-java-5.1.0/README.md --- libwoodstox-java-4.1.3/README.md 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/README.md 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,42 @@ +# Overview + +The gold standard Stax XML API implementation. Now at Github. + +## Status + +[![Build Status](https://travis-ci.org/FasterXML/woodstox.svg)](https://travis-ci.org/FasterXML/woodstox) +[![Maven Central](https://maven-badges.herokuapp.com/maven-central/com.fasterxml.woodstox/woodstox-core/badge.svg)](https://maven-badges.herokuapp.com/maven-central/com.fasterxml.woodstox/woodstox-core/) +[![Javadoc](https://javadoc.io/badge/com.fasterxml.woodstox/woodstox-core.svg)](http://www.javadoc.io/doc/com.fasterxml.woodstox/woodstox-core) + +# Get it! + +## Maven + +The most common way is to use Maven (or Ivy) to access it from Maven Central repository. +Coordinates for this are: + +* Group id: `com.fasterxml.woodstox` +* Artifact id: `woodstox-core` +* Latest published version: 5.0.3 (23-Aug-2016) + * (NOTE! Version `5.0.0` was accidentally released as broken, not containing actual classes -- 5.0.1 is the first functioning 5.x version). + +Note that Maven id has changed since Woodstox 4.x. + +## Requirements + +Woodstox 5 and above require Java 6 (JDK 1.6); as well as Stax API that is included in JDK. +The only other mandatory dependence is [Stax2 API](../../../stax2-api), extended API implemented by Woodstox +and some other Stax implementations (like [Aalto](../../../aalto-xml). + +Optional dependency is [Multi-Schema Validator (MSV)](https://github.com/kohsuke/msv) that is needed if +using XML Schema or RelaxNG validation functionality + +## License + +Woodstox 5.x is licensed under [Apache 2](http://www.apache.org/licenses/LICENSE-2.0.txt) license. + +## Documentation etc + +* User mailing list for Qs: [woodstox-user](https://groups.google.com/forum/#!forum/woodstox-user) Google group +* Check out [project Wiki](../../wiki) for javadocs + diff -Nru libwoodstox-java-4.1.3/release-notes/asl/ASL2.0 libwoodstox-java-5.1.0/release-notes/asl/ASL2.0 --- libwoodstox-java-4.1.3/release-notes/asl/ASL2.0 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/release-notes/asl/ASL2.0 1970-01-01 00:00:00.000000000 +0000 @@ -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 -Nru libwoodstox-java-4.1.3/release-notes/asl/LICENSE libwoodstox-java-5.1.0/release-notes/asl/LICENSE --- libwoodstox-java-4.1.3/release-notes/asl/LICENSE 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/release-notes/asl/LICENSE 1970-01-01 00:00:00.000000000 +0000 @@ -1,14 +0,0 @@ -This copy of Woodstox XML processor is licensed under the -Apache (Software) License, version 2.0 ("the License"). -See the License for details about distribution rights, and the -specific rights regarding derivate works. - -You may obtain a copy of the License at: - -http://www.apache.org/licenses/ - -A copy is also included with both the the downloadable source code package -and jar that contains class bytecodes, as file "ASL 2.0". In both cases, -that file should be located next to this file: in source distribution -the location should be "release-notes/asl"; and in jar "META-INF/" - diff -Nru libwoodstox-java-4.1.3/release-notes/asl/NOTICE libwoodstox-java-5.1.0/release-notes/asl/NOTICE --- libwoodstox-java-4.1.3/release-notes/asl/NOTICE 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/release-notes/asl/NOTICE 1970-01-01 00:00:00.000000000 +0000 @@ -1,8 +0,0 @@ -This product currently only contains code developed by authors -of specific components, as identified by the source code files. - -Since product implements StAX API, it has dependencies to StAX API -classes. - -For additional credits (generally to people who reported problems) -see CREDITS file. diff -Nru libwoodstox-java-4.1.3/release-notes/bsd/LICENSE libwoodstox-java-5.1.0/release-notes/bsd/LICENSE --- libwoodstox-java-4.1.3/release-notes/bsd/LICENSE 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/release-notes/bsd/LICENSE 1970-01-01 00:00:00.000000000 +0000 @@ -1,26 +0,0 @@ -Copyright (c) 2004-2010, Woodstox Project (http://woodstox.codehaus.org/) -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - -1. Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. -2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. -3. Neither the name of the Woodstox XML Processor nor the names - of its contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. diff -Nru libwoodstox-java-4.1.3/release-notes/COMPATIBILITY libwoodstox-java-5.1.0/release-notes/COMPATIBILITY --- libwoodstox-java-4.1.3/release-notes/COMPATIBILITY 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/release-notes/COMPATIBILITY 1970-01-01 00:00:00.000000000 +0000 @@ -1,91 +0,0 @@ -== Changes from 3.0.x to 4.0.x == - -=== Stream reader === - -* Defaulting reporting of "no prefix" and "no namespace [URI]" - have been changed from null value to empty Strig (""), to be - in accordance with the latest consensus regarding Stax API. -* Fix for [WSTX-140] changes default for IS_COALESCING to be - Boolean.FALSE as per Stax specs. 3.0 and earlier were defaulting - to Boolean.TRUE. -* XMLStreamReader.getProperty() will no longer throw IllegalArgumentException, - if fed an unknown property name. Rather, null is returned. - This is thought to be Stax 1.0 compliant, and both more convenient - and performant for cases where application needs to offer interoperability - with multiple Stax implementations. - -=== Stream writer === - -* Default setting of WstxOutputProperties.P_OUTPUT_FIX_CONTENT was - true in 3.x. While this seemed like a good idea for maximum xml - conformance, it also causes incompatibility issue with the JDK 6 - included Sun Stax implementation, which does not implement either - well-formedness checks or fixing algorithm. As a result, something - that works well with Woodstox would not necessarily work well with - JDK6 default Stax implementation. - As a result, *WstxOutputProperties.P_OUTPUT_FIX_CONTENT* was - default settings was *changed to false*. -* Default setting for WstxOutputProperties.P_ADD_SPACE_AFTER_EMPTY was set - to 'false', meaning that no space is added in empty element: that is, - output will look like "" instead of "" (as was the case - for 3.2 and prior) - -=== Validation === - -* Validation methods now consistently allow throwing of XMLStreamException - instead of limiting it to just XMLValidationException. - The reason is that due to call chaining, XMLReporter (which allows throwing - of generic stream exception) may be called from within validation - problem reporting methods, and resulting exceptions must - be let pass through call stack (see [WSTX-154] for details). - -== Changes from 2.0.x to 3.0.x == - -=== XML compatibility === - -* 3.0 now supports xml 1.1 cleanly (is aware of differences between 1.0, - uses separate well-formedness checks where necessary) -* XML conformance significantly improved, to pass XMLTest test suite - (with 99%+ pass rate). - -=== Packaging === - -* EscapingWriterFactory moved from main org.codehaus.stax2 package - to the new org.codehaus.stax.io sub-package. - -=== Stream reader === - -* Default setting for P_REPORT_PROLOG_WHITESPACE is - now Boolean.TRUE (instead of Boolean.FALSE), to emulate behaviour - of the StAX reference implementation, and to keep output in pass-through - configurations more similar to input. -* Handling of undeclared entities changed so that no exception is thrown - in non-expanding mode; this is similar to the way ref. impl. works. -* isCharacters() now only returns true if current event is CHARACTERS, - instead of CHARACTERS, CDATA and SPACE (as in 1.0 and 2.0). Change was - done for interoperatibility -- the StAX reference implementation - behaves like 3.0. -* Removed property P_TEXT_BUFFER_LENGTH, since there is no real benefit - from changing this setting -- text buffer is resized dynamically as - needed, and initial value is largely irrelevant. - -=== Stream writer === - -* In 2.0.x most well-formedness checks (P_CHECK_xxx) resulted in - unchecked IllegalStateException. Due to requests by developers, who - found this unintuitive, these were replaced by checked XMLStreamExceptions. -* In 2.0.x, WstxOutputProperties.P_OUTPUT_VALIDATE_CONTENT was false - by default: in 3.0 it is true. Change was due to more efficient checking - of the content, made possible by integrated transcoding. As such, it seems - useful to have more rigorous checks enabled by default. Also, since - WstxOutputProperties.P_OUTPUT_FIX_CONTENT was and is true by default, - CDATA and COMMENT sections will be automatically "fixed" now. - -=== Event reader === - -* Event readers are now constructed so that P_LAZY_PARSING is always - disabled (to get accurate XMLStreamExceptions instead of possible - runtime exceptions, with no performance difference). - Also, P_MIN_TEXT_SEGMENT will be set to maximum value, to avoid - ever splitting a CHARACTERS or CDATA segment (to minimize number - of event objects created). diff -Nru libwoodstox-java-4.1.3/release-notes/CREDITS libwoodstox-java-5.1.0/release-notes/CREDITS --- libwoodstox-java-4.1.3/release-notes/CREDITS 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/release-notes/CREDITS 1970-01-01 00:00:00.000000000 +0000 @@ -1,494 +0,0 @@ -Here are people who have contributed to Woodstox development: -(version numbers in brackets indicate release in which the contribution was applied) - -Tatu Saloranta, tatu.saloranta@iki.fi: Author - -Christian Niles: - * Pointed out an improvement to the woodstox.jar to add service - entries under META-INF so that Woodstox will auto-register - as a Stax implementation. - to use - [0.8.3] - -James Fogarty: - * Found 3 bugs (getElementText() not working, incorrect index offset - for non-ns getAttributeLocalName(), index-out-of-bounds when there - were lots of attribute names whose hashes collide) - [1.0] - -James Strachan: - * Found problems with stream writer; namespace repairing mode was not - working as expected - [1.0] - -Stepan Koltsov: - * Found problems with event reader: was setting peeked event to null, yet - trying to de-reference it - [1.0] - -Mat Gessel: - * Pointed out a problem with XMLStreamReader.nextTag() implementation; - was not skipping comments and PIs - [1.0] - -Dan Diephouse: - * Reported problems with QName construction (null prefix causes - exception on some QName implementations) - [1.0.1] - * Reported [WSTX-9] (sr.getTextCharacters() problems) - [2.0.3/2.7] - * Pointed out code that could be used to resolve [WSTX-26]. - -Sven Köhler: - * Reported the problem with blocking input streams, and behaviour of - the UTF8 decoder Woodstox uses: this could cause "too early" blocking - of readers, in cases where event(s) could be returned before needing - to read more from underlying input stream. - [1.0.4/1.7] - * Reported a bug in stream writer; a call to writeEmptyElement() followed - by a call to writeEndElement() ignored latter call. - [1.0.5/1.8.2] - -Casey Bowman: - * Pointed out the (potential) problem with javax.xml.stream.Location; - return values are ints, and may thus overflow for BIG documents. - StAX2 extensions (XMLStreamLocation2) added to properly deal with - the problem. - [1.8] - -Stefan Wachter: - * Reported a problem with handling of large documents; was sometimes - throwing an ArrayIndexOutOfBounds exception (mostly when dealing - with gzipped streams). - [1.0.3/1.8.1] - -Eric Jain: - * Reported a bug in default namespace handling; was reporting a bogus - problem when declaring an explicit namespace before the default one - on a start element - [1.0.3/1.8.1] - * Re-reported the problem with UTF-8 streams and array bounds (originally - reported by Stefan Wachter), and provided unit test to reproduce it. - [1.0.4/1.8.1] - -Marius Raschip: - * Reported a problem with handling of UTF-16 (and in general all non-UTF-8 - multi-byte encodings): wasn't handling xml declaration correctly. - [1.0.5/1.8.2] - -Olivier Potonniee: - * Reported compilation problems (incorrect package name for one class, - conflicting method name for LineSuppressWriter) - [1.0.6/1.9] - -Ron Yang: - * Reported an intermittent problem caused by broken handling of SymbolTable - sharing, and also pointed out a potential solution (had been fixed for - 2.0 branch earlier, but not for 1.0.x). - [1.0.7] - -Ulrich Callmeier: - * Reported a bug with START_DOCUMENT handling of XMLStreamWriter - implementation - [1.0.7/2.0.0] - * Reported a bug with the input factory: entity and dtd resolvers were - not being properly passed to instances - [1.0.7/2.0.0] - * Report a bug with WriterBase, base class for all encoding writers - (attribute, element text): an NPE was thrown when trying to output - encoded characters. - [2.0.1/3.0.0] - * Reported a bug in DTD-handling; DTDs that had enumerated value "-" - (or "--"), were throwing an exception. - [2.0.1/3.0.0] - -Peter Tauter: - * Reported a bug with WriterBase; see the entry next to Ulrich for details. - -Linus Ericson: - * Reported bugs: - * [WSTX-3]: WDTD.java was missing one double quote from output - [2.0.2/3.0.0] - * [WSTX-7] SimpleNsStreamWriter was stripping out attribute namespaces - [2.0.3/3.0.0] - * [WSTX-114]: Handling of ID attribute values broken, in non-namespace - mode: last character was dropped. - [3.2.0/4.0.0] - -Patrick D'Cruze: - * Reported [WSTX-8]; nextTag() followed by peek() at the start of a - document did not work. - [2.0.3/3.0.0] - -Erik Smith: - * Reported [WSTX-9] (sr.getTextCharacters() problems) - [2.0.3/3.0.0] - -Kevin Vargo: - * Reported [WSTX-9] (sr.getTextCharacters() problems) - [2.0.3/3.0.0] - -Heinz Drews: - * Reported [WSTX-10] (handling of 3-byte UTF-8 Byte Order Marker did - not work properly when XMLStreamReader was constructed for a Reader) - [2.0.3/3.0.0] - * Reported [WSTX-19] (unnecessary default namespace declarations written - in repairing mode) - [2.0.4/2.8.1] - -Wolfgang Hoschek: - * Reported [WSTX-27] (incorrect handling of #FIXED attribute defaults) - [2.0.4/2.8.1] - * Reported [WTSX-59]: Stream writer tries to quote \r and \t in - prolog and epilog. - * Pointed out countless other bugs based on extensive Nux and Xom - xml compatibility suites (and w3c compatibility suite as well). - * Pointed out multiple optimization possibilities (both on reader and - writer side), esp. via performance - test suite Nux has: this helped performance tuning of 3.0 release - significantly. - * Reported [WSTX-65], [WSTX-66] and [WSTX-67], regarding event handling - problems. - [3.0.0] - * Pointed out compilation problem on JDK 1.4 with SAX2 API - [3.2.0] - * Reported [WSTX-96] - [3.2.0] - -Bartlomiej Rymkowski: - * Reported [WSTX-28] (broken handling of property - (WstxInputProperties.P_CUSTOM_INTERNAL_ENTITIES) - [2.0.5/3.0.0] - -Arjen Poutsma: - * Reported [WSTX-45] (WstxEventReader#peek() throwing EOF instead - of returning null), pointed out fix. - [2.0.6/3.0.0] - -John Kristian: - * Reported [WSTX-46]: Trying to write another root element produced an - incorrect error message - [2.0.6/3.0.0] - -Steve Yost: - * Reported a problem with setting P_VALIDATE_STRUCTURE - [2.0.6] - * Reported a problem with stream writer when trying to output - non-wellformed (multiple root elements) content even when - structural well-formedness checks are disabled. - -Anli Shundi: - * Reported [WTSX-58]: a problem with DOMWrappingReader throwing an NPE, when - accessing attribute properties of an element with only ns declarations. - [3.0.0] - -Lucian Holland: - * Reported a bug in handling of StartDocument event, peeking and - XMLEventReader.nextTag(). - [3.0.0] - * Reported a stax incompliancy wrt. XMLStreamReader.next() not throwing - NoSuchElementException after END_DOCUMENT event. - [3.0.1/3.1.0] - -Matt Solnit: - * Reported [WSTX-72]: Output streams/writers sometimes closed when they - should not be. - [3.0.1/3.1.0] - -Michael Kay: - * Reported [WSTX-69]: Incorrect types returned by XMLStreamReader, when - notations/entities are requested. - [3.0.1/3.1.0] - * Reported [WSTX-70]: External parsed entity reference resolution was - not functioning correctly, was using wrong path context. - [3.2.0] - * Reported [WSTX-71]: Use of unchecked exceptions sub-optimal, for cases - where it would be possible to just defer throwing of checked ones - -Vim de Rammelaere: - * Reported [WSTX-77]: Bug in DTDValidator.validateAttribute() -- wrong - arguments passed to StringUtil.matches() - [3.0.1/3.1.0] - -Mickael Goujon: - * Reported [WSTX-81], contributed a patch for it: Calculation of - char/byte offsets was buggy. - [3.0.2/3.1.0] - -Christian Bering: - * Reported [WSTX-82], contributed a patch for it: URL handling code - had problems on Windows, when referring to files on network drives. - [3.0.2/3.1.0] - -Oleg Rudenko: - * Reported [WSTX-83], contributed a patch for it: NPE in ElemAttrs - for namespace URI checks. - [3.0.2/3.1.0] - -Pavol Vaskovic: - * Reported [WSTX-87], and documented the problem (including a unit test) - which allowed otherwise hard-to-track problem to be quite easily - resolved. Problem was that event writer could produce non-wellformed - output for medium/large-sized content, when using Latin1 encoding. - [3.0.3/3.1.0] - -Michael Haeusler: - * Reported [WSTX-88], suggested fix; Latin1 output wasn't working - correctly: some characters in range 0x80 - 0xFF were output both - as is, and as character entities - [3.0.3/3.1.0] - -Frank Baxter: - * Reported [WSTX-89], with sample document that exhibits the problem: - line number information was not properly updated in - some cases (boundary condition with Windows, \r\n, linefeeds) - [3.1.1] - * Reported [WSTX-97], with sample document and code to reproduce - the problem: Character offsets (for XMLStreamReader.getLocation()) - were sometimes decremented - [3.1.1] - * Reported [WSTX-141], supplied test case demonstrate it: - Copying of CDATA events using XMLEventWriter was producing - garbled output. - [3.2.4/4.0.0] - -Davanum Srinivas: - * Reported [WSTX-90], submitted a patch (used as the guideline for - the changes): output writing efficiency could be improved by - using System.arraycopy() instead of basic character copying. - Can improve speed even for relatively short strings, it turns out. - [3.2.0] - * Reported [WSTX-91], submitted patch (regression caused by changes - for [WSTX-90]); array index of bounds on stream writer. - [3.2.0] - -Werner Donné: - * Reported [WSTX-102], submitted patch to fix it: WStartDocument - constructor would NPE when building using DOM source. - [3.0.3 / 3.1.1] - -Michael Allman: - * [WSTX-103] Repairing writer had a bug that could result in wrong - prefix being reported/output. - [3.0.4 / 3.1.2] - -Wayne Fay: - * Suggested good improvements wrt [WSTX-85], for improving Maven - artifacts - [4.0] - -Sami Dalouche: - * Pointed out [WSTX-106], unhelpful XMLStreamException being thrown - when trying to write illegal attribute value characters - [3.2.1 / 4.0.0] - -Daniel Kulp: - * Pointed out [WSTX-108] (Maven pom missing info), helped resolve - [3.2.1 / 4.0.0] - * Reported [WSTX-113] (problems with DOMSource when DOM parsed in - non-namespace mode) - [3.2.1 / 4.0.0] - -Abde Sassi: - * Reported [WSTX-109], a bug in xml declaration handling in multi-doc - mode. - [3.2.1 / 4.0.0] - -Erik Bergersjö: - * Reported [WSTX-110], problems regarding Exception root cause setting. - [3.2.1 / 4.0.0] - -Santiago Pericas-Geertsen: - * Pointed out [WSTX-111], Stax TCK non-compliancy, regarding filtered stream - reader. - [3.2.1 / 4.0.0] - -Wouter Cordewiner: - * Pointed out [WSTX-122], helped in adding EBCDIC support. - [3.2.2 / 4.0.0] - * Pointed out [WSTX-138], confusing error msg for xml declaration / - physical encoding inconsistency (EBCDIC vs UTF-x) - [3.2.3 / 4.0.0] - -Lukasz Wielek: - * Reported [WSTX-132], NPE when event writer was passing null namespace - URI - [3.2.3 / 4.0.0] - -Yoon-Je Choi: - * Reported [WSTX-134]: DOMWrapperingReader.isWhiteSpace was using - incorrect check, suggested fix. - [3.2.3 / 4.0.0] - * Reported [WSTX-135]: Repairing stream writer was associating namespace - bindings with parent element, pointed out solution. - [3.2.3 / 4.0.0] - * Reported [WSTX-139]: DOMWrappingWriter did not support namespace-repairing - mode: contributed a working solution - [4.0.0] - -Matt Gormley: - * Reported [WSTX-143], bug in handling of DEL char in UTF8Reader, - suggested fix, submitted unit test. - [3.2.4 / 4.0.0] - -Jim Ancona: - * Reported [WSTX-146], contributed a unit test for verifying fix. - [3.2.5 / 4.0.0] - -David Citron: - * Reported [WSTX-145]: DOMWrappingReader was not implementing coalescing - mode. - [3.2.7 / 4.0.0] - -Martin Vanek: - * Reported [WSTX-144]: Problem when trying to output namespace declaration - using a DOMResult-backed writer. - [3.2.6 / 4.0.0] - * Reported [WSTX-271] DOMWrappingWriter.writeComment() creating CDATASection - [4.1.2] - -Sylvain Loiseau: - * Requested [WSTX-148]: Implement XMLEvent.equals(), .hashCode(), to allow - for easy comparison of XMLEvent instances. - [4.0.0] - -Eduardo Ribeiro Rodrigues: - * Reported [WSTX-153]: XMLReporter not getting called for non-fatal - validation errors - [3.2.6 / 4.0.0] - * Reported [WSTX-155]: NPE after reporting missing #REQUIRED attribute - [3.2.6 / 4.0.0] - -Daniel Rodrigue: - * Reported [WSTX-158], provided a test: XMLStreamReader.isWhiteSpace() - returns potentially incorrect value when text segments starts with an - entity. - [3.2.7 / 4.0.0] - -Pawel Lipka: - * [WSTX-162] Name/namespace-URI interning not enabled for DOM-backed - readers, getProperty() claims they are. - [3.2.7 / 4.0.0] - -Arash Amiri: - * [WSTX-174] Some old App servers have broken QName impl, are missing - 3-arg constructor. - [3.2.8 / 4.0.0] - -Ian Brandt: - * [WSTX-165] Add property (WstxOutputProperties.P_AUTOMATIC_END_ELEMENTS) - to allow enabling/disabling automatic addition of end elements - when closing stream writer. - [3.2.8 / 4.0.0] - -Romain Deltour: - * Requested [WTSX-152], suggested a way to solve it: Add OSGi headers to - the jar manifest. - [4.0.0] - -Christopher Paul Simmons: - * Reported [WSTX-182], inability to use StreamResult that only has - SystemId set. - [4.0.0] - * Reported [WSTX-183], problem with creating stream/event writer - with a DOM Element (instead of document), contributed unit tests. - [4.0.0] - * Contributed [WSTX-193], unit test for verifying that namespace bindings - are properly passed through in namespace-repairing mode - [4.1.0] - -Roger Wegmann: - * [WSTX-188] Could get an ArrayIndexOutOfBounds exception for - StartElement.getAttributeByName() under specific conditions - [3.2.9, 4.0.2] - -Andreas Veithen: - * Reported [WSTX-190], NPE with DTD validator, missing attribute. - [3.2.9, 4.0.2] - * Reported [WSTX-201]: XMLStreamReader.isCharacters() can return - inconsistent value compared to XMLStreamReader.getEventType() - [4.1.0, 5.0.0] - * Reported [WSTX-202], suggested fix for it: BijectiveNsMap#findPrefixByUri - doesn't handle masked namespace declarations correctly - [3.2.9, 4.0.4] - * Reported [WSTX-226], SAX parser implementation ignoring passed-in encoding - [4.0.8] - * Reported [WSTX-276]: Conflict between InputConfigFlags 'CFG_AUTO_CLOSE_INPUT' - and 'CFG_NORMALIZE_LFS', which accidentally lead to 'auto-close-input' being - enabled by default, which is NOT what Stax specification mandatates - [4.1.3] - -Yves Ménard: - * Reported [WSTX-191] Validation failure with W3C Schema, empty text. - [4.0.3] - -Stéphane Claret: - * Reported [WSTX-204] Custom entity resolver setting was not working with - SAX API (due to JDK impl idiocy) - [4.0.4] - * Suggested [WSTX-206] Allow more configurability for SAX parser impl - [4.0.8] - -Jack S. Rugh: - * Reported [WSTX-208] Value of default attributes not found using - XMLStreamReader.getAttributeValue(String,String) - [4.0.5] - -Arun Kumar: - * Reported [WSTX-207] Schema factory failing to load schema if filename has - characters that need to be escaped when converted to URL - [4.0.5] - -Kevin Braun: - * Reported [WSTX-211]: Failure to parse long CDATA section properly when - using XMLStreamReader.getElementText(), non-coalescing - [4.0.6] - -Alexander Rydén: - * Reported [WSTX-224]: getElementAsBinary() fails when reading large - amounts of data (in coalescing mode) - [4.0.7] - -Brian Sterner: - * Reported [WSTX-228]: Property WstxOutputProperties.P_OUTPUT_ESCAPE_CR - not used for attribute content - [4.0.8] - -Myles Bunbury: - * Suggested [WSTX-236]: Make WstxInputLocation Serializable - [4.0.8] - -Habib Chehade: - * Reported [WSTX-249]: TextAccumulator had a bug in one code path - [4.0.9] - -Stefan Vladov: - * Suggested [WSTX-243] Don't throw IllegalArgumentException for CommonConfig.getProperty/setProperty() - [4.1.0] - -Eric Dalquist: - * [WSTX-251] Improve extensibility of XMLOutputFactory by relaxing access restrictions - [4.1.0] - * [WSTX-252] Add EmptyElementHandler callback support to allow determining whether - empty elements are written in compressed form or not - [4.1.0] - -Andrey Shaposnikov - * [WSTX-256] Incorrect handling of surrogate pairs in general entities. - [4.1.1] - -Eric Sirianni - * [WSTX-257] DOMWrappingWriter problem with fragments, multiple root-level - elements - [4.1.1] - * [WSTX-259]: DOMWrappingReader fails with NPE for empty DocumentFragment - [4.1.1] - -Mike Sokolov: - * [WSTX-267] P_NORMALIZE_LFS mis-mapped - [4.1.2] - -Blaise Doughan: - * [WSTX-268] Missing namespace information when unmarshalling from DOMSource - [4.1.2] - diff -Nru libwoodstox-java-4.1.3/release-notes/FAAQ libwoodstox-java-5.1.0/release-notes/FAAQ --- libwoodstox-java-4.1.3/release-notes/FAAQ 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/release-notes/FAAQ 1970-01-01 00:00:00.000000000 +0000 @@ -1,341 +0,0 @@ -h1. Woodstox XML-parser Frequently Asked/Anticipated Questions - -h2. 1. General - -h3. 1.1 What is Woodstox? - -Woodstox is a high-performance XML processor that implements Stax API, specified by JSR-173. XML processor means that it can read (parse, unmarshall, deserialize) and write (output, marshall, serialize) XML content such as XML documents. - -Woodstox is developed as Open Source, and is available under 2 "standard" Open Source/Free Software licenses: Free Software Foundataion's LGPL 2.1 and Apache Foundation's ASL 2.0. - -h3. 1.2 Where can I find Woodstox? - -Woodstox project home page is at Codehaus: - - http://woodstox.codehaus.org - -The home page contains most up-to-date information regarding current status of the project, and contact information - -h3. 1.3 Standard compliancy - -h4. 1.3.1 Which XML technologies does Woodstox support? - -Currently supported specifications are: - -* XML 1.0 and 1.1 (latter mostly); including full support for all entity types (internal, external; parsed, unparsed) and full DTD validation. (DTD validation from Woodstox 2.0 on; entities from 1.0) -* XML Namespaces 1.0 (Woodstox 1.0 and above) -* RelaxNG (using external validation component) (Woodstox 3.0) -* XML:Id (Woodstox 3.1) -* XML Schema validation (using external validation component) (Woodstox 4.0) - -And ones planned for future: - -* XML Include (planned for Woodstox 4.0 or later) - -h4. 1.3.2 Which Java API does Woodstox implement? - -Currently Woodstox implements following standard APIs: - -* Stax 1.0 API as specified by JSR-173. -* SAX2 (Woodstox 3.2) - -Additionally, Woodstox also implements: - -* Experimental "Stax2" extension API (a collection of interfaces and abstract classes in org.codehaus.stax2 package), which is not proprietary to Woodstox implementation (some other projects -- such as StaxMate and Aalto -- also use it) - -h3. 1.4 How do I report bugs and request new features? - -Woodstox development team uses Jira bug tracking system at codehaus: - - http://jira.codehaus.org/browse/WSTX - -and it can be used for bug reports, requests for enchanced functionality and so on. - -Alternatively, you can also join the Codehaus mailing lists: - -* user@woodstox.codehaus.org is the general mailing list for Woodstox users -* dev@woodstox.codehaus.org is for more involved technical questions, and discussion on implementation aspects of Woodstox. - -Additionally, for problems regarding Stax (1.0) specification and API, you may want to use Stax API bug tracking system at: - - http://www.extreme.indiana.edu/bugzilla/query.cgi - -(search for component Stax) - -or, for some of the problems, Jira instance for Stax reference implementation: - - http://jira.codehaus.org/browse/STAX - -General discussion about Stax API, and various implementations (including Woodstox) usually happens at Stax builders list: - - stax_builders@yahoogroups.com - -which is open for anyone (not just stax implementation developers) to join. - - -h3. 1.5 What are the design goals of Woodstox? - -Main goals are, in rough order: - -* Implement Stax API, to the fullest extent possible based on accepted - interpretation of the specification and associated documentation (javadocs - of the reference implementation). -* Implement full XML (1.1) functionality; specifically make sure all - well-formed/valid documents are properly handled. Secondary goal is to - gracefully handle non-wellformed documents (and to catch problems). -* Make parser as efficient as possible without completely sacrificing - its maintainability (code clarity, simplicity). Efficiency is meant - to encompass both time AND space constraints, ie. not only should it be - fast, but also try to use memory sparingly. -* Sensible default values, so that Woodstox functions adequately with - the default settings, with no need for extensive tweaking of settings. -* Good error reporting: there is nothing more frustrating than getting - either minimal information about problem ("Invalid content"), or too - much of information ("Element 'xyz' does not match Content model - (a|b|(c, d+)|.......) derived from (foo, bar?, ...)...") -* Make features that can have significant impact on performance - configurable; use reasonably defaults for settings. It should be easy - to just plug-in and use, but also allow "power coders" to configure it - optimally for specific use cases. -* Extensive, modular, pluggable validation functionality; not just for input - but also output side; allow for writing custom validators and plugging - them in, efficiently chaining multiple validators if necessary. -* Modularity; try to implement only features that can not be implement - efficiently or reliably on top of StAX interface: other features should be - implemented as separate add-on packages, to be usable with other StAX - implementations. - - -h3. 1.6 What's in the Name? - -Name Woodstox is just a silly combination of various motifs; mainly mutation of "Stax" part (from the Java API it implements), and then similarity to both a sidekick cartoon character and the music festival location. -There is no real reason for it -- it just sounded like a good idea at the time. :-) - -h2. 2. StAX API features - -h3. 2.1. How do I use XMLStreamWriter? This API is a mess! - -Yes, it indeed is bit of a mess. Unfortunately Stax 1.0 specification underspecifies writer side, leading to lots of confusion, not only for users, but for Stax implementors as well. - -A full explanation of how Woodstox implementors undestand how XMLStreamWriter functionality should work is at [[link to be added]] but here is a quick rundown on various modes and settings. - -Basic Stax 1.0 specifies two different operating modes; where the different is between handling of namespace bindings (declarations, prefix mappings). If you do not use namespaces, there is no difference between these modes - -* Repairing mode means that the writer takes full responsibility for - declaring and binding namespaces. Application can request specific - bindings, but the writer ultimately decides on which bindings to - use, to produce well-formed namespace output that corresponds to - the fully-qualified name (namespace URI and local name via prefix - bindings). Writer thus will output all namespace declarations - automatically, and application should not try outputting them. - This mode has associated overhead with it, but it is convenient - and useful especially when merging documents that use different - namespaces. -* Non-repairing mode is simple manual mode, in which the stream writer - does not output any namespace declarations, nor map prefixes and - namespace URIs. Application is to call appropriate output methods - to produce valid output. The only namespace support available is - the possibility to add bindings between prefix and namespace URI: - this allows for using prefix-less write methods. - This mode has very little overhead for namespace management (and if - prefix mapping is not used, practically none), but it can lead - to invalid output. - -h4. 2.1.1. XMLStreamWriter in non-repairing (manual namespaces) mode - -In this mode, application has to output all namespace declarations similar to the way regular attributes are added: - -* Namespace output methods (writeNamespace(), writeDefaultNamespace() - should be called AFTER outputting element that is to contain the - declaration. The declarations do not have to be output before attributes - that use the binding; stream writer does not verify bindings in any way during output. -* If application uses 'full' write methods for elements and attributes - (ones that 3 arguments; local name, prefix, namespace URI), prefix - given is output as is with no checks done regarding binding. -* If application wants to use write methods that do NOT take prefix - as the argument (but just local name and namespace URI), application - is to call 'setPrefix()' (when mapping explicit prefix to a namespace - URI) or 'setDefaultNamespace()' (when defining mapping of the default - namespace). These bindings are guaranteed to persist for the element - that was output last (or for root level, for the document scope), but - some implementations may leave bindings in effect until the end of the - document (Stax 1.0 specification does not specify life cycle for these - bindings). - Note that even if prefixes are bound, output will still not be done - by the stream writer. And conversely, adding prefix bindings is not - a requirement for calling 'writeNamespace()'/'writeDefaultNamespace()': - these methods are orthogonal. -* Methods that take neither prefix nor namespace URI are assumed to - be output with no prefix; which means that (as per XML specs) elements - will be in the currently bound default namespace, if any, and attributes - will not be in any namespace. - -h4. 2.1.2. XMLStreamWriter in repairing (automatic namespaces) mode - -In repairing mode, application does not have to do anything to manage namespace bindings and mappings. It can, if it wants to, indicate prefix preferences. There are 2 ways to do that: - -* If application uses 'full' write methods (ones that take prefix and - namespace URI), prefix passed is taken as the preferred prefix (if - empty, trying to use the default namespace for elements): if prefix - is already bound, it is used as is; if not, writer may try to bind - it (exact behaviour is unspecified by Stax specs -- Woodstox tries - to bind it if prefix is unbound, but not if it is already bound to - another namespace URI). -* Application may also indicate preferred binding of namespaces by - calling 'setPrefix()' and 'setDefaultNamespace()' methods. These - will indicate preference that will be used when using write methods - that only take the namespace URI. -* Write methods that take neither namespace URI nor prefix behave as - in non-repairing mode, ie. they will output elements and attributes - that have no prefixes, and bind respectively as per xml specification - (elements to currently active default namespace, if any, attributes - belong to no namespace). - -If a namespace binding is needed and either no preference is found, or the preference can not be used (for example, different binding for the prefix is already output for the current element), stream writer will generate an implementation dependant prefix to bind (and ensure it does not collide with other bindings). - -h3. 2.2. Text handling: Why do I get these short partial segments? - -By default StAX readers are allowed to return text and CDATA segments in parts, ie. more than one event per physical segment. This is usually done so that readers need not allocate big consequtive memory buffers for long text segments. With default settings, it is possible to sometimes get as little as 64 characters per event, even if the text/CDATA segment itself was significantly longer. - -However, you can easily change this behaviour. There are two properties you can modify (check documentation for details): - -* IS_COALESCING is a standard StAX property; turning it to true will force reader to coalesce ALL adjacent text/CDATA segments into just one text event. This may make it easier to process document. Downside is that it may slightly impac performance; the effect should not be drastic in normal use cases, however. -* P_MIN_TEXT_SEGMENT is a Woodstox-specific property that defines the smallest text/CDATA fragment that reader is allowed to return. The default value is 64 characters; setting it to Integer.MAX_VALUE effectively forces reader to always return the full segment. However, unlike IS_COALESCING, it does not make reader coalesce adjacent segments. Because of this, the performance impact is smaller, and changing this value is unlikely to have big performance impact. - - -h2. 3 Deployment/packaging - -Basic distributable jars that one needs to use Woodstox are: - -(a) Stax 1.0 API jar that contains javax.xml.stream.* classes. This is based on JSR-173 specification. -(b) Woodstox implementation jar (under appropriate license, see below) - -In addition, it is possible use following optional jars: - -* stax2.jar contains only classes of the experimental Stax2 API - (interfaces and classes in 'org.codehaus.stax2' package). - These can be used by applications that want to be able to dynamically - use extended Woodstox capabilities, if available, but otherwise - revert basic Stax 1.0 API. This can be achieved by only including - stax2.jar by default, and allowing full Woodstox jar to be included - as an optional component. - Note that the full woodstox jar does contains these API classes by - default, for convenience. - -h3. 3.1 Licensing - -Currently (Woodstox 2.0 and above), you can choose to use Woodstox either -according to terms of LGPL (2.1) or ASL (2.0) licenses. The choice is made -by using one of two distributed implementation jars, which contains -appropriate license, and determines licensing restrictions. -Please note that the functionality provided is identical -- there are -no technical differences, or reasons to use one over the other. - -The choice you make has only effect in regards to specific use for that -particular jar -- you may use instances of both jars for different -purposes; in each case, licensing restrictions are based on specific jar -used. -In general, choice depends mostly on other (Open Source) components you -are using; some limit you so that you may have to use LGPL version; others -that you have to use ASL version. This is the main reason Woodstox is -dual-licensed: to offer the choice, while maintaining some basic -Open Source restrictions on redistribution. - -h3. 3.2 Functionality subsets (alternate jars) - -Although it is most common to use one of 2 full standard implementation -jars, there are situations where application only needs to use subset -of Woodstox functionality. For example, some applications may only want -to use input functionality (parsing), while others only produce xml -output. Or, in some cases validation is never used. - -In these cases it may be beneficial to use a jar that only contains subset -of the full functonality. These jars are smaller, and may reduce size of -application deployment, and potentially slightly reduce memory usage. - -One thing to note about these subsets: due to the way Stax 1.0 is -structured, it is not possible to transparently support subsets while -implementing other parts of the API. As a result, normal Stax 1.0 -factories can NOT be used with these subsets -- special factory classes -needed to be used directly. This makes using these jars non-portable, -and best suited for resource limited environments like mobile phones. - -By default, Woodstox Ant build scripts produce following subset jars -(using nifty 'classfileset' optional Ant task) - -* wstx-j2me-min-input.jar contains non-validating stream reader classes; - and excludes Event API implementation, output classes and validation - functionality (except for classes that non-validating reader classes - need to support API). - NOTE: although name implies j2me compliancy, this has not been verified, - and is likely not the case. -* wstx-j2me-min-output.jar similar to above, but only contains non-validating - stream writer functionality. -* wstx-j2me-min-both.jar. Combination of both of above, ie. contains - non-validating cursor API (no event API) implementation. - -When using input functionality, factory to use is: - - com.ctc.wstx.stax.MinimalInputFactory - -and when using output functionality: - - com.ctc.wstx.stax.MinimalOutputFactory - -both of which have subset of methods from XMLInputFactory and -XMLOutputFactory, respectively. - -h2. 4. Features, quirks: Parsing (stream/event readers) - -h2. 5. Features, quirks: Writing (stream/event writer) - -h3. 5.1 Output escaping - -h3. 5.1.1 "Why does Windows/Mac linefeeds get messed up"? - -(and: "How can I make it stop doing that?") - -By default, Woodstox tries to escape things it must, and things it should. Former contains '<' and '&', as well as '"' and '>' in some cases. Latter contains non-default linefeeds; defaults is '\n' (Unix linefeed) characters. -Windows uses combination '\r\n' and MacOS '\r'. Since XML parsers replace all of these with '\n', stream writer by default escapes '\r' so that it will be preserved. -This is not always what user wants. - -So, if you don't like this behavior, configure output factory instance like this: - - XMLOutputFactory f = XMLOutputFactory.newInstance(); - f.setProperty(WstxOutputProperties.P_OUTPUT_ESCAPE_CR, Boolean.FALSE); - -(note: for full explanation of the issue, check out: [http://jira.codehaus.org/browse/WSTX-94]) - - -h2. 6. Implementation details - -h3. 6.1 String interning - -Which Strings and when does Woodstox intern? - -* Names (prefixes and local names of elements and attributes, names - of processing instruction targets and entities) are always intern()ed - (and this is also visible using - streamReader.getProperty(XMLInputFactory2.P_INTERN_NAMES)) -* Namespace URIs MAY be interned, depending on setting of - XMLInputFactory2.P_INTERN_URIS (accessible via - streamReader.getProperty(XMLInputFactory2.P_INTERN_URIS)). - By default this interning is NOT done. However, URI Strings for a single - document are still shared, so that within a single document, namespace - URIs CAN always be compared for String identity (nsUri1 == nsUri2 is true - if and only if they contain same String). - -h2. 7. Performance - -h3. 7.1. How can I make Woodstox work as fast as possible? - -Although default settings of Woodstox are chosen to allow efficient operation, there are things that application needs to do, to help. -Here are some of more important things to do: - -* Reuse factories (XMLInputFactory, XMLOutputFactory, validation schema factories). This important, because: -** Instantiation factories through Stax API is costly (although actual construction of Woodstox factories is less so) -** Most caches are per-factory: symbol (element, attribute name) caching, DTD caching. -* Let Woodstox take care of character encoding: pass InputStreams and OutputStreams as is, without trying to help by creating Writers. Similarly, if you have a File or URL, consider using these (via Stax2 create methods), instead of constructing InputStreams. -* Close XMLStreamReader and XMLStreamWriter instances when you are done with them: this allows Woodstox to possibly reuse underlying buffers. - -So how significant are these simple rules? They are most important when dealing with small documents: in these cases difference can be an order of magnitude. For bigger documents effects are more limited, but still significant. diff -Nru libwoodstox-java-4.1.3/release-notes/IMPL_DETAILS libwoodstox-java-5.1.0/release-notes/IMPL_DETAILS --- libwoodstox-java-4.1.3/release-notes/IMPL_DETAILS 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/release-notes/IMPL_DETAILS 1970-01-01 00:00:00.000000000 +0000 @@ -1,21 +0,0 @@ -Here are some notes on implementation, as of Woodstox 4.0. - -Namespace handling: - -* Internally there is inconsistencies regarding storing of "no prefix" - and "no namespace URI", due to long and confusing history of how - these should be returned. The planned division for handling this - consistently in future is as follows: - - "No prefix" is to be stored as NULL entries in all applicable - arrays. - + Conversion to "" that Stax API is to return is to be done not - by internal components (InputElementStack, AttributeCollector), - but by front-end (BasicStreamReader). - + Event objects are to store values as they are to be returned - via api, i.e. as "". - - "No namespace" is to be stored as NULL internally - + Conversion to "" that Stax API is to return is to be done not - by internal components (InputElementStack, AttributeCollector), - but by front-end (BasicStreamReader). - + Event objects are to store values as they are to be returned - via api, i.e. as "". diff -Nru libwoodstox-java-4.1.3/release-notes/lgpl/LGPL2.1 libwoodstox-java-5.1.0/release-notes/lgpl/LGPL2.1 --- libwoodstox-java-4.1.3/release-notes/lgpl/LGPL2.1 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/release-notes/lgpl/LGPL2.1 1970-01-01 00:00:00.000000000 +0000 @@ -1,504 +0,0 @@ - GNU LESSER GENERAL PUBLIC LICENSE - Version 2.1, February 1999 - - Copyright (C) 1991, 1999 Free Software Foundation, Inc. - 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - -[This is the first released version of the Lesser GPL. It also counts - as the successor of the GNU Library Public License, version 2, hence - the version number 2.1.] - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -Licenses are intended to guarantee your freedom to share and change -free software--to make sure the software is free for all its users. - - This license, the Lesser General Public License, applies to some -specially designated software packages--typically libraries--of the -Free Software Foundation and other authors who decide to use it. You -can use it too, but we suggest you first think carefully about whether -this license or the ordinary General Public License is the better -strategy to use in any particular case, based on the explanations below. - - When we speak of free software, we are referring to freedom of use, -not price. Our General Public Licenses are designed to make sure that -you have the freedom to distribute copies of free software (and charge -for this service if you wish); that you receive source code or can get -it if you want it; that you can change the software and use pieces of -it in new free programs; and that you are informed that you can do -these things. - - To protect your rights, we need to make restrictions that forbid -distributors to deny you these rights or to ask you to surrender these -rights. These restrictions translate to certain responsibilities for -you if you distribute copies of the library or if you modify it. - - For example, if you distribute copies of the library, whether gratis -or for a fee, you must give the recipients all the rights that we gave -you. You must make sure that they, too, receive or can get the source -code. If you link other code with the library, you must provide -complete object files to the recipients, so that they can relink them -with the library after making changes to the library and recompiling -it. And you must show them these terms so they know their rights. - - We protect your rights with a two-step method: (1) we copyright the -library, and (2) we offer you this license, which gives you legal -permission to copy, distribute and/or modify the library. - - To protect each distributor, we want to make it very clear that -there is no warranty for the free library. Also, if the library is -modified by someone else and passed on, the recipients should know -that what they have is not the original version, so that the original -author's reputation will not be affected by problems that might be -introduced by others. - - Finally, software patents pose a constant threat to the existence of -any free program. We wish to make sure that a company cannot -effectively restrict the users of a free program by obtaining a -restrictive license from a patent holder. Therefore, we insist that -any patent license obtained for a version of the library must be -consistent with the full freedom of use specified in this license. - - Most GNU software, including some libraries, is covered by the -ordinary GNU General Public License. This license, the GNU Lesser -General Public License, applies to certain designated libraries, and -is quite different from the ordinary General Public License. We use -this license for certain libraries in order to permit linking those -libraries into non-free programs. - - When a program is linked with a library, whether statically or using -a shared library, the combination of the two is legally speaking a -combined work, a derivative of the original library. The ordinary -General Public License therefore permits such linking only if the -entire combination fits its criteria of freedom. The Lesser General -Public License permits more lax criteria for linking other code with -the library. - - We call this license the "Lesser" General Public License because it -does Less to protect the user's freedom than the ordinary General -Public License. It also provides other free software developers Less -of an advantage over competing non-free programs. These disadvantages -are the reason we use the ordinary General Public License for many -libraries. However, the Lesser license provides advantages in certain -special circumstances. - - For example, on rare occasions, there may be a special need to -encourage the widest possible use of a certain library, so that it becomes -a de-facto standard. To achieve this, non-free programs must be -allowed to use the library. A more frequent case is that a free -library does the same job as widely used non-free libraries. In this -case, there is little to gain by limiting the free library to free -software only, so we use the Lesser General Public License. - - In other cases, permission to use a particular library in non-free -programs enables a greater number of people to use a large body of -free software. For example, permission to use the GNU C Library in -non-free programs enables many more people to use the whole GNU -operating system, as well as its variant, the GNU/Linux operating -system. - - Although the Lesser General Public License is Less protective of the -users' freedom, it does ensure that the user of a program that is -linked with the Library has the freedom and the wherewithal to run -that program using a modified version of the Library. - - The precise terms and conditions for copying, distribution and -modification follow. Pay close attention to the difference between a -"work based on the library" and a "work that uses the library". The -former contains code derived from the library, whereas the latter must -be combined with the library in order to run. - - GNU LESSER GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License Agreement applies to any software library or other -program which contains a notice placed by the copyright holder or -other authorized party saying it may be distributed under the terms of -this Lesser General Public License (also called "this License"). -Each licensee is addressed as "you". - - A "library" means a collection of software functions and/or data -prepared so as to be conveniently linked with application programs -(which use some of those functions and data) to form executables. - - The "Library", below, refers to any such software library or work -which has been distributed under these terms. A "work based on the -Library" means either the Library or any derivative work under -copyright law: that is to say, a work containing the Library or a -portion of it, either verbatim or with modifications and/or translated -straightforwardly into another language. (Hereinafter, translation is -included without limitation in the term "modification".) - - "Source code" for a work means the preferred form of the work for -making modifications to it. For a library, complete source code means -all the source code for all modules it contains, plus any associated -interface definition files, plus the scripts used to control compilation -and installation of the library. - - Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running a program using the Library is not restricted, and output from -such a program is covered only if its contents constitute a work based -on the Library (independent of the use of the Library in a tool for -writing it). Whether that is true depends on what the Library does -and what the program that uses the Library does. - - 1. You may copy and distribute verbatim copies of the Library's -complete source code as you receive it, in any medium, provided that -you conspicuously and appropriately publish on each copy an -appropriate copyright notice and disclaimer of warranty; keep intact -all the notices that refer to this License and to the absence of any -warranty; and distribute a copy of this License along with the -Library. - - You may charge a fee for the physical act of transferring a copy, -and you may at your option offer warranty protection in exchange for a -fee. - - 2. You may modify your copy or copies of the Library or any portion -of it, thus forming a work based on the Library, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) The modified work must itself be a software library. - - b) You must cause the files modified to carry prominent notices - stating that you changed the files and the date of any change. - - c) You must cause the whole of the work to be licensed at no - charge to all third parties under the terms of this License. - - d) If a facility in the modified Library refers to a function or a - table of data to be supplied by an application program that uses - the facility, other than as an argument passed when the facility - is invoked, then you must make a good faith effort to ensure that, - in the event an application does not supply such function or - table, the facility still operates, and performs whatever part of - its purpose remains meaningful. - - (For example, a function in a library to compute square roots has - a purpose that is entirely well-defined independent of the - application. Therefore, Subsection 2d requires that any - application-supplied function or table used by this function must - be optional: if the application does not supply it, the square - root function must still compute square roots.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Library, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Library, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote -it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Library. - -In addition, mere aggregation of another work not based on the Library -with the Library (or with a work based on the Library) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may opt to apply the terms of the ordinary GNU General Public -License instead of this License to a given copy of the Library. To do -this, you must alter all the notices that refer to this License, so -that they refer to the ordinary GNU General Public License, version 2, -instead of to this License. (If a newer version than version 2 of the -ordinary GNU General Public License has appeared, then you can specify -that version instead if you wish.) Do not make any other change in -these notices. - - Once this change is made in a given copy, it is irreversible for -that copy, so the ordinary GNU General Public License applies to all -subsequent copies and derivative works made from that copy. - - This option is useful when you wish to copy part of the code of -the Library into a program that is not a library. - - 4. You may copy and distribute the Library (or a portion or -derivative of it, under Section 2) in object code or executable form -under the terms of Sections 1 and 2 above provided that you accompany -it with the complete corresponding machine-readable source code, which -must be distributed under the terms of Sections 1 and 2 above on a -medium customarily used for software interchange. - - If distribution of object code is made by offering access to copy -from a designated place, then offering equivalent access to copy the -source code from the same place satisfies the requirement to -distribute the source code, even though third parties are not -compelled to copy the source along with the object code. - - 5. A program that contains no derivative of any portion of the -Library, but is designed to work with the Library by being compiled or -linked with it, is called a "work that uses the Library". Such a -work, in isolation, is not a derivative work of the Library, and -therefore falls outside the scope of this License. - - However, linking a "work that uses the Library" with the Library -creates an executable that is a derivative of the Library (because it -contains portions of the Library), rather than a "work that uses the -library". The executable is therefore covered by this License. -Section 6 states terms for distribution of such executables. - - When a "work that uses the Library" uses material from a header file -that is part of the Library, the object code for the work may be a -derivative work of the Library even though the source code is not. -Whether this is true is especially significant if the work can be -linked without the Library, or if the work is itself a library. The -threshold for this to be true is not precisely defined by law. - - If such an object file uses only numerical parameters, data -structure layouts and accessors, and small macros and small inline -functions (ten lines or less in length), then the use of the object -file is unrestricted, regardless of whether it is legally a derivative -work. (Executables containing this object code plus portions of the -Library will still fall under Section 6.) - - Otherwise, if the work is a derivative of the Library, you may -distribute the object code for the work under the terms of Section 6. -Any executables containing that work also fall under Section 6, -whether or not they are linked directly with the Library itself. - - 6. As an exception to the Sections above, you may also combine or -link a "work that uses the Library" with the Library to produce a -work containing portions of the Library, and distribute that work -under terms of your choice, provided that the terms permit -modification of the work for the customer's own use and reverse -engineering for debugging such modifications. - - You must give prominent notice with each copy of the work that the -Library is used in it and that the Library and its use are covered by -this License. You must supply a copy of this License. If the work -during execution displays copyright notices, you must include the -copyright notice for the Library among them, as well as a reference -directing the user to the copy of this License. Also, you must do one -of these things: - - a) Accompany the work with the complete corresponding - machine-readable source code for the Library including whatever - changes were used in the work (which must be distributed under - Sections 1 and 2 above); and, if the work is an executable linked - with the Library, with the complete machine-readable "work that - uses the Library", as object code and/or source code, so that the - user can modify the Library and then relink to produce a modified - executable containing the modified Library. (It is understood - that the user who changes the contents of definitions files in the - Library will not necessarily be able to recompile the application - to use the modified definitions.) - - b) Use a suitable shared library mechanism for linking with the - Library. A suitable mechanism is one that (1) uses at run time a - copy of the library already present on the user's computer system, - rather than copying library functions into the executable, and (2) - will operate properly with a modified version of the library, if - the user installs one, as long as the modified version is - interface-compatible with the version that the work was made with. - - c) Accompany the work with a written offer, valid for at - least three years, to give the same user the materials - specified in Subsection 6a, above, for a charge no more - than the cost of performing this distribution. - - d) If distribution of the work is made by offering access to copy - from a designated place, offer equivalent access to copy the above - specified materials from the same place. - - e) Verify that the user has already received a copy of these - materials or that you have already sent this user a copy. - - For an executable, the required form of the "work that uses the -Library" must include any data and utility programs needed for -reproducing the executable from it. However, as a special exception, -the materials to be distributed need not include anything that is -normally distributed (in either source or binary form) with the major -components (compiler, kernel, and so on) of the operating system on -which the executable runs, unless that component itself accompanies -the executable. - - It may happen that this requirement contradicts the license -restrictions of other proprietary libraries that do not normally -accompany the operating system. Such a contradiction means you cannot -use both them and the Library together in an executable that you -distribute. - - 7. You may place library facilities that are a work based on the -Library side-by-side in a single library together with other library -facilities not covered by this License, and distribute such a combined -library, provided that the separate distribution of the work based on -the Library and of the other library facilities is otherwise -permitted, and provided that you do these two things: - - a) Accompany the combined library with a copy of the same work - based on the Library, uncombined with any other library - facilities. This must be distributed under the terms of the - Sections above. - - b) Give prominent notice with the combined library of the fact - that part of it is a work based on the Library, and explaining - where to find the accompanying uncombined form of the same work. - - 8. You may not copy, modify, sublicense, link with, or distribute -the Library except as expressly provided under this License. Any -attempt otherwise to copy, modify, sublicense, link with, or -distribute the Library is void, and will automatically terminate your -rights under this License. However, parties who have received copies, -or rights, from you under this License will not have their licenses -terminated so long as such parties remain in full compliance. - - 9. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Library or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Library (or any work based on the -Library), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Library or works based on it. - - 10. Each time you redistribute the Library (or any work based on the -Library), the recipient automatically receives a license from the -original licensor to copy, distribute, link with or modify the Library -subject to these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties with -this License. - - 11. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Library at all. For example, if a patent -license would not permit royalty-free redistribution of the Library by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Library. - -If any portion of this section is held invalid or unenforceable under any -particular circumstance, the balance of the section is intended to apply, -and the section as a whole is intended to apply in other circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 12. If the distribution and/or use of the Library is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Library under this License may add -an explicit geographical distribution limitation excluding those countries, -so that distribution is permitted only in or among countries not thus -excluded. In such case, this License incorporates the limitation as if -written in the body of this License. - - 13. The Free Software Foundation may publish revised and/or new -versions of the Lesser General Public License from time to time. -Such new versions will be similar in spirit to the present version, -but may differ in detail to address new problems or concerns. - -Each version is given a distinguishing version number. If the Library -specifies a version number of this License which applies to it and -"any later version", you have the option of following the terms and -conditions either of that version or of any later version published by -the Free Software Foundation. If the Library does not specify a -license version number, you may choose any version ever published by -the Free Software Foundation. - - 14. If you wish to incorporate parts of the Library into other free -programs whose distribution conditions are incompatible with these, -write to the author to ask for permission. For software which is -copyrighted by the Free Software Foundation, write to the Free -Software Foundation; we sometimes make exceptions for this. Our -decision will be guided by the two goals of preserving the free status -of all derivatives of our free software and of promoting the sharing -and reuse of software generally. - - NO WARRANTY - - 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO -WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. -EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR -OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY -KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE -LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME -THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN -WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY -AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU -FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR -CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE -LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING -RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A -FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF -SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH -DAMAGES. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Libraries - - If you develop a new library, and you want it to be of the greatest -possible use to the public, we recommend making it free software that -everyone can redistribute and change. You can do so by permitting -redistribution under these terms (or, alternatively, under the terms of the -ordinary General Public License). - - To apply these terms, attach the following notices to the library. It is -safest to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least the -"copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -Also add information on how to contact you by electronic and paper mail. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the library, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the - library `Frob' (a library for tweaking knobs) written by James Random Hacker. - - , 1 April 1990 - Ty Coon, President of Vice - -That's all there is to it! - - diff -Nru libwoodstox-java-4.1.3/release-notes/lgpl/LICENSE libwoodstox-java-5.1.0/release-notes/lgpl/LICENSE --- libwoodstox-java-4.1.3/release-notes/lgpl/LICENSE 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/release-notes/lgpl/LICENSE 1970-01-01 00:00:00.000000000 +0000 @@ -1,14 +0,0 @@ -This copy of Woodstox XML processor is licensed under the -Lesser General Public License (LGPL), version 2.1 ("the License"). -See the License for details about distribution rights, and the -specific rights regarding derivate works. - -You may obtain a copy of the License at: - -http://www.gnu.org/licenses/licenses.html - -A copy is also included with both the the downloadable source code package -and jar that contains class bytecodes, as file "LGPL 2.1". In both cases, -that file should be located next to this file: in source distribution -the location should be "release-notes/lgpl"; and in jar "META-INF/" - diff -Nru libwoodstox-java-4.1.3/release-notes/lgpl/NOTICE libwoodstox-java-5.1.0/release-notes/lgpl/NOTICE --- libwoodstox-java-4.1.3/release-notes/lgpl/NOTICE 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/release-notes/lgpl/NOTICE 1970-01-01 00:00:00.000000000 +0000 @@ -1,8 +0,0 @@ -This product currently only contains code developed by authors -of specific components, as identified by the source code files. - -Since product implements StAX API, it has dependencies to StAX API -classes. - -For additional credits (generally to people who reported problems) -see CREDITS file. diff -Nru libwoodstox-java-4.1.3/release-notes/PERF libwoodstox-java-5.1.0/release-notes/PERF --- libwoodstox-java-4.1.3/release-notes/PERF 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/release-notes/PERF 1970-01-01 00:00:00.000000000 +0000 @@ -1,52 +0,0 @@ -== Performance metrics == - -Here are miscellaneous non-normative test runs - -=== Red Hat Linux 9.0, Athlon 1800+, JDK 1.4.2 == - -PerfTest, 30 seconds: - - stax_elem.xml: - Wstx: 420 - 439 [with just .length: 415 - 449] - StaX RI: 331 - 338 [with just .length: 350 - 359] - Crimson, Sax: 300 - 321 - Xerces, Sax: 280 - 307 - Crimson, DOM: 57 - 58 - Xerces, DOM: 86 - - stax_text.xml: - RI: - Wstx: - -=== Solaris 8, Ultra-60 (2 x 450 Mhz Sparc III), JDK 1.4.2 ==- - -[Woodstox 0.9.1] -PerfTest, 30 seconds: - - stax_elem.xml, ISO-Latin: - Wstx: 87 - 93 - StaX RI: 84 - 86 - Crimson, Sax: - Xerces, Sax: - Crimson, DOM: - Xerces, DOM: - - stax_elem.xml, UTF-8: - Wstx: 77 - 85 - StaX RI: 77 - 79 - Crimson, Sax: - Xerces, Sax: 63 - 72 - Crimson, DOM: - Xerces, DOM: - - stax_text.xml, ISO-Latin: - Wstx: 207 - 217 - RI: 154 - 166 - - stax_text.xml, UTF-8: - Wstx: 319 - 330 - 344 - RI: 280 - 294 - - test-30.xml, UTF-8 (StarOffice xml content): - Wstx: 319 - 330 - 344 - RI: 280 - 294 diff -Nru libwoodstox-java-4.1.3/release-notes/README libwoodstox-java-5.1.0/release-notes/README --- libwoodstox-java-4.1.3/release-notes/README 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/release-notes/README 1970-01-01 00:00:00.000000000 +0000 @@ -1,18 +0,0 @@ -== Woodstox XML parser == - -Woodstox is an XML-parser that allows parsing of XML documents in so-called -pull mode (aka "pull parsing"). -It specifically implements StAX 1.0 API: - -http://www.jcp.org/en/jsr/detail?id=173 - -which defines what is closest to being the J2xE standard for XML pull parsers. - -Woodstox was originally written by Tatu Saloranta (. - -Woodstox licensing is explained in file LICENSE; be sure to read it -to understand licensing. - -Contributions to the source code need to be made as specified by -the License; so that they can be distributed according to the -License terms. diff -Nru libwoodstox-java-4.1.3/release-notes/STAX2.txt libwoodstox-java-5.1.0/release-notes/STAX2.txt --- libwoodstox-java-4.1.3/release-notes/STAX2.txt 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/release-notes/STAX2.txt 1970-01-01 00:00:00.000000000 +0000 @@ -1,69 +0,0 @@ -This document groups functionality offered by the Stax2 interface -(packages under org.codehaus.stax2) above and beyond basic Stax 1.0 -API. - -== Access to formerly missing information == - -* DOCTYPE declaration: can access root name, public/system identifiers, - and internal subset all separately; similarly added matching - output methods -* Attribute information: can find index of the specified attribute, - as well as ID and NOTATION attribute indexes (as per DTD) -* Location information (XMLStreamLocation2): - * Access to nested Locations (parent context) - * Separate byte/char offsets; value type as long instead of - int to allow for multi-gigabyte input [NOT FULLY IMPLEMENTED] -* Misc. information: - * XMLStreamReader.isEmptyElement() (whether current - START_ELEMENT was a result of an empty element, i.e. ), - * XMLStreamReader.getDepth() (number of enclosing start elements, - including current START_ELEMENT) - -== Efficient (fully streaming) access == - -* getText methods that write contents of textual events through - Writer object passed as the argument -* Pass-through XMLStreamWriter.copyEventFromReader method -* XMLStreamReader.skipElement allows efficient skipping of all children - of an element - -== Configurable writers == - -* All events can now be output through specified XMLStreamWriter; - this allows for full configuration of output (namespace bindings, - encoding/quoting) -* Can define a custom quoter/encoder for textual content -* Can define a custom quoter/encoder for attribute values -* Raw write access using XMLStreamWriter.writeRaw(), for outputting - text as is, without quoting/encoding. - -== Basic support for per-reader/writer configuration == - -* XMLStreamReader: allow overriding of external DTD subset. -* XMLStreamWriter: (no options yet) - -== Fully pluggable bi-directional validation framework == - -(for Stax2 v2.0 and above, i.e. Woodstox 3.0) - -* Extensible: easy to add custom validators, and infoset augmenters (for - example, DTD validator adds default attribute values). -* Support for multiple chainable validators (for example: can do both - DTD validation and RelaxNG validation simultaneously). -* Fully bi-directional: can not only validate when parsing, but - when outputting as well. -* Configurable problem (validation error) handling: can collect all - validation problems, or do fail-fast validation (exception on encountering - the first problem). - -== Typed access (reading and writing simple Schema/Java types) - -(for Stax v3.0 and above, i.e. Woodstox 4.0) - -* Bi-directional, for stream readers and writers -* Both for attribute and element content -* Primitive types (boolean, numeric) -* List types (lists of ints, doubles) -* Chunked binary (base64) element content access - - diff -Nru libwoodstox-java-4.1.3/release-notes/stax-compatibility.txt libwoodstox-java-5.1.0/release-notes/stax-compatibility.txt --- libwoodstox-java-4.1.3/release-notes/stax-compatibility.txt 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/release-notes/stax-compatibility.txt 1970-01-01 00:00:00.000000000 +0000 @@ -1,25 +0,0 @@ -Current version implements full StAX 1.0 API, to the best understanding -of the author. Note, however, that 1.0 version of the specification -has quite a bit of ambiguity regarding several features (see below for -examples). - -First, there are some features where implementation could -arguably be improved, to bring it to closer to the spirit of -the specification: - -* SAX input (source) and output (result) objects can not be used with - XMLInputFactory and XMLOutputFactory. - -Some of open questions regarding exact meaning of the specification -include: - -* If entities are NOT to be expanded, how does this affect: - * Pre-defined entities (amp, lt, gr, apos)? Currently Woodstox leaves - this unexpanded as well, and returns them as separate entities; - this seems close to what XML specs indicates (these entities are - no different from explicitly declared ones), but is not necessarily - intuitive from application's point of view. - * Entities in attribute values. Since there is no mechanism to return - such events, Woodstox expands such entities automatically. The - alternative would be to signal an error. - diff -Nru libwoodstox-java-4.1.3/release-notes/USAGE libwoodstox-java-5.1.0/release-notes/USAGE --- libwoodstox-java-4.1.3/release-notes/USAGE 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/release-notes/USAGE 1970-01-01 00:00:00.000000000 +0000 @@ -1,114 +0,0 @@ -== Using Woodstox XML parser via StAX == - -Woodstox is designed to be used as pluggable StAX implementation (see - for explanation about -StAX specification). As such, reader and writer instances are usually -created using STaX factory methods; this is the recommended method. - -StAX specification defines couple of methods for specifying which StAX -implementation to use (properties file, service entries in jar file, -System properties); in each case you have to basically define 3 classes: -one that implements XMLInputFactory, one that implements XMLOutputFactory, -and third one that implements XMLEventFactory (to potentially be used by -XMLInputFactory implementation). -[sidenote: current version of Woodstox really only needs first two for - correct operation; internally it does not make use of the event factory]. - -For Woodstox classes are, respectively: - -com.ctc.wstx.stax.WstxInputFactory -com.ctc.wstx.stax.WstxOutputFactory -com.ctc.wstx.stax.WstxEventFactory - -Woodstox jar files include service entries that will effectively also -specify Stax implementation classes, instead of system properties -(although note that system properties have preference over service -entries). This works well if you only include a single Stax implementation -jar in the classpath. - -However, if you have multiple StAX implementations, you may have to -specifically set/override system properties to point to the implementation -you want: from Java code it can be done by calling: - -System.setProperty("javax.xml.stream.XMLInputFactory", - "com.ctc.wstx.stax.WstxInputFactory"); -System.setProperty("javax.xml.stream.XMLOutputFactory", - "com.ctc.wstx.stax.WstxOutputFactory"); -System.setProperty("javax.xml.stream.XMLEventFactory", - "com.ctc.wstx.stax.WstxEventFactory"); - -when your application starts (or the class that access factories is -initialised). Alternatively, you can also set system properties via command -line switches when starting your application -(-Djavax.xml.stream.XMLInputFactory=javax.xml.stream.XMLInputFactory - and so on). - -And of course the simplest possible way is to just refer to the Woodstox -implementations of the input factories directly: - - XMLInputFactory ifact = new WstxInputFactory(); - - -== Using Woodstox XML parser without StAX == - -It is also possible to directly instantiate objects (specifically, -Woodstox implementations of Stax factories), but the API (class -names, constructors, factory methods) is not guaranteed to remain -static between major releases. -It is possible that in future some public factory methods will be added, -to allow creating more specialized instances, to overcome some of -StAX API limitations. - -It is NOT possible to use Woodstox without having StAX classes -available, since many Woodstox classes implement or extend -StAX interfaces/abstract classes. - - -== Dependencies == - -Due to implementing StAX API, Woodstox has dependency to StAX API JAR -file. For up to JDK 1.5.0, StAX is not (yet?) part of J2SE or J2EE, so you -have to download StAX jar separately. - -Woodstox version up to 3.0 can be run on JDKs 1.2 and up. -Some of features of later JDKs are optionally used if available; -these generally are "nice-to-have" -features, such as chained Exceptions (1.4+), order-retaining definitions -for entities and notations (1.4+) and so on. -The only caveat is that compiling Woodstox has to be done using javac -with 1.4 libs, or alternatively, by modifying Ant build.xml to ignore -the few class files that refer to 1.3/1.4 features (found in -com.ctc.wstx.compat package). - -Woodstox version after 3.0.x will require JDK 1.4 or higher as the -baseline. There are no plans to require JDK 1.5 currently. - - -== Performance == - -Full discussion on best practices for good performance needs to be done -outside scope of a simple document, but here are some basic things regarding - performance: - -* For optimal performance, factory instances should be reused whenever - possible. - Since factory objects (XMLInputFactory, XMLOutputFactory) are thread-safe - after being initialized and configured, there is no risk sharing - them (but only after proper initialization!). It is thus often possible - to share a single input and single output factory instances for the - whole application. The reasons why factory reusing is very important - for performance are: - o There is significant overhead in constructing new factories when - using Stax interface (but note: no significant overhead when just - instantiating Woodstox factories themselves) - o Most caching is done on per-factory basis: specifically, symbol - tables are cached this way. Similarly DTD caches are per-factory. -* It is important to CLOSE XMLStreamReader and XMLStreamWriter instances - after they are no longer needed. This allows readers/writers to - release internal buffers they use -- this is especially important when - processing small documents, since relative overhead of buffer allocation - is most significant for these use cases. -* Many input factory configuration settings do have effect on performance. - For obtaining highest performance, there is a specific profile that can - be set when 100% XML specs compatibility is not needed (default settings - support 100% XML compatibility). diff -Nru libwoodstox-java-4.1.3/release-notes/VERSION libwoodstox-java-5.1.0/release-notes/VERSION --- libwoodstox-java-4.1.3/release-notes/VERSION 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/release-notes/VERSION 2018-03-31 01:33:28.000000000 +0000 @@ -1,641 +1,41 @@ -Version: 4.1.3 - -Release date: 23-Apr-2012 - -Description: - Third patch release for 4.1 - -Problems fixed: - -* [WSTX-271] DOMWrappingWriter.writeComment() creating CDATASection, not Comment - (reported by Martin V) -* [WSTX-276] 'InputConfigFlags.CFG_NORMALIZE_LFS' flag conflicts with 'CFG_AUTO_CLOSE_INPUT' - (reported by Andreas V) +Project: woodstox ------------------------------------------------------------------------ -== History: == +=== Releases === ------------------------------------------------------------------------ -4.1.2 [27-Aug-2011] - -Problems fixed: - -* [WSTX-267] P_NORMALIZE_LFS mis-mapped - (reported by Mike S) -* [WSTX-268] Missing namespace information when unmarshalling from DOMSource - (reported by Blaise D) -* [WSTX-270] Allow changing whether prefix for default namespace - is returned as "" (4.x default) or null (which apparently is what - latest Stax spec says) using WstxInputProperties. - (requested by Ivan) - -4.1.1 [27-Jan-2011] - -Problems fixed: - -- All fixes from 4.0.x up to 4.0.10 - -4.1.0 [13-Dec-2010] - -Problems fixed: - -* [WSTX-201]: XMLStreamReader.isCharacters() can return inconsistent - value compared to XMLStreamReader.getEventType() - (reported by Andreas V) -* [WSTX-254]: Stax2ReaderAdapter2.getDepth() incorrect after calling - getElementAs (from StaxMate bug) - -Improvements: - -* [WSTX-237] Add size limit to InternCache -* [WSTX-248] Java URL.hashCode() cause issues with DTD caching - (reported by Christophe C) -* [WSTX-251] Improve extensibility of XMLStreamWriter construction - (suggested by Eric D) -* [WSTX-252] Add EmptyElementHandler to allow customizing whether - empty elements can be written, on per-tag basis - (suggested by Eric D) -* Rewrote attribute parsing/collection part to use separate wrapper - classes (instead of primitive arrays); to support easier modifications - and custom additions to collected attribute information. - -4.0.9 [08-Oct-2010] - -Problems fixed: - -* [WSTX-244] DOMWrappingReader sometimes duplicates text content - (reported by Laszlo V) -* [WSTX-246] DOMWrappingReader returns null Location -* [WSTX-249] TextAccumulator had a bug corrupting text - (reported by Habib C) - -4.0.8 [05-May-2010] - - Improvements: - - * [WSTX-206] Provide a way to configure SAX parser with all config - settings available to Stax readers (add WstxSAXParser.getStaxConfig()) - (suggested by StŽphane C) - * [WSTX-234] Restore feature WstxInputProperties.NORMALIZE_LFS; add - WstxInputProperties.TREAT_CHAR_REFS_AS_ENTS - (requested by Peter S) - - Problems fixed: - - * [WSTX-220]: Issues in cases where excessive intern()ing causes - synchronization problems; reduce contention by splitting sync block - (reported by Rajeswar R) - * [WSTX-226]: SAX parser was ignoring passed encoding. - (reported by Andreas V) - * [WSTX-228]: Property WstxOutputProperties.P_OUTPUT_ESCAPE_CR - not used for attribute content - (reported by Brian S) - * [WSTX-236]: Make WstxInputLocation Serializable - (suggested by Myles B) - -4.0.7 [16-Dec-2009] - - * [WSTX-224]: getElementAsBinary() fails when reading large amounts of - data (in coalescing mode) - (reported by Alexander R) - -4.0.6 [01-Oct-2009] - - Problems fixed: - - * [WSTX-211]: Failure to parse long CDATA section properly when - using XMLStreamReader.getElementText(), non-coalescing - (reported by Kevin B) - -4.0.5 [09-Jun-2009] - - Problems fixed: - - * [WSTX-207]: Schema factory failing to load schema if filename has - characters that need to be escaped when converted to URL - (reported by Arun K) - * [WSTX-208]: Value of default attributes not found using - XMLStreamReader.getAttributeValue(String,String) - (reported by Jack R) - * [WSTX-209]: Validation issues not reported to validation problem reporter - (reported and fixed by Benson M) - -4.0.4 [07-May-2009] +5.1.0 (31-Mar-2018) - Problems fixed: +#23: Text content is not validated correctly when copying events to `XmlStreamWriter` + (reported by hxc9@github) +#43: `CompactStartElement` appears to incorrectly classify attributes as default + (reported by Jonathan T) +- Add `Automatic-Module-Name` indicator in jar metadata, for Java 9 +- Upgrade `stax2-api` dependency to 4.1 (from 3.1) - * [WSTX-200]: NPE when validating partial documents (sub-trees) - (reported by Benson M) - * [WSTX-202]: BijectiveNsMap#findPrefixByUri doesn't handle masked - namespace declarations correctly - (reported by Andreas V) - * [WSTX-204] Custom entity resolver setting was not working with - SAX API (due to JDK impl idiocy) - (reported by Stéphane Claret) +5.0.3 (23-Aug-2016) -4.0.3 [04-Mar-2009] +#13: `BasicStreamReader.getElementText()` behavior doesn't match Java documentation + (reported by Caleb-An@github) +#15: `BasicStreamReader` should use `WstxUnexpectedCharException` instead of WstxParsingException + (reported by dima-kapustin@github) +#16: Incorrect validation error(s) only using Stax2 writer + (reported by hxc9@github) +#21: 500 characters limit when calling XMLStreamReader#getText() after CDATA event + (reported by elrodro83@github) - Problems fixed: +5.0.2 (10-Dec-2015) - * [WSTX-191] Validation failure with W3C Schema, empty text - (reported by Yves M) +#10: Stax 4.0.0 is not compatible with Woodstox 5.0.1 + (reported by naveengopi@github) -4.0.2 [25-Feb-2009] +5.0.1 (02-Apr-2015) - Problems fixed: +#3: Initial 5.0.0 release did not contain class files (d'oh!) + (reported by norrisjeremy@github) +#4: Fix validation of text for an XMLStreamWriter + (reported by Wilco G, wgreven-ibr@github) - * [WSTX-188] Could get an ArrayIndexOutOfBounds exception for - StartElement.getAttributeByName() under specific conditions - (reported by Roger W) - * [WSTX-190]: NPE with DTD validator, missing attribute. - (reported by Andreas V) - -4.0.1 [29-Jan-2009] - - Problems fixed: - - * A bug in Stax2 RI CharArrayBase64Decoder was skipping part of - input under certain conditions; did not occur in stax2 test - suite, but did happen for another Stax2 implementation. - * There were many problems with Maven dependencies; specifically it looks - like support for version ranges is hard to make work with somewhat - manual release process in use now. Thus changed dependencies to use - exact versions for now (until 5.0?) - -4.0.0 [01-Jan-2009] - - The first official release: no major changes over 3.9.9-3. - However, here is a summary of work since 3.2. - (For details refer to release notes for preceding release candidates) - - Major new functionality: - - * W3C Schema Validation support - * Typed Access API (org.codehaus.stax2.typed.*), including: - * TypedXMLStreamReader, TypedXMLStreamWriter (reading and writing) - * Types based on W3C Schema Datatypes, supporting: - * Simple values (int, long, float, double, boolean, QName) - * Array values of integral numeric types - * Binary support for base64 encoded content - * Additional extension methods for efficient custom decoding. - - Interoperability improvements: - - * DOM-compatibility: Namespace-repairing mode implemented for DOM-backed - stream writers (ones built for DOMResult) - * OSGi: Woodstox jars are now OSGi bundles (as well as supporting MSV - jars when needed for validation) - * Maven: split core woodstox jar and stax2 api jar, relationship now - properly modelled (including dependencies to MSV jars) - - New configuration properties: - - * WstxOutputProperties.P_ADD_SPACE_AFTER_EMPTY_ELEM: whether to add space - between name of empty tag and following "/>". - * WstxOutputProperties.P_AUTOMATIC_END_ELEMENTS: whether stream writers - closes open xml tree upon stream writer close: - * WstxOutputProperties.P_OUTPUT_INVALID_CHAR_HANDLER to allow for - replacing "invalid XML characters" on output. - - Other improvements: - - * Implement XMLEvent.equals() and .hashCode() to allow for reliable - comparisons of event objects. - * Add direct support for Stax2ByteArraySource for improved performance - when used instead of ByteArrayInputStream. - - Compatibility changes: - - * JDK: minimum required now 1.4 - * Stax 1.0 API: - * All empty/missing namespace/prefix values now reported as "", not null - * WstxInputFactory.IS_COALESCING defaults to 'false' (was erroneously - defaulting to 'true') - * Removed deprecated properties P_NORMALIZE_LFS and P_NORMALIZE_ATTR_VALUES - ------------------------------------------------------------------------- - -3.9.9-3 [26-Dec-2008] - - API changes: - - * Changed passing of Base64Variant argument: since it's an optional argument - it should come after mandatory ones (wasn't with earlier RCs). - - Problems fixed: - - * [WSTX-182], StreamResult with only SystemId did not work. - (reported by Christoper P-S) - * [WSTX-183] Trying to create DOM-backed writer with DOM Element (as opposed - to Document) failed, due to trying to attach the element. - (reported by Christoper P-S) - -3.9.9-2 [17-Dec-2008] - - Problems fixed: - - * [WSTX-177] Added support for accessing Stax2 factories (input, output, - validation schema) through OSGi services interface. - * [WSTX-178] Source code distribution did not have an intervening "[artifact]-[version]" - directory, which means that when unexpanding, contents may spill in unexpected places - * [WTSX-179] Problem with XMLStreamReader.getElementText(), where - data may be corrupt under some situations (could also affect - typed access methods similarly). - -3.9.9-1 [21-Nov-2008] - - Problems fixed: - - * [WTSX-121] Ordering of NOTATION definitions and ATTLIST references - should not matter - * [WTSX-142] Ordering of NOTATION definitions and ENTITY references - should not matter - * [WSTX-154] XMLStreamReader, XMLStreamWriter implementations were - quietly discarding XMLStreamException thrown by XMLReporter. - - New functionality: - - * [WSTX-50] Improve handling of base URIs; notation and entity declarations, doc property. - * [WSTX-148] Implement XMLEvent.equals() and .hashCode() to allow - for easy comparisons. - (requested by Sylvain L) - * [WSTX-150] Add stream reader AND writer delegates for Stax2. - * [WSTX-151] Generic typed access methods (getElementAs(), getAttributeAs()) - added to TypedXMLStreamReader. - * [WSTX-152] Add OSGi headers to the jar manifest. - (requested by Romain D) - * [WSTX-157] Add XMLReporter2 to allow for extended access to - information about non-fatal problems (including validation probs) - * [WSTX-163] Add XMLStreamWriter2.closeCompletely() - * [WSTX-165] Add property (WstxOutputProperties.P_AUTOMATIC_END_ELEMENTS) - to allow enabling/disabling automatic addition of end elements - when closing stream writer - (requested by Ian B) - * [WSTX-166] Add direct support for Stax2ByteArraySource for improved - performance. Measured speedup 5-10% compared to using ByteArrayInputStream. - * [WSTX-167] Add new property (WstxOutputProperties.P_OUTPUT_INVALID_CHAR_HANDLER) - which can be used to replace invalid characters (such as Ascii control - characters) from within content to output. - * [WSTX-169] Add support for alternative (non-standard) Base64 encoding - variants. - * [WSTX-175] Add OSGi support for bundled MSV jars. - -3.9.2 [06-May-2008] -3.9.1 [16-Mar-2008] -3.9.0 [23-Nov-2007] - - New functionality (major): - - * [WSTX-137] Add W3C Schema validation support using MSV. - * Reference implementation of Stax2 API now included under - org.codehaus.stax2.ri (implements classes that can be implemented - in generic way, making use of existing Stax 1.0 implementation - or other Stax2 classes) - * Partial/preliminary Stax2 Typed Access API, implementation (including - configurable value encoder): supports booleans, ints, longs, for - element and attribute content. - - New functionality (minor): - - * [WSTX-125] Adding of space between empty element, and closing - "/>" is now optional, configurable using - 'WstxOutputProperties.P_ADD_SPACE_AFTER_EMPTY_ELEM'. - * Converted Woodstox-specific property WstxInputProperties.P_LAZY_PARSING - to XMLInputFactory2.P_LAZY_PARSING (stax2 API). - * More complete Stax2 API ref. impl, adding generic XMLEventReader - implementation. - - Problems fixed: - - * [WSTX-120] By default, content fixing is now disabled, to - maximize interoperability, and to follow "principle of least - surprise" (i.e. avoid confusion arising from the stream writer - outsmarting developer) - * [WSTX-139] DOMWrappingWriter now implements repairing mode. - * [WSTX-140] Default settings for WstxInputFactory.IS_COALESCING - changed to Boolean.FALSE as per Stax specs; was defaulting to - true by accident - - Clean-up: - - * Removed compatibility classes from under com.ctc.wstx.compat, - since baseline JDK requirement is now 1.4, and workarounds are - not needed (for now?) - * Removed deprecated properties P_NORMALIZE_LFS and - P_NORMALIZE_ATTR_VALUES, and needed code support. - * [WSTX-105] Transformed the only existing input-side feature - (FEAT_DTD_OVERRIDE) into matching input-side property - (XMLInputFactoty2.P_OVERRIDE_DTD). - * [WSTX-127] Stax API specification compatibility improvements: - (also resolves [WSTX-57]) - * Missing prefixes now reported as "", not nulls. - * "No namespace" now reported as "", not null. - * Changing behavior of XMLStreamReader.getProperty() slightly (but within - constraints of Stax 1.0 API specification): requesting value of - an unknown property will now return null, instead of throwing an - exception. - ------------------------------------------------------------------------- - -3.2.8 [26-Dec-2008] - - Problems fixed: - - * [WSTX-172] WstxInputFactory and WstxOutputFactory were final, should not be. - * [WSTX-174] Some old App servers have broken QName impl, are missing - 3-arg constructor - (requested by Arash A) - -3.2.7 [02-Sep-2008] - - Problems fixed: - - * [WSTX-145] DOMWrappingReader was not implementing coalescing mode. - (reported by David C) - * [WSTX-156] Pass XMLValidationProblem as 'relatedInformation' object - in call XMLReporter.report(...) - * [WSTX-158] XMLStreamReader.isWhiteSpace() returns potentially incorrect - value when text segments starts with an entity - (reported by Daniel R) - * [WSTX-162] Name/namespace-URI interning not enabled for DOM-backed - readers, getProperty() claims they are - (reported by Pawel L) - * Stax2ReaderAdapter.getDepth() was off by one (too low) for - END_ELEMENT (causing problems for StaxMate) - * [WSTX-164] Some XMLStreamReader.getAttributeXxx() methods were not - properly checking validity of passed-in index argument. - -3.2.6 [01-Jun-2008] - - Problems fixed: - - * [WSTX-144] Problem when trying to output namespace declaration using - a DOMResult-backed writer. - (reported by Martin V) - * [WSTX-153] XMLReporter not getting called for non-fatal validation errors - (reported by Eduardo R-R) - * [WSTX-155] NPE after reporting a missing #REQUIRED attribute. - (reported by Eduardo R-R) - -3.2.5 [23-Apr-2008] - - Problems fixed: - - * [WSTX-146] XMLStreamWriter implementation was using encoding - returned by OutputStreamWriter as is; and JDK was reporting - legacy encodings. Needed to normalize encoding. - (reported by Jim A) - - Improvements: - - * Added support for property: - "http://java.sun.com/xml/stream/properties/implementation-name" - it is now recognized as a synonym of XMLStreamProperties2.XSP_IMPLEMENTATION_NAME - -3.2.4 [17-Jan-2008] - - Problems fixed: - - * [WSTX-141]: Copying of CDATA events, using XMLEventWriter, was - producing garbled output. - (reported by Frank B) - * [WSTX-143]: UTF8Reader had a bug in handling of DEL (127) character - at buffer boundary. - (report by Matt G) - -3.2.3 [14-Nov-2007] - - Problems fixed: - - * [WSTX-132]: NPE in BaseNsStreamWriter if event writer managed to - pass in null namespace URI. - * [WSTX-134]: Bug in DOMWrappingReader.isWhiteSpace implementation - (reported by Yoon-Je C) - * [WSTX-135]: Incorrect namespace binding for parent element, for - repairing namespace writer. - (reported by Yoon-Je C) - * [WSTX-138]: Sub-optimal error messaging for incompatible encoding - declaration, physical encoding used (EBCDIC vs UTF-x) - (reported by Wouter C) - -3.2.2 [26-Sep-2007] - -Description: - Second patch release for 3.2. - - Problems fixed: - - * [WSTX-104] Added missing support for outputting to a DOM tree (via - XMLOutputFactory.createXMLStreamWriter(DOMSource)). - - Newfunctionality: - - * [WSTX-122] Adding support for EBCDIC encoding(s), using a - simple bootstrapper to process xml declaration, then use - JDK default codec. - -3.2.1 [03-Apr-2007] - - Problems fixed: - - * Added deprecation marker for Wstx properties that will not be - supported in 4.0 - * [WSTX-106] Descriptions missing from many wrapped IOExceptions; - specifically obscuring some character validity failures - (reported by Sami D) - * [WSTX-108] Maven pom files were missing info (license, org etc) - (reported by Daniel K) - * [WSTX-109], a bug in xml declaration handling in multi-doc mode - (reported by Abde S) - * [WSTX-110] Exception chaining would itself cause an exception, - on some platforms. - (reported by Erik Bergersjö) - * [WSTX-111] (Stax 1.0 TCK incompliancy): Filtered stream reader was - not initialized to point to first accepted event. This is different - from expectations of Stax TCK (although identical to behavior of - Stax RI). - (reported by Santiago P-G) - * [WSTX-113]: problems with DOMSource when DOM parsed in - non-namespace mode) - (reported by Daniel K) - * [WSTX-114] Handling of ID attribute uniqueness check was failing - in non-namespace mode: last character was dropped, leading to - false collisions - (reported by Linus E) - - Newfunctionality: - - * [WSTX-112] Added access to underlying output stream/writer, via - XMLStreamReader.getProperty(). Properties added are - 'WstxOutputProperties.P_OUTPUT_UNDERLYING_STREAM' and - 'WstxOutputProperties.P_OUTPUT_UNDERLYING_WRITER'. - -3.2.0 [28-Dec-2006] - - Problems fixed: - - * [WSTX-70] External parsed entity references were not resolved using - correct path context - (reported by Michael K) - * [WSTX-86] Maven group id wrong: was "woodstox", should be - "org.codehaus.woodstox" - * [WSTX-89] Line number information was not properly updated in - some cases (boundary condition with Windows, \r\n, linefeeds) - (reported by Frank B) - * [WSTX-96] Beginning part of comments (for longer comments) - was sometimes duplicated by the XMLStreamWriter implementation - (reported by Wolfgang H) - * [WSTX-97] Character offsets (for XMLStreamReader.getLocation()) - were sometimes decremented; fixed, and added a unit test - (reported by Frank B) - * [WSTX-99] Encoding problems with XMLStreamWriter. - * [WSTX-102] WStartDocument construction resulted in NPE, when using - DOM source. - (reported by Werner D) - * [WSTX-103] Repairing writer had a bug that could result in wrong - prefix being reported/output. - (reported by Michael A) - * StartElement.writeUsing() was not properly outputting attributes. - - Improvements: - - * [WSTX-90] Xml writing improved by 5-10% by consistenly using - System.arraycopy (and String.getChars() which uses it) where - possible. - (reported by Davanum S., submitted patch suggesting optimization - that was included) - (also note that this fix resulted in regression, WSTX-91, fixed) - * [WSTX-92] Improved speed of XMLStreamWriter.writeCharacters, by - using intermediate char[] buffer for longer String. - (suggested by Davanum S, submitted a patch) - * [WSTX-93] System id part of Location reported for expanded external - entities was not a valid (resolved) URI, now is. - - New functionality: - - * [WSTX-33] Woodstox now implements SAX2 interface natively. So, it - is fair to say that Woodstox is now StAX/SAX implementation. - (also, note that there were transient problems related to this - feature, in trunk, such as WSTX-95, WSTX-101 - * [WSTX-94] Added new property (WstxOutputProperties.P_OUTPUT_ESCAPE_CR; - default is Boolean.TRUE), which determines whether \r in textual - content to be written will be escaped by the default stream writer - serializers. The default is to escape \r characters, to ensure - clean round-trippability. - (requested by Brett P) - -3.1.0 [02-Nov-2006] - - Problems fixed: - - * [WSTX-23] xml:space attribute DTD type (should be enumeration as per - xml 1.0 specification) was not checked - - Improvements: - - * [WSTX-42] SPACE events were not returned in DTD-aware non-validating mode. - * [WSTX-68] XMLStreamWriter.writeNamespace() was ignored in repairing mode - (but not any more). Similarly, prefix was only used if no existing binding - was found: now will try to honor prefix even at expense of reusing - existing bindings. - - Newfunctionality: - - * [WSTX-22] Basic xml:id (typing) support added. Will only validate - uniqueness of xml:id attribute values in DTD-validating mode, for now. - -3.0.2 [27-Sep-2006] - - Problems fixed: - - * [WSTX-81] Character/byte offset for Location not correctly calculated - (reported by Mickael G) - * [WTSX-82] URL handling had problems on Windows platform, with file-based - URLs that refer to network drives - (reported by Christian B) - * [WSTX-83] One more NPE in ElemAttrs for namespace URI checks. - (reported by Oleg R) - -3.0.1 [29-Aug-2006] - - Problems fixed: - - * [WSTX-69] Incorrect types returned by XMLStreamReader, when - notations/entities are requested. - (report by Michael K) - * [WSTX-72] Closing of output streams/writers in cases where that should - not be done (plus similar problems on input side) - (reported by Matt S) - * [WSTX-74] Woodstox wasn't throwing NoSuchElementException at the end - (reported by Lucian H) - * [WSTX-77] Bug in DTDValidator.validateAttribute() passing wrong args - to StringUtil.matches() - (reported by Vim D R) - * [WSTX-81] Character/byte offset for Location not correctly calculated - (reported by Mickael G) - * [WTSX-82] URL handling had problems on Windows platform, with file-based - URLs that refer to network drives - (reported by Christian B) - -3.0.0 (final) [07-Aug-2006] - - Problems fixed: - - * A NullPointerException with StartElement.getAttributeByName() (apparently - only happening when creating Attributes via Event Factory) - * [WSTX-64]: CompactNsContext.outputNamespaceDeclarations NPE. - (reported by Wolfgang H) - * Fixed a problem with XMLEventReader.nextTag(), when peek() was called - to access StartDocument event first. - (reported by Lucian H) - * Fixed a minor non-conformance issue with StartDocument, was not defaulting - version pseudo-attribute to '1.0' (returned null if no xml declaration, - ie. same as what XMLStreamReader returns). - * [WSTX-65]: Fixed multiple problems with repairing stream writer, and - the handling of automatic namespace declarations. - -3.0rc1, 3.0rc2 [08-Jun-2006], [21-Jul-2006] - - Problems fixed: - - * [WTSX-38], [WSTX-56]: Filtered event reader was not filtering events - correctly. Now should work much better. - * [WSTX-54]: Added method XMLStreamWriter2.getEncoding, which allows for - accessing encoding of the underlying output stream/writer (if such - info available to the stream writer). - * [WSTX-55]: XMLStreamWriter.flush() is now once again side-effect - free (rule of minimal surprise) - * [WSTX-57]: (partial fix) getNamespaceURI(int) will now return "" for - 'no namespace', instead of null. Value will thus be the exact lexival - value from the declaration. - * [WSTX-58]: a problem with DOMWrappingReader throwing an NPE, when - accessing attribute properties of an element with only ns declarations. - * [WSTX-59]: Stream writer trying to quote \r and \t in prolog/epilog. - * [WSTX-60]: No pom file was generated for woodstox jar distributions; - added generation, and dependencies to stax api jar generated by ref. impl. - * [WSTX-61]: Using non-woodstox XMLStreamReader with the default - event allocator fails. - - Improvements: - - * More significant parsing speed improvements, related to white space and - linefeed handling. - * Significant optimizations on the output side: adding BufferedWriter - increases output speed very significantly (i.e. non-buffering basic - OutputStreamWriter was dead slow for almost all use cases). - Also, added simple buffer recycling, similar to reader side. - - New functionality: - - * [WSTX-25]: Added Stax2 interface ValidationProblemHandler, and associated - methods to XMLStreamReader2 and XMLStreamWriter2: this allows for - custom validation error handling, overriding default logic. - * [WSTX-52]: Added a set of basic Stax2Source and Stax2Result - implementations: these allow for more efficient and accurate source/result - identification, and possible later optimizations. - ------------------------------------------------------------------------- -End of History (as we know it) ------------------------------------------------------------------------- +5.0.0 (earlier) -(changes for versions prior to 3.0.0 are not included) +Attempted initial release -- unfortunately, as per #3 (see above), not a working jar. diff -Nru libwoodstox-java-4.1.3/release-notes/xml-compatibility.txt libwoodstox-java-5.1.0/release-notes/xml-compatibility.txt --- libwoodstox-java-4.1.3/release-notes/xml-compatibility.txt 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/release-notes/xml-compatibility.txt 1970-01-01 00:00:00.000000000 +0000 @@ -1,30 +0,0 @@ -Version: 3.1 - -Current version is very close to complete XML 1.0 compliance; and also -mostly XML 1.1 compliant. In addition to the core xml specification, -Woodstox implements following specifications: - -* Xml Namespaces (1.0 and 1.1) -* Xml:id - -Known issues regarding strict XML-conformance checking are: - -XML 1.0: - -* Surrogate pairing checks for identifiers (element and attribute names, - PI targets) is slightly incomplete, resulting in 4 failing XMLTest test - cases. -* Validity checks for characters 0xFFFE and 0xFFFF does not work for - UTF-16 encoding (need to implement custom reader). Results in 2 failing - XMLTest test cases. -* Namespace declaration pseudo-attributes are always dealt as being - type CDATA, even if DTD declares otherwise: this means that the white - space included will not be normalized (one failing XMLTest test cases) - -XML 1.0: - -[no known 1.0 specific additional problems] - -XML 1.1: - -[no known 1.1 specific additional problems] diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/api/CommonConfig.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/api/CommonConfig.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/api/CommonConfig.java 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/api/CommonConfig.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,245 +0,0 @@ -package com.ctc.wstx.api; - -import java.util.*; - -import org.codehaus.stax2.XMLStreamProperties; - -import com.ctc.wstx.util.DataUtil; - -/** - * Shared common base class for variour configuration container implementations - * for public factories Woodstox uses: implementations of - * {@link javax.xml.stream.XMLInputFactory}, - * {@link javax.xml.stream.XMLOutputFactory} and - * {@link org.codehaus.stax2.validation.XMLValidationSchemaFactory}. - * Implements basic settings for some shared settings, defined by the - * shared property interface {@link XMLStreamProperties}. - */ -abstract class CommonConfig - implements XMLStreamProperties -{ - /* - /////////////////////////////////////////////////////////////////////// - // Implementation info - /////////////////////////////////////////////////////////////////////// - */ - - protected final static String IMPL_NAME = "woodstox"; - - /* !!! TBI: get from props file or so? Or build as part of Ant - * build process? - */ - /** - * This is "major.minor" version used for purposes of determining - * the feature set. Patch level is not included, since those should - * not affect API or feature set. Using applications should be - * prepared to take additional levels, however, just not depend - * on those being available. - */ - protected final static String IMPL_VERSION = "4.1"; - - /* - /////////////////////////////////////////////////////////////////////// - // Internal constants - /////////////////////////////////////////////////////////////////////// - */ - - final static int PROP_IMPL_NAME = 1; - final static int PROP_IMPL_VERSION = 2; - - final static int PROP_SUPPORTS_XML11 = 3; - final static int PROP_SUPPORT_XMLID = 4; - - final static int PROP_RETURN_NULL_FOR_DEFAULT_NAMESPACE = 5; - - /** - * Map to use for converting from String property ids to enumeration - * (ints). Used for faster dispatching. - */ - final static HashMap sStdProperties = new HashMap(16); - static { - // Basic information about the implementation: - sStdProperties.put(XMLStreamProperties.XSP_IMPLEMENTATION_NAME, - DataUtil.Integer(PROP_IMPL_NAME)); - sStdProperties.put(XMLStreamProperties.XSP_IMPLEMENTATION_VERSION, - DataUtil.Integer(PROP_IMPL_VERSION)); - - // XML version support: - sStdProperties.put(XMLStreamProperties.XSP_SUPPORTS_XML11, - DataUtil.Integer(PROP_SUPPORTS_XML11)); - - // Xml:id support: - sStdProperties.put(XMLStreamProperties.XSP_SUPPORT_XMLID, - DataUtil.Integer(PROP_SUPPORT_XMLID)); - - sStdProperties.put(WstxInputProperties.P_RETURN_NULL_FOR_DEFAULT_NAMESPACE, - DataUtil.Integer(PROP_RETURN_NULL_FOR_DEFAULT_NAMESPACE)); - - /* 23-Apr-2008, tatus: Additional interoperability property, - * one that Sun implementation uses. Can map tor Stax2 - * property quite easily. - */ - sStdProperties.put("http://java.sun.com/xml/stream/properties/implementation-name", - DataUtil.Integer(PROP_IMPL_NAME)); - - } - - protected CommonConfig() { } - - /* - /////////////////////////////////////////////////////////////////////// - // Public API, generic StAX config methods - /////////////////////////////////////////////////////////////////////// - */ - - public Object getProperty(String propName) - { - /* Related to [WSTX-243]; would be nice to not to have to throw an - * exception; but Stax spec suggests that we do need to indicate - * unrecognized property by exception. - */ - int id = findPropertyId(propName); - if (id >= 0) { - return getProperty(id); - } - id = findStdPropertyId(propName); - if (id < 0) { - reportUnknownProperty(propName); - return null; - } - return getStdProperty(id); - } - - public boolean isPropertySupported(String propName) - { - return (findPropertyId(propName) >= 0) - || (findStdPropertyId(propName) >= 0); - } - - /** - * @return True, if the specified property was succesfully - * set to specified value; false if its value was not changed - */ - public boolean setProperty(String propName, Object value) - { - int id = findPropertyId(propName); - if (id >= 0) { - return setProperty(propName, id, value); - } - id = findStdPropertyId(propName); - if (id < 0) { - reportUnknownProperty(propName); - return false; - } - return setStdProperty(propName, id, value); - } - - protected void reportUnknownProperty(String propName) - { - // see [WSTX-243] for discussion on whether to throw... - throw new IllegalArgumentException("Unrecognized property '"+propName+"'"); - } - - /* - /////////////////////////////////////////////////////////////////////// - // Additional methods used by Woodstox core - /////////////////////////////////////////////////////////////////////// - */ - - public final Object safeGetProperty(String propName) - { - int id = findPropertyId(propName); - if (id >= 0) { - return getProperty(id); - } - id = findStdPropertyId(propName); - if (id < 0) { - return null; - } - return getStdProperty(id); - } - - /** - * Method used to figure out the official implementation name - * for input/output/validation factories. - */ - public static String getImplName() { return IMPL_NAME; } - - /** - * Method used to figure out the official implementation version - * for input/output/validation factories. - */ - public static String getImplVersion() { return IMPL_VERSION; } - - /* - /////////////////////////////////////////////////////////////////////// - // Interface sub-classes have to implement / can override - /////////////////////////////////////////////////////////////////////// - */ - - /** - * @return Internal enumerated int matching the String name - * of the property, if one found: -1 to indicate no match - * was found. - */ - protected abstract int findPropertyId(String propName); - - protected boolean doesSupportXml11() { - /* Woodstox does support xml 1.1 ... but sub-classes can - * override it if/as necessary (validator factories might not - * support it?) - */ - return true; - } - - protected boolean doesSupportXmlId() { - /* Woodstox does support Xml:id ... but sub-classes can - * override it if/as necessary. - */ - return true; - } - - protected boolean returnNullForDefaultNamespace() { - return Boolean.getBoolean(WstxInputProperties.P_RETURN_NULL_FOR_DEFAULT_NAMESPACE); - } - - protected abstract Object getProperty(int id); - - protected abstract boolean setProperty(String propName, int id, Object value); - - /* - /////////////////////////////////////////////////////////////////////// - // Internal methods - /////////////////////////////////////////////////////////////////////// - */ - - protected int findStdPropertyId(String propName) - { - Integer I = (Integer) sStdProperties.get(propName); - return (I == null) ? -1 : I.intValue(); - } - - protected boolean setStdProperty(String propName, int id, Object value) - { - // None of the current shared properties are settable... - return false; - } - - protected Object getStdProperty(int id) - { - switch (id) { - case PROP_IMPL_NAME: - return IMPL_NAME; - case PROP_IMPL_VERSION: - return IMPL_VERSION; - case PROP_SUPPORTS_XML11: - return doesSupportXml11() ? Boolean.TRUE : Boolean.FALSE; - case PROP_SUPPORT_XMLID: - return doesSupportXmlId() ? Boolean.TRUE : Boolean.FALSE; - case PROP_RETURN_NULL_FOR_DEFAULT_NAMESPACE: - return returnNullForDefaultNamespace() ? Boolean.TRUE : Boolean.FALSE; - default: // sanity check, should never happen - throw new IllegalStateException("Internal error: no handler for property with internal id "+id+"."); - } - } -} diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/api/EmptyElementHandler.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/api/EmptyElementHandler.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/api/EmptyElementHandler.java 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/api/EmptyElementHandler.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,81 +0,0 @@ -package com.ctc.wstx.api; - -import java.util.Set; -import java.util.TreeSet; - -/** - * Optional handler used to determine if a specific empty element (by name) should - * be allowed to use the self-closing syntax instead of having a separate end tag. - * - * @since 4.1 - */ -public interface EmptyElementHandler -{ - /** - * @param prefix The element's namespace prefix, null if not set - * @param localName The element's local name - * @param nsURI The elements's namespace URI, null if not set - * @param allowEmpty The allow empty setting specified by the caller. - * @return True if the empty element can be self-closing. False if a separate end tag should be written. - */ - public boolean allowEmptyElement(String prefix, String localName, String nsURI, boolean allowEmpty); - - /** - * Handler that uses a Set of Strings. If the local part of the element's QName is contained - * in the Set the element is allowed to be empty. - *

- * Users of this class are encouraged to use a {@link TreeSet} with the {@link String#CASE_INSENSITIVE_ORDER} - * comparator if case-insensitive comparison is needed (like when dealing with HTML tags). - */ - public static class SetEmptyElementHandler - implements EmptyElementHandler - { - final protected Set mEmptyElements; - - public SetEmptyElementHandler(Set emptyElements) - { - mEmptyElements = emptyElements; - } - - public boolean allowEmptyElement(String prefix, String localName, String nsURI, boolean allowEmpty) - { - return mEmptyElements.contains(localName); - } - } - - /** - * HTML specific empty element handler. - * Extends the {@link SetEmptyElementHandler} and configures - * the HTML elements that must be self-closing according to the W3C: - * http://www.w3.org/TR/html4/index/elements.html - *

- * Note that element name comparison is case-insensitive as required - * by HTML specification. - */ - public static class HtmlEmptyElementHandler - extends SetEmptyElementHandler - { - private final static HtmlEmptyElementHandler sInstance = new HtmlEmptyElementHandler(); - - public static HtmlEmptyElementHandler getInstance() { return sInstance; } - - protected HtmlEmptyElementHandler() - { - super(new TreeSet(String.CASE_INSENSITIVE_ORDER)); - mEmptyElements.add("area"); - mEmptyElements.add("base"); - mEmptyElements.add("basefont"); - mEmptyElements.add("br"); - mEmptyElements.add("col"); - mEmptyElements.add("frame"); - mEmptyElements.add("hr"); - mEmptyElements.add("input"); - mEmptyElements.add("img"); - mEmptyElements.add("isindex"); - mEmptyElements.add("link"); - mEmptyElements.add("meta"); - mEmptyElements.add("param"); - } - } -} - diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/api/InvalidCharHandler.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/api/InvalidCharHandler.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/api/InvalidCharHandler.java 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/api/InvalidCharHandler.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,91 +0,0 @@ -package com.ctc.wstx.api; - -import java.io.IOException; - -/** - * Simple converter interface designed to be used with stream writer property - * {@link WstxOutputProperties#P_OUTPUT_INVALID_CHAR_HANDLER}. - * The idea is that it should be easy to have a way to convert invalid - * characters such as Ascii control characters into something that - * is legal to include in XML content. This only allows for simple - * char-by-char replacements, instead of something more advanced such - * as escaping. If escaping is needed, check out - * {@link org.codehaus.stax2.XMLOutputFactory2#P_TEXT_ESCAPER} instead. - *

- * Note about exceptions: choice of only allowing throwing of - * {@link IOException}s is due to the way Woodstox stream writer - * backend works; XmlWriter can only throw IOExceptions. - */ -public interface InvalidCharHandler -{ - public char convertInvalidChar(int invalidChar) throws IOException; - - /** - * This handler implementation just throws an exception for - * all invalid characters encountered. It is the default handler - * used if nothing else has been specified. - */ - public static class FailingHandler - implements InvalidCharHandler - { - public final static int SURR1_FIRST = 0xD800; - public final static int SURR1_LAST = 0xDBFF; - public final static int SURR2_FIRST = 0xDC00; - public final static int SURR2_LAST = 0xDFFF; - - private final static FailingHandler sInstance = new FailingHandler(); - - protected FailingHandler() { } - - public static FailingHandler getInstance() { return sInstance; } - - public char convertInvalidChar(int c) throws IOException - { - /* 17-May-2006, TSa: Would really be useful if we could throw - * XMLStreamExceptions; esp. to indicate actual output location. - * However, this causes problem with methods that call us and - * can only throw IOExceptions (when invoked via Writer proxy). - * Need to figure out how to resolve this. - */ - if (c == 0) { - throw new IOException("Invalid null character in text to output"); - } - if (c < ' ' || (c >= 0x7F && c <= 0x9F)) { - String msg = "Invalid white space character (0x"+Integer.toHexString(c)+") in text to output (in xml 1.1, could output as a character entity)"; - throw new IOException(msg); - } - if (c > 0x10FFFF) { - throw new IOException("Illegal unicode character point (0x"+Integer.toHexString(c)+") to output; max is 0x10FFFF as per RFC 3629"); - } - /* Surrogate pair in non-quotable (not text or attribute value) - * content, and non-unicode encoding (ISO-8859-x, Ascii)? - */ - if (c >= SURR1_FIRST && c <= SURR2_LAST) { - throw new IOException("Illegal surrogate pair -- can only be output via character entities, which are not allowed in this content"); - } - throw new IOException("Invalid XML character (0x"+Integer.toHexString(c)+") in text to output"); - } - } - - /** - * Alternative to the default handler, this handler converts all invalid - * characters to the specified output character. That character will - * not be further verified or modified by the stream writer. - */ - public static class ReplacingHandler - implements InvalidCharHandler - { - final char mReplacementChar; - - public ReplacingHandler(char c) - { - mReplacementChar = c; - } - - public char convertInvalidChar(int c) throws IOException - { - return mReplacementChar; - } - } -} - diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/api/package.html libwoodstox-java-5.1.0/src/java/com/ctc/wstx/api/package.html --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/api/package.html 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/api/package.html 1970-01-01 00:00:00.000000000 +0000 @@ -1,7 +0,0 @@ - -Package that contains subset of Woodstox classes that are considered to be -its public API (in addition to regular Stax 1.0 -- javax.xml.stream.* -- and -Stax2 -- org.codehaus.stax2.*). This means that application code can rely -on these classes, and effort is made to keep them backwards compatible -between releases. - diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/api/ReaderConfig.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/api/ReaderConfig.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/api/ReaderConfig.java 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/api/ReaderConfig.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,1547 +0,0 @@ -package com.ctc.wstx.api; - -import java.lang.ref.SoftReference; -import java.net.URL; -import java.util.*; - -import javax.xml.stream.*; - -import org.codehaus.stax2.XMLInputFactory2; // for property consts -import org.codehaus.stax2.XMLStreamProperties; // for property consts -import org.codehaus.stax2.validation.DTDValidationSchema; - -import com.ctc.wstx.api.WstxInputProperties; -import com.ctc.wstx.cfg.InputConfigFlags; -import com.ctc.wstx.dtd.DTDEventListener; -import com.ctc.wstx.ent.IntEntity; -import com.ctc.wstx.ent.EntityDecl; -import com.ctc.wstx.io.BufferRecycler; -import com.ctc.wstx.util.ArgUtil; -import com.ctc.wstx.util.DataUtil; -import com.ctc.wstx.util.SymbolTable; - -/** - * Simple configuration container class; passed by reader factory to reader - * instance created. - *

- * In addition to its main task as a configuration container, this class - * also acts as a wrapper around simple buffer recycling functionality. - * The reason is that while conceptually this is a separate concern, - * there are enough commonalities with the life-cycle of this object to - * make this a very convenience place to add that functionality... - * (that is: conceptually this is not right, but from pragmatic viewpoint - * it just makes sense) - */ -public final class ReaderConfig - extends CommonConfig - implements InputConfigFlags -{ - /* - /////////////////////////////////////////////////////////////////////// - // Constants for reader properties: - /////////////////////////////////////////////////////////////////////// - */ - - // // First, standard StAX properties: - - // Simple flags: - final static int PROP_COALESCE_TEXT = 1; - final static int PROP_NAMESPACE_AWARE = 2; - final static int PROP_REPLACE_ENTITY_REFS = 3; - final static int PROP_SUPPORT_EXTERNAL_ENTITIES = 4; - final static int PROP_VALIDATE_AGAINST_DTD = 5; - final static int PROP_SUPPORT_DTD = 6; - - // Object type properties - public final static int PROP_EVENT_ALLOCATOR = 7; - final static int PROP_WARNING_REPORTER = 8; - final static int PROP_XML_RESOLVER = 9; - - // // Then StAX2 standard properties: - - // Simple flags: - final static int PROP_INTERN_NS_URIS = 20; - final static int PROP_INTERN_NAMES = 21; - final static int PROP_REPORT_CDATA = 22; - final static int PROP_REPORT_PROLOG_WS = 23; - final static int PROP_PRESERVE_LOCATION = 24; - final static int PROP_AUTO_CLOSE_INPUT = 25; - - // Enum / Object type properties: - final static int PROP_SUPPORT_XMLID = 26; // shared with WriterConfig - final static int PROP_DTD_OVERRIDE = 27; - - // // // Constants for additional Wstx properties: - - // Simple flags: - - /** - * Note: this entry was deprecated for 4.0 versions up until - * and including 4.0.7; was brought back for 4.0.8 (and will - * be retained for 4.1) - */ - final static int PROP_NORMALIZE_LFS = 40; - - /* This entry was deprecated for 3.2 and removed in 4.0 - * version. There are no plans to bring it back. - */ - //final static int PROP_NORMALIZE_ATTR_VALUES = 41; - - final static int PROP_CACHE_DTDS = 42; - final static int PROP_CACHE_DTDS_BY_PUBLIC_ID = 43; - final static int PROP_LAZY_PARSING = 44; - final static int PROP_SUPPORT_DTDPP = 45; - final static int PROP_TREAT_CHAR_REFS_AS_ENTS = 46; - - // Object type properties: - - final static int PROP_INPUT_BUFFER_LENGTH = 50; - //final static int PROP_TEXT_BUFFER_LENGTH = 51; - final static int PROP_MIN_TEXT_SEGMENT = 52; - final static int PROP_CUSTOM_INTERNAL_ENTITIES = 53; - final static int PROP_DTD_RESOLVER = 54; - final static int PROP_ENTITY_RESOLVER = 55; - final static int PROP_UNDECLARED_ENTITY_RESOLVER = 56; - final static int PROP_BASE_URL = 57; - final static int PROP_INPUT_PARSING_MODE = 58; - - /* - //////////////////////////////////////////////// - // Limits for numeric properties - //////////////////////////////////////////////// - */ - - /** - * Need to set a minimum size, since there are some limitations to - * smallest consequtive block that can be used. - */ - final static int MIN_INPUT_BUFFER_LENGTH = 8; // 16 bytes - - /** - * Let's allow caching of just a dozen DTDs... shouldn't really - * matter, how many DTDs does one really use? - */ - final static int DTD_CACHE_SIZE_J2SE = 12; - - final static int DTD_CACHE_SIZE_J2ME = 5; - - /* - /////////////////////////////////////////////////////////////////////// - // Default values for custom properties: - /////////////////////////////////////////////////////////////////////// - */ - - /** - * By default, let's require minimum of 64 chars to be delivered - * as shortest partial (piece of) text (CDATA, text) segment; - * same for both J2ME subset and full readers. Prevents tiniest - * runts from getting passed - */ - final static int DEFAULT_SHORTEST_TEXT_SEGMENT = 64; - - /** - * Default config flags are converted from individual settings, - * to conform to StAX 1.0 specifications. - */ - final static int DEFAULT_FLAGS_FULL = - 0 - // First, default settings StAX specs dictate: - - | CFG_NAMESPACE_AWARE - // Coalescing to be disabled - //| CFG_COALESCE_TEXT - | CFG_REPLACE_ENTITY_REFS - | CFG_SUPPORT_EXTERNAL_ENTITIES - | CFG_SUPPORT_DTD - - // and then custom setting defaults: - - // and namespace URI interning - | CFG_INTERN_NAMES - | CFG_INTERN_NS_URIS - - // we will also accurately report CDATA, by default - | CFG_REPORT_CDATA - - /* 20-Jan-2006, TSa: As per discussions on stax-builders list - * (and input from xml experts), 4.0 will revert to "do not - * report SPACE events outside root element by default" - * settings. Conceptually this is what xml specification - * implies should be done: there is no content outside of - * the element tree, including any ignorable content, just - * processing instructions and comments. - */ - //| CFG_REPORT_PROLOG_WS - - /* but enable DTD caching (if they are handled): - * (... maybe J2ME subset shouldn't do it?) - */ - | CFG_CACHE_DTDS - /* 29-Mar-2006, TSa: But note, no caching by public-id, due - * to problems with cases where public-id/system-id were - * inconsistently used, leading to problems. - */ - - /* by default, let's also allow lazy parsing, since it tends - * to improve performance - */ - | CFG_LAZY_PARSING - - /* and also make Event objects preserve location info... - * can be turned off for maximum performance - */ - | CFG_PRESERVE_LOCATION - - // As per Stax 1.0 specs, we can not enable this by default: - //| CFG_AUTO_CLOSE_INPUT); - - /* Also, let's enable dtd++ support (shouldn't hurt with non-dtd++ - * dtds) - */ - - | CFG_SUPPORT_DTDPP - - /* - * Set this as a default, as this is required in xml; - */ - | CFG_NORMALIZE_LFS - - /* Regarding Xml:id, let's enabled typing by default, but not - * uniqueness validity checks: latter will be taken care of - * by DTD validation if enabled, otherwise needs to be explicitly - * enabled - */ - | CFG_XMLID_TYPING - // | CFG_XMLID_UNIQ_CHECKS - ; - - /** - * For now defaults for J2ME flags can be identical to 'full' set; - * differences are in buffer sizes. - */ - final static int DEFAULT_FLAGS_J2ME = DEFAULT_FLAGS_FULL; - - // // // - - /** - * Map to use for converting from String property ids to ints - * described above; useful to allow use of switch later on. - */ - final static HashMap sProperties = new HashMap(64); // we have about 40 entries - static { - // Standard ones; support for features - sProperties.put(XMLInputFactory.IS_COALESCING, - DataUtil.Integer(PROP_COALESCE_TEXT)); - sProperties.put(XMLInputFactory.IS_NAMESPACE_AWARE, - DataUtil.Integer(PROP_NAMESPACE_AWARE)); - sProperties.put(XMLInputFactory.IS_REPLACING_ENTITY_REFERENCES, - DataUtil.Integer(PROP_REPLACE_ENTITY_REFS)); - sProperties.put(XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES, - DataUtil.Integer(PROP_SUPPORT_EXTERNAL_ENTITIES)); - sProperties.put(XMLInputFactory.IS_VALIDATING, - DataUtil.Integer(PROP_VALIDATE_AGAINST_DTD)); - sProperties.put(XMLInputFactory.SUPPORT_DTD, - DataUtil.Integer(PROP_SUPPORT_DTD)); - - // Standard ones; pluggable components - sProperties.put(XMLInputFactory.ALLOCATOR, - DataUtil.Integer(PROP_EVENT_ALLOCATOR)); - sProperties.put(XMLInputFactory.REPORTER, - DataUtil.Integer(PROP_WARNING_REPORTER)); - sProperties.put(XMLInputFactory.RESOLVER, - DataUtil.Integer(PROP_XML_RESOLVER)); - - // StAX2-introduced flags: - sProperties.put(XMLInputFactory2.P_INTERN_NAMES, - DataUtil.Integer(PROP_INTERN_NAMES)); - sProperties.put(XMLInputFactory2.P_INTERN_NS_URIS, - DataUtil.Integer(PROP_INTERN_NS_URIS)); - sProperties.put(XMLInputFactory2.P_REPORT_CDATA, - DataUtil.Integer(PROP_REPORT_CDATA)); - sProperties.put(XMLInputFactory2.P_REPORT_PROLOG_WHITESPACE, - DataUtil.Integer(PROP_REPORT_PROLOG_WS)); - sProperties.put(XMLInputFactory2.P_PRESERVE_LOCATION, - DataUtil.Integer(PROP_PRESERVE_LOCATION)); - sProperties.put(XMLInputFactory2.P_AUTO_CLOSE_INPUT, - DataUtil.Integer(PROP_AUTO_CLOSE_INPUT)); - sProperties.put(XMLInputFactory2.XSP_SUPPORT_XMLID, - DataUtil.Integer(PROP_SUPPORT_XMLID)); - sProperties.put(XMLInputFactory2.P_DTD_OVERRIDE, - DataUtil.Integer(PROP_DTD_OVERRIDE)); - - // Non-standard ones, flags: - - sProperties.put(WstxInputProperties.P_CACHE_DTDS, - DataUtil.Integer(PROP_CACHE_DTDS)); - sProperties.put(WstxInputProperties.P_CACHE_DTDS_BY_PUBLIC_ID, - DataUtil.Integer(PROP_CACHE_DTDS_BY_PUBLIC_ID)); - sProperties.put(XMLInputFactory2.P_LAZY_PARSING, - DataUtil.Integer(PROP_LAZY_PARSING)); - sProperties.put(WstxInputProperties.P_SUPPORT_DTDPP, - DataUtil.Integer(PROP_SUPPORT_DTDPP)); - sProperties.put(WstxInputProperties.P_TREAT_CHAR_REFS_AS_ENTS, - DataUtil.Integer(PROP_TREAT_CHAR_REFS_AS_ENTS)); - sProperties.put(WstxInputProperties.P_NORMALIZE_LFS, - DataUtil.Integer(PROP_NORMALIZE_LFS)); - - - // Non-standard ones, non-flags: - - sProperties.put(WstxInputProperties.P_INPUT_BUFFER_LENGTH, - DataUtil.Integer(PROP_INPUT_BUFFER_LENGTH)); - sProperties.put(WstxInputProperties.P_MIN_TEXT_SEGMENT, - DataUtil.Integer(PROP_MIN_TEXT_SEGMENT)); - sProperties.put(WstxInputProperties.P_CUSTOM_INTERNAL_ENTITIES, - DataUtil.Integer(PROP_CUSTOM_INTERNAL_ENTITIES)); - sProperties.put(WstxInputProperties.P_DTD_RESOLVER, - DataUtil.Integer(PROP_DTD_RESOLVER)); - sProperties.put(WstxInputProperties.P_ENTITY_RESOLVER, - DataUtil.Integer(PROP_ENTITY_RESOLVER)); - sProperties.put(WstxInputProperties.P_UNDECLARED_ENTITY_RESOLVER, - DataUtil.Integer(PROP_UNDECLARED_ENTITY_RESOLVER)); - sProperties.put(WstxInputProperties.P_BASE_URL, - DataUtil.Integer(PROP_BASE_URL)); - sProperties.put(WstxInputProperties.P_INPUT_PARSING_MODE, - DataUtil.Integer(PROP_INPUT_PARSING_MODE)); - } - - /* - /////////////////////////////////////////////////////////////////////// - // Current config state: - /////////////////////////////////////////////////////////////////////// - */ - - final boolean mIsJ2MESubset; - - final SymbolTable mSymbols; - - /** - * Bitset that contains state of on/off properties; initialized - * to defaults, but can be set/cleared. - */ - int mConfigFlags; - - /** - * Bitset that indicates explicit changes to {@link #mConfigFlags} - * through calls; empty bit means that the corresponding property - * has its default value, set bit that an explicit call has been - * made. - */ - int mConfigFlagMods; - - /** - * 13-Nov-2008, tatus: Need to be able to keep track of whether - * name-interning has been explicitly enabled/disable or not - * (not if it's whatever defaults we have) - */ - final static int PROP_INTERN_NAMES_EXPLICIT = 26; - final static int PROP_INTERN_NS_URIS_EXPLICIT = 27; - - - int mInputBufferLen; - int mMinTextSegmentLen; - - /** - * Base URL to use as the resolution context for relative entity - * references - */ - URL mBaseURL = null; - - /** - * Parsing mode can be changed from the default xml compliant - * behavior to one of alternate modes (fragment processing, - * multiple document processing). - */ - WstxInputProperties.ParsingMode mParsingMode = - WstxInputProperties.PARSING_MODE_DOCUMENT; - - /** - * This boolean flag is set if the input document requires - * xml 1.1 (or above) compliant processing: default is xml 1.0 - * compliant. Note that unlike most other properties, this - * does not come from configuration settings, but from processed - * document itself. - */ - boolean mXml11 = false; - - /* - /////////////////////////////////////////////////////////////////////// - // Common configuration objects - /////////////////////////////////////////////////////////////////////// - */ - - XMLReporter mReporter; - - XMLResolver mDtdResolver = null; - XMLResolver mEntityResolver = null; - - /* - /////////////////////////////////////////////////////////////////////// - // More special(ized) configuration objects - /////////////////////////////////////////////////////////////////////// - */ - - //Map mCustomEntities; - //XMLResolver mUndeclaredEntityResolver; - //DTDEventListener mDTDEventListener; - - Object[] mSpecialProperties = null; - - private final static int SPEC_PROC_COUNT = 4; - - private final static int SP_IX_CUSTOM_ENTITIES = 0; - private final static int SP_IX_UNDECL_ENT_RESOLVER = 1; - private final static int SP_IX_DTD_EVENT_LISTENER = 2; - private final static int SP_IX_DTD_OVERRIDE = 3; - - /* - /////////////////////////////////////////////////////////////////////// - // Buffer recycling: - /////////////////////////////////////////////////////////////////////// - */ - - /** - * This ThreadLocal contains a {@link SoftRerefence} - * to a {@link BufferRecycler} used to provide a low-cost - * buffer recycling between Reader instances. - */ - final static ThreadLocal mRecyclerRef = new ThreadLocal(); - - /** - * This is the actually container of the recyclable buffers. It - * is obtained via ThreadLocal/SoftReference combination, if one - * exists, when Config instance is created. If one does not - * exist, it will created first time a buffer is returned. - */ - BufferRecycler mCurrRecycler = null; - - /* - /////////////////////////////////////////////////////////////////////// - // Life-cycle - /////////////////////////////////////////////////////////////////////// - */ - - private ReaderConfig(boolean j2meSubset, SymbolTable symbols, - int configFlags, int configFlagMods, - int inputBufLen, - int minTextSegmentLen) - { - mIsJ2MESubset = j2meSubset; - mSymbols = symbols; - - mConfigFlags = configFlags; - mConfigFlagMods = configFlagMods; - - mInputBufferLen = inputBufLen; - mMinTextSegmentLen = minTextSegmentLen; - - /* Ok, let's then see if we can find a buffer recycler. Since they - * are lazily constructed, and since GC may just flush them out - * on its whims, it's possible we might not find one. That's ok; - * we can reconstruct one if and when we are to return one or more - * buffers. - */ - SoftReference ref = (SoftReference) mRecyclerRef.get(); - if (ref != null) { - mCurrRecycler = (BufferRecycler) ref.get(); - } - } - - public static ReaderConfig createJ2MEDefaults() - { - /* For J2ME we'll use slightly smaller buffer sizes by - * default, on assumption lower memory usage is desireable: - */ - ReaderConfig rc = new ReaderConfig - (true, null, DEFAULT_FLAGS_J2ME, 0, - // 4k input buffer (2000 chars): - 2000, - DEFAULT_SHORTEST_TEXT_SEGMENT); - return rc; - } - - public static ReaderConfig createFullDefaults() - { - /* For full version, can use bit larger buffers to achieve better - * overall performance. - */ - ReaderConfig rc = new ReaderConfig - (false, null, DEFAULT_FLAGS_FULL, 0, - // 8k input buffer (4000 chars): - 4000, - DEFAULT_SHORTEST_TEXT_SEGMENT); - return rc; - } - - public ReaderConfig createNonShared(SymbolTable sym) - { - // should we throw an exception? - //if (sym == null) { } - ReaderConfig rc = new ReaderConfig(mIsJ2MESubset, sym, - mConfigFlags, mConfigFlagMods, - mInputBufferLen, - mMinTextSegmentLen); - rc.mReporter = mReporter; - rc.mDtdResolver = mDtdResolver; - rc.mEntityResolver = mEntityResolver; - rc.mBaseURL = mBaseURL; - rc.mParsingMode = mParsingMode; - if (mSpecialProperties != null) { - int len = mSpecialProperties.length; - Object[] specProps = new Object[len]; - System.arraycopy(mSpecialProperties, 0, specProps, 0, len); - rc.mSpecialProperties = specProps; - } - - return rc; - } - - /** - * Unlike name suggests there is also some limited state information - * associated with the config object. If these objects are reused, - * that state needs to be reset between reuses, to avoid carrying - * over incorrect state. - */ - public void resetState() - { - // Current, only xml 1.0 vs 1.1 state is stored here: - mXml11 = false; - } - - /* - /////////////////////////////////////////////////////////////////////// - // Implementation of abstract methods - /////////////////////////////////////////////////////////////////////// - */ - - protected int findPropertyId(String propName) - { - Integer I = (Integer) sProperties.get(propName); - return (I == null) ? -1 : I.intValue(); - } - - /* - /////////////////////////////////////////////////////////////////////// - // Public API, accessors - /////////////////////////////////////////////////////////////////////// - */ - - // // // Accessors for immutable configuration: - - public SymbolTable getSymbols() { return mSymbols; } - - /** - * In future this property could/should be made configurable? - */ - - public int getDtdCacheSize() { - return mIsJ2MESubset ? DTD_CACHE_SIZE_J2ME : DTD_CACHE_SIZE_J2SE; - } - - // // // "Raw" accessors for on/off properties: - - public int getConfigFlags() { return mConfigFlags; } - - // // // Standard StAX on/off property accessors - - public boolean willCoalesceText() { - return _hasConfigFlag(CFG_COALESCE_TEXT); - } - - public boolean willSupportNamespaces() { - return _hasConfigFlag(CFG_NAMESPACE_AWARE); - } - - public boolean willReplaceEntityRefs() { - return _hasConfigFlag(CFG_REPLACE_ENTITY_REFS); - } - - public boolean willSupportExternalEntities() { - return _hasConfigFlag(CFG_SUPPORT_EXTERNAL_ENTITIES); - } - - public boolean willSupportDTDs() { - return _hasConfigFlag(CFG_SUPPORT_DTD); - } - - public boolean willValidateWithDTD() { - return _hasConfigFlag(CFG_VALIDATE_AGAINST_DTD); - } - - // // // Stax2 on/off property accessors - - public boolean willReportCData() { - return _hasConfigFlag(CFG_REPORT_CDATA); - } - - public boolean willParseLazily() { - return _hasConfigFlag(CFG_LAZY_PARSING); - } - - public boolean willInternNames() { - return _hasConfigFlag(CFG_INTERN_NAMES); - } - - public boolean willInternNsURIs() { - return _hasConfigFlag(CFG_INTERN_NS_URIS); - } - - public boolean willPreserveLocation() { - return _hasConfigFlag(CFG_PRESERVE_LOCATION); - } - - public boolean willAutoCloseInput() { - return _hasConfigFlag(CFG_AUTO_CLOSE_INPUT); - } - - // // // Woodstox on/off property accessors - - public boolean willReportPrologWhitespace() { - return _hasConfigFlag(CFG_REPORT_PROLOG_WS); - } - - public boolean willCacheDTDs() { - return _hasConfigFlag(CFG_CACHE_DTDS); - } - - public boolean willCacheDTDsByPublicId() { - return _hasConfigFlag(CFG_CACHE_DTDS_BY_PUBLIC_ID); - } - - public boolean willDoXmlIdTyping() { - return _hasConfigFlag(CFG_XMLID_TYPING); - } - - public boolean willDoXmlIdUniqChecks() { - return _hasConfigFlag(CFG_XMLID_UNIQ_CHECKS); - } - - public boolean willSupportDTDPP() { - return _hasConfigFlag(CFG_SUPPORT_DTDPP); - } - - public boolean willNormalizeLFs() { - return _hasConfigFlag(CFG_NORMALIZE_LFS); - } - - public boolean willTreatCharRefsAsEnts() { - return _hasConfigFlag(CFG_TREAT_CHAR_REFS_AS_ENTS); - } - - public int getInputBufferLength() { return mInputBufferLen; } - - public int getShortestReportedTextSegment() { return mMinTextSegmentLen; } - - public Map getCustomInternalEntities() - { - Map custEnt = (Map) _getSpecialProperty(SP_IX_CUSTOM_ENTITIES); - if (custEnt == null) { - return Collections.EMPTY_MAP; - } - // Better be defensive and just return a copy... - int len = custEnt.size(); - HashMap m = new HashMap(len + (len >> 2), 0.81f); - Iterator it = custEnt.entrySet().iterator(); - while (it.hasNext()) { - Map.Entry me = (Map.Entry) it.next(); - /* Cast is there just as a safe-guard (assertion), and to - * document the type... - */ - m.put(me.getKey(), (EntityDecl) me.getValue()); - } - return m; - } - - public EntityDecl findCustomInternalEntity(String id) - { - Map custEnt = (Map) _getSpecialProperty(SP_IX_CUSTOM_ENTITIES); - if (custEnt == null) { - return null; - } - return (EntityDecl) custEnt.get(id); - } - - public XMLReporter getXMLReporter() { return mReporter; } - - public XMLResolver getXMLResolver() { return mEntityResolver; } - - public XMLResolver getDtdResolver() { return mDtdResolver; } - public XMLResolver getEntityResolver() { return mEntityResolver; } - public XMLResolver getUndeclaredEntityResolver() { - return (XMLResolver) _getSpecialProperty(SP_IX_UNDECL_ENT_RESOLVER); - } - - public URL getBaseURL() { return mBaseURL; } - - public WstxInputProperties.ParsingMode getInputParsingMode() { - return mParsingMode; - } - - public boolean inputParsingModeDocuments() { - return mParsingMode == WstxInputProperties.PARSING_MODE_DOCUMENTS; - } - - public boolean inputParsingModeFragment() { - return mParsingMode == WstxInputProperties.PARSING_MODE_FRAGMENT; - } - - /** - * @return True if the input well-formedness and validation checks - * should be done according to xml 1.1 specification; false if - * xml 1.0 specification. - */ - public boolean isXml11() { - return mXml11; - } - - public DTDEventListener getDTDEventListener() { - return (DTDEventListener) _getSpecialProperty(SP_IX_DTD_EVENT_LISTENER); - } - - public DTDValidationSchema getDTDOverride() { - return (DTDValidationSchema) _getSpecialProperty(SP_IX_DTD_OVERRIDE); - } - - /** - * Special accessor to use to verify whether name interning has - * explicitly been enabled; true if call was been made to set - * it to true; false otherwise (default, or set to false) - */ - public boolean hasInternNamesBeenEnabled() { - return _hasExplicitConfigFlag(CFG_INTERN_NAMES); - } - - public boolean hasInternNsURIsBeenEnabled() { - return _hasExplicitConfigFlag(CFG_INTERN_NS_URIS); - } - - /* - /////////////////////////////////////////////////////////////////////// - // Simple mutators - /////////////////////////////////////////////////////////////////////// - */ - - public void setConfigFlag(int flag) { - mConfigFlags |= flag; - mConfigFlagMods |= flag; - } - - public void clearConfigFlag(int flag) { - mConfigFlags &= ~flag; - mConfigFlagMods |= flag; - } - - // // // Mutators for standard StAX properties - - public void doCoalesceText(boolean state) { - setConfigFlag(CFG_COALESCE_TEXT, state); - } - - public void doSupportNamespaces(boolean state) { - setConfigFlag(CFG_NAMESPACE_AWARE, state); - } - - public void doReplaceEntityRefs(boolean state) { - setConfigFlag(CFG_REPLACE_ENTITY_REFS, state); - } - - public void doSupportExternalEntities(boolean state) { - setConfigFlag(CFG_SUPPORT_EXTERNAL_ENTITIES, state); - } - - public void doSupportDTDs(boolean state) { - setConfigFlag(CFG_SUPPORT_DTD, state); - } - - public void doValidateWithDTD(boolean state) { - setConfigFlag(CFG_VALIDATE_AGAINST_DTD, state); - } - - // // // Mutators for Woodstox-specific properties - - public void doInternNames(boolean state) { - setConfigFlag(CFG_INTERN_NAMES, state); - } - - public void doInternNsURIs(boolean state) { - setConfigFlag(CFG_INTERN_NS_URIS, state); - } - - public void doReportPrologWhitespace(boolean state) { - setConfigFlag(CFG_REPORT_PROLOG_WS, state); - } - - public void doReportCData(boolean state) { - setConfigFlag(CFG_REPORT_CDATA, state); - } - - public void doCacheDTDs(boolean state) { - setConfigFlag(CFG_CACHE_DTDS, state); - } - - public void doCacheDTDsByPublicId(boolean state) { - setConfigFlag(CFG_CACHE_DTDS_BY_PUBLIC_ID, state); - } - - public void doParseLazily(boolean state) { - setConfigFlag(CFG_LAZY_PARSING, state); - } - - public void doXmlIdTyping(boolean state) { - setConfigFlag(CFG_XMLID_TYPING, state); - } - - public void doXmlIdUniqChecks(boolean state) { - setConfigFlag(CFG_XMLID_UNIQ_CHECKS, state); - } - - public void doPreserveLocation(boolean state) { - setConfigFlag(CFG_PRESERVE_LOCATION, state); - } - - public void doAutoCloseInput(boolean state) { - setConfigFlag(CFG_AUTO_CLOSE_INPUT, state); - } - - public void doSupportDTDPP(boolean state) { - setConfigFlag(CFG_SUPPORT_DTDPP, state); - } - - public void doTreatCharRefsAsEnts(final boolean state) { - setConfigFlag(CFG_TREAT_CHAR_REFS_AS_ENTS, state); - } - - public void doNormalizeLFs(final boolean state) { - setConfigFlag(CFG_NORMALIZE_LFS, state); - } - - public void setInputBufferLength(int value) - { - /* Let's enforce minimum here; necessary to allow longest - * consequtive text span to be available (xml decl, etc) - */ - if (value < MIN_INPUT_BUFFER_LENGTH) { - value = MIN_INPUT_BUFFER_LENGTH; - } - mInputBufferLen = value; - } - - public void setShortestReportedTextSegment(int value) { - mMinTextSegmentLen = value; - } - - public void setCustomInternalEntities(Map m) - { - Map entMap; - if (m == null || m.size() < 1) { - entMap = Collections.EMPTY_MAP; - } else { - int len = m.size(); - entMap = new HashMap(len + (len >> 1), 0.75f); - Iterator it = m.entrySet().iterator(); - while (it.hasNext()) { - Map.Entry me = (Map.Entry) it.next(); - Object val = me.getValue(); - char[] ch; - if (val == null) { - ch = DataUtil.getEmptyCharArray(); - } else if (val instanceof char[]) { - ch = (char[]) val; - } else { - // Probably String, but let's just ensure that - String str = val.toString(); - ch = str.toCharArray(); - } - String name = (String) me.getKey(); - entMap.put(name, IntEntity.create(name, ch)); - } - } - _setSpecialProperty(SP_IX_CUSTOM_ENTITIES, entMap); - } - - public void setXMLReporter(XMLReporter r) { - mReporter = r; - } - - /** - * Note: for better granularity, you should call {@link #setEntityResolver} - * and {@link #setDtdResolver} instead. - */ - public void setXMLResolver(XMLResolver r) { - mEntityResolver = r; - mDtdResolver = r; - } - - public void setDtdResolver(XMLResolver r) { - mDtdResolver = r; - } - - public void setEntityResolver(XMLResolver r) { - mEntityResolver = r; - } - - public void setUndeclaredEntityResolver(XMLResolver r) { - _setSpecialProperty(SP_IX_UNDECL_ENT_RESOLVER, r); - } - - public void setBaseURL(URL baseURL) { mBaseURL = baseURL; } - - public void setInputParsingMode(WstxInputProperties.ParsingMode mode) { - mParsingMode = mode; - } - - /** - * Method called to enable or disable 1.1 compliant processing; if - * disabled, defaults to xml 1.0 compliant processing. - */ - public void enableXml11(boolean state) { - mXml11 = state; - } - - public void setDTDEventListener(DTDEventListener l) { - _setSpecialProperty(SP_IX_DTD_EVENT_LISTENER, l); - } - - public void setDTDOverride(DTDValidationSchema schema) { - _setSpecialProperty(SP_IX_DTD_OVERRIDE, schema); - } - - /* - /////////////////////////////////////////////////////////////////////// - // Profile mutators: - /////////////////////////////////////////////////////////////////////// - */ - - /** - * Method to call to make Reader created conform as closely to XML - * standard as possible, doing all checks and transformations mandated - * (linefeed conversions, attr value normalizations). - * See {@link XMLInputFactory2#configureForXmlConformance} for - * required settings for standard StAX/StAX properties. - *

- * In addition to the standard settings, following Woodstox-specific - * settings are also done: - *

    - * None. - *
- *

- * Notes: Does NOT change 'performance' settings (buffer sizes, - * DTD caching, coalescing, interning, accurate location info). - */ - public void configureForXmlConformance() - { - // // StAX 1.0 settings - doSupportNamespaces(true); - doSupportDTDs(true); - doSupportExternalEntities(true); - doReplaceEntityRefs(true); - - // // Stax2 additional settings - - // Better enable full xml:id checks: - doXmlIdTyping(true); - doXmlIdUniqChecks(true); - - // Woodstox-specific ones: - } - - /** - * Method to call to make Reader created be as "convenient" to use - * as possible; ie try to avoid having to deal with some of things - * like segmented text chunks. This may incur some slight performance - * penalties, but should not affect XML conformance. - * See {@link XMLInputFactory2#configureForConvenience} for - * required settings for standard StAX/StAX properties. - *

- * In addition to the standard settings, following Woodstox-specific - * settings are also done: - *

    - *
  • Disable XMLStreamFactory2.P_LAZY_PARSING (to allow for synchronous - * error notification by forcing full XML events to be completely - * parsed when reader's next() is called) - *
  • - *
- */ - public void configureForConvenience() - { - // StAX (1.0) settings: - doCoalesceText(true); - doReplaceEntityRefs(true); - - // StAX2: - doReportCData(false); - doReportPrologWhitespace(false); - /* Also, knowing exact locations is nice esp. for error - * reporting purposes - */ - doPreserveLocation(true); - - // Woodstox-specific: - - /* Also, we can force errors to be reported in timely manner: - * (once again, at potential expense of performance) - */ - doParseLazily(false); - } - - /** - * Method to call to make the Reader created be as fast as possible reading - * documents, especially for long-running processes where caching is - * likely to help. - * - * See {@link XMLInputFactory2#configureForSpeed} for - * required settings for standard StAX/StAX properties. - *

- * In addition to the standard settings, following Woodstox-specific - * settings are also done: - *

    - *
  • Enable P_CACHE_DTDS. - *
  • - *
  • Enable XMLStremaFactory2.P_LAZY_PARSING (can improve performance - * especially when skipping text segments) - *
  • - *
  • Disable Xml:id uniqueness checks (and leave typing as is) - *
  • - *
  • Set lowish value for P_MIN_TEXT_SEGMENT, to allow - * reader to optimize segment length it uses (and possibly avoids - * one copy operation in the process) - *
  • - *
  • Increase P_INPUT_BUFFER_LENGTH a bit from default, - * to allow for longer consequtive read operations; also reduces cases - * where partial text segments are on input buffer boundaries. - *
  • - *
- */ - public void configureForSpeed() - { - // StAX (1.0): - doCoalesceText(false); - - // StAX2: - doPreserveLocation(false); - doReportPrologWhitespace(false); - //doInternNames(true); // this is a NOP - doInternNsURIs(true); - doXmlIdUniqChecks(false); - - // Woodstox-specific: - doCacheDTDs(true); - doParseLazily(true); - - /* If we let Reader decide sizes of text segments, it should be - * able to optimize it better, thus low min value. This value - * is only used in cases where text is at buffer boundary, or - * where entity prevents using consequtive chars from input buffer: - */ - setShortestReportedTextSegment(16); - setInputBufferLength(8000); // 16k input buffer - } - - /** - * Method to call to minimize the memory usage of the stream/event reader; - * both regarding Objects created, and the temporary memory usage during - * parsing. - * This generally incurs some performance penalties, due to using - * smaller input buffers. - *

- * See {@link XMLInputFactory2#configureForLowMemUsage} for - * required settings for standard StAX/StAX properties. - *

- * In addition to the standard settings, following Woodstox-specific - * settings are also done: - *

    - *
  • Disable P_CACHE_DTDS - *
  • - *
  • Enable P_PARSE_LAZILY - *
  • - *
  • Resets P_MIN_TEXT_SEGMENT to the (somewhat low) - * default value. - *
  • - *
  • Reduces P_INPUT_BUFFER_LENGTH a bit from the default - *
  • - *
- */ - public void configureForLowMemUsage() - { - // StAX (1.0) - doCoalesceText(false); - - // StAX2: - - doPreserveLocation(false); // can reduce temporary mem usage - - // Woodstox-specific: - doCacheDTDs(false); - doParseLazily(true); // can reduce temporary mem usage - doXmlIdUniqChecks(false); // enabling would increase mem usage - setShortestReportedTextSegment(ReaderConfig.DEFAULT_SHORTEST_TEXT_SEGMENT); - setInputBufferLength(512); // 1k input buffer - // Text buffer need not be huge, as we do not coalesce - } - - /** - * Method to call to make Reader try to preserve as much of input - * formatting as possible, so that round-tripping would be as lossless - * as possible. - *

- * See {@link XMLInputFactory2#configureForLowMemUsage} for - * required settings for standard StAX/StAX properties. - *

- * In addition to the standard settings, following Woodstox-specific - * settings are also done: - *

    - *
  • Increases P_MIN_TEXT_SEGMENT to the maximum value so - * that all original text segment chunks are reported without - * segmentation (but without coalescing with adjacent CDATA segments) - *
  • - *
  • Sets P_TREAT_CHAR_REFS_AS_ENTS to true, so the all the - * original character references are reported with their position, - * original text, and the replacement text. - *
  • - *
- */ - public void configureForRoundTripping() - { - // StAX (1.0) - doCoalesceText(false); - doReplaceEntityRefs(false); - - // StAX2: - doReportCData(true); - doReportPrologWhitespace(true); - - // Woodstox specific settings - doTreatCharRefsAsEnts(true); - doNormalizeLFs(false); - - // effectively prevents from reporting partial segments: - setShortestReportedTextSegment(Integer.MAX_VALUE); - } - - /* - /////////////////////////////////////////////////////////////////////// - // Buffer recycling: - /////////////////////////////////////////////////////////////////////// - */ - - public char[] allocSmallCBuffer(int minSize) - { -//System.err.println("DEBUG: cfg, allocCSmall: "+mCurrRecycler); - if (mCurrRecycler != null) { - char[] result = mCurrRecycler.getSmallCBuffer(minSize); - if (result != null) { - return result; - } - } - // Nope; no recycler, or it has no suitable buffers, let's create: - return new char[minSize]; - } - - public void freeSmallCBuffer(char[] buffer) - { -//System.err.println("DEBUG: cfg, freeCSmall: "+buffer); - // Need to create (and assign) the buffer? - if (mCurrRecycler == null) { - mCurrRecycler = createRecycler(); - } - mCurrRecycler.returnSmallCBuffer(buffer); - } - - public char[] allocMediumCBuffer(int minSize) - { -//System.err.println("DEBUG: cfg, allocCMed: "+mCurrRecycler); - if (mCurrRecycler != null) { - char[] result = mCurrRecycler.getMediumCBuffer(minSize); - if (result != null) { - return result; - } - } - return new char[minSize]; - } - - public void freeMediumCBuffer(char[] buffer) - { -//System.err.println("DEBUG: cfg, freeCMed: "+buffer); - if (mCurrRecycler == null) { - mCurrRecycler = createRecycler(); - } - mCurrRecycler.returnMediumCBuffer(buffer); - } - - public char[] allocFullCBuffer(int minSize) - { -//System.err.println("DEBUG: cfg, allocCFull: "+mCurrRecycler); - if (mCurrRecycler != null) { - char[] result = mCurrRecycler.getFullCBuffer(minSize); - if (result != null) { - return result; - } - } - return new char[minSize]; - } - - public void freeFullCBuffer(char[] buffer) - { -//System.err.println("DEBUG: cfg, freeCFull: "+buffer); - // Need to create (and assign) the buffer? - if (mCurrRecycler == null) { - mCurrRecycler = createRecycler(); - } - mCurrRecycler.returnFullCBuffer(buffer); - } - - public byte[] allocFullBBuffer(int minSize) - { -//System.err.println("DEBUG: cfg, allocBFull: "+mCurrRecycler); - if (mCurrRecycler != null) { - byte[] result = mCurrRecycler.getFullBBuffer(minSize); - if (result != null) { - return result; - } - } - return new byte[minSize]; - } - - public void freeFullBBuffer(byte[] buffer) - { -//System.err.println("DEBUG: cfg, freeBFull: "+buffer); - // Need to create (and assign) the buffer? - if (mCurrRecycler == null) { - mCurrRecycler = createRecycler(); - } - mCurrRecycler.returnFullBBuffer(buffer); - } - - static int Counter = 0; - - private BufferRecycler createRecycler() - { - BufferRecycler recycler = new BufferRecycler(); - // No way to reuse/reset SoftReference, have to create new always: -//System.err.println("DEBUG: RefCount: "+(++Counter)); - mRecyclerRef.set(new SoftReference(recycler)); - return recycler; - } - - /* - /////////////////////////////////////////////////////////////////////// - // Internal methods: - /////////////////////////////////////////////////////////////////////// - */ - - private void setConfigFlag(int flag, boolean state) - { - if (state) { - mConfigFlags |= flag; - } else { - mConfigFlags &= ~flag; - } - mConfigFlagMods |= flag; - } - - public Object getProperty(int id) - { - switch (id) { - // First, standard Stax 1.0 properties: - - case PROP_COALESCE_TEXT: - return willCoalesceText() ? Boolean.TRUE : Boolean.FALSE; - case PROP_NAMESPACE_AWARE: - return willSupportNamespaces() ? Boolean.TRUE : Boolean.FALSE; - case PROP_REPLACE_ENTITY_REFS: - return willReplaceEntityRefs() ? Boolean.TRUE : Boolean.FALSE; - case PROP_SUPPORT_EXTERNAL_ENTITIES: - return willSupportExternalEntities() ? Boolean.TRUE : Boolean.FALSE; - - case PROP_VALIDATE_AGAINST_DTD: - return willValidateWithDTD() ? Boolean.TRUE : Boolean.FALSE; - case PROP_SUPPORT_DTD: - return willSupportDTDs() ? Boolean.TRUE : Boolean.FALSE; - case PROP_WARNING_REPORTER: - return getXMLReporter(); - case PROP_XML_RESOLVER: - return getXMLResolver(); - case PROP_EVENT_ALLOCATOR: - /* 25-Mar-2006, TSa: Not really supported here, so let's - * return null - */ - return null; - - // Then Stax2 properties: - - case PROP_REPORT_PROLOG_WS: - return willReportPrologWhitespace() ? Boolean.TRUE : Boolean.FALSE; - case PROP_REPORT_CDATA: - return willReportCData() ? Boolean.TRUE : Boolean.FALSE; - - case PROP_INTERN_NAMES: - return willInternNames() ? Boolean.TRUE : Boolean.FALSE; - case PROP_INTERN_NS_URIS: - return willInternNsURIs() ? Boolean.TRUE : Boolean.FALSE; - - case PROP_PRESERVE_LOCATION: - return willPreserveLocation() ? Boolean.TRUE : Boolean.FALSE; - case PROP_AUTO_CLOSE_INPUT: - return willAutoCloseInput() ? Boolean.TRUE : Boolean.FALSE; - - case PROP_DTD_OVERRIDE: - return getDTDOverride(); - - // // // Then Woodstox custom properties: - - // first, flags: - case PROP_CACHE_DTDS: - return willCacheDTDs() ? Boolean.TRUE : Boolean.FALSE; - case PROP_CACHE_DTDS_BY_PUBLIC_ID: - return willCacheDTDsByPublicId() ? Boolean.TRUE : Boolean.FALSE; - case PROP_LAZY_PARSING: - return willParseLazily() ? Boolean.TRUE : Boolean.FALSE; - case PROP_SUPPORT_XMLID: - { - if (!_hasConfigFlag(CFG_XMLID_TYPING)) { - return XMLStreamProperties.XSP_V_XMLID_NONE; - } - return _hasConfigFlag(CFG_XMLID_UNIQ_CHECKS) ? - XMLStreamProperties.XSP_V_XMLID_FULL : - XMLStreamProperties.XSP_V_XMLID_TYPING; - } - - case PROP_TREAT_CHAR_REFS_AS_ENTS: - return willTreatCharRefsAsEnts() ? Boolean.TRUE : Boolean.FALSE; - - case PROP_NORMALIZE_LFS: - return willNormalizeLFs() ? Boolean.TRUE : Boolean.FALSE; - - // then object values: - case PROP_INPUT_BUFFER_LENGTH: - return DataUtil.Integer(getInputBufferLength()); - case PROP_MIN_TEXT_SEGMENT: - return DataUtil.Integer(getShortestReportedTextSegment()); - case PROP_CUSTOM_INTERNAL_ENTITIES: - return getCustomInternalEntities(); - case PROP_DTD_RESOLVER: - return getDtdResolver(); - case PROP_ENTITY_RESOLVER: - return getEntityResolver(); - case PROP_UNDECLARED_ENTITY_RESOLVER: - return getUndeclaredEntityResolver(); - case PROP_BASE_URL: - return getBaseURL(); - case PROP_INPUT_PARSING_MODE: - return getInputParsingMode(); - - default: // sanity check, should never happen - throw new IllegalStateException("Internal error: no handler for property with internal id "+id+"."); - } - } - - public boolean setProperty(String propName, int id, Object value) - { - switch (id) { - // First, standard (Stax 1.0) properties: - - case PROP_COALESCE_TEXT: - doCoalesceText(ArgUtil.convertToBoolean(propName, value)); - break; - - case PROP_NAMESPACE_AWARE: - doSupportNamespaces(ArgUtil.convertToBoolean(propName, value)); - break; - - case PROP_REPLACE_ENTITY_REFS: - doReplaceEntityRefs(ArgUtil.convertToBoolean(propName, value)); - break; - - case PROP_SUPPORT_EXTERNAL_ENTITIES: - doSupportExternalEntities(ArgUtil.convertToBoolean(propName, value)); - break; - - case PROP_SUPPORT_DTD: - doSupportDTDs(ArgUtil.convertToBoolean(propName, value)); - break; - - // // // Then ones that can be dispatched: - - case PROP_VALIDATE_AGAINST_DTD: - doValidateWithDTD(ArgUtil.convertToBoolean(propName, value)); - break; - - case PROP_WARNING_REPORTER: - setXMLReporter((XMLReporter) value); - break; - - case PROP_XML_RESOLVER: - setXMLResolver((XMLResolver) value); - break; - - case PROP_EVENT_ALLOCATOR: - /* 25-Mar-2006, TSa: Not really supported here, so let's - * return false to let caller deal with it - */ - return false; - - // // // Then Stax2 properties, flags: - - case PROP_INTERN_NS_URIS: - doInternNsURIs(ArgUtil.convertToBoolean(propName, value)); - break; - - case PROP_INTERN_NAMES: - doInternNames(ArgUtil.convertToBoolean(propName, value)); - break; - - case PROP_REPORT_CDATA: - doReportCData(ArgUtil.convertToBoolean(propName, value)); - break; - - case PROP_REPORT_PROLOG_WS: - doReportPrologWhitespace(ArgUtil.convertToBoolean(propName, value)); - break; - - case PROP_PRESERVE_LOCATION: - doPreserveLocation(ArgUtil.convertToBoolean(propName, value)); - break; - - case PROP_AUTO_CLOSE_INPUT: - doAutoCloseInput(ArgUtil.convertToBoolean(propName, value)); - break; - - // // // Then Stax2 properties, enum/object types: - - case PROP_SUPPORT_XMLID: - { - boolean typing, uniq; - - if (XMLStreamProperties.XSP_V_XMLID_NONE.equals(value)) { - typing = uniq = false; - } else if (XMLStreamProperties.XSP_V_XMLID_TYPING.equals(value)) { - typing = true; - uniq = false; - } else if (XMLStreamProperties.XSP_V_XMLID_FULL.equals(value)) { - typing = uniq = true; - } else { - throw new IllegalArgumentException - ("Illegal argument ('"+value+"') to set property " -+XMLStreamProperties.XSP_SUPPORT_XMLID+" to: has to be one of '" -+XMLStreamProperties.XSP_V_XMLID_NONE+"', '"+XMLStreamProperties.XSP_V_XMLID_TYPING+"' or '"+XMLStreamProperties.XSP_V_XMLID_FULL+"'" - ); - } - setConfigFlag(CFG_XMLID_TYPING, typing); - setConfigFlag(CFG_XMLID_UNIQ_CHECKS, uniq); - } - break; - - case PROP_DTD_OVERRIDE: - setDTDOverride((DTDValidationSchema) value); - break; - - // // // And then Woodstox specific, flags - - case PROP_CACHE_DTDS: - doCacheDTDs(ArgUtil.convertToBoolean(propName, value)); - break; - - case PROP_CACHE_DTDS_BY_PUBLIC_ID: - doCacheDTDsByPublicId(ArgUtil.convertToBoolean(propName, value)); - break; - - case PROP_LAZY_PARSING: - doParseLazily(ArgUtil.convertToBoolean(propName, value)); - break; - - case PROP_TREAT_CHAR_REFS_AS_ENTS: - doTreatCharRefsAsEnts(ArgUtil.convertToBoolean(propName, value)); - break; - - case PROP_NORMALIZE_LFS: - doNormalizeLFs(ArgUtil.convertToBoolean(propName, value)); - break; - - // // // And then Woodstox specific, enum/object: - - case PROP_INPUT_BUFFER_LENGTH: - setInputBufferLength(ArgUtil.convertToInt(propName, value, 1)); - break; - - case PROP_MIN_TEXT_SEGMENT: - setShortestReportedTextSegment(ArgUtil.convertToInt(propName, value, 1)); - break; - - case PROP_CUSTOM_INTERNAL_ENTITIES: - setCustomInternalEntities((Map) value); - break; - - case PROP_DTD_RESOLVER: - setDtdResolver((XMLResolver) value); - break; - - case PROP_ENTITY_RESOLVER: - setEntityResolver((XMLResolver) value); - break; - - case PROP_UNDECLARED_ENTITY_RESOLVER: - setUndeclaredEntityResolver((XMLResolver) value); - break; - - case PROP_BASE_URL: - /* 17-Nov-2008, TSa: Let's make it bit more versatile; if it's not - * a URL per se, let's assume it is something that we can convert - * to URL - */ - { - URL u; - if (value == null) { - u = null; - } else if (value instanceof URL) { - u = (URL) value; - } else { - try { - u = new URL(value.toString()); - } catch (Exception ioe) { // MalformedURLException actually... - throw new IllegalArgumentException(ioe.getMessage(), ioe); - } - } - setBaseURL(u); - } - break; - - case PROP_INPUT_PARSING_MODE: - setInputParsingMode((WstxInputProperties.ParsingMode) value); - break; - - default: // sanity check, should never happen - throw new IllegalStateException("Internal error: no handler for property with internal id "+id+"."); - } - - return true; - } - - protected boolean _hasConfigFlag(int flag) { - return (mConfigFlags & flag) != 0; - } - - /** - * Method similar to {@link #_hasConfigFlag}, but that will only - * return true if in addition to being set, flag has been explicitly - * modified (i.e. setProperty has been called to modify it) - */ - protected boolean _hasExplicitConfigFlag(int flag) { - return _hasConfigFlag(flag) && (mConfigFlagMods & flag) != 0; - } - - private final Object _getSpecialProperty(int ix) - { - if (mSpecialProperties == null) { - return null; - } - return mSpecialProperties[ix]; - } - - private final void _setSpecialProperty(int ix, Object value) - { - if (mSpecialProperties == null) { - mSpecialProperties = new Object[SPEC_PROC_COUNT]; - } - mSpecialProperties[ix] = value; - } -} diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/api/ValidatorConfig.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/api/ValidatorConfig.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/api/ValidatorConfig.java 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/api/ValidatorConfig.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,39 +0,0 @@ -package com.ctc.wstx.api; - -public final class ValidatorConfig - extends CommonConfig -{ - /** - * For now, since there are no mutable properties, we can share - * a singleton instance. - */ - final static ValidatorConfig sInstance = new ValidatorConfig(); - - private ValidatorConfig() - { - } - - public static ValidatorConfig createDefaults() - { - /* For now, since there are no mutable properties, we can share - * a singleton instance. - */ - return sInstance; - } - - protected int findPropertyId(String propName) { - // Nothing above and beyond default settings... - return -1; - } - - protected Object getProperty(int id) { - // nothing to get: - return null; - } - - protected boolean setProperty(String propName, int id, Object value) { - // nothing to set: - return false; - } -} - diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/api/WriterConfig.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/api/WriterConfig.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/api/WriterConfig.java 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/api/WriterConfig.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,869 +0,0 @@ -package com.ctc.wstx.api; - -import java.lang.ref.SoftReference; -import java.util.HashMap; - -import javax.xml.stream.*; - -import org.codehaus.stax2.XMLOutputFactory2; // for property consts -import org.codehaus.stax2.XMLStreamProperties; -import org.codehaus.stax2.io.EscapingWriterFactory; - -import com.ctc.wstx.api.WstxOutputProperties; -import com.ctc.wstx.cfg.OutputConfigFlags; -import com.ctc.wstx.io.BufferRecycler; -import com.ctc.wstx.util.ArgUtil; -import com.ctc.wstx.util.DataUtil; - -/** - * Simple configuration container class; passed by reader factory to reader - * instance created. - */ -public final class WriterConfig - extends CommonConfig - implements OutputConfigFlags -{ - // // // Constants for standard Stax properties: - - protected final static String DEFAULT_AUTOMATIC_NS_PREFIX = "wstxns"; - - // // // First, standard Stax writer properties - - final static int PROP_AUTOMATIC_NS = 1; // standard property ("repairing") - - // // // And then additional Stax2 properties: - - // General output settings - final static int PROP_AUTOMATIC_EMPTY_ELEMENTS = 2; - final static int PROP_AUTO_CLOSE_OUTPUT = 3; - // Namespace settings: - final static int PROP_ENABLE_NS = 4; - final static int PROP_AUTOMATIC_NS_PREFIX = 5; - // Escaping text content/attr values: - final static int PROP_TEXT_ESCAPER = 6; - final static int PROP_ATTR_VALUE_ESCAPER = 7; - // Problem checking/reporting options - final static int PROP_PROBLEM_REPORTER = 8; - - // // // And then custom Wstx properties: - - // Output settings: - final static int PROP_OUTPUT_CDATA_AS_TEXT = 11; - - final static int PROP_COPY_DEFAULT_ATTRS = 12; - - final static int PROP_ESCAPE_CR = 13; - - final static int PROP_ADD_SPACE_AFTER_EMPTY_ELEM = 14; - - final static int PROP_AUTOMATIC_END_ELEMENTS = 15; - - // Validation flags: - - final static int PROP_VALIDATE_STRUCTURE = 16; - final static int PROP_VALIDATE_CONTENT = 17; - final static int PROP_VALIDATE_ATTR = 18; - final static int PROP_VALIDATE_NAMES = 19; - final static int PROP_FIX_CONTENT = 20; - - // Other: - - final static int PROP_OUTPUT_INVALID_CHAR_HANDLER = 21; - final static int PROP_OUTPUT_EMPTY_ELEMENT_HANDLER = 22; - - // Per-writer instance information - - final static int PROP_UNDERLYING_STREAM = 30; - final static int PROP_UNDERLYING_WRITER = 31; - - // // // Default settings for additional properties: - - final static boolean DEFAULT_OUTPUT_CDATA_AS_TEXT = false; - final static boolean DEFAULT_COPY_DEFAULT_ATTRS = false; - - /* 26-Dec-2006, TSa: Since CRs have been auto-escaped so far, let's - * retain the defaults when adding new properties/features. - */ - final static boolean DEFAULT_ESCAPE_CR = true; - - /** - * 09-Aug-2007, TSa: Space has always been added after empty - * element (before closing "/>"), but now it is configurable. - * 31-Dec-2009, TSa: Intention was to leave it enabled for backwards - * compatibility: but due to a bug this was NOT the case... ugh. - */ - final static boolean DEFAULT_ADD_SPACE_AFTER_EMPTY_ELEM = false; - - /* How about validation? Let's turn them mostly off by default, since - * there are some performance hits when enabling them. - */ - - // Structural checks are easy, cheap and useful... - final static boolean DEFAULT_VALIDATE_STRUCTURE = true; - - /* 17-May-2006, TSa: Since content validation is now much cheaper - * (due to integrated transcoders) than it used to be, let's - * just enable content validation too. - */ - final static boolean DEFAULT_VALIDATE_CONTENT = true; - final static boolean DEFAULT_VALIDATE_ATTR = false; - final static boolean DEFAULT_VALIDATE_NAMES = false; - - // This only matters if content validation is enabled... - /** - * As per [WSTX-120], default was changed to false, - * from true (default prior to wstx 4.0) - */ - //final static boolean DEFAULT_FIX_CONTENT = true; - final static boolean DEFAULT_FIX_CONTENT = false; - - /** - * Default config flags are converted from individual settings, - * to conform to Stax 1.0 specifications. - */ - final static int DEFAULT_FLAGS_J2ME = - 0 - - // Stax 1.0 mandated: - - // namespace-awareness assumed; repairing disabled by default: - // | CFG_AUTOMATIC_NS - | CFG_ENABLE_NS - - // Usually it's good to allow writer to produce empty elems - // (note: default for woodstox 1.x was false) - | CFG_AUTOMATIC_EMPTY_ELEMENTS - - | (DEFAULT_OUTPUT_CDATA_AS_TEXT ? CFG_OUTPUT_CDATA_AS_TEXT : 0) - | (DEFAULT_COPY_DEFAULT_ATTRS ? CFG_COPY_DEFAULT_ATTRS : 0) - | (DEFAULT_ESCAPE_CR ? CFG_ESCAPE_CR : 0) - | (DEFAULT_ADD_SPACE_AFTER_EMPTY_ELEM ? CFG_ADD_SPACE_AFTER_EMPTY_ELEM : 0) - | CFG_AUTOMATIC_END_ELEMENTS - - | (DEFAULT_VALIDATE_STRUCTURE ? CFG_VALIDATE_STRUCTURE : 0) - | (DEFAULT_VALIDATE_CONTENT ? CFG_VALIDATE_CONTENT : 0) - | (DEFAULT_VALIDATE_ATTR ? CFG_VALIDATE_ATTR : 0) - | (DEFAULT_VALIDATE_NAMES ? CFG_VALIDATE_NAMES : 0) - | (DEFAULT_FIX_CONTENT ? CFG_FIX_CONTENT : 0) - - // As per Stax 1.0 specs, we can not enable this by default: - //| CFG_AUTO_CLOSE_INPUT); - ; - - /** - * For now, full instances start with same settings as J2ME subset - */ - final static int DEFAULT_FLAGS_FULL = DEFAULT_FLAGS_J2ME; - - // // // - - /** - * Map to use for converting from String property ids to ints - * described above; useful to allow use of switch later on. - */ - final static HashMap sProperties = new HashMap(8); - static { - // // Stax (1.0) standard ones: - sProperties.put(XMLOutputFactory.IS_REPAIRING_NAMESPACES, - DataUtil.Integer(PROP_AUTOMATIC_NS)); - - // // Stax2 standard ones: - - // Namespace support - sProperties.put(XMLStreamProperties.XSP_NAMESPACE_AWARE, - DataUtil.Integer(PROP_ENABLE_NS)); - - // Generic output - sProperties.put(XMLOutputFactory2.P_AUTOMATIC_EMPTY_ELEMENTS, - DataUtil.Integer(PROP_AUTOMATIC_EMPTY_ELEMENTS)); - sProperties.put(XMLOutputFactory2.P_AUTO_CLOSE_OUTPUT, - DataUtil.Integer(PROP_AUTO_CLOSE_OUTPUT)); - // Namespace support - sProperties.put(XMLOutputFactory2.P_AUTOMATIC_NS_PREFIX, - DataUtil.Integer(PROP_AUTOMATIC_NS_PREFIX)); - // Text/attr value escaping (customized escapers) - sProperties.put(XMLOutputFactory2.P_TEXT_ESCAPER, - DataUtil.Integer(PROP_TEXT_ESCAPER)); - sProperties.put(XMLOutputFactory2.P_ATTR_VALUE_ESCAPER, - DataUtil.Integer(PROP_ATTR_VALUE_ESCAPER)); - // Problem checking/reporting options - sProperties.put(XMLStreamProperties.XSP_PROBLEM_REPORTER, - DataUtil.Integer(PROP_PROBLEM_REPORTER)); - - // // Woodstox-specifics: - - // Output conversions - sProperties.put(WstxOutputProperties.P_OUTPUT_CDATA_AS_TEXT, - DataUtil.Integer(PROP_OUTPUT_CDATA_AS_TEXT)); - sProperties.put(WstxOutputProperties.P_COPY_DEFAULT_ATTRS, - DataUtil.Integer(PROP_COPY_DEFAULT_ATTRS)); - sProperties.put(WstxOutputProperties.P_OUTPUT_ESCAPE_CR, - DataUtil.Integer(PROP_ESCAPE_CR)); - sProperties.put(WstxOutputProperties.P_ADD_SPACE_AFTER_EMPTY_ELEM -, - DataUtil.Integer(PROP_ADD_SPACE_AFTER_EMPTY_ELEM)); - sProperties.put(WstxOutputProperties.P_AUTOMATIC_END_ELEMENTS, - DataUtil.Integer(PROP_AUTOMATIC_END_ELEMENTS)); - sProperties.put(WstxOutputProperties.P_OUTPUT_INVALID_CHAR_HANDLER, - DataUtil.Integer(PROP_OUTPUT_INVALID_CHAR_HANDLER)); - sProperties.put(WstxOutputProperties.P_OUTPUT_EMPTY_ELEMENT_HANDLER, - DataUtil.Integer(PROP_OUTPUT_EMPTY_ELEMENT_HANDLER)); - - // Validation settings: - sProperties.put(WstxOutputProperties.P_OUTPUT_VALIDATE_STRUCTURE, - DataUtil.Integer(PROP_VALIDATE_STRUCTURE)); - sProperties.put(WstxOutputProperties.P_OUTPUT_VALIDATE_CONTENT, - DataUtil.Integer(PROP_VALIDATE_CONTENT)); - sProperties.put(WstxOutputProperties.P_OUTPUT_VALIDATE_ATTR, - DataUtil.Integer(PROP_VALIDATE_ATTR)); - sProperties.put(WstxOutputProperties.P_OUTPUT_VALIDATE_NAMES, - DataUtil.Integer(PROP_VALIDATE_NAMES)); - sProperties.put(WstxOutputProperties.P_OUTPUT_FIX_CONTENT, - DataUtil.Integer(PROP_FIX_CONTENT)); - - // Underlying stream/writer access - sProperties.put(WstxOutputProperties.P_OUTPUT_UNDERLYING_STREAM, - DataUtil.Integer(PROP_UNDERLYING_STREAM)); - sProperties.put(WstxOutputProperties.P_OUTPUT_UNDERLYING_STREAM, - DataUtil.Integer(PROP_UNDERLYING_STREAM)); - } - - /* - ////////////////////////////////////////////////////////// - // Current config state: - ////////////////////////////////////////////////////////// - */ - - final boolean mIsJ2MESubset; - - protected int mConfigFlags; - - /* - ////////////////////////////////////////////////////////// - // More special(ized) configuration objects - ////////////////////////////////////////////////////////// - */ - - //protected String mAutoNsPrefix; - //protected EscapingWriterFactory mTextEscaperFactory = null; - //protected EscapingWriterFactory mAttrValueEscaperFactory = null; - //protected XMLReporter mProblemReporter = null; - //protected InvalidCharHandler mInvalidCharHandler = null; - - Object[] mSpecialProperties = null; - - private final static int SPEC_PROC_COUNT = 6; - - private final static int SP_IX_AUTO_NS_PREFIX = 0; - private final static int SP_IX_TEXT_ESCAPER_FACTORY = 1; - private final static int SP_IX_ATTR_VALUE_ESCAPER_FACTORY = 2; - private final static int SP_IX_PROBLEM_REPORTER = 3; - private final static int SP_IX_INVALID_CHAR_HANDLER = 4; - private final static int SP_IX_EMPTY_ELEMENT_HANDLER = 5; - - /* - ////////////////////////////////////////////////////////// - // Buffer recycling: - ////////////////////////////////////////////////////////// - */ - - /** - * This ThreadLocal contains a {@link SoftRerefence} - * to a {@link BufferRecycler} used to provide a low-cost - * buffer recycling between Reader instances. - */ - final static ThreadLocal mRecyclerRef = new ThreadLocal(); - - /** - * This is the actually container of the recyclable buffers. It - * is obtained via ThreadLocal/SoftReference combination, if one - * exists, when Config instance is created. If one does not - * exists, it will created first time a buffer is returned. - */ - BufferRecycler mCurrRecycler = null; - - /* - ////////////////////////////////////////////////////////// - // Life-cycle: - ////////////////////////////////////////////////////////// - */ - - private WriterConfig(boolean j2meSubset, int flags, Object[] specProps) - { - mIsJ2MESubset = j2meSubset; - mConfigFlags = flags; - mSpecialProperties = specProps; - - /* Ok, let's then see if we can find a buffer recycler. Since they - * are lazily constructed, and since GC may just flush them out - * on its whims, it's possible we might not find one. That's ok; - * we can reconstruct one if and when we are to return one or more - * buffers. - */ - SoftReference ref = (SoftReference) mRecyclerRef.get(); - if (ref != null) { - mCurrRecycler = (BufferRecycler) ref.get(); - } - } - - public static WriterConfig createJ2MEDefaults() - { - return new WriterConfig(true, DEFAULT_FLAGS_J2ME, null); - } - - public static WriterConfig createFullDefaults() - { - return new WriterConfig(true, DEFAULT_FLAGS_FULL, null); - } - - public WriterConfig createNonShared() - { - Object[] specProps; - - if (mSpecialProperties != null) { - int len = mSpecialProperties.length; - specProps = new Object[len]; - System.arraycopy(mSpecialProperties, 0, specProps, 0, len); - } else { - specProps = null; - } - return new WriterConfig(mIsJ2MESubset, mConfigFlags, specProps); - } - - /* - ////////////////////////////////////////////////////////// - // Implementation of abstract methods - ////////////////////////////////////////////////////////// - */ - - protected int findPropertyId(String propName) - { - Integer I = (Integer) sProperties.get(propName); - return (I == null) ? -1 : I.intValue(); - } - - /* - ////////////////////////////////////////////////////////// - // Public API - ////////////////////////////////////////////////////////// - */ - - public Object getProperty(int id) - { - switch (id) { - - // First, Stax 1.0 properties: - - case PROP_AUTOMATIC_NS: - return automaticNamespacesEnabled() ? Boolean.TRUE : Boolean.FALSE; - - // Then Stax2 properties: - - // First, properties common to input/output factories: - - case PROP_ENABLE_NS: - return willSupportNamespaces() ? Boolean.TRUE : Boolean.FALSE; - case PROP_PROBLEM_REPORTER: - return getProblemReporter(); - - // Then output-specific properties: - case PROP_AUTOMATIC_EMPTY_ELEMENTS: - return automaticEmptyElementsEnabled() ? Boolean.TRUE : Boolean.FALSE; - case PROP_AUTO_CLOSE_OUTPUT: - return willAutoCloseOutput() ? Boolean.TRUE : Boolean.FALSE; - case PROP_AUTOMATIC_NS_PREFIX: - return getAutomaticNsPrefix(); - case PROP_TEXT_ESCAPER: - return getTextEscaperFactory(); - case PROP_ATTR_VALUE_ESCAPER: - return getAttrValueEscaperFactory(); - - // // // Then Woodstox-specific properties: - - case PROP_OUTPUT_CDATA_AS_TEXT: - return willOutputCDataAsText() ? Boolean.TRUE : Boolean.FALSE; - case PROP_COPY_DEFAULT_ATTRS: - return willCopyDefaultAttrs() ? Boolean.TRUE : Boolean.FALSE; - case PROP_ESCAPE_CR: - return willEscapeCr() ? Boolean.TRUE : Boolean.FALSE; - case PROP_ADD_SPACE_AFTER_EMPTY_ELEM: - return willAddSpaceAfterEmptyElem() ? Boolean.TRUE : Boolean.FALSE; - case PROP_AUTOMATIC_END_ELEMENTS: - return automaticEndElementsEnabled() ? Boolean.TRUE : Boolean.FALSE; - - case PROP_VALIDATE_STRUCTURE: - return willValidateStructure() ? Boolean.TRUE : Boolean.FALSE; - case PROP_VALIDATE_CONTENT: - return willValidateContent() ? Boolean.TRUE : Boolean.FALSE; - case PROP_VALIDATE_ATTR: - return willValidateAttributes() ? Boolean.TRUE : Boolean.FALSE; - case PROP_VALIDATE_NAMES: - return willValidateNames() ? Boolean.TRUE : Boolean.FALSE; - case PROP_FIX_CONTENT: - return willFixContent() ? Boolean.TRUE : Boolean.FALSE; - case PROP_OUTPUT_INVALID_CHAR_HANDLER: - return getInvalidCharHandler(); - case PROP_OUTPUT_EMPTY_ELEMENT_HANDLER: - return getEmptyElementHandler(); - - // And then per-instance properties: not valid via config object - case PROP_UNDERLYING_STREAM: - case PROP_UNDERLYING_WRITER: - throw new IllegalStateException("Can not access per-stream-writer properties via factory"); - } - - throw new IllegalStateException("Internal error: no handler for property with internal id "+id+"."); - } - - /** - * @return True, if the specified property was succesfully - * set to specified value; false if its value was not changed - */ - public boolean setProperty(String name, int id, Object value) - { - switch (id) { - // First, Stax 1.0 properties: - - case PROP_AUTOMATIC_NS: - enableAutomaticNamespaces(ArgUtil.convertToBoolean(name, value)); - break; - - // // // Then Stax2 ones: - - case PROP_ENABLE_NS: - doSupportNamespaces(ArgUtil.convertToBoolean(name, value)); - break; - case PROP_PROBLEM_REPORTER: - setProblemReporter((XMLReporter) value); - break; - - case PROP_AUTOMATIC_EMPTY_ELEMENTS: - enableAutomaticEmptyElements(ArgUtil.convertToBoolean(name, value)); - break; - - case PROP_AUTO_CLOSE_OUTPUT: - doAutoCloseOutput(ArgUtil.convertToBoolean(name, value)); - break; - - case PROP_AUTOMATIC_NS_PREFIX: - // value should be a String, but let's verify that: - setAutomaticNsPrefix(value.toString()); - break; - - case PROP_TEXT_ESCAPER: - setTextEscaperFactory((EscapingWriterFactory) value); - break; - - case PROP_ATTR_VALUE_ESCAPER: - setAttrValueEscaperFactory((EscapingWriterFactory) value); - break; - - // // // Then Woodstox-specific ones: - - case PROP_OUTPUT_CDATA_AS_TEXT: - doOutputCDataAsText(ArgUtil.convertToBoolean(name, value)); - break; - case PROP_COPY_DEFAULT_ATTRS: - doCopyDefaultAttrs(ArgUtil.convertToBoolean(name, value)); - break; - case PROP_ESCAPE_CR: - doEscapeCr(ArgUtil.convertToBoolean(name, value)); - break; - case PROP_ADD_SPACE_AFTER_EMPTY_ELEM: - doAddSpaceAfterEmptyElem(ArgUtil.convertToBoolean(name, value)); - break; - case PROP_AUTOMATIC_END_ELEMENTS: - enableAutomaticEndElements(ArgUtil.convertToBoolean(name, value)); - break; - case PROP_VALIDATE_STRUCTURE: - doValidateStructure(ArgUtil.convertToBoolean(name, value)); - break; - case PROP_VALIDATE_CONTENT: - doValidateContent(ArgUtil.convertToBoolean(name, value)); - break; - case PROP_VALIDATE_ATTR: - doValidateAttributes(ArgUtil.convertToBoolean(name, value)); - break; - case PROP_VALIDATE_NAMES: - doValidateNames(ArgUtil.convertToBoolean(name, value)); - break; - case PROP_FIX_CONTENT: - doFixContent(ArgUtil.convertToBoolean(name, value)); - break; - case PROP_OUTPUT_INVALID_CHAR_HANDLER: - setInvalidCharHandler((InvalidCharHandler) value); - break; - case PROP_OUTPUT_EMPTY_ELEMENT_HANDLER: - setEmptyElementHandler((EmptyElementHandler) value); - break; - - case PROP_UNDERLYING_STREAM: - case PROP_UNDERLYING_WRITER: - throw new IllegalStateException("Can not modify per-stream-writer properties via factory"); - - default: - throw new IllegalStateException("Internal error: no handler for property with internal id "+id+"."); - } - - return true; - } - - /* - ////////////////////////////////////////////////////////// - // Extended Woodstox API, accessors/modifiers - ////////////////////////////////////////////////////////// - */ - - // // // "Raw" accessors for on/off properties: - - public int getConfigFlags() { return mConfigFlags; } - - - // // // Accessors, standard properties: - - public boolean automaticNamespacesEnabled() { - return hasConfigFlag(CFG_AUTOMATIC_NS); - } - - // // // Accessors, Woodstox properties: - - public boolean automaticEmptyElementsEnabled() { - return hasConfigFlag(CFG_AUTOMATIC_EMPTY_ELEMENTS); - } - -public boolean willAutoCloseOutput() { - return hasConfigFlag(CFG_AUTO_CLOSE_OUTPUT); - } - - public boolean willSupportNamespaces() { - return hasConfigFlag(CFG_ENABLE_NS); - } - - public boolean willOutputCDataAsText() { - return hasConfigFlag(CFG_OUTPUT_CDATA_AS_TEXT); - } - - public boolean willCopyDefaultAttrs() { - return hasConfigFlag(CFG_COPY_DEFAULT_ATTRS); - } - - public boolean willEscapeCr() { - return hasConfigFlag(CFG_ESCAPE_CR); - } - - public boolean willAddSpaceAfterEmptyElem() { - return hasConfigFlag(CFG_ADD_SPACE_AFTER_EMPTY_ELEM); - } - - public boolean automaticEndElementsEnabled() { - return hasConfigFlag(CFG_AUTOMATIC_END_ELEMENTS); - } - - public boolean willValidateStructure() { - return hasConfigFlag(CFG_VALIDATE_STRUCTURE); - } - - public boolean willValidateContent() { - return hasConfigFlag(CFG_VALIDATE_CONTENT); - } - - public boolean willValidateAttributes() { - return hasConfigFlag(CFG_VALIDATE_ATTR); - } - - public boolean willValidateNames() { - return hasConfigFlag(CFG_VALIDATE_NAMES); - } - - public boolean willFixContent() { - return hasConfigFlag(CFG_FIX_CONTENT); - } - - /** - * @return Prefix to use as the base for automatically generated - * namespace prefixes ("namespace prefix prefix", so to speak). - * Defaults to "wstxns". - */ - public String getAutomaticNsPrefix() { - String prefix = (String) getSpecialProperty(SP_IX_AUTO_NS_PREFIX); - if (prefix == null) { - prefix = DEFAULT_AUTOMATIC_NS_PREFIX; - } - return prefix; - } - - public EscapingWriterFactory getTextEscaperFactory() { - return (EscapingWriterFactory) getSpecialProperty(SP_IX_TEXT_ESCAPER_FACTORY); - } - - public EscapingWriterFactory getAttrValueEscaperFactory() { - return (EscapingWriterFactory) getSpecialProperty(SP_IX_ATTR_VALUE_ESCAPER_FACTORY); - } - - public XMLReporter getProblemReporter() { - return (XMLReporter) getSpecialProperty(SP_IX_PROBLEM_REPORTER); - } - - public InvalidCharHandler getInvalidCharHandler() { - return (InvalidCharHandler) getSpecialProperty(SP_IX_INVALID_CHAR_HANDLER); - } - - public EmptyElementHandler getEmptyElementHandler() { - return (EmptyElementHandler) getSpecialProperty(SP_IX_EMPTY_ELEMENT_HANDLER); - } - - // // // Mutators: - - // Standard properies: - - public void enableAutomaticNamespaces(boolean state) { - setConfigFlag(CFG_AUTOMATIC_NS, state); - } - - // Wstx properies: - - public void enableAutomaticEmptyElements(boolean state) { - setConfigFlag(CFG_AUTOMATIC_EMPTY_ELEMENTS, state); - } - - public void doAutoCloseOutput(boolean state) { - setConfigFlag(CFG_AUTO_CLOSE_OUTPUT, state); - } - - public void doSupportNamespaces(boolean state) { - setConfigFlag(CFG_ENABLE_NS, state); - } - - public void doOutputCDataAsText(boolean state) { - setConfigFlag(CFG_OUTPUT_CDATA_AS_TEXT, state); - } - - public void doCopyDefaultAttrs(boolean state) { - setConfigFlag(CFG_COPY_DEFAULT_ATTRS, state); - } - - public void doEscapeCr(boolean state) { - setConfigFlag(CFG_ESCAPE_CR, state); - } - - public void doAddSpaceAfterEmptyElem(boolean state) { - setConfigFlag(CFG_ADD_SPACE_AFTER_EMPTY_ELEM, state); - } - - public void enableAutomaticEndElements(boolean state) { - setConfigFlag(CFG_AUTOMATIC_END_ELEMENTS, state); - } - - public void doValidateStructure(boolean state) { - setConfigFlag(CFG_VALIDATE_STRUCTURE, state); - } - - public void doValidateContent(boolean state) { - setConfigFlag(CFG_VALIDATE_CONTENT, state); - } - - public void doValidateAttributes(boolean state) { - setConfigFlag(CFG_VALIDATE_ATTR, state); - } - - public void doValidateNames(boolean state) { - setConfigFlag(CFG_VALIDATE_NAMES, state); - } - - public void doFixContent(boolean state) { - setConfigFlag(CFG_FIX_CONTENT, state); - } - - /** - * @param prefix Prefix to use as the base for automatically generated - * namespace prefixes ("namespace prefix prefix", so to speak). - */ - public void setAutomaticNsPrefix(String prefix) { - setSpecialProperty(SP_IX_AUTO_NS_PREFIX, prefix); - } - - public void setTextEscaperFactory(EscapingWriterFactory f) { - setSpecialProperty(SP_IX_TEXT_ESCAPER_FACTORY, f); - } - - public void setAttrValueEscaperFactory(EscapingWriterFactory f) { - setSpecialProperty(SP_IX_ATTR_VALUE_ESCAPER_FACTORY, f); - } - - public void setProblemReporter(XMLReporter rep) { - setSpecialProperty(SP_IX_PROBLEM_REPORTER, rep); - } - - public void setInvalidCharHandler(InvalidCharHandler h) { - setSpecialProperty(SP_IX_INVALID_CHAR_HANDLER, h); - } - - public void setEmptyElementHandler(EmptyElementHandler h) { - setSpecialProperty(SP_IX_EMPTY_ELEMENT_HANDLER, h); - } - - /* - ////////////////////////////////////////////////////////// - // Extended Woodstox API, profiles - ////////////////////////////////////////////////////////// - */ - - /** - * For Woodstox, this profile enables all basic well-formedness checks, - * including checking for name validity. - */ - public void configureForXmlConformance() - { - doValidateAttributes(true); - doValidateContent(true); - doValidateStructure(true); - doValidateNames(true); - } - - /** - * For Woodstox, this profile enables all basic well-formedness checks, - * including checking for name validity, and also enables all matching - * "fix-me" properties (currently only content-fixing property exists). - */ - public void configureForRobustness() - { - doValidateAttributes(true); - doValidateStructure(true); - doValidateNames(true); - - /* This the actual "meat": we do want to not only check if the - * content is ok, but also "fix" it if not, and if there's a way - * to fix it: - */ - doValidateContent(true); - doFixContent(true); - } - - /** - * For Woodstox, setting this profile disables most checks for validity; - * specifically anything that can have measurable performance impact. - * - */ - public void configureForSpeed() - { - doValidateAttributes(false); - doValidateContent(false); - doValidateNames(false); - - // Structural validation is cheap: can be left enabled (if already so) - //doValidateStructure(false); - } - - /* - ///////////////////////////////////////////////////// - // Buffer recycling: - ///////////////////////////////////////////////////// - */ - - /** - * Method called to allocate intermediate recyclable copy buffers - */ - public char[] allocMediumCBuffer(int minSize) - { - if (mCurrRecycler != null) { - char[] result = mCurrRecycler.getMediumCBuffer(minSize); - if (result != null) { - return result; - } - } - return new char[minSize]; - } - - public void freeMediumCBuffer(char[] buffer) - { - // Need to create (and assign) the buffer? - if (mCurrRecycler == null) { - mCurrRecycler = createRecycler(); - } - mCurrRecycler.returnMediumCBuffer(buffer); - } - - public char[] allocFullCBuffer(int minSize) - { - if (mCurrRecycler != null) { - char[] result = mCurrRecycler.getFullCBuffer(minSize); - if (result != null) { - return result; - } - } - return new char[minSize]; - } - - public void freeFullCBuffer(char[] buffer) - { - // Need to create (and assign) the buffer? - if (mCurrRecycler == null) { - mCurrRecycler = createRecycler(); - } - mCurrRecycler.returnFullCBuffer(buffer); - } - - public byte[] allocFullBBuffer(int minSize) - { - if (mCurrRecycler != null) { - byte[] result = mCurrRecycler.getFullBBuffer(minSize); - if (result != null) { - return result; - } - } - return new byte[minSize]; - } - - public void freeFullBBuffer(byte[] buffer) - { - // Need to create (and assign) the buffer? - if (mCurrRecycler == null) { - mCurrRecycler = createRecycler(); - } - mCurrRecycler.returnFullBBuffer(buffer); - } - - static int Counter = 0; - - private BufferRecycler createRecycler() - { - BufferRecycler recycler = new BufferRecycler(); - // No way to reuse/reset SoftReference, have to create new always: - mRecyclerRef.set(new SoftReference(recycler)); - return recycler; - } - - /* - ////////////////////////////////////////////////////////// - // Internal methods - ////////////////////////////////////////////////////////// - */ - - private void setConfigFlag(int flag, boolean state) { - if (state) { - mConfigFlags |= flag; - } else { - mConfigFlags &= ~flag; - } - } - - private final boolean hasConfigFlag(int flag) { - return ((mConfigFlags & flag) == flag); - } - - private final Object getSpecialProperty(int ix) - { - if (mSpecialProperties == null) { - return null; - } - return mSpecialProperties[ix]; - } - - private final void setSpecialProperty(int ix, Object value) - { - if (mSpecialProperties == null) { - mSpecialProperties = new Object[SPEC_PROC_COUNT]; - } - mSpecialProperties[ix] = value; - } -} diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/api/WstxInputProperties.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/api/WstxInputProperties.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/api/WstxInputProperties.java 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/api/WstxInputProperties.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,263 +0,0 @@ -package com.ctc.wstx.api; - -import javax.xml.stream.XMLResolver; - -import org.codehaus.stax2.XMLInputFactory2; - -/** - * Class that contains constant for property names used to configure - * cursor and event readers produced by Wstx implementation of - * {@link javax.xml.stream.XMLInputFactory}. - *

- * TODO: - * - * - CHECK_CHAR_VALIDITY (separate for white spaces?) - * - CATALOG_RESOLVER? (or at least, ENABLE_CATALOGS) - */ -public final class WstxInputProperties -{ - /** - * Constants used when no DTD handling is done, and we do not know the - * 'real' type of an attribute. Seems like CDATA is the safe choice. - */ - public final static String UNKNOWN_ATTR_TYPE = "CDATA"; - - /* - /////////////////////////////////////////////////////// - // Simple on/off settings: - /////////////////////////////////////////////////////// - */ - - // // // Normalization: - - /** - * Feature that controls whether linefeeds are normalized into - * canonical linefeed as mandated by xml specification. - *

- * Note that disabling this property (from its default enabled - * state) will result in non-conforming XML processing. It may - * be useful for use cases where changes to input content should - * be minimized. - *

- * Note: this property was initially removed from Woodstox 4.0, - * but was reintroduced in 4.0.8 due to user request. - */ - public final static String P_NORMALIZE_LFS = "com.ctc.wstx.normalizeLFs"; - - //public final static String P_NORMALIZE_ATTR_VALUES = "com.ctc.wstx.normalizeAttrValues"; - - // // // XML character validation: - - /** - * Whether readers will verify that characters in text content are fully - * valid XML characters (not just Unicode). If true, will check - * that they are valid (including white space); if false, will not - * check. - *

- * Turning this option off may improve parsing performance; leaving - * it on guarantees compatibility with XML 1.0 specs regarding character - * validity rules. - */ - public final static String P_VALIDATE_TEXT_CHARS = "com.ctc.wstx.validateTextChars"; - - - // // // Caching: - - /** - * Whether readers will try to cache parsed external DTD subsets or not. - */ - - public final static String P_CACHE_DTDS = "com.ctc.wstx.cacheDTDs"; - - /** - * Whether reader is to cache DTDs (when caching enabled) based on public id - * or not: if not, system id will be primarily used. Although theoretically - * public IDs should be unique, and should be good caching keys, sometimes - * broken documents use 'wrong' public IDs, and such by default caching keys - * are based on system id only. - */ - public final static String P_CACHE_DTDS_BY_PUBLIC_ID = "com.ctc.wstx.cacheDTDsByPublicId"; - - - // // // Enabling/disabling lazy/incomplete parsing - - /** - * Whether stream readers are allowed to do lazy parsing, meaning - * to parse minimal part of the event when - * {@link javax.xml.stream.XMLStreamReader#next} is called, and only parse the rest - * as needed (or skip remainder of no extra information is needed). - * Alternative to lazy parsing is called "eager parsing", and is - * what most xml parsers use by default. - *

- * Enabling lazy parsing can improve performance for tasks where - * number of textual events are skipped. The downside is that - * not all well-formedness problems are reported when - * {@link javax.xml.stream.XMLStreamReader#next} is called, but only when the - * rest of event are read or skipped. - *

- * Default value for Woodstox is such that lazy parsing is - * enabled. - * - * @deprecated As of Woodstox 4.0 use - * {@link XMLInputFactory2#P_LAZY_PARSING} instead (from - * Stax2 extension API, v3.0) - */ - public final static String P_LAZY_PARSING = XMLInputFactory2.P_LAZY_PARSING; - - // // // API behavior (for backwards compatibility) - - /** - * This read-only property indicates whether null is returned for default name space prefix; - * Boolean.TRUE indicates it does, Boolean.FALSE that it does not. - *

- * Default value for 4.1 is 'false'; this will most likely change for 5.0 since - * Stax API actually specifies null to be used. - * - * @since 4.1.2 - */ - public final static String P_RETURN_NULL_FOR_DEFAULT_NAMESPACE = "com.ctc.wstx.returnNullForDefaultNamespace"; - - // // // Enabling/disabling support for dtd++ - - /** - * Whether the Reader will recognized DTD++ extensions when parsing - * DTD subsets. - *

- * Note: not implemented as of 2.0.x - */ - public final static String P_SUPPORT_DTDPP = "com.ctc.wstx.supportDTDPP"; - - - /** - * Whether the Reader will treat character references as entities while parsing - * XML documents. - */ - public static final String P_TREAT_CHAR_REFS_AS_ENTS = "com.ctc.wstx.treatCharRefsAsEnts"; - - // // // Enabling alternate mode for parsing XML fragments instead - // // // of full documents - - // Automatic W3C Schema support? - /* - * Whether W3C Schema hint attributes are recognized within document, - * and used to locate Schema to use for validation. - */ - //public final static String P_AUTOMATIC_W3C_SCHEMA = 0x00100000; - - /* - /////////////////////////////////////////////////////// - // More complex settings: - /////////////////////////////////////////////////////// - */ - - // // // Buffer sizes; - - /** - * Size of input buffer (in chars), to use for reading XML content - * from input stream/reader. - */ - public final static String P_INPUT_BUFFER_LENGTH = "com.ctc.wstx.inputBufferLength"; - - // // // Constraints on sizes of text segments parsed: - - - /** - * Property to specify shortest non-complete text segment (part of - * CDATA section or text content) that parser is allowed to return, - * if not required to coalesce text. - */ - public final static String P_MIN_TEXT_SEGMENT = "com.ctc.wstx.minTextSegment"; - - // // // Entity handling - - /** - * Property of type {@link java.util.Map}, that defines explicit set of - * internal (generic) entities that will define of override any entities - * defined in internal or external subsets; except for the 5 pre-defined - * entities (lt, gt, amp, apos, quot). Can be used to explicitly define - * entites that would normally come from a DTD. - *

- * @deprecated This feature may be removed from future versions of - * Woodstox, since the same functionality can be achieved by using - * custom entity resolvers. - */ - public final static String P_CUSTOM_INTERNAL_ENTITIES = "com.ctc.wstx.customInternalEntities"; - - /** - * Property of type {@link XMLResolver}, that - * will allow overriding of default DTD and external parameter entity - * resolution. - */ - public final static String P_DTD_RESOLVER = "com.ctc.wstx.dtdResolver"; - - /** - * Property of type {@link XMLResolver}, that - * will allow overriding of default external general entity - * resolution. Note that using this property overrides settings done - * using {@link javax.xml.stream.XMLInputFactory#RESOLVER} (and vice versa). - */ - public final static String P_ENTITY_RESOLVER = "com.ctc.wstx.entityResolver"; - - /** - * Property of type {@link XMLResolver}, that - * will allow graceful handling of references to undeclared (general) - * entities. - */ - public final static String P_UNDECLARED_ENTITY_RESOLVER = "com.ctc.wstx.undeclaredEntityResolver"; - - /** - * Property of type {@link java.net.URL}, that will allow specifying - * context URL to use when resolving relative references, for the - * main-level entities (external DTD subset, references from the internal - * DTD subset). - */ - public final static String P_BASE_URL = "com.ctc.wstx.baseURL"; - - // // // Alternate parsing modes - - /** - * Three-valued property (one of - * {@link #PARSING_MODE_DOCUMENT}, - * {@link #PARSING_MODE_FRAGMENT} or - * {@link #PARSING_MODE_DOCUMENTS}; default being the document mode) - * that can be used to handle "non-standard" XML content. The default - * mode (PARSING_MODE_DOCUMENT) allows parsing of only - * well-formed XML documents, but the other two modes allow more lenient - * parsing. Fragment mode allows parsing of XML content that does not - * have a single root element (can have zero or more), nor can have - * XML or DOCTYPE declarations: this may be useful if parsing a subset - * of a full XML document. Multi-document - * (PARSING_MODE_DOCUMENTS) mode on the other hand allows - * parsing of a stream that contains multiple consequtive well-formed - * documents, with possibly multiple XML and DOCTYPE declarations. - *

- * The main difference from the API perspective is that in first two - * modes, START_DOCUMENT and END_DOCUMENT are used as usual (as the first - * and last events returned), whereas the multi-document mode can return - * multiple pairs of these events: although it is still true that the - * first event (one cursor points to when reader is instantiated or - * returned by the event reader), there may be intervening pairs that - * signal boundary between two adjacent enclosed documents. - */ - public final static String P_INPUT_PARSING_MODE = "com.ctc.wstx.fragmentMode"; - - // // // DTD defaulting, overriding - - /* - //////////////////////////////////////////////////////////////////// - // Helper classes, values enumerations - //////////////////////////////////////////////////////////////////// - */ - - public final static ParsingMode PARSING_MODE_DOCUMENT = new ParsingMode(); - public final static ParsingMode PARSING_MODE_FRAGMENT = new ParsingMode(); - public final static ParsingMode PARSING_MODE_DOCUMENTS = new ParsingMode(); - - /** - * Inner class used for creating type-safe enumerations (prior to JDK 1.5). - */ - public final static class ParsingMode - { - ParsingMode() { } - } -} diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/api/WstxOutputProperties.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/api/WstxOutputProperties.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/api/WstxOutputProperties.java 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/api/WstxOutputProperties.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,178 +0,0 @@ -package com.ctc.wstx.api; - -/** - * Class that contains constant for property names used to configure - * cursor and event writers produced by Wstx implementation of - * {@link javax.xml.stream.XMLOutputFactory}. - *

- */ -public final class WstxOutputProperties -{ - /** - * Default xml version number output, if none was specified by - * application. Version 1.0 is used - * to try to maximize compatibility (some older parsers - * may barf on 1.1 and later...) - */ - public final static String DEFAULT_XML_VERSION = "1.0"; - - /** - * If no encoding is passed, we should just default to what xml - * in general expects (and can determine), UTF-8. - *

- * Note: you can check out bug entry [WSTX-18] for more details - */ - public final static String DEFAULT_OUTPUT_ENCODING = "UTF-8"; - - // // // Output options, simple on/off settings: - - /** - * Whether writer should just automatically convert all calls that - * would normally produce CDATA to produce (quoted) text. - */ - public final static String P_OUTPUT_CDATA_AS_TEXT = "com.ctc.wstx.outputCDataAsText"; - - /** - * Whether writer should copy attributes that were initially expanded - * using default settings ("implicit" attributes) or not. - */ - public final static String P_COPY_DEFAULT_ATTRS = "com.ctc.wstx.copyDefaultAttrs"; - - /** - * Whether writer is to add a single white space before closing "/>" - * of the empty element or not. It is sometimes useful to add to - * increase compatibility with HTML browsers, or to increase - * readability. - *

- * The default value is 'false', up to Woodstox 4.x. - *

- * NOTE: JavaDocs for versions 4.0.0 - 4.0.7 incorrectly state that - * default is 'true': this is NOT the case. - *

- * Note: added to resolve Jira entry - * WSTX-125. - */ - public final static String P_ADD_SPACE_AFTER_EMPTY_ELEM = "com.ctc.wstx.addSpaceAfterEmptyElem"; - - /** - * Whether stream writer is to automatically add end elements that are - * needed to properly close the output tree, when the stream is closed - * (either explicitly by a call to close or - * closeCompletely, or implicitly by a call - * to writeEndDocument. - *

- * The default value is 'true' as of Woodstox 4.x. - * Prior to 4.0, this feature was always enabled and there was no - * way to disable it) - * - * @since 3.2.8 - */ - public final static String P_AUTOMATIC_END_ELEMENTS = "com.ctc.wstx.automaticEndElements"; - - // // // Validation options: - - /** - * Whether output classes should do basic verification that the output - * structure is well-formed (start and end elements match); that - * there is one and only one root, and that there is no textual content - * in prolog/epilog. If false, won't do any checking regarding structure. - */ - public final static String P_OUTPUT_VALIDATE_STRUCTURE = "com.ctc.wstx.outputValidateStructure"; - - /** - * Whether output classes should do basic verification that the textual - * content output as part of nodes should be checked for validity, - * if there's a possibility of invalid content. Nodes that include - * such constraints are: comment/'--', cdata/']]>', - * proc. instr/'?>'. - */ - public final static String P_OUTPUT_VALIDATE_CONTENT = "com.ctc.wstx.outputValidateContent"; - - /** - * Whether output classes should check uniqueness of attribute names, - * to prevent accidental output of duplicate attributes. - */ - public final static String P_OUTPUT_VALIDATE_ATTR = "com.ctc.wstx.outputValidateAttr"; - - /** - * Whether output classes should check validity of names, ie that they - * only contain legal XML identifier characters. - */ - public final static String P_OUTPUT_VALIDATE_NAMES = "com.ctc.wstx.outputValidateNames"; - - /** - * Property that further modifies handling of invalid content so - * that if {@link #P_OUTPUT_VALIDATE_CONTENT} is enabled, instead of - * reporting an error, writer will try to fix the problem. - * Invalid content in this context refers to comment - * content with "--", CDATA with "]]>" and proc. instr data with "?>". - * This can - * be done for some content (CDATA, possibly comment), by splitting - * content into separate - * segments; but not for others (proc. instr, since that might - * change the semantics in unintended ways). - */ - public final static String P_OUTPUT_FIX_CONTENT = "com.ctc.wstx.outputFixContent"; - - /** - * Property that determines whether Carriage Return (\r) characters are - * to be escaped when output or not. If enabled, all instances of - * of character \r are escaped using a character entity (where possible, - * that is, within CHARACTERS events, and attribute values). Otherwise - * they are output as is. The main reason to enable this property is - * to ensure that carriage returns are preserved as is through parsing, - * since otherwise they will be converted to canonical xml linefeeds - * (\n), when occuring along or as part of \r\n pair. - */ - public final static String P_OUTPUT_ESCAPE_CR = "com.ctc.wstx.outputEscapeCr"; - - /** - * Property that defines a {@link InvalidCharHandler} used to determine - * what to do with a Java character that app tries to output but which - * is not a valid xml character. Alternatives are converting it to - * another character or throw an exception: default implementations - * exist for both behaviors. - */ - public final static String P_OUTPUT_INVALID_CHAR_HANDLER = "com.ctc.wstx.outputInvalidCharHandler"; - - /** - * Property that defines an {@link EmptyElementHandler} used to determine - * if the end tag for an empty element should be written or not. - * - * If specified {@link org.codehaus.stax2.XMLOutputFactory2#P_AUTOMATIC_EMPTY_ELEMENTS} is ignored. - */ - public final static String P_OUTPUT_EMPTY_ELEMENT_HANDLER = "com.ctc.wstx.outputEmptyElementHandler"; - - // // // Per-instance access to underlying output objects - - /** - * Property that can be used to find out the underlying - * {@link java.io.OutputStream} that an - * {@link javax.xml.stream.XMLStreamWriter} instance is using, - * if known (not known if constructed with a {@link java.io.Writer}, - * or other non-stream destination). Null is returned, if not - * known. - *

- * Note: in general it is dangerous to operate on returned stream - * (if any), due to buffering stream writer can do. As such, caller - * has to take care to know what he is doing, including properly - * flushing output. - */ - public final static String P_OUTPUT_UNDERLYING_STREAM = "com.ctc.wstx.outputUnderlyingStream"; - - /** - * Property that can be used to find out the underlying - * {@link java.io.Writer} that an - * {@link javax.xml.stream.XMLStreamWriter} instance is using, - * if known (may not be known if constructed with a {@link java.io.OutputStream}, - * or other non-Writer destination). Null is returned, if not - * known. Note that the Writer may be an internal wrapper over - * an output stream. - *

- * Note: in general it is dangerous to operate on returned Writer - * (if any), due to buffering stream writer can do. As such, caller - * has to take care to know what he is doing, including properly - * flushing output. - */ - public final static String P_OUTPUT_UNDERLYING_WRITER = "com.ctc.wstx.outputUnderlyingWriter"; -} diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/cfg/ErrorConsts.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/cfg/ErrorConsts.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/cfg/ErrorConsts.java 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/cfg/ErrorConsts.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,193 +0,0 @@ -package com.ctc.wstx.cfg; - -import javax.xml.XMLConstants; -import javax.xml.stream.XMLStreamConstants; - -/** - * "Static" class that contains error message constants. Note that the - * error message constants are NOT made final; reason is that doing so - * would make compiler inline them in other classes. Doing so would increase - * class size (although not mem usage -- Strings do get interned), with - * minimal performance impact. - */ -public class ErrorConsts - implements XMLStreamConstants -{ - // // // Types of warnings we issue via XMLReporter - - public static String WT_ENT_DECL = "entity declaration"; - public static String WT_ELEM_DECL = "element declaration"; - public static String WT_ATTR_DECL = "attribute declaration"; - public static String WT_XML_DECL = "xml declaration"; - public static String WT_DT_DECL = "doctype declaration"; - public static String WT_NS_DECL = "namespace declaration"; - - /** - * This is the generic type for warnings based on XMLValidationProblem - * objects. - */ - public static String WT_VALIDATION = "schema validation"; - - // // And then warning strings - - public static String W_UNDEFINED_ELEM = "Undefined element \"{0}\"; referred to by attribute(s)"; - public static String W_MIXED_ENCODINGS = "Inconsistent text encoding; declared as \"{0}\" in xml declaration, application had passed \"{1}\""; - public static String W_MISSING_DTD = "Missing DOCTYPE declaration in validating mode; can not validate elements or attributes"; - public static String W_DTD_DUP_ATTR = "Attribute \"{0}\" (for element <{1}>) declared multiple times"; - public static String W_DTD_ATTR_REDECL = "Attribute \"{0}\" already declared for element <{1}>; ignoring re-declaration"; - - // // // Generic errors: - - public static String ERR_INTERNAL = "Internal error"; - public static String ERR_NULL_ARG = "Illegal to pass null as argument"; - public static String ERR_UNKNOWN_FEATURE = "Unrecognized feature \"{0}\""; - - // // // Wrong reader state: - - public static String ERR_STATE_NOT_STELEM = "Current event not START_ELEMENT"; - public static String ERR_STATE_NOT_ELEM = "Current event not START_ELEMENT or END_ELEMENT"; - public static String ERR_STATE_NOT_PI = "Current event not PROCESSING_INSTRUCTION"; - public static String ERR_STATE_NOT_ELEM_OR_TEXT = "Current event ({0}) not START_ELEMENT, END_ELEMENT, CHARACTERS or CDATA"; - - // // // XML declaration related problems - - public static String ERR_XML_10_VS_11 = "XML 1.0 document can not refer to XML 1.1 parsed external entities"; - - // // // Structural problems, prolog/epilog: - - public static String ERR_DTD_IN_EPILOG = "Can not have DOCTYPE declaration in epilog"; - public static String ERR_DTD_DUP = "Duplicate DOCTYPE declaration"; - public static String ERR_CDATA_IN_EPILOG = " (CDATA not allowed in prolog/epilog)"; - - // // // Illegal input: - - public static String ERR_HYPHENS_IN_COMMENT = "String '--' not allowed in comment (missing '>'?)"; - public static String ERR_BRACKET_IN_TEXT = "String ']]>' not allowed in textual content, except as the end marker of CDATA section"; - - // // // Generic parsing errors: - - public static String ERR_UNEXP_KEYWORD = "Unexpected keyword \"{0}\"; expected \"{1}\""; - - public static String ERR_WF_PI_MISSING_TARGET = "Missing processing instruction target"; - public static String ERR_WF_PI_XML_TARGET = "Illegal processing instruction target (\"{0}\"); 'xml' (case insensitive) is reserved by the specs."; - public static String ERR_WF_PI_XML_MISSING_SPACE = "excepted either space or \"?>\" after PI target"; - - // // // Entity problems: - - public static String ERR_WF_ENTITY_EXT_DECLARED = "Entity \"{0}\" declared externally, but referenced from a document declared 'standalone=\"yes\"'"; - - public static String ERR_WF_GE_UNDECLARED = "Undeclared general entity \"{0}\""; - - public static String ERR_WF_GE_UNDECLARED_SA = "Undeclared general entity \"{0}\" (document in stand-alone mode; perhaps declared externally?)"; - - // // // Namespace problems: - - public static String ERR_NS_UNDECLARED = "Undeclared namespace prefix \"{0}\""; - public static String ERR_NS_UNDECLARED_FOR_ATTR = "Undeclared namespace prefix \"{0}\" (for attribute \"{1}\")"; - - public static String ERR_NS_REDECL_XML = "Trying to redeclare prefix 'xml' from its default URI '" - +XMLConstants.XML_NS_URI - +"' to \"{0}\""; - - public static String ERR_NS_REDECL_XMLNS = "Trying to declare prefix 'xmlns' (illegal as per NS 1.1 #4)"; - - public static String ERR_NS_REDECL_XML_URI = "Trying to bind URI '" - +XMLConstants.XML_NS_URI+" to prefix \"{0}\" (can only bind to 'xml')"; - - public static String ERR_NS_REDECL_XMLNS_URI = "Trying to bind URI '" - +XMLConstants.XMLNS_ATTRIBUTE_NS_URI+" to prefix \"{0}\" (can not be explicitly bound)"; - - public static String ERR_NS_EMPTY = -"Non-default namespace can not map to empty URI (as per Namespace 1.0 # 2) in XML 1.0 documents"; - - - // // // DTD-specific: - - public static String ERR_DTD_MAINLEVEL_KEYWORD = "; expected a keyword (ATTLIST, ELEMENT, ENTITY, NOTATION), comment, or conditional section"; - - public static String ERR_DTD_ATTR_TYPE = "; expected one of type (CDATA, ID, IDREF, IDREFS, ENTITY, ENTITIES NOTATION, NMTOKEN or NMTOKENS)"; - - public static String ERR_DTD_DEFAULT_TYPE = "; expected #REQUIRED, #IMPLIED or #FIXED"; - - public static String ERR_DTD_ELEM_REDEFD = - "Trying to redefine element \"{0}\" (originally defined at {1})"; - public static String ERR_DTD_NOTATION_REDEFD = - "Trying to redefine notation \"{0}\" (originally defined at {1})"; - - public static String ERR_DTD_UNDECLARED_ENTITY = - "Undeclared {0} entity \"{1}\""; - - public static String ERR_DTD_XML_SPACE = "Attribute xml:space has to be defined of type enumerated, and have 1 or 2 values, 'default' and/or 'preserve'"; - - public static String ERR_DTD_XML_ID = "Attribute xml:id has to have attribute type of ID, as per Xml:id specification"; - - - // // // DTD-validation: - - public static String ERR_VLD_UNKNOWN_ELEM = "Undefined element <{0}> encountered"; - - public static String ERR_VLD_EMPTY = "Element <{0}> has EMPTY content specification; can not contain {1}"; - public static String ERR_VLD_NON_MIXED = "Element <{0}> has non-mixed content specification; can not contain non-white space text, or any CDATA sections"; - public static String ERR_VLD_ANY = "Element <{0}> has ANY content specification; can not contain {1}"; - public static String ERR_VLD_UNKNOWN_ATTR = "Element <{0}> has no attribute \"{1}\""; - public static String ERR_VLD_WRONG_ROOT = "Unexpected root element <{0}>; expected <{0}> as per DOCTYPE declaration"; - - // // // Output problems: - - public static String WERR_PROLOG_CDATA = - "Trying to output a CDATA block outside main element tree (in prolog or epilog)"; - public static String WERR_PROLOG_NONWS_TEXT = - "Trying to output non-whitespace characters outside main element tree (in prolog or epilog)"; - public static String WERR_PROLOG_SECOND_ROOT = - "Trying to output second root, <{0}>"; - - public static String WERR_CDATA_CONTENT = - "Illegal input: CDATA block has embedded ']]>' in it (index {0})"; - public static String WERR_COMMENT_CONTENT = - "Illegal input: comment content has embedded '--' in it (index {0})"; - - public static String WERR_ATTR_NO_ELEM = - "Trying to write an attribute when there is no open start element."; - - public static String WERR_NAME_EMPTY = "Illegal to pass empty name"; - - public static String WERR_NAME_ILLEGAL_FIRST_CHAR = "Illegal first name character {0}"; - public static String WERR_NAME_ILLEGAL_CHAR = "Illegal name character {0}"; - - /* - //////////////////////////////////////////////////// - // Utility methods - //////////////////////////////////////////////////// - */ - - public static String tokenTypeDesc(int type) - { - switch (type) { - case START_ELEMENT: - return "START_ELEMENT"; - case END_ELEMENT: - return "END_ELEMENT"; - case START_DOCUMENT: - return "START_DOCUMENT"; - case END_DOCUMENT: - return "END_DOCUMENT"; - - case CHARACTERS: - return "CHARACTERS"; - case CDATA: - return "CDATA"; - case SPACE: - return "SPACE"; - - case COMMENT: - return "COMMENT"; - case PROCESSING_INSTRUCTION: - return "PROCESSING_INSTRUCTION"; - case DTD: - return "DTD"; - case ENTITY_REFERENCE: - return "ENTITY_REFERENCE"; - } - return "["+type+"]"; - } -} diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/cfg/InputConfigFlags.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/cfg/InputConfigFlags.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/cfg/InputConfigFlags.java 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/cfg/InputConfigFlags.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,204 +0,0 @@ -package com.ctc.wstx.cfg; - -/** - * Constant interface that contains configuration flag used by parser - * and parser factory, as well as some other input constants. - */ -public interface InputConfigFlags -{ - /* - ////////////////////////////////////////////////////// - // Flags for standard StAX features: - ////////////////////////////////////////////////////// - */ - - // // // Namespace handling: - - /** - * If true, parser will handle namespaces according to XML specs; if - * false, will only pass them as part of element/attribute name value - * information. - */ - final static int CFG_NAMESPACE_AWARE = 0x0001; - - - // // // Text normalization - - - /// Flag that indicates iterator should coalesce all text segments. - final static int CFG_COALESCE_TEXT = 0x0002; - - - // // // Entity handling - - /** - * Flag that enables automatic replacement of internal entities - */ - final static int CFG_REPLACE_ENTITY_REFS = 0x0004; - - /** - * Flag that enables support for expanding external entities. Woodstox - * pretty much ignores the setting, since effectively it is irrelevant, - * as {@link #CFG_REPLACE_ENTITY_REFS} and {@link #CFG_SUPPORT_DTD} - * both need to be enabled for external entities to be supported. - */ - final static int CFG_SUPPORT_EXTERNAL_ENTITIES = 0x0008; - - // // // DTD handling - - /** - * Whether DTD handling is enabled or disabled; disabling means both - * internal and external subsets will just be skipped unprocessed. - */ - final static int CFG_SUPPORT_DTD = 0x0010; - - /** - * Not yet (fully) supported; added as the placeholder - */ - final static int CFG_VALIDATE_AGAINST_DTD = 0x0020; - - // // Note: can add 2 more 'standard' flags here... - - /* - ////////////////////////////////////////////////////// - // Flags for StAX2 features - ////////////////////////////////////////////////////// - */ - - /** - * If true, parser will report (ignorable) white space events in prolog - * and epilog; if false, it will silently ignore them. - */ - final static int CFG_REPORT_PROLOG_WS = 0x0100; - - // // // Type conversions: - - - /** - * If true, parser will accurately report CDATA event as such (unless - * coalescing); otherwise will always report them as CHARACTERS - * independent of coalescing settings. - */ - final static int CFG_REPORT_CDATA = 0x0200; - - // // // String interning: - - /** - * If true, will guarantee that all names (attribute/element local names - * have been intern()ed. If false, this is not guaranteed although - * implementation may still choose to do it. - */ - final static int CFG_INTERN_NAMES = 0x0400; - - /** - * It true, will call intern() on all namespace URIs parsed; otherwise - * will just use 'regular' Strings created from parsed contents. Interning - * makes namespace-based access faster, but has initial overhead of - * intern() call. - */ - final static int CFG_INTERN_NS_URIS = 0x0800; - - // // // Lazy/incomplete parsing - - /** - * Property that determines whether Event objects created will - * contain (accurate) {@link javax.xml.stream.Location} information or not. If not, - * Location may be null or a fixed location (beginning of main - * XML file). - *

- * Note, however, that the underlying parser will still keep track - * of location information for error reporting purposes; it's only - * Event objects that are affected. - */ - final static int CFG_PRESERVE_LOCATION = 0x1000; - - // // // Input source handling - - /** - * Property that enables/disables stream reader to close the underlying - * input source, either when it is asked to (.close() is called), or - * when it doesn't need it any more (reaching EOF, hitting an - * unrecoverable exception). - * As per Stax 1.0 specification, automatic closing is NOT enabled by - * default; except if the caller has no access to the target (i.e. - * when factory created it) - */ - final static int CFG_AUTO_CLOSE_INPUT = 0x2000; - - /* - ////////////////////////////////////////////////////// - // Flags for Woodstox-specific features - ////////////////////////////////////////////////////// - */ - - // // // Content normalization - - // 20-Jan-2007, TSa: These properties removed from 4.0, deprecated: - final static int CFG_NORMALIZE_LFS = 0x4000; - //final static int CFG_NORMALIZE_ATTR_VALUES = 0x8000; - - // // // Caching - - /** - * If true, input factory is allowed cache parsed external DTD subsets, - * potentially speeding up things for which DTDs are needed for: entity - * substitution, attribute defaulting, and of course DTD-based validation. - */ - final static int CFG_CACHE_DTDS = 0x00010000; - - /** - * If true, key used for matching DTD subsets can be the public id, - * if false, only system id can be used. - */ - final static int CFG_CACHE_DTDS_BY_PUBLIC_ID = 0x00020000; - - // // // Lazy/incomplete parsing - - /** - * If true, input factory can defer parsing of nodes until data is - * actually needed; if false, it has to read all the data in right - * away when next type is requested. Setting it to true is good for - * performance, in the cases where some of the nodes (like comments, - * processing instructions, or whole subtrees) are ignored. Otherwise - * setting will not make much of a difference. Downside is that error - * reporting is also done 'lazily'; not right away when getting the next - * even type but when either accessing data, or skipping it. - */ - final static int CFG_LAZY_PARSING = 0x00040000; - - // // // Validation support - - // DTD++ support - - /** - * If true, DTD-parser will recognize DTD++ features, and the validator - * will also use any such information found from DTD when DTD validation - * is enabled. - */ - final static int CFG_SUPPORT_DTDPP = 0x00080000; - - // Automatic W3C Schema support? - //final static int CFG_AUTOMATIC_W3C_SCHEMA = 0x00100000; - - // // // Xml:id support - - /** - * If true, xml:id attribute type assignment and matching checks will - * be done as per Xml:id specification. Needs to be enabled for xml:id - * uniqueness checks to function properly - */ - final static int CFG_XMLID_TYPING = 0x00200000; - - /** - * If true, xml:id attribute uniqueness constraints are enforced, even - * if not validating against DTD otherwise. - */ - final static int CFG_XMLID_UNIQ_CHECKS = 0x00400000; - - /** - * If true, the XML parser will treat character references as entities. - * - */ - final static int CFG_TREAT_CHAR_REFS_AS_ENTS = 0x00800000; -} - diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/cfg/OutputConfigFlags.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/cfg/OutputConfigFlags.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/cfg/OutputConfigFlags.java 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/cfg/OutputConfigFlags.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,105 +0,0 @@ -package com.ctc.wstx.cfg; - -/** - * Constant interface that contains configuration flag used by output - * classes internally, for presenting on/off configuration options. - */ -public interface OutputConfigFlags -{ - /** - * Flag that indicates whether writer is namespace-aware or not; if not, - * only local part is ever used. - */ - final static int CFG_ENABLE_NS = 0x0001; - - /// Flag that indicates that output class should auto-generate namespace prefixes as necessary. - final static int CFG_AUTOMATIC_NS = 0x0002; - - /// Flag that indicates we can output 'automatic' empty elements. - final static int CFG_AUTOMATIC_EMPTY_ELEMENTS = 0x0004; - - /** - * Whether writer should just automatically convert all calls that - * would normally produce CDATA to produce (quoted) text. - */ - final static int CFG_OUTPUT_CDATA_AS_TEXT = 0x0008; - - /** - * Flag that indicates whether attributes expanded from default attribute - * values should be copied to output, when using copy methods. - */ - final static int CFG_COPY_DEFAULT_ATTRS = 0x0010; - - /** - * Flag that indicates whether CR (\r, ascii 13) characters occuring - * in text (CHARACTERS) and attribute values should be escaped using - * character entities or not. Escaping is needed to enable seamless - * round-tripping (preserving CR characters). - */ - final static int CFG_ESCAPE_CR = 0x0020; - - /** - * Flag that indicates - * whether writer is to add a single white space before closing "/>" - * of the empty element or not. It is sometimes useful to add to - * increase compatibility with HTML browsers, or to increase - * readability. - */ - final static int CFG_ADD_SPACE_AFTER_EMPTY_ELEM = 0x0040; - - /** - * Flag that indicates we can output 'automatic' empty elements; - * end elements needed to close the logical output tree when - * stream writer is closed (by closing it explicitly, or by writing - * end-document event) - * - * @since 3.2.8 - */ - final static int CFG_AUTOMATIC_END_ELEMENTS = 0x0080; - - /// Flag that indicates we should check validity of output XML structure. - final static int CFG_VALIDATE_STRUCTURE = 0x0100; - - /** - * Flag that indicates we should check validity of textual content of - * nodes that have constraints. - *

- * Specifically: comments can not have '--', CDATA sections can not - * have ']]>' and processing instruction can not have '?<' character - * combinations in content passed in. - */ - final static int CFG_VALIDATE_CONTENT = 0x0200; - - /** - * Flag that indicates we should check validity of names (element and - * attribute names and prefixes; processing instruction names), that they - * contain only legal identifier characters. - */ - final static int CFG_VALIDATE_NAMES = 0x0400; - - /** - * Flag that indicates we should check uniqueness of attribute names, - * to prevent accidental output of duplicate attributes. - */ - final static int CFG_VALIDATE_ATTR = 0x0800; - - /** - * Flag that will enable writer that checks for validity of content - * to try to fix the problem, by splitting output segments as - * necessary. If disabled, validation will throw an exception; and - * without validation no problem is noticed by writer (but instead - * invalid output is created). - */ - final static int CFG_FIX_CONTENT = 0x1000; - - /** - * Property that enables/disables stream write to close the underlying - * output target, either when it is asked to (.close() is called), or - * when it doesn't need it any more (reaching EOF, hitting an - * unrecoverable exception). - * As per Stax 1.0 specification, automatic closing is NOT enabled by - * default; except if the caller has no access to the target (i.e. - * when factory created it) - */ - final static int CFG_AUTO_CLOSE_OUTPUT = 0x2000; -} diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/cfg/package.html libwoodstox-java-5.1.0/src/java/com/ctc/wstx/cfg/package.html --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/cfg/package.html 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/cfg/package.html 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ - -Package that contains internal configuration settings for Woodstox. - diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/cfg/ParsingErrorMsgs.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/cfg/ParsingErrorMsgs.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/cfg/ParsingErrorMsgs.java 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/cfg/ParsingErrorMsgs.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,26 +0,0 @@ -package com.ctc.wstx.cfg; - -public interface ParsingErrorMsgs -{ - // // // EOF problems: - - final static String SUFFIX_IN_ATTR_VALUE = " in attribute value"; - final static String SUFFIX_IN_DEF_ATTR_VALUE = " in attribute default value"; - final static String SUFFIX_IN_CDATA = " in CDATA section"; - final static String SUFFIX_IN_CLOSE_ELEMENT = " in end tag"; - final static String SUFFIX_IN_COMMENT = " in comment"; - final static String SUFFIX_IN_DTD = " in DOCTYPE declaration"; - final static String SUFFIX_IN_DTD_EXTERNAL = " in external DTD subset"; - final static String SUFFIX_IN_DTD_INTERNAL = " in internal DTD subset"; - final static String SUFFIX_IN_DOC = " in main document content"; - final static String SUFFIX_IN_ELEMENT = " in start tag"; - final static String SUFFIX_IN_ENTITY_REF = " in entity reference"; - final static String SUFFIX_IN_EPILOG = " in epilog"; - final static String SUFFIX_IN_NAME = " in name token"; - final static String SUFFIX_IN_PROC_INSTR = " in processing instruction"; - final static String SUFFIX_IN_PROLOG = " in prolog"; - final static String SUFFIX_IN_TEXT = " in document text content"; - final static String SUFFIX_IN_XML_DECL = " in xml declaration"; - - final static String SUFFIX_EOF_EXP_NAME = "; expected an identifier"; -} diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/cfg/XmlConsts.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/cfg/XmlConsts.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/cfg/XmlConsts.java 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/cfg/XmlConsts.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,66 +0,0 @@ -package com.ctc.wstx.cfg; - -/** - * Simple constant container interface, shared by input and output - * sides. - */ -public interface XmlConsts -{ - // // // Constants for XML declaration - - public final static String XML_DECL_KW_ENCODING = "encoding"; - public final static String XML_DECL_KW_VERSION = "version"; - public final static String XML_DECL_KW_STANDALONE = "standalone"; - - public final static String XML_V_10_STR = "1.0"; - public final static String XML_V_11_STR = "1.1"; - - /** - * This constants refers to cases where the version has not been - * declared explicitly; and needs to be considered to be 1.0. - */ - public final static int XML_V_UNKNOWN = 0x0000; - - public final static int XML_V_10 = 0x0100; - public final static int XML_V_11 = 0x0110; - - public final static String XML_SA_YES = "yes"; - public final static String XML_SA_NO = "no"; - - // // // Stax specs mandates some settings: but since exact - // // // definitions have been re-interpreted a few times, - // // // let's isolate them in a single place - - /* 13-Mar-2008, TSa: As per latest reading of Stax specs, - * all of these are expected to be "", not null. - */ - - public final static String ELEM_NO_NS_URI = ""; - - public final static String ATTR_NO_NS_URI = ""; - - public final static String ELEM_NO_PREFIX = ""; - - public final static String ATTR_NO_PREFIX = ""; - - /** - * Top-most namespace URI assigned for root element, if not specifically - * defined (default namespace unbound). - *

- * As per Stax specs, related clarifying discussion on - * the mailing list, and especially JDK 1.6 definitions - * in {@link javax.xml.XMLConstants} constants, empty String - * should be used instead of null. - */ - public final static String DEFAULT_NAMESPACE_URI = ELEM_NO_NS_URI; - - // // // Well, these are not strictly xml constants, but for - // // // now can live here - - /** - * This constant defines the highest Unicode character allowed - * in XML content. - */ - final static int MAX_UNICODE_CHAR = 0x10FFFF; - -} diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/compat/package.html libwoodstox-java-5.1.0/src/java/com/ctc/wstx/compat/package.html --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/compat/package.html 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/compat/package.html 1970-01-01 00:00:00.000000000 +0000 @@ -1,7 +0,0 @@ - -Package that contains classes that allow abstracting out the details of -JDK platform version being used. Currently classes are used to implement -"graceful degradation" of functionality, when certain JDK classes are only -fully implemented as part of JDKs later than the minimum version -Woodstox needs for running (for Woodstox versions up to 3.x it was JDK 1.2, for 4.x JDK 1.4). - diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/compat/QNameCreator.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/compat/QNameCreator.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/compat/QNameCreator.java 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/compat/QNameCreator.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,70 +0,0 @@ -package com.ctc.wstx.compat; - -import java.util.logging.Logger; - -import javax.xml.namespace.QName; - -/** - * Helper class used to solve [WSTX-174]: some older AppServers were - * shipped with incompatible version of QName class, which is missing - * the 3 argument constructor. To address this, we'll use bit of - * ClassLoader hacker to gracefully (?) downgrade to using 2 arg - * alternatives if necessary. - *

- * Note: choice of java.util.logging logging is only based on the - * fact that it is guaranteed to be present (we have JDK 1.4 baseline - * requirement) so that we do not add external dependencies. - * It is not a recommendation for using JUL per se; most users would - * do well to just use slf4j or log4j directly instead. - * - * @author Tatu Saloranta - * - * @since 3.2.8 - */ -public final class QNameCreator -{ - /** - * Creator object that creates QNames using proper 3-arg constructor. - * If dynamic class loading fails - */ - private final static Helper _helper; - static { - Helper h = null; - try { - // Not sure where it'll fail, constructor or create... - Helper h0 = new Helper(); - /*QName n =*/ h0.create("elem", "http://dummy", "ns"); - h = h0; - } catch (Throwable t) { - String msg = "Could not construct QNameCreator.Helper; assume 3-arg QName constructor not available and use 2-arg method instead. Problem: "+t.getMessage(); - try { - Logger.getLogger("com.ctc.wstx.compat.QNameCreator").warning(msg); - } catch (Throwable t2) { // just in case JUL craps out... - System.err.println("ERROR: failed to log error using Logger (problem "+t.getMessage()+"), original problem: "+msg); - } - } - _helper = h; - } - - public static QName create(String uri, String localName, String prefix) - { - if (_helper == null) { // can't use 3-arg constructor; but 2-arg will be there - return new QName(uri, localName); - } - return _helper.create(uri, localName, prefix); - } - - /** - * Helper class used to encapsulate calls to the missing method. - */ - private final static class Helper - { - public Helper() { } - - public QName create(String localName, String nsURI, String prefix) - { - return new QName(localName, nsURI, prefix); - } - } -} - diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/dom/DOMOutputElement.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/dom/DOMOutputElement.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/dom/DOMOutputElement.java 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/dom/DOMOutputElement.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,212 +0,0 @@ -package com.ctc.wstx.dom; - -import javax.xml.namespace.NamespaceContext; - -import org.w3c.dom.Element; -import org.w3c.dom.Node; - -import com.ctc.wstx.sw.OutputElementBase; -import com.ctc.wstx.util.BijectiveNsMap; - -/** - * Context object that holds information about an open element - * (one for which START_ELEMENT has been sent, but no END_ELEMENT) - */ -public final class DOMOutputElement - extends OutputElementBase -{ - /** - * Reference to the parent element, element enclosing this element. - * Null for root element. - * Non-final to allow temporary pooling - * (on per-writer basis, to keep these short-lived). - */ - private DOMOutputElement mParent; - - /** - * DOM node that is the root under which content is written, in case - * where there is no parent (mParent == null). If mParent is not null, - * this will be null. - * Value is of type - * {@link Document}, {@link DocumentFragment} or {@link Element} - */ - private final Node mRootNode; - - /** - * Actual DOM element for which this element object acts as a proxy. - */ - private Element mElement; - - private boolean mDefaultNsSet; - - /** - * Constructor for the virtual root element - */ - private DOMOutputElement(Node rootNode) - { - super(); - mRootNode = rootNode; - mParent = null; - mElement = null; - mNsMapping = null; - mNsMapShared = false; - mDefaultNsURI = ""; - mRootNsContext = null; - mDefaultNsSet = false; - } - - private DOMOutputElement(DOMOutputElement parent, Element element, BijectiveNsMap ns) - { - super(parent, ns); - mRootNode = null; - mParent = parent; - mElement = element; - mNsMapping = ns; - mNsMapShared = (ns != null); - mDefaultNsURI = parent.mDefaultNsURI; - mRootNsContext = parent.mRootNsContext; - mDefaultNsSet = false; - } - - /** - * Method called to reuse a pooled instance. - * - * @return Chained pooled instance that should now be head of the - * reuse chain - */ - private void relink(DOMOutputElement parent, Element element) - { - super.relink(parent); - mParent = parent; - mElement = element; - parent.appendNode(element); - mDefaultNsSet = false; - } - - public static DOMOutputElement createRoot(Node rootNode) - { - return new DOMOutputElement(rootNode); - } - - /** - * Simplest factory method, which gets called when a 1-argument - * element output method is called. It is, then, assumed to - * use the default namespace. - * Will both create the child element and attach it to parent element, - * or lacking own owner document. - */ - protected DOMOutputElement createAndAttachChild(Element element) - { - if (mRootNode != null) { - mRootNode.appendChild(element); - } else { - mElement.appendChild(element); - } - return createChild(element); - } - - protected DOMOutputElement createChild(Element element) - { - return new DOMOutputElement(this, element, mNsMapping); - } - - /** - * @return New head of the recycle pool - */ - protected DOMOutputElement reuseAsChild(DOMOutputElement parent, Element element) - { - DOMOutputElement poolHead = mParent; - relink(parent, element); - return poolHead; - } - - /** - * Method called to temporarily link this instance to a pool, to - * allow reusing of instances with the same reader. - */ - protected void addToPool(DOMOutputElement poolHead) - { - mParent = poolHead; - } - - /* - /////////////////////////////////////////////////////////// - // Public API, accessors - /////////////////////////////////////////////////////////// - */ - - public DOMOutputElement getParent() { - return mParent; - } - - public boolean isRoot() { - // (Virtual) Root element has no parent... - return (mParent == null); - } - - /** - * @return String presentation of the fully-qualified name, in - * "prefix:localName" format (no URI). Useful for error and - * debugging messages. - */ - public String getNameDesc() { - if(mElement != null) { - return mElement.getLocalName(); - } - return "#error"; // unexpected case - } - - /* - /////////////////////////////////////////////////////////// - // Public API, mutators - /////////////////////////////////////////////////////////// - */ - - public void setDefaultNsUri(String uri) { - mDefaultNsURI = uri; - mDefaultNsSet = true; - } - - protected void setRootNsContext(NamespaceContext ctxt) - { - mRootNsContext = ctxt; - /* Let's also see if we have an active default ns mapping: - * (provided it hasn't yet explicitly been set for this element) - */ - if (!mDefaultNsSet) { - String defURI = ctxt.getNamespaceURI(""); - if (defURI != null && defURI.length() > 0) { - mDefaultNsURI = defURI; - } - } - } - - /* - /////////////////////////////////////////////////////////// - // Public API, DOM manipulation - /////////////////////////////////////////////////////////// - */ - - protected void appendNode(Node n) - { - if (mRootNode != null) { - mRootNode.appendChild(n); - } else { - mElement.appendChild(n); - } - } - - protected void addAttribute(String pname, String value) - { - mElement.setAttribute(pname, value); - } - - protected void addAttribute(String uri, String qname, String value) - { - mElement.setAttributeNS(uri, qname, value); - } - - public void appendChild(Node n) { - mElement.appendChild(n); - } -} diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/dom/WstxDOMWrappingReader.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/dom/WstxDOMWrappingReader.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/dom/WstxDOMWrappingReader.java 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/dom/WstxDOMWrappingReader.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,91 +0,0 @@ -package com.ctc.wstx.dom; - -import java.util.Collections; - -import javax.xml.stream.*; -import javax.xml.transform.dom.DOMSource; - -//import org.codehaus.stax2.XMLInputFactory2; -import org.codehaus.stax2.ri.dom.DOMWrappingReader; - -import com.ctc.wstx.api.ReaderConfig; -import com.ctc.wstx.exc.WstxParsingException; - -public class WstxDOMWrappingReader - extends DOMWrappingReader -{ - protected final ReaderConfig mConfig; - - /* - /////////////////////////////////////////////////// - // Life-cycle - /////////////////////////////////////////////////// - */ - - protected WstxDOMWrappingReader(DOMSource src, ReaderConfig cfg) - throws XMLStreamException - { - super(src, cfg.willSupportNamespaces(), cfg.willCoalesceText()); - mConfig = cfg; - // [WSTX-162]: allow enabling/disabling name/ns intern()ing - if (cfg.hasInternNamesBeenEnabled()) { - setInternNames(true); - } - if (cfg.hasInternNsURIsBeenEnabled()) { - setInternNsURIs(true); - } - } - - public static WstxDOMWrappingReader createFrom(DOMSource src, ReaderConfig cfg) - throws XMLStreamException - { - return new WstxDOMWrappingReader(src, cfg); - } - - /* - /////////////////////////////////////////////////// - // Defined/Overridden config methods - /////////////////////////////////////////////////// - */ - - public boolean isPropertySupported(String name) - { - // !!! TBI: not all these properties are really supported - return mConfig.isPropertySupported(name); - } - - public Object getProperty(String name) - { - if (name.equals("javax.xml.stream.entities")) { - // !!! TBI - return Collections.EMPTY_LIST; - } - if (name.equals("javax.xml.stream.notations")) { - // !!! TBI - return Collections.EMPTY_LIST; - } - return mConfig.getProperty(name); - } - - public boolean setProperty(String name, Object value) - { - // Basic config accessor works just fine... - return mConfig.setProperty(name, value); - } - - /* - /////////////////////////////////////////////////// - // Defined/Overridden error reporting - /////////////////////////////////////////////////// - */ - - // @Override - protected void throwStreamException(String msg, Location loc) - throws XMLStreamException - { - if (loc == null) { - throw new WstxParsingException(msg); - } - throw new WstxParsingException(msg, loc); - } -} diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/dom/WstxDOMWrappingWriter.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/dom/WstxDOMWrappingWriter.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/dom/WstxDOMWrappingWriter.java 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/dom/WstxDOMWrappingWriter.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,744 +0,0 @@ -package com.ctc.wstx.dom; - -import java.util.*; - -import javax.xml.XMLConstants; -import javax.xml.namespace.*; -import javax.xml.stream.*; -import javax.xml.transform.dom.DOMResult; - -import org.w3c.dom.*; - -import org.codehaus.stax2.ri.EmptyNamespaceContext; -import org.codehaus.stax2.ri.dom.DOMWrappingWriter; - -import com.ctc.wstx.api.WriterConfig; -import com.ctc.wstx.cfg.ErrorConsts; -import com.ctc.wstx.sw.OutputElementBase; - -/* TODO: - * - * - validator interface implementation - */ - -/** - * This is an adapter class that allows building a DOM tree using - * {@link XMLStreamWriter} interface. - *

- * Note that the implementation is only to be used for use with - * javax.xml.transform.dom.DOMResult. - *

- * Some notes regarding missing/incomplete functionality: - *

    - *
  • Validation functionality not implemented - *
  • - *
- * - * @author Tatu Saloranta - * @author Dan Diephouse - */ -public class WstxDOMWrappingWriter - extends DOMWrappingWriter -{ - /* - /////////////////////////////////////////////////////////// - // Constants - /////////////////////////////////////////////////////////// - */ - - final protected static String ERR_NSDECL_WRONG_STATE = - "Trying to write a namespace declaration when there is no open start element."; - - /* - /////////////////////////////////////////////////////////// - // Configuration - /////////////////////////////////////////////////////////// - */ - - protected final WriterConfig mConfig; - - /* - /////////////////////////////////////////////////////////// - // State - /////////////////////////////////////////////////////////// - */ - - /** - * This element is the current context element, under which - * all other nodes are added, until matching end element - * is output. Null outside of the main element tree. - *

- * Note: explicit empty element (written using - * writeEmptyElement) will never become - * current element. - */ - protected DOMOutputElement mCurrElem; - - /** - * This element is non-null right after a call to - * either writeStartElement and - * writeEmptyElement, and can be used to - * add attributes and namespace declarations. - *

- * Note: while this is often the same as {@link #mCurrElem}, - * it's not always. Specifically, an empty element (written - * explicitly using writeEmptyElement) will - * become open element but NOT current element. Conversely, - * regular elements will remain current element when - * non elements are written (text, comments, PI), but - * not the open element. - */ - protected DOMOutputElement mOpenElement; - - /** - * for NsRepairing mode - */ - protected int[] mAutoNsSeq; - protected String mSuggestedDefNs = null; - protected String mAutomaticNsPrefix; - - /** - * Map that contains URI-to-prefix entries that point out suggested - * prefixes for URIs. These are populated by calls to - * {@link #setPrefix}, and they are only used as hints for binding; - * if there are conflicts, repairing writer can just use some other - * prefix. - */ - HashMap mSuggestedPrefixes = null; - - /* - /////////////////////////////////////////////////////////// - // Life-cycle - /////////////////////////////////////////////////////////// - */ - - private WstxDOMWrappingWriter(WriterConfig cfg, Node treeRoot) - throws XMLStreamException - { - super(treeRoot, cfg.willSupportNamespaces(), cfg.automaticNamespacesEnabled()); - mConfig = cfg; - mAutoNsSeq = null; - mAutomaticNsPrefix = mNsRepairing ? mConfig.getAutomaticNsPrefix() : null; - - /* Ok; we need a document node; or an element node; or a document - * fragment node. - */ - switch (treeRoot.getNodeType()) { - case Node.DOCUMENT_NODE: - case Node.DOCUMENT_FRAGMENT_NODE: - // both are ok, but no current element - mCurrElem = DOMOutputElement.createRoot(treeRoot); - mOpenElement = null; - break; - - case Node.ELEMENT_NODE: // can make sub-tree... ok - { - // still need a virtual root node as parent - DOMOutputElement root = DOMOutputElement.createRoot(treeRoot); - Element elem = (Element) treeRoot; - mOpenElement = mCurrElem = root.createChild(elem); - } - break; - - default: // other Nodes not usable - throw new XMLStreamException("Can not create an XMLStreamWriter for a DOM node of type "+treeRoot.getClass()); - } - } - - public static WstxDOMWrappingWriter createFrom(WriterConfig cfg, DOMResult dst) - throws XMLStreamException - { - Node rootNode = dst.getNode(); - return new WstxDOMWrappingWriter(cfg, rootNode); - } - - /* - /////////////////////////////////////////////////////////// - // XMLStreamWriter API (Stax 1.0) - /////////////////////////////////////////////////////////// - */ - - //public void close() { } - //public void flush() { } - - - public NamespaceContext getNamespaceContext() - { - if (!mNsAware) { - return EmptyNamespaceContext.getInstance(); - } - return mCurrElem; - } - - public String getPrefix(String uri) - { - if (!mNsAware) { - return null; - } - if (mNsContext != null) { - String prefix = mNsContext.getPrefix(uri); - if (prefix != null) { - return prefix; - } - } - return mCurrElem.getPrefix(uri); - } - - public Object getProperty(String name) { - return mConfig.getProperty(name); - } - - public void setDefaultNamespace(String uri) { - mSuggestedDefNs = (uri == null || uri.length() == 0) ? null : uri; - } - - //public void setNamespaceContext(NamespaceContext context) - - public void setPrefix(String prefix, String uri) - throws XMLStreamException - { - if (prefix == null) { - throw new NullPointerException("Can not pass null 'prefix' value"); - } - // Are we actually trying to set the default namespace? - if (prefix.length() == 0) { - setDefaultNamespace(uri); - return; - } - if (uri == null) { - throw new NullPointerException("Can not pass null 'uri' value"); - } - - /* Let's verify that xml/xmlns are never (mis)declared; as - * mandated by XML NS specification - */ - { - if (prefix.equals("xml")) { - if (!uri.equals(XMLConstants.XML_NS_URI)) { - throwOutputError(ErrorConsts.ERR_NS_REDECL_XML, uri); - } - } else if (prefix.equals("xmlns")) { // prefix "xmlns" - if (!uri.equals(XMLConstants.XMLNS_ATTRIBUTE_NS_URI)) { - throwOutputError(ErrorConsts.ERR_NS_REDECL_XMLNS, uri); - } - // At any rate; we are NOT to output it - return; - } else { - // Neither of prefixes.. but how about URIs? - if (uri.equals(XMLConstants.XML_NS_URI)) { - throwOutputError(ErrorConsts.ERR_NS_REDECL_XML_URI, prefix); - } else if (uri.equals(XMLConstants.XMLNS_ATTRIBUTE_NS_URI)) { - throwOutputError(ErrorConsts.ERR_NS_REDECL_XMLNS_URI, prefix); - } - } - } - - if (mSuggestedPrefixes == null) { - mSuggestedPrefixes = new HashMap(16); - } - mSuggestedPrefixes.put(uri, prefix); - - } - - public void writeAttribute(String localName, String value) - throws XMLStreamException - { - outputAttribute(null, null, localName, value); - } - - public void writeAttribute(String nsURI, String localName, String value) - throws XMLStreamException - { - outputAttribute(nsURI, null, localName, value); - } - - public void writeAttribute(String prefix, String nsURI, String localName, String value) - throws XMLStreamException - { - outputAttribute(nsURI, prefix, localName, value); - } - - //public void writeCData(String data) - //public void writeCharacters(char[] text, int start, int len) - //public void writeCharacters(String text) - //public void writeComment(String data) - - public void writeDefaultNamespace(String nsURI) - { - if (mOpenElement == null) { - throw new IllegalStateException("No currently open START_ELEMENT, cannot write attribute"); - } - setDefaultNamespace(nsURI); - mOpenElement.addAttribute(XMLConstants.XMLNS_ATTRIBUTE_NS_URI, "xmlns", nsURI); - } - - //public void writeDTD(String dtd) - - public void writeEmptyElement(String localName) - throws XMLStreamException - { - writeEmptyElement(null, localName); - } - - public void writeEmptyElement(String nsURI, String localName) - throws XMLStreamException - { - // First things first: must - - /* Note: can not just call writeStartElement(), since this - * element will only become the open elem, but not a parent elem - */ - createStartElem(nsURI, null, localName, true); - } - - public void writeEmptyElement(String prefix, String localName, String nsURI) - throws XMLStreamException - { - if (prefix == null) { // passing null would mean "dont care", if repairing - prefix = ""; - } - createStartElem(nsURI, prefix, localName, true); - } - - public void writeEndDocument() - { - mCurrElem = mOpenElement = null; - } - - public void writeEndElement() - { - // Simple, just need to traverse up... if we can - if (mCurrElem == null || mCurrElem.isRoot()) { - throw new IllegalStateException("No open start element to close"); - } - mOpenElement = null; // just in case it was open - mCurrElem = mCurrElem.getParent(); - } - - //public void writeEntityRef(String name) - - public void writeNamespace(String prefix, String nsURI) throws XMLStreamException - { - if (prefix == null || prefix.length() == 0) { - writeDefaultNamespace(nsURI); - return; - } - if (!mNsAware) { - throwOutputError("Can not write namespaces with non-namespace writer."); - } - outputAttribute(XMLConstants.XMLNS_ATTRIBUTE_NS_URI, "xmlns", prefix, nsURI); - mCurrElem.addPrefix(prefix, nsURI); - } - - //public void writeProcessingInstruction(String target) - //public void writeProcessingInstruction(String target, String data) - - //public void writeStartDocument() - //public void writeStartDocument(String version) - //public void writeStartDocument(String encoding, String version) - - public void writeStartElement(String localName) - throws XMLStreamException - { - writeStartElement(null, localName); - } - - public void writeStartElement(String nsURI, String localName) - throws XMLStreamException - { - createStartElem(nsURI, null, localName, false); - } - - public void writeStartElement(String prefix, String localName, String nsURI) - throws XMLStreamException - { - createStartElem(nsURI, prefix, localName, false); - } - - /* - /////////////////////////////////////////////////////////// - // XMLStreamWriter2 API (Stax2 v3.0): - // additional accessors - /////////////////////////////////////////////////////////// - */ - - //public XMLStreamLocation2 getLocation() - //public String getEncoding() - - public boolean isPropertySupported(String name) - { - // !!! TBI: not all these properties are really supported - return mConfig.isPropertySupported(name); - } - - public boolean setProperty(String name, Object value) - { - /* Note: can not call local method, since it'll return false for - * recognized but non-mutable properties - */ - return mConfig.setProperty(name, value); - } - - /* - /////////////////////////////////////////////////////////// - // XMLStreamWriter2 API (Stax2 v2.0): - // extended write methods - /////////////////////////////////////////////////////////// - */ - - //public void writeCData(char[] text, int start, int len) - - public void writeDTD(String rootName, String systemId, String publicId, - String internalSubset) - throws XMLStreamException - { - /* Alas: although we can create a DocumentType object, there - * doesn't seem to be a way to attach it in DOM-2! - */ - if (mCurrElem != null) { - throw new IllegalStateException("Operation only allowed to the document before adding root element"); - } - reportUnsupported("writeDTD()"); - } - - //public void writeFullEndElement() throws XMLStreamException - - //public void writeSpace(char[] text, int start, int len) - //public void writeSpace(String text) - - - //public void writeStartDocument(String version, String encoding, boolean standAlone) - - /* - /////////////////////////////////////////////////////////// - // XMLStreamWriter2 API (Stax2 v2.0): validation - /////////////////////////////////////////////////////////// - */ - - //public XMLValidator validateAgainst(XMLValidationSchema schema) - //public XMLValidator stopValidatingAgainst(XMLValidationSchema schema) - //public XMLValidator stopValidatingAgainst(XMLValidator validator) - //public ValidationProblemHandler setValidationProblemHandler(ValidationProblemHandler h) - - /* - /////////////////////////////////////////////////////////// - // Impls of abstract methods from base class - /////////////////////////////////////////////////////////// - */ - - protected void appendLeaf(Node n) - throws IllegalStateException - { - mCurrElem.appendNode(n); - mOpenElement = null; - } - - /* - /////////////////////////////////////////////////////////// - // Internal methods - /////////////////////////////////////////////////////////// - */ - - /* Note: copied from regular RepairingNsStreamWriter#writeStartOrEmpty - * (and its non-repairing counterpart). - */ - - /** - * Method called by all start element write methods. - * - * @param nsURI Namespace URI to use: null and empty String denote 'no namespace' - */ - protected void createStartElem(String nsURI, String prefix, String localName, boolean isEmpty) - throws XMLStreamException - { - DOMOutputElement elem; - - if (!mNsAware) { - if(nsURI != null && nsURI.length() > 0) { - throwOutputError("Can not specify non-empty uri/prefix in non-namespace mode"); - } - elem = mCurrElem.createAndAttachChild(mDocument.createElement(localName)); - } else { - if (mNsRepairing) { - String actPrefix = validateElemPrefix(prefix, nsURI, mCurrElem); - if (actPrefix != null) { // fine, an existing binding we can use: - if (actPrefix.length() != 0) { - elem = mCurrElem.createAndAttachChild(mDocument.createElementNS(nsURI, actPrefix+":"+localName)); - } else { - elem = mCurrElem.createAndAttachChild(mDocument.createElementNS(nsURI, localName)); - } - } else { // nah, need to create a new binding... - /* Need to ensure that we'll pass "" as prefix, not null, - * so it is understood as "I want to use the default NS", - * not as "whatever prefix, I don't care" - */ - if (prefix == null) { - prefix = ""; - } - actPrefix = generateElemPrefix(prefix, nsURI, mCurrElem); - boolean hasPrefix = (actPrefix.length() != 0); - if (hasPrefix) { - localName = actPrefix + ":" + localName; - } - elem = mCurrElem.createAndAttachChild(mDocument.createElementNS(nsURI, localName)); - /* Hmmh. writeNamespace method requires open element - * to be defined. So we'll need to set it first - * (will be set again at a later point -- would be - * good to refactor this method into separate - * sub-classes or so) - */ - mOpenElement = elem; - // Need to add new ns declaration as well - if (hasPrefix) { - writeNamespace(actPrefix, nsURI); - elem.addPrefix(actPrefix, nsURI); - } else { - writeDefaultNamespace(nsURI); - elem.setDefaultNsUri(nsURI); - } - } - } else { - /* Non-repairing; if non-null prefix (including "" to - * indicate "no prefix") passed, use as is, otherwise - * try to locate the prefix if got namespace. - */ - if (prefix == null && nsURI != null && nsURI.length() > 0) { - if (nsURI == null) { - nsURI = ""; - } - prefix = (mSuggestedPrefixes == null) ? null : (String) mSuggestedPrefixes.get(nsURI); - if (prefix == null) { - throwOutputError("Can not find prefix for namespace \""+nsURI+"\""); - } - } - if (prefix != null && prefix.length() != 0) { - localName = prefix + ":" +localName; - } - elem = mCurrElem.createAndAttachChild(mDocument.createElementNS(nsURI, localName)); - } - } - /* Got the element; need to make it the open element, and - * if it's not an (explicit) empty element, current element as well - */ - mOpenElement = elem; - if (!isEmpty) { - mCurrElem = elem; - } - } - - protected void outputAttribute(String nsURI, String prefix, String localName, String value) - throws XMLStreamException - { - if (mOpenElement == null) { - throw new IllegalStateException("No currently open START_ELEMENT, cannot write attribute"); - } - - if (mNsAware) { - if (mNsRepairing) { - prefix = findOrCreateAttrPrefix(prefix, nsURI, mOpenElement); - } - if (prefix != null && prefix.length() > 0) { - localName = prefix + ":" + localName; - } - mOpenElement.addAttribute(nsURI, localName, value); - } else { // non-ns, simple - if (prefix != null && prefix.length() > 0) { - localName = prefix + ":" + localName; - } - mOpenElement.addAttribute(localName, value); - } - } - - private final String validateElemPrefix(String prefix, String nsURI, - DOMOutputElement elem) - throws XMLStreamException - { - /* 06-Feb-2005, TSa: Special care needs to be taken for the - * "empty" (or missing) namespace: - * (see comments from findOrCreatePrefix()) - */ - if (nsURI == null || nsURI.length() == 0) { - String currURL = elem.getDefaultNsUri(); - if (currURL == null || currURL.length() == 0) { - // Ok, good: - return ""; - } - // Nope, needs to be re-bound: - return null; - } - - int status = elem.isPrefixValid(prefix, nsURI, true); - if (status == DOMOutputElement.PREFIX_OK) { - return prefix; - } - return null; - } - - /* - /////////////////////////////////////////////////////////// - // Internal methods - /////////////////////////////////////////////////////////// - */ - - /** - * Method called to find an existing prefix for the given namespace, - * if any exists in the scope. If one is found, it's returned (including - * "" for the current default namespace); if not, null is returned. - * - * @param nsURI URI of namespace for which we need a prefix - */ - protected final String findElemPrefix(String nsURI, DOMOutputElement elem) - throws XMLStreamException - { - /* Special case: empty NS URI can only be bound to the empty - * prefix... - */ - if (nsURI == null || nsURI.length() == 0) { - String currDefNsURI = elem.getDefaultNsUri(); - if (currDefNsURI != null && currDefNsURI.length() > 0) { - // Nope; won't do... has to be re-bound, but not here: - return null; - } - return ""; - } - return mCurrElem.getPrefix(nsURI); - } - - - /** - * Method called after {@link #findElemPrefix} has returned null, - * to create and bind a namespace mapping for specified namespace. - */ - protected final String generateElemPrefix(String suggPrefix, String nsURI, - DOMOutputElement elem) - throws XMLStreamException - { - /* Ok... now, since we do not have an existing mapping, let's - * see if we have a preferred prefix to use. - */ - /* Except if we need the empty namespace... that can only be - * bound to the empty prefix: - */ - if (nsURI == null || nsURI.length() == 0) { - return ""; - } - - /* Ok; with elements this is easy: the preferred prefix can - * ALWAYS be used, since it can mask preceding bindings: - */ - if (suggPrefix == null) { - // caller wants this URI to map as the default namespace? - if (mSuggestedDefNs != null && mSuggestedDefNs.equals(nsURI)) { - suggPrefix = ""; - } else { - suggPrefix = (mSuggestedPrefixes == null) ? null: - (String) mSuggestedPrefixes.get(nsURI); - if (suggPrefix == null) { - /* 16-Oct-2005, TSa: We have 2 choices here, essentially; - * could make elements always try to override the def - * ns... or can just generate new one. Let's do latter - * for now. - */ - if (mAutoNsSeq == null) { - mAutoNsSeq = new int[1]; - mAutoNsSeq[0] = 1; - } - suggPrefix = elem.generateMapping(mAutomaticNsPrefix, nsURI, - mAutoNsSeq); - } - } - } - - // Ok; let's let the caller deal with bindings - return suggPrefix; - } - - - /** - * Method called to somehow find a prefix for given namespace, to be - * used for a new start element; either use an existing one, or - * generate a new one. If a new mapping needs to be generated, - * it will also be automatically bound, and necessary namespace - * declaration output. - * - * @param suggPrefix Suggested prefix to bind, if any; may be null - * to indicate "no preference" - * @param nsURI URI of namespace for which we need a prefix - * @param elem Currently open start element, on which the attribute - * will be added. - */ - protected final String findOrCreateAttrPrefix(String suggPrefix, String nsURI, - DOMOutputElement elem) - throws XMLStreamException - { - if (nsURI == null || nsURI.length() == 0) { - /* Attributes never use the default namespace; missing - * prefix always leads to the empty ns... so nothing - * special is needed here. - */ - return null; - } - // Maybe the suggested prefix is properly bound? - if (suggPrefix != null) { - int status = elem.isPrefixValid(suggPrefix, nsURI, false); - if (status == OutputElementBase.PREFIX_OK) { - return suggPrefix; - } - /* Otherwise, if the prefix is unbound, let's just bind - * it -- if caller specified a prefix, it probably prefers - * binding that prefix even if another prefix already existed? - * The remaining case (already bound to another URI) we don't - * want to touch, at least not yet: it may or not be safe - * to change binding, so let's just not try it. - */ - if (status == OutputElementBase.PREFIX_UNBOUND) { - elem.addPrefix(suggPrefix, nsURI); - writeNamespace(suggPrefix, nsURI); - return suggPrefix; - } - } - - // If not, perhaps there's another existing binding available? - String prefix = elem.getExplicitPrefix(nsURI); - if (prefix != null) { // already had a mapping for the URI... cool. - return prefix; - } - - /* Nope, need to create one. First, let's see if there's a - * preference... - */ - if (suggPrefix != null) { - prefix = suggPrefix; - } else if (mSuggestedPrefixes != null) { - prefix = (String) mSuggestedPrefixes.get(nsURI); - // note: def ns is never added to suggested prefix map - } - - if (prefix != null) { - /* Can not use default namespace for attributes. - * Also, re-binding is tricky for attributes; can't - * re-bind anything that's bound on this scope... or - * used in this scope. So, to simplify life, let's not - * re-bind anything for attributes. - */ - if (prefix.length() == 0 - || (elem.getNamespaceURI(prefix) != null)) { - prefix = null; - } - } - - if (prefix == null) { - if (mAutoNsSeq == null) { - mAutoNsSeq = new int[1]; - mAutoNsSeq[0] = 1; - } - prefix = mCurrElem.generateMapping(mAutomaticNsPrefix, nsURI, - mAutoNsSeq); - } - - // Ok; so far so good: let's now bind and output the namespace: - elem.addPrefix(prefix, nsURI); - writeNamespace(prefix, nsURI); - return prefix; - } -} diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/dtd/ChoiceContentSpec.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/dtd/ChoiceContentSpec.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/dtd/ChoiceContentSpec.java 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/dtd/ChoiceContentSpec.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,240 +0,0 @@ -package com.ctc.wstx.dtd; - -import java.util.*; - -import com.ctc.wstx.util.ExceptionUtil; -import com.ctc.wstx.util.PrefixedName; - -/** - * Content specification that defines content model that has - * multiple alternative elements; including mixed content model. - */ -public class ChoiceContentSpec - extends ContentSpec -{ - final boolean mNsAware; - - /** - * Whether this is a mixed content model; mostly affects String - * representation - */ - final boolean mHasMixed; - - final ContentSpec[] mContentSpecs; - - /* - /////////////////////////////////////////////////// - // Life-cycle - /////////////////////////////////////////////////// - */ - - private ChoiceContentSpec(boolean nsAware, char arity, boolean mixed, - ContentSpec[] specs) - { - super(arity); - mNsAware = nsAware; - mHasMixed = mixed; - mContentSpecs = specs; - } - - private ChoiceContentSpec(boolean nsAware, char arity, boolean mixed, Collection specs) - { - super(arity); - mNsAware = nsAware; - mHasMixed = mixed; - mContentSpecs = new ContentSpec[specs.size()]; - specs.toArray(mContentSpecs); - } - - public static ChoiceContentSpec constructChoice(boolean nsAware, char arity, - Collection specs) - { - return new ChoiceContentSpec(nsAware, arity, false, specs); - } - - public static ChoiceContentSpec constructMixed(boolean nsAware, Collection specs) - { - return new ChoiceContentSpec(nsAware, '*', true, specs); - } - - /* - /////////////////////////////////////////////////// - // Public API - /////////////////////////////////////////////////// - */ - - public StructValidator getSimpleValidator() - { - /* Can we create a simple validator? Yes, if the sub-specs are - * all simple (leaves == element tokens with no arity modifier); - * this is always true for mixed. - */ - ContentSpec[] specs = mContentSpecs; - int len = specs.length; - int i; - - if (mHasMixed) { - i = len; - } else { - i = 0; - for (; i < len; ++i) { - if (!specs[i].isLeaf()) { - break; - } - } - } - - if (i == len) { // all leaves, kewl - PrefixedNameSet keyset = namesetFromSpecs(mNsAware, specs); - return new Validator(mArity, keyset); - } - - // Nah, need a DFA... - return null; - } - - public ModelNode rewrite() - { - // First, need to convert sub-specs: - ContentSpec[] specs = mContentSpecs; - int len = specs.length; - ModelNode[] models = new ModelNode[len]; - for (int i = 0; i < len; ++i) { - models[i] = specs[i].rewrite(); - } - ChoiceModel model = new ChoiceModel(models); - - // and then resolve arity modifiers, if necessary: - if (mArity == '*') { - return new StarModel(model); - } - if (mArity == '?') { - return new OptionalModel(model); - } - if (mArity == '+') { - return new ConcatModel(model, - new StarModel(model.cloneModel())); - } - return model; - } - - public String toString() - { - StringBuffer sb = new StringBuffer(); - - if (mHasMixed) { - sb.append("(#PCDATA | "); - } else { - sb.append('('); - } - for (int i = 0; i < mContentSpecs.length; ++i) { - if (i > 0) { - sb.append(" | "); - } - sb.append(mContentSpecs[i].toString()); - } - sb.append(')'); - - if (mArity != ' ') { - sb.append(mArity); - } - return sb.toString(); - } - - /* - /////////////////////////////////////////////////// - // Internal methods - /////////////////////////////////////////////////// - */ - - /* - /////////////////////////////////////////////////// - // Package methods - /////////////////////////////////////////////////// - */ - - protected static PrefixedNameSet namesetFromSpecs(boolean nsAware, ContentSpec[] specs) - { - int len = specs.length; - PrefixedName[] nameArray = new PrefixedName[len]; - for (int i = 0; i < len; ++i) { - nameArray[i] = ((TokenContentSpec)specs[i]).getName(); - } - - if (len < 5) { // 4 or fewer elements -> small - return new SmallPrefixedNameSet(nsAware, nameArray); - } - return new LargePrefixedNameSet(nsAware, nameArray); - } - - /* - /////////////////////////////////////////////////// - // Validator class that can be used for simple - // choices (including mixed content) - /////////////////////////////////////////////////// - */ - - final static class Validator - extends StructValidator - { - final char mArity; - final PrefixedNameSet mNames; - - int mCount = 0; - - public Validator(char arity, PrefixedNameSet names) - { - mArity = arity; - mNames = names; - } - - /** - * Rules for reuse are simple: if we can have any number of - * repetitions, we can just use a shared root instance. Although - * its count variable will get updated this doesn't really - * matter as it won't be used. Otherwise a new instance has to - * be created always, to keep track of instance counts. - */ - public StructValidator newInstance() { - return (mArity == '*') ? this : new Validator(mArity, mNames); - } - - public String tryToValidate(PrefixedName elemName) - { - if (!mNames.contains(elemName)) { - if (mNames.hasMultiple()) { - return "Expected one of ("+mNames.toString(" | ")+")"; - } - return "Expected <"+mNames.toString("")+">"; - } - if (++mCount > 1 && (mArity == '?' || mArity == ' ')) { - if (mNames.hasMultiple()) { - return "Expected $END (already had one of [" - +mNames.toString(" | ")+"]"; - } - return "Expected $END (already had one <" - +mNames.toString("")+">]"; - } - return null; - } - - public String fullyValid() - { - switch (mArity) { - case '*': - case '?': - return null; - case '+': // need at least one (and multiples checked earlier) - case ' ': - if (mCount > 0) { - return null; - } - return "Expected "+(mArity == '+' ? "at least" : "") - +" one of elements ("+mNames+")"; - } - // should never happen: - ExceptionUtil.throwGenericInternal(); - return null; - } - } -} diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/dtd/ChoiceModel.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/dtd/ChoiceModel.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/dtd/ChoiceModel.java 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/dtd/ChoiceModel.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,110 +0,0 @@ -package com.ctc.wstx.dtd; - -import java.util.*; - -/** - * Model class that encapsulates set of sub-models, of which one (and only - * one) needs to be matched. - */ -public class ChoiceModel - extends ModelNode -{ - final ModelNode[] mSubModels; - - boolean mNullable = false; - - BitSet mFirstPos, mLastPos; - - /* - /////////////////////////////////////////////////// - // Life-cycle - /////////////////////////////////////////////////// - */ - - protected ChoiceModel(ModelNode[] subModels) - { - super(); - mSubModels = subModels; - boolean nullable = false; - for (int i = 0, len = subModels.length; i < len; ++i) { - if (subModels[i].isNullable()) { - nullable = true; - break; - } - } - mNullable = nullable; - } - - /* - /////////////////////////////////////////////////// - // Public API - /////////////////////////////////////////////////// - */ - - public String toString() - { - StringBuffer sb = new StringBuffer(); - for (int i = 0; i < mSubModels.length; ++i) { - if (i > 0) { - sb.append(" | "); - } - sb.append(mSubModels[i].toString()); - } - sb.append(')'); - return sb.toString(); - } - - /** - * Method that has to create a deep copy of the model, without - * sharing any of existing Objects. - */ - public ModelNode cloneModel() - { - int len = mSubModels.length; - ModelNode[] newModels = new ModelNode[len]; - for (int i = 0; i < len; ++i) { - newModels[i] = mSubModels[i].cloneModel(); - } - return new ChoiceModel(newModels); - } - - public boolean isNullable() { - return mNullable; - } - - public void indexTokens(List tokens) - { - // First, let's ask sub-models to calc their settings - for (int i = 0, len = mSubModels.length; i < len; ++i) { - mSubModels[i].indexTokens(tokens); - } - } - - public void addFirstPos(BitSet firstPos) { - if (mFirstPos == null) { - mFirstPos = new BitSet(); - for (int i = 0, len = mSubModels.length; i < len; ++i) { - mSubModels[i].addFirstPos(mFirstPos); - } - } - firstPos.or(mFirstPos); - } - - public void addLastPos(BitSet lastPos) { - if (mLastPos == null) { - mLastPos = new BitSet(); - for (int i = 0, len = mSubModels.length; i < len; ++i) { - mSubModels[i].addLastPos(mLastPos); - } - } - lastPos.or(mLastPos); - } - - public void calcFollowPos(BitSet[] followPosSets) - { - // need to let child models do their stuff: - for (int i = 0, len = mSubModels.length; i < len; ++i) { - mSubModels[i].calcFollowPos(followPosSets); - } - } -} diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/dtd/ConcatModel.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/dtd/ConcatModel.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/dtd/ConcatModel.java 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/dtd/ConcatModel.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,114 +0,0 @@ -package com.ctc.wstx.dtd; - -import java.util.*; - -/** - * Model class that represents sequence of 2 sub-models, needed to be - * matched in the order. - */ -public class ConcatModel - extends ModelNode -{ - ModelNode mLeftModel; - ModelNode mRightModel; - - final boolean mNullable; - - BitSet mFirstPos, mLastPos; - - /* - /////////////////////////////////////////////////// - // Life-cycle - /////////////////////////////////////////////////// - */ - - public ConcatModel(ModelNode left, ModelNode right) - { - super(); - mLeftModel = left; - mRightModel = right; - mNullable = mLeftModel.isNullable() && mRightModel.isNullable(); - } - - /* - /////////////////////////////////////////////////// - // Public API - /////////////////////////////////////////////////// - */ - - /** - * Method that has to create a deep copy of the model, without - * sharing any of existing Objects. - */ - public ModelNode cloneModel() { - return new ConcatModel(mLeftModel.cloneModel(), mRightModel.cloneModel()); - } - - public boolean isNullable() { - return mNullable; - } - - public void indexTokens(List tokens) - { - mLeftModel.indexTokens(tokens); - mRightModel.indexTokens(tokens); - } - - public void addFirstPos(BitSet pos) { - if (mFirstPos == null) { - mFirstPos = new BitSet(); - mLeftModel.addFirstPos(mFirstPos); - if (mLeftModel.isNullable()) { - mRightModel.addFirstPos(mFirstPos); - } - } - pos.or(mFirstPos); - } - - public void addLastPos(BitSet pos) { - if (mLastPos == null) { - mLastPos = new BitSet(); - mRightModel.addLastPos(mLastPos); - if (mRightModel.isNullable()) { - mLeftModel.addLastPos(mLastPos); - } - } - pos.or(mLastPos); - } - - public void calcFollowPos(BitSet[] followPosSets) - { - // Let's let sub-models do what they need to do - mLeftModel.calcFollowPos(followPosSets); - mRightModel.calcFollowPos(followPosSets); - - /* And then we can calculate follower sets between left and - * right sub models; so that left model's last position entries - * have right model's first position entries included - */ - BitSet foll = new BitSet(); - mRightModel.addFirstPos(foll); - - BitSet toAddTo = new BitSet(); - mLeftModel.addLastPos(toAddTo); - - int ix = 0; // need to/can skip the null entry (index 0) - while ((ix = toAddTo.nextSetBit(ix+1)) >= 0) { - /* Ok; so token at this index needs to have follow positions - * added... - */ - followPosSets[ix].or(foll); - } - } - - public String toString() - { - StringBuffer sb = new StringBuffer(); - sb.append('('); - sb.append(mLeftModel.toString()); - sb.append(", "); - sb.append(mRightModel.toString()); - sb.append(')'); - return sb.toString(); - } -} diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/dtd/ContentSpec.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/dtd/ContentSpec.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/dtd/ContentSpec.java 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/dtd/ContentSpec.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,68 +0,0 @@ -/* Woodstox XML processor - * - * Copyright (c) 2004 Tatu Saloranta, tatu.saloranta@iki.fi - * - * Licensed under the License specified in the file LICENSE which is - * included with the source code. - * You may not use this file except in compliance with the License. - * - * 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 com.ctc.wstx.dtd; - -/** - * Abstract base class for classes that contain parts of a content - * specification of an element defined in DTD. They are created - * by {@link FullDTDReader} when parsing an DTD subset, and they - * will be used for constructing actual validators for the element - * content. - */ -public abstract class ContentSpec -{ - protected char mArity; - - /* - /////////////////////////////////////////////////// - // Life-cycle - /////////////////////////////////////////////////// - */ - - public ContentSpec(char arity) { - mArity = arity; - } - - /* - /////////////////////////////////////////////////// - // Public API - /////////////////////////////////////////////////// - */ - - public final char getArity() { return mArity; } - - public final void setArity(char c) { mArity = c; } - - public boolean isLeaf() { return false; } - - /** - * Method called by input element stack to get validator for - * this content specification, if this specification is simple - * enough not to need full DFA-based validator. - * - * @return Simple content model validator, if one can be directly - * constructed, or null to indicate that a DFA needs to be - * created. - */ - public abstract StructValidator getSimpleValidator(); - - /** - * Method called as the first part of DFA construction, if necessary; - * will usually create simpler {@link ModelNode} instances that will - * match definition this instance contains. - */ - public abstract ModelNode rewrite(); -} diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/dtd/DefaultAttrValue.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/dtd/DefaultAttrValue.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/dtd/DefaultAttrValue.java 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/dtd/DefaultAttrValue.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,218 +0,0 @@ -/* Woodstox XML processor - * - * Copyright (c) 2004- Tatu Saloranta, tatu.saloranta@iki.fi - * - * Licensed under the License specified in the file LICENSE which is - * included with the source code. - * You may not use this file except in compliance with the License. - * - * 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 com.ctc.wstx.dtd; - -import java.text.MessageFormat; - -import javax.xml.stream.Location; -import javax.xml.stream.XMLStreamException; - -import org.codehaus.stax2.validation.ValidationContext; -import org.codehaus.stax2.validation.XMLValidationProblem; -import org.codehaus.stax2.validation.XMLValidator; - -import com.ctc.wstx.cfg.ErrorConsts; - -/** - * Simple container class used to contain information about the default - * value for an attribute. Although for most use cases a simple String - * would suffice, there are cases where additional information is needed - * (especially status of 'broken' default values, which only need to be - * reported should the default value be needed). - */ -public final class DefaultAttrValue -{ - /* - //////////////////////////////////////////////////// - // Constants - //////////////////////////////////////////////////// - */ - - // // // Default value types - - public final static int DEF_DEFAULT = 1; - public final static int DEF_IMPLIED = 2; - public final static int DEF_REQUIRED = 3; - public final static int DEF_FIXED = 4; - - /* - //////////////////////////////////////////////////// - // Singleton instances - //////////////////////////////////////////////////// - */ - - final static DefaultAttrValue sImplied = new DefaultAttrValue(DEF_IMPLIED); - - final static DefaultAttrValue sRequired = new DefaultAttrValue(DEF_REQUIRED); - - /* - //////////////////////////////////////////////////// - // State - //////////////////////////////////////////////////// - */ - - final int mDefValueType; - - /** - * Actual expanded textual content of the default attribute value; - * normalized if appropriate in this mode. - * Note that all entities have been expanded: if a GE/PE was undefined, - * and no fatal errors were reported (non-validating mode), the - * references were just silently removed, and matching entries added - * to mUndeclaredEntity - */ - private String mValue = null; - - /** - * For now, let's only keep track of the first undeclared entity: - * can be extended if necessary. - */ - private UndeclaredEntity mUndeclaredEntity = null; - - /* - //////////////////////////////////////////////////// - // Life-cycle (creation, configuration) - //////////////////////////////////////////////////// - */ - - private DefaultAttrValue(int defValueType) - { - mDefValueType = defValueType; - } - - public static DefaultAttrValue constructImplied() { return sImplied; } - public static DefaultAttrValue constructRequired() { return sRequired; } - - public static DefaultAttrValue constructFixed() { - return new DefaultAttrValue(DEF_FIXED); - } - - public static DefaultAttrValue constructOptional() { - return new DefaultAttrValue(DEF_DEFAULT); - } - - public void setValue(String v) { - mValue = v; - } - - public void addUndeclaredPE(String name, Location loc) - { - addUndeclaredEntity(name, loc, true); - } - - public void addUndeclaredGE(String name, Location loc) - { - addUndeclaredEntity(name, loc, false); - } - - public void reportUndeclared(ValidationContext ctxt, XMLValidator dtd) - throws XMLStreamException - { - mUndeclaredEntity.reportUndeclared(ctxt, dtd); - } - - /* - //////////////////////////////////////////////////// - // Accessors: - //////////////////////////////////////////////////// - */ - - public boolean hasUndeclaredEntities() { - return (mUndeclaredEntity != null); - } - - public String getValue() { - return mValue; - } - - /** - * @return Expanded default value String, if there were no problems - * (no undeclared entities), or null to indicate there were problems. - * In latter case, caller is to figure out exact type of the problem - * and report this appropriately to the application. - */ - public String getValueIfOk() - { - return (mUndeclaredEntity == null) ? mValue : null; - } - - public boolean isRequired() { - return (this == sRequired); - } - - public boolean isFixed() { - return (mDefValueType == DEF_FIXED); - } - - public boolean hasDefaultValue() { - return (mDefValueType == DEF_DEFAULT) - || (mDefValueType == DEF_FIXED); - } - - /** - * Method used by the element to figure out if attribute needs "special" - * checking; basically if it's required, and/or has a default value. - * In both cases missing the attribute has specific consequences, either - * exception or addition of a default value. - */ - public boolean isSpecial() { - // Only non-special if #IMPLIED - return (this != sImplied); - } - - /* - //////////////////////////////////////////////////// - // Internal methods - //////////////////////////////////////////////////// - */ - - private void addUndeclaredEntity(String name, Location loc, boolean isPe) - { - if (mUndeclaredEntity == null) { - mUndeclaredEntity = new UndeclaredEntity(name, loc, isPe); - } - } - - /* - //////////////////////////////////////////////////// - // Helper class(es): - //////////////////////////////////////////////////// - */ - - final static class UndeclaredEntity - { - final String mName; - final boolean mIsPe; - final Location mLocation; - - UndeclaredEntity(String name, Location loc, boolean isPe) - { - mName = name; - mIsPe = isPe; - mLocation = loc; - } - - public void reportUndeclared(ValidationContext ctxt, XMLValidator dtd) - throws XMLStreamException - { - String msg = MessageFormat.format(ErrorConsts.ERR_DTD_UNDECLARED_ENTITY, new Object[] { (mIsPe ? "parsed" : "general"), mName }); - XMLValidationProblem prob = new XMLValidationProblem - (mLocation, msg, XMLValidationProblem.SEVERITY_FATAL); - prob.setReporter(dtd); - ctxt.reportProblem(prob); - } - } -} diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/dtd/DFAState.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/dtd/DFAState.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/dtd/DFAState.java 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/dtd/DFAState.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,207 +0,0 @@ -/* Woodstox XML processor - * - * Copyright (c) 2004 Tatu Saloranta, tatu.saloranta@iki.fi - * - * Licensed under the License specified in the file LICENSE which is - * included with the source code. - * You may not use this file except in compliance with the License. - * - * 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 com.ctc.wstx.dtd; - -import java.util.*; - -import com.ctc.wstx.util.PrefixedName; - -/** - * Class that represents a state in DFA used for validating complex - * DTD content models. - */ -public final class DFAState -{ - final int mIndex; - final boolean mAccepting; - - BitSet mTokenSet; - - HashMap mNext = new HashMap(); - - /* - /////////////////////////////////////////////// - // Life-cycle: - /////////////////////////////////////////////// - */ - - public DFAState(int index, BitSet tokenSet) - { - mIndex = index; - // If we have a transition to state 0, it is an accepting state... - mAccepting = tokenSet.get(0); - mTokenSet = tokenSet; - } - - public static DFAState constructDFA(ContentSpec rootSpec) - { - // Let's first create the real model tree: - ModelNode modelRoot = rootSpec.rewrite(); - - /* Then we need to add the dummy end token, and concat node - * to contain it: - */ - TokenModel eofToken = TokenModel.getNullToken(); - ConcatModel dummyRoot = new ConcatModel(modelRoot, eofToken); - - /* then need to allocate index numbers for tokens - * (which will also calculate nullability) - */ - ArrayList tokens = new ArrayList(); - tokens.add(eofToken); // has to be added first, explicitly - dummyRoot.indexTokens(tokens); - - /* And then we can request calculation of follow pos; this will - * also recursively calculate first/last pos as needed: - */ - int flen = tokens.size(); - BitSet[] followPos = new BitSet[flen]; - PrefixedName[] tokenNames = new PrefixedName[flen]; - for (int i = 0; i < flen; ++i) { - followPos[i] = new BitSet(flen); - tokenNames[i] = ((TokenModel) tokens.get(i)).getName(); - } - dummyRoot.calcFollowPos(followPos); - - /* And then we can calculate DFA stuff. First step is to get - * firstpos set for the root node, for creating the first - * state: - */ - BitSet initial = new BitSet(flen); - dummyRoot.addFirstPos(initial); - DFAState firstState = new DFAState(0, initial); - ArrayList stateList = new ArrayList(); - stateList.add(firstState); - HashMap stateMap = new HashMap(); - stateMap.put(initial, firstState); - - int i = 0; - while (i < stateList.size()) { - DFAState curr = (DFAState) stateList.get(i++); - curr.calcNext(tokenNames, followPos, stateList, stateMap); - } - - // DEBUG: - /* - for (i = 0; i < stateList.size(); ++i) { - //System.out.println(stateList.get(i)); - } - */ - - // And there we have it! - return firstState; - } - - /* - /////////////////////////////////////////////// - // Public API, accessors: - /////////////////////////////////////////////// - */ - - public boolean isAcceptingState() { - return mAccepting; - } - - public int getIndex() { - return mIndex; - } - - public DFAState findNext(PrefixedName elemName) { - return (DFAState) mNext.get(elemName); - } - - public TreeSet getNextNames() { - // Let's order them alphabetically - TreeSet names = new TreeSet(); - Iterator it = mNext.keySet().iterator(); - while (it.hasNext()) { - Object o = it.next(); - names.add(o); - } - return names; - } - - public void calcNext(PrefixedName[] tokenNames, BitSet[] tokenFPs, - List stateList, Map stateMap) - { - /* Need to loop over all included tokens, and find groups - * of said tokens - */ - int first = -1; - - /* Need to clone; can not modify in place, since the BitSet - * is also used as the key... - */ - BitSet tokenSet = (BitSet) mTokenSet.clone(); - // No need to keep the reference to it, though: - mTokenSet = null; - - while ((first = tokenSet.nextSetBit(first+1)) >= 0) { - PrefixedName tokenName = tokenNames[first]; - - /* Special case; the dummy end token has null as name; - * we can skip that one: - */ - if (tokenName == null) { - continue; - } - - BitSet nextGroup = (BitSet) tokenFPs[first].clone(); - int second = first; - - while ((second = tokenSet.nextSetBit(second+1)) > 0) { - if (tokenNames[second] == tokenName) { - // Let's clear it, too, so we won't match it again: - tokenSet.clear(second); - nextGroup.or(tokenFPs[second]); - } - } - - // Ok; is it a new group? - DFAState next = (DFAState) stateMap.get(nextGroup); - if (next == null) { // yup! - next = new DFAState(stateList.size(), nextGroup); - stateList.add(next); - stateMap.put(nextGroup, next); - } - mNext.put(tokenName, next); - } - } - - /* - /////////////////////////////////////////////// - // Other methods - /////////////////////////////////////////////// - */ - - public String toString() - { - StringBuffer sb = new StringBuffer(); - sb.append("State #"+mIndex+":\n"); - sb.append(" Accepting: "+mAccepting); - sb.append("\n Next states:\n"); - Iterator it = mNext.entrySet().iterator(); - while (it.hasNext()) { - Map.Entry en = (Map.Entry) it.next(); - sb.append(en.getKey()); - sb.append(" -> "); - DFAState next = (DFAState) en.getValue(); - sb.append(next.getIndex()); - sb.append("\n"); - } - return sb.toString(); - } -} diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/dtd/DFAValidator.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/dtd/DFAValidator.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/dtd/DFAValidator.java 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/dtd/DFAValidator.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,77 +0,0 @@ -/* Woodstox XML processor - * - * Copyright (c) 2004 Tatu Saloranta, tatu.saloranta@iki.fi - * - * Licensed under the License specified in the file LICENSE which is - * included with the source code. - * You may not use this file except in compliance with the License. - * - * 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 com.ctc.wstx.dtd; - -import java.util.*; - -import com.ctc.wstx.util.PrefixedName; -import com.ctc.wstx.util.StringUtil; - -/** - * Validator class that is based on a DFA constructed from DTD content - * specification. - */ -public final class DFAValidator - extends StructValidator -{ - /** - * For root validator instance, the start state of DFA; for other - * instances, current state. - */ - DFAState mState; - - public DFAValidator(DFAState initialState) { - mState = initialState; - } - - public StructValidator newInstance() { - return new DFAValidator(mState); - } - - public String tryToValidate(PrefixedName elemName) - { - // Do we have a follow state with that key? - DFAState next = mState.findNext(elemName); - - if (next == null) { - // Nope; let's show what we'd have expected instead... - TreeSet names = mState.getNextNames(); - if (names.size() == 0) { // expected end tag? - return "Expected $END"; - } - - // Either end tag, or another tag? - if (mState.isAcceptingState()) { - return "Expected <"+StringUtil.concatEntries(names, ">, <", null)+"> or $END"; - } - return "Expected <"+StringUtil.concatEntries(names, - ">, <", "> or <")+">"; - } - - mState = next; - return null; - } - - public String fullyValid() - { - if (mState.isAcceptingState()) { - return null; - } - TreeSet names = mState.getNextNames(); - return "Expected <"+StringUtil.concatEntries(names, - ">, <", "> or <")+">"; - } -} diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/dtd/DTDAttribute.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/dtd/DTDAttribute.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/dtd/DTDAttribute.java 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/dtd/DTDAttribute.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,508 +0,0 @@ -/* Woodstox XML processor - * - * Copyright (c) 2004- Tatu Saloranta, tatu.saloranta@iki.fi - * - * Licensed under the License specified in the file LICENSE which is - * included with the source code. - * You may not use this file except in compliance with the License. - * - * 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 com.ctc.wstx.dtd; - -import java.util.Map; - -import javax.xml.stream.XMLStreamException; - -import org.codehaus.stax2.validation.ValidationContext; -import org.codehaus.stax2.validation.XMLValidator; - -import com.ctc.wstx.ent.EntityDecl; -import com.ctc.wstx.io.WstxInputData; -import com.ctc.wstx.sr.InputProblemReporter; -import com.ctc.wstx.util.PrefixedName; -import com.ctc.wstx.util.StringUtil; -import com.ctc.wstx.util.WordResolver; - -/** - * Base class for objects that contain attribute definitions from DTD. - * Sub-classes exists for specific typed attributes (enumeration-valued, - * non-CDATA ones); base class itself is used for attributes of type - * CDATA. - */ -public abstract class DTDAttribute -{ - final static char CHAR_SPACE = (char) 0x0020; - - /* - /////////////////////////////////////////////////// - // Type constants - /////////////////////////////////////////////////// - */ - - // // // Value types - - public final static int TYPE_CDATA = 0; // default... - public final static int TYPE_ENUMERATED = 1; - - public final static int TYPE_ID = 2; - public final static int TYPE_IDREF = 3; - public final static int TYPE_IDREFS = 4; - - public final static int TYPE_ENTITY = 5; - public final static int TYPE_ENTITIES = 6; - - public final static int TYPE_NOTATION = 7; - public final static int TYPE_NMTOKEN = 8; - public final static int TYPE_NMTOKENS = 9; - - /** - * Array that has String constants matching above mentioned - * value types - */ - final static String[] sTypes = new String[] { - "CDATA", - /* 05-Feb-2006, TSa: Hmmh. Apparently SAX specs indicate that - * enumerated type should be listed as "NMTOKEN"... but most - * SAX parsers use ENUMERATED, plus this way application can - * distinguish real NMTOKEN from enumerated type. - */ - /* 26-Nov-2006, TSa: Either way, we can change type to SAX - * compatible within SAX classes, not here. - */ - //"NMTOKEN" - "ENUMERATED", - "ID", - "IDREF", - "IDREFS", - "ENTITY", - "ENTITIES", - "NOTATION", - "NMTOKEN", - "NMTOKENS", - }; - - /* - /////////////////////////////////////////////////// - // Information about the attribute itself - /////////////////////////////////////////////////// - */ - - protected final PrefixedName mName; - - /** - * Index number amongst "special" attributes (required ones, attributes - * that have default values), if attribute is one: -1 if not. - */ - protected final int mSpecialIndex; - - protected final DefaultAttrValue mDefValue; - - protected final boolean mCfgNsAware; - protected final boolean mCfgXml11; - - /* - /////////////////////////////////////////////////// - // Life-cycle - /////////////////////////////////////////////////// - */ - - public DTDAttribute(PrefixedName name, DefaultAttrValue defValue, int specIndex, - boolean nsAware, boolean xml11) - { - mName = name; - mDefValue = defValue; - mSpecialIndex = specIndex; - mCfgNsAware = nsAware; - mCfgXml11 = xml11; - } - - public abstract DTDAttribute cloneWith(int specIndex); - - /* - /////////////////////////////////////////////////// - // Public API, accessors - /////////////////////////////////////////////////// - */ - - public final PrefixedName getName() { return mName; } - - public final String toString() { - return mName.toString(); - } - - public final String getDefaultValue(ValidationContext ctxt, XMLValidator dtd) - throws XMLStreamException - { - String val = mDefValue.getValueIfOk(); - if (val == null) { - mDefValue.reportUndeclared(ctxt, dtd); - /* should never get here, but just to be safe, let's use - * the 'raw' value (one that does not have undeclared entities - * included, most likely) - */ - val = mDefValue.getValue(); - } - return val; - } - - public final int getSpecialIndex() { - return mSpecialIndex; - } - - public final boolean needsValidation() { - return (getValueType() != TYPE_CDATA); - } - - public final boolean isFixed() { - return mDefValue.isFixed(); - } - - public final boolean isRequired() { - return mDefValue.isRequired(); - } - - /** - * Method used by the element to figure out if attribute needs "special" - * checking; basically if it's required, and/or has a default value. - * In both cases missing the attribute has specific consequences, either - * exception or addition of a default value. - */ - public final boolean isSpecial() { - return mDefValue.isSpecial(); - } - - public final boolean hasDefaultValue() { - return mDefValue.hasDefaultValue(); - } - - /** - * Returns the value type of this attribute as an enumerated int - * to match type (CDATA, ...) - *

- * Note: - */ - public int getValueType() { - return TYPE_CDATA; - } - - public String getValueTypeString() - { - return sTypes[getValueType()]; - } - - public boolean typeIsId() { - return false; - } - - public boolean typeIsNotation() { - return false; - } - - /* - /////////////////////////////////////////////////// - // Public API, validation - /////////////////////////////////////////////////// - */ - - public abstract String validate(DTDValidatorBase v, char[] cbuf, int start, int end, boolean normalize) - throws XMLStreamException; - - /** - *

- * Note: the default implementation is not optimized, as it does - * a potentially unnecessary copy of the contents. It is expected that - * this method is seldom called (Woodstox never directly calls it; it - * only gets called for chained validators when one validator normalizes - * the value, and then following validators are passed a String, not - * char array) - */ - public String validate(DTDValidatorBase v, String value, boolean normalize) - throws XMLStreamException - { - int len = value.length(); - /* Temporary buffer has to come from the validator itself, since - * attribute objects are stateless and shared... - */ - char[] cbuf = v.getTempAttrValueBuffer(value.length()); - if (len > 0) { - value.getChars(0, len, cbuf, 0); - } - return validate(v, cbuf, 0, len, normalize); - } - - /** - * Method called by the {@link DTDValidator} - * to ask attribute to verify that the default it has (if any) is - * valid for such type. - */ - public abstract void validateDefault(InputProblemReporter rep, boolean normalize) - throws XMLStreamException; - - /** - * Method called when no validation is to be done, but value is still - * to be normalized as much as it can. What this usually means is that - * all regular space (parser earlier on converts other white space to - * spaces, except for specific character entities; and these special - * cases are NOT to be normalized). - *

- * The only exception is that CDATA will not do any normalization. But - * for now, let's implement basic functionality that CDTA instance will - * override - * - * @return Normalized value as a String, if any changes were done; - * null if input was normalized - */ - public String normalize(DTDValidatorBase v, char[] cbuf, int start, int end) - { - return StringUtil.normalizeSpaces(cbuf, start, end); - } - - /** - * Method called to do initial normalization of the default attribute - * value, without trying to verify its validity. Thus, it's - * called independent of whether we are fully validating the document. - */ - public void normalizeDefault() - { - String val = mDefValue.getValue(); - if (val.length() > 0) { - char[] cbuf = val.toCharArray(); - String str = StringUtil.normalizeSpaces(cbuf, 0, cbuf.length); - if (str != null) { - mDefValue.setValue(str); - } - } - } - - /* - /////////////////////////////////////////////////// - // Package methods, validation helper methods - /////////////////////////////////////////////////// - */ - - protected String validateDefaultName(InputProblemReporter rep, boolean normalize) - throws XMLStreamException - { - String origDefValue = mDefValue.getValue(); - String defValue = origDefValue.trim(); - - if (defValue.length() == 0) { - reportValidationProblem(rep, "Invalid default value '"+defValue - +"'; empty String is not a valid name"); - } - - // Ok, needs to be a valid XML name: - int illegalIx = WstxInputData.findIllegalNameChar(defValue, mCfgNsAware, mCfgXml11); - if (illegalIx >= 0) { - if (illegalIx == 0) { - reportValidationProblem(rep, "Invalid default value '"+defValue+"'; character " - +WstxInputData.getCharDesc(defValue.charAt(0)) - +") not valid first character of a name"); - } else { - reportValidationProblem(rep, "Invalid default value '"+defValue+"'; character #"+illegalIx+" (" - +WstxInputData.getCharDesc(defValue.charAt(illegalIx)) - +") not valid name character"); - } - } - - // Ok, cool it's ok... - return normalize ? defValue : origDefValue; - } - - protected String validateDefaultNames(InputProblemReporter rep, boolean normalize) - throws XMLStreamException - { - String defValue = mDefValue.getValue().trim(); - int len = defValue.length(); - - // Then code similar to actual value validation: - StringBuffer sb = null; - int count = 0; - int start = 0; - - main_loop: - while (start < len) { - char c = defValue.charAt(start); - - // Ok, any white space to skip? - while (true) { - if (!WstxInputData.isSpaceChar(c)) { - break; - } - if (++start >= len) { - break main_loop; - } - c = defValue.charAt(start); - } - - // Then need to find the token itself: - int i = start+1; - - for (; i < len; ++i) { - if (WstxInputData.isSpaceChar(defValue.charAt(i))) { - break; - } - } - String token = defValue.substring(start, i); - int illegalIx = WstxInputData.findIllegalNameChar(token, mCfgNsAware, mCfgXml11); - if (illegalIx >= 0) { - if (illegalIx == 0) { - reportValidationProblem(rep, "Invalid default value '"+defValue - +"'; character " - +WstxInputData.getCharDesc(defValue.charAt(start)) - +") not valid first character of a name token"); - } else { - reportValidationProblem(rep, "Invalid default value '"+defValue - +"'; character " - +WstxInputData.getCharDesc(c) - +") not a valid name character"); - } - } - ++count; - if (normalize) { - if (sb == null) { - sb = new StringBuffer(i - start + 32); - } else { - sb.append(' '); - } - sb.append(token); - } - start = i+1; - } - - if (count == 0) { - reportValidationProblem(rep, "Invalid default value '"+defValue - +"'; empty String is not a valid name value"); - } - - return normalize ? sb.toString() : defValue; - } - - protected String validateDefaultNmToken(InputProblemReporter rep, boolean normalize) - throws XMLStreamException - { - String origDefValue = mDefValue.getValue(); - String defValue = origDefValue.trim(); - - if (defValue.length() == 0) { - reportValidationProblem(rep, "Invalid default value '"+defValue+"'; empty String is not a valid NMTOKEN"); - } - int illegalIx = WstxInputData.findIllegalNmtokenChar(defValue, mCfgNsAware, mCfgXml11); - if (illegalIx >= 0) { - reportValidationProblem(rep, "Invalid default value '"+defValue - +"'; character #"+illegalIx+" (" - +WstxInputData.getCharDesc(defValue.charAt(illegalIx)) - +") not valid NMTOKEN character"); - } - // Ok, cool it's ok... - return normalize ? defValue : origDefValue; - } - - /** - * Method called by validation/normalization code for enumeration-valued - * attributes, to trim - * specified attribute value (full normalization not needed -- called - * for values that CAN NOT have spaces inside; such values can not - * be legal), and then check whether it is included - * in set of words (tokens) passed in. If actual value was included, - * will return the normalized word (as well as store shared String - * locally); otherwise will return null. - */ - public String validateEnumValue(char[] cbuf, int start, int end, - boolean normalize, - WordResolver res) - { - /* Better NOT to build temporary Strings quite yet; can resolve - * matches via resolver more efficiently. - */ - // Note: at this point, should only have real spaces... - if (normalize) { - while (start < end && cbuf[start] <= CHAR_SPACE) { - ++start; - } - while (--end > start && cbuf[end] <= CHAR_SPACE) { - ; - } - ++end; // so it'll point to the first char (or beyond end of buffer) - } - - // Empty String is never legal for enums: - if (start >= end) { - return null; - } - return res.find(cbuf, start, end); - } - - protected EntityDecl findEntityDecl(DTDValidatorBase v, - char[] ch, int start, int len, int hash) - throws XMLStreamException - { - Map entMap = v.getEntityMap(); - /* !!! 13-Nov-2005, TSa: If this was to become a bottle-neck, we - * could use/share a symbol table. Or at least reuse Strings... - */ - String id = new String(ch, start, len); - EntityDecl ent = (EntityDecl) entMap.get(id); - - if (ent == null) { - reportValidationProblem(v, "Referenced entity '"+id+"' not defined"); - } else if (ent.isParsed()) { - reportValidationProblem(v, "Referenced entity '"+id+"' is not an unparsed entity"); - } - return ent; - } - - /* Too bad this method can not be combined with previous segment -- - * the reason is that DTDValidator does not implement - * InputProblemReporter... - */ - - protected void checkEntity(InputProblemReporter rep, String id, EntityDecl ent) - throws XMLStreamException - { - if (ent == null) { - rep.reportValidationProblem("Referenced entity '"+id+"' not defined"); - } else if (ent.isParsed()) { - rep.reportValidationProblem("Referenced entity '"+id+"' is not an unparsed entity"); - } - } - - /* - /////////////////////////////////////////////////// - // Package methods, error reporting - /////////////////////////////////////////////////// - */ - - protected String reportInvalidChar(DTDValidatorBase v, char c, String msg) - throws XMLStreamException - { - reportValidationProblem(v, "Invalid character "+WstxInputData.getCharDesc(c)+": "+msg); - return null; - } - - protected String reportValidationProblem(DTDValidatorBase v, String msg) - throws XMLStreamException - { - v.reportValidationProblem("Attribute '"+mName+"': "+msg); - return null; - } - - /** - * Method called during parsing of DTD schema, to report a problem. - * Note that unlike during actual validation, we have no option of - * just gracefully listing problems and ignoring them; an exception - * is always thrown. - */ - protected String reportValidationProblem(InputProblemReporter rep, String msg) - throws XMLStreamException - { - rep.reportValidationProblem("Attribute definition '"+mName+"': "+msg); - return null; - } -} diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/dtd/DTDCdataAttr.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/dtd/DTDCdataAttr.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/dtd/DTDCdataAttr.java 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/dtd/DTDCdataAttr.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,61 +0,0 @@ -package com.ctc.wstx.dtd; - -import org.codehaus.stax2.validation.XMLValidationException; - -import com.ctc.wstx.sr.InputProblemReporter; -import com.ctc.wstx.util.PrefixedName; - -/** - * Simple {@link DTDAttribute} sub-class used for plain vanilla CDATA - * valued attributes. Although base class implements most of the methods, - * it's better designwise to keep that base class abstract and have - * separate CDATA type as well. - */ -public final class DTDCdataAttr - extends DTDAttribute -{ - public DTDCdataAttr(PrefixedName name, DefaultAttrValue defValue, int specIndex, - boolean nsAware, boolean xml11) - { - super(name, defValue, specIndex, nsAware, xml11); - } - - public DTDAttribute cloneWith(int specIndex) - { - return new DTDCdataAttr(mName, mDefValue, specIndex, mCfgNsAware, mCfgXml11); - } - - /* - /////////////////////////////////////////////////// - // Public API, validation - /////////////////////////////////////////////////// - */ - - // @Override - public String validate(DTDValidatorBase v, char[] cbuf, int start, int end, boolean normalize) - throws XMLValidationException - { - // Nothing to do for pure CDATA attributes... - return null; - } - - // @Override - public void validateDefault(InputProblemReporter rep, boolean normalize) - throws javax.xml.stream.XMLStreamException - { - // Nothing to do for CDATA; all values are fine - } - - // @Override - public String normalize(DTDValidatorBase v, char[] cbuf, int start, int end) - { - // Nothing to do for pure CDATA attributes... - return null; - } - - // @Override - public void normalizeDefault() - { - // Nothing to do for pure CDATA attributes... - } -} diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/dtd/DTDElement.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/dtd/DTDElement.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/dtd/DTDElement.java 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/dtd/DTDElement.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,576 +0,0 @@ -/* Woodstox XML processor - * - * Copyright (c) 2004- Tatu Saloranta, tatu.saloranta@iki.fi - * - * Licensed under the License specified in the file LICENSE which is - * included with the source code. - * You may not use this file except in compliance with the License. - * - * 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 com.ctc.wstx.dtd; - -import java.util.*; - -import javax.xml.stream.Location; -import javax.xml.stream.XMLStreamException; - -import org.codehaus.stax2.validation.XMLValidator; - -import com.ctc.wstx.api.ReaderConfig; -import com.ctc.wstx.cfg.ErrorConsts; -import com.ctc.wstx.sr.InputProblemReporter; -import com.ctc.wstx.util.ExceptionUtil; -import com.ctc.wstx.util.PrefixedName; -import com.ctc.wstx.util.WordResolver; - -/** - * Class that contains element definitions from DTD. - *

- * Notes about thread-safety: this class is not thread-safe, since it does - * not have to be, in general case. That is, the only instances that can - * be shared are external subset instances, and those are used in read-only - * manner (with the exception of temporary arrays constructed on-demand). - */ -public final class DTDElement -{ - - /* - /////////////////////////////////////////////////// - // Information about the element itself - /////////////////////////////////////////////////// - */ - - final PrefixedName mName; - - /** - * Location of the (real) definition of the element; may be null for - * placeholder elements created to hold ATTLIST definitions - */ - final Location mLocation; - - /** - * Base validator object for validating content model of this element; - * may be null for some simple content models (ANY, EMPTY). - */ - StructValidator mValidator; - - int mAllowedContent; - - /** - * True if the DTD was parsed (and is to be used) in namespace-aware - * mode. - * Affects (name) validation amongst other things. - */ - final boolean mNsAware; - - /** - * True if the DTD was parsed in xml1.1 compliant mode (referenced to - * from an xml 1.1 document). - * Affects (name) validation amongst other things. - */ - final boolean mXml11; - - /* - /////////////////////////////////////////////////// - // Attribute info - /////////////////////////////////////////////////// - */ - - HashMap mAttrMap = null; - - /** - * Ordered list of attributes that have 'special' properties (attribute - * is required, has a default value [regular or fixed]); these attributes - * have to be specifically checked after actual values have been resolved. - */ - ArrayList mSpecAttrList = null; - - boolean mAnyFixed = false; - - /** - * Flag set to true if there are any attributes that have either - * basic default value, or #FIXED default value. - */ - boolean mAnyDefaults = false; - - /** - * Flag that is set to true if there is at least one attribute that - * has type that requires normalization and/or validation; that is, - * is of some other type than CDATA. - */ - boolean mValidateAttrs = false; - - /** - * Id attribute instance, if one already declared for this element; - * can only have up to one such attribute per element. - */ - DTDAttribute mIdAttr; - - /** - * Notation attribute instance, if one already declared for this element; - * can only have up to one such attribute per element. - */ - DTDAttribute mNotationAttr; - - // // // !! If you add new attributes, make sure they get copied - // // // in #define() method !! - - /* - /////////////////////////////////////////////////// - // Namespace declaration defaulting... - /////////////////////////////////////////////////// - */ - - /** - * Set of namespace declarations with default values, if any - * (regular ns pseudo-attr declarations are just ignored) - */ - HashMap mNsDefaults = null; // [String : DTDAttribute] - - /* - /////////////////////////////////////////////////// - // Life-cycle - /////////////////////////////////////////////////// - */ - - private DTDElement(Location loc, PrefixedName name, - StructValidator val, int allowedContent, - boolean nsAware, boolean xml11) - { - mName = name; - mLocation = loc; - mValidator = val; - mAllowedContent = allowedContent; - mNsAware = nsAware; - mXml11 = xml11; - } - - /** - * Method called to create an actual element definition, matching - * an ELEMENT directive in a DTD subset. - */ - public static DTDElement createDefined(ReaderConfig cfg, Location loc, PrefixedName name, - StructValidator val, int allowedContent) - { - if (allowedContent == XMLValidator.CONTENT_ALLOW_UNDEFINED) { // sanity check - ExceptionUtil.throwInternal("trying to use XMLValidator.CONTENT_ALLOW_UNDEFINED via createDefined()"); - } - return new DTDElement(loc, name, val, allowedContent, - cfg.willSupportNamespaces(), cfg.isXml11()); - } - - /** - * Method called to create a "placeholder" element definition, needed to - * contain attribute definitions. - */ - public static DTDElement createPlaceholder(ReaderConfig cfg, Location loc, PrefixedName name) - { - return new DTDElement(loc, name, null, XMLValidator.CONTENT_ALLOW_UNDEFINED, - cfg.willSupportNamespaces(), cfg.isXml11()); - } - - /** - * Method called on placeholder element, to create a real instance that - * has all attribute definitions placeholder had (it'll always have at - * least one -- otherwise no placeholder was needed). - */ - public DTDElement define(Location loc, StructValidator val, - int allowedContent) - { - verifyUndefined(); - if (allowedContent == XMLValidator.CONTENT_ALLOW_UNDEFINED) { // sanity check - ExceptionUtil.throwInternal("trying to use CONTENT_ALLOW_UNDEFINED via define()"); - } - - DTDElement elem = new DTDElement(loc, mName, val, allowedContent, - mNsAware, mXml11); - - // Ok, need to copy state collected so far: - elem.mAttrMap = mAttrMap; - elem.mSpecAttrList = mSpecAttrList; - elem.mAnyFixed = mAnyFixed; - elem.mValidateAttrs = mValidateAttrs; - elem.mAnyDefaults = mAnyDefaults; - elem.mIdAttr = mIdAttr; - elem.mNotationAttr = mNotationAttr; - elem.mNsDefaults = mNsDefaults; - - return elem; - } - - /** - * Method called to "upgrade" a placeholder using a defined element, - * including adding attributes. - */ - public void defineFrom(InputProblemReporter rep, DTDElement definedElem, - boolean fullyValidate) - throws XMLStreamException - { - if (fullyValidate) { - verifyUndefined(); - } - mValidator = definedElem.mValidator; - mAllowedContent = definedElem.mAllowedContent; - mergeMissingAttributesFrom(rep, definedElem, fullyValidate); - } - - private void verifyUndefined() - { - if (mAllowedContent != XMLValidator.CONTENT_ALLOW_UNDEFINED) { // sanity check - ExceptionUtil.throwInternal("redefining defined element spec"); - } - } - - /** - * Method called by DTD parser when it has read information about - * an attribute that belong to this element - * - * @return Newly created attribute Object if the attribute definition was - * added (hadn't been declared yet); null if it's a duplicate, in which - * case original definition sticks. - */ - public DTDAttribute addAttribute(InputProblemReporter rep, - PrefixedName attrName, int valueType, - DefaultAttrValue defValue, WordResolver enumValues, - boolean fullyValidate) - throws XMLStreamException - { - HashMap m = mAttrMap; - if (m == null) { - mAttrMap = m = new HashMap(); - } - - List specList = defValue.isSpecial() ? getSpecialList() : null; - - DTDAttribute attr; - int specIndex = (specList == null) ? -1 : specList.size(); - - switch (valueType) { - case DTDAttribute.TYPE_CDATA: - attr = new DTDCdataAttr(attrName, defValue, specIndex, mNsAware, mXml11); - break; - - case DTDAttribute.TYPE_ENUMERATED: - attr = new DTDEnumAttr(attrName, defValue, specIndex, mNsAware, mXml11, enumValues); - break; - - case DTDAttribute.TYPE_ID: - /* note: although ID attributes are not to have default value, - * this is 'only' a validity constraint, and in dtd-aware-but- - * not-validating mode it is apparently 'legal' to add default - * values. Bleech. - */ - attr = new DTDIdAttr(attrName, defValue, specIndex, mNsAware, mXml11); - break; - - case DTDAttribute.TYPE_IDREF: - attr = new DTDIdRefAttr(attrName, defValue, specIndex, mNsAware, mXml11); - break; - - case DTDAttribute.TYPE_IDREFS: - attr = new DTDIdRefsAttr(attrName, defValue, specIndex, mNsAware, mXml11); - break; - - case DTDAttribute.TYPE_ENTITY: - attr = new DTDEntityAttr(attrName, defValue, specIndex, mNsAware, mXml11); - break; - - case DTDAttribute.TYPE_ENTITIES: - attr = new DTDEntitiesAttr(attrName, defValue, specIndex, mNsAware, mXml11); - break; - - case DTDAttribute.TYPE_NOTATION: - attr = new DTDNotationAttr(attrName, defValue, specIndex, mNsAware, mXml11, enumValues); - break; - - case DTDAttribute.TYPE_NMTOKEN: - attr = new DTDNmTokenAttr(attrName, defValue, specIndex, mNsAware, mXml11); - break; - - case DTDAttribute.TYPE_NMTOKENS: - attr = new DTDNmTokensAttr(attrName, defValue, specIndex, mNsAware, mXml11); - break; - - default: - // 18-Jan-2006, TSa: should never get here... - ExceptionUtil.throwGenericInternal(); - attr = null; // unreachable, but compiler wants it - } - - DTDAttribute old = doAddAttribute(m, rep, attr, specList, fullyValidate); - return (old == null) ? attr : null; - } - - /** - * Method called to add a definition of a namespace-declaration - * pseudo-attribute with a default value. - * - * @return Attribute that acts as the placeholder, if the declaration - * was added; null to indicate it - * was a dup (there was an earlier declaration) - */ - public DTDAttribute addNsDefault - (InputProblemReporter rep, PrefixedName attrName, int valueType, - DefaultAttrValue defValue, boolean fullyValidate) - throws XMLStreamException - { - /* Let's simplify handling a bit: although theoretically all - * combinations of value can be used, let's really only differentiate - * between CDATA and 'other' (for which let's use NMTOKEN) - */ - DTDAttribute nsAttr; - - switch (valueType) { - case DTDAttribute.TYPE_CDATA: - nsAttr = new DTDCdataAttr(attrName, defValue, -1, mNsAware, mXml11); - break; - default: // something else, default to NMTOKEN then - nsAttr = new DTDNmTokenAttr(attrName, defValue, -1, mNsAware, mXml11); - break; - } - - // Ok. So which prefix are we to bind? Need to access by prefix... - String prefix = attrName.getPrefix(); - if (prefix == null || prefix.length() == 0) { // defult NS -> "" - prefix = ""; - } else { // non-default, use the local name - prefix = attrName.getLocalName(); - } - - if (mNsDefaults == null) { - mNsDefaults = new HashMap(); - } else { - if (mNsDefaults.containsKey(prefix)) { - return null; - } - } - mNsDefaults.put(prefix, nsAttr); - return nsAttr; - } - - public void mergeMissingAttributesFrom(InputProblemReporter rep, DTDElement other, - boolean fullyValidate) - throws XMLStreamException - { - Map otherMap = other.getAttributes(); - HashMap m = mAttrMap; - if (m == null) { - mAttrMap = m = new HashMap(); - } - - //boolean anyAdded = false; - - if (otherMap != null && otherMap.size() > 0) { - Iterator it = otherMap.entrySet().iterator(); - while (it.hasNext()) { - Map.Entry me = (Map.Entry) it.next(); - Object key = me.getKey(); - // Should only add if no such attribute exists... - if (!m.containsKey(key)) { - // can only use as is, if it's not a special attr - DTDAttribute newAttr = (DTDAttribute) me.getValue(); - List specList; - // otherwise need to clone - if (newAttr.isSpecial()) { - specList = getSpecialList(); - newAttr = newAttr.cloneWith(specList.size()); - } else { - specList = null; - } - doAddAttribute(m, rep, newAttr, specList, fullyValidate); - } - } - } - - HashMap otherNs = other.mNsDefaults; - if (otherNs != null) { - if (mNsDefaults == null) { - mNsDefaults = new HashMap(); - } - Iterator it = otherNs.entrySet().iterator(); - while (it.hasNext()) { - Map.Entry me = (Map.Entry) it.next(); - Object key = me.getKey(); - // Should only add if no such attribute exists... - if (!mNsDefaults.containsKey(key)) { - mNsDefaults.put(key, me.getValue()); - } - } - } - } - - /** - * @return Earlier declaration of the attribute, if any; null if - * this was a new attribute - */ - private DTDAttribute doAddAttribute(Map attrMap, InputProblemReporter rep, - DTDAttribute attr, List specList, - boolean fullyValidate) - throws XMLStreamException - { - PrefixedName attrName = attr.getName(); - - // Maybe we already have it? If so, need to ignore - DTDAttribute old = (DTDAttribute) attrMap.get(attrName); - if (old != null) { - rep.reportProblem(null, ErrorConsts.WT_ATTR_DECL, ErrorConsts.W_DTD_DUP_ATTR, - attrName, mName); - return old; - } - - switch (attr.getValueType()) { - case DTDAttribute.TYPE_ID: - // Only one such attribute per element (Specs, 1.0#3.3.1) - if (fullyValidate && mIdAttr != null) { - rep.throwParseError("Invalid id attribute \"{0}\" for element <{1}>: already had id attribute \""+mIdAttr.getName()+"\"", attrName, mName); - } - mIdAttr = attr; - break; - - case DTDAttribute.TYPE_NOTATION: - // Only one such attribute per element (Specs, 1.0#3.3.1) - if (fullyValidate && mNotationAttr != null) { - rep.throwParseError("Invalid notation attribute '"+attrName+"' for element <"+mName+">: already had notation attribute '"+mNotationAttr.getName()+"'"); - } - mNotationAttr = attr; - break; - } - - attrMap.put(attrName, attr); - if (specList != null) { - specList.add(attr); - } - if (!mAnyFixed) { - mAnyFixed = attr.isFixed(); - } - if (!mValidateAttrs) { - mValidateAttrs = attr.needsValidation(); - } - if (!mAnyDefaults) { - mAnyDefaults = attr.hasDefaultValue(); - } - - return null; - } - - /* - /////////////////////////////////////////////////// - // Public API, accessors: - /////////////////////////////////////////////////// - */ - - public PrefixedName getName() { return mName; } - - public String toString() { - return mName.toString(); - } - - public String getDisplayName() { - return mName.toString(); - } - - public Location getLocation() { return mLocation; } - - public boolean isDefined() { - return (mAllowedContent != XMLValidator.CONTENT_ALLOW_UNDEFINED); - } - - /** - * @return Constant that identifies what kind of nodes are in general - * allowed inside this element. - */ - public int getAllowedContent() { - return mAllowedContent; - } - - /** - * Specialized accessor used by non-validating but typing 'validator': - * essentially, used to figure out whether #PCDATA is allowed or not; - * and based on that, return one of 2 allowable text values (only - * space, or anything). This is the relevant subset in non-validating - * modes, needed to properly type resulting character events. - */ - public int getAllowedContentIfSpace() - { - int vld = mAllowedContent; - return (vld <= XMLValidator.CONTENT_ALLOW_WS) ? - XMLValidator.CONTENT_ALLOW_WS_NONSTRICT : - XMLValidator.CONTENT_ALLOW_ANY_TEXT; - } - - public HashMap getAttributes() { - return mAttrMap; - } - - public int getSpecialCount() { - return (mSpecAttrList == null) ? 0 : mSpecAttrList.size(); - } - - public List getSpecialAttrs() { - return mSpecAttrList; - } - - /** - * @return True if at least one of the attributes has type other than - * CDATA; false if not - */ - public boolean attrsNeedValidation() { - return mValidateAttrs; - } - - public boolean hasFixedAttrs() { - return mAnyFixed; - } - - public boolean hasAttrDefaultValues() { - return mAnyDefaults; - } - - public DTDAttribute getIdAttribute() { - return mIdAttr; - } - - public DTDAttribute getNotationAttribute() { - return mNotationAttr; - } - - public boolean hasNsDefaults() { - return (mNsDefaults != null); - } - - /* - /////////////////////////////////////////////////// - // Public API, factory methods: - /////////////////////////////////////////////////// - */ - - public StructValidator getValidator() - { - return (mValidator == null) ? null : mValidator.newInstance(); - } - - protected HashMap getNsDefaults() { - return mNsDefaults; - } - - /* - /////////////////////////////////////////////////// - // Internal methods - /////////////////////////////////////////////////// - */ - - private List getSpecialList() - { - ArrayList l = mSpecAttrList; - if (l == null) { - mSpecAttrList = l = new ArrayList(); - } - return l; - } -} diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/dtd/DTDEntitiesAttr.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/dtd/DTDEntitiesAttr.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/dtd/DTDEntitiesAttr.java 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/dtd/DTDEntitiesAttr.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,177 +0,0 @@ -package com.ctc.wstx.dtd; - -import java.util.StringTokenizer; - -import javax.xml.stream.XMLStreamException; - -import com.ctc.wstx.ent.EntityDecl; -import com.ctc.wstx.io.WstxInputData; -import com.ctc.wstx.sr.InputProblemReporter; -import com.ctc.wstx.util.PrefixedName; - -/** - * Specific attribute class for attributes that contain (unique) - * identifiers. - */ -public final class DTDEntitiesAttr - extends DTDAttribute -{ - /* - /////////////////////////////////////////////////// - // Life-cycle - /////////////////////////////////////////////////// - */ - - /** - * Main constructor. Note that id attributes can never have - * default values. - */ - public DTDEntitiesAttr(PrefixedName name, DefaultAttrValue defValue, int specIndex, - boolean nsAware, boolean xml11) - - { - super(name, defValue, specIndex, nsAware, xml11); - } - - public DTDAttribute cloneWith(int specIndex) - { - return new DTDEntitiesAttr(mName, mDefValue, specIndex, mCfgNsAware, mCfgXml11); - } - - /* - /////////////////////////////////////////////////// - // Public API - /////////////////////////////////////////////////// - */ - - public int getValueType() { - return TYPE_ENTITIES; - } - - /* - /////////////////////////////////////////////////// - // Public API, validation - /////////////////////////////////////////////////// - */ - - /** - * Method called by the {@link DTDValidatorBase} - * to let the attribute do necessary normalization and/or validation - * for the value. - * - */ - public String validate(DTDValidatorBase v, char[] cbuf, int start, int end, boolean normalize) - throws XMLStreamException - { - /* Let's skip leading/trailing white space, even if we are not - * to normalize visible attribute value. This allows for better - * round-trip handling (no changes for physical value caller - * gets), but still allows succesful validation. - */ - while (start < end && WstxInputData.isSpaceChar(cbuf[start])) { - ++start; - } - - // Empty value? - if (start >= end) { - return reportValidationProblem(v, "Empty ENTITIES value"); - } - --end; // so that it now points to the last char - while (end > start && WstxInputData.isSpaceChar(cbuf[end])) { - --end; - } - - // Ok; now start points to first, last to last char (both inclusive) - String idStr = null; - StringBuffer sb = null; - - while (start <= end) { - // Ok, need to check char validity, and also calc hash code: - char c = cbuf[start]; - if (!WstxInputData.isNameStartChar(c, mCfgNsAware, mCfgXml11)) { - return reportInvalidChar(v, c, "not valid as the first ENTITIES character"); - } - int hash = (int) c; - int i = start+1; - for (; i <= end; ++i) { - c = cbuf[i]; - if (WstxInputData.isSpaceChar(c)) { - break; - } - if (!WstxInputData.isNameChar(c, mCfgNsAware, mCfgXml11)) { - return reportInvalidChar(v, c, "not valid as an ENTITIES character"); - } - hash = (hash * 31) + (int) c; - } - - EntityDecl ent = findEntityDecl(v, cbuf, start, (i - start), hash); - // only returns if entity was found... - - // Can skip the trailing space char (if there was one) - start = i+1; - - /* When normalizing, we can possibly share id String, or - * alternatively, compose normalized String if multiple - */ - if (normalize) { - if (idStr == null) { // first idref - idStr = ent.getName(); - } else { - if (sb == null) { - sb = new StringBuffer(idStr); - } - idStr = ent.getName(); - sb.append(' '); - sb.append(idStr); - } - } - - // Ok, any white space to skip? - while (start <= end && WstxInputData.isSpaceChar(cbuf[start])) { - ++start; - } - } - - if (normalize) { - if (sb != null) { - idStr = sb.toString(); - } - return idStr; - } - - return null; - } - - /** - * Method called by the validator object - * to ask attribute to verify that the default it has (if any) is - * valid for such type. - */ - public void validateDefault(InputProblemReporter rep, boolean normalize) - throws XMLStreamException - { - String normStr = validateDefaultNames(rep, true); - if (normalize) { - mDefValue.setValue(normStr); - } - - // Ok, but were they declared? - - /* Performance really shouldn't be critical here (only called when - * parsing DTDs, which get cached) -- let's just - * tokenize using standard StringTokenizer - */ - StringTokenizer st = new StringTokenizer(normStr); - /* !!! 03-Dec-2004, TSa: This is rather ugly -- need to know we - * actually really get a DTD reader, and DTD reader needs - * to expose a special method... but it gets things done. - */ - MinimalDTDReader dtdr = (MinimalDTDReader) rep; - while (st.hasMoreTokens()) { - String str = st.nextToken(); - EntityDecl ent = dtdr.findEntity(str); - // Needs to exists, and be an unparsed entity... - checkEntity(rep, normStr, ent); - } - } -} diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/dtd/DTDEntityAttr.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/dtd/DTDEntityAttr.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/dtd/DTDEntityAttr.java 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/dtd/DTDEntityAttr.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,118 +0,0 @@ -package com.ctc.wstx.dtd; - -import javax.xml.stream.XMLStreamException; - -import com.ctc.wstx.ent.EntityDecl; -import com.ctc.wstx.io.WstxInputData; -import com.ctc.wstx.sr.InputProblemReporter; -import com.ctc.wstx.util.PrefixedName; - -/** - * Specific attribute class for attributes that contain (unique) - * identifiers. - */ -public final class DTDEntityAttr - extends DTDAttribute -{ - /* - /////////////////////////////////////////////////// - // Life-cycle - /////////////////////////////////////////////////// - */ - - /** - * Main constructor. Note that id attributes can never have - * default values. - */ - public DTDEntityAttr(PrefixedName name, DefaultAttrValue defValue, int specIndex, - boolean nsAware, boolean xml11) - { - super(name, defValue, specIndex, nsAware, xml11); - } - - public DTDAttribute cloneWith(int specIndex) - { - return new DTDEntityAttr(mName, mDefValue, specIndex, mCfgNsAware, mCfgXml11); - } - - /* - /////////////////////////////////////////////////// - // Public API - /////////////////////////////////////////////////// - */ - - public int getValueType() { - return TYPE_ENTITY; - } - - /* - /////////////////////////////////////////////////// - // Public API, validation - /////////////////////////////////////////////////// - */ - - /** - * Method called by the {@link DTDValidatorBase} - * to let the attribute do necessary normalization and/or validation - * for the value. - */ - public String validate(DTDValidatorBase v, char[] cbuf, int start, int end, boolean normalize) - throws XMLStreamException - { - while (start < end && WstxInputData.isSpaceChar(cbuf[start])) { - ++start; - } - - // Empty value? - if (start >= end) { - return reportValidationProblem(v, "Empty ENTITY value"); - } - --end; // so that it now points to the last char - while (end > start && WstxInputData.isSpaceChar(cbuf[end])) { - --end; - } - - // Ok, need to check char validity, and also calc hash code: - char c = cbuf[start]; - if (!WstxInputData.isNameStartChar(c, mCfgNsAware, mCfgXml11) && c != ':') { - return reportInvalidChar(v, c, "not valid as the first ID character"); - } - int hash = (int) c; - - for (int i = start+1; i <= end; ++i) { - c = cbuf[i]; - if (!WstxInputData.isNameChar(c, mCfgNsAware, mCfgXml11)) { - return reportInvalidChar(v, c, "not valid as an ID character"); - } - hash = (hash * 31) + (int) c; - } - - EntityDecl ent = findEntityDecl(v, cbuf, start, (end - start + 1), hash); - // only returns if it succeeded... - - return normalize ? ent.getName() : null; - } - - /** - * Method called by the validator object - * to ask attribute to verify that the default it has (if any) is - * valid for such type. - */ - public void validateDefault(InputProblemReporter rep, boolean normalize) - throws XMLStreamException - { - String normStr = validateDefaultName(rep, normalize); - if (normalize) { - mDefValue.setValue(normStr); - } - - // Ok, but was it declared? - - /* 03-Dec-2004, TSa: This is rather ugly -- need to know we - * actually really get a DTD reader, and DTD reader needs - * to expose a special method... but it gets things done. - */ - EntityDecl ent = ((MinimalDTDReader) rep).findEntity(normStr); - checkEntity(rep, normStr, ent); - } -} diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/dtd/DTDEnumAttr.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/dtd/DTDEnumAttr.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/dtd/DTDEnumAttr.java 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/dtd/DTDEnumAttr.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,93 +0,0 @@ -package com.ctc.wstx.dtd; - -import javax.xml.stream.XMLStreamException; - -import com.ctc.wstx.sr.InputProblemReporter; -import com.ctc.wstx.util.PrefixedName; -import com.ctc.wstx.util.WordResolver; - -/** - * Specific attribute class for attributes that have enumerated values. - */ -public final class DTDEnumAttr - extends DTDAttribute -{ - final WordResolver mEnumValues; - - /* - /////////////////////////////////////////////////// - // Life-cycle - /////////////////////////////////////////////////// - */ - - public DTDEnumAttr(PrefixedName name, DefaultAttrValue defValue, - int specIndex, boolean nsAware, boolean xml11, - WordResolver enumValues) - { - super(name, defValue, specIndex, nsAware, xml11); - mEnumValues = enumValues; - } - - public DTDAttribute cloneWith(int specIndex) - { - return new DTDEnumAttr(mName, mDefValue, specIndex, mCfgNsAware, - mCfgXml11, mEnumValues); - } - - /* - /////////////////////////////////////////////////// - // Public API - /////////////////////////////////////////////////// - */ - - public int getValueType() { - return TYPE_ENUMERATED; - } - - /* - /////////////////////////////////////////////////// - // Public API, validation - /////////////////////////////////////////////////// - */ - - /** - * Method called by the validator - * to let the attribute do necessary normalization and/or validation - * for the value. - */ - public String validate(DTDValidatorBase v, char[] cbuf, int start, int end, boolean normalize) - throws XMLStreamException - { - String ok = validateEnumValue(cbuf, start, end, normalize, mEnumValues); - if (ok == null) { - String val = new String(cbuf, start, (end-start)); - return reportValidationProblem(v, "Invalid enumerated value '"+val+"': has to be one of (" - +mEnumValues+")"); - } - return ok; - } - - /** - * Method called by the validator - * to ask attribute to verify that the default it has (if any) is - * valid for such type. - */ - public void validateDefault(InputProblemReporter rep, boolean normalize) - throws XMLStreamException - { - String def = validateDefaultNmToken(rep, normalize); - - // And then that it's one of listed values: - String shared = mEnumValues.find(def); - if (shared == null) { - reportValidationProblem(rep, "Invalid default value '"+def+"': has to be one of (" - +mEnumValues+")"); - return; - } - - // Ok, cool it's ok... - if (normalize) { - mDefValue.setValue(shared); - } - } -} diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/dtd/DTDEventListener.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/dtd/DTDEventListener.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/dtd/DTDEventListener.java 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/dtd/DTDEventListener.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,51 +0,0 @@ -/* Woodstox XML processor - * - * Copyright (c) 2004- Tatu Saloranta, tatu.saloranta@iki.fi - * - * Licensed under the License specified in file LICENSE, included with - * the source code. - * You may not use this file except in compliance with the License. - * - * 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 com.ctc.wstx.dtd; - -import java.net.URL; - -import javax.xml.stream.XMLStreamException; - -public interface DTDEventListener -{ - // Configuration - - /** - * @return True, if there is a listener interested in getting comment - * events within DTD subset (since that's optional) - */ - public boolean dtdReportComments(); - - // Basic content events - - public void dtdProcessingInstruction(String target, String data); - public void dtdComment(char[] data, int offset, int len); - public void dtdSkippedEntity(String name); - - // DTD declarations that must be exposed - public void dtdNotationDecl(String name, String publicId, String systemId, URL baseURL) - throws XMLStreamException; - - public void dtdUnparsedEntityDecl(String name, String publicId, String systemId, String notationName, URL baseURL) - throws XMLStreamException; - - // DTD declarations that can be exposed - - public void attributeDecl(String eName, String aName, String type, String mode, String value); - public void dtdElementDecl(String name, String model); - public void dtdExternalEntityDecl(String name, String publicId, String systemId); - public void dtdInternalEntityDecl(String name, String value); -} diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/dtd/DTDIdAttr.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/dtd/DTDIdAttr.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/dtd/DTDIdAttr.java 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/dtd/DTDIdAttr.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,131 +0,0 @@ -package com.ctc.wstx.dtd; - -import javax.xml.stream.Location; -import javax.xml.stream.XMLStreamException; - -import com.ctc.wstx.cfg.ErrorConsts; -import com.ctc.wstx.io.WstxInputData; -import com.ctc.wstx.sr.InputProblemReporter; -import com.ctc.wstx.util.ElementId; -import com.ctc.wstx.util.ElementIdMap; -import com.ctc.wstx.util.PrefixedName; - -/** - * Specific attribute class for attributes that contain (unique) - * identifiers. - */ -public final class DTDIdAttr - extends DTDAttribute -{ - /* - /////////////////////////////////////////////////// - // Life-cycle - /////////////////////////////////////////////////// - */ - - /** - * Main constructor. Note that id attributes can never have - * default values. - *

- * note: although ID attributes are not to have default value, - * this is 'only' a validity constraint, and in dtd-aware-but- - * not-validating mode it is apparently 'legal' to add default - * values. - */ - public DTDIdAttr(PrefixedName name, DefaultAttrValue defValue, int specIndex, - boolean nsAware, boolean xml11) - { - super(name, defValue, specIndex, nsAware, xml11); - } - - public DTDAttribute cloneWith(int specIndex) - { - return new DTDIdAttr(mName, mDefValue, specIndex, mCfgNsAware, mCfgXml11); - } - - /* - /////////////////////////////////////////////////// - // Public API - /////////////////////////////////////////////////// - */ - - public int getValueType() { - return TYPE_ID; - } - - public boolean typeIsId() { - return true; - } - - /* - /////////////////////////////////////////////////// - // Public API, validation - /////////////////////////////////////////////////// - */ - - /** - * Method called by the validator - * to let the attribute do necessary normalization and/or validation - * for the value. - */ - public String validate(DTDValidatorBase v, char[] cbuf, int start, int end, boolean normalize) - throws XMLStreamException - { - // Let's trim leading white space first... - while (start < end && WstxInputData.isSpaceChar(cbuf[start])) { - ++start; - } - - // No id? - if (start >= end) { - return reportValidationProblem(v, "Empty ID value"); - } - --end; // so that it now points to the last char - while (end > start && WstxInputData.isSpaceChar(cbuf[end])) { - --end; - } - - // Ok, need to check char validity, and also calc hash code: - char c = cbuf[start]; - if (!WstxInputData.isNameStartChar(c, mCfgNsAware, mCfgXml11)) { - return reportInvalidChar(v, c, "not valid as the first ID character"); - } - int hash = (int) c; - for (int i = start+1; i <= end; ++i) { - c = cbuf[i]; - if (!WstxInputData.isNameChar(c, mCfgNsAware, mCfgXml11)) { - return reportInvalidChar(v, c, "not valid as an ID character"); - } - hash = (hash * 31) + (int) c; - } - - // Either way, we do need to validate characters, and calculate hash - ElementIdMap m = v.getIdMap(); - PrefixedName elemName = v.getElemName(); - Location loc = v.getLocation(); - ElementId id = m.addDefined(cbuf, start, (end - start + 1), hash, - loc, elemName, mName); - - // We can detect dups by checking if Location is the one we passed: - if (id.getLocation() != loc) { - return reportValidationProblem(v, "Duplicate id '"+id.getId()+"', first declared at " - +id.getLocation()); - } - - if (normalize) { - return id.getId(); - } - return null; - } - - /** - * Method called by the validator - * to ask attribute to verify that the default it has (if any) is - * valid for such type. - */ - public void validateDefault(InputProblemReporter rep, boolean normalize) - { - // Should never get called - throw new IllegalStateException(ErrorConsts.ERR_INTERNAL); - } -} diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/dtd/DTDId.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/dtd/DTDId.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/dtd/DTDId.java 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/dtd/DTDId.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,139 +0,0 @@ -/* Woodstox XML processor - * - * Copyright (c) 2004- Tatu Saloranta, tatu.saloranta@iki.fi - * - * Licensed under the License specified in the file LICENSE which is - * included with the source code. - * You may not use this file except in compliance with the License. - * - * 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 com.ctc.wstx.dtd; - -import java.net.URI; - -/** - * Simple key object class, used for accessing (external) DTDs when stored for - * caching. Main idea is that the primary id of a DTD (public or system id; - * latter normalized if possible) - * has to match, as well as couple of on/off settings for parsing (namespace - * support, text normalization). - * Latter restriction is needed since although DTDs do not deal - * with (or understand) namespaces, some parsing is done to be able to validate - * namespace aware/non-aware documents, and handling differs between the two. - * As to primary key part, public id is used if one was defined; if so, - * comparison is String equality. If not, then system id is compared: system - * id has to be expressed as URL if so. - */ -public final class DTDId -{ - protected final String mPublicId; - - protected final URI mSystemId; - - protected final int mConfigFlags; - - protected final boolean mXml11; - - protected int mHashCode = 0; - - /* - /////////////////////////////////////////////////////////////////////// - // Life-cycle: - /////////////////////////////////////////////////////////////////////// - */ - - private DTDId(String publicId, URI systemId, int configFlags, boolean xml11) - { - mPublicId = publicId; - mSystemId = systemId; - mConfigFlags = configFlags; - mXml11 = xml11; - } - - public static DTDId constructFromPublicId(String publicId, int configFlags, - boolean xml11) - { - if (publicId == null || publicId.length() == 0) { - throw new IllegalArgumentException("Empty/null public id."); - } - return new DTDId(publicId, null, configFlags, xml11); - } - - public static DTDId constructFromSystemId(URI systemId, int configFlags, - boolean xml11) - { - if (systemId == null) { - throw new IllegalArgumentException("Null system id."); - } - return new DTDId(null, systemId, configFlags, xml11); - } - - public static DTDId construct(String publicId, URI systemId, int configFlags, boolean xml11) - { - if (publicId != null && publicId.length() > 0) { - return new DTDId(publicId, null, configFlags, xml11); - } - if (systemId == null) { - throw new IllegalArgumentException("Illegal arguments; both public and system id null/empty."); - } - return new DTDId(null, systemId, configFlags, xml11); - } - - /* - /////////////////////////////////////////////////////////////////////// - // Overridden standard methods - /////////////////////////////////////////////////////////////////////// - */ - - public int hashCode() { - int hash = mHashCode; - if (hash == 0) { - hash = mConfigFlags; - if (mPublicId != null) { - hash ^= mPublicId.hashCode(); - } else { - hash ^= mSystemId.hashCode(); - } - if (mXml11) { - hash ^= 1; - } - mHashCode = hash; - } - return hash; - } - - public String toString() { - StringBuffer sb = new StringBuffer(60); - sb.append("Public-id: "); - sb.append(mPublicId); - sb.append(", system-id: "); - sb.append(mSystemId); - sb.append(" [config flags: 0x"); - sb.append(Integer.toHexString(mConfigFlags)); - sb.append("], xml11: "); - sb.append(mXml11); - return sb.toString(); - } - - public boolean equals(Object o) - { - if (o == this) return true; - if (o == null || o.getClass() != getClass()) return false; - DTDId other = (DTDId) o; - if (other.mConfigFlags != mConfigFlags - || other.mXml11 != mXml11) { - return false; - } - if (mPublicId != null) { - String op = other.mPublicId; - return (op != null) && op.equals(mPublicId); - } - return mSystemId.equals(other.mSystemId); - } -} diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/dtd/DTDIdRefAttr.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/dtd/DTDIdRefAttr.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/dtd/DTDIdRefAttr.java 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/dtd/DTDIdRefAttr.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,116 +0,0 @@ -package com.ctc.wstx.dtd; - -import javax.xml.stream.Location; -import javax.xml.stream.XMLStreamException; - -import com.ctc.wstx.io.WstxInputData; -import com.ctc.wstx.sr.InputProblemReporter; -import com.ctc.wstx.util.ElementId; -import com.ctc.wstx.util.ElementIdMap; -import com.ctc.wstx.util.PrefixedName; - -/** - * Attribute class for attributes that contain references - * to elements that have matching identifier specified. - */ -public final class DTDIdRefAttr - extends DTDAttribute -{ - /* - /////////////////////////////////////////////////// - // Life-cycle - /////////////////////////////////////////////////// - */ - - /** - * Main constructor. - */ - public DTDIdRefAttr(PrefixedName name, DefaultAttrValue defValue, int specIndex, - boolean nsAware, boolean xml11) - { - super(name, defValue, specIndex, nsAware, xml11); - } - - public DTDAttribute cloneWith(int specIndex) - { - return new DTDIdRefAttr(mName, mDefValue, specIndex, mCfgNsAware, mCfgXml11); - } - - /* - /////////////////////////////////////////////////// - // Public API - /////////////////////////////////////////////////// - */ - - public int getValueType() { - return TYPE_IDREF; - } - - /* - /////////////////////////////////////////////////// - // Public API, validation - /////////////////////////////////////////////////// - */ - - /** - * Method called by the validator - * to let the attribute do necessary normalization and/or validation - * for the value. - */ - public String validate(DTDValidatorBase v, char[] cbuf, int start, int end, boolean normalize) - throws XMLStreamException - { - /* Let's skip leading/trailing white space, even if we are not - * to normalize visible attribute value. This allows for better - * round-trip handling, but still allow validation. - */ - while (start < end && WstxInputData.isSpaceChar(cbuf[start])) { - ++start; - } - - if (start >= end) { // empty (all white space) value? - return reportValidationProblem(v, "Empty IDREF value"); - } - - --end; // so that it now points to the last char - while (end > start && WstxInputData.isSpaceChar(cbuf[end])) { - --end; - } - - // Ok, need to check char validity, and also calc hash code: - char c = cbuf[start]; - if (!WstxInputData.isNameStartChar(c, mCfgNsAware, mCfgXml11)) { - return reportInvalidChar(v, c, "not valid as the first IDREF character"); - } - int hash = (int) c; - for (int i = start+1; i <= end; ++i) { - c = cbuf[i]; - if (!WstxInputData.isNameChar(c, mCfgNsAware, mCfgXml11)) { - return reportInvalidChar(v, c, "not valid as an IDREF character"); - } - hash = (hash * 31) + (int) c; - } - - // Ok, let's check and update id ref list... - ElementIdMap m = v.getIdMap(); - Location loc = v.getLocation(); - ElementId id = m.addReferenced(cbuf, start, (end - start + 1), hash, - loc, v.getElemName(), mName); - // and that's all; no more checks needed here - return normalize ? id.getId() : null; - } - - /** - * Method called by the validator - * to ask attribute to verify that the default it has (if any) is - * valid for such type. - */ - public void validateDefault(InputProblemReporter rep, boolean normalize) - throws XMLStreamException - { - String def = validateDefaultName(rep, normalize); - if (normalize) { - mDefValue.setValue(def); - } - } -} diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/dtd/DTDIdRefsAttr.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/dtd/DTDIdRefsAttr.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/dtd/DTDIdRefsAttr.java 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/dtd/DTDIdRefsAttr.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,158 +0,0 @@ -package com.ctc.wstx.dtd; - -import javax.xml.stream.Location; -import javax.xml.stream.XMLStreamException; - -import com.ctc.wstx.io.WstxInputData; -import com.ctc.wstx.sr.InputProblemReporter; -import com.ctc.wstx.util.ElementId; -import com.ctc.wstx.util.ElementIdMap; -import com.ctc.wstx.util.PrefixedName; - -/** - * Attribute class for attributes that contain multiple references - * to elements that have matching identifier specified. - */ -public final class DTDIdRefsAttr - extends DTDAttribute -{ - /* - /////////////////////////////////////////////////// - // Life-cycle - /////////////////////////////////////////////////// - */ - - /** - * Main constructor. - */ - public DTDIdRefsAttr(PrefixedName name, DefaultAttrValue defValue, int specIndex, - boolean nsAware, boolean xml11) - { - super(name, defValue, specIndex, nsAware, xml11); - } - - public DTDAttribute cloneWith(int specIndex) - { - return new DTDIdRefsAttr(mName, mDefValue, specIndex, mCfgNsAware, mCfgXml11); - } - - /* - /////////////////////////////////////////////////// - // Public API - /////////////////////////////////////////////////// - */ - - public int getValueType() { - return TYPE_IDREFS; - } - - /* - /////////////////////////////////////////////////// - // Public API, validation - /////////////////////////////////////////////////// - */ - - public String validate(DTDValidatorBase v, char[] cbuf, int start, int end, boolean normalize) - throws XMLStreamException - { - /* Let's skip leading/trailing white space, even if we are not - * to normalize visible attribute value. This allows for better - * round-trip handling (no changes for physical value caller - * gets), but still allows succesful validation. - */ - while (start < end && WstxInputData.isSpaceChar(cbuf[start])) { - ++start; - } - - // No id? - if (start >= end) { - return reportValidationProblem(v, "Empty IDREFS value"); - } - - --end; // so that it now points to the last char - // We now the first char is not a space by now... - while (end > start && WstxInputData.isSpaceChar(cbuf[end])) { - --end; - } - - // Ok; now start points to first, end to last char (both inclusive) - ElementIdMap m = v.getIdMap(); - Location loc = v.getLocation(); - - String idStr = null; - StringBuffer sb = null; - while (start <= end) { - // Ok, need to check char validity, and also calc hash code: - char c = cbuf[start]; - if (!WstxInputData.isNameStartChar(c, mCfgNsAware, mCfgXml11)) { - return reportInvalidChar(v, c, "not valid as the first IDREFS character"); - } - int hash = (int) c; - int i = start+1; - for (; i <= end; ++i) { - c = cbuf[i]; - if (WstxInputData.isSpaceChar(c)) { - break; - } - if (!WstxInputData.isNameChar(c, mCfgNsAware, mCfgXml11)) { - return reportInvalidChar(v, c, "not valid as an IDREFS character"); - } - hash = (hash * 31) + (int) c; - } - - // Ok, got the next id ref... - ElementId id = m.addReferenced(cbuf, start, i - start, hash, - loc, v.getElemName(), mName); - - // Can skip the trailing space char (if there was one) - start = i+1; - - /* When normalizing, we can possibly share id String, or - * alternatively, compose normalized String if multiple - */ - if (normalize) { - if (idStr == null) { // first idref - idStr = id.getId(); - } else { - if (sb == null) { - sb = new StringBuffer(idStr); - } - idStr = id.getId(); - sb.append(' '); - sb.append(idStr); - } - } - - // Ok, any white space to skip? - while (start <= end && WstxInputData.isSpaceChar(cbuf[start])) { - ++start; - } - } - - if (normalize) { - if (sb != null) { - idStr = sb.toString(); - } - return idStr; - } - - return null; - } - - /** - * Method called by the validator - * to ask attribute to verify that the default it has (if any) is - * valid for such type. - *

- * It's unlikely there will be default values... but just in case, - * let's implement it properly. - */ - public void validateDefault(InputProblemReporter rep, boolean normalize) - throws XMLStreamException - { - String def = validateDefaultNames(rep, normalize); - if (normalize) { - mDefValue.setValue(def); - } - } -} diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/dtd/DTDNmTokenAttr.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/dtd/DTDNmTokenAttr.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/dtd/DTDNmTokenAttr.java 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/dtd/DTDNmTokenAttr.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,108 +0,0 @@ -package com.ctc.wstx.dtd; - -import javax.xml.stream.XMLStreamException; - -import com.ctc.wstx.io.WstxInputData; -import com.ctc.wstx.sr.InputProblemReporter; -import com.ctc.wstx.util.PrefixedName; - -/** - * Specific attribute class for attributes that contain (unique) - * identifiers. - */ -public final class DTDNmTokenAttr - extends DTDAttribute -{ - /* - /////////////////////////////////////////////////// - // Life-cycle - /////////////////////////////////////////////////// - */ - - /** - * Main constructor. - */ - public DTDNmTokenAttr(PrefixedName name, DefaultAttrValue defValue, int specIndex, - boolean nsAware, boolean xml11) - { - super(name, defValue, specIndex, nsAware, xml11); - } - - public DTDAttribute cloneWith(int specIndex) - { - return new DTDNmTokenAttr(mName, mDefValue, specIndex, mCfgNsAware, mCfgXml11); - } - - /* - /////////////////////////////////////////////////// - // Public API - /////////////////////////////////////////////////// - */ - - public int getValueType() { - return TYPE_NMTOKEN; - } - - /* - /////////////////////////////////////////////////// - // Public API, validation - /////////////////////////////////////////////////// - */ - - /** - * Method called by the validator - * to let the attribute do necessary normalization and/or validation - * for the value. - */ - public String validate(DTDValidatorBase v, char[] cbuf, int start, int end, boolean normalize) - throws XMLStreamException - { - int origLen = end-start; - - // Let's trim leading white space first... - while (start < end && WstxInputData.isSpaceChar(cbuf[start])) { - ++start; - } - - // Empty value? - if (start >= end) { - return reportValidationProblem(v, "Empty NMTOKEN value"); - } - - --end; // so that it now points to the last char - while (end > start && WstxInputData.isSpaceChar(cbuf[end])) { - --end; - } - - // Ok, need to check char validity - for (int i = start; i <= end; ++i) { - char c = cbuf[i]; - if (!WstxInputData.isNameChar(c, mCfgNsAware, mCfgXml11)) { - return reportInvalidChar(v, c, "not valid NMTOKEN character"); - } - } - - if (normalize) { - // Let's only create the String if we trimmed something - int len = (end - start)+1; - if (len != origLen) { - return new String(cbuf, start, len); - } - } - return null; - } - - /** - * Method called by the validator - * to ask attribute to verify that the default it has (if any) is - * valid for such type. - */ - public void validateDefault(InputProblemReporter rep, boolean normalize) - throws XMLStreamException - { - String def = validateDefaultNmToken(rep, normalize); - if (normalize) { - mDefValue.setValue(def); - } - } -} diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/dtd/DTDNmTokensAttr.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/dtd/DTDNmTokensAttr.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/dtd/DTDNmTokensAttr.java 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/dtd/DTDNmTokensAttr.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,205 +0,0 @@ -package com.ctc.wstx.dtd; - -import javax.xml.stream.XMLStreamException; - -import com.ctc.wstx.io.WstxInputData; -import com.ctc.wstx.sr.InputProblemReporter; -import com.ctc.wstx.util.PrefixedName; - -/** - * Specific attribute class for attributes that contain (unique) - * identifiers. - */ -public final class DTDNmTokensAttr - extends DTDAttribute -{ - /* - /////////////////////////////////////////////////// - // Life-cycle - /////////////////////////////////////////////////// - */ - - /** - * Main constructor. - */ - public DTDNmTokensAttr(PrefixedName name, DefaultAttrValue defValue, int specIndex, - boolean nsAware, boolean xml11) - { - super(name, defValue, specIndex, nsAware, xml11); - } - - public DTDAttribute cloneWith(int specIndex) - { - return new DTDNmTokensAttr(mName, mDefValue, specIndex, mCfgNsAware, mCfgXml11); - } - - /* - /////////////////////////////////////////////////// - // Public API - /////////////////////////////////////////////////// - */ - - public int getValueType() { - return TYPE_NMTOKENS; - } - - /* - /////////////////////////////////////////////////// - // Public API, validation - /////////////////////////////////////////////////// - */ - - /** - * Method called by the validator - * to let the attribute do necessary normalization and/or validation - * for the value. - */ - public String validate(DTDValidatorBase v, char[] cbuf, int start, int end, boolean normalize) - throws XMLStreamException - { - //int origStart = start; - - /* First things first; let's ensure value is not empty (all - * white space)... - */ - while (start < end && WstxInputData.isSpaceChar(cbuf[start])) { - ++start; - } - // Empty value? - if (start >= end) { - return reportValidationProblem(v, "Empty NMTOKENS value"); - } - - /* Then, let's have separate handling for normalizing and - * non-normalizing case, since latter is trivially easy case: - */ - if (!normalize) { - for (; start < end; ++start) { - char c = cbuf[start]; - if (!WstxInputData.isSpaceChar(c) - && !WstxInputData.isNameChar(c, mCfgNsAware, mCfgXml11)) { - return reportInvalidChar(v, c, "not valid as NMTOKENS character"); - } - } - return null; // ok, all good - } - - //boolean trimmed = (origStart != start); - //origStart = start; - - --end; // so that it now points to the last char - // Wouldn't absolutely have to trim trailing... but is easy to do - while (end > start && WstxInputData.isSpaceChar(cbuf[end])) { - --end; - //trimmed = true; - } - - /* Ok, now, need to check we only have valid chars, and maybe - * also coalesce multiple spaces, if any. - */ - StringBuffer sb = null; - - while (start <= end) { - int i = start; - for (; i <= end; ++i) { - char c = cbuf[i]; - if (WstxInputData.isSpaceChar(c)) { - break; - } - if (!WstxInputData.isNameChar(c, mCfgNsAware, mCfgXml11)) { - return reportInvalidChar(v, c, "not valid as an NMTOKENS character"); - } - } - - if (sb == null) { - sb = new StringBuffer(end - start + 1); - } else { - sb.append(' '); - } - sb.append(cbuf, start, (i - start)); - - start = i + 1; - // Ok, any white space to skip? - while (start <= end && WstxInputData.isSpaceChar(cbuf[start])) { - ++start; - } - } - - /* 27-Nov-2005, TSa: Could actually optimize trimming, and often - * avoid using StringBuffer... but let's only do it if it turns - * out dealing with NMTOKENS normalization shows up on profiling... - */ - return sb.toString(); - } - - /** - * Method called by the validator - * to ask attribute to verify that the default it has (if any) is - * valid for such type. - */ - public void validateDefault(InputProblemReporter rep, boolean normalize) - throws XMLStreamException - { - String defValue = mDefValue.getValue(); - int len = defValue.length(); - - // Then code similar to actual value validation: - StringBuffer sb = null; - int count = 0; - int start = 0; - - main_loop: - while (start < len) { - char c = defValue.charAt(start); - - // Ok, any white space to skip? - while (true) { - if (!WstxInputData.isSpaceChar(c)) { - break; - } - if (++start >= len) { - break main_loop; - } - c = defValue.charAt(start); - } - - int i = start+1; - - do { - if (++i >= len) { - break; - } - c = defValue.charAt(i); - } while (!WstxInputData.isSpaceChar(c)); - ++count; - String token = defValue.substring(start, i); - int illegalIx = WstxInputData.findIllegalNmtokenChar(token, mCfgNsAware, mCfgXml11); - if (illegalIx >= 0) { - reportValidationProblem(rep, "Invalid default value '"+defValue - +"'; character #"+illegalIx+" (" - +WstxInputData.getCharDesc(defValue.charAt(illegalIx)) - +") not a valid NMTOKENS character"); - } - - if (normalize) { - if (sb == null) { - sb = new StringBuffer(i - start + 32); - } else { - sb.append(' '); - } - sb.append(token); - } - start = i+1; - } - - if (count == 0) { - reportValidationProblem(rep, "Invalid default value '"+defValue - +"'; empty String is not a valid NMTOKENS value"); - return; - } - - if (normalize) { - mDefValue.setValue(sb.toString()); - } - } -} diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/dtd/DTDNotationAttr.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/dtd/DTDNotationAttr.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/dtd/DTDNotationAttr.java 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/dtd/DTDNotationAttr.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,100 +0,0 @@ -package com.ctc.wstx.dtd; - -import javax.xml.stream.XMLStreamException; - -import com.ctc.wstx.sr.InputProblemReporter; -import com.ctc.wstx.util.PrefixedName; -import com.ctc.wstx.util.WordResolver; - -/** - * Specific attribute class for attributes that are of NOTATION type, - * and also contain enumerated set of legal values. - */ -public final class DTDNotationAttr - extends DTDAttribute -{ - final WordResolver mEnumValues; - - /* - /////////////////////////////////////////////////// - // Life-cycle - /////////////////////////////////////////////////// - */ - - public DTDNotationAttr(PrefixedName name, DefaultAttrValue defValue, - int specIndex, boolean nsAware, boolean xml11, - WordResolver enumValues) - { - super(name, defValue, specIndex, nsAware, xml11); - mEnumValues = enumValues; - } - - public DTDAttribute cloneWith(int specIndex) - { - return new DTDNotationAttr(mName, mDefValue, specIndex, - mCfgNsAware, mCfgXml11, mEnumValues); - } - - /* - /////////////////////////////////////////////////// - // Public API - /////////////////////////////////////////////////// - */ - - public int getValueType() { - return TYPE_NOTATION; - } - - public boolean typeIsNotation() { - return true; - } - - /* - /////////////////////////////////////////////////// - // Public API, validation - /////////////////////////////////////////////////// - */ - - /** - * Method called by the validator - * to let the attribute do necessary normalization and/or validation - * for the value. - *

- * Note: identical to the implementation in {@link DTDEnumAttr} - */ - public String validate(DTDValidatorBase v, char[] cbuf, int start, int end, boolean normalize) - throws XMLStreamException - { - String ok = validateEnumValue(cbuf, start, end, normalize, mEnumValues); - if (ok == null) { - String val = new String(cbuf, start, (end-start)); - return reportValidationProblem(v, "Invalid notation value '"+val+"': has to be one of (" - +mEnumValues+")"); - } - return ok; - } - - /** - * Method called by the validator - * to ask attribute to verify that the default it has (if any) is - * valid for such type. - */ - public void validateDefault(InputProblemReporter rep, boolean normalize) - throws XMLStreamException - { - // First, basic checks that it's a valid non-empty name: - String def = validateDefaultName(rep, normalize); - - // And then that it's one of listed values: - String shared = mEnumValues.find(def); - if (shared == null) { - reportValidationProblem(rep, "Invalid default value '"+def+"': has to be one of (" - +mEnumValues+")"); - } - - // Ok, cool it's ok... - if (normalize) { - mDefValue.setValue(shared); - } - } -} diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/dtd/DTDSchemaFactory.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/dtd/DTDSchemaFactory.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/dtd/DTDSchemaFactory.java 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/dtd/DTDSchemaFactory.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,202 +0,0 @@ -/* Woodstox XML processor - * - * Copyright (c) 2004- Tatu Saloranta, tatu.saloranta@iki.fi - * - * Licensed under the License specified in the file LICENSE which is - * included with the source code. - * You may not use this file except in compliance with the License. - * - * 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 com.ctc.wstx.dtd; - -import java.io.*; -import java.net.URL; - -import javax.xml.stream.*; - -import org.codehaus.stax2.validation.*; - -import com.ctc.wstx.api.ReaderConfig; -import com.ctc.wstx.api.ValidatorConfig; -import com.ctc.wstx.cfg.XmlConsts; -import com.ctc.wstx.exc.WstxIOException; -import com.ctc.wstx.io.*; -import com.ctc.wstx.util.DefaultXmlSymbolTable; -import com.ctc.wstx.util.SymbolTable; -import com.ctc.wstx.util.URLUtil; - -/** - * Factory for creating DTD validator schema objects (shareable stateless - * "blueprints" for creating actual validators). - *

- * Due to close coupling of XML and DTD, some of the functionality - * implemented (like that of reading internal subsets embedded in XML - * documents) is only accessible by core Woodstox. The externally - * accessible - */ -public class DTDSchemaFactory - extends XMLValidationSchemaFactory -{ - /* - ///////////////////////////////////////////////////// - // Objects shared by actual parsers - ///////////////////////////////////////////////////// - */ - - /** - * 'Root' symbol table, used for creating actual symbol table instances, - * but never as is. - */ - final static SymbolTable mRootSymbols = DefaultXmlSymbolTable.getInstance(); - static { - mRootSymbols.setInternStrings(true); - } - - /** - * Current configurations for this factory - */ - protected final ValidatorConfig mSchemaConfig; - - /** - * This configuration object is used (instead of a more specific one) - * since the actual DTD reader uses such configuration object. - */ - protected final ReaderConfig mReaderConfig; - - public DTDSchemaFactory() - { - super(XMLValidationSchema.SCHEMA_ID_DTD); - mReaderConfig = ReaderConfig.createFullDefaults(); - mSchemaConfig = ValidatorConfig.createDefaults(); - } - - /* - //////////////////////////////////////////////////////////// - // Stax2, Configuration methods - //////////////////////////////////////////////////////////// - */ - - public boolean isPropertySupported(String propName) - { - return mSchemaConfig.isPropertySupported(propName); - } - - public boolean setProperty(String propName, Object value) - { - return mSchemaConfig.setProperty(propName, value); - } - - public Object getProperty(String propName) - { - return mSchemaConfig.getProperty(propName); - } - - /* - //////////////////////////////////////////////////////////// - // Stax2, Factory methods - //////////////////////////////////////////////////////////// - */ - - public XMLValidationSchema createSchema(InputStream in, String encoding, - String publicId, String systemId) - throws XMLStreamException - { - ReaderConfig rcfg = createPrivateReaderConfig(); - return doCreateSchema(rcfg, StreamBootstrapper.getInstance - (publicId, systemId, in), publicId, systemId, null); - } - - public XMLValidationSchema createSchema(Reader r, String publicId, - String systemId) - throws XMLStreamException - { - ReaderConfig rcfg = createPrivateReaderConfig(); - return doCreateSchema(rcfg, ReaderBootstrapper.getInstance - (publicId, systemId, r, null), publicId, systemId, null); - } - - public XMLValidationSchema createSchema(URL url) - throws XMLStreamException - { - ReaderConfig rcfg = createPrivateReaderConfig(); - try { - InputStream in = URLUtil.inputStreamFromURL(url); - return doCreateSchema(rcfg, StreamBootstrapper.getInstance - (null, null, in), - null, url.toExternalForm(), url); - } catch (IOException ioe) { - throw new WstxIOException(ioe); - } - } - - public XMLValidationSchema createSchema(File f) - throws XMLStreamException - { - ReaderConfig rcfg = createPrivateReaderConfig(); - try { - URL url = f.toURL(); - return doCreateSchema(rcfg, StreamBootstrapper.getInstance - (null, null, new FileInputStream(f)), - null, url.toExternalForm(), url); - } catch (IOException ioe) { - throw new WstxIOException(ioe); - } - } - - /* - //////////////////////////////////////////////////////////// - // Woodstox-specific API - //////////////////////////////////////////////////////////// - */ - - /* - //////////////////////////////////////////////////////////// - // Internal methods - //////////////////////////////////////////////////////////// - */ - - /** - * The main validator construction method, called by all externally - * visible methods. - */ - protected XMLValidationSchema doCreateSchema - (ReaderConfig rcfg, InputBootstrapper bs, String publicId, String systemId, URL ctxt) - throws XMLStreamException - { - try { - Reader r = bs.bootstrapInput(rcfg, false, XmlConsts.XML_V_UNKNOWN); - if (bs.declaredXml11()) { - rcfg.enableXml11(true); - } - if (ctxt == null) { // this is just needed as context for param entity expansion - ctxt = URLUtil.urlFromCurrentDir(); - } - /* Note: need to pass unknown for 'xmlVersion' here (as well as - * above for bootstrapping), since this is assumed to be the main - * level parsed document and no xml version compatibility checks - * should be done. - */ - WstxInputSource src = InputSourceFactory.constructEntitySource - (rcfg, null, null, bs, publicId, systemId, XmlConsts.XML_V_UNKNOWN, ctxt, r); - - /* true -> yes, fully construct for validation - * (does not mean it has to be used for validation, but required - * if it is to be used for that purpose) - */ - return FullDTDReader.readExternalSubset(src, rcfg, /*int.subset*/null, true, bs.getDeclaredVersion()); - } catch (IOException ioe) { - throw new WstxIOException(ioe); - } - } - - private ReaderConfig createPrivateReaderConfig() - { - return mReaderConfig.createNonShared(mRootSymbols.makeChild()); - } -} diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/dtd/DTDSubsetImpl.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/dtd/DTDSubsetImpl.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/dtd/DTDSubsetImpl.java 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/dtd/DTDSubsetImpl.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,527 +0,0 @@ -/* Woodstox XML processor - * - * Copyright (c) 2004- Tatu Saloranta, tatu.saloranta@iki.fi - * - * Licensed under the License specified in file LICENSE, included with - * the source code. - * You may not use this file except in compliance with the License. - * - * 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 com.ctc.wstx.dtd; - -import java.text.MessageFormat; -import java.util.*; - -import javax.xml.stream.Location; -import javax.xml.stream.XMLStreamException; -import javax.xml.stream.events.NotationDeclaration; - -import org.codehaus.stax2.validation.*; - -import com.ctc.wstx.cfg.ErrorConsts; -import com.ctc.wstx.exc.WstxParsingException; -import com.ctc.wstx.sr.InputProblemReporter; -import com.ctc.wstx.util.DataUtil; - -/** - * The default implementation of {@link DTDSubset} - */ -public final class DTDSubsetImpl - extends DTDSubset -{ - /** - * Whether this subset is cachable. Only those external - * subsets that do not refer to PEs defined by internal subsets (or - * GEs via default attribute value expansion) are cachable. - */ - final boolean mIsCachable; - - /** - * Whether this subset has full validation information; and - * consequently whether it will do actual validation, or just allow - * access to type information, notations, entities, and add default - * attribute values. - */ - final boolean mFullyValidating; - - /** - * Flag that indicates whether any of the elements declarared - * has any attribute default values for namespace pseudo-attributes. - */ - final boolean mHasNsDefaults; - - /* - ////////////////////////////////////////////////////// - // Entity information - ////////////////////////////////////////////////////// - */ - - /** - * Map (name-to-EntityDecl) of general entity declarations (internal, - * external) for this DTD subset. - */ - final HashMap mGeneralEntities; - - /** - * Lazily instantiated List that contains all notations from - * {@link #mGeneralEntities} (preferably in their declaration order; depends - * on whether platform, ie. JDK version, has insertion-ordered - * Maps available), used by DTD event Objects. - */ - volatile transient List mGeneralEntityList = null; - - /** - * Set of names of general entities references by this subset. Note that - * only those GEs that are referenced by default attribute value - * definitions count, since GEs in text content are only expanded - * when reading documents, but attribute default values are expanded - * when reading DTD subset itself. - *

- * Needed - * for determinining if external subset materially depends on definitions - * from internal subset; if so, such subset is not cachable. - * This also - * means that information is not stored for non-cachable instance. - */ - final Set mRefdGEs; - - // // // Parameter entity info: - - /** - * Map (name-to-WEntityDeclaration) that contains all parameter entities - * defined by this subset. May be empty if such information will not be - * needed for use; for example, external subset's definitions are needed, - * nor are combined DTD set's. - */ - final HashMap mDefinedPEs; - - /** - * Set of names of parameter entities references by this subset. Needed - * when determinining if external subset materially depends on definitions - * from internal subset, which is needed to know when caching external - * subsets. - *

- * Needed - * for determinining if external subset materially depends on definitions - * from internal subset; if so, such subset is not cachable. - * This also - * means that information is not stored for non-cachable instance. - */ - final Set mRefdPEs; - - /* - ////////////////////////////////////////////////////// - // Notation definitions: - ////////////////////////////////////////////////////// - */ - - /** - * Map (name-to-NotationDecl) that this subset has defined. - */ - final HashMap mNotations; - - /** - * Lazily instantiated List that contains all notations from - * {@link #mNotations} (preferably in their declaration order; depends - * on whether platform, ie. JDK version, has insertion-ordered - * Maps available), used by DTD event Objects. - */ - transient List mNotationList = null; - - - /* - ////////////////////////////////////////////////////// - // Element definitions: - ////////////////////////////////////////////////////// - */ - - final HashMap mElements; - - /* - ////////////////////////////////////////////////////// - // Life-cycle - ////////////////////////////////////////////////////// - */ - - private DTDSubsetImpl(boolean cachable, - HashMap genEnt, Set refdGEs, - HashMap paramEnt, Set peRefs, - HashMap notations, HashMap elements, - boolean fullyValidating) - { - mIsCachable = cachable; - mGeneralEntities = genEnt; - mRefdGEs = refdGEs; - mDefinedPEs = paramEnt; - mRefdPEs = peRefs; - mNotations = notations; - mElements = elements; - mFullyValidating = fullyValidating; - - boolean anyNsDefs = false; - if (elements != null) { - Iterator it = elements.values().iterator(); - while (it.hasNext()) { - DTDElement elem = (DTDElement) it.next(); - if (elem.hasNsDefaults()) { - anyNsDefs = true; - break; - } - } - } - mHasNsDefaults = anyNsDefs; - } - - public static DTDSubsetImpl constructInstance(boolean cachable, - HashMap genEnt, Set refdGEs, - HashMap paramEnt, Set refdPEs, - HashMap notations, HashMap elements, - boolean fullyValidating) - { - return new DTDSubsetImpl(cachable, genEnt, refdGEs, - paramEnt, refdPEs, - notations, elements, - fullyValidating); - } - - /** - * Method that will combine definitions from internal and external subsets, - * producing a single DTD set. - */ - public DTDSubset combineWithExternalSubset(InputProblemReporter rep, DTDSubset extSubset) - throws XMLStreamException - { - /* First let's see if we can just reuse GE Map used by int or ext - * subset; (if only one has contents), or if not, combine them. - */ - HashMap ge1 = getGeneralEntityMap(); - HashMap ge2 = extSubset.getGeneralEntityMap(); - if (ge1 == null || ge1.isEmpty()) { - ge1 = ge2; - } else { - if (ge2 != null && !ge2.isEmpty()) { - /* Internal subset Objects are never shared or reused (and by - * extension, neither are objects they contain), so we can just - * modify GE map if necessary - */ - combineMaps(ge1, ge2); - } - } - - // Ok, then, let's combine notations similarly - HashMap n1 = getNotationMap(); - HashMap n2 = extSubset.getNotationMap(); - if (n1 == null || n1.isEmpty()) { - n1 = n2; - } else { - if (n2 != null && !n2.isEmpty()) { - /* First; let's make sure there are no colliding notation - * definitions: it's an error to try to redefine notations. - */ - checkNotations(n1, n2); - - /* Internal subset Objects are never shared or reused (and by - * extension, neither are objects they contain), so we can just - * modify notation map if necessary - */ - combineMaps(n1, n2); - } - } - - - // And finally elements, rather similarly: - HashMap e1 = getElementMap(); - HashMap e2 = extSubset.getElementMap(); - if (e1 == null || e1.isEmpty()) { - e1 = e2; - } else { - if (e2 != null && !e2.isEmpty()) { - /* Internal subset Objects are never shared or reused (and by - * extension, neither are objects they contain), so we can just - * modify element map if necessary - */ - combineElements(rep, e1, e2); - } - } - - /* Combos are not cachable, and because of that, there's no point - * in storing any PE info either. - */ - return constructInstance(false, ge1, null, null, null, n1, e1, - mFullyValidating); - } - - /* - ////////////////////////////////////////////////////// - // XMLValidationSchema implementation - ////////////////////////////////////////////////////// - */ - - public XMLValidator createValidator(ValidationContext ctxt) - throws XMLStreamException - { - if (mFullyValidating) { - return new DTDValidator(this, ctxt, mHasNsDefaults, - getElementMap(), getGeneralEntityMap()); - } - return new DTDTypingNonValidator(this, ctxt, mHasNsDefaults, - getElementMap(), getGeneralEntityMap()); - - } - - /* - ////////////////////////////////////////////////////// - // DTDValidationSchema implementation - ////////////////////////////////////////////////////// - */ - - public int getEntityCount() { - return (mGeneralEntities == null) ? 0 : mGeneralEntities.size(); - } - - public int getNotationCount() { - return (mNotations == null) ? 0 : mNotations.size(); - } - - /* - ////////////////////////////////////////////////////// - // Woodstox-specific public API - ////////////////////////////////////////////////////// - */ - - public boolean isCachable() { - return mIsCachable; - } - - public HashMap getGeneralEntityMap() { - return mGeneralEntities; - } - - public List getGeneralEntityList() - { - List l = mGeneralEntityList; - if (l == null) { - if (mGeneralEntities == null || mGeneralEntities.size() == 0) { - l = Collections.EMPTY_LIST; - } else { - l = Collections.unmodifiableList(new ArrayList(mGeneralEntities.values())); - } - mGeneralEntityList = l; - } - - return l; - } - - public HashMap getParameterEntityMap() { - return mDefinedPEs; - } - - public HashMap getNotationMap() { - return mNotations; - } - - public synchronized List getNotationList() - { - List l = mNotationList; - if (l == null) { - if (mNotations == null || mNotations.size() == 0) { - l = Collections.EMPTY_LIST; - } else { - l = Collections.unmodifiableList(new ArrayList(mNotations.values())); - } - mNotationList = l; - } - - return l; - } - - public HashMap getElementMap() { - return mElements; - } - - /** - * Method used in determining whether cached external subset instance - * can be used with specified internal subset. If ext. subset references - * any parameter/general entities int subset (re-)defines, it can not; - * otherwise it can be used. - * - * @return True if this (external) subset refers to a parameter entity - * defined in passed-in internal subset. - */ - public boolean isReusableWith(DTDSubset intSubset) - { - Set refdPEs = mRefdPEs; - - if (refdPEs != null && refdPEs.size() > 0) { - HashMap intPEs = intSubset.getParameterEntityMap(); - if (intPEs != null && intPEs.size() > 0) { - if (DataUtil.anyValuesInCommon(refdPEs, intPEs.keySet())) { - return false; - } - } - } - Set refdGEs = mRefdGEs; - - if (refdGEs != null && refdGEs.size() > 0) { - HashMap intGEs = intSubset.getGeneralEntityMap(); - if (intGEs != null && intGEs.size() > 0) { - if (DataUtil.anyValuesInCommon(refdGEs, intGEs.keySet())) { - return false; - } - } - } - return true; // yep, no dependencies overridden - } - - /* - ////////////////////////////////////////////////////// - // Overridden default methods: - ////////////////////////////////////////////////////// - */ - - public String toString() { - StringBuffer sb = new StringBuffer(); - sb.append("[DTDSubset: "); - int count = getEntityCount(); - sb.append(count); - sb.append(" general entities"); - sb.append(']'); - return sb.toString(); - } - - /* - ////////////////////////////////////////////////////// - // Convenience methods used by other classes - ////////////////////////////////////////////////////// - */ - - public static void throwNotationException(NotationDeclaration oldDecl, NotationDeclaration newDecl) - throws XMLStreamException - { - throw new WstxParsingException - (MessageFormat.format(ErrorConsts.ERR_DTD_NOTATION_REDEFD, - new Object[] { - newDecl.getName(), - oldDecl.getLocation().toString()}), - newDecl.getLocation()); - } - - public static void throwElementException(DTDElement oldElem, Location loc) - throws XMLStreamException - { - throw new WstxParsingException - (MessageFormat.format(ErrorConsts.ERR_DTD_ELEM_REDEFD, - new Object[] { - oldElem.getDisplayName(), - oldElem.getLocation().toString() }), - loc); - } - - /* - ////////////////////////////////////////////////////// - // Internal methods - ////////////////////////////////////////////////////// - */ - - /** - *

- * Note: The first Map argument WILL be modified; second one - * not. Caller needs to ensure this is acceptable. - */ - private static void combineMaps(HashMap m1, HashMap m2) - { - Iterator it = m2.entrySet().iterator(); - while (it.hasNext()) { - Map.Entry me = (Map.Entry) it.next(); - Object key = me.getKey(); - /* Int. subset has precedence, but let's guess most of - * the time there are no collisions: - */ - Object old = m1.put(key, me.getValue()); - // Oops, got value! Let's put it back - if (old != null) { - m1.put(key, old); - } - } - } - - /** - * Method that will try to merge in elements defined in the external - * subset, into internal subset; it will also check for redeclarations - * when doing this, as it's invalid to redeclare elements. Care has to - * be taken to only check actual redeclarations: placeholders should - * not cause problems. - */ - private void combineElements(InputProblemReporter rep, HashMap intElems, HashMap extElems) - throws XMLStreamException - { - Iterator it = extElems.entrySet().iterator(); - while (it.hasNext()) { - Map.Entry me = (Map.Entry) it.next(); - Object key = me.getKey(); - Object extVal = me.getValue(); - Object oldVal = intElems.get(key); - - // If there was no old value, can just merge new one in and continue - if (oldVal == null) { - intElems.put(key, extVal); - continue; - } - - DTDElement extElem = (DTDElement) extVal; - DTDElement intElem = (DTDElement) oldVal; - - // Which one is defined (if either)? - if (extElem.isDefined()) { // one from the ext subset - if (intElem.isDefined()) { // but both can't be; that's an error - throwElementException(intElem, extElem.getLocation()); - } else { - /* Note: can/should not modify the external element (by - * for example adding attributes); external element may - * be cached and shared... so, need to do the reverse, - * define the one from internal subset. - */ - intElem.defineFrom(rep, extElem, mFullyValidating); - } - } else { - if (!intElem.isDefined()) { - /* ??? Should we warn about neither of them being really - * declared? - */ - rep.reportProblem(intElem.getLocation(), - ErrorConsts.WT_ENT_DECL, - ErrorConsts.W_UNDEFINED_ELEM, - extElem.getDisplayName(), null); - - } else { - intElem.mergeMissingAttributesFrom(rep, extElem, mFullyValidating); - } - } - } - } - - private static void checkNotations(HashMap fromInt, HashMap fromExt) - throws XMLStreamException - { - /* Since it's external subset that would try to redefine things - * defined in internal subset, let's traverse definitions in - * the ext. subset first (even though that may not be the fastest - * way), so that we have a chance of catching the first problem - * (As long as Maps iterate in insertion order). - */ - Iterator it = fromExt.entrySet().iterator(); - while (it.hasNext()) { - Map.Entry en = (Map.Entry) it.next(); - if (fromInt.containsKey(en.getKey())) { - throwNotationException((NotationDeclaration) fromInt.get(en.getKey()), - (NotationDeclaration) en.getValue()); - } - } - } -} diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/dtd/DTDSubset.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/dtd/DTDSubset.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/dtd/DTDSubset.java 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/dtd/DTDSubset.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,115 +0,0 @@ -/* Woodstox XML processor - * - * Copyright (c) 2004- Tatu Saloranta, tatu.saloranta@iki.fi - * - * Licensed under the License specified in the file LICENSE which is - * included with the source code. - * You may not use this file except in compliance with the License. - * - * 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 com.ctc.wstx.dtd; - -import java.util.*; - -import javax.xml.stream.XMLStreamException; - -import org.codehaus.stax2.validation.*; - -import com.ctc.wstx.sr.InputProblemReporter; - -/** - * This is the abstract base class that implements the standard Stax2 - * validation schema base class ({@link XMLValidationSchema}, as well - * as specifies extended Woodstox-specific interface for accessing - * DTD-specific things like entity expansions and notation properties. - *

- * API is separated from its implementation to reduce coupling; for example, - * it is possible to have DTD subset implementations that do not implement - * validation logics, just entity expansion. - */ -public abstract class DTDSubset - implements DTDValidationSchema -{ - /* - ////////////////////////////////////////////////////// - // Life-cycle - ////////////////////////////////////////////////////// - */ - - protected DTDSubset() { } - - /** - * Method that will combine definitions from this internal subset with - * definitions from passed-in external subset, producing a new combined - * DTDSubset instance. - */ - public abstract DTDSubset combineWithExternalSubset(InputProblemReporter rep, - DTDSubset extSubset) - throws XMLStreamException; - - /* - ////////////////////////////////////////////////////// - // XMLValidationSchema implementation - ////////////////////////////////////////////////////// - */ - - public abstract XMLValidator createValidator(ValidationContext ctxt) - throws XMLStreamException; - - public String getSchemaType() { - return XMLValidationSchema.SCHEMA_ID_DTD; - } - - /* - ////////////////////////////////////////////////////// - // And extended DTDValidationSchema - ////////////////////////////////////////////////////// - */ - - public abstract int getEntityCount(); - - public abstract int getNotationCount(); - - /* - ////////////////////////////////////////////////////// - // Woodstox-specific API, caching support - ////////////////////////////////////////////////////// - */ - - public abstract boolean isCachable(); - - /** - * Method used in determining whether cached external subset instance - * can be used with specified internal subset. If ext. subset references - * any parameter entities int subset (re-)defines, it can not; otherwise - * it can be used. - * - * @return True if this (external) subset refers to a parameter entity - * defined in passed-in internal subset. - */ - public abstract boolean isReusableWith(DTDSubset intSubset); - - /* - ////////////////////////////////////////////////////// - // Woodstox-specific API, entity/notation handling - ////////////////////////////////////////////////////// - */ - - public abstract HashMap getGeneralEntityMap(); - - public abstract List getGeneralEntityList(); - - public abstract HashMap getParameterEntityMap(); - - public abstract HashMap getNotationMap(); - - public abstract List getNotationList(); - - public abstract HashMap getElementMap(); -} diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/dtd/DTDTypingNonValidator.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/dtd/DTDTypingNonValidator.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/dtd/DTDTypingNonValidator.java 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/dtd/DTDTypingNonValidator.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,315 +0,0 @@ -/* Woodstox XML processor - * - * Copyright (c) 2004- Tatu Saloranta, tatu.saloranta@iki.fi - * - * Licensed under the License specified in file LICENSE, included with - * the source code. - * You may not use this file except in compliance with the License. - * - * 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 com.ctc.wstx.dtd; - -import java.util.*; - -import javax.xml.stream.XMLStreamException; - -import org.codehaus.stax2.validation.*; - -import com.ctc.wstx.util.DataUtil; -import com.ctc.wstx.util.ElementIdMap; -import com.ctc.wstx.util.ExceptionUtil; - -/** - * This class is a "non-validating validator"; a validator-like object - * that handles DTD-based non-validation functionality: determining type - * information and default values. This instance does NOT implement any - * actual DTD-validation, and is to be used in DTD-aware non-validating - * mode. - */ -public class DTDTypingNonValidator - extends DTDValidatorBase -{ - /* - /////////////////////////////////////////// - // Element def/spec/validator stack, state - /////////////////////////////////////////// - */ - - /** - * Flag that indicates if current element has any attributes that - * have default values. - */ - protected boolean mHasAttrDefaults = false; - - /** - * Bitset used for keeping track of defaulted attributes for which values - * have been found. Only non-null when current element does have such - * attributes - */ - protected BitSet mCurrDefaultAttrs = null; - - /** - * Flag that indicates whether any of the attributes is potentially - * normalizable, and we are in attribute-normalizing mode. - */ - protected boolean mHasNormalizableAttrs = false; - - /* - /////////////////////////////////////// - // Temporary helper objects - /////////////////////////////////////// - */ - - /** - * Reusable lazily instantiated BitSet; needed to keep track of - * 'missing' attributes with default values (normal default, #FIXED). - */ - BitSet mTmpDefaultAttrs; - - /* - /////////////////////////////////////////// - // Life-cycle - /////////////////////////////////////////// - */ - - public DTDTypingNonValidator(DTDSubset schema, ValidationContext ctxt, boolean hasNsDefaults, - Map elemSpecs, Map genEntities) - { - super(schema, ctxt, hasNsDefaults, elemSpecs, genEntities); - } - - /** - * @return False, since this is not a real validator - */ - public final boolean reallyValidating() { return false; } - - /* - /////////////////////////////////////// - // Configuration - /////////////////////////////////////// - */ - - /** - * This 'validator' will not normalize any attributes, - * so let's implement this as no-op. - */ - public void setAttrValueNormalization(boolean state) { - // nop - } - - /* - /////////////////////////////////////// - // XMLValidator implementation - /////////////////////////////////////// - */ - - //public XMLValidationSchema getSchema() - - public void validateElementStart(String localName, String uri, String prefix) - throws XMLStreamException - { - // Ok, can we find the element definition? - mTmpKey.reset(prefix, localName); - DTDElement elem = (DTDElement) mElemSpecs.get(mTmpKey); - // whether it's found or not, let's add a stack frame: - int elemCount = mElemCount++; - if (elemCount >= mElems.length) { - mElems = (DTDElement[]) DataUtil.growArrayBy50Pct(mElems); - } - - mElems[elemCount] = mCurrElem = elem; - mAttrCount = 0; - mIdAttrIndex = -2; // -2 as a "don't know yet" marker - - /* but if not found, can not obtain any type information. Not - * a validation problem though, since we are doing none... - * Oh, also, unlike with real validation, not having actual element - * information is ok; can still have attributes! - */ - if (elem == null) { // || !elem.isDefined()) - mCurrAttrDefs = EMPTY_MAP; - mHasAttrDefaults = false; - mCurrDefaultAttrs = null; - mHasNormalizableAttrs = false; - return; - } - - // If element found, does it have any attributes? - mCurrAttrDefs = elem.getAttributes(); - if (mCurrAttrDefs == null) { - mCurrAttrDefs = EMPTY_MAP; - mHasAttrDefaults = false; - mCurrDefaultAttrs = null; - mHasNormalizableAttrs = false; - return; - } - - // Any normalization needed? - mHasNormalizableAttrs = mNormAttrs || elem.attrsNeedValidation(); - - // Any default values? - mHasAttrDefaults = elem.hasAttrDefaultValues(); - if (mHasAttrDefaults) { - /* Special count also contains ones with #REQUIRED value, but - * that's a minor sub-optimality... - */ - int specCount = elem.getSpecialCount(); - BitSet bs = mTmpDefaultAttrs; - if (bs == null) { - mTmpDefaultAttrs = bs = new BitSet(specCount); - } else { - bs.clear(); - } - mCurrDefaultAttrs = bs; - } else { - mCurrDefaultAttrs = null; - } - } - - public String validateAttribute(String localName, String uri, - String prefix, String value) - throws XMLStreamException - { - /* no need to do any validation; however, need to do following: - * - * (a) Figure out type info, if any (to get data type, id index etc); - * if yes, do: - * (1) If attribute has default value, note down it's not needed due - * to explicit definition - * (2) If attribute is normalizable, normalize it without validation - */ - DTDAttribute attr = (DTDAttribute) mCurrAttrDefs.get(mTmpKey.reset(prefix, localName)); - int index = mAttrCount++; - if (index >= mAttrSpecs.length) { - mAttrSpecs = (DTDAttribute[]) DataUtil.growArrayBy50Pct(mAttrSpecs); - } - mAttrSpecs[index] = attr; - - /* Although undeclared attribute would be a validation error, - * we don't care here... just need to skip it - */ - if (attr != null) { - if (mHasAttrDefaults) { - /* Once again, let's use more generic 'special' index, - * even though it also includes #REQUIRED values - */ - int specIndex = attr.getSpecialIndex(); - if (specIndex >= 0) { - mCurrDefaultAttrs.set(specIndex); - } - } - if (mHasNormalizableAttrs) { - // !!! TBI - } - } - return null; // fine as is - } - - public String validateAttribute(String localName, String uri, - String prefix, - char[] valueChars, int valueStart, - int valueEnd) - throws XMLStreamException - { - // note: cut'n pasted from above... - DTDAttribute attr = (DTDAttribute) mCurrAttrDefs.get(mTmpKey.reset(prefix, localName)); - int index = mAttrCount++; - if (index >= mAttrSpecs.length) { - mAttrSpecs = (DTDAttribute[]) DataUtil.growArrayBy50Pct(mAttrSpecs); - } - mAttrSpecs[index] = attr; - if (attr != null) { - if (mHasAttrDefaults) { - int specIndex = attr.getSpecialIndex(); - if (specIndex >= 0) { - mCurrDefaultAttrs.set(specIndex); - } - } - if (mHasNormalizableAttrs) { // may get normalized, after all - return attr.normalize(this, valueChars, valueStart, valueEnd); - } - } - return null; // fine as is - } - - public int validateElementAndAttributes() - throws XMLStreamException - { - /* Ok; since we are not really validating, we just need to add possible - * attribute default values, and return "anything goes" - * as the allowable content: - */ - DTDElement elem = mCurrElem; - if (mHasAttrDefaults) { - BitSet specBits = mCurrDefaultAttrs; - int specCount = elem.getSpecialCount(); - int ix = specBits.nextClearBit(0); - while (ix < specCount) { // something amiss! - List specAttrs = elem.getSpecialAttrs(); - DTDAttribute attr = (DTDAttribute) specAttrs.get(ix); - if (attr.hasDefaultValue()) { // no default for #REQUIRED... - doAddDefaultValue(attr); - } - ix = specBits.nextClearBit(ix+1); - } - } - /* However: we should indicate cases where PCDATA is not supposed - * to occur -- although it won't be considered an error, when not - * validating, info is needed to determine type of SPACE instead - * of CHARACTERS. Other validation types are not to be returned, - * however, since caller doesn't know how to deal with such - * cases. - */ - return (elem == null) ? XMLValidator.CONTENT_ALLOW_ANY_TEXT : - elem.getAllowedContentIfSpace(); - } - - public int validateElementEnd(String localName, String uri, String prefix) - throws XMLStreamException - { - /* Since we are not really validating, only need to maintain - * the element stack, and return "anything goes" as allowable content: - */ - int ix = --mElemCount; - mElems[ix] = null; - if (ix < 1) { - return XMLValidator.CONTENT_ALLOW_ANY_TEXT; - } - DTDElement elem = mElems[ix-1]; - return (elem == null) ? XMLValidator.CONTENT_ALLOW_ANY_TEXT : - mElems[ix-1].getAllowedContentIfSpace(); - } - - // base class implements these ok: - //public void validateText(String text, boolean lastTextSegment) - //public void validateText(char[] cbuf, int textStart, int textEnd, boolean lastTextSegment) - - public void validationCompleted(boolean eod) - //throws XMLStreamException - { - // fine, great, nothing to do... - } - - /* - /////////////////////////////////////// - // Package methods, accessors - /////////////////////////////////////// - */ - - protected ElementIdMap getIdMap() - { - /* should never be called; for now let's throw an exception, if it - * turns out it does get called can/should return an empty immutable - * map or something - */ - ExceptionUtil.throwGenericInternal(); - return null; // never gets here - } - -} diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/dtd/DTDValidatorBase.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/dtd/DTDValidatorBase.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/dtd/DTDValidatorBase.java 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/dtd/DTDValidatorBase.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,531 +0,0 @@ -/* Woodstox XML processor - * - * Copyright (c) 2004- Tatu Saloranta, tatu.saloranta@iki.fi - * - * Licensed under the License specified in file LICENSE, included with - * the source code. - * You may not use this file except in compliance with the License. - * - * 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 com.ctc.wstx.dtd; - -import java.text.MessageFormat; -import java.util.*; - -import javax.xml.stream.Location; -import javax.xml.stream.XMLStreamException; - -import org.codehaus.stax2.validation.*; - -import com.ctc.wstx.api.WstxInputProperties; -import com.ctc.wstx.sr.NsDefaultProvider; -import com.ctc.wstx.sr.InputElementStack; -import com.ctc.wstx.util.DataUtil; -import com.ctc.wstx.util.ElementIdMap; -import com.ctc.wstx.util.ExceptionUtil; -import com.ctc.wstx.util.PrefixedName; - -/** - * Shared abstract base class for Woodstox implementations - * of {@link XMLValidator} for DTD validation. - * Since there are 2 sub-types -- full actual DTD validator, and a dummy - * one that only adds type information and default values, with no actual - * validation -- common functionality was refactored into this base - * class. - */ -public abstract class DTDValidatorBase - extends XMLValidator - implements NsDefaultProvider // for namespace attr defaults -{ - /* - ///////////////////////////////////////////////////// - // Constants - ///////////////////////////////////////////////////// - */ - - /** - * Estimated maximum depth of typical documents; used to allocate - * the array for element stack - */ - final static int DEFAULT_STACK_SIZE = 16; - - /** - * Estimated maximum number of attributes for a single element - */ - final static int EXP_MAX_ATTRS = 16; - - /** - * Let's actually just reuse a local Map... - */ - protected final static HashMap EMPTY_MAP = new HashMap(); - - /* - /////////////////////////////////////// - // Configuration - /////////////////////////////////////// - */ - - /** - * Flag that indicates whether any of the elements declared has default - * attribute values for namespace declaration pseudo-attributes. - */ - final boolean mHasNsDefaults; - - /** - * DTD schema ({@link DTDSubsetImpl}) object that created this validator - * instance. - */ - final DTDSubset mSchema; - - /** - * Validation context (owner) for this validator. Needed for adding - * default attribute values, for example. - */ - final ValidationContext mContext; - - /** - * Map that contains element specifications from DTD; null if no - * DOCTYPE declaration found. - */ - final Map mElemSpecs; - - /** - * General entities defined in DTD subsets; needed for validating - * ENTITY/ENTITIES attributes. - */ - final Map mGeneralEntities; - - /** - * Flag that indicates whether parser wants the attribute values - * to be normalized (according to XML specs) or not (which may be - * more efficient, although not compliant with the specs) - */ - protected boolean mNormAttrs; - - /* - /////////////////////////////////////////// - // Element def/spec/validator stack, state - /////////////////////////////////////////// - */ - - /** - * This is the element that is currently being validated; valid - * during - * validateElementStart, - * validateAttribute, - * validateElementAndAttributes calls. - */ - protected DTDElement mCurrElem = null; - - /** - * Stack of element definitions matching the current active element stack. - * Instances are elements definitions read from DTD. - */ - protected DTDElement[] mElems = null; - - /** - * Number of elements in {@link #mElems}. - */ - protected int mElemCount = 0; - - /** - * Attribute definitions for attributes the current element may have - */ - protected HashMap mCurrAttrDefs = null; - - /** - * List of attribute declarations/specifications, one for each - * attribute of the current element, for which there is a matching - * value (either explicitly defined, or assigned via defaulting). - */ - protected DTDAttribute[] mAttrSpecs = new DTDAttribute[EXP_MAX_ATTRS]; - - /** - * Number of attribute specification Objects in - * {@link #mAttrSpecs}; needed to store in case type information - * is requested later on. - */ - protected int mAttrCount = 0; - - /** - * Index of the attribute of type ID, within current element's - * attribute list. Track of this is kept separate from other - * attribute since id attributes often need to be used for resolving - * cross-references. - */ - protected int mIdAttrIndex = -1; - - /* - /////////////////////////////////////// - // Temporary helper objects - /////////////////////////////////////// - */ - - protected final transient PrefixedName mTmpKey = new PrefixedName(null, null); - - /** - * Temporary buffer attribute instances can share for validation - * purposes - */ - char[] mTmpAttrValueBuffer = null; - - /* - /////////////////////////////////////// - // Life-cycle - /////////////////////////////////////// - */ - - public DTDValidatorBase(DTDSubset schema, ValidationContext ctxt, boolean hasNsDefaults, - Map elemSpecs, Map genEntities) - { - mSchema = schema; - mContext = ctxt; - mHasNsDefaults = hasNsDefaults; - mElemSpecs = (elemSpecs == null || elemSpecs.size() == 0) ? - Collections.EMPTY_MAP : elemSpecs; - mGeneralEntities = genEntities; - // By default, let's assume attrs are to be normalized (fully xml compliant) - mNormAttrs = true; - mElems = new DTDElement[DEFAULT_STACK_SIZE]; - } - - /* - /////////////////////////////////////// - // Configuration - /////////////////////////////////////// - */ - - /** - * Method that allows enabling/disabling attribute value normalization. - * In general, readers by default enable normalization (to be fully xml - * compliant), - * whereas writers do not (since there is usually little to gain, if - * anything -- it is even possible value may be written before validation - * is called in some cases) - */ - public void setAttrValueNormalization(boolean state) { - mNormAttrs = state; - } - - /** - * @return True for validator object that actually do validate - * content; false for objects that only use DTD type information. - */ - public abstract boolean reallyValidating(); - - /* - /////////////////////////////////////// - // XMLValidator implementation - /////////////////////////////////////// - */ - - public final XMLValidationSchema getSchema() { - return mSchema; - } - - /** - * Method called to update information about the newly encountered (start) - * element. At this point namespace information has been resolved, but - * no DTD validation has been done. Validator is to do these validations, - * including checking for attribute value (and existence) compatibility. - */ - public abstract void validateElementStart(String localName, String uri, String prefix) - throws XMLStreamException; - - public abstract String validateAttribute(String localName, String uri, - String prefix, String value) - throws XMLStreamException; - - public abstract String validateAttribute(String localName, String uri, - String prefix, - char[] valueChars, int valueStart, - int valueEnd) - throws XMLStreamException; - - public abstract int validateElementAndAttributes() - throws XMLStreamException; - - /** - * @return Validation state that should be effective for the parent - * element state - */ - public abstract int validateElementEnd(String localName, String uri, String prefix) - throws XMLStreamException; - - public void validateText(String text, boolean lastTextSegment) - throws XMLStreamException - { - /* This method is a NOP, since basic DTD has no mechanism for - * validating textual content. - */ - } - - public void validateText(char[] cbuf, int textStart, int textEnd, - boolean lastTextSegment) - throws XMLStreamException - { - /* This method is a NOP, since basic DTD has no mechanism for - * validating textual content. - */ - } - - public abstract void validationCompleted(boolean eod) - throws XMLStreamException; - - /* - /////////////////////////////////////// - // Attribute info access - /////////////////////////////////////// - */ - - // // // Access to type info - - public String getAttributeType(int index) - { - DTDAttribute attr = mAttrSpecs[index]; - return (attr == null) ? WstxInputProperties.UNKNOWN_ATTR_TYPE : - attr.getValueTypeString(); - } - - /** - * Method for finding out the index of the attribute (collected using - * the attribute collector; having DTD-derived info in same order) - * that is of type ID. DTD explicitly specifies that at most one - * attribute can have this type for any element. - * - * @return Index of the attribute with type ID, in the current - * element, if one exists: -1 otherwise - */ - public int getIdAttrIndex() - { - // Let's figure out the index only when needed - int ix = mIdAttrIndex; - if (ix == -2) { - ix = -1; - if (mCurrElem != null) { - DTDAttribute idAttr = mCurrElem.getIdAttribute(); - if (idAttr != null) { - DTDAttribute[] attrs = mAttrSpecs; - for (int i = 0, len = attrs.length; i < len; ++i) { - if (attrs[i] == idAttr) { - ix = i; - break; - } - } - } - } - mIdAttrIndex = ix; - } - return ix; - } - - /** - * Method for finding out the index of the attribute (collected using - * the attribute collector; having DTD-derived info in same order) - * that is of type NOTATION. DTD explicitly specifies that at most one - * attribute can have this type for any element. - * - * @return Index of the attribute with type NOTATION, in the current - * element, if one exists: -1 otherwise - */ - public int getNotationAttrIndex() - { - /* If necessary, we could find this index when resolving the - * element, could avoid linear search. But who knows how often - * it's really needed... - */ - for (int i = 0, len = mAttrCount; i < len; ++i) { - if (mAttrSpecs[i].typeIsNotation()) { - return i; - } - } - return -1; - } - - /* - ///////////////////////////////////////////////////// - // NsDefaultProvider interface - ///////////////////////////////////////////////////// - */ - - /** - * Calling this method before {@link #checkNsDefaults} is necessary - * to pass information regarding the current element; although - * it will become available later on (via normal XMLValidator interface), - * that's too late (after namespace binding and resolving). - */ - public boolean mayHaveNsDefaults(String elemPrefix, String elemLN) - { - mTmpKey.reset(elemPrefix, elemLN); - DTDElement elem = (DTDElement) mElemSpecs.get(mTmpKey); - mCurrElem = elem; - return (elem != null) && elem.hasNsDefaults(); - } - - public void checkNsDefaults(InputElementStack nsStack) - throws XMLStreamException - { - // We only get called if mCurrElem != null, and has defaults - HashMap m = mCurrElem.getNsDefaults(); - if (m != null) { - Iterator it = m.entrySet().iterator(); - while (it.hasNext()) { - Map.Entry me = (Map.Entry) it.next(); - String prefix = (String) me.getKey(); - if (!nsStack.isPrefixLocallyDeclared(prefix)) { - DTDAttribute attr = (DTDAttribute) me.getValue(); - String uri = attr.getDefaultValue(mContext, this); - nsStack.addNsBinding(prefix, uri); - } - } - } - } - - /* - /////////////////////////////////////// - // Package methods, accessors - /////////////////////////////////////// - */ - - /** - * Name of current element on the top of the element stack. - */ - PrefixedName getElemName() { - DTDElement elem = mElems[mElemCount-1]; - return elem.getName(); - } - - Location getLocation() { - return mContext.getValidationLocation(); - } - - protected abstract ElementIdMap getIdMap(); - - Map getEntityMap() { - return mGeneralEntities; - } - - char[] getTempAttrValueBuffer(int neededLength) - { - if (mTmpAttrValueBuffer == null - || mTmpAttrValueBuffer.length < neededLength) { - int size = (neededLength < 100) ? 100 : neededLength; - mTmpAttrValueBuffer = new char[size]; - } - return mTmpAttrValueBuffer; - } - - public boolean hasNsDefaults() { - return mHasNsDefaults; - } - - /* - /////////////////////////////////////// - // Package methods, error handling - /////////////////////////////////////// - */ - - /** - * Method called to report validity problems; depending on mode, will - * either throw an exception, or add a problem notification to the - * list of problems. - */ - void reportValidationProblem(String msg) - throws XMLStreamException - { - doReportValidationProblem(msg, null); - } - - void reportValidationProblem(String msg, Location loc) - throws XMLStreamException - { - doReportValidationProblem(msg, loc); - } - - void reportValidationProblem(String format, Object arg) - throws XMLStreamException - { - doReportValidationProblem(MessageFormat.format(format, new Object[] { arg }), - null); - } - - void reportValidationProblem(String format, Object arg1, Object arg2) - throws XMLStreamException - { - doReportValidationProblem(MessageFormat.format(format, new Object[] { arg1, arg2 }), - null); - } - - /* - /////////////////////////////////////// - // Private/sub-class methods - /////////////////////////////////////// - */ - - protected void doReportValidationProblem(String msg, Location loc) - throws XMLStreamException - { - if (loc == null) { - loc = getLocation(); - } - XMLValidationProblem prob = new XMLValidationProblem(loc, msg, XMLValidationProblem.SEVERITY_ERROR); - prob.setReporter(this); - mContext.reportProblem(prob); - } - - protected void doAddDefaultValue(DTDAttribute attr) - throws XMLStreamException - { - /* If we get here, we should have a non-null (possibly empty) default - * value: - */ - String def = attr.getDefaultValue(mContext, this); - if (def == null) { - ExceptionUtil.throwInternal("null default attribute value"); - } - PrefixedName an = attr.getName(); - // Ok, do we need to find the URI? - String prefix = an.getPrefix(); - String uri = ""; - if (prefix != null && prefix.length() > 0) { - uri = mContext.getNamespaceURI(prefix); - // Can not map to empty NS! - if (uri == null || uri.length() == 0) { - /* Hmmh. This is a weird case where we do have to - * throw a validity exception; even though it really - * is more a ns-well-formedness error... - */ - reportValidationProblem("Unbound namespace prefix \"{0}\" for default attribute \"{1}\"", prefix, attr); - // May continue if we don't throw errors, just collect them to a list - uri = ""; - } - } - int defIx = mContext.addDefaultAttribute(an.getLocalName(), uri, prefix, def); - if (defIx < 0) { - /* 13-Dec-2005, Tatus: Hmmh. For readers this is an error - * condition, but writers may just indicate they are not - * interested in defaults. So let's let context report - * problem(s) if it has any regarding the request. - */ - // nop - } else { - while (defIx >= mAttrSpecs.length) { - mAttrSpecs = (DTDAttribute[]) DataUtil.growArrayBy50Pct(mAttrSpecs); - } - /* Any intervening empty slots? (can happen if other - * validators add default attributes...) - */ - while (mAttrCount < defIx) { - mAttrSpecs[mAttrCount++] = null; - } - mAttrSpecs[defIx] = attr; - mAttrCount = defIx+1; - } - } -} diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/dtd/DTDValidator.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/dtd/DTDValidator.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/dtd/DTDValidator.java 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/dtd/DTDValidator.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,406 +0,0 @@ -/* Woodstox XML processor - * - * Copyright (c) 2004- Tatu Saloranta, tatu.saloranta@iki.fi - * - * Licensed under the License specified in file LICENSE, included with - * the source code. - * You may not use this file except in compliance with the License. - * - * 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 com.ctc.wstx.dtd; - -import java.util.*; - -import javax.xml.stream.XMLStreamException; - -import org.codehaus.stax2.validation.*; - -import com.ctc.wstx.cfg.ErrorConsts; -import com.ctc.wstx.util.DataUtil; -import com.ctc.wstx.util.ElementId; -import com.ctc.wstx.util.ElementIdMap; -import com.ctc.wstx.util.StringUtil; - -/** - * Woodstox implementation of {@link XMLValidator}; the class that - * handles DTD-based validation. - */ -public class DTDValidator - extends DTDValidatorBase -{ - /* - /////////////////////////////////////// - // Configuration - /////////////////////////////////////// - */ - - /** - * Determines if identical problems (definition of the same element, - * for example) should cause multiple error notifications or not: - * if true, will get one error per instance, if false, only the first - * one will get reported. - */ - protected boolean mReportDuplicateErrors = false; - - /* - /////////////////////////////////////// - // Id/idref state - /////////////////////////////////////// - */ - - /** - * Information about declared and referenced element ids (unique - * ids that attributes may defined, as defined by DTD) - */ - protected ElementIdMap mIdMap = null; - - /* - /////////////////////////////////////////// - // Element def/spec/validator stack, state - /////////////////////////////////////////// - */ - - /** - * Stack of validators for open elements - */ - protected StructValidator[] mValidators = null; - - /** - * Bitset used for keeping track of required and defaulted attributes - * for which values have been found. - */ - protected BitSet mCurrSpecialAttrs = null; - - boolean mCurrHasAnyFixed = false; - - /* - /////////////////////////////////////// - // Temporary helper objects - /////////////////////////////////////// - */ - - /** - * Reusable lazily instantiated BitSet; needed to keep track of - * missing 'special' attributes (required ones, ones with default - * values) - */ - BitSet mTmpSpecialAttrs; - - /* - /////////////////////////////////////// - // Life-cycle - /////////////////////////////////////// - */ - - public DTDValidator(DTDSubset schema, ValidationContext ctxt, boolean hasNsDefaults, - Map elemSpecs, Map genEntities) - { - super(schema, ctxt, hasNsDefaults, elemSpecs, genEntities); - mValidators = new StructValidator[DEFAULT_STACK_SIZE]; - } - - public final boolean reallyValidating() { return true; } - - /* - /////////////////////////////////////// - // XMLValidator implementation - /////////////////////////////////////// - */ - - //public XMLValidationSchema getSchema(); - - /** - * Method called to update information about the newly encountered (start) - * element. At this point namespace information has been resolved, but - * no DTD validation has been done. Validator is to do these validations, - * including checking for attribute value (and existence) compatibility. - */ - public void validateElementStart(String localName, String uri, String prefix) - throws XMLStreamException - { - /* Ok, need to find the element definition; if not found (or - * only implicitly defined), need to throw the exception. - */ - mTmpKey.reset(prefix, localName); - - DTDElement elem = (DTDElement) mElemSpecs.get(mTmpKey); - - /* Let's add the entry in (even if it's a null); this is necessary - * to keep things in-sync if allowing graceful handling of validity - * errors - */ - int elemCount = mElemCount++; - if (elemCount >= mElems.length) { - mElems = (DTDElement[]) DataUtil.growArrayBy50Pct(mElems); - mValidators = (StructValidator[]) DataUtil.growArrayBy50Pct(mValidators); - } - mElems[elemCount] = mCurrElem = elem; - if (elem == null || !elem.isDefined()) { - reportValidationProblem(ErrorConsts.ERR_VLD_UNKNOWN_ELEM, mTmpKey.toString()); - } - - // Is this element legal under the parent element? - StructValidator pv = (elemCount > 0) ? mValidators[elemCount-1] : null; - - if (pv != null && elem != null) { - String msg = pv.tryToValidate(elem.getName()); - if (msg != null) { - int ix = msg.indexOf("$END"); - String pname = mElems[elemCount-1].toString(); - if (ix >= 0) { - msg = msg.substring(0, ix) + "" - +msg.substring(ix+4); - } - reportValidationProblem("Validation error, encountered element <" - +elem.getName()+"> as a child of <" - +pname+">: "+msg); - } - } - - mAttrCount = 0; - mIdAttrIndex = -2; // -2 as a "don't know yet" marker - - // Ok, need to get the child validator, then: - if (elem == null) { - mValidators[elemCount] = null; - mCurrAttrDefs = EMPTY_MAP; - mCurrHasAnyFixed = false; - mCurrSpecialAttrs = null; - } else { - mValidators[elemCount] = elem.getValidator(); - mCurrAttrDefs = elem.getAttributes(); - if (mCurrAttrDefs == null) { - mCurrAttrDefs = EMPTY_MAP; - } - mCurrHasAnyFixed = elem.hasFixedAttrs(); - int specCount = elem.getSpecialCount(); - if (specCount == 0) { - mCurrSpecialAttrs = null; - } else { - BitSet bs = mTmpSpecialAttrs; - if (bs == null) { - mTmpSpecialAttrs = bs = new BitSet(specCount); - } else { - bs.clear(); - } - mCurrSpecialAttrs = bs; - } - } - } - - public String validateAttribute(String localName, String uri, - String prefix, String value) - throws XMLStreamException - { - DTDAttribute attr = (DTDAttribute) mCurrAttrDefs.get(mTmpKey.reset(prefix, localName)); - if (attr == null) { - // Only report error if not already covering from an error: - if (mCurrElem != null) { - reportValidationProblem(ErrorConsts.ERR_VLD_UNKNOWN_ATTR, - mCurrElem.toString(), mTmpKey.toString()); - } - /* [WSTX-190] NPE if we continued (after reported didn't - * throw an exception); nothing more to do, let's leave - */ - return value; - } - int index = mAttrCount++; - if (index >= mAttrSpecs.length) { - mAttrSpecs = (DTDAttribute[]) DataUtil.growArrayBy50Pct(mAttrSpecs); - } - mAttrSpecs[index] = attr; - if (mCurrSpecialAttrs != null) { // Need to mark that we got it - int specIndex = attr.getSpecialIndex(); - if (specIndex >= 0) { - mCurrSpecialAttrs.set(specIndex); - } - } - String result = attr.validate(this, value, mNormAttrs); - if (mCurrHasAnyFixed && attr.isFixed()) { - String act = (result == null) ? value : result; - String exp = attr.getDefaultValue(mContext, this); - if (!act.equals(exp)) { - reportValidationProblem("Value of attribute \""+attr+"\" (element <"+mCurrElem+">) not \""+exp+"\" as expected, but \""+act+"\""); - } - } - return result; - } - - public String validateAttribute(String localName, String uri, - String prefix, - char[] valueChars, int valueStart, - int valueEnd) - throws XMLStreamException - { - DTDAttribute attr = (DTDAttribute) mCurrAttrDefs.get(mTmpKey.reset(prefix, localName)); - if (attr == null) { - // Only report error if not already covering from an error: - if (mCurrElem != null) { - reportValidationProblem(ErrorConsts.ERR_VLD_UNKNOWN_ATTR, - mCurrElem.toString(), mTmpKey.toString()); - } - /* [WSTX-190] NPE if we continued (after reported didn't - * throw an exception); nothing more to do, let's leave - */ - return new String(valueChars, valueStart, valueEnd); - } - int index = mAttrCount++; - if (index >= mAttrSpecs.length) { - mAttrSpecs = (DTDAttribute[]) DataUtil.growArrayBy50Pct(mAttrSpecs); - } - mAttrSpecs[index] = attr; - if (mCurrSpecialAttrs != null) { // Need to mark that we got it - int specIndex = attr.getSpecialIndex(); - if (specIndex >= 0) { - mCurrSpecialAttrs.set(specIndex); - } - } - String result = attr.validate(this, valueChars, valueStart, valueEnd, mNormAttrs); - if (mCurrHasAnyFixed && attr.isFixed()) { - String exp = attr.getDefaultValue(mContext, this); - boolean match; - if (result == null) { - match = StringUtil.matches(exp, valueChars, valueStart, valueEnd - valueStart); - } else { - match = exp.equals(result); - } - if (!match) { - String act = (result == null) ? - new String(valueChars, valueStart, valueEnd) : result; - reportValidationProblem("Value of #FIXED attribute \""+attr+"\" (element <"+mCurrElem+">) not \""+exp+"\" as expected, but \""+act+"\""); - } - } - return result; - } - - public int validateElementAndAttributes() - throws XMLStreamException - { - // Ok: are we fine with the attributes? - DTDElement elem = mCurrElem; - if (elem == null) { // had an error, most likely no such element defined... - // need to just return, nothing to do here - return XMLValidator.CONTENT_ALLOW_ANY_TEXT; - } - - // Any special attributes missing? - if (mCurrSpecialAttrs != null) { - BitSet specBits = mCurrSpecialAttrs; - int specCount = elem.getSpecialCount(); - int ix = specBits.nextClearBit(0); - while (ix < specCount) { // something amiss! - List specAttrs = elem.getSpecialAttrs(); - DTDAttribute attr = (DTDAttribute) specAttrs.get(ix); - - /* [WSTX-155]: Problems if reportValidationProblem returns - * ok (which happens if a reporter handles it). So what - * to do with missing required value? First thought is - * to just leave it as is. - */ - if (attr.isRequired()) { - reportValidationProblem("Required attribute \"{0}\" missing from element <{1}>", attr, elem); - } else { - doAddDefaultValue(attr); - } - ix = specBits.nextClearBit(ix+1); - } - } - - return elem.getAllowedContent(); - } - - /** - * @return Validation state that should be effective for the parent - * element state - */ - public int validateElementEnd(String localName, String uri, String prefix) - throws XMLStreamException - { - // First, let's remove the top: - int ix = mElemCount-1; - /* [WSTX-200]: need to avoid problems when doing sub-tree - * validation... - */ - if (ix < 0) { - return XMLValidator.CONTENT_ALLOW_WS; - } - mElemCount = ix; - - DTDElement closingElem = mElems[ix]; - mElems[ix] = null; - StructValidator v = mValidators[ix]; - mValidators[ix] = null; - - // Validation? - if (v != null) { - String msg = v.fullyValid(); - if (msg != null) { - reportValidationProblem("Validation error, element : "+msg); - } - } - - // Then let's get info from parent, if any - if (ix < 1) { // root element closing.. - // doesn't really matter; epilog/prolog differently handled: - return XMLValidator.CONTENT_ALLOW_WS; - } - return mElems[ix-1].getAllowedContent(); - } - - //public void validateText(String text, boolean lastTextSegment) ; - //public void validateText(char[] cbuf, int textStart, int textEnd, boolean lastTextSegment) ; - - public void validationCompleted(boolean eod) - throws XMLStreamException - { - /* Need to now ensure that all IDREF/IDREFS references - * point to defined ID attributes - */ - checkIdRefs(); - } - - /* - /////////////////////////////////////// - // Package methods, accessors - /////////////////////////////////////// - */ - - protected ElementIdMap getIdMap() { - if (mIdMap == null) { - mIdMap = new ElementIdMap(); - } - return mIdMap; - } - - /* - /////////////////////////////////////// - // Internal methods - /////////////////////////////////////// - */ - - protected void checkIdRefs() - throws XMLStreamException - { - /* 02-Oct-2004, TSa: Now we can also check that all id references - * pointed to ids that actually are defined - */ - if (mIdMap != null) { - ElementId ref = mIdMap.getFirstUndefined(); - if (ref != null) { // problem! - reportValidationProblem("Undefined id '"+ref.getId() - +"': referenced from element <" - +ref.getElemName()+">, attribute '" - +ref.getAttrName()+"'", - ref.getLocation()); - } - } - } - -} diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/dtd/DTDWriter.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/dtd/DTDWriter.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/dtd/DTDWriter.java 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/dtd/DTDWriter.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,164 +0,0 @@ -package com.ctc.wstx.dtd; - -import java.io.IOException; -import java.io.Writer; - -import javax.xml.stream.XMLStreamException; - -import com.ctc.wstx.exc.WstxIOException; - -/** - * Simple utility class used by {@link DTDReader} when writing out - * flattened external DTD subset file. Writing functionality encapsulated - * here since it's specific to one mode of operation (flattening). - *

- * Note, too, that underlying {@link IOException}s are generally wrapped - * as {@link XMLStreamException}s. This is needed to reduce amount of - * work caller has to do for wrapping. It will still be possible to - * unwrap these exceptions further up the call stack if need be. - */ -final class DTDWriter -{ - /* - ////////////////////////////////////////////////// - // Configuration - ////////////////////////////////////////////////// - */ - - final Writer mWriter; - - final boolean mIncludeComments; - - final boolean mIncludeConditionals; - - final boolean mIncludePEs; - - /* - ////////////////////////////////////////////////// - // Output status - ////////////////////////////////////////////////// - */ - - /** - * Counter that indicates whether flattened output should be written to - * (non-null) mWriter; values above zero indicate output is enabled, - * zero and below that output is disabled. - * Only enabled if mWriter is not - * null; will be temporarily disabled during processing of content - * that is not to be included (PE reference; or comments / conditional - * sections if comment/cs output is suppressed) - */ - int mIsFlattening = 0; - - /** - * Pointer to first character in the current input buffer that - * has not yet been written to flatten writer. - */ - int mFlattenStart = 0; - - /* - ////////////////////////////////////////////////// - // Life-cycle - ////////////////////////////////////////////////// - */ - - public DTDWriter(Writer out, boolean inclComments, boolean inclCond, - boolean inclPEs) - { - mWriter = out; - mIncludeComments = inclComments; - mIncludeConditionals = inclCond; - mIncludePEs = inclPEs; - - mIsFlattening = 1; // starts enabled - } - - /* - ////////////////////////////////////////////////// - // Public API, accessors, state change - ////////////////////////////////////////////////// - */ - - public boolean includeComments() { - return mIncludeComments; - } - - public boolean includeConditionals() { - return mIncludeConditionals; - } - - public boolean includeParamEntities() { - return mIncludePEs; - } - - public void disableOutput() - { - --mIsFlattening; - } - - public void enableOutput(int newStart) - { - ++mIsFlattening; - mFlattenStart = newStart; - } - - public void setFlattenStart(int ptr) { - mFlattenStart = ptr; - } - - public int getFlattenStart() { - return mFlattenStart; - } - - /* - ////////////////////////////////////////////////// - // Public API, output methods: - ////////////////////////////////////////////////// - */ - - public void flush(char[] buf, int upUntil) - throws XMLStreamException - { - if (mFlattenStart < upUntil) { - if (mIsFlattening > 0) { - try { - mWriter.write(buf, mFlattenStart, upUntil - mFlattenStart); - } catch (IOException ioe) { - throw new WstxIOException(ioe); - } - } - mFlattenStart = upUntil; - } - } - - /** - * Method called when explicit output has to be done for flatten output: - * this is usually done when there's need to do speculative checks - * before it's known if some chars are output (when suppressing comments - * or conditional sections) - */ - public void output(String output) - throws XMLStreamException - { - if (mIsFlattening > 0) { - try { - mWriter.write(output); - } catch (IOException ioe) { - throw new WstxIOException(ioe); - } - } - } - - public void output(char c) - throws XMLStreamException - { - if (mIsFlattening > 0) { - try { - mWriter.write(c); - } catch (IOException ioe) { - throw new WstxIOException(ioe); - } - } - } -} - diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/dtd/EmptyValidator.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/dtd/EmptyValidator.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/dtd/EmptyValidator.java 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/dtd/EmptyValidator.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,48 +0,0 @@ -package com.ctc.wstx.dtd; - -import com.ctc.wstx.util.PrefixedName; - -/** - * Simple content model validator that accepts no elements, ever; this - * is true for pure #PCDATA content model as well as EMPTY content model. - * Can be used as a singleton, since all info needed for diagnostics - * is passed via methods. - */ -public class EmptyValidator - extends StructValidator -{ - final static EmptyValidator sPcdataInstance = new EmptyValidator("No elements allowed in pure #PCDATA content model"); - - final static EmptyValidator sEmptyInstance = new EmptyValidator("No elements allowed in EMPTY content model"); - - final String mErrorMsg; - - private EmptyValidator(String errorMsg) { - mErrorMsg = errorMsg; - } - - public static EmptyValidator getPcdataInstance() { return sPcdataInstance; } - public static EmptyValidator getEmptyInstance() { return sPcdataInstance; } - - /** - * Simple; can always (re)use instance itself; no state information - * is kept. - */ - public StructValidator newInstance() { - return this; - } - - public String tryToValidate(PrefixedName elemName) - { - return mErrorMsg; - } - - /** - * If we ever get as far as element closing, things are all good; - * can just return null. - */ - public String fullyValid() - { - return null; - } -} diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/dtd/FullDTDReader.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/dtd/FullDTDReader.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/dtd/FullDTDReader.java 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/dtd/FullDTDReader.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,3499 +0,0 @@ -/* Woodstox XML processor - * - * Copyright (c) 2004- Tatu Saloranta, tatu.saloranta@iki.fi - * - * Licensed under the License specified in file LICENSE, included with - * the source code. - * You may not use this file except in compliance with the License. - * - * 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 com.ctc.wstx.dtd; - -import java.io.IOException; -import java.io.Writer; -import java.net.URL; -import java.text.MessageFormat; -import java.util.*; - -import javax.xml.stream.Location; -import javax.xml.stream.XMLReporter; -import javax.xml.stream.XMLStreamException; -import javax.xml.stream.events.NotationDeclaration; - -import org.codehaus.stax2.validation.XMLValidationProblem; -import org.codehaus.stax2.validation.XMLValidator; - -import com.ctc.wstx.api.ReaderConfig; -import com.ctc.wstx.cfg.ErrorConsts; -import com.ctc.wstx.cfg.XmlConsts; -import com.ctc.wstx.ent.*; -import com.ctc.wstx.evt.WNotationDeclaration; -import com.ctc.wstx.io.WstxInputData; -import com.ctc.wstx.io.WstxInputSource; -import com.ctc.wstx.util.*; - -/** - * Reader that reads in DTD information from internal or external subset. - *

- * There are 2 main modes for DTDReader, depending on whether it is parsing - * internal or external subset. Parsing of internal subset is somewhat - * simpler, since no dependency checking is needed. For external subset, - * handling of parameter entities is bit more complicated, as care has to - * be taken to distinguish between using PEs defined in int. subset, and - * ones defined in ext. subset itself. This determines cachability of - * external subsets. - *

- * Reader also implements simple stand-alone functionality for flattening - * DTD files (expanding all references to their eventual textual form); - * this is sometimes useful when optimizing modularized DTDs - * (which are more maintainable) into single monolithic DTDs (which in - * general can be more performant). - * - * @author Tatu Saloranta - */ -public class FullDTDReader - extends MinimalDTDReader -{ - /** - * Flag that can be changed to enable or disable interning of shared - * names; shared names are used for enumerated values to reduce - * memory usage. - */ - final static boolean INTERN_SHARED_NAMES = false; - - // // // Entity expansion types: - - final static Boolean ENTITY_EXP_GE = Boolean.FALSE; - - final static Boolean ENTITY_EXP_PE = Boolean.TRUE; - - /* - ////////////////////////////////////////////////// - // Configuration - ////////////////////////////////////////////////// - */ - - final int mConfigFlags; - - // Extracted wstx-specific settings: - - final boolean mCfgSupportDTDPP; - - /** - * This flag indicates whether we should build a validating 'real' - * validator (true, the usual case), - * or a simpler pseudo-validator that can do all non-validation tasks - * that are based on DTD info (entity expansion, notation references, - * default attribute values). Latter is used in non-validating mode. - *

- */ - final boolean mCfgFullyValidating; - - /* - ////////////////////////////////////////////////// - // Entity handling, parameter entities (PEs) - ////////////////////////////////////////////////// - */ - - /** - * Set of parameter entities defined so far in the currently parsed - * subset. Note: the first definition sticks, entities can not be - * redefined. - *

- * Keys are entity name Strings; values are instances of EntityDecl - */ - HashMap mParamEntities; - - /** - * Set of parameter entities already defined for the subset being - * parsed; namely, PEs defined in the internal subset passed when - * parsing matching external subset. Null when parsing internal - * subset. - */ - final HashMap mPredefdPEs; - - /** - * Set of parameter entities (ids) that have been referenced by this - * DTD; only maintained for external subsets, and only as long as - * no pre-defined PE has been referenced. - */ - Set mRefdPEs; - - /* - ////////////////////////////////////////////////// - // Entity handling, general entities (GEs) - ////////////////////////////////////////////////// - */ - - /** - * Set of generic entities defined so far in this subset. - * As with parameter entities, the first definition sticks. - *

- * Keys are entity name Strings; values are instances of EntityDecl - *

- * Note: this Map only contains entities declared and defined in the - * subset being parsed; no previously defined values are passed. - */ - HashMap mGeneralEntities; - - /** - * Set of general entities already defined for the subset being - * parsed; namely, PEs defined in the internal subset passed when - * parsing matching external subset. Null when parsing internal - * subset. Such entities are only needed directly for one purpose; - * to be expanded when reading attribute default value definitions. - */ - final HashMap mPredefdGEs; - - /** - * Set of general entities (ids) that have been referenced by this - * DTD; only maintained for external subsets, and only as long as - * no pre-defined GEs have been referenced. - */ - Set mRefdGEs; - - /* - ////////////////////////////////////////////////// - // Entity handling, both PEs and GEs - ////////////////////////////////////////////////// - */ - - /** - * Flag used to keep track of whether current (external) subset - * has referenced at least one PE that was pre-defined. - */ - boolean mUsesPredefdEntities = false; - - /* - ////////////////////////////////////////////////// - // Notation settings - ////////////////////////////////////////////////// - */ - - /** - * Set of notations defined so far. Since it's illegal to (try to) - * redefine notations, there's no specific precedence. - *

- * Keys are entity name Strings; values are instances of - * NotationDecl objects - */ - HashMap/**/ mNotations; - - /** - * Notations already parsed before current subset; that is, - * notations from the internal subset if we are currently - * parsing matching external subset. - */ - final HashMap/**/ mPredefdNotations; - - /** - * Flag used to keep track of whether current (external) subset - * has referenced at least one notation that was defined in internal - * subset. If so, can not cache the external subset - */ - boolean mUsesPredefdNotations = false; - - /** - * Finally, we need to keep track of Notation references that were - * made prior to declaration. This is needed to ensure that all - * references can be properly resolved. - */ - HashMap/**/ mNotationForwardRefs; - - /* - ////////////////////////////////////////////////// - // Element specifications - ////////////////////////////////////////////////// - */ - - /** - * Map used to shared PrefixedName instances, to reduce memory usage - * of (qualified) element and attribute names - */ - HashMap mSharedNames = null; - - /** - * Contains definition of elements and matching content specifications. - * Also contains temporary placeholders for elements that are indirectly - * "created" by ATTLIST declarations that precede actual declaration - * for the ELEMENT referred to. - */ - HashMap mElements; - - /** - * Map used for sharing legal enumeration values; used since oftentimes - * same enumeration values are used with multiple attributes - */ - HashMap mSharedEnumValues = null; - - /* - ////////////////////////////////////////////////// - // Entity expansion state: - ////////////////////////////////////////////////// - */ - - /** - * This is the attribute default value that is currently being parsed. - * Needs to be a global member due to the way entity expansion failures - * are reported: problems need to be attached to this object, even - * thought the default value itself will not be passed through. - */ - DefaultAttrValue mCurrAttrDefault = null; - - /** - * Flag that indicates if the currently expanding (or last expanded) - * entity is a Parameter Entity or General Entity. - */ - boolean mExpandingPE = false; - - /** - * Text buffer used for constructing expansion value of the internal - * entities, and for default attribute values. - * Lazily constructed when needed, reused. - */ - TextBuffer mValueBuffer = null; - - /* - ////////////////////////////////////////////////// - // Reader state - ////////////////////////////////////////////////// - */ - - /** - * Nesting count for conditionally included sections; 0 means that - * we are not inside such a section. Note that condition ignore is - * handled separately. - */ - int mIncludeCount = 0; - - /** - * This flag is used to catch uses of PEs in the internal subset - * within declarations (full declarations are ok, but not other types) - */ - boolean mCheckForbiddenPEs = false; - - /** - * Keyword of the declaration being currently parsed (if any). Can be - * used for error reporting purposes. - */ - String mCurrDeclaration; - - /* - ////////////////////////////////////////////////// - // DTD++ support information - ////////////////////////////////////////////////// - */ - - /** - * Flag that indicates if any DTD++ features have been encountered - * (in DTD++-supporting mode). - */ - boolean mAnyDTDppFeatures = false; - - /** - * Currently active default namespace URI. - */ - String mDefaultNsURI = ""; - - /** - * Prefix-to-NsURI mappings for this DTD, if any: lazily - * constructed when needed - */ - HashMap mNamespaces = null; - - /* - ////////////////////////////////////////////////// - // Additional support for creating expanded output - // of processed DTD. - ////////////////////////////////////////////////// - */ - - DTDWriter mFlattenWriter = null; - - /* - ////////////////////////////////////////////////// - // Support for SAX API impl: - ////////////////////////////////////////////////// - */ - - final DTDEventListener mEventListener; - - transient TextBuffer mTextBuffer = null; - - /* - ////////////////////////////////////////////////// - // Life-cycle - ////////////////////////////////////////////////// - */ - - /** - * Constructor used for reading/skipping internal subset. - */ - private FullDTDReader(WstxInputSource input, ReaderConfig cfg, - boolean constructFully, int xmlVersion) - { - this(input, cfg, false, null, constructFully, xmlVersion); - } - - /** - * Constructor used for reading external subset. - */ - private FullDTDReader(WstxInputSource input, ReaderConfig cfg, - DTDSubset intSubset, - boolean constructFully, int xmlVersion) - { - this(input, cfg, true, intSubset, constructFully, xmlVersion); - - // Let's make sure line/col offsets are correct... - input.initInputLocation(this, mCurrDepth); - } - - /** - * Common initialization part of int/ext subset constructors. - */ - private FullDTDReader(WstxInputSource input, ReaderConfig cfg, - boolean isExt, DTDSubset intSubset, - boolean constructFully, int xmlVersion) - { - super(input, cfg, isExt); - /* What matters here is what the main xml doc had; that determines - * xml conformance level to use. - */ - mDocXmlVersion = xmlVersion; - mXml11 = cfg.isXml11(); - int cfgFlags = cfg.getConfigFlags(); - mConfigFlags = cfgFlags; - mCfgSupportDTDPP = (cfgFlags & CFG_SUPPORT_DTDPP) != 0; - mCfgFullyValidating = constructFully; - - mUsesPredefdEntities = false; - mParamEntities = null; - mRefdPEs = null; - mRefdGEs = null; - mGeneralEntities = null; - - // Did we get any existing parameter entities? - HashMap pes = (intSubset == null) ? - null : intSubset.getParameterEntityMap(); - if (pes == null || pes.isEmpty()) { - mPredefdPEs = null; - } else { - mPredefdPEs = pes; - } - - // How about general entities (needed only for attr. def. values) - HashMap ges = (intSubset == null) ? - null : intSubset.getGeneralEntityMap(); - if (ges == null || ges.isEmpty()) { - mPredefdGEs = null; - } else { - mPredefdGEs = ges; - } - - // And finally, notations - HashMap not = (intSubset == null) ? - null : intSubset.getNotationMap(); - if (not == null || not.isEmpty()) { - mPredefdNotations = null; - } else { - mPredefdNotations = not; - } - mEventListener = mConfig.getDTDEventListener(); - } - - /** - * Method called to read in the internal subset definition. - */ - public static DTDSubset readInternalSubset(WstxInputData srcData, - WstxInputSource input, - ReaderConfig cfg, - boolean constructFully, - int xmlVersion) - throws XMLStreamException - { - FullDTDReader r = new FullDTDReader(input, cfg, constructFully, xmlVersion); - // Need to read using the same low-level reader interface: - r.copyBufferStateFrom(srcData); - DTDSubset ss; - - try { - ss = r.parseDTD(); - } finally { - /* And then need to restore changes back to owner (line nrs etc); - * effectively means that we'll stop reading external DTD subset, - * if so. - */ - srcData.copyBufferStateFrom(r); - } - return ss; - } - - /** - * Method called to read in the external subset definition. - */ - public static DTDSubset readExternalSubset - (WstxInputSource src, ReaderConfig cfg, DTDSubset intSubset, - boolean constructFully, int xmlVersion) - throws XMLStreamException - { - FullDTDReader r = new FullDTDReader(src, cfg, intSubset, constructFully, xmlVersion); - return r.parseDTD(); - } - - /** - * Method that will parse, process and output contents of an external - * DTD subset. It will do processing similar to - * {@link #readExternalSubset}, but additionally will copy its processed - * ("flattened") input to specified writer. - * - * @param src Input source used to read the main external subset - * @param flattenWriter Writer to output processed DTD content to - * @param inclComments If true, will pass comments to the writer; if false, - * will strip comments out - * @param inclConditionals If true, will include conditional block markers, - * as well as intervening content; if false, will strip out both markers - * and ignorable sections. - * @param inclPEs If true, will output parameter entity declarations; if - * false will parse and use them, but not output. - */ - public static DTDSubset flattenExternalSubset(WstxInputSource src, Writer flattenWriter, - boolean inclComments, boolean inclConditionals, - boolean inclPEs) - throws IOException, XMLStreamException - { - ReaderConfig cfg = ReaderConfig.createFullDefaults(); - // Need to create a non-shared copy to populate symbol table field - cfg = cfg.createNonShared(new SymbolTable()); - - /* Let's assume xml 1.0... can be taken as an arg later on, if we - * truly care. - */ - FullDTDReader r = new FullDTDReader(src, cfg, null, true, XmlConsts.XML_V_UNKNOWN); - r.setFlattenWriter(flattenWriter, inclComments, inclConditionals, - inclPEs); - DTDSubset ss = r.parseDTD(); - r.flushFlattenWriter(); - flattenWriter.flush(); - return ss; - } - - private TextBuffer getTextBuffer() - { - if (mTextBuffer == null) { - mTextBuffer = TextBuffer.createTemporaryBuffer(); - mTextBuffer.resetInitialized(); - } else { - mTextBuffer.resetWithEmpty(); - } - return mTextBuffer; - } - - /* - ////////////////////////////////////////////////// - // Configuration - ////////////////////////////////////////////////// - */ - - /** - * Method that will set specified Writer as the 'flattening writer'; - * writer used to output flattened version of DTD read in. This is - * similar to running a C-preprocessor on C-sources, except that - * defining writer will not prevent normal parsing of DTD itself. - */ - public void setFlattenWriter(Writer w, boolean inclComments, - boolean inclConditionals, boolean inclPEs) - { - mFlattenWriter = new DTDWriter(w, inclComments, inclConditionals, - inclPEs); - } - - private void flushFlattenWriter() - throws XMLStreamException - { - mFlattenWriter.flush(mInputBuffer, mInputPtr); - } - - /* - ////////////////////////////////////////////////// - // Internal API - ////////////////////////////////////////////////// - */ - - /** - * Method that may need to be called by attribute default value - * validation code, during parsing.... - *

- * Note: see base class for some additional remarks about this - * method. - */ - public EntityDecl findEntity(String entName) - { - if (mPredefdGEs != null) { - EntityDecl decl = (EntityDecl) mPredefdGEs.get(entName); - if (decl != null) { - return decl; - } - } - return (EntityDecl) mGeneralEntities.get(entName); - } - - /* - ////////////////////////////////////////////////// - // Main-level parsing methods - ////////////////////////////////////////////////// - */ - - protected DTDSubset parseDTD() - throws XMLStreamException - { - while (true) { - mCheckForbiddenPEs = false; // PEs are ok at this point - int i = getNextAfterWS(); - if (i < 0) { - if (mIsExternal) { // ok for external DTDs - break; - } - // Error for internal subset - throwUnexpectedEOF(SUFFIX_IN_DTD_INTERNAL); - } - if (i == '%') { // parameter entity - expandPE(); - continue; - } - - /* First, let's keep track of start of the directive; needed for - * entity and notation declaration events. - */ - mTokenInputTotal = mCurrInputProcessed + mInputPtr; - mTokenInputRow = mCurrInputRow; - mTokenInputCol = mInputPtr - mCurrInputRowStart; - - if (i == '<') { - // PEs not allowed within declarations, in the internal subset proper - mCheckForbiddenPEs = !mIsExternal && (mInput == mRootInput); - if (mFlattenWriter == null) { - parseDirective(); - } else { - parseDirectiveFlattened(); - } - continue; - } - - if (i == ']') { - if (mIncludeCount == 0 && !mIsExternal) { // End of internal subset - break; - } - if (mIncludeCount > 0) { // active INCLUDE block(s) open? - boolean suppress = (mFlattenWriter != null) && !mFlattenWriter.includeConditionals(); - - if (suppress) { - mFlattenWriter.flush(mInputBuffer, mInputPtr-1); - mFlattenWriter.disableOutput(); - } - - try { - // ]]> needs to be a token, can not come from PE: - char c = dtdNextFromCurr(); - if (c == ']') { - c = dtdNextFromCurr(); - if (c == '>') { - // Ok, fine, conditional include section ended. - --mIncludeCount; - continue; - } - } - throwDTDUnexpectedChar(c, "; expected ']]>' to close conditional include section"); - } finally { - if (suppress) { - mFlattenWriter.enableOutput(mInputPtr); - } - } - } - // otherwise will fall through, and give an error - } - - if (mIsExternal) { - throwDTDUnexpectedChar(i, "; expected a '<' to start a directive"); - } - throwDTDUnexpectedChar(i, "; expected a '<' to start a directive, or \"]>\" to end internal subset"); - } - - /* 05-Feb-2006, TSa: Not allowed to have unclosed INCLUDE/IGNORE - * blocks... - */ - if (mIncludeCount > 0) { // active INCLUDE block(s) open? - String suffix = (mIncludeCount == 1) ? "an INCLUDE block" : (""+mIncludeCount+" INCLUDE blocks"); - throwUnexpectedEOF(getErrorMsg()+"; expected closing marker for "+suffix); - } - - /* First check: have all notation references been resolved? - * (related to [WSTX-121]) - */ - if (mNotationForwardRefs != null && mNotationForwardRefs.size() > 0) { - _reportUndefinedNotationRefs(); - } - - // Ok; time to construct and return DTD data object. - DTDSubset ss; - - // There are more settings for ext. subsets: - if (mIsExternal) { - /* External subsets are cachable if they did not refer to any - * PEs or GEs defined in internal subset passed in (if any), - * nor to any notations. - * We don't care about PEs it defined itself, but need to pass - * in Set of PEs it refers to, to check if cached copy can be - * used with different int. subsets. - * We need not worry about notations referred, since they are - * not allowed to be re-defined. - */ - boolean cachable = !mUsesPredefdEntities && !mUsesPredefdNotations; - ss = DTDSubsetImpl.constructInstance(cachable, - mGeneralEntities, mRefdGEs, - null, mRefdPEs, - mNotations, mElements, - mCfgFullyValidating); - } else { - /* Internal subsets are not cachable (no unique way to refer - * to unique internal subsets), and there can be no references - * to pre-defined PEs, as none were passed. - */ - ss = DTDSubsetImpl.constructInstance(false, mGeneralEntities, null, - mParamEntities, null, - mNotations, mElements, - mCfgFullyValidating); - } - - return ss; - } - - protected void parseDirective() - throws XMLStreamException - { - /* Hmmh. Don't think PEs are allowed to contain starting - * '!' (or '?')... and it has to come from the same - * input source too (no splits) - */ - char c = dtdNextFromCurr(); - if (c == '?') { // xml decl? - readPI(); - return; - } - if (c != '!') { // nothing valid - throwDTDUnexpectedChar(c, "; expected '!' to start a directive"); - } - - /* ignore/include, comment, or directive; we are still getting - * token from same section though - */ - c = dtdNextFromCurr(); - if (c == '-') { // plain comment - c = dtdNextFromCurr(); - if (c != '-') { - throwDTDUnexpectedChar(c, "; expected '-' for a comment"); - } - if (mEventListener != null && mEventListener.dtdReportComments()) { - readComment(mEventListener); - } else { - skipComment(); - } - } else if (c == '[') { - checkInclusion(); - } else if (c >= 'A' && c <= 'Z') { - handleDeclaration(c); - } else { - throwDTDUnexpectedChar(c, ErrorConsts.ERR_DTD_MAINLEVEL_KEYWORD); - } - } - - /** - * Method similar to {@link #parseDirective}, but one that takes care - * to properly output dtd contents via {@link com.ctc.wstx.dtd.DTDWriter} - * as necessary. - * Separated to simplify both methods; otherwise would end up with - * 'if (... flatten...) ... else ...' spaghetti code. - */ - protected void parseDirectiveFlattened() - throws XMLStreamException - { - /* First, need to flush any flattened output there may be, at - * this point (except for opening lt char): and then need to - * temporarily disable more output until we know the type and - * whether it should be output or not: - */ - mFlattenWriter.flush(mInputBuffer, mInputPtr-1); - mFlattenWriter.disableOutput(); - - /* Let's determine type here, and call appropriate skip/parse - * methods. - */ - char c = dtdNextFromCurr(); - if (c == '?') { // xml decl? - mFlattenWriter.enableOutput(mInputPtr); - mFlattenWriter.output("= 'A' && c <= 'Z') { - mFlattenWriter.enableOutput(mInputPtr); - mFlattenWriter.output(" 0) { - if (mFlattenWriter != null) { - mFlattenWriter.setFlattenStart(mInputPtr); - } - return true; - } - input.close(); - } catch (IOException ioe) { - throw constructFromIOE(ioe); - } - if (input == mRootInput) { - return false; - } - WstxInputSource parent = input.getParent(); - if (parent == null) { // sanity check! - throwNullParent(input); - } - /* 13-Feb-2006, TSa: Ok, do we violate a proper nesting constraints - * with this input block closure? - */ - if (mCurrDepth != input.getScopeId()) { - handleIncompleteEntityProblem(input); - } - - mInput = input = parent; - input.restoreContext(this); - if (mFlattenWriter != null) { - mFlattenWriter.setFlattenStart(mInputPtr); - } - mInputTopDepth = input.getScopeId(); - /* 21-Feb-2006, TSa: Since linefeed normalization needs to be - * suppressed for internal entity expansion, we may need to - * change the state... - */ - if (!mNormalizeLFs) { - mNormalizeLFs = !input.fromInternalEntity(); - } - // Maybe there are leftovers from that input in buffer now? - } while (mInputPtr >= mInputEnd); - - return true; - } - - protected boolean loadMoreFromCurrent() - throws XMLStreamException - { - // Any flattened not-yet-output input to flush? - if (mFlattenWriter != null) { - mFlattenWriter.flush(mInputBuffer, mInputEnd); - } - - // Need to update offsets properly - mCurrInputProcessed += mInputEnd; - mCurrInputRowStart -= mInputEnd; - try { - int count = mInput.readInto(this); - if (count > 0) { - if (mFlattenWriter != null) { - mFlattenWriter.setFlattenStart(mInputPtr); - } - return true; - } - } catch (IOException ie) { - throwFromIOE(ie); - } - return false; - } - - protected boolean ensureInput(int minAmount) - throws XMLStreamException - { - int currAmount = mInputEnd - mInputPtr; - if (currAmount >= minAmount) { - return true; - } - // Any flattened not-yet-output input to flush? - if (mFlattenWriter != null) { - mFlattenWriter.flush(mInputBuffer, mInputEnd); - } - try { - if (mInput.readMore(this, minAmount)) { - if (mFlattenWriter != null) { - //mFlattenWriter.setFlattenStart(mInputPtr); - mFlattenWriter.setFlattenStart(currAmount); - } - return true; - } - } catch (IOException ie) { - throwFromIOE(ie); - } - return false; - } - - /* - ////////////////////////////////////////////////// - // Internal methods, input access: - ////////////////////////////////////////////////// - */ - - private void loadMoreScoped(WstxInputSource currScope, - String entityName, Location loc) - throws XMLStreamException - { - boolean check = (mInput == currScope); - loadMore(getErrorMsg()); - // Did we get out of the scope? - if (check && (mInput != currScope)) { - _reportWFCViolation("Unterminated entity value for entity '" - +entityName+"' (definition started at " - +loc+")"); - } - } - - /** - * @return Next character from the current input block, if any left; - * NULL if end of block (entity expansion) - */ - private char dtdNextIfAvailable() - throws XMLStreamException - { - char c; - if (mInputPtr < mInputEnd) { - c = mInputBuffer[mInputPtr++]; - } else { - int i = peekNext(); - if (i < 0) { - return CHAR_NULL; - } - ++mInputPtr; - c = (char) i; - } - if (c == CHAR_NULL) { - throwNullChar(); - } - return c; - } - - /** - * Method that will get next character, and either return it as is (for - * normal chars), or expand parameter entity that starts with next - * character (which has to be '%'). - */ - private char getNextExpanded() - throws XMLStreamException - { - while (true) { - char c = (mInputPtr < mInputEnd) ? - mInputBuffer[mInputPtr++] : getNextChar(getErrorMsg()); - if (c != '%') { - return c; - } - expandPE(); - } - } - - private char skipDtdWs(boolean handlePEs) - throws XMLStreamException - { - while (true) { - char c = (mInputPtr < mInputEnd) - ? mInputBuffer[mInputPtr++] : getNextChar(getErrorMsg()); - if (c > CHAR_SPACE) { - if (c == '%' && handlePEs) { - expandPE(); - continue; - } - return c; - } - if (c == '\n' || c == '\r') { - skipCRLF(c); - } else if (c != CHAR_SPACE && c != '\t') { - throwInvalidSpace(c); - } - } - } - - /** - * Note: Apparently a parameter entity expansion does also count - * as white space (that is, PEs outside of quoted text are considered - * to be separated by white spaces on both sides). Fortunately this - * can be handled by 2 little hacks: both a start of a PE, and an - * end of input block (== end of PE expansion) count as succesful - * spaces. - * - * @return Character following the obligatory boundary (white space - * or PE start/end) - */ - private char skipObligatoryDtdWs() - throws XMLStreamException - { - /* Ok; since we need at least one space, or a PE, or end of input - * block, let's do this unique check first... - */ - int i = peekNext(); - char c; - - if (i == -1) { // just means 'local' EOF (since peek only checks current) - c = getNextChar(getErrorMsg()); - // Non-space, non PE is ok, due to end-of-block... - if (c > CHAR_SPACE && c != '%') { - return c; - } - } else { - c = mInputBuffer[mInputPtr++]; // was peek, need to read - if (c > CHAR_SPACE && c != '%') { - throwDTDUnexpectedChar(c, "; expected a separating white space"); - } - } - - // Ok, got it, now can loop... - while (true) { - if (c == '%') { - expandPE(); - } else if (c > CHAR_SPACE) { - break; - } else { - if (c == '\n' || c == '\r') { - skipCRLF(c); - } else if (c != CHAR_SPACE && c != '\t') { - throwInvalidSpace(c); - } - } - /* Now we got one space (or end of input block) -- no need to - * restrict get next on current block (in case PE ends); happens - * with xmltest/valid/not-sa/003.xml, for eaxmple. - */ - c = (mInputPtr < mInputEnd) - ? mInputBuffer[mInputPtr++] : getNextChar(getErrorMsg()); - } - return c; - } - - /** - * Method called to handle expansion of parameter entities. When called, - * '%' character has been encountered as a reference indicator, and - * now we should get parameter entity name. - */ - private void expandPE() - throws XMLStreamException - { - String id; - char c; - - if (mCheckForbiddenPEs) { - /* Ok; we hit a PE where we should not have (within the internal - * dtd subset proper, within a declaration). This is a WF error. - */ - throwForbiddenPE(); - } - - // 01-Jul-2004, TSa: When flattening, need to flush previous output - if (mFlattenWriter != null) { - // Flush up to but not including ampersand... - mFlattenWriter.flush(mInputBuffer, mInputPtr-1); - mFlattenWriter.disableOutput(); - c = (mInputPtr < mInputEnd) ? - mInputBuffer[mInputPtr++] : dtdNextFromCurr(); - id = readDTDName(c); - try { - c = (mInputPtr < mInputEnd) ? - mInputBuffer[mInputPtr++] : dtdNextFromCurr(); - } finally { - // will ignore name and colon (or whatever was parsed) - mFlattenWriter.enableOutput(mInputPtr); - } - } else { - c = (mInputPtr < mInputEnd) ? - mInputBuffer[mInputPtr++] : dtdNextFromCurr(); - id = readDTDName(c); - c = (mInputPtr < mInputEnd) ? - mInputBuffer[mInputPtr++] : dtdNextFromCurr(); - } - - // Should now get semicolon... - if (c != ';') { - throwDTDUnexpectedChar(c, "; expected ';' to end parameter entity name"); - } - mExpandingPE = true; - expandEntity(id, true, ENTITY_EXP_PE); - } - - /* - ////////////////////////////////////////////////// - // Internal methods, low-level parsing: - ////////////////////////////////////////////////// - */ - - /** - * Method called to verify whether input has specified keyword; if it - * has, returns null and points to char after the keyword; if not, - * returns whatever constitutes a keyword matched, for error - * reporting purposes. - */ - protected String checkDTDKeyword(String exp) - throws XMLStreamException - { - int i = 0; - int len = exp.length(); - char c = ' '; - - for (; i < len; ++i) { - if (mInputPtr < mInputEnd) { - c = mInputBuffer[mInputPtr++]; - } else { - c = dtdNextIfAvailable(); - if (c == CHAR_NULL) { // end of block, fine - return exp.substring(0, i); - } - } - if (c != exp.charAt(i)) { - break; - } - } - - if (i == len) { - // Got a match? Cool... except if identifier still continues... - c = dtdNextIfAvailable(); - if (c == CHAR_NULL) { // EOB, fine - return null; - } - if (!isNameChar(c)) { - --mInputPtr; // to push it back - return null; - } - } - StringBuffer sb = new StringBuffer(exp.substring(0, i)); - sb.append(c); - while (true) { - c = dtdNextIfAvailable(); - if (c == CHAR_NULL) { // EOB, fine - break; - } - if (!isNameChar(c) && c != ':') { - --mInputPtr; // to push it back - break; - } - sb.append(c); - } - return sb.toString(); - } - - /** - * Method called usually to indicate an error condition; will read rest - * of specified keyword (including characters that can be part of XML - * identifiers), append that to passed prefix (which is optional), and - * return resulting String. - * - * @param prefix Part of keyword already read in. - */ - protected String readDTDKeyword(String prefix) - throws XMLStreamException - { - StringBuffer sb = new StringBuffer(prefix); - - while (true) { - char c; - if (mInputPtr < mInputEnd) { - c = mInputBuffer[mInputPtr++]; - } else { - // Don't want to cross block boundary - c = dtdNextIfAvailable(); - if (c == CHAR_NULL) { - break; // end-of-block - } - } - if (!isNameChar(c) && c != ':') { - --mInputPtr; - break; - } - sb.append(c); - } - return sb.toString(); - } - - /** - * @return True, if input contains 'PUBLIC' keyword; false if it - * contains 'SYSTEM'; otherwise throws an exception. - */ - private boolean checkPublicSystemKeyword(char c) - throws XMLStreamException - { - String errId; - - if (c == 'P') { - errId = checkDTDKeyword("UBLIC"); - if (errId == null) { - return true; - } - errId = "P" + errId; - } else if (c == 'S') { - errId = checkDTDKeyword("YSTEM"); - if (errId == null) { - return false; - } - errId = "S" + errId; - } else { - if (!isNameStartChar(c)) { - throwDTDUnexpectedChar(c, "; expected 'PUBLIC' or 'SYSTEM' keyword"); - } - errId = readDTDKeyword(String.valueOf(c)); - } - - _reportWFCViolation("Unrecognized keyword '"+errId+"'; expected 'PUBLIC' or 'SYSTEM'"); - return false; // never gets here - } - - private String readDTDName(char c) - throws XMLStreamException - { - // Let's just check this before trying to parse the id... - if (!isNameStartChar(c)) { - throwDTDUnexpectedChar(c, "; expected an identifier"); - } - return parseFullName(c); - } - - private String readDTDLocalName(char c, boolean checkChar) - throws XMLStreamException - { - /* Let's just check this first, to get better error msg - * (parseLocalName() will double-check it too) - */ - if (checkChar && !isNameStartChar(c)) { - throwDTDUnexpectedChar(c, "; expected an identifier"); - } - return parseLocalName(c); - } - - /** - * Similar to {@link #readDTDName}, except that the rules are bit looser, - * ie. there are no additional restrictions for the first char - */ - private String readDTDNmtoken(char c) - throws XMLStreamException - { - char[] outBuf = getNameBuffer(64); - int outLen = outBuf.length; - int outPtr = 0; - - while (true) { - /* Note: colon not included in name char array, since it has - * special meaning WRT QNames, need to add into account here: - */ - if (!isNameChar(c) && c != ':') { - // Need to get at least one char - if (outPtr == 0) { - throwDTDUnexpectedChar(c, "; expected a NMTOKEN character to start a NMTOKEN"); - } - --mInputPtr; - break; - } - if (outPtr >= outLen) { - outBuf = expandBy50Pct(outBuf); - outLen = outBuf.length; - } - outBuf[outPtr++] = c; - if (mInputPtr < mInputEnd) { - c = mInputBuffer[mInputPtr++]; - } else { - c = dtdNextIfAvailable(); - if (c == CHAR_NULL) { // end-of-block - break; - } - } - } - - /* Nmtokens need not be canonicalized; they will be processed - * as necessary later on: - */ - return new String(outBuf, 0, outPtr); - } - - /** - * Method that will read an element or attribute name from DTD; depending - * on namespace mode, it can have prefix as well. - *

- * Note: returned {@link PrefixedName} instances are canonicalized so that - * all instances read during parsing of a single DTD subset so that - * identity comparison can be used instead of calling equals() - * method (but only within a single subset!). This also reduces memory - * usage to some extent. - */ - private PrefixedName readDTDQName(char firstChar) - throws XMLStreamException - { - String prefix, localName; - - if (!mCfgNsEnabled) { - prefix = null; - localName = parseFullName(firstChar); - } else { - localName = parseLocalName(firstChar); - /* Hmmh. This is tricky; should only read from the current - * scope, but it is ok to hit end-of-block if it was a PE - * expansion... - */ - char c = dtdNextIfAvailable(); - if (c == CHAR_NULL) { // end-of-block - // ok, that's it... - prefix = null; - } else { - if (c == ':') { // Ok, got namespace and local name - prefix = localName; - c = dtdNextFromCurr(); - localName = parseLocalName(c); - } else { - prefix = null; - --mInputPtr; - } - } - } - - return findSharedName(prefix, localName); - } - - private char readArity() - throws XMLStreamException - { - char c = (mInputPtr < mInputEnd) ? - mInputBuffer[mInputPtr++] : getNextChar(getErrorMsg()); - if (c == '?' || c == '*' || c == '+') { - return c; - } - // Hmmh, not recognized, let's put it back: - --mInputPtr; - - // Default is 'just one' - return ' '; - } - - /** - * Method that reads and pre-processes replacement text for an internal - * entity (parameter or generic). - */ - private char[] parseEntityValue(String id, Location loc, char quoteChar) - throws XMLStreamException - { - /* 25-Jun-2004, TSa: Let's first mark current input source as the - * scope, so we can both make sure it ends in this input - * context (file), and that embedded single/double quotes - * in potentially expanded entities do not end the value - * definition (as per XML 1.0/3, 4.4.5) - */ - WstxInputSource currScope = mInput; - - /* 18-Jul-2004, TSa: Also, let's see if parameter entities are - * allowed; they are only legal outside of main internal subset - * (ie. main XML input) file (or to be precise; they are legal - * in the int. subset only as complete declarations) - */ - //boolean allowPEs = mIsExternal || (mInput != mRootInput); - - TextBuffer tb = mValueBuffer; - if (tb == null) { - tb = TextBuffer.createTemporaryBuffer(); - } - tb.resetInitialized(); - - char[] outBuf = tb.getCurrentSegment(); - int outPtr = tb.getCurrentSegmentSize(); - - while (true) { - if (mInputPtr >= mInputEnd) { - loadMoreScoped(currScope, id, loc); - } - char c = mInputBuffer[mInputPtr++]; - - // Let's get most normal chars 'skipped' first - if (c >= CHAR_FIRST_PURE_TEXT) { - ; - } else if (c == quoteChar) { - // Only end if we are in correct scope: - if (mInput == currScope) { - break; - } - } else if (c == '&') { // char entity that needs to be replaced? - /* 06-Sep-2004, TSa: We can NOT expand pre-defined entities, as - * XML specs consider them 'real' (non-char) entities. - * And expanding them would cause problems with entities - * that have such entities. - */ - int d = resolveCharOnlyEntity(false); - // Did we get a real char entity? - if (d != 0) { - if (d <= 0xFFFF) { - c = (char) d; - } else { - // Need more room? - if (outPtr >= outBuf.length) { - outBuf = tb.finishCurrentSegment(); - outPtr = 0; - } - d -= 0x10000; - outBuf[outPtr++] = (char) ((d >> 10) + 0xD800);; - c = (char) ((d & 0x3FF) + 0xDC00); - } - } else { - /* 11-Feb-2006, TSa: Even so, must verify that the - * entity reference is well-formed. - */ - boolean first = true; - while (true) { - if (outPtr >= outBuf.length) { // need more room? - outBuf = tb.finishCurrentSegment(); - outPtr = 0; - } - outBuf[outPtr++] = c; // starting with '&' - if (mInputPtr >= mInputEnd) { - loadMoreScoped(currScope, id, loc); - } - c = mInputBuffer[mInputPtr++]; - if (c == ';') { - break; - } - if (first) { - first = false; - if (isNameStartChar(c)) { - continue; - } - } else { - if (isNameChar(c)) { - continue; - } - } - if (c == ':' && !mCfgNsEnabled) { - continue; // fine in non-ns mode - } - if (first) { // missing name - throwDTDUnexpectedChar(c, "; expected entity name after '&'"); - } - throwDTDUnexpectedChar(c, "; expected semi-colon after entity name"); - } - // we can just fall through to let semicolon be added - } - // Either '&' itself, or expanded char entity - } else if (c == '%') { // param entity? - expandPE(); - // Need to loop over, no char available yet - continue; - } else if (c < CHAR_SPACE) { - if (c == '\n') { - markLF(); - } else if (c == '\r') { - if (skipCRLF(c)) { - if (!mNormalizeLFs) { - // Special handling, to output 2 chars at a time: - if (outPtr >= outBuf.length) { // need more room? - outBuf = tb.finishCurrentSegment(); - outPtr = 0; - } - outBuf[outPtr++] = c; - } - c = '\n'; - } else { - if (mNormalizeLFs) { // Mac LF - c = '\n'; - } - } - } else if (c != '\t') { - throwInvalidSpace(c); - } - } - - // Need more room? - if (outPtr >= outBuf.length) { - outBuf = tb.finishCurrentSegment(); - outPtr = 0; - } - // Ok, let's add char to output: - outBuf[outPtr++] = c; - } - tb.setCurrentLength(outPtr); - - // Ok, now need the closing '>': - char c = skipDtdWs(true); - if (c != '>') { - throwDTDUnexpectedChar(c, "; expected closing '>' after ENTITY declaration"); - } - char[] result = tb.contentsAsArray(); - mValueBuffer = tb; // recycle, if needed later on - - return result; - } - - /** - * This method is similar to {@link #parseEntityValue} in some ways, - * but has some notable differences, due to the way XML specs define - * differences. Main differences are that parameter entities are not - * allowed (or rather, recognized as entities), and that general - * entities need to be verified, but NOT expanded right away. - * Whether forward references are allowed or not is an open question - * right now. - */ - private void parseAttrDefaultValue(DefaultAttrValue defVal, char quoteChar, PrefixedName attrName, - Location loc, boolean gotFixed) - throws XMLStreamException - { - if (quoteChar != '"' && quoteChar != '\'') { // caller doesn't test it - String msg = "; expected a single or double quote to enclose the default value"; - if (!gotFixed) { - msg += ", or one of keywords (#REQUIRED, #IMPLIED, #FIXED)"; - } - msg += " (for attribute '"+attrName+"')"; - throwDTDUnexpectedChar(quoteChar, msg); - } - - /* Let's mark the current input source as the scope, so we can both - * make sure it ends in this input context (DTD subset), and that - * embedded single/double quotes in potentially expanded entities do - * not end the value definition (as per XML 1.0/3, 4.4.5) - */ - WstxInputSource currScope = mInput; - - TextBuffer tb = mValueBuffer; - if (tb == null) { - tb = TextBuffer.createTemporaryBuffer(); - } - tb.resetInitialized(); - - int outPtr = 0; - char[] outBuf = tb.getCurrentSegment(); - int outLen = outBuf.length; - - /* One more note: this is mostly cut'n pasted from stream reader's - * parseNormalizedAttrValue... - */ - main_loop: - - while (true) { - if (mInputPtr >= mInputEnd) { - boolean check = (mInput == currScope); - loadMore(getErrorMsg()); - // Did we get out of the scope? - if (check && (mInput != currScope)) { - _reportWFCViolation("Unterminated attribute default value for attribute '" - +attrName+"' (definition started at " - +loc+")"); - } - } - char c = mInputBuffer[mInputPtr++]; - - // Let's do a quick for most attribute content chars: - if (c < CHAR_FIRST_PURE_TEXT) { - if (c <= CHAR_SPACE) { - if (c == '\n') { - markLF(); - } else if (c == '\r') { - c = getNextChar(SUFFIX_IN_DEF_ATTR_VALUE); - if (c != '\n') { // nope, not 2-char lf (Mac?) - --mInputPtr; - c = mNormalizeLFs ? '\n' : '\r'; - } else { - // Fine if we are to normalize lfs - /* !!! 20-Jan-2007, TSa: Hmmh. Not sure if and - * how to preserve: for now, let's assume there's - * no need. - */ - /* - if (!mNormalizeLFs) { - if (outPtr >= outLen) { // need more room? - outBuf = tb.finishCurrentSegment(); - outPtr = 0; - outLen = outBuf.length; - } - outBuf[outPtr++] = '\r'; - // c is fine to continue - } - */ - } - markLF(); - } else if (c != CHAR_SPACE && c != '\t') { - throwInvalidSpace(c); - } - c = CHAR_SPACE; - } else if (c == quoteChar) { - /* It is possible to get these via expanded entities; - * need to make sure this is the same input level as - * the one that had starting quote - */ - if (mInput == currScope) { - break; - } - } else if (c == '&') { // an entity of some sort... - /* Will need to expand char entities and pre-defd - * int. entities (amp, lt, apos, gt): first method - * is just more optimized than the second - */ - int d; - if (inputInBuffer() >= 3) { - d = resolveSimpleEntity(true); - } else { - d = resolveCharOnlyEntity(true); - } - // Only get null if it's a 'real' general entity... - if (d == 0) { - c = getNextChar(SUFFIX_IN_ENTITY_REF); - String id = parseEntityName(c); - try { - mCurrAttrDefault = defVal; - mExpandingPE = false; - expandEntity(id, false, ENTITY_EXP_GE); - } finally { - mCurrAttrDefault = null; - } - // Ok, should have updated the input source by now - continue main_loop; - } - - if (c <= 0xFFFF) { - - } else{ - if (d <= 0xFFFF) { - c = (char) d; - } else { - // Need more room? - if (outPtr >= outBuf.length) { - outBuf = tb.finishCurrentSegment(); - outPtr = 0; - } - d -= 0x10000; - outBuf[outPtr++] = (char) ((d >> 10) + 0xD800);; - c = (char) ((d & 0x3FF) + 0xDC00); - } - } - } else if (c == '<') { - throwDTDUnexpectedChar(c, SUFFIX_IN_DEF_ATTR_VALUE); - } - } // if (c < CHAR_FIRST_PURE_TEXT) - - // Ok, let's just add char in, whatever it was - if (outPtr >= outLen) { // need more room? - outBuf = tb.finishCurrentSegment(); - outPtr = 0; - outLen = outBuf.length; - } - outBuf[outPtr++] = c; - } - - tb.setCurrentLength(outPtr); - defVal.setValue(tb.contentsAsString()); - mValueBuffer = tb; - } - - /** - * Method similar to {@link #skipPI}, but one that does basic - * well-formedness checks. - */ - protected void readPI() - throws XMLStreamException - { - String target = parseFullName(); - if (target.length() == 0) { - _reportWFCViolation(ErrorConsts.ERR_WF_PI_MISSING_TARGET); - } - if (target.equalsIgnoreCase("xml")) { - _reportWFCViolation(ErrorConsts.ERR_WF_PI_XML_TARGET, target); - } - - char c = dtdNextFromCurr(); - // Ok, need a space between target and data nonetheless - if (!isSpaceChar(c)) { // except if it ends right away - if (c != '?' || dtdNextFromCurr() != '>') { - throwUnexpectedChar(c, ErrorConsts.ERR_WF_PI_XML_MISSING_SPACE); - } - if (mEventListener != null) { - mEventListener.dtdProcessingInstruction(target, ""); - } - } else if (mEventListener == null) { - /* Otherwise, not that much to check since we don't care about - * the contents. - */ - while (true) { - c = (mInputPtr < mInputEnd) - ? mInputBuffer[mInputPtr++] : dtdNextFromCurr(); - if (c == '?') { - do { - c = (mInputPtr < mInputEnd) - ? mInputBuffer[mInputPtr++] : dtdNextFromCurr(); - } while (c == '?'); - if (c == '>') { - break; - } - } - if (c < CHAR_SPACE) { - if (c == '\n' || c == '\r') { - skipCRLF(c); - } else if (c != '\t') { - throwInvalidSpace(c); - } - } - } - } else { - // 24-Nov-2006, TSa: Actually, someone does care... - // First, need to skip extra space (if any) - while (c <= CHAR_SPACE) { - if (c == '\n' || c == '\r') { - skipCRLF(c); - } else if (c != '\t' && c != ' ') { - throwInvalidSpace(c); - } - c = (mInputPtr < mInputEnd) - ? mInputBuffer[mInputPtr++] : dtdNextFromCurr(); - } - - TextBuffer tb = getTextBuffer(); - char[] outBuf = tb.getCurrentSegment(); - int outPtr = 0; - - while (true) { - if (c == '?') { - while (true) { - c = (mInputPtr < mInputEnd) - ? mInputBuffer[mInputPtr++] : dtdNextFromCurr(); - if (c != '?') { - break; - } - if (outPtr >= outBuf.length) { - outBuf = tb.finishCurrentSegment(); - outPtr = 0; - } - outBuf[outPtr++] = c; - } - if (c == '>') { - break; - } - // Need to push back char that follows '?', output '?' - --mInputPtr; - c = '?'; - } else if (c < CHAR_SPACE) { - if (c == '\n' || c == '\r') { - skipCRLF(c); - c = '\n'; - } else if (c != '\t') { - throwInvalidSpace(c); - } - } - // Need more room? - if (outPtr >= outBuf.length) { - outBuf = tb.finishCurrentSegment(); - outPtr = 0; - } - // Ok, let's add char to output: - outBuf[outPtr++] = c; - c = (mInputPtr < mInputEnd) - ? mInputBuffer[mInputPtr++] : dtdNextFromCurr(); - } - tb.setCurrentLength(outPtr); - String data = tb.contentsAsString(); - mEventListener.dtdProcessingInstruction(target, data); - } - } - - /** - * Method similar to {@link #skipComment}, but that has to collect - * contents, to be reported for a SAX handler. - */ - protected void readComment(DTDEventListener l) - throws XMLStreamException - { - TextBuffer tb = getTextBuffer(); - char[] outBuf = tb.getCurrentSegment(); - int outPtr = 0; - - while (true) { - char c = (mInputPtr < mInputEnd) - ? mInputBuffer[mInputPtr++] : dtdNextFromCurr(); - if (c < CHAR_SPACE) { - if (c == '\n' || c == '\r') { - skipCRLF(c); - c = '\n'; - } else if (c != '\t') { - throwInvalidSpace(c); - } - } else if (c == '-') { - c = dtdNextFromCurr(); - if (c == '-') { // Ok, has to be end marker then: - // Either get '>' or error: - c = dtdNextFromCurr(); - if (c != '>') { - throwParseError(ErrorConsts.ERR_HYPHENS_IN_COMMENT); - } - break; - } - c = '-'; - --mInputPtr; // need to push back the second char read - } - // Need more room? - if (outPtr >= outBuf.length) { - outBuf = tb.finishCurrentSegment(); - outPtr = 0; - } - // Ok, let's add char to output: - outBuf[outPtr++] = c; - } - tb.setCurrentLength(outPtr); - tb.fireDtdCommentEvent(l); - } - - /* - ////////////////////////////////////////////////// - // Internal methods, conditional blocks: - ////////////////////////////////////////////////// - */ - - private void checkInclusion() - throws XMLStreamException - { - String keyword; - - // INCLUDE/IGNORE not allowed in internal subset... - /* 18-Jul-2004, TSa: Except if it's in an expanded parsed external - * entity... - */ - if (!mIsExternal && mInput == mRootInput) { - _reportWFCViolation("Internal DTD subset can not use (INCLUDE/IGNORE) directives (except via external entities)"); - } - - char c = skipDtdWs(true); - if (c != 'I') { - // let's obtain the keyword for error reporting purposes: - keyword = readDTDKeyword(String.valueOf(c)); - } else { - c = dtdNextFromCurr(); - if (c == 'G') { - keyword = checkDTDKeyword("NORE"); - if (keyword == null) { - handleIgnored(); - return; - } - keyword = "IG"+keyword; - } else if (c == 'N') { - keyword = checkDTDKeyword("CLUDE"); - if (keyword == null) { - handleIncluded(); - return; - } - keyword = "IN"+keyword; - } else { - --mInputPtr; - keyword = readDTDKeyword("I"); - } - } - - // If we get here, it was an error... - _reportWFCViolation("Unrecognized directive '"+keyword+"'; expected either 'IGNORE' or 'INCLUDE'"); - } - - private void handleIncluded() - throws XMLStreamException - { - char c = skipDtdWs(false); - if (c != '[') { - throwDTDUnexpectedChar(c, "; expected '[' to follow 'INCLUDE' directive"); - } - ++mIncludeCount; - } - - private void handleIgnored() - throws XMLStreamException - { - char c = skipDtdWs(false); - int count = 1; // Nesting of IGNORE/INCLUDE sections we have to match - - if (c != '[') { - throwDTDUnexpectedChar(c, "; expected '[' to follow 'IGNORE' directive"); - } - - /* Ok; now, let's just skip until we get the closing ']]>' - */ - String errorMsg = getErrorMsg(); - while (true) { - c = (mInputPtr < mInputEnd) - ? mInputBuffer[mInputPtr++] : getNextChar(errorMsg); - if (c < CHAR_SPACE) { - if (c == '\n' || c == '\r') { - skipCRLF(c); - } else if (c != '\t') { - throwInvalidSpace(c); - } - } else if (c == ']') { // closing? - if (getNextChar(errorMsg) == ']' - && getNextChar(errorMsg) == '>') { - if (--count < 1) { // done! - return; - } - // nested ignores, let's just continue - } else { - --mInputPtr; // need to push one char back, may be '<' - } - } else if (c == '<') { - if (getNextChar(errorMsg) == '!' - && getNextChar(errorMsg) == '[') { - // Further nesting, sweet - ++count; - } else { - --mInputPtr; // need to push one char back, may be '<' - } - } - } - } - - /* - ////////////////////////////////////////////////// - // Internal methods, validation, exceptions: - ////////////////////////////////////////////////// - */ - - private void _reportUndefinedNotationRefs() - throws XMLStreamException - { - int count = mNotationForwardRefs.size(); - - String id = (String) mNotationForwardRefs.keySet().iterator().next(); - String msg = ""+count+" referenced notation"+((count == 1) ? "":"s")+" undefined: first one '"+id+"'"; - _reportVCViolation(msg); - } - - private void _reportBadDirective(String dir) - throws XMLStreamException - { - String msg = "Unrecognized DTD directive ''; expected ATTLIST, ELEMENT, ENTITY or NOTATION"; - if (mCfgSupportDTDPP) { - msg += " (or, for DTD++, TARGETNS)"; - } - _reportWFCViolation(msg); - } - - private void _reportVCViolation(String msg) - throws XMLStreamException - { - /* 01-Sep-2006, TSa: Not 100% sure what's the right way to do it -- - * they are errors (non-fatal, but not warnings), but the way - * base class handles things, we probably better 'downgrade' - * them to warnings in non-validating mode. - */ - if (mCfgFullyValidating) { - reportValidationProblem(msg, XMLValidationProblem.SEVERITY_ERROR); - } else { - reportValidationProblem(msg, XMLValidationProblem.SEVERITY_WARNING); - } - } - - private void _reportWFCViolation(String msg) - throws XMLStreamException - { - throwParseError(msg); - } - - private void _reportWFCViolation(String format, Object arg) - throws XMLStreamException - { - throwParseError(format, arg, null); - } - - private void throwDTDElemError(String msg, Object elem) - throws XMLStreamException - { - _reportWFCViolation(elemDesc(elem) + ": " + msg); - } - - private void throwDTDAttrError(String msg, DTDElement elem, PrefixedName attrName) - throws XMLStreamException - { - _reportWFCViolation(attrDesc(elem, attrName) + ": " + msg); - } - - private void throwDTDUnexpectedChar(int i, String extraMsg) - throws XMLStreamException - { - if (extraMsg == null) { - throwUnexpectedChar(i, getErrorMsg()); - } - throwUnexpectedChar(i, getErrorMsg()+extraMsg); - } - - private void throwForbiddenPE() - throws XMLStreamException - { - _reportWFCViolation("Can not have parameter entities in the internal subset, except for defining complete declarations (XML 1.0, #2.8, WFC 'PEs In Internal Subset')"); - } - - private String elemDesc(Object elem) { - return "Element <"+elem+">)"; - } - - private String attrDesc(Object elem, PrefixedName attrName) { - return "Attribute '"+attrName+"' (of element <"+elem+">)"; - } - - private String entityDesc(WstxInputSource input) { - return "Entity &"+input.getEntityId()+";"; - } - - /* - ///////////////////////////////////////////////////// - // Internal methods, main-level declaration parsing: - ///////////////////////////////////////////////////// - */ - - /** - *

- * Note: c is known to be a letter (from 'A' to 'Z') at this poit. - */ - private void handleDeclaration(char c) - throws XMLStreamException - { - String keyw = null; - - /* We need to ensure that PEs do not span declaration boundaries - * (similar to element nesting wrt. GE expansion for xml content). - * This VC is defined in xml 1.0, section 2.8 as - * "VC: Proper Declaration/PE Nesting" - */ - /* We have binary depths within DTDs, for now: since the declaration - * just started, we should now have 1 as the depth: - */ - mCurrDepth = 1; - - try { - do { // dummy loop, for break - if (c == 'A') { // ATTLIST? - keyw = checkDTDKeyword("TTLIST"); - if (keyw == null) { - mCurrDeclaration = "ATTLIST"; - handleAttlistDecl(); - break; - } - keyw = "A" + keyw; - } else if (c == 'E') { // ENTITY, ELEMENT? - c = dtdNextFromCurr(); - if (c == 'N') { - keyw = checkDTDKeyword("TITY"); - if (keyw == null) { - mCurrDeclaration = "ENTITY"; - handleEntityDecl(false); - break; - } - keyw = "EN" + keyw; - } else if (c == 'L') { - keyw = checkDTDKeyword("EMENT"); - if (keyw == null) { - mCurrDeclaration = "ELEMENT"; - handleElementDecl(); - break; - } - keyw = "EL" + keyw; - } else { - keyw = readDTDKeyword("E"); - } - } else if (c == 'N') { // NOTATION? - keyw = checkDTDKeyword("OTATION"); - if (keyw == null) { - mCurrDeclaration = "NOTATION"; - handleNotationDecl(); - break; - } - keyw = "N" + keyw; - } else if (c == 'T' && mCfgSupportDTDPP) { // (dtd++ only) TARGETNS? - keyw = checkDTDKeyword("ARGETNS"); - if (keyw == null) { - mCurrDeclaration = "TARGETNS"; - handleTargetNsDecl(); - break; - } - keyw = "T" + keyw; - } else { - keyw = readDTDKeyword(String.valueOf(c)); - } - - // If we got this far, we got a problem... - _reportBadDirective(keyw); - } while (false); - /* Ok: now, the current input can not have been started - * within the scope... so: - */ - if (mInput.getScopeId() > 0) { - handleGreedyEntityProblem(mInput); - } - - } finally { - // Either way, declaration has ended now... - mCurrDepth = 0; - mCurrDeclaration = null; - } - } - - /** - * Specialized method that handles potentially suppressable entity - * declaration. Specifically: at this point it is known that first - * letter is 'E', that we are outputting flattened DTD info, - * and that parameter entity declarations are to be suppressed. - * Furthermore, flatten output is still being disabled, and needs - * to be enabled by the method at some point. - */ - private void handleSuppressedDeclaration() - throws XMLStreamException - { - String keyw; - char c = dtdNextFromCurr(); - - if (c == 'N') { - keyw = checkDTDKeyword("TITY"); - if (keyw == null) { - handleEntityDecl(true); - return; - } - keyw = "EN" + keyw; - mFlattenWriter.enableOutput(mInputPtr); // error condition... - } else { - mFlattenWriter.enableOutput(mInputPtr); - mFlattenWriter.output("' char; - * otherwise it's obligatory. - */ - c = getNextExpanded(); - if (isSpaceChar(c)) { - // Let's push it back in case it's LF, to be handled properly - --mInputPtr; - c = skipDtdWs(true); - - /* 26-Jan-2006, TSa: actually there are edge cases where - * we may get the attribute name right away (esp. - * with PEs...); so let's defer possible error for - * later on. Should not allow missing spaces between - * attribute declarations... ? - */ - /* - } else if (c != '>') { - throwDTDUnexpectedChar(c, "; excepted either '>' closing ATTLIST declaration, or a white space character separating individual attribute declarations"); - */ - } - if (c == '>') { - break; - } - handleAttrDecl(elem, c, index, loc); - ++index; - } - } - - private void handleElementDecl() - throws XMLStreamException - { - char c = skipObligatoryDtdWs(); - final PrefixedName elemName = readDTDQName(c); - - /* Ok, event needs to know its exact starting point (opening '<' - * char), let's get that info now (note: data has been preserved - * earlier) - */ - Location loc = getStartLocation(); - - // Ok; name got, need some white space next - c = skipObligatoryDtdWs(); - - /* Then the content spec: either a special case (ANY, EMPTY), or - * a parenthesis group for 'real' content spec - */ - StructValidator val = null; - int vldContent = XMLValidator.CONTENT_ALLOW_ANY_TEXT; - - if (c == '(') { // real content model - c = skipDtdWs(true); - if (c == '#') { - val = readMixedSpec(elemName, mCfgFullyValidating); - vldContent = XMLValidator.CONTENT_ALLOW_ANY_TEXT; // checked against DTD - } else { - --mInputPtr; // let's push it back... - ContentSpec spec = readContentSpec(elemName, true, mCfgFullyValidating); - val = spec.getSimpleValidator(); - if (val == null) { - val = new DFAValidator(DFAState.constructDFA(spec)); - } - vldContent = XMLValidator.CONTENT_ALLOW_WS; // checked against DTD - } - } else if (isNameStartChar(c)) { - do { // dummy loop to allow break: - String keyw = null; - if (c == 'A') { - keyw = checkDTDKeyword("NY"); - if (keyw == null) { - val = null; - vldContent = XMLValidator.CONTENT_ALLOW_ANY_TEXT; // no DTD checks - break; - } - keyw = "A"+keyw; - } else if (c == 'E') { - keyw = checkDTDKeyword("MPTY"); - if (keyw == null) { - val = EmptyValidator.getPcdataInstance(); - vldContent = XMLValidator.CONTENT_ALLOW_NONE; // needed to prevent non-elements too - break; - } - keyw = "E"+keyw; - } else { - --mInputPtr; - keyw = readDTDKeyword(String.valueOf(c)); - } - _reportWFCViolation("Unrecognized DTD content spec keyword '" - +keyw+"' (for element <"+elemName+">); expected ANY or EMPTY"); - } while (false); - } else { - throwDTDUnexpectedChar(c, ": excepted '(' to start content specification for element <"+elemName+">"); - } - - // Ok, still need the trailing gt-char to close the declaration: - c = skipDtdWs(true); - if (c != '>') { - throwDTDUnexpectedChar(c, "; expected '>' to finish the element declaration for <"+elemName+">"); - } - - HashMap m = getElementMap(); - DTDElement oldElem = (DTDElement) m.get(elemName); - // Ok to have it if it's not 'really' declared - - if (oldElem != null) { - if (oldElem.isDefined()) { // oops, a problem! - /* 03-Feb-2006, TSa: Hmmh. Apparently all other XML parsers - * consider it's ok in non-validating mode. All right. - */ - if (mCfgFullyValidating) { - DTDSubsetImpl.throwElementException(oldElem, loc); - } else { - // let's just ignore re-definition if not validating - return; - } - } - - /* 09-Sep-2004, TSa: Need to transfer existing attribute - * definitions, however... - */ - oldElem = oldElem.define(loc, val, vldContent); - } else { - // Sweet, let's then add the definition: - oldElem = DTDElement.createDefined(mConfig, loc, elemName, val, vldContent); - } - m.put(elemName, oldElem); - } - - /** - * This method is tricky to implement, since it can contain parameter - * entities in multiple combinations... and yet declare one as well. - * - * @param suppressPEDecl If true, will need to take of enabling/disabling - * of flattened output. - */ - private void handleEntityDecl(boolean suppressPEDecl) - throws XMLStreamException - { - /* Hmmh. It seems that PE reference are actually accepted - * even here... which makes distinguishing definition from - * reference bit challenging. - */ - char c = dtdNextFromCurr(); - boolean gotSeparator = false; - boolean isParam = false; - - while (true) { - if (c == '%') { // reference? - // note: end-of-block acceptable, same as space - char d = dtdNextIfAvailable(); - if (d == CHAR_NULL || isSpaceChar(d)) { // ok, PE declaration - isParam = true; - if (d == '\n' || c == '\r') { - skipCRLF(d); - } - break; - } - // Reference? - if (!isNameStartChar(d)) { - throwDTDUnexpectedChar(d, "; expected a space (for PE declaration) or PE reference name"); - } - --mInputPtr; // need to push the first char back, then - gotSeparator = true; - expandPE(); - // need the next char, from the new scope... or if it gets closed, this one - c = dtdNextChar(); - } else if (!isSpaceChar(c)) { // non-PE entity? - break; - } else { - gotSeparator = true; - c = dtdNextFromCurr(); - } - } - - if (!gotSeparator) { - throwDTDUnexpectedChar(c, "; expected a space separating ENTITY keyword and entity name"); - } - - /* Ok; fair enough: now must have either '%', or a name start - * character: - */ - if (isParam) { - /* PE definition: at this point we already know that there must - * have been a space... just need to skip the rest, if any. - * Also, can still get a PE to expand (name of a PE to define - * from a PE reference) - */ - c = skipDtdWs(true); - } - - if (suppressPEDecl) { // only if mFlattenWriter != null - if (!isParam) { - mFlattenWriter.enableOutput(mInputPtr); - mFlattenWriter.output(" 0 && (old = m.get(id)) != null) { - // Application may want to know about the problem... - XMLReporter rep = mConfig.getXMLReporter(); - if (rep != null) { - EntityDecl oldED = (EntityDecl) old; - String str = " entity '"+id+"' defined more than once: first declaration at " - + oldED.getLocation(); - if (isParam) { - str = "Parameter" + str; - } else { - str = "General" + str; - } - _reportWarning(rep, ErrorConsts.WT_ENT_DECL, str, evtLoc); - } - } else { - m.put(id, ent); - } - - // And finally, let's notify listener, if we have one... - if (mEventListener != null) { - if (ent.isParsed()) { // Parsed GE or PE - } else { // unparsed GE - mEventListener.dtdUnparsedEntityDecl(id, ent.getPublicId(), ent.getSystemId(), ent.getNotationName(), mInput.getSource()); - } - } - } - - /** - * Method called to handle declaration. - */ - private void handleNotationDecl() - throws XMLStreamException - { - char c = skipObligatoryDtdWs(); - String id = readDTDName(c); - - c = skipObligatoryDtdWs(); - boolean isPublic = checkPublicSystemKeyword(c); - - String pubId, sysId; - - c = skipObligatoryDtdWs(); - - // Ok, now we can parse the reference; first public id if needed: - if (isPublic) { - if (c != '"' && c != '\'') { - throwDTDUnexpectedChar(c, "; expected a quote to start the public identifier"); - } - pubId = parsePublicId(c, getErrorMsg()); - c = skipDtdWs(true); - } else { - pubId = null; - } - - /* And then we may need the system id; one NOTATION oddity, if - * there's public id, system one is optional. - */ - if (c == '"' || c == '\'') { - sysId = parseSystemId(c, mNormalizeLFs, getErrorMsg()); - c = skipDtdWs(true); - } else { - if (!isPublic) { - throwDTDUnexpectedChar(c, "; expected a quote to start the system identifier"); - } - sysId = null; - } - - // And then we should get the closing '>' - if (c != '>') { - throwDTDUnexpectedChar(c, "; expected closing '>' after NOTATION declaration"); - } - URL baseURL = mInput.getSource(); - - // Any external listeners? - if (mEventListener != null) { - mEventListener.dtdNotationDecl(id, pubId, sysId, baseURL); - } - - /* Ok, event needs to know its exact starting point (opening '<' - * char), let's get that info now (note: data has been preserved - * earlier) - */ - Location evtLoc = getStartLocation(); - NotationDeclaration nd = new WNotationDeclaration(evtLoc, id, pubId, sysId, baseURL); - - // Any definitions from the internal subset? - if (mPredefdNotations != null) { - NotationDeclaration oldDecl = (NotationDeclaration) mPredefdNotations.get(id); - if (oldDecl != null) { // oops, a problem! - DTDSubsetImpl.throwNotationException(oldDecl, nd); - } - } - - HashMap m = mNotations; - if (m == null) { - /* Let's try to get insert-ordered Map, to be able to - * report redefinition problems in proper order when validating - * subset compatibility - */ - mNotations = m = new LinkedHashMap(); - } else { - NotationDeclaration oldDecl = (NotationDeclaration) m.get(id); - if (oldDecl != null) { // oops, a problem! - DTDSubsetImpl.throwNotationException(oldDecl, nd); - } - } - // Does this resolve a dangling reference? - if (mNotationForwardRefs != null) { - mNotationForwardRefs.remove(id); - } - m.put(id, nd); - } - - /** - * Method called to handle declaration (the only - * new declaration type for DTD++) - *

- * Note: only valid for DTD++, in 'plain DTD' mode shouldn't get - * called. - */ - private void handleTargetNsDecl() - throws XMLStreamException - { - mAnyDTDppFeatures = true; - - char c = skipObligatoryDtdWs(); - String name; - - // Explicit namespace name? - if (isNameStartChar(c)) { - name = readDTDLocalName(c, false); - c = skipObligatoryDtdWs(); - } else { // no, default namespace (or error) - name = null; - } - - // Either way, should now get a quote: - if (c != '"' && c != '\'') { - if (c == '>') { // slightly more accurate error - _reportWFCViolation("Missing namespace URI for TARGETNS directive"); - } - throwDTDUnexpectedChar(c, "; expected a single or double quote to enclose the namespace URI"); - } - - /* !!! 07-Nov-2004, TSa: what's the exact value we should get - * here? Ns declarations can have any attr value... - */ - String uri = parseSystemId(c, false, "in namespace URI"); - - // Do we need to normalize the URI? - if ((mConfigFlags & CFG_INTERN_NS_URIS) != 0) { - uri = InternCache.getInstance().intern(uri); - } - - // Ok, and then the closing '>': - c = skipDtdWs(true); - if (c != '>') { - throwDTDUnexpectedChar(c, "; expected '>' to end TARGETNS directive"); - } - - if (name == null) { // default NS URI - mDefaultNsURI = uri; - } else { - if (mNamespaces == null) { - mNamespaces = new HashMap(); - } - mNamespaces.put(name, uri); - } - } - - /* - ///////////////////////////////////////////////////// - // Internal methods, secondary decl parsing methods - ///////////////////////////////////////////////////// - */ - - /** - * @param elem Element that contains this attribute - * @param c First character of what should be the attribute name - * @param index Sequential index number of this attribute as children - * of the element; used for creating bit masks later on. - * @param loc Location of the element name in attribute list declaration - */ - private void handleAttrDecl(DTDElement elem, char c, int index, - Location loc) - throws XMLStreamException - { - // First attribute name - PrefixedName attrName = readDTDQName(c); - - // then type: - c = skipObligatoryDtdWs(); - - int type = 0; - WordResolver enumValues = null; - - if (c == '(') { // enumerated type - enumValues = parseEnumerated(elem, attrName, false); - type = DTDAttribute.TYPE_ENUMERATED; - } else { - String typeStr = readDTDName(c); - - dummy: - do { // dummy loop - switch (typeStr.charAt(0)) { - case 'C': // CDATA - if (typeStr == "CDATA") { - type = DTDAttribute.TYPE_CDATA; - break dummy; - } - break; - case 'I': // ID, IDREF, IDREFS - if (typeStr == "ID") { - type = DTDAttribute.TYPE_ID; - break dummy; - } else if (typeStr == "IDREF") { - type = DTDAttribute.TYPE_IDREF; - break dummy; - } else if (typeStr == "IDREFS") { - type = DTDAttribute.TYPE_IDREFS; - break dummy; - } - break; - case 'E': // ENTITY, ENTITIES - if (typeStr == "ENTITY") { - type = DTDAttribute.TYPE_ENTITY; - break dummy; - } else if (typeStr == "ENTITIES") { - type = DTDAttribute.TYPE_ENTITIES; - break dummy; - } - break; - case 'N': // NOTATION, NMTOKEN, NMTOKENS - if (typeStr == "NOTATION") { - type = DTDAttribute.TYPE_NOTATION; - /* Special case; is followed by a list of - * enumerated ids... - */ - c = skipObligatoryDtdWs(); - if (c != '(') { - throwDTDUnexpectedChar(c, "Excepted '(' to start the list of NOTATION ids"); - } - enumValues = parseEnumerated(elem, attrName, true); - break dummy; - } else if (typeStr == "NMTOKEN") { - type = DTDAttribute.TYPE_NMTOKEN; - break dummy; - } else if (typeStr == "NMTOKENS") { - type = DTDAttribute.TYPE_NMTOKENS; - break dummy; - } - break; - } - - // Problem: - throwDTDAttrError("Unrecognized attribute type '"+typeStr+"'" - +ErrorConsts.ERR_DTD_ATTR_TYPE, - elem, attrName); - } while (false); - } - DefaultAttrValue defVal; - - // Ok, and how about the default declaration? - c = skipObligatoryDtdWs(); - if (c == '#') { - String defTypeStr = readDTDName(getNextExpanded()); - if (defTypeStr == "REQUIRED") { - defVal = DefaultAttrValue.constructRequired(); - } else if (defTypeStr == "IMPLIED") { - defVal = DefaultAttrValue.constructImplied(); - } else if (defTypeStr == "FIXED") { - defVal = DefaultAttrValue.constructFixed(); - c = skipObligatoryDtdWs(); - parseAttrDefaultValue(defVal, c, attrName, loc, true); - } else { - throwDTDAttrError("Unrecognized attribute default value directive #"+defTypeStr - +ErrorConsts.ERR_DTD_DEFAULT_TYPE, - elem, attrName); - defVal = null; // never gets here... - } - } else { - defVal = DefaultAttrValue.constructOptional(); - parseAttrDefaultValue(defVal, c, attrName, loc, false); - } - - /* There are some checks that can/need to be done now, such as: - * - * - [#3.3.1/VC: ID Attribute default] def. value type can not - * be #FIXED - */ - if (type == DTDAttribute.TYPE_ID && defVal.hasDefaultValue()) { - // Just a VC, not WFC... so: - if (mCfgFullyValidating) { - throwDTDAttrError("has type ID; can not have a default (or #FIXED) value (XML 1.0/#3.3.1)", - elem, attrName); - } - } else { // not an ID... shouldn't be xml:id, then - if (mConfig.willDoXmlIdTyping()) { - if (attrName.isXmlReservedAttr(mCfgNsEnabled, "id")) { - // 26-Sep-2006, TSa: For [WSTX-22], need to verify 'xml:id' - checkXmlIdAttr(type); - } - } - } - - /* 01-Sep-2006, TSa: To address [WSTX-23], we should verify declaration - * of 'xml:space' attribute - */ - if (attrName.isXmlReservedAttr(mCfgNsEnabled, "space")) { - checkXmlSpaceAttr(type, enumValues); - } - - DTDAttribute attr; - - /* 17-Feb-2006, TSa: Ok. So some (legacy?) DTDs do declare namespace - * declarations too... sometimes including default values. - */ - if (mCfgNsEnabled && attrName.isaNsDeclaration()) { // only check in ns mode - /* Ok: just declaring them is unnecessary, and can be safely - * ignored. It's only the default values that matter (and yes, - * let's not worry about #REQUIRED for now) - */ - if (!defVal.hasDefaultValue()) { - return; - } - // But defaulting... Hmmh. - attr = elem.addNsDefault(this, attrName, type, - defVal, mCfgFullyValidating); - } else { - attr = elem.addAttribute(this, attrName, type, - defVal, enumValues, - mCfgFullyValidating); - } - - // getting null means this is a dup... - if (attr == null) { - // anyone interested in knowing about possible problem? - XMLReporter rep = mConfig.getXMLReporter(); - if (rep != null) { - String msg = MessageFormat.format(ErrorConsts.W_DTD_ATTR_REDECL, new Object[] { attrName, elem }); - _reportWarning(rep, ErrorConsts.WT_ATTR_DECL, msg, loc); - } - } else { - if (defVal.hasDefaultValue()) { - // always normalize - attr.normalizeDefault(); - // but only validate in validating mode: - if (mCfgFullyValidating) { - attr.validateDefault(this, true); - } - } - } - } - - /** - * Parsing method that reads a list of one or more space-separated - * tokens (nmtoken or name, depending on 'isNotation' argument) - */ - private WordResolver parseEnumerated(DTDElement elem, PrefixedName attrName, - boolean isNotation) - throws XMLStreamException - { - /* Need to use tree set to be able to construct the data - * structs we need later on... - */ - TreeSet set = new TreeSet(); - - char c = skipDtdWs(true); - if (c == ')') { // just to give more meaningful error msgs - throwDTDUnexpectedChar(c, " (empty list; missing identifier(s))?"); - } - - HashMap sharedEnums; - - if (isNotation) { - sharedEnums = null; - } else { - sharedEnums = mSharedEnumValues; - if (sharedEnums == null && !isNotation) { - mSharedEnumValues = sharedEnums = new HashMap(); - } - } - - String id = isNotation ? readNotationEntry(c, attrName, elem.getLocation()) - : readEnumEntry(c, sharedEnums); - set.add(id); - - while (true) { - c = skipDtdWs(true); - if (c == ')') { - break; - } - if (c != '|') { - throwDTDUnexpectedChar(c, "; missing '|' separator?"); - } - c = skipDtdWs(true); - id = isNotation ? readNotationEntry(c, attrName, elem.getLocation()) - : readEnumEntry(c, sharedEnums); - if (!set.add(id)) { - /* 03-Feb-2006, TSa: Hmmh. Apparently all other XML parsers - * consider it's ok in non-validating mode. All right. - */ - if (mCfgFullyValidating) { - throwDTDAttrError("Duplicate enumeration value '"+id+"'", - elem, attrName); - } - } - } - - // Ok, let's construct the minimal data struct, then: - return WordResolver.constructInstance(set); - } - - /** - * Method called to read a notation reference entry; done both for - * attributes of type NOTATION, and for external unparsed entities - * that refer to a notation. In both cases, notation referenced - * needs to have been defined earlier; but only if we are building - * a fully validating DTD subset object (there is the alternative - * of a minimal DTD in DTD-aware mode, which does no validation - * but allows attribute defaulting and normalization, as well as - * access to entity and notation declarations). - * - * @param refLoc Starting location of the DTD component that contains - * the reference - */ - private String readNotationEntry(char c, PrefixedName attrName, Location refLoc) - throws XMLStreamException - { - String id = readDTDName(c); - - /* Need to check whether we have a reference to a "pre-defined" - * notation: pre-defined here means that it was defined in the - * internal subset (prior to this parsing which then would external - * subset). This is needed to know if the subset can be cached or - * not. - */ - if (mPredefdNotations != null) { - NotationDeclaration decl = (NotationDeclaration) mPredefdNotations.get(id); - if (decl != null) { - mUsesPredefdNotations = true; - return decl.getName(); - } - } - - NotationDeclaration decl = (mNotations == null) ? null : - (NotationDeclaration) mNotations.get(id); - if (decl == null) { - // In validating mode, this may be a problem (otherwise not) - if (mCfgFullyValidating) { - if (mNotationForwardRefs == null) { - mNotationForwardRefs = new LinkedHashMap(); - } - mNotationForwardRefs.put(id, refLoc); - } - return id; - } - return decl.getName(); - } - - private String readEnumEntry(char c, HashMap sharedEnums) - throws XMLStreamException - { - String id = readDTDNmtoken(c); - - /* Let's make sure it's shared for this DTD subset; saves memory - * both for DTDs and resulting docs. Could also intern Strings? - */ - String sid = (String) sharedEnums.get(id); - if (sid == null) { - sid = id; - if (INTERN_SHARED_NAMES) { - /* 19-Nov-2004, TSa: Let's not use intern cache here... - * shouldn't be performance critical (DTDs themselves - * cached), and would add more entries to cache. - */ - sid = sid.intern(); - } - sharedEnums.put(sid, sid); - } - return sid; - } - - - /** - * Method called to parse what seems like a mixed content specification. - * - * @param construct If true, will build full object for validating content - * within mixed content model; if false, will just parse and discard - * information (done in non-validating DTD-supporting mode) - */ - private StructValidator readMixedSpec(PrefixedName elemName, boolean construct) - throws XMLStreamException - { - String keyw = checkDTDKeyword("PCDATA"); - if (keyw != null) { - _reportWFCViolation("Unrecognized directive #"+keyw+"'; expected #PCDATA (or element name)"); - } - - HashMap m = new LinkedHashMap(); - while (true) { - char c = skipDtdWs(true); - if (c == ')') { - break; - } - if (c == '|') { - c = skipDtdWs(true); - } else if (c == ',') { - throwDTDUnexpectedChar(c, " (sequences not allowed within mixed content)"); - } else if (c == '(') { - throwDTDUnexpectedChar(c, " (sub-content specs not allowed within mixed content)"); - } else { - throwDTDUnexpectedChar(c, "; expected either '|' to separate elements, or ')' to close the list"); - } - PrefixedName n = readDTDQName(c); - Object old = m.put(n, TokenContentSpec.construct(' ', n)); - if (old != null) { - /* 03-Feb-2006, TSa: Hmmh. Apparently all other XML parsers - * consider it's ok in non-validating mode. All right. - */ - if (mCfgFullyValidating) { - throwDTDElemError("duplicate child element <"+n+"> in mixed content model", - elemName); - } - } - } - - /* One more check: can have a trailing asterisk; in fact, have - * to have one if there were any elements. - */ - char c = (mInputPtr < mInputEnd) ? - mInputBuffer[mInputPtr++] : getNextChar(getErrorMsg()); - if (c != '*') { - if (m.size() > 0) { - _reportWFCViolation("Missing trailing '*' after a non-empty mixed content specification"); - } - --mInputPtr; // need to push it back - } - if (!construct) { // no one cares? - return null; - } - - /* Without elements, it's considered "pure" PCDATA, which can use a - * specific 'empty' validator: - */ - if (m.isEmpty()) { - return EmptyValidator.getPcdataInstance(); - } - ContentSpec spec = ChoiceContentSpec.constructMixed(mCfgNsEnabled, m.values()); - StructValidator val = spec.getSimpleValidator(); - if (val == null) { - DFAState dfa = DFAState.constructDFA(spec); - val = new DFAValidator(dfa); - } - return val; - } - - private ContentSpec readContentSpec(PrefixedName elemName, boolean mainLevel, - boolean construct) - throws XMLStreamException - { - ArrayList subSpecs = new ArrayList(); - boolean isChoice = false; // default to sequence - boolean choiceSet = false; - - while (true) { - char c = skipDtdWs(true); - if (c == ')') { - // Need to have had at least one entry... - if (subSpecs.isEmpty()) { - _reportWFCViolation("Empty content specification for '"+elemName+"' (need at least one entry)"); - } - break; - } - if (c == '|' || c == ',') { // choice/seq indicator - boolean newChoice = (c == '|'); - if (!choiceSet) { - isChoice = newChoice; - choiceSet = true; - } else { - if (isChoice != newChoice) { - _reportWFCViolation("Can not mix content spec separators ('|' and ','); need to use parenthesis groups"); - } - } - c = skipDtdWs(true); - } else { - // Need separator between subspecs... - if (!subSpecs.isEmpty()) { - throwDTDUnexpectedChar(c, " (missing separator '|' or ','?)"); - } - } - if (c == '(') { - ContentSpec cs = readContentSpec(elemName, false, construct); - subSpecs.add(cs); - continue; - } - - // Just to get better error messages: - if (c == '|' || c == ',') { - throwDTDUnexpectedChar(c, " (missing element name?)"); - } - PrefixedName thisName = readDTDQName(c); - - /* Now... it's also legal to directly tag arity marker to a - * single element name, too... - */ - char arity = readArity(); - ContentSpec cs = construct ? - TokenContentSpec.construct(arity, thisName) - : TokenContentSpec.getDummySpec(); - subSpecs.add(cs); - } - - char arity = readArity(); - - /* Not really interested in constructing anything? Let's just - * return the dummy placeholder. - */ - if (!construct) { - return TokenContentSpec.getDummySpec(); - } - - // Just one entry? Can just return it as is, combining arities - if (subSpecs.size() == 1) { - ContentSpec cs = (ContentSpec) subSpecs.get(0); - char otherArity = cs.getArity(); - if (arity != otherArity) { - cs.setArity(combineArities(arity, otherArity)); - } - return cs; - } - - if (isChoice) { - return ChoiceContentSpec.constructChoice(mCfgNsEnabled, arity, subSpecs); - } - return SeqContentSpec.construct(mCfgNsEnabled, arity, subSpecs); - } - - private static char combineArities(char arity1, char arity2) - { - if (arity1 == arity2) { - return arity1; - } - - // no modifier doesn't matter: - if (arity1 == ' ') { - return arity2; - } - if (arity2 == ' ') { - return arity1; - } - // Asterisk is most liberal, supercedes others: - if (arity1 == '*' || arity2 == '*') { - return '*'; - } - - /* Ok, can only have '+' and '?'; which combine to - * '*' - */ - return '*'; - } - - /** - * Method that handles rest of external entity declaration, after - * it's been figured out entity is not internal (does not continue - * with a quote). - * - * @param inputSource Input source for the start of the declaration. - * Needed for resolving relative system references, if any. - * @param isParam True if this a parameter entity declaration; false - * if general entity declaration - * @param evtLoc Location where entity declaration directive started; - * needed when construction event Objects for declarations. - */ - private EntityDecl handleExternalEntityDecl(WstxInputSource inputSource, - boolean isParam, String id, - char c, Location evtLoc) - throws XMLStreamException - { - boolean isPublic = checkPublicSystemKeyword(c); - - String pubId = null; - - // Ok, now we can parse the reference; first public id if needed: - if (isPublic) { - c = skipObligatoryDtdWs(); - if (c != '"' && c != '\'') { - throwDTDUnexpectedChar(c, "; expected a quote to start the public identifier"); - } - pubId = parsePublicId(c, getErrorMsg()); - /* 30-Sep-2005, TSa: SGML has public ids that miss the system - * id. Although not legal with XML DTDs, let's give bit more - * meaningful error in those cases... - */ - c = getNextExpanded(); - if (c <= CHAR_SPACE) { // good - c = skipDtdWs(true); - } else { // not good... - // Let's just push it back and generate normal error then: - if (c != '>') { // this is handled below though - --mInputPtr; - c = skipObligatoryDtdWs(); - } - } - - /* But here let's deal with one case that we are familiar with: - * SGML does NOT require system id after public one... - */ - if (c == '>') { - _reportWFCViolation("Unexpected end of ENTITY declaration (expected a system id after public id): trying to use an SGML DTD instead of XML one?"); - } - } else { - // Just need some white space here - c = skipObligatoryDtdWs(); - } - if (c != '"' && c != '\'') { - throwDTDUnexpectedChar(c, "; expected a quote to start the system identifier"); - } - String sysId = parseSystemId(c, mNormalizeLFs, getErrorMsg()); - - // Ok; how about notation? - String notationId = null; - - /* Ok; PEs are simpler, as they always are parsed (see production - * #72 in xml 1.0 specs) - */ - if (isParam) { - c = skipDtdWs(true); - } else { - /* GEs can be unparsed, too, so it's bit more complicated; - * if we get '>', don't need space; otherwise need separating - * space (or PE boundary). Thus, need bit more code. - */ - int i = peekNext(); - if (i == '>') { // good - c = '>'; - ++mInputPtr; - } else if (i < 0) { // local EOF, ok - c = skipDtdWs(true); - } else if (i == '%') { - c = getNextExpanded(); - } else { - ++mInputPtr; - c = (char) i; - if (!isSpaceChar(c)) { - throwDTDUnexpectedChar(c, "; expected a separating space or closing '>'"); - } - c = skipDtdWs(true); - } - - if (c != '>') { - if (!isNameStartChar(c)) { - throwDTDUnexpectedChar(c, "; expected either NDATA keyword, or closing '>'"); - } - String keyw = checkDTDKeyword("DATA"); - if (keyw != null) { - _reportWFCViolation("Unrecognized keyword '"+keyw+"'; expected NOTATION (or closing '>')"); - } - c = skipObligatoryDtdWs(); - notationId = readNotationEntry(c, null, evtLoc); - c = skipDtdWs(true); - } - } - - // Ok, better have '>' now: - if (c != '>') { - throwDTDUnexpectedChar(c, "; expected closing '>'"); - } - - URL ctxt = inputSource.getSource(); - if (notationId == null) { // parsed entity: - return new ParsedExtEntity(evtLoc, id, ctxt, pubId, sysId); - } - return new UnparsedExtEntity(evtLoc, id, ctxt, pubId, sysId, notationId); - } - - /* - /////////////////////////////////////////////////////// - // Data struct access - /////////////////////////////////////////////////////// - */ - - private HashMap getElementMap() { - HashMap m = mElements; - if (m == null) { - /* Let's try to get insert-ordered Map, to be able to - * report redefinition problems in proper order when validating - * subset compatibility - */ - mElements = m = new LinkedHashMap(); - } - return m; - } - - final PrefixedName mAccessKey = new PrefixedName(null, null); - - /** - * Method used to 'intern()' qualified names; main benefit is reduced - * memory usage as the name objects are shared. May also slightly - * speed up Map access, as more often identity comparisons catch - * matches. - *

- * Note: it is assumed at this point that access is only from a single - * thread, and non-recursive -- generally valid assumption as readers are - * not shared. Restriction is needed since the method is not re-entrant: - * it uses mAccessKey during the method call. - */ - private PrefixedName findSharedName(String prefix, String localName) - { - HashMap m = mSharedNames; - - if (mSharedNames == null) { - mSharedNames = m = new HashMap(); - } else { - // Maybe we already have a shared instance... ? - PrefixedName key = mAccessKey; - key.reset(prefix, localName); - key = (PrefixedName) m.get(key); - if (key != null) { // gotcha - return key; - } - } - - // Not found; let's create, cache and return it: - PrefixedName result = new PrefixedName(prefix, localName); - m.put(result, result); - return result; - } - - /* - ////////////////////////////////////////////////////////// - // Implementations of abstract methods from StreamScanner - ////////////////////////////////////////////////////////// - */ - - // @Override - /** - * @param arg If Boolean.TRUE, we are expanding a general entity - * - */ - protected EntityDecl findEntity(String id, Object arg) - { - // Expand a Parameter Entity? - if (arg == ENTITY_EXP_PE) { // for attribute default - EntityDecl ed = (mPredefdPEs == null) ? null : (EntityDecl) mPredefdPEs.get(id); - if (ed != null) { // Entity from int. subset... - mUsesPredefdEntities = true; - /* No need to further keep track of internal references, - * since this subset can not be cached, so let's just free - * up Map if it has been created - */ - mRefdPEs = null; - } else if (mParamEntities != null) { - ed = (EntityDecl) mParamEntities.get(id); - if (ed != null) { - if (!mUsesPredefdEntities) { - // Let's also mark down the fact we referenced the entity: - Set used = mRefdPEs; - if (used == null) { - mRefdPEs = used = new HashSet(); - } - used.add(id); - } - } - } - return ed; - } - - // Nope, General Entity (within attribute default value)? - if (arg == ENTITY_EXP_GE) { - /* This is only complicated for external subsets, since - * they may 'inherit' entity definitions from preceding - * internal subset... - */ - EntityDecl ed = (mPredefdGEs == null) ? null : (EntityDecl) mPredefdGEs.get(id); - if (ed != null) { - mUsesPredefdEntities = true; - /* No need to further keep track of references, - * as this means this subset is not cachable... - * so let's just free up Map if it has been created - */ - mRefdGEs = null; - } else if (mGeneralEntities != null) { - ed = (EntityDecl) mGeneralEntities.get(id); - if (ed != null) { - // Ok, just need to mark reference, if we still care: - if (!mUsesPredefdEntities) { - // Let's also mark down the fact we referenced the entity: - if (mRefdGEs == null) { - mRefdGEs = new HashSet(); - } - mRefdGEs.add(id); - } - } - } - return ed; - } - - throw new IllegalStateException(ErrorConsts.ERR_INTERNAL); - } - - // @Override - /** - * Undeclared parameter entity is a VC, not WFC... - */ - protected void handleUndeclaredEntity(String id) - throws XMLStreamException - { - _reportVCViolation("Undeclared parameter entity '"+id+"'."); - if (mCurrAttrDefault != null) { - Location loc = getLastCharLocation(); - if (mExpandingPE) { - mCurrAttrDefault.addUndeclaredPE(id, loc); - } else { - mCurrAttrDefault.addUndeclaredGE(id, loc); - } - } - if (mEventListener != null) { - // GEs only matter when expanding... - if (mExpandingPE) { - mEventListener.dtdSkippedEntity("%"+id); - } - } - } - - // @Override - /** - * Handling of PE matching problems is actually intricate; one type - * will be a WFC ("PE Between Declarations", which refers to PEs that - * start from outside declarations), and another just a VC - * ("Proper Declaration/PE Nesting", when PE is contained within - * declaration) - */ - protected void handleIncompleteEntityProblem(WstxInputSource closing) - throws XMLStreamException - { - // Did it start outside of declaration? - if (closing.getScopeId() == 0) { // yup - // and being WFC, need not be validating - _reportWFCViolation(entityDesc(closing) + ": " - +"Incomplete PE: has to fully contain a declaration (as per xml 1.0.3, section 2.8, WFC 'PE Between Declarations')"); - } else { - // whereas the other one is only sent in validating mode.. - if (mCfgFullyValidating) { - _reportVCViolation(entityDesc(closing) + ": " - +"Incomplete PE: has to be fully contained in a declaration (as per xml 1.0.3, section 2.8, VC 'Proper Declaration/PE Nesting')"); - } - } - } - - protected void handleGreedyEntityProblem(WstxInputSource input) - throws XMLStreamException - { - // Here it can only be of VC kind... - if (mCfgFullyValidating) { // since it's a VC, not WFC - _reportWFCViolation(entityDesc(input) + ": " + - "Unbalanced PE: has to be fully contained in a declaration (as per xml 1.0.3, section 2.8, VC 'Proper Declaration/PE Nesting')"); - } - } - - /* - /////////////////////////////////////////////////////// - // Additional validity checking - /////////////////////////////////////////////////////// - */ - - protected void checkXmlSpaceAttr(int type, WordResolver enumValues) - throws XMLStreamException - { - boolean ok = (type == DTDAttribute.TYPE_ENUMERATED); - if (ok) { - switch (enumValues.size()) { - case 1: - ok = (enumValues.find("preserve") != null) - || (enumValues.find("default") != null); - break; - case 2: - ok = (enumValues.find("preserve") != null) - && (enumValues.find("default") != null); - break; - default: - ok = false; - } - } - - if (!ok) { - _reportVCViolation(ErrorConsts.ERR_DTD_XML_SPACE); - } - } - - protected void checkXmlIdAttr(int type) - throws XMLStreamException - { - if (type != DTDAttribute.TYPE_ID) { - _reportVCViolation(ErrorConsts.ERR_DTD_XML_ID); - } - } - - /* - /////////////////////////////////////////////////////// - // Error handling - /////////////////////////////////////////////////////// - */ - - private void _reportWarning(XMLReporter rep, String probType, String msg, - Location loc) - throws XMLStreamException - { - if (rep != null) { - /* Note: since the problem occurs at DTD (schema) parsing, - * not during validation, can not set reporter. - */ - XMLValidationProblem prob = new XMLValidationProblem - (loc, msg, XMLValidationProblem.SEVERITY_WARNING, probType); - rep.report(msg, probType, prob, loc); - } - } -} diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/dtd/LargePrefixedNameSet.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/dtd/LargePrefixedNameSet.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/dtd/LargePrefixedNameSet.java 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/dtd/LargePrefixedNameSet.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,184 +0,0 @@ -package com.ctc.wstx.dtd; - -import java.util.Iterator; -import java.util.TreeSet; - -import com.ctc.wstx.util.PrefixedName; - -/** - * Implementation of {@link PrefixedNameSet} suitable for storing large number - * of entries; basically anything above trivially small sets (4 or less). - *

- * Notes about usage: - *

    - *
  • All Strings contained in {@link PrefixedName} instances are assumed - * interned, so that equality comparison can be done (both for values - * stored and keys used) - *
  • - *
  • It is assumed that sets are never empty, ie. always contain at - * least one entry. - *
  • - *
  • It is assumed that caller has ensured that there are no duplicates - * in the set -- this data structure does no further validation. - *
  • - *
- */ -public final class LargePrefixedNameSet - extends PrefixedNameSet -{ - /** - * Let's not bother creating tiny hash areas; should seldom be a problem - * as smaller sets are usually created using different impl. class. - */ - final static int MIN_HASH_AREA = 8; - - final boolean mNsAware; - - /** - * Primary hash area in which NameKeys are added. Sized to be the smallest - * power of two bigger than number of entries; but at least 4 (it doesn't - * make sense to create smaller arrays) - */ - final PrefixedName[] mNames; - - /** - * Secondary (spill) area, in which keys whose hash values collide - * with primary ones are added. Number of buckets is 1/4 of number - * of primary entries, - */ - final Bucket[] mBuckets; - - public LargePrefixedNameSet(boolean nsAware, PrefixedName[] names) - { - mNsAware = nsAware; - int len = names.length; - - // Let's find the size first... let's except 1/8 slack (88% fill rate) - int minSize = len + ((len + 7) >> 3); - // Let's not create hash areas smaller than certain limit - int tableSize = MIN_HASH_AREA; - - while (tableSize < minSize) { - tableSize += tableSize; - } - - mNames = new PrefixedName[tableSize]; - // and 1/4 of that for spill area... but let's do that lazily - - Bucket[] buckets = null; - int mask = (tableSize - 1); - - for (int i = 0; i < len; ++i) { - PrefixedName nk = names[i]; - int ix = (nk.hashCode() & mask); - if (mNames[ix] == null) { // no collision - mNames[ix] = nk; - } else { // collision, need to add a bucket - ix >>= 2; - - Bucket old; - if (buckets == null) { - buckets = new Bucket[tableSize >> 2]; - old = null; - } else { - old = buckets[ix]; - } - buckets[ix] = new Bucket(nk, old); - } - } - - mBuckets = buckets; - } - - public boolean hasMultiple() { return true; } - - /** - * @return True if the set contains specified name; false if not. - */ - public boolean contains(PrefixedName name) - { - PrefixedName[] hashArea = mNames; - int index = name.hashCode() & (hashArea.length - 1); - PrefixedName res = hashArea[index]; - - if (res != null && res.equals(name)) { - return true; - } - - Bucket[] buckets = mBuckets; - if (buckets != null) { - for (Bucket bucket = buckets[index >> 2]; bucket != null; - bucket = bucket.getNext()) { - res = bucket.getName(); - if (res.equals(name)) { - return true; - } - } - } - return false; - } - - /** - * Method called by debug/error handling code, to get a list of - * all names contained. - */ - public void appendNames(StringBuffer sb, String sep) - { - // Let's first get the alphabetized list of all names from main hash - TreeSet ts = new TreeSet(); - for (int i = 0; i < mNames.length; ++i) { - PrefixedName name = mNames[i]; - if (name != null) { - ts.add(name); - } - } - - // then spill area - if (mBuckets != null) { - for (int i = 0; i < (mNames.length >> 2); ++i) { - Bucket b = mBuckets[i]; - while (b != null) { - ts.add(b.getName()); - b = b.getNext(); - } - } - } - - // And then append them: - Iterator it = ts.iterator(); - boolean first = true; - while (it.hasNext()) { - if (first) { - first = false; - } else { - sb.append(sep); - } - sb.append(it.next().toString()); - } - } - - /* - /////////////////////////////////////////////////////////// - // Helper class(es) - /////////////////////////////////////////////////////////// - */ - - private final static class Bucket - { - final PrefixedName mName; - - final Bucket mNext; - - public Bucket(PrefixedName name, Bucket next) { - mName = name; - mNext = next; - } - - public PrefixedName getName() { return mName; } - public Bucket getNext() { return mNext; } - - public boolean contains(PrefixedName n) { - return mName.equals(n); - } - } -} diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/dtd/MinimalDTDReader.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/dtd/MinimalDTDReader.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/dtd/MinimalDTDReader.java 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/dtd/MinimalDTDReader.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,411 +0,0 @@ -/* Woodstox XML processor - * - * Copyright (c) 2004- Tatu Saloranta, tatu.saloranta@iki.fi - * - * Licensed under the License specified in file LICENSE, included with - * the source code. - * You may not use this file except in compliance with the License. - * - * 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 com.ctc.wstx.dtd; - -import javax.xml.stream.Location; -import javax.xml.stream.XMLStreamException; - -import com.ctc.wstx.api.ReaderConfig; -import com.ctc.wstx.ent.EntityDecl; -import com.ctc.wstx.io.WstxInputData; -import com.ctc.wstx.io.WstxInputSource; -import com.ctc.wstx.sr.StreamScanner; - -/** - * Minimal DTD reader implementation that only knows how to skip - * internal DTD subsets. - */ -public class MinimalDTDReader - extends StreamScanner -{ - /* - ////////////////////////////////////////////////// - // Configuration - ////////////////////////////////////////////////// - */ - - /** - * True, when reading external subset, false when reading internal - * subset. - */ - final boolean mIsExternal; - - /* - ////////////////////////////////////////////////// - // Life-cycle - ////////////////////////////////////////////////// - */ - - /** - * Constructor used for reading/skipping internal subset. - */ - private MinimalDTDReader(WstxInputSource input, ReaderConfig cfg) - { - this(input, cfg, false); - } - - /** - * Common initialization part of int/ext subset constructors. - */ - protected MinimalDTDReader(WstxInputSource input, ReaderConfig cfg, - boolean isExt) - { - super(input, cfg, cfg.getDtdResolver()); - mIsExternal = isExt; - /* And let's force expansion (matters mostly/only for undefined - * entities) - */ - mCfgReplaceEntities = true; - } - - /** - * Method that just skims - * through structure of internal subset, but without doing any sort - * of validation, or parsing of contents. Method may still throw an - * exception, if skipping causes EOF or there's an I/O problem. - * - * @param srcData Link back to the input buffer shared with the owning - * stream reader. - */ - public static void skipInternalSubset(WstxInputData srcData, WstxInputSource input, - ReaderConfig cfg) - throws XMLStreamException - { - MinimalDTDReader r = new MinimalDTDReader(input, cfg); - // Need to read from same source as the master (owning stream reader) - r.copyBufferStateFrom(srcData); - try { - r.skipInternalSubset(); - } finally { - /* And then need to restore changes back to srcData (line nrs etc); - * effectively means that we'll stop reading internal DTD subset, - * if so. - */ - srcData.copyBufferStateFrom(r); - } - } - - /* - ////////////////////////////////////////////////// - // Abstract methods from StreamScanner - ////////////////////////////////////////////////// - */ - - /** - * What DTD reader returns doesn't really matter, so let's just return - * perceived start location (different from what stream readers actually - * do) - */ - public final Location getLocation() - { - return getStartLocation(); - } - - // @Override - protected EntityDecl findEntity(String id, Object arg) { - throwIllegalCall(); - return null; // never gets here but javac needs it - } - - /** - * This is a VC, not WFC, nothing to do when skipping through - * DTD in non-supporting mode. - */ - protected void handleUndeclaredEntity(String id) - throws XMLStreamException - { - // nothing to do... - } - - /** - * Since improper entity/PE nesting is VC, not WFC, let's not - * react to this failure at all when only skipping the DTD subset. - */ - protected void handleIncompleteEntityProblem(WstxInputSource closing) - throws XMLStreamException - { - // nothing to do... - } - - protected char handleExpandedSurrogate(char first, char second) - { - // should we throw an exception? - return first; - } - - /* - ////////////////////////////////////////////////// - // Internal API - ////////////////////////////////////////////////// - */ - - /** - * Method that may need to be called by attribute default value - * validation code, during parsing.... - *

- * 03-Dec-2004, TSa: This is not particularly elegant: should be - * able to pass the information some other way. But for now it - * works and is necessary. - */ - public EntityDecl findEntity(String entName) { - return null; - } - - /* - ////////////////////////////////////////////////// - // Main-level skipping method(s) - ////////////////////////////////////////////////// - */ - - /** - * Method that will skip through internal DTD subset, without doing - * any parsing, except for trying to match end of subset properly. - */ - protected void skipInternalSubset() - throws XMLStreamException - { - while (true) { - int i = getNextAfterWS(); - if (i < 0) { - // Error for internal subset - throwUnexpectedEOF(SUFFIX_IN_DTD_INTERNAL); - } - if (i == '%') { // parameter entity - skipPE(); - continue; - } - if (i == '<') { - /* Let's determine type here, and call appropriate skip - * methods. - */ - char c = getNextSkippingPEs(); - if (c == '?') { // xml decl? - /* Not sure if PIs are really allowed in DTDs, but let's - * just allow them until proven otherwise. XML declaration - * is legal in the beginning, anyhow - */ - skipPI(); - } else if (c == '!') { // ignore/include, comment, declaration? - c = getNextSkippingPEs(); - if (c == '[') { - /* Shouldn't really get these, as they are not allowed - * in the internal subset? So let's just leave it - * as is, and see what happens. :-) - */ - ; - } else if (c == '-') { // plain comment - skipComment(); - } else if (c >= 'A' && c <= 'Z') { - skipDeclaration(c); - } else { - /* Hmmh, let's not care too much; but we need to try - * to match the closing gt-char nonetheless? - */ - skipDeclaration(c); - } - } else { - /* Shouldn't fail (since we are to completely ignore - * subset); let's just push it back and continue. - */ - --mInputPtr; - } - continue; - } - - if (i == ']') { - // Int. subset has no conditional sections, has to be the end... - /* 18-Jul-2004, TSa: Let's just make sure it happened - * in the main input source, not at external entity... - */ - if (mInput != mRootInput) { - throwParseError("Encountered int. subset end marker ']]>' in an expanded entity; has to be at main level."); - } - // End of internal subset - break; - } - throwUnexpectedChar(i, SUFFIX_IN_DTD_INTERNAL+"; expected a '<' to start a directive, or \"]>\" to end internal subset."); - } - } - - /* - ////////////////////////////////////////////////// - // Internal methods, input access: - ////////////////////////////////////////////////// - */ - - protected char dtdNextFromCurr() - throws XMLStreamException - { - return (mInputPtr < mInputEnd) ? - mInputBuffer[mInputPtr++] : getNextCharFromCurrent(getErrorMsg()); - } - - protected char dtdNextChar() - throws XMLStreamException - { - return (mInputPtr < mInputEnd) ? - mInputBuffer[mInputPtr++] : getNextChar(getErrorMsg()); - } - - protected char getNextSkippingPEs() - throws XMLStreamException - { - while (true) { - char c = (mInputPtr < mInputEnd) ? - mInputBuffer[mInputPtr++] : getNextChar(getErrorMsg()); - if (c != '%') { - return c; - } - skipPE(); - } - } - - /* - ////////////////////////////////////////////////// - // Internal methods, skipping: - ////////////////////////////////////////////////// - */ - - private void skipPE() - throws XMLStreamException - { - skipDTDName(); - /* Should now get semicolon... let's try to find and skip it; but - * if none found, let's not throw an exception -- we are just skipping - * internal subset here. - */ - char c = (mInputPtr < mInputEnd) ? - mInputBuffer[mInputPtr++] : dtdNextFromCurr(); - if (c != ';') { - --mInputPtr; - } - } - - protected void skipComment() - throws XMLStreamException - { - skipCommentContent(); - // Now, we may be getting end mark; first need second marker char:. - char c = (mInputPtr < mInputEnd) - ? mInputBuffer[mInputPtr++] : dtdNextFromCurr(); - if (c != '>') { - throwParseError("String '--' not allowed in comment (missing '>'?)"); - } - } - - protected void skipCommentContent() - throws XMLStreamException - { - while (true) { - char c = (mInputPtr < mInputEnd) ? - mInputBuffer[mInputPtr++] : dtdNextFromCurr(); - if (c == '-') { - c = (mInputPtr < mInputEnd) ? - mInputBuffer[mInputPtr++] : dtdNextFromCurr(); - if (c == '-') { - return; - } - } else if (c == '\n' || c == '\r') { - skipCRLF(c); - } - } - } - - protected void skipPI() - throws XMLStreamException - { - while (true) { - char c = (mInputPtr < mInputEnd) - ? mInputBuffer[mInputPtr++] : dtdNextFromCurr(); - if (c == '?') { - do { - c = (mInputPtr < mInputEnd) - ? mInputBuffer[mInputPtr++] : dtdNextFromCurr(); - } while (c == '?'); - if (c == '>') { - break; - } - } - if (c == '\n' || c == '\r') { - skipCRLF(c); - } - } - } - - private void skipDeclaration(char c) - throws XMLStreamException - { - while (c != '>') { - c = (mInputPtr < mInputEnd) - ? mInputBuffer[mInputPtr++] : dtdNextFromCurr(); - if (c == '\n' || c == '\r') { - skipCRLF(c); - /* No need for specific handling for PE refs; they just have - * identifier that'll get properly skipped. - */ - /* 17-Jul-2004, TSa: But we do need to properly handle literals; - * it is possible to add '>' char in entity expansion values. - */ - } else if (c == '\'' || c == '"') { - skipLiteral(c); - } - } - } - - private void skipLiteral(char quoteChar) - throws XMLStreamException - { - while (true) { - char c = (mInputPtr < mInputEnd) - ? mInputBuffer[mInputPtr++] : dtdNextFromCurr(); - if (c == '\n' || c == '\r') { - skipCRLF(c); - } else if (c == quoteChar) { - break; - } - /* No need for specific handling for PE refs, should be ignored - * just ok (plus they need to properly nested in any case) - */ - } - } - - private void skipDTDName() - throws XMLStreamException - { - /*int len =*/ skipFullName(getNextChar(getErrorMsg())); - /* Should we give an error about missing name? For now, - * let's just exit. - */ - } - - /* - ////////////////////////////////////////////////// - // Internal methods, error handling: - ////////////////////////////////////////////////// - */ - - protected String getErrorMsg() { - return mIsExternal ? SUFFIX_IN_DTD_EXTERNAL : SUFFIX_IN_DTD_INTERNAL; - } - - - protected void throwIllegalCall() - throws Error - { - throw new IllegalStateException("Internal error: this method should never be called"); - } -} - diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/dtd/ModelNode.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/dtd/ModelNode.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/dtd/ModelNode.java 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/dtd/ModelNode.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,35 +0,0 @@ -package com.ctc.wstx.dtd; - -import java.util.BitSet; -import java.util.List; - -/** - * Abstract base class for classes constructed from {@link ContentSpec} - * objects, when they get rewritten (when their {@link ContentSpec#rewrite} - * gets called). These nodes are then used for constructing complete DFA - * states for validation. - */ -public abstract class ModelNode -{ - /* - /////////////////////////////////////////////////// - // Methods needed for DFA construction - /////////////////////////////////////////////////// - */ - - /** - * Method that has to create a deep copy of the model, without - * sharing any of existing Objects. - */ - public abstract ModelNode cloneModel(); - - public abstract boolean isNullable(); - - public abstract void indexTokens(List tokens); - - public abstract void addFirstPos(BitSet firstPos); - - public abstract void addLastPos(BitSet firstPos); - - public abstract void calcFollowPos(BitSet[] followPosSets); -} diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/dtd/OptionalModel.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/dtd/OptionalModel.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/dtd/OptionalModel.java 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/dtd/OptionalModel.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,65 +0,0 @@ -package com.ctc.wstx.dtd; - -import java.util.*; - -/** - * Content specification class that represents an optional specification. - * Optional specifications are generally a result of '?' arity marker, - * and are created when {@link ContentSpec#rewrite} is called - * on a specification with '?' arity modifier. - */ -public class OptionalModel - extends ModelNode -{ - ModelNode mModel; - - /* - /////////////////////////////////////////////////// - // Life-cycle - /////////////////////////////////////////////////// - */ - - public OptionalModel(ModelNode model) { - mModel = model; - } - - /* - /////////////////////////////////////////////////// - // Public API - /////////////////////////////////////////////////// - */ - - /** - * Method that has to create a deep copy of the model, without - * sharing any of existing Objects. - */ - public ModelNode cloneModel() { - return new OptionalModel(mModel.cloneModel()); - } - - public boolean isNullable() { - return true; - } - - public void indexTokens(List tokens) { - mModel.indexTokens(tokens); - } - - public void addFirstPos(BitSet pos) { - mModel.addFirstPos(pos); - } - - public void addLastPos(BitSet pos) { - mModel.addLastPos(pos); - } - - public void calcFollowPos(BitSet[] followPosSets) - { - // Let's let sub-model do its stuff - mModel.calcFollowPos(followPosSets); - } - - public String toString() { - return mModel + "[?]"; - } -} diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/dtd/package.html libwoodstox-java-5.1.0/src/java/com/ctc/wstx/dtd/package.html --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/dtd/package.html 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/dtd/package.html 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ - -Package that contains Woodstox classes that implement DTD handling. - diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/dtd/PrefixedNameSet.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/dtd/PrefixedNameSet.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/dtd/PrefixedNameSet.java 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/dtd/PrefixedNameSet.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,46 +0,0 @@ -/* Woodstox XML processor - * - * Copyright (c) 2004 Tatu Saloranta, tatu.saloranta@iki.fi - * - * Licensed under the License specified in file LICENSE, included with - * the source code. - * You may not use this file except in compliance with the License. - * - * 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 com.ctc.wstx.dtd; - -import com.ctc.wstx.util.PrefixedName; - -public abstract class PrefixedNameSet -{ - protected PrefixedNameSet() { } - - /** - * @return True if set contains more than one entry; false if not - * (empty or has one) - */ - public abstract boolean hasMultiple(); - - /** - * @return True if the set contains specified name; false if not. - */ - public abstract boolean contains(PrefixedName name); - - public abstract void appendNames(StringBuffer sb, String sep); - - public final String toString() { - return toString(", "); - } - - public final String toString(String sep) { - StringBuffer sb = new StringBuffer(); - appendNames(sb, sep); - return sb.toString(); - } -} diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/dtd/SeqContentSpec.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/dtd/SeqContentSpec.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/dtd/SeqContentSpec.java 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/dtd/SeqContentSpec.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,233 +0,0 @@ -package com.ctc.wstx.dtd; - -import java.util.*; - -import com.ctc.wstx.util.PrefixedName; - -/** - * Content specification that defines model that has sequence of one or more - * elements that have to come in the specified order. - */ -public class SeqContentSpec - extends ContentSpec -{ - final boolean mNsAware; - - final ContentSpec[] mContentSpecs; - - /* - /////////////////////////////////////////////////// - // Life-cycle - /////////////////////////////////////////////////// - */ - - public SeqContentSpec(boolean nsAware, char arity, ContentSpec[] subSpecs) - { - super(arity); - mNsAware = nsAware; - mContentSpecs = subSpecs; - } - - public static SeqContentSpec construct(boolean nsAware, char arity, Collection subSpecs) - { - ContentSpec[] specs = new ContentSpec[subSpecs.size()]; - subSpecs.toArray(specs); - return new SeqContentSpec(nsAware, arity, specs); - } - - /* - /////////////////////////////////////////////////// - // Public API - /////////////////////////////////////////////////// - */ - - public StructValidator getSimpleValidator() - { - /* Can we create a simple validator? Yes, if the sub-specs are - * all simple (leaves == element tokens with no arity modifier) - */ - ContentSpec[] specs = mContentSpecs; - int i = 0; - int len = specs.length; - - for (; i < len; ++i) { - if (!specs[i].isLeaf()) { - break; - } - } - - if (i == len) { // all leaves, kewl - PrefixedName[] set = new PrefixedName[len]; - for (i = 0; i < len; ++i) { - TokenContentSpec ss = (TokenContentSpec) specs[i]; - set[i] = ss.getName(); - } - return new Validator(mArity, set); - } - - // Nope, need a DFA: - return null; - } - - public ModelNode rewrite() - { - /* First, need to create a tree of sub-models, consisting of - * binary concat nodes (as opposed to n-ary list). Can do that - * recursively (note that we'll always have at least 2 child - * nodes!) - */ - ModelNode model = rewrite(mContentSpecs, 0, mContentSpecs.length); - - // and then resolve arity modifiers, if necessary: - if (mArity == '*') { - return new StarModel(model); - } - if (mArity == '?') { - return new OptionalModel(model); - } - if (mArity == '+') { - return new ConcatModel(model, - new StarModel(model.cloneModel())); - } - return model; - } - - private ModelNode rewrite(ContentSpec[] specs, int first, int last) - { - // 3 or less, can convert and create; 4 or more, need to recurse: - int count = last - first; - if (count > 3) { - int mid = (last + first + 1) >> 1; - return new ConcatModel(rewrite(specs, first, mid), - rewrite(specs, mid, last)); - } - ConcatModel model = new ConcatModel(specs[first].rewrite(), - specs[first+1].rewrite()); - if (count == 3) { - model = new ConcatModel(model, specs[first+2].rewrite()); - } - return model; - } - - public String toString() - { - StringBuffer sb = new StringBuffer(); - sb.append('('); - - for (int i = 0; i < mContentSpecs.length; ++i) { - if (i > 0) { - sb.append(", "); - } - sb.append(mContentSpecs[i].toString()); - } - sb.append(')'); - - if (mArity != ' ') { - sb.append(mArity); - } - return sb.toString(); - } - - /* - /////////////////////////////////////////////////// - // Validator class that can be used for simple - // choices (including mixed content) - /////////////////////////////////////////////////// - */ - - /** - * Simple validator that can be used if all components of a sequence - * are leaf nodes, ie. elements with no explicit arity modifiers. - */ - final static class Validator - extends StructValidator - { - final char mArity; - final PrefixedName[] mNames; - - /** - * Number of full repetitions done over the sequence - */ - int mRounds = 0; - - /** - * Expected next element in the sequence - */ - int mStep = 0; - - public Validator(char arity, PrefixedName[] names) - { - mArity = arity; - mNames = names; - } - - - /** - * Sequence content specification is always stateful; can not - * use a shared instance... so let's create new instance: - */ - public StructValidator newInstance() { - return new Validator(mArity, mNames); - } - - public String tryToValidate(PrefixedName elemName) - { - // First; have we already done that max. 1 sequence? - if (mStep == 0 && mRounds == 1) { - if (mArity == '?' || mArity == ' ') { - return "was not expecting any more elements in the sequence (" - +concatNames(mNames)+")"; - } - } - - PrefixedName next = mNames[mStep]; - if (!elemName.equals(next)) { - return expElem(mStep); - } - if (++mStep == mNames.length) { - ++mRounds; - mStep = 0; - } - return null; - } - - public String fullyValid() - { - if (mStep != 0) { - return expElem(mStep)+"; got end element"; - } - - switch (mArity) { - case '*': - case '?': - return null; - case '+': // need at least one (and multiples checked earlier) - case ' ': - if (mRounds > 0) { - return null; - } - return "Expected sequence ("+concatNames(mNames)+"); got end element"; - } - // should never happen: - throw new IllegalStateException("Internal error"); - } - - private String expElem(int step) - { - return "expected element <"+mNames[step]+"> in sequence (" - +concatNames(mNames)+")"; - } - - final static String concatNames(PrefixedName[] names) - { - StringBuffer sb = new StringBuffer(); - for (int i = 0, len = names.length; i < len; ++i) { - if (i > 0) { - sb.append(", "); - } - sb.append(names[i].toString()); - } - return sb.toString(); - } - } -} diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/dtd/SmallPrefixedNameSet.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/dtd/SmallPrefixedNameSet.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/dtd/SmallPrefixedNameSet.java 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/dtd/SmallPrefixedNameSet.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,101 +0,0 @@ -package com.ctc.wstx.dtd; - -import com.ctc.wstx.util.PrefixedName; - -/** - * PrefixedNameSet implementation suitable for storing small set of PrefixedName - * values (generally 8 or less). Uses linear search, and is thus the - * most compact presentation for a set - *

- * Notes about usage: - *

    - *
  • All Strings contained in {@link PrefixedName} instances are assumed - * interned, so that equality comparison can be done (both for values - * stored and keys used) - *
  • - *
  • It is assumed that sets are never empty, ie. always contain at - * least one entry. - *
  • - *
  • It is assumed that caller has ensured that there are no duplicates - * in the set -- this data structure does no further validation. - *
  • - *
- */ -public final class SmallPrefixedNameSet - extends PrefixedNameSet -{ - final boolean mNsAware; - - final String[] mStrings; - - public SmallPrefixedNameSet(boolean nsAware, PrefixedName[] names) - { - mNsAware = nsAware; - int len = names.length; - if (len == 0) { // sanity check - throw new IllegalStateException("Trying to construct empty PrefixedNameSet"); - } - mStrings = new String[nsAware ? (len+len) : len]; - for (int out = 0, in = 0; in < len; ++in) { - PrefixedName nk = names[in]; - if (nsAware) { - mStrings[out++] = nk.getPrefix(); - } - mStrings[out++] = nk.getLocalName(); - } - } - - public boolean hasMultiple() { - return mStrings.length > 1; - } - - /** - * @return True if the set contains specified name; false if not. - */ - public boolean contains(PrefixedName name) - { - int len = mStrings.length; - String ln = name.getLocalName(); - String[] strs = mStrings; - - if (mNsAware) { - String prefix = name.getPrefix(); - if (strs[1] == ln && strs[0] == prefix) { - return true; - } - for (int i = 2; i < len; i += 2) { - if (strs[i+1] == ln && strs[i] == prefix) { - return true; - } - } - } else { - if (strs[0] == ln) { - return true; - } - for (int i = 1; i < len; ++i) { - if (strs[i] == ln) { - return true; - } - } - } - - return false; - } - - public void appendNames(StringBuffer sb, String sep) - { - for (int i = 0; i < mStrings.length; ) { - if (i > 0) { - sb.append(sep); - } - if (mNsAware) { - String prefix = mStrings[i++]; - if (prefix != null) { - sb.append(prefix); - sb.append(':'); - } - } - sb.append(mStrings[i++]); - } - } -} diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/dtd/StarModel.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/dtd/StarModel.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/dtd/StarModel.java 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/dtd/StarModel.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,83 +0,0 @@ -package com.ctc.wstx.dtd; - -import java.util.*; - -/** - * Model class that represents any number of repetitions of its submodel - * (including no repetitions). - */ -public class StarModel - extends ModelNode -{ - ModelNode mModel; - - /* - /////////////////////////////////////////////////// - // Life-cycle - /////////////////////////////////////////////////// - */ - - public StarModel(ModelNode model) { - super(); - mModel = model; - } - - /* - /////////////////////////////////////////////////// - // Public API - /////////////////////////////////////////////////// - */ - - /** - * Method that has to create a deep copy of the model, without - * sharing any of existing Objects. - */ - public ModelNode cloneModel() { - return new StarModel(mModel.cloneModel()); - } - - public boolean isNullable() { - return true; - } - - public void indexTokens(List tokens) { - mModel.indexTokens(tokens); - } - - public void addFirstPos(BitSet pos) { - mModel.addFirstPos(pos); - } - - public void addLastPos(BitSet pos) { - mModel.addLastPos(pos); - } - - public void calcFollowPos(BitSet[] followPosSets) - { - // First, let's let sub-model do its stuff - mModel.calcFollowPos(followPosSets); - - /* And then add the closure for the model (since sub-model - * can 'follow itself' as many times as it needs to) - */ - - BitSet foll = new BitSet(); - mModel.addFirstPos(foll); - - BitSet toAddTo = new BitSet(); - mModel.addLastPos(toAddTo); - - int ix = 0; // need to/can skip the null entry (index 0) - while ((ix = toAddTo.nextSetBit(ix+1)) >= 0) { - /* Ok; so token at this index needs to have follow positions - * added... - */ - followPosSets[ix].or(foll); - } - } - - public String toString() { - return mModel.toString() + "*"; - } -} - diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/dtd/StructValidator.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/dtd/StructValidator.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/dtd/StructValidator.java 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/dtd/StructValidator.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,51 +0,0 @@ -/* Woodstox XML processor - * - * Copyright (c) 2004 Tatu Saloranta, tatu.saloranta@iki.fi - * - * Licensed under the License specified in the file LICENSE which is - * included with the source code. - * You may not use this file except in compliance with the License. - * - * 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 com.ctc.wstx.dtd; - -import com.ctc.wstx.util.PrefixedName; - -/** - * Base class for validator Objects used to validate tree structure of an - * XML-document against DTD. - */ -public abstract class StructValidator -{ - /** - * Method that should be called to get the actual usable validator - * instance, from the 'template' validator. - */ - public abstract StructValidator newInstance(); - - /** - * Method called when a new (start) element is encountered within the - * scope of parent element this validator monitors. - * - * @return Null if element is valid in its current position; error - * message if not. - */ - public abstract String tryToValidate(PrefixedName elemName); - - /** - * Method called when the end element of the scope this validator - * validates is encountered. It should make sure that the content - * model is valid, and if not, to construct an error message. - * - * @return Null if the content model for the element is valid; error - * message if not. - */ - public abstract String fullyValid(); -} - diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/dtd/TokenContentSpec.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/dtd/TokenContentSpec.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/dtd/TokenContentSpec.java 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/dtd/TokenContentSpec.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,138 +0,0 @@ -package com.ctc.wstx.dtd; - -import com.ctc.wstx.cfg.ErrorConsts; -import com.ctc.wstx.util.PrefixedName; - -/** - * Content specification that defines content model consisting of just - * one allowed element. In addition to the allowed element, spec can have - * optional arity ("*", "+", "?") marker. - */ -public class TokenContentSpec - extends ContentSpec -{ - final static TokenContentSpec sDummy = new TokenContentSpec - (' ', new PrefixedName("*", "*")); - - final PrefixedName mElemName; - - /* - /////////////////////////////////////////////////// - // Life-cycle - /////////////////////////////////////////////////// - */ - - public TokenContentSpec(char arity, PrefixedName elemName) - { - super(arity); - mElemName = elemName; - } - - public static TokenContentSpec construct(char arity, PrefixedName elemName) - { - return new TokenContentSpec(arity, elemName); - } - - public static TokenContentSpec getDummySpec() { - return sDummy; - } - - /* - /////////////////////////////////////////////////// - // Public API - /////////////////////////////////////////////////// - */ - - public boolean isLeaf() { - return mArity == ' '; - } - - public PrefixedName getName() { - return mElemName; - } - - public StructValidator getSimpleValidator() { - return new Validator(mArity, mElemName); - } - - public ModelNode rewrite() { - TokenModel model = new TokenModel(mElemName); - if (mArity == '*') { - return new StarModel(model); - } - if (mArity == '?') { - return new OptionalModel(model); - } - if (mArity == '+') { - return new ConcatModel(model, - new StarModel(new TokenModel(mElemName))); - } - return model; - } - - public String toString() { - return (mArity == ' ') ? mElemName.toString() - : (mElemName.toString() + mArity); - } - - /* - /////////////////////////////////////////////////// - // Validator class: - /////////////////////////////////////////////////// - */ - - final static class Validator - extends StructValidator - { - final char mArity; - final PrefixedName mElemName; - - int mCount = 0; - - public Validator(char arity, PrefixedName elemName) - { - mArity = arity; - mElemName = elemName; - } - - /** - * Rules for reuse are simple: if we can have any number of - * repetitions, we can just use a shared root instance. Although - * its count variable will get updated this doesn't really - * matter as it won't be used. Otherwise a new instance has to - * be created always, to keep track of instance counts. - */ - public StructValidator newInstance() { - return (mArity == '*') ? this : new Validator(mArity, mElemName); - } - - public String tryToValidate(PrefixedName elemName) - { - if (!elemName.equals(mElemName)) { - return "Expected element <"+mElemName+">"; - } - if (++mCount > 1 && (mArity == '?' || mArity == ' ')) { - return "More than one instance of element <"+mElemName+">"; - } - return null; - } - - public String fullyValid() - { - switch (mArity) { - case '*': - case '?': - return null; - case '+': // need at least one (and multiples checked earlier) - case ' ': - if (mCount > 0) { - return null; - } - return "Expected "+(mArity == '+' ? "at least one" : "") - +" element <"+mElemName+">"; - } - // should never happen: - throw new IllegalStateException(ErrorConsts.ERR_INTERNAL); - } - } -} diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/dtd/TokenModel.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/dtd/TokenModel.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/dtd/TokenModel.java 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/dtd/TokenModel.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,90 +0,0 @@ -package com.ctc.wstx.dtd; - -import java.util.BitSet; -import java.util.List; - -import com.ctc.wstx.util.PrefixedName; - -/** - * Model class that encapsulates a single (obligatory) token instance. - */ -public final class TokenModel - extends ModelNode -{ - final static TokenModel NULL_TOKEN = new TokenModel(null); - static { // null token needs to have 0 as its index... - NULL_TOKEN.mTokenIndex = 0; - } - - final PrefixedName mElemName; - - int mTokenIndex = -1; // to catch errors... - - /* - /////////////////////////////////////////////////// - // Life-cycle - /////////////////////////////////////////////////// - */ - - public TokenModel(PrefixedName elemName) { - mElemName = elemName; - } - - public static TokenModel getNullToken() { - return NULL_TOKEN; - } - - /* - /////////////////////////////////////////////////// - // Public API - /////////////////////////////////////////////////// - */ - - public PrefixedName getName() { return mElemName; } - - /** - * Method that has to create a deep copy of the model, without - * sharing any of existing Objects. - */ - public ModelNode cloneModel() { - return new TokenModel(mElemName); - } - - public boolean isNullable() { - return false; - } - - public void indexTokens(List tokens) - { - /* Doh. This is not clean... but need to make sure the null - * token never gets reindexed or explicitly added: - */ - if (this != NULL_TOKEN) { - int index = tokens.size(); - mTokenIndex = index; - tokens.add(this); - } - } - - public void addFirstPos(BitSet firstPos) { - firstPos.set(mTokenIndex); - } - - public void addLastPos(BitSet lastPos) { - lastPos.set(mTokenIndex); - } - - public void calcFollowPos(BitSet[] followPosSets) { - // nothing to do, for tokens... - } - - public String toString() { - return (mElemName == null) ? "[null]" : mElemName.toString(); - } - - /* - /////////////////////////////////////////////////// - // Internal methods - /////////////////////////////////////////////////// - */ -} diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/ent/EntityDecl.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/ent/EntityDecl.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/ent/EntityDecl.java 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/ent/EntityDecl.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,135 +0,0 @@ -/* Woodstox XML processor - * - * Copyright (c) 2004 Tatu Saloranta, tatu.saloranta@iki.fi - * - * Licensed under the License specified in file LICENSE, included with - * the source code. - * You may not use this file except in compliance with the License. - * - * 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 com.ctc.wstx.ent; - -import java.io.IOException; -import java.io.Writer; -import java.net.URL; - -import javax.xml.stream.Location; -import javax.xml.stream.XMLResolver; -import javax.xml.stream.XMLStreamException; - -import com.ctc.wstx.api.ReaderConfig; -import com.ctc.wstx.evt.WEntityDeclaration; -import com.ctc.wstx.io.WstxInputSource; - -/** - * Abstract base class for various entity declarations DTD reader - * has parsed from DTD subsets. - */ -public abstract class EntityDecl - extends WEntityDeclaration -{ - /** - * Name/id of the entity used to reference it. - */ - final String mName; - - /** - * Context that is to be used to resolve references encountered from - * expanded contents of this entity. - */ - final URL mContext; - - /** - * Flag that can be set to indicate that the declaration was in the - * external DTD subset. Default is false. - */ - protected boolean mDeclaredExternally = false; - - public EntityDecl(Location loc, String name, URL ctxt) - { - super(loc); - mName = name; - mContext = ctxt; - } - - public void markAsExternallyDeclared() { - mDeclaredExternally = true; - } - - public final String getBaseURI() { - return mContext.toExternalForm(); - } - - public final String getName() { - return mName; - } - - public final Location getLocation() { - return mLocation; - } - - public abstract String getNotationName(); - - public abstract String getPublicId(); - - public abstract String getReplacementText(); - - public abstract int getReplacementText(Writer w) - throws IOException; - - public abstract String getSystemId(); - - /** - * @return True, if the declaration occured in the external DTD - * subset; false if not (internal subset, custom declaration) - */ - public boolean wasDeclaredExternally() { - return mDeclaredExternally; - } - - /* - /////////////////////////////////////////// - // Implementation of abstract base methods - /////////////////////////////////////////// - */ - - public abstract void writeEnc(Writer w) throws IOException; - - /* - /////////////////////////////////////////// - // Extended API for Wstx core - /////////////////////////////////////////// - */ - - // // // Access to data - - public abstract char[] getReplacementChars(); - - public final int getReplacementTextLength() { - String str = getReplacementText(); - return (str == null) ? 0 : str.length(); - } - - // // // Type information - - public abstract boolean isExternal(); - - public abstract boolean isParsed(); - - // // // Factory methods - - /** - * Method called to create the new input source through which expansion - * value of the entity can be read. - */ - public abstract WstxInputSource expand(WstxInputSource parent, - XMLResolver res, ReaderConfig cfg, - int xmlVersion) - throws IOException, XMLStreamException; -} diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/ent/ExtEntity.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/ent/ExtEntity.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/ent/ExtEntity.java 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/ent/ExtEntity.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,78 +0,0 @@ -package com.ctc.wstx.ent; - -import com.ctc.wstx.api.ReaderConfig; -import java.io.IOException; -import java.io.Writer; -import java.net.URL; - -import javax.xml.stream.Location; -import javax.xml.stream.XMLResolver; -import javax.xml.stream.XMLStreamException; - -import com.ctc.wstx.io.WstxInputSource; - -public abstract class ExtEntity - extends EntityDecl -{ - final String mPublicId; - final String mSystemId; - - public ExtEntity(Location loc, String name, URL ctxt, - String pubId, String sysId) - { - super(loc, name, ctxt); - mPublicId = pubId; - mSystemId = sysId; - } - - public abstract String getNotationName(); - - public String getPublicId() { - return mPublicId; - } - - public String getReplacementText() { - return null; - } - - public int getReplacementText(Writer w) - //throws IOException - { - return 0; - } - - public String getSystemId() { - return mSystemId; - } - - /* - /////////////////////////////////////////// - // Implementation of abstract base methods - /////////////////////////////////////////// - */ - - public abstract void writeEnc(Writer w) throws IOException; - - /* - /////////////////////////////////////////// - // Extended API for Wstx core - /////////////////////////////////////////// - */ - - // // // Access to data - - public char[] getReplacementChars() { - return null; - } - - // // // Type information - - public boolean isExternal() { return true; } - - public abstract boolean isParsed(); - - public abstract WstxInputSource expand(WstxInputSource parent, - XMLResolver res, ReaderConfig cfg, - int xmlVersion) - throws IOException, XMLStreamException; -} diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/ent/IntEntity.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/ent/IntEntity.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/ent/IntEntity.java 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/ent/IntEntity.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,134 +0,0 @@ -package com.ctc.wstx.ent; - -import java.io.IOException; -import java.io.Writer; -import java.net.URL; - -import javax.xml.stream.Location; -import javax.xml.stream.XMLResolver; - -import com.ctc.wstx.api.ReaderConfig; -import com.ctc.wstx.io.InputSourceFactory; -import com.ctc.wstx.io.TextEscaper; -import com.ctc.wstx.io.WstxInputLocation; -import com.ctc.wstx.io.WstxInputSource; - -public class IntEntity - extends EntityDecl -{ - /** - * Location where entity content definition started; - * points to the starting/opening quote for internal - * entities. - */ - protected final Location mContentLocation; - - /** - * Replacement text of the entity; full array contents. - */ - final char[] mRepl; - - String mReplText = null; - - public IntEntity(Location loc, String name, URL ctxt, - char[] repl, Location defLoc) - { - super(loc, name, ctxt); - mRepl = repl; - mContentLocation = defLoc; - } - - public static IntEntity create(String id, String repl) - { - return create(id, repl.toCharArray()); - } - - public static IntEntity create(String id, char[] val) - { - WstxInputLocation loc = WstxInputLocation.getEmptyLocation(); - return new IntEntity(loc, id, null, val, loc); - } - - public String getNotationName() { - return null; - } - - public String getPublicId() { - return null; - } - - public String getReplacementText() - { - String repl = mReplText; - if (repl == null) { - repl = (mRepl.length == 0) ? "" : new String(mRepl); - mReplText = repl; - } - return mReplText; - } - - public int getReplacementText(Writer w) - throws IOException - { - w.write(mRepl); - return mRepl.length; - } - - public String getSystemId() { - return null; - } - - /* - /////////////////////////////////////////// - // Implementation of abstract base methods - /////////////////////////////////////////// - */ - - public void writeEnc(Writer w) throws IOException - { - w.write(""); - } - - /* - /////////////////////////////////////////// - // Extended API for Wstx core - /////////////////////////////////////////// - */ - - // // // Access to data - - /** - * Gives raw access to replacement text data... - *

- * Note: this is not really safe, as caller can modify the array, but - * since this method is thought to provide fast access, let's avoid making - * copy here. - */ - public char[] getReplacementChars() { - return mRepl; - } - - // // // Type information - - public boolean isExternal() { return false; } - - public boolean isParsed() { return true; } - - public WstxInputSource expand(WstxInputSource parent, - XMLResolver res, ReaderConfig cfg, - int xmlVersion) - { - /* 26-Dec-2006, TSa: Better leave source as null, since internal - * entity declaration context should never be used: when expanding, - * reference context is to be used. - */ - return InputSourceFactory.constructCharArraySource - //(parent, mName, mRepl, 0, mRepl.length, mContentLocation, getSource()); - (parent, mName, mRepl, 0, mRepl.length, mContentLocation, null); - } -} - diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/ent/package.html libwoodstox-java-5.1.0/src/java/com/ctc/wstx/ent/package.html --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/ent/package.html 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/ent/package.html 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ - -Package contains internal entity object implementations, which are used -by stream reader classes, but parsed by dtd functionality. They are also -used for constructing entity events, - diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/ent/ParsedExtEntity.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/ent/ParsedExtEntity.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/ent/ParsedExtEntity.java 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/ent/ParsedExtEntity.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,76 +0,0 @@ -package com.ctc.wstx.ent; - -import java.io.IOException; -import java.io.Writer; -import java.net.URL; - -import javax.xml.stream.Location; -import javax.xml.stream.XMLResolver; -import javax.xml.stream.XMLStreamException; - -import com.ctc.wstx.api.ReaderConfig; -import com.ctc.wstx.cfg.XmlConsts; -import com.ctc.wstx.io.DefaultInputResolver; -import com.ctc.wstx.io.WstxInputSource; - -public class ParsedExtEntity - extends ExtEntity -{ - public ParsedExtEntity(Location loc, String name, URL ctxt, - String pubId, String sysId) - { - super(loc, name, ctxt, pubId, sysId); - } - - public String getNotationName() { - return null; - } - - /* - /////////////////////////////////////////// - // Implementation of abstract base methods - /////////////////////////////////////////// - */ - - public void writeEnc(Writer w) throws IOException - { - w.write(""); - } - - /* - /////////////////////////////////////////// - // Extended API for Wstx core - /////////////////////////////////////////// - */ - - // // // Type information - - public boolean isParsed() { return true; } - - public WstxInputSource expand(WstxInputSource parent, - XMLResolver res, ReaderConfig cfg, - int xmlVersion) - throws IOException, XMLStreamException - { - /* 05-Feb-2006, TSa: If xmlVersion not explicitly known, it defaults - * to 1.0 - */ - if (xmlVersion == XmlConsts.XML_V_UNKNOWN) { - xmlVersion = XmlConsts.XML_V_10; - } - return DefaultInputResolver.resolveEntity - (parent, mContext, mName, getPublicId(), getSystemId(), res, cfg, xmlVersion); - } -} diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/ent/UnparsedExtEntity.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/ent/UnparsedExtEntity.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/ent/UnparsedExtEntity.java 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/ent/UnparsedExtEntity.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,72 +0,0 @@ -package com.ctc.wstx.ent; - -import java.io.IOException; -import java.io.Writer; -import java.net.URL; - -import javax.xml.stream.Location; -import javax.xml.stream.XMLResolver; - -import com.ctc.wstx.api.ReaderConfig; -import com.ctc.wstx.io.WstxInputSource; - -public class UnparsedExtEntity - extends ExtEntity -{ - final String mNotationId; - - public UnparsedExtEntity(Location loc, String name, URL ctxt, - String pubId, String sysId, - String notationId) - { - super(loc, name, ctxt, pubId, sysId); - mNotationId = notationId; - } - - public String getNotationName() { - return mNotationId; - } - - /* - /////////////////////////////////////////// - // Implementation of abstract base methods - /////////////////////////////////////////// - */ - - public void writeEnc(Writer w) throws IOException - { - w.write("'); - } - - /* - /////////////////////////////////////////// - // Extended API for Wstx core - /////////////////////////////////////////// - */ - - // // // Type information - - public boolean isParsed() { return false; } - - public WstxInputSource expand(WstxInputSource parent, - XMLResolver res, ReaderConfig cfg, - int xmlVersion) - { - // Should never get called, actually... - throw new IllegalStateException("Internal error: createInputSource() called for unparsed (external) entity."); - } -} diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/evt/BaseStartElement.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/evt/BaseStartElement.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/evt/BaseStartElement.java 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/evt/BaseStartElement.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,184 +0,0 @@ -/* Woodstox XML processor - * - * Copyright (c) 2004 Tatu Saloranta, tatu.saloranta@iki.fi - * - * Licensed under the License specified in file LICENSE, included with - * the source code. - * You may not use this file except in compliance with the License. - * - * 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 com.ctc.wstx.evt; - -import java.io.IOException; -import java.io.Writer; -import java.util.Iterator; - -import javax.xml.namespace.NamespaceContext; -import javax.xml.namespace.QName; -import javax.xml.stream.*; -import javax.xml.stream.events.Attribute; -import javax.xml.stream.events.StartElement; - -import org.codehaus.stax2.XMLStreamWriter2; -import org.codehaus.stax2.ri.EmptyIterator; -import org.codehaus.stax2.ri.evt.BaseEventImpl; - -import com.ctc.wstx.exc.WstxIOException; -import com.ctc.wstx.util.BaseNsContext; - -/** - * Shared base class of {@link StartElement} implementations Wstx uses. - */ -abstract class BaseStartElement - extends BaseEventImpl - implements StartElement -{ - protected final QName mName; - - protected final BaseNsContext mNsCtxt; - - /* - ///////////////////////////////////////////// - // Life cycle - ///////////////////////////////////////////// - */ - - protected BaseStartElement(Location loc, QName name, BaseNsContext nsCtxt) - { - super(loc); - mName = name; - mNsCtxt = nsCtxt; - } - - /* - ///////////////////////////////////////////// - // StartElement API - ///////////////////////////////////////////// - */ - - public abstract Attribute getAttributeByName(QName name); - - public abstract Iterator getAttributes(); - - public final QName getName() { - return mName; - } - - public Iterator getNamespaces() - { - if (mNsCtxt == null) { - return EmptyIterator.getInstance(); - } - /* !!! 28-Sep-2004: Should refactor, since now it's up to ns context - * to construct namespace events... which adds unnecessary - * up-dependency from stream level to event objects. - */ - return mNsCtxt.getNamespaces(); - } - - public NamespaceContext getNamespaceContext() - { - return mNsCtxt; - } - - public String getNamespaceURI(String prefix) { - return (mNsCtxt == null) ? null : mNsCtxt.getNamespaceURI(prefix); - } - - /* - ///////////////////////////////////////////////////// - // Implementation of abstract base methods, overrides - ///////////////////////////////////////////////////// - */ - - public StartElement asStartElement() { // overriden to save a cast - return this; - } - - public int getEventType() { - return START_ELEMENT; - } - - public boolean isStartElement() { - return true; - } - - public void writeAsEncodedUnicode(Writer w) - throws XMLStreamException - { - try { - w.write('<'); - String prefix = mName.getPrefix(); - if (prefix != null && prefix.length() > 0) { - w.write(prefix); - w.write(':'); - } - w.write(mName.getLocalPart()); - - // Base class can output namespaces and attributes: - outputNsAndAttr(w); - - w.write('>'); - } catch (IOException ie) { - throw new WstxIOException(ie); - } - } - - public void writeUsing(XMLStreamWriter2 w) throws XMLStreamException - { - QName n = mName; - w.writeStartElement(n.getPrefix(), n.getLocalPart(), - n.getNamespaceURI()); - outputNsAndAttr(w); - } - - protected abstract void outputNsAndAttr(Writer w) throws IOException; - - protected abstract void outputNsAndAttr(XMLStreamWriter w) throws XMLStreamException; - - /* - /////////////////////////////////////////// - // Standard method implementation - // - // note: copied from Stax2 RI's StartElementEventImpl - /////////////////////////////////////////// - */ - - public boolean equals(Object o) - { - if (o == this) return true; - if (o == null) return false; - - if (!(o instanceof StartElement)) return false; - - StartElement other = (StartElement) o; - - // First things first: names must match - if (mName.equals(other.getName())) { - /* Rest is much trickier. I guess the easiest way is to - * just blindly iterate through ns decls and attributes. - * The main issue is whether ordering should matter; it will, - * if just iterating. Would need to sort to get canonical - * comparison. - */ - if (iteratedEquals(getNamespaces(), other.getNamespaces())) { - return iteratedEquals(getAttributes(), other.getAttributes()); - } - } - return false; - } - - public int hashCode() - { - int hash = mName.hashCode(); - hash = addHash(getNamespaces(), hash); - hash = addHash(getAttributes(), hash); - return hash; - } -} diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/evt/CompactStartElement.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/evt/CompactStartElement.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/evt/CompactStartElement.java 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/evt/CompactStartElement.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,162 +0,0 @@ -package com.ctc.wstx.evt; - -import java.io.IOException; -import java.io.Writer; -import java.util.ArrayList; -import java.util.Iterator; - -import javax.xml.namespace.QName; -import javax.xml.stream.*; -import javax.xml.stream.events.Attribute; -import javax.xml.stream.events.StartElement; - -import org.codehaus.stax2.ri.EmptyIterator; -import org.codehaus.stax2.ri.SingletonIterator; -import org.codehaus.stax2.ri.evt.AttributeEventImpl; - -import com.ctc.wstx.io.TextEscaper; -import com.ctc.wstx.sr.ElemAttrs; -import com.ctc.wstx.util.BaseNsContext; - -/** - * Wstx {@link StartElement} implementation used when directly creating - * events from a stream reader. - */ -public class CompactStartElement - extends BaseStartElement -{ - // Need to be in sync with ones from ElemAttrs - //private final static int OFFSET_LOCAL_NAME = 0; - private final static int OFFSET_NS_URI = 1; - private final static int OFFSET_NS_PREFIX = 2; - private final static int OFFSET_VALUE = 3; - - /* - ///////////////////////////////////////////// - // Attribute information - ///////////////////////////////////////////// - */ - - /** - * Container object that has enough information about attributes to - * be able to implement attribute accessor methods of this class. - */ - final ElemAttrs mAttrs; - - /** - * Array needed for accessing actual String components of the attributes - */ - final String[] mRawAttrs; - - /** - * Lazily created List that contains Attribute instances contained - * in this list. Created only if there are at least 2 attributes. - */ - private ArrayList mAttrList = null; - - - /* - ///////////////////////////////////////////// - // Life cycle - ///////////////////////////////////////////// - */ - - protected CompactStartElement(Location loc, QName name, BaseNsContext nsCtxt, - ElemAttrs attrs) - { - super(loc, name, nsCtxt); - mAttrs = attrs; - mRawAttrs = (attrs == null) ? null : attrs.getRawAttrs(); - } - - /* - ///////////////////////////////////////////// - // StartElement implementation - ///////////////////////////////////////////// - */ - - public Attribute getAttributeByName(QName name) - { - if (mAttrs == null) { - return null; - } - int ix = mAttrs.findIndex(name); - if (ix < 0) { - return null; - } - return constructAttr(mRawAttrs, ix, !mAttrs.isDefault(ix)); - } - - public Iterator getAttributes() - { - if (mAttrList == null) { // List is lazily constructed as needed - if (mAttrs == null) { - return EmptyIterator.getInstance(); - } - String[] rawAttrs = mRawAttrs; - int rawLen = rawAttrs.length; - int defOffset = mAttrs.getFirstDefaultOffset(); - if (rawLen == 4) { - return new SingletonIterator - (constructAttr(rawAttrs, 0, (defOffset == 0))); - } - ArrayList l = new ArrayList(rawLen >> 2); - for (int i = 0; i < rawLen; i += 4) { - l.add(constructAttr(rawAttrs, i, (i >= defOffset))); - } - mAttrList = l; - } - return mAttrList.iterator(); - } - - protected void outputNsAndAttr(Writer w) throws IOException - { - if (mNsCtxt != null) { - mNsCtxt.outputNamespaceDeclarations(w); - } - - String[] raw = mRawAttrs; - if (raw != null) { - for (int i = 0, len = raw.length; i < len; i += 4) { - w.write(' '); - String prefix = raw[i + OFFSET_NS_PREFIX]; - if (prefix != null && prefix.length() > 0) { - w.write(prefix); - w.write(':'); - } - w.write(raw[i]); // local name - w.write("=\""); - TextEscaper.writeEscapedAttrValue(w, raw[i + OFFSET_VALUE]); - w.write('"'); - } - } - } - - protected void outputNsAndAttr(XMLStreamWriter w) throws XMLStreamException - { - if (mNsCtxt != null) { - mNsCtxt.outputNamespaceDeclarations(w); - } - String[] raw = mRawAttrs; - if (raw != null) { - for (int i = 0, len = raw.length; i < len; i += 4) { - String ln = raw[i]; - String prefix = raw[i + OFFSET_NS_PREFIX]; - String nsURI = raw[i + OFFSET_NS_URI]; - w.writeAttribute(prefix, nsURI, ln, raw[i + OFFSET_VALUE]); - } - } - } - - /* - ///////////////////////////////////////////// - // Internal methods - ///////////////////////////////////////////// - */ - - public Attribute constructAttr(String[] raw, int rawIndex, boolean isDef) - { - return new AttributeEventImpl(mLocation, raw[rawIndex], raw[rawIndex+1], - raw[rawIndex+2], raw[rawIndex+3], isDef); - } -} diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/evt/DefaultEventAllocator.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/evt/DefaultEventAllocator.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/evt/DefaultEventAllocator.java 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/evt/DefaultEventAllocator.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,285 +0,0 @@ -/* Woodstox XML processor - * - * Copyright (c) 2004 Tatu Saloranta, tatu.saloranta@iki.fi - * - * Licensed under the License specified in file LICENSE, included with - * the source code. - * You may not use this file except in compliance with the License. - * - * 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 com.ctc.wstx.evt; - -import java.util.*; - -import javax.xml.namespace.QName; -import javax.xml.namespace.NamespaceContext; -import javax.xml.stream.*; -import javax.xml.stream.events.XMLEvent; -import javax.xml.stream.util.XMLEventAllocator; -import javax.xml.stream.util.XMLEventConsumer; - -import org.codehaus.stax2.*; -import org.codehaus.stax2.ri.evt.*; - -import com.ctc.wstx.cfg.ErrorConsts; -import com.ctc.wstx.dtd.DTDSubset; -import com.ctc.wstx.ent.EntityDecl; -import com.ctc.wstx.exc.WstxException; -import com.ctc.wstx.sr.ElemAttrs; -import com.ctc.wstx.sr.ElemCallback; -import com.ctc.wstx.sr.StreamReaderImpl; -import com.ctc.wstx.util.BaseNsContext; - -/** - * Straight-forward implementation of {@link XMLEventAllocator}, to be - * used with Woodstox' event reader. - *

- * One of few complications here is the way start elements are constructed. - * The pattern used is double-indirection, needed to get a callback from - * the stream reader, with data we need for constructing even Object... - * but without stream reader having any understanding of event Objects - * per se. - *

- * 03-Dec-2004, TSa: One additional twist is that it's now possible to - * create slightly faster event handling, by indicating that the - * fully accurate Location information is not necessary. If so, - * allocator will just use one shared Location object passed to - * all event objects constructed. - */ -public class DefaultEventAllocator - extends ElemCallback - implements XMLEventAllocator, XMLStreamConstants -{ - final static DefaultEventAllocator sStdInstance = new DefaultEventAllocator(true); - - /* - //////////////////////////////////////// - // Configuration - //////////////////////////////////////// - */ - - protected final boolean mAccurateLocation; - - /* - //////////////////////////////////////// - // Recycled objects - //////////////////////////////////////// - */ - - /** - * Last used location info; only relevant to non-accurate-location - * allocators. - */ - protected Location mLastLocation = null; - - /** - * @param accurateLocation If true, allocator will construct instances - * that have accurate location information; if false, instances - * will only have some generic shared Location info. Latter option - * will reduce memory usage/thrashing a bit, and may improve speed. - */ - protected DefaultEventAllocator(boolean accurateLocation) { - mAccurateLocation = accurateLocation; - } - - public static DefaultEventAllocator getDefaultInstance() { - /* Default (accurate location) instance can be shared as it - * has no state - */ - return sStdInstance; - } - - public static DefaultEventAllocator getFastInstance() { - /* Can not share instances, due to QName caching, as well as because - * of Location object related state - */ - return new DefaultEventAllocator(false); - } - - /* - ////////////////////////////////////////////////////////// - // XMLEventAllocator implementation - ////////////////////////////////////////////////////////// - */ - - public XMLEvent allocate(XMLStreamReader r) - throws XMLStreamException - { - Location loc; - - // Need to keep track of accurate location info? - if (mAccurateLocation) { - loc = r.getLocation(); - } else { - loc = mLastLocation; - /* And even if we can just share one instance, we need that - * first instance... - */ - if (loc == null) { - loc = mLastLocation = r.getLocation(); - } - } - - switch (r.getEventType()) { - case CDATA: - return new CharactersEventImpl(loc, r.getText(), true); - case CHARACTERS: - return new CharactersEventImpl(loc, r.getText(), false); - case COMMENT: - return new CommentEventImpl(loc, r.getText()); - case DTD: - // Not sure if we really need this defensive coding but... - if (r instanceof XMLStreamReader2) { - XMLStreamReader2 sr2 = (XMLStreamReader2) r; - DTDInfo dtd = sr2.getDTDInfo(); - return new WDTD(loc, - dtd.getDTDRootName(), - dtd.getDTDSystemId(), dtd.getDTDPublicId(), - dtd.getDTDInternalSubset(), - (DTDSubset) dtd.getProcessedDTD()); - } - /* No way to get all information... the real big problem is - * that of how to access root name: it's obligatory for - * DOCTYPE construct. :-/ - */ - return new WDTD(loc, null, r.getText()); - - case END_DOCUMENT: - return new EndDocumentEventImpl(loc); - - case END_ELEMENT: - return new EndElementEventImpl(loc, r); - - case PROCESSING_INSTRUCTION: - return new ProcInstrEventImpl(loc, r.getPITarget(), r.getPIData()); - case SPACE: - { - CharactersEventImpl ch = new CharactersEventImpl(loc, r.getText(), false); - ch.setWhitespaceStatus(true); - return ch; - } - case START_DOCUMENT: - return new StartDocumentEventImpl(loc, r); - - case START_ELEMENT: - { - /* Creating the event is bit complicated, as the stream - * reader is not to know anything about event objects. - * To do this, we do double-indirection, which means that - * this object actually gets a callback: - */ - /* 19-Jul-2006, TSa: WSTX-61 points out that the code was - * assuming it's always Woodstox reader we had... not - * necessarily so. - */ - if (r instanceof StreamReaderImpl) { - StreamReaderImpl sr = (StreamReaderImpl) r; - BaseStartElement be = (BaseStartElement) sr.withStartElement(this, loc); - if (be == null) { // incorrect state - throw new WstxException("Trying to create START_ELEMENT when current event is " - +ErrorConsts.tokenTypeDesc(sr.getEventType()), - loc); - } - return be; - } - /* Ok, not woodstox impl, will be bit more work (plus less - * efficient, and may miss some info)... but can be done. - */ - NamespaceContext nsCtxt = null; - if (r instanceof XMLStreamReader2) { - nsCtxt = ((XMLStreamReader2) r).getNonTransientNamespaceContext(); - } - Map attrs; - { - int attrCount = r.getAttributeCount(); - if (attrCount < 1) { - attrs = null; - } else { - attrs = new LinkedHashMap(); - for (int i = 0; i < attrCount; ++i) { - QName aname = r.getAttributeName(i); - attrs.put(aname, new AttributeEventImpl(loc, aname, r.getAttributeValue(i), r.isAttributeSpecified(i))); - } - } - } - List ns; - { - int nsCount = r.getNamespaceCount(); - if (nsCount < 1) { - ns = null; - } else { - ns = new ArrayList(nsCount); - for (int i = 0; i < nsCount; ++i) { - ns.add(NamespaceEventImpl.constructNamespace(loc, r.getNamespacePrefix(i), r.getNamespaceURI(i))); - } - } - } - - return SimpleStartElement.construct(loc, r.getName(), attrs, ns, nsCtxt); - } - - case ENTITY_REFERENCE: - { - /* 19-Jul-2006, TSa: Let's also allow other impls, although - * we can't get actual declaration if so... - */ - if (r instanceof StreamReaderImpl) { - EntityDecl ed = ((StreamReaderImpl) r).getCurrentEntityDecl(); - if (ed == null) { // undefined? - // We'll still know the name though... - return new WEntityReference(loc, r.getLocalName()); - } - return new WEntityReference(loc, ed); - } - return new WEntityReference(loc, r.getLocalName()); - } - - - /* Following 2 types should never get in here; they are directly - * handled by DTDReader, and can only be accessed via DTD event - * element. - */ - case ENTITY_DECLARATION: - case NOTATION_DECLARATION: - /* Following 2 types should never get in here; they are directly - * handled by the reader, and can only be accessed via start - * element. - */ - case NAMESPACE: - case ATTRIBUTE: - throw new WstxException("Internal error: should not get " - +ErrorConsts.tokenTypeDesc(r.getEventType())); - default: - throw new IllegalStateException("Unrecognized event type "+r.getEventType()+"."); - } - } - - public void allocate(XMLStreamReader r, XMLEventConsumer consumer) - throws XMLStreamException - { - consumer.add(allocate(r)); - } - - public XMLEventAllocator newInstance() { - return new DefaultEventAllocator(mAccurateLocation); - } - - /* - ////////////////////////////////////////////////////////// - // ElemCallback implementation - ////////////////////////////////////////////////////////// - */ - - public Object withStartElement(Location loc, QName name, - BaseNsContext nsCtxt, ElemAttrs attrs, - boolean wasEmpty) - { - return new CompactStartElement(loc, name, nsCtxt, attrs); - } -} diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/evt/MergedNsContext.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/evt/MergedNsContext.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/evt/MergedNsContext.java 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/evt/MergedNsContext.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,212 +0,0 @@ -package com.ctc.wstx.evt; - -import java.io.IOException; -import java.io.Writer; -import java.util.*; - -import javax.xml.XMLConstants; -import javax.xml.namespace.NamespaceContext; -import javax.xml.stream.XMLStreamException; -import javax.xml.stream.XMLStreamWriter; -import javax.xml.stream.events.Namespace; - -import org.codehaus.stax2.ri.EmptyIterator; - -import com.ctc.wstx.util.BaseNsContext; - -/** - * Hierarchic {@link NamespaceContext} implementation used when constructing - * event and namespace information explicitly via - * {@link javax.xml.stream.XMLEventFactory}, - * not by a stream reader. - *

- * TODO: - *

    - *
  • Figure out a way to check for namespace masking; tricky but not - * impossible to determine - *
  • - *
- */ -public class MergedNsContext - extends BaseNsContext -{ - final NamespaceContext mParentCtxt; - - /** - * List of {@link Namespace} instances. - */ - final List mNamespaces; - - Map mNsByPrefix = null; - - Map mNsByURI = null; - - protected MergedNsContext(NamespaceContext parentCtxt, List localNs) - { - mParentCtxt = parentCtxt; - mNamespaces = (localNs == null) ? Collections.EMPTY_LIST : localNs; - } - - public static BaseNsContext construct(NamespaceContext parentCtxt, - List localNs) - { - return new MergedNsContext(parentCtxt, localNs); - } - - /* - ///////////////////////////////////////////// - // NamespaceContext API - ///////////////////////////////////////////// - */ - - public String doGetNamespaceURI(String prefix) - { - // Note: base class checks for 'known' problems and prefixes: - if (mNsByPrefix == null) { - mNsByPrefix = buildByPrefixMap(); - } - Namespace ns = (Namespace) mNsByPrefix.get(prefix); - if (ns == null && mParentCtxt != null) { - return mParentCtxt.getNamespaceURI(prefix); - } - return (ns == null) ? null : ns.getNamespaceURI(); - } - - public String doGetPrefix(String nsURI) - { - // Note: base class checks for 'known' problems and prefixes: - if (mNsByURI == null) { - mNsByURI = buildByNsURIMap(); - } - Namespace ns = (Namespace) mNsByURI.get(nsURI); - if (ns == null && mParentCtxt != null) { - return mParentCtxt.getPrefix(nsURI); - } - return (ns == null) ? null : ns.getPrefix(); - } - - public Iterator doGetPrefixes(String nsURI) - { - // Note: base class checks for 'known' problems and prefixes: - ArrayList l = null; - - for (int i = 0, len = mNamespaces.size(); i < len; ++i) { - Namespace ns = (Namespace) mNamespaces.get(i); - String uri = ns.getNamespaceURI(); - if (uri == null) { - uri = ""; - } - if (uri.equals(nsURI)) { - if (l == null) { - l = new ArrayList(); - } - String prefix = ns.getPrefix(); - l.add((prefix == null) ? "" : prefix); - } - } - - if (mParentCtxt != null) { - Iterator it = mParentCtxt.getPrefixes(nsURI); - if (l == null) { - return it; - } - while (it.hasNext()) { - l.add(it.next()); - } - } - - return (l == null) ? EmptyIterator.getInstance() : l.iterator(); - } - - /* - ///////////////////////////////////////////// - // Extended API - ///////////////////////////////////////////// - */ - - /** - * Method that returns information about namespace definition declared - * in this scope; not including ones declared in outer scopes. - */ - public Iterator getNamespaces() - { - return mNamespaces.iterator(); - } - - public void outputNamespaceDeclarations(Writer w) throws IOException - { - for (int i = 0, len = mNamespaces.size(); i < len; ++i) { - Namespace ns = (Namespace) mNamespaces.get(i); - w.write(' '); - w.write(XMLConstants.XMLNS_ATTRIBUTE); - if (!ns.isDefaultNamespaceDeclaration()) { - w.write(':'); - w.write(ns.getPrefix()); - } - w.write("=\""); - w.write(ns.getNamespaceURI()); - w.write('"'); - } - } - - /** - * Method called by the matching start element class to - * output all namespace declarations active in current namespace - * scope, if any. - */ - public void outputNamespaceDeclarations(XMLStreamWriter w) throws XMLStreamException - { - for (int i = 0, len = mNamespaces.size(); i < len; ++i) { - Namespace ns = (Namespace) mNamespaces.get(i); - if (ns.isDefaultNamespaceDeclaration()) { - w.writeDefaultNamespace(ns.getNamespaceURI()); - } else { - w.writeNamespace(ns.getPrefix(), ns.getNamespaceURI()); - } - } - } - - /* - ///////////////////////////////////////////// - // Private methods: - ///////////////////////////////////////////// - */ - - private Map buildByPrefixMap() - { - int len = mNamespaces.size(); - if (len == 0) { - return Collections.EMPTY_MAP; - } - - LinkedHashMap m = new LinkedHashMap(1 + len + (len>>1)); - for (int i = 0; i < len; ++i) { - Namespace ns = (Namespace) mNamespaces.get(i); - String prefix = ns.getPrefix(); - if (prefix == null) { // shouldn't happen but... - prefix = ""; - } - m.put(prefix, ns); - } - return m; - } - - private Map buildByNsURIMap() - { - int len = mNamespaces.size(); - if (len == 0) { - return Collections.EMPTY_MAP; - } - - LinkedHashMap m = new LinkedHashMap(1 + len + (len>>1)); - for (int i = 0; i < len; ++i) { - Namespace ns = (Namespace) mNamespaces.get(i); - String uri = ns.getNamespaceURI(); - if (uri == null) { // shouldn't happen but... - uri = ""; - } - m.put(uri, ns); - } - return m; - } -} diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/evt/package.html libwoodstox-java-5.1.0/src/java/com/ctc/wstx/evt/package.html --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/evt/package.html 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/evt/package.html 1970-01-01 00:00:00.000000000 +0000 @@ -1,4 +0,0 @@ - -Package contains Woodstox implementation of the StAX event layer; functionality -that is built on top of stream readers and writers. - diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/evt/SimpleStartElement.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/evt/SimpleStartElement.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/evt/SimpleStartElement.java 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/evt/SimpleStartElement.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,172 +0,0 @@ -package com.ctc.wstx.evt; - -import java.io.IOException; -import java.io.Writer; -import java.util.*; - -import javax.xml.namespace.NamespaceContext; -import javax.xml.namespace.QName; -import javax.xml.stream.Location; -import javax.xml.stream.XMLStreamException; -import javax.xml.stream.XMLStreamWriter; -import javax.xml.stream.events.Attribute; -import javax.xml.stream.events.Namespace; -import javax.xml.stream.events.StartElement; - -import org.codehaus.stax2.ri.EmptyIterator; - -import com.ctc.wstx.io.TextEscaper; -import com.ctc.wstx.util.BaseNsContext; - -/** - * Wstx {@link StartElement} implementation used when event is constructed - * from already objectified data, for example when constructed by the event - * factory. - */ -public class SimpleStartElement - extends BaseStartElement -{ - final Map mAttrs; - - /* - ///////////////////////////////////////////// - // Life cycle - ///////////////////////////////////////////// - */ - - protected SimpleStartElement(Location loc, QName name, BaseNsContext nsCtxt, - Map attr) - { - super(loc, name, nsCtxt); - mAttrs = attr; - } - - /** - * Factory method called when a start element needs to be constructed - * from an external source (most likely, non-woodstox stream reader). - */ - public static SimpleStartElement construct(Location loc, QName name, - Map attrs, List ns, - NamespaceContext nsCtxt) - { - BaseNsContext myCtxt = MergedNsContext.construct(nsCtxt, ns); - return new SimpleStartElement(loc, name, myCtxt, attrs); - } - - public static SimpleStartElement construct(Location loc, QName name, - Iterator attrs, Iterator ns, - NamespaceContext nsCtxt) - { - Map attrMap; - if (attrs == null || !attrs.hasNext()) { - attrMap = null; - } else { - attrMap = new LinkedHashMap(); - do { - Attribute attr = (Attribute) attrs.next(); - attrMap.put(attr.getName(), attr); - } while (attrs.hasNext()); - } - - BaseNsContext myCtxt; - if (ns != null && ns.hasNext()) { - ArrayList l = new ArrayList(); - do { - l.add((Namespace) ns.next()); // cast to catch type problems early - } while (ns.hasNext()); - myCtxt = MergedNsContext.construct(nsCtxt, l); - } else { - /* Doh. Need specificially 'our' namespace context, to get them - * output properly... - */ - if (nsCtxt == null) { - myCtxt = null; - } else if (nsCtxt instanceof BaseNsContext) { - myCtxt = (BaseNsContext) nsCtxt; - } else { - myCtxt = MergedNsContext.construct(nsCtxt, null); - } - } - return new SimpleStartElement(loc, name, myCtxt, attrMap); - } - - /* - ///////////////////////////////////////////// - // Public API - ///////////////////////////////////////////// - */ - - public Attribute getAttributeByName(QName name) - { - if (mAttrs == null) { - return null; - } - return (Attribute) mAttrs.get(name); - } - - public Iterator getAttributes() - { - if (mAttrs == null) { - return EmptyIterator.getInstance(); - } - return mAttrs.values().iterator(); - } - - protected void outputNsAndAttr(Writer w) throws IOException - { - // First namespace declarations, if any: - if (mNsCtxt != null) { - mNsCtxt.outputNamespaceDeclarations(w); - } - // Then attributes, if any: - if (mAttrs != null && mAttrs.size() > 0) { - Iterator it = mAttrs.values().iterator(); - while (it.hasNext()) { - Attribute attr = (Attribute) it.next(); - // Let's only output explicit attribute values: - if (!attr.isSpecified()) { - continue; - } - - w.write(' '); - QName name = attr.getName(); - String prefix = name.getPrefix(); - if (prefix != null && prefix.length() > 0) { - w.write(prefix); - w.write(':'); - } - w.write(name.getLocalPart()); - w.write("=\""); - String val = attr.getValue(); - if (val != null && val.length() > 0) { - TextEscaper.writeEscapedAttrValue(w, val); - } - w.write('"'); - } - } - } - - protected void outputNsAndAttr(XMLStreamWriter w) throws XMLStreamException - { - // First namespace declarations, if any: - if (mNsCtxt != null) { - mNsCtxt.outputNamespaceDeclarations(w); - } - // Then attributes, if any: - if (mAttrs != null && mAttrs.size() > 0) { - Iterator it = mAttrs.values().iterator(); - while (it.hasNext()) { - Attribute attr = (Attribute) it.next(); - // Let's only output explicit attribute values: - if (!attr.isSpecified()) { - continue; - } - QName name = attr.getName(); - String prefix = name.getPrefix(); - String ln = name.getLocalPart(); - String nsURI = name.getNamespaceURI(); - w.writeAttribute(prefix, nsURI, ln, attr.getValue()); - } - } - } -} diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/evt/WDTD.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/evt/WDTD.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/evt/WDTD.java 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/evt/WDTD.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,93 +0,0 @@ -package com.ctc.wstx.evt; - -import java.util.ArrayList; -import java.util.List; - -import javax.xml.stream.Location; - -import org.codehaus.stax2.ri.evt.DTDEventImpl; - -import com.ctc.wstx.dtd.DTDSubset; - -/** - * Event that contains all StAX accessible information read from internal - * and external DTD subsets. - */ -public class WDTD - extends DTDEventImpl -{ - /** - * Internal DTD Object that contains combined information from internal - * and external subsets. - */ - final DTDSubset mSubset; - - /* - ///////////////////////////////////////////////////// - // Lazily constructed objects - ///////////////////////////////////////////////////// - */ - - List mEntities = null; - - List mNotations = null; - - /* - ///////////////////////////////////////////////////// - // Constuctors - ///////////////////////////////////////////////////// - */ - - public WDTD(Location loc, String rootName, - String sysId, String pubId, String intSubset, - DTDSubset dtdSubset) - { - super(loc, rootName, sysId, pubId, intSubset, dtdSubset); - mSubset = dtdSubset; - } - - public WDTD(Location loc, String rootName, - String sysId, String pubId, String intSubset) - { - this(loc, rootName, sysId, pubId, intSubset, null); - } - - /** - * Constructor used when only partial information is available... - */ - public WDTD(Location loc, String rootName, String intSubset) - { - this(loc, rootName, null, null, intSubset, null); - } - - public WDTD(Location loc, String fullText) - { - super(loc, fullText); - mSubset = null; - } - - /* - ///////////////////////////////////////////////////// - // Accessors - ///////////////////////////////////////////////////// - */ - - public List getEntities() - { - if (mEntities == null && (mSubset != null)) { - /* Better make a copy, so that caller can not modify list - * DTD has, which may be shared (since DTD subset instances - * are cached and reused) - */ - mEntities = new ArrayList(mSubset.getGeneralEntityList()); - } - return mEntities; - } - - public List getNotations() { - if (mNotations == null && (mSubset != null)) { - mNotations = new ArrayList(mSubset.getNotationList()); - } - return mNotations; - } -} diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/evt/WEntityDeclaration.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/evt/WEntityDeclaration.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/evt/WEntityDeclaration.java 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/evt/WEntityDeclaration.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,109 +0,0 @@ -package com.ctc.wstx.evt; - -import java.io.IOException; -import java.io.Writer; - -import javax.xml.stream.Location; -import javax.xml.stream.XMLStreamException; -import javax.xml.stream.events.EntityDeclaration; - -import org.codehaus.stax2.XMLStreamWriter2; -import org.codehaus.stax2.ri.evt.BaseEventImpl; - -import com.ctc.wstx.ent.EntityDecl; -import com.ctc.wstx.exc.WstxIOException; - -/** - * Simple implementation of StAX entity declaration events; for the - * most just wraps a {@link EntityDecl} instance. - */ -public abstract class WEntityDeclaration - extends BaseEventImpl - implements EntityDeclaration -{ - public WEntityDeclaration(Location loc) - { - super(loc); - } - - public abstract String getBaseURI(); - - public abstract String getName(); - - public abstract String getNotationName(); - - public abstract String getPublicId(); - - public abstract String getReplacementText(); - - public abstract String getSystemId(); - - /* - /////////////////////////////////////////// - // Implementation of abstract base methods - /////////////////////////////////////////// - */ - - public int getEventType() { - return ENTITY_DECLARATION; - } - - public abstract void writeEnc(Writer w) throws IOException; - - public void writeAsEncodedUnicode(Writer w) - throws XMLStreamException - { - try { - writeEnc(w); - } catch (IOException ie) { - throw new WstxIOException(ie); - } - } - - /** - * This method does not make much sense for this event type -- the reason - * being that the entity declarations can only be written as part of - * a DTD (internal or external subset), not separately. Can basically - * choose to either skip silently (output nothing), or throw an - * exception. - */ - public void writeUsing(XMLStreamWriter2 w) throws XMLStreamException - { - /* Fail silently, or throw an exception? Let's do latter; at least - * then we'll get useful (?) bug reports! - */ - throw new XMLStreamException("Can not write entity declarations using an XMLStreamWriter"); - } - - /* - /////////////////////////////////////////// - // Standard method impl: note, copied - // from Stax2 RI "EntityDeclarationEventImpl" - /////////////////////////////////////////// - */ - - public boolean equals(Object o) - { - if (o == this) return true; - if (o == null) return false; - - if (!(o instanceof EntityDeclaration)) return false; - - EntityDeclaration other = (EntityDeclaration) o; - return stringsWithNullsEqual(getName(), other.getName()) - && stringsWithNullsEqual(getBaseURI(), other.getBaseURI()) - && stringsWithNullsEqual(getNotationName(), other.getNotationName()) - && stringsWithNullsEqual(getPublicId(), other.getPublicId()) - && stringsWithNullsEqual(getReplacementText(), other.getReplacementText()) - && stringsWithNullsEqual(getSystemId(), other.getSystemId()) - ; - } - - public int hashCode() - { - /* Hmmh. Could try using most of the data, but really, name - * should be enough for most use cases - */ - return getName().hashCode(); - } -} diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/evt/WEntityReference.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/evt/WEntityReference.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/evt/WEntityReference.java 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/evt/WEntityReference.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,44 +0,0 @@ -package com.ctc.wstx.evt; - -import javax.xml.stream.Location; -import javax.xml.stream.events.EntityReference; -import javax.xml.stream.events.EntityDeclaration; - -import org.codehaus.stax2.ri.evt.EntityReferenceEventImpl; - -/** - * We need a slightly specialized version to support concept of - * undeclared entities, which can be used in (non-default, non-standard) - * mode where undeclared entities are allowed to be handled. - */ -public class WEntityReference - extends EntityReferenceEventImpl - implements EntityReference -{ - final String mName; - - public WEntityReference(Location loc, EntityDeclaration decl) - { - super(loc, decl); - mName = null; - } - - /** - * This constructor gets called for undeclared/defined entities: we will - * still know the name (from the reference), but not how it's defined - * (since it is not defined). - */ - public WEntityReference(Location loc, String name) - { - super(loc, (EntityDeclaration) null); - mName = name; - } - - public String getName() - { - if (mName != null) { - return mName; - } - return super.getName(); - } -} diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/evt/WNotationDeclaration.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/evt/WNotationDeclaration.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/evt/WNotationDeclaration.java 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/evt/WNotationDeclaration.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,43 +0,0 @@ -package com.ctc.wstx.evt; - -import java.net.URL; - -import javax.xml.stream.Location; - -import org.codehaus.stax2.ri.evt.NotationDeclarationEventImpl; - -/** - * Woodstox implementation of {@link org.codehaus.stax2.evt.NotationDeclaration2}. - * The only required addition is that of passing in the Base URI. - * - * @author Tatu Saloranta - * - * @since 4.0.0 - */ -public class WNotationDeclaration - extends NotationDeclarationEventImpl -{ - /** - * Base URL that can be used to resolve the notation reference if - * necessary. - */ - final URL _baseURL; - - public WNotationDeclaration(Location loc, - String name, String pubId, String sysId, - URL baseURL) - { - super(loc, name, pubId, sysId); - _baseURL = baseURL; - } - - //@Override - public String getBaseURI() - { - if (_baseURL == null) { - return super.getBaseURI(); - } - return _baseURL.toExternalForm(); - } -} - diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/evt/WstxEventReader.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/evt/WstxEventReader.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/evt/WstxEventReader.java 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/evt/WstxEventReader.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,84 +0,0 @@ -/* Woodstox XML processor - * - * Copyright (c) 2004- Tatu Saloranta, tatu.saloranta@iki.fi - * - * Licensed under the License specified in the file LICENSE which is - * included with the source code. - * You may not use this file except in compliance with the License. - * - * 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 com.ctc.wstx.evt; - -import javax.xml.stream.*; -import javax.xml.stream.util.XMLEventAllocator; - -import org.codehaus.stax2.XMLStreamReader2; -import org.codehaus.stax2.ri.Stax2EventReaderImpl; - -import com.ctc.wstx.cfg.ErrorConsts; -import com.ctc.wstx.exc.WstxParsingException; - -/** - * Woodstox version, based on generic Stax reference implementation - * baseline of {@link Stax2EventReaderImpl}. - */ -public class WstxEventReader - extends Stax2EventReaderImpl -{ - public WstxEventReader(XMLEventAllocator a, XMLStreamReader2 r) - { - super(a, r); - } - - /* - ////////////////////////////////////////////////////// - // Impl of abstract methods - ////////////////////////////////////////////////////// - */ - - protected String getErrorDesc(int errorType, int currEvent) - { - // Defaults are mostly fine, except we can easily add event type desc - switch (errorType) { - case ERR_GETELEMTEXT_NOT_START_ELEM: - return ErrorConsts.ERR_STATE_NOT_STELEM+", got "+ErrorConsts.tokenTypeDesc(currEvent); - case ERR_GETELEMTEXT_NON_TEXT_EVENT: - return "Expected a text token, got "+ErrorConsts.tokenTypeDesc(currEvent); - case ERR_NEXTTAG_NON_WS_TEXT: - return "Only all-whitespace CHARACTERS/CDATA (or SPACE) allowed for nextTag(), got "+ErrorConsts.tokenTypeDesc(currEvent); - case ERR_NEXTTAG_WRONG_TYPE: - return "Got "+ErrorConsts.tokenTypeDesc(currEvent)+", instead of START_ELEMENT, END_ELEMENT or SPACE"; - } - return null; - } - - public boolean isPropertySupported(String name) - { - return ((XMLStreamReader2)getStreamReader()).isPropertySupported(name); - } - - public boolean setProperty(String name, Object value) - { - return ((XMLStreamReader2)getStreamReader()).setProperty(name, value); - } - - - /* - ////////////////////////////////////////////////////// - // Overrides - ////////////////////////////////////////////////////// - */ - - // @Override - protected void reportProblem(String msg, Location loc) - throws XMLStreamException - { - throw new WstxParsingException(msg, loc); - } -} diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/exc/package.html libwoodstox-java-5.1.0/src/java/com/ctc/wstx/exc/package.html --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/exc/package.html 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/exc/package.html 1970-01-01 00:00:00.000000000 +0000 @@ -1,4 +0,0 @@ - -Package that contains all exceptions Woodstox readers and writers throw. -Exceptions generally extend {@link javax.xml.stream.XMLStreamException}. - diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/exc/WstxEOFException.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/exc/WstxEOFException.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/exc/WstxEOFException.java 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/exc/WstxEOFException.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,17 +0,0 @@ -package com.ctc.wstx.exc; - -import javax.xml.stream.Location; - -/** - * Exception thrown during parsing, if an unexpected EOF is encountered. - * Location usually signals starting position of current Node. - */ -public class WstxEOFException - extends WstxParsingException -{ - private static final long serialVersionUID = 1L; - - public WstxEOFException(String msg, Location loc) { - super(msg, loc); - } -} diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/exc/WstxException.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/exc/WstxException.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/exc/WstxException.java 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/exc/WstxException.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,104 +0,0 @@ -/* Woodstox XML processor - * - * Copyright (c) 2004 Tatu Saloranta, tatu.saloranta@iki.fi - * - * Licensed under the License specified in file LICENSE, included with - * the source code. - * You may not use this file except in compliance with the License. - * - * 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 com.ctc.wstx.exc; - -import javax.xml.stream.Location; -import javax.xml.stream.XMLStreamException; - -import com.ctc.wstx.util.ExceptionUtil; -import com.ctc.wstx.util.StringUtil; - -/** - * Base class for all implementatations of {@link XMLStreamException} - * Wstx uses. - */ -public class WstxException - extends XMLStreamException -{ - private static final long serialVersionUID = 1L; - - /** - * D'oh. Super-class munges and hides the message, have to duplicate here - */ - final protected String mMsg; - - public WstxException(String msg) { - super(msg); - mMsg = msg; - } - - public WstxException(Throwable th) { - super(th.getMessage(), th); - mMsg = th.getMessage(); - - // 13-Aug-2004, TSa: Better make sure root cause is set... - ExceptionUtil.setInitCause(this, th); - } - - public WstxException(String msg, Location loc) { - super(msg, loc); - mMsg = msg; - } - - public WstxException(String msg, Location loc, Throwable th) { - super(msg, loc, th); - mMsg = msg; - - // 13-Aug-2004, TSa: Better make sure root cause is set... - ExceptionUtil.setInitCause(this, th); - } - - /** - * Method is overridden for two main reasons: first, default method - * does not display public/system id information, even if it exists, and - * second, default implementation can not handle nested Location - * information. - */ - public String getMessage() - { - String locMsg = getLocationDesc(); - /* Better not use super's message if we do have location information, - * since parent's message contains (part of) Location - * info; something we can regenerate better... - */ - if (locMsg == null) { - return super.getMessage(); - } - StringBuffer sb = new StringBuffer(mMsg.length() + locMsg.length() + 20); - sb.append(mMsg); - StringUtil.appendLF(sb); - sb.append(" at "); - sb.append(locMsg); - return sb.toString(); - } - - public String toString() - { - return getClass().getName()+": "+getMessage(); - } - - /* - //////////////////////////////////////////////////////// - // Internal methods: - //////////////////////////////////////////////////////// - */ - - protected String getLocationDesc() - { - Location loc = getLocation(); - return (loc == null) ? null : loc.toString(); - } -} diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/exc/WstxIOException.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/exc/WstxIOException.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/exc/WstxIOException.java 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/exc/WstxIOException.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,21 +0,0 @@ -package com.ctc.wstx.exc; - -import java.io.IOException; - -/** - * Simple wrapper for {@link IOException}s; needed when StAX does not expose - * underlying I/O exceptions via its methods. - */ -public class WstxIOException - extends WstxException -{ - private static final long serialVersionUID = 1L; - - public WstxIOException(IOException ie) { - super(ie); - } - - public WstxIOException(String msg) { - super(msg); - } -} diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/exc/WstxLazyException.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/exc/WstxLazyException.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/exc/WstxLazyException.java 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/exc/WstxLazyException.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,61 +0,0 @@ -/* Woodstox XML processor - * - * Copyright (c) 2004 Tatu Saloranta, tatu.saloranta@iki.fi - * - * Licensed under the License specified in file LICENSE, included with - * the source code. - * You may not use this file except in compliance with the License. - * - * 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 com.ctc.wstx.exc; - -import javax.xml.stream.XMLStreamException; - -import com.ctc.wstx.util.ExceptionUtil; - -/** - * Alternative exception class Woodstox code uses when it is not allowed - * to throw an instance of {@link XMLStreamException}; this generally - * happens when doing lazy parsing. - */ -public class WstxLazyException - extends RuntimeException -{ - private static final long serialVersionUID = 1L; - - final XMLStreamException mOrig; - - public WstxLazyException(XMLStreamException origEx) - { - super(origEx.getMessage()); - mOrig = origEx; - // Let's additionally to set source message - ExceptionUtil.setInitCause(this, origEx); - } - - public static void throwLazily(XMLStreamException ex) - throws WstxLazyException - { - throw new WstxLazyException(ex); - } - - /** - * Need to override this, to be able to dynamically construct and - * display the location information... - */ - public String getMessage() - { - return "["+getClass().getName()+"] "+mOrig.getMessage(); - } - - public String toString() - { - return "["+getClass().getName()+"] "+mOrig.toString(); - } -} diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/exc/WstxOutputException.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/exc/WstxOutputException.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/exc/WstxOutputException.java 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/exc/WstxOutputException.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,16 +0,0 @@ -package com.ctc.wstx.exc; - -/** - * Exception class used for notifying about well-formedness errors that - * writers would create. Such exceptions are thrown when strict output - * validation is enabled. - */ -public class WstxOutputException - extends WstxException -{ - private static final long serialVersionUID = 1L; - - public WstxOutputException(String msg) { - super(msg); - } -} diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/exc/WstxParsingException.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/exc/WstxParsingException.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/exc/WstxParsingException.java 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/exc/WstxParsingException.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,19 +0,0 @@ -package com.ctc.wstx.exc; - -import javax.xml.stream.Location; - -/** - * Intermediate base class for reporting actual Wstx parsing problems. - */ -public class WstxParsingException - extends WstxException -{ - private static final long serialVersionUID = 1L; - - public WstxParsingException(String msg, Location loc) { - super(msg, loc); - } - - // !!! 13-Sep-2008, tatus: Only needed for DOMWrapping reader, for now - public WstxParsingException(String msg) { super(msg); } -} diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/exc/WstxUnexpectedCharException.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/exc/WstxUnexpectedCharException.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/exc/WstxUnexpectedCharException.java 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/exc/WstxUnexpectedCharException.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,26 +0,0 @@ -package com.ctc.wstx.exc; - -import javax.xml.stream.Location; - -/** - * Generic exception type that indicates that tokenizer/parser encountered - * unexpected (but not necessarily invalid per se) character; character that - * is not legal in current context. Could happen, for example, if white space - * was missing between attribute value and name of next attribute. - */ -public class WstxUnexpectedCharException - extends WstxParsingException -{ - private static final long serialVersionUID = 1L; - - final char mChar; - - public WstxUnexpectedCharException(String msg, Location loc, char c) { - super(msg, loc); - mChar = c; - } - - public char getChar() { - return mChar; - } -} diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/exc/WstxValidationException.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/exc/WstxValidationException.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/exc/WstxValidationException.java 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/exc/WstxValidationException.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,101 +0,0 @@ -package com.ctc.wstx.exc; - -import javax.xml.stream.Location; -import javax.xml.stream.XMLStreamException; - -import org.codehaus.stax2.validation.XMLValidationException; -import org.codehaus.stax2.validation.XMLValidationProblem; - -import com.ctc.wstx.util.StringUtil; - -/** - * Specific exception thrown when document has validation (DTD, W3C Schema) - * errors; things that are not well-formedness problems. - *

- * The current implementation does not add much beyond basic - * {@link XMLValidationException}, except for fixing some problems that - * underlying {@link XMLStreamException} has. - *

- * Note that some of the code is shared with {@link WstxException}. Unfortunately - * it is not possible to extend it, however, since it extends basic - * {@link XMLStreamException}, not {@link XMLValidationException}. - *

- * One more thing to note: unlike some other exception classes, these - * exceptions do not have chained root causes. That's why no special - * handling is necessary for setting the root cause in backwards compatible - * way. - */ -public class WstxValidationException - extends XMLValidationException -{ - private static final long serialVersionUID = 1L; - - protected WstxValidationException(XMLValidationProblem cause, String msg) - { - super(cause, msg); - } - - protected WstxValidationException(XMLValidationProblem cause, String msg, - Location loc) - { - super(cause, msg, loc); - } - - public static WstxValidationException create(XMLValidationProblem cause) - { - // Should always get a message - Location loc = cause.getLocation(); - if (loc == null) { - return new WstxValidationException(cause, cause.getMessage()); - } - return new WstxValidationException(cause, cause.getMessage(), loc); - } - - /* - ///////////////////////////////////////////////////////// - // Overridden methods from XMLStreamException - ///////////////////////////////////////////////////////// - */ - - /** - * Method is overridden for two main reasons: first, default method - * does not display public/system id information, even if it exists, and - * second, default implementation can not handle nested Location - * information. - */ - public String getMessage() - { - String locMsg = getLocationDesc(); - /* Better not use super's message if we do have location information, - * since parent's message contains (part of) Location - * info; something we can regenerate better... - */ - if (locMsg == null) { - return super.getMessage(); - } - String msg = getValidationProblem().getMessage(); - StringBuffer sb = new StringBuffer(msg.length() + locMsg.length() + 20); - sb.append(msg); - StringUtil.appendLF(sb); - sb.append(" at "); - sb.append(locMsg); - return sb.toString(); - } - - public String toString() - { - return getClass().getName()+": "+getMessage(); - } - - /* - //////////////////////////////////////////////////////// - // Internal methods: - //////////////////////////////////////////////////////// - */ - - protected String getLocationDesc() - { - Location loc = getLocation(); - return (loc == null) ? null : loc.toString(); - } -} diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/io/AsciiReader.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/io/AsciiReader.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/io/AsciiReader.java 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/io/AsciiReader.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,136 +0,0 @@ -/* Woodstox XML processor - * - * Copyright (c) 2004 Tatu Saloranta, tatu.saloranta@iki.fi - * - * Licensed under the License specified in file LICENSE, included with - * the source code. - * You may not use this file except in compliance with the License. - * - * 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 com.ctc.wstx.io; - -import java.io.*; - -import com.ctc.wstx.api.ReaderConfig; -import com.ctc.wstx.cfg.XmlConsts; - -/** - * Optimized Reader that reads ascii content from an input stream. - * In addition to doing (hopefully) optimal conversion, it can also take - * array of "pre-read" (leftover) bytes; this is necessary when preliminary - * stream/reader is trying to figure out XML encoding. - */ -public final class AsciiReader - extends BaseReader -{ - boolean mXml11 = false; - - /** - * Total read character count; used for error reporting purposes - * (note: byte count is the same, due to fixed one-byte-per char mapping) - */ - int mCharCount = 0; - - /* - //////////////////////////////////////// - // Life-cycle - //////////////////////////////////////// - */ - - public AsciiReader(ReaderConfig cfg, InputStream in, byte[] buf, int ptr, int len, - boolean recycleBuffer) - { - super(cfg, in, buf, ptr, len, recycleBuffer); - } - - public void setXmlCompliancy(int xmlVersion) - { - mXml11 = (xmlVersion == XmlConsts.XML_V_11); - } - - /* - //////////////////////////////////////// - // Public API - //////////////////////////////////////// - */ - - public int read(char[] cbuf, int start, int len) - throws IOException - { - // Let's first ensure there's enough room... - if (start < 0 || (start+len) > cbuf.length) { - reportBounds(cbuf, start, len); - } - // Already EOF? - if (mByteBuffer == null) { - return -1; - } - if (len < 1) { - return 0; - } - - // Need to load more data? - int avail = mByteBufferEnd - mBytePtr; - if (avail <= 0) { - mCharCount += mByteBufferEnd; - // Let's always try to read full buffers, actually... - int count = readBytes(); - if (count <= 0) { - if (count == 0) { - reportStrangeStream(); - } - /* Let's actually then free the buffer right away; shouldn't - * yet close the underlying stream though? - */ - freeBuffers(); // to help GC? - return -1; - } - avail = count; - } - - // K, have at least one byte == char, good enough: - - if (len > avail) { - len = avail; - } - int i = mBytePtr; - int last = i + len; - - for (; i < last; ) { - char c = (char) mByteBuffer[i++]; - if (c >= CHAR_DEL) { - if (c > CHAR_DEL) { - reportInvalidAscii(c); - } else { - if (mXml11) { - int pos = mCharCount + mBytePtr; - reportInvalidXml11(c, pos, pos); - } - } - } - cbuf[start++] = c; - } - - mBytePtr = last; - return len; - } - - /* - //////////////////////////////////////// - // Internal methods - //////////////////////////////////////// - */ - - private void reportInvalidAscii(char c) - throws IOException - { - throw new CharConversionException("Invalid ascii byte; value above 7-bit ascii range ("+((int) c)+"; at pos #"+(mCharCount + mBytePtr)+")"); - } -} - diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/io/BaseInputSource.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/io/BaseInputSource.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/io/BaseInputSource.java 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/io/BaseInputSource.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,173 +0,0 @@ -package com.ctc.wstx.io; - -import java.io.IOException; -import java.net.URL; - -import javax.xml.stream.XMLStreamException; - -/** - * Abstract base class that implements shared functionality that all current - * {@link WstxInputSource} implementations Woodstox includes need. - */ -public abstract class BaseInputSource - extends WstxInputSource -{ - final String mPublicId; - - final String mSystemId; - - /** - * URL that points to original source of input, if known; null if not - * known (source constructed with just a stream or reader). Used for - * resolving references from the input that's read from this source. - * Can be overridden by reader; done if P_BASE_URL is changed on - * stream reader for which this input source is the currently - * active input source. - */ - protected URL mSource; - - /** - * Input buffer this input source uses, if any. - */ - protected char[] mBuffer; - - /** - * Length of the buffer, if buffer used - */ - protected int mInputLast; - - /* - //////////////////////////////////////////////////////////////// - // Saved location information; active information is directly - // handled by Reader, and then saved to input source when switching - // to a nested input source. - //////////////////////////////////////////////////////////////// - */ - - /** - * Number of characters read from the current input source prior to - * the current buffer - */ - long mSavedInputProcessed = 0; - - int mSavedInputRow = 1; - int mSavedInputRowStart = 0; - - int mSavedInputPtr = 0; - - /* - //////////////////////////////////////////////////////////////// - // Some simple lazy-loading/reusing support... - //////////////////////////////////////////////////////////////// - */ - - transient WstxInputLocation mParentLocation = null; - - /* - //////////////////////////////////////////////////////////////// - // Life-cycle - //////////////////////////////////////////////////////////////// - */ - protected BaseInputSource(WstxInputSource parent, String fromEntity, - String publicId, String systemId, URL src) - { - super(parent, fromEntity); - mSystemId = systemId; - mPublicId = publicId; - mSource = src; - } - - public void overrideSource(URL src) - { - mSource = src; - } - - public abstract boolean fromInternalEntity(); - - public URL getSource() { - return mSource; - } - - public String getPublicId() { - return mPublicId; - } - - public String getSystemId() { - return mSystemId; - } - - protected abstract void doInitInputLocation(WstxInputData reader); - - public abstract int readInto(WstxInputData reader) - throws IOException, XMLStreamException; - - public abstract boolean readMore(WstxInputData reader, int minAmount) - throws IOException, XMLStreamException; - - public void saveContext(WstxInputData reader) - { - // First actual input data - mSavedInputPtr = reader.mInputPtr; - - // then location - mSavedInputProcessed = reader.mCurrInputProcessed; - mSavedInputRow = reader.mCurrInputRow; - mSavedInputRowStart = reader.mCurrInputRowStart; - } - - public void restoreContext(WstxInputData reader) - { - reader.mInputBuffer = mBuffer; - reader.mInputEnd = mInputLast; - reader.mInputPtr = mSavedInputPtr; - - // then location - reader.mCurrInputProcessed = mSavedInputProcessed; - reader.mCurrInputRow = mSavedInputRow; - reader.mCurrInputRowStart = mSavedInputRowStart; - } - - public abstract void close() throws IOException; - - /* - ////////////////////////////////////////////////////////// - // Methods for accessing location information - ////////////////////////////////////////////////////////// - */ - - /** - * This method only gets called by the 'child' input source (for example, - * contents of an expanded entity), to get the enclosing context location. - */ - protected final WstxInputLocation getLocation() - { - // Note: columns are 1-based, need to add 1. - return getLocation(mSavedInputProcessed + mSavedInputPtr - 1L, - mSavedInputRow, - mSavedInputPtr - mSavedInputRowStart + 1); - } - - public final WstxInputLocation getLocation(long total, int row, int col) - { - WstxInputLocation pl; - - if (mParent == null) { - pl = null; - } else { - /* 13-Apr-2005, TSa: We can actually reuse parent location, since - * it can not change during lifetime of this child context... - */ - pl = mParentLocation; - if (pl == null) { - mParentLocation = pl = mParent.getLocation(); - } - pl = mParent.getLocation(); - } - /* !!! 15-Apr-2005, TSa: This will cause overflow for total count, - * but since StAX 1.0 API doesn't have any way to deal with that, - * let's just let that be... - */ - return new WstxInputLocation(pl, getPublicId(), getSystemId(), - (int) total, row, col); - } -} diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/io/BaseReader.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/io/BaseReader.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/io/BaseReader.java 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/io/BaseReader.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,227 +0,0 @@ -package com.ctc.wstx.io; - -import java.io.*; - -import com.ctc.wstx.api.ReaderConfig; - -/** - * Simple basic class for optimized Readers Woodstox has; implements - * "cookie-cutter" methods that are used by all actual implementations. - */ -abstract class BaseReader - extends Reader -{ - protected final static char NULL_CHAR = (char) 0; - protected final static char NULL_BYTE = (byte) 0; - - /** - * In xml 1.1, NEL (0x85) behaves much the way \n does (can - * be follow \r as part of the linefeed - */ - protected final static char CONVERT_NEL_TO = '\n'; - - /** - * In xml 1.1, LSEP bit like \n, or \r. Need to choose one as the - * result. Let's use \n, for simplicity - */ - protected final static char CONVERT_LSEP_TO = '\n'; - - /** - * DEL character is both the last ascii char, and illegal in xml 1.1. - */ - final static char CHAR_DEL = (char) 127; - - protected final ReaderConfig mConfig; - - private InputStream mIn; - - protected byte[] mByteBuffer; - - /** - * Pointer to the next available byte (if any), iff less than - * mByteBufferEnd - */ - protected int mBytePtr; - - /** - * Pointed to the end marker, that is, position one after the last - * valid available byte. - */ - protected int mByteBufferEnd; - - /** - * Flag that indicates whether the read buffer is to be recycled - * when Reader is closed or not. - */ - private final boolean mRecycleBuffer; - - /* - //////////////////////////////////////// - // Life-cycle - //////////////////////////////////////// - */ - - protected BaseReader(ReaderConfig cfg, InputStream in, byte[] buf, int ptr, int len, - boolean recycleBuffer) - { - mConfig = cfg; - mIn = in; - mByteBuffer = buf; - mBytePtr = ptr; - mByteBufferEnd = len; - mRecycleBuffer = recycleBuffer; - } - - /* - //////////////////////////////////////// - // Configuration - //////////////////////////////////////// - */ - - /** - * Method that can be called to indicate the xml conformance used - * when reading content using this reader. Some of the character - * validity checks need to be done at reader level, and sometimes - * they depend on xml level (for example, xml 1.1 has new linefeeds - * and both more and less restricted characters). - */ - public abstract void setXmlCompliancy(int xmlVersion); - - /** - * Method that can be used to see if we can actually modify the - * underlying buffer. This is the case if we are managing the buffer, - * but not if it was just given to us. - */ - protected final boolean canModifyBuffer() - { - return mRecycleBuffer; - } - - /* - //////////////////////////////////////// - // Reader API - //////////////////////////////////////// - */ - - public void close() - throws IOException - { - InputStream in = mIn; - - if (in != null) { - mIn = null; - freeBuffers(); - in.close(); - } - } - - char[] mTmpBuf = null; - - /** - * Although this method is implemented by the base class, AND it should - * never be called by Woodstox code, let's still implement it bit more - * efficiently just in case - */ - public int read() - throws IOException - { - if (mTmpBuf == null) { - mTmpBuf = new char[1]; - } - if (read(mTmpBuf, 0, 1) < 1) { - return -1; - } - return mTmpBuf[0]; - } - - /* - //////////////////////////////////////// - // Internal/package methods: - //////////////////////////////////////// - */ - - protected final InputStream getStream() { return mIn; } - - /** - * Method for reading as many bytes from the underlying stream as possible - * (that fit in the buffer), to the beginning of the buffer. - */ - protected final int readBytes() - throws IOException - { - mBytePtr = 0; - mByteBufferEnd = 0; - if (mIn != null) { - int count = mIn.read(mByteBuffer, 0, mByteBuffer.length); - if (count > 0) { - mByteBufferEnd = count; - } - return count; - } - return -1; - } - - /** - * Method for reading as many bytes from the underlying stream as possible - * (that fit in the buffer considering offset), to the specified offset. - * - * @return Number of bytes read, if any; -1 to indicate none available - * (that is, end of input) - */ - protected final int readBytesAt(int offset) - throws IOException - { - // shouldn't modify mBytePtr, assumed to be 'offset' - if (mIn != null) { - int count = mIn.read(mByteBuffer, offset, mByteBuffer.length - offset); - if (count > 0) { - mByteBufferEnd += count; - } - return count; - } - return -1; - } - - /** - * This method should be called along with (or instead of) normal - * close. After calling this method, no further reads should be tried. - * Method will try to recycle read buffers (if any). - */ - public final void freeBuffers() - { - /* 11-Apr-2005, TSa: Ok, we can release the buffer now, to be - * recycled by the next stream reader instantiated by this - * thread (if any). - */ - if (mRecycleBuffer) { - byte[] buf = mByteBuffer; - if (buf != null) { - mByteBuffer = null; - if (mConfig != null) { - mConfig.freeFullBBuffer(buf); - } - } - } - } - - protected void reportBounds(char[] cbuf, int start, int len) - throws IOException - { - throw new ArrayIndexOutOfBoundsException("read(buf,"+start+","+len+"), cbuf["+cbuf.length+"]"); - } - - protected void reportStrangeStream() - throws IOException - { - throw new IOException("Strange I/O stream, returned 0 bytes on read"); - } - - protected void reportInvalidXml11(int value, int bytePos, int charPos) - throws IOException - { - throw new CharConversionException("Invalid character 0x" - +Integer.toHexString(value) - +", can only be included in xml 1.1 using character entities (at char #"+charPos+", byte #"+bytePos+")"); - } -} - diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/io/BranchingReaderSource.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/io/BranchingReaderSource.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/io/BranchingReaderSource.java 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/io/BranchingReaderSource.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,158 +0,0 @@ -package com.ctc.wstx.io; - -import java.io.IOException; -import java.io.Reader; -import java.net.URL; - -import javax.xml.stream.XMLStreamException; - -import com.ctc.wstx.api.ReaderConfig; -import com.ctc.wstx.util.TextBuffer; - -/** - * Specialized input source that can "branch" input it reads; essentially - * both giving out read data AND also writing it out to a Writer. - *

- * Currently this Reader is only used as the main-level Reader, to allow for - * branching of internal DTD subset to a text buffer if necessary. - */ -public final class BranchingReaderSource - extends ReaderSource -{ - - // // // Branching information - - TextBuffer mBranchBuffer = null; - - int mBranchStartOffset = 0; - - boolean mConvertLFs = false; - - /** - * Flag that indicates that last char from previous buffer was - * '\r', and that following '\n' (if there is one) needs to be - * ignored. - */ - boolean mGotCR = false; - - public BranchingReaderSource(ReaderConfig cfg, String pubId, String sysId, URL src, - Reader r, boolean realClose) - { - /* null -> no parent, - * null -> not from explicit entity (no id/name) - */ - super(cfg, null, null, pubId, sysId, src, r, realClose); - } - - public int readInto(WstxInputData reader) - throws IOException, XMLStreamException - { - // Need to flush out branched content? - if (mBranchBuffer != null) { - if (mInputLast > mBranchStartOffset) { - appendBranched(mBranchStartOffset, mInputLast); - } - mBranchStartOffset = 0; - } - return super.readInto(reader); - } - - public boolean readMore(WstxInputData reader, int minAmount) - throws IOException, XMLStreamException - { - // Existing data to output to branch? - if (mBranchBuffer != null) { - int ptr = reader.mInputPtr; - int currAmount = mInputLast - ptr; - if (currAmount > 0) { - if (ptr > mBranchStartOffset) { - appendBranched(mBranchStartOffset, ptr); - } - mBranchStartOffset = 0; - } - } - return super.readMore(reader, minAmount); - } - - /* - ////////////////////////////////////////////////// - // Branching methods; used mostly to make a copy - // of parsed internal subsets. - ////////////////////////////////////////////////// - */ - - public void startBranch(TextBuffer tb, int startOffset, - boolean convertLFs) - { - mBranchBuffer = tb; - mBranchStartOffset = startOffset; - mConvertLFs = convertLFs; - mGotCR = false; - } - - /** - * Currently this input source does not implement branching - */ - public void endBranch(int endOffset) - { - if (mBranchBuffer != null) { - if (endOffset > mBranchStartOffset) { - appendBranched(mBranchStartOffset, endOffset); - } - // Let's also make sure no branching is done from this point on: - mBranchBuffer = null; - } - } - - /* - ////////////////////////////////////////////////// - // Internal methods - ////////////////////////////////////////////////// - */ - - private void appendBranched(int startOffset, int pastEnd) { - // Main tricky thing here is just replacing of linefeeds... - if (mConvertLFs) { - char[] inBuf = mBuffer; - /* this will also unshare() and ensure there's room for at - * least one more char - */ - char[] outBuf = mBranchBuffer.getCurrentSegment(); - int outPtr = mBranchBuffer.getCurrentSegmentSize(); - - // Pending \n to skip? - if (mGotCR) { - if (inBuf[startOffset] == '\n') { - ++startOffset; - } - } - - while (startOffset < pastEnd) { - char c = inBuf[startOffset++]; - if (c == '\r') { - if (startOffset < pastEnd) { - if (inBuf[startOffset] == '\n') { - ++startOffset; - } - } else { - mGotCR = true; - } - c = '\n'; - } - - // Ok, let's add char to output: - outBuf[outPtr++] = c; - - // Need more room? - if (outPtr >= outBuf.length) { - outBuf = mBranchBuffer.finishCurrentSegment(); - outPtr = 0; - } - } - - mBranchBuffer.setCurrentLength(outPtr); - } else { - mBranchBuffer.append(mBuffer, startOffset, pastEnd-startOffset); - } - } -} diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/io/BufferRecycler.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/io/BufferRecycler.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/io/BufferRecycler.java 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/io/BufferRecycler.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,108 +0,0 @@ -package com.ctc.wstx.io; - -/** - * This is a small utility class, whose main functionality is to allow - * simple reuse of raw byte/char buffers. It is usually used through - * ThreadLocal member of the owning class pointing to - * instance of this class through a SoftReference. The - * end result is a low-overhead GC-cleanable recycling: hopefully - * ideal for use by stream readers. - *

- * Regarding implementation: the key design goal is simplicity; and to - * that end, different types of buffers are handled separately. While - * code may look inelegant as a result (wouldn't it be neat to just - * have generic char[]/byte[] buffer accessors?), benefit is that - * no data structures are needed, just simple references. As long - * as usage pattern is well known (which it is, for stream readers) - * this should be highly optimal and robust implementation. - */ -public final class BufferRecycler -{ - private char[] mSmallCBuffer = null; // temp buffers - private char[] mMediumCBuffer = null; // text collector - private char[] mFullCBuffer = null; // for actual parsing buffer - - private byte[] mFullBBuffer = null; - - public BufferRecycler() { } - - // // // Char buffers: - - // // Small buffers, for temporary parsing - - public char[] getSmallCBuffer(int minSize) - { - char[] result = null; - if (mSmallCBuffer != null && mSmallCBuffer.length >= minSize) { - result = mSmallCBuffer; - mSmallCBuffer = null; - } -//System.err.println("DEBUG: Alloc CSmall: "+result); - return result; - } - - public void returnSmallCBuffer(char[] buffer) - { -//System.err.println("DEBUG: Return CSmall ("+buffer.length+"): "+buffer); - mSmallCBuffer = buffer; - } - - // // Medium buffers, for text output collection - - public char[] getMediumCBuffer(int minSize) - { - char[] result = null; - if (mMediumCBuffer != null && mMediumCBuffer.length >= minSize) { - result = mMediumCBuffer; - mMediumCBuffer = null; - } -//System.err.println("DEBUG: Alloc CMed: "+result); - return result; - } - - public void returnMediumCBuffer(char[] buffer) - { - mMediumCBuffer = buffer; -//System.err.println("DEBUG: Return CMed ("+buffer.length+"): "+buffer); - } - - // // Full buffers, for parser buffering - - public char[] getFullCBuffer(int minSize) - { - char[] result = null; - if (mFullCBuffer != null && mFullCBuffer.length >= minSize) { - result = mFullCBuffer; - mFullCBuffer = null; - } -//System.err.println("DEBUG: Alloc CFull: "+result); - return result; - } - - public void returnFullCBuffer(char[] buffer) - { - mFullCBuffer = buffer; -//System.err.println("DEBUG: Return CFull ("+buffer.length+"): "+buffer); - } - - // // // Byte buffers: - - // // Full byte buffers, for byte->char conversion (Readers) - - public byte[] getFullBBuffer(int minSize) - { - byte[] result = null; - if (mFullBBuffer != null && mFullBBuffer.length >= minSize) { - result = mFullBBuffer; - mFullBBuffer = null; - } -//System.err.println("DEBUG: Alloc BFull: "+result); - return result; - } - - public void returnFullBBuffer(byte[] buffer) - { - mFullBBuffer = buffer; -//System.err.println("DEBUG: Return BFull ("+buffer.length+"): "+buffer); - } -} diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/io/CharArraySource.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/io/CharArraySource.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/io/CharArraySource.java 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/io/CharArraySource.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,107 +0,0 @@ -package com.ctc.wstx.io; - -import javax.xml.stream.Location; - -import java.net.URL; - -/** - * Input source that reads input from a static char array, usually used - * when expanding internal entities. It can also be used if the input - * given is a raw character array. - */ -public final class CharArraySource - extends BaseInputSource -{ - int mOffset; - - // // // Plus, location offset info: - - final Location mContentStart; - - CharArraySource(WstxInputSource parent, String fromEntity, - char[] chars, int offset, int len, - Location loc, URL src) - { - super(parent, fromEntity, loc.getPublicId(), loc.getSystemId(), src); - mBuffer = chars; - mOffset = offset; - mInputLast = offset + len; - mContentStart = loc; - } - - /** - * This is a hard-coded assumption, but yes, for now this source is - * only created from internal entities. - */ - public boolean fromInternalEntity() { - return true; - } - - /** - * Unlike with reader source, we won't start from beginning of a file, - * but usually from somewhere in the middle... - */ - protected void doInitInputLocation(WstxInputData reader) - { - reader.mCurrInputProcessed = mContentStart.getCharacterOffset(); - reader.mCurrInputRow = mContentStart.getLineNumber(); - /* 13-Apr-2005, TSa: Since column offsets reported by Location - * objects are 1-based, but internally we use 0-based counts, - * need to offset this start by 1 to begin with. - */ - reader.mCurrInputRowStart = -mContentStart.getColumnNumber() + 1; - } - - public int readInto(WstxInputData reader) - { - /* Shouldn't really try to read after closing, but it may be easier - * for caller not to have to keep track of open/close state... - */ - if (mBuffer == null) { - return -1; - } - - /* In general, there are only 2 states; either this has been - * read or not. Offset is used as the marker; plus, in case - * somehow we get a dummy char source (length of 0), it'll - * also prevent any reading. - */ - int len = mInputLast - mOffset; - if (len < 1) { - return -1; - } - reader.mInputBuffer = mBuffer; - reader.mInputPtr = mOffset; - reader.mInputEnd = mInputLast; - // Also, need to note the fact we're done - mOffset = mInputLast; - return len; - } - - public boolean readMore(WstxInputData reader, int minAmount) - { - /* Only case where this may work is if we haven't yet been - * read from at all. And that should mean caller also has no - * existing input... - */ - if (reader.mInputPtr >= reader.mInputEnd) { - int len = mInputLast - mOffset; - if (len >= minAmount) { - return (readInto(reader) > 0); - } - } - return false; - } - - public void close() - { - /* Let's help GC a bit, in case there might be back references - * to this Object from somewhere... - */ - mBuffer = null; - } - - public void closeCompletely() { - close(); - } -} diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/io/CharsetNames.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/io/CharsetNames.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/io/CharsetNames.java 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/io/CharsetNames.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,294 +0,0 @@ -package com.ctc.wstx.io; - -import java.io.OutputStreamWriter; -import java.io.Writer; - -import com.ctc.wstx.util.StringUtil; - -/** - * Simple utility class that normalizes given character input character - * set names into canonical (within Woodstox, anyways) names. - */ -public final class CharsetNames -{ - /* - ////////////////////////////////////////////////// - // Canonical names used internally - ////////////////////////////////////////////////// - */ - - // // // Unicode variants: - - public final static String CS_US_ASCII = "US-ASCII"; - public final static String CS_UTF8 = "UTF-8"; - - /** - * This constants is intentionally vague, so that some other information - * will be needed to determine the endianness. - */ - public final static String CS_UTF16 = "UTF-16"; - - public final static String CS_UTF16BE = "UTF-16BE"; - public final static String CS_UTF16LE = "UTF-16LE"; - public final static String CS_UTF32 = "UTF-32"; - public final static String CS_UTF32BE = "UTF-32BE"; - public final static String CS_UTF32LE = "UTF-32LE"; - - // // // 8-bit ISO encodings: - - public final static String CS_ISO_LATIN1 = "ISO-8859-1"; - - // // // Japanese non-unicode encodings: - - public final static String CS_SHIFT_JIS = "Shift_JIS"; - - // // // Other oddities: - - /* There are tons of EBCDIC varieties, with similar but - * non-identical names. As a result, we can not give or use - * just a single canonical name for general use. - * However, we can choose a single one to use for bootstrapping; - * that is, for parsing xml declaration to know the "real" - * EBCDIC variant. - */ - public final static String CS_EBCDIC_SUBSET = "IBM037"; - - /* - ////////////////////////////////////////////////// - // Utility methods - ////////////////////////////////////////////////// - */ - - public static String normalize(String csName) - { - if (csName == null || csName.length() < 3) { - return csName; - } - - /* Canonical charset names here are from IANA recommendation: - * http://www.iana.org/assignments/character-sets - * but comparison is done loosely (case-insensitive, ignoring - * spacing, underscore vs. hyphen etc) to try to make detection - * as extensive as possible. - */ - - /* But first bit of pre-filtering: it seems like 'cs' prefix - * is applicable to pretty much all actual encodings (as per - * IANA recommendations; csASCII, csUcs4 etc). So, let's just - * strip out the prefix if so - */ - boolean gotCsPrefix = false; - char c = csName.charAt(0); - if (c == 'c' || c == 'C'){ - char d = csName.charAt(1); - if (d == 's' || d == 'S') { - csName = csName.substring(2); - c = csName.charAt(0); - gotCsPrefix = true; - } - } - - switch (c) { - case 'a': - case 'A': - if (StringUtil.equalEncodings(csName, "ASCII")) { - return CS_US_ASCII; - } - break; - - case 'c': - case 'C': - /* Tons of variants: let's assume 'cpXXX' is an EBCDIC - * variant, and should read 'IBMXXX' - */ - if (StringUtil.encodingStartsWith(csName, "cp")) { - return "IBM" + StringUtil.trimEncoding(csName, true).substring(2); - } - // Hmmh. There are boatloads of these... but what to do with them? - if (StringUtil.encodingStartsWith(csName, "cs")) { - // Well, "csIBMxx" means EBCDIC of "IBMxx" - if (StringUtil.encodingStartsWith(csName, "csIBM")) { - // So let's just peel off "cs" prefix: - return StringUtil.trimEncoding(csName, true).substring(2); - } - // !!! TBI - } - break; - - case 'e': - case 'E': - if (csName.startsWith("EBCDIC-CP-") || - csName.startsWith("ebcdic-cp-")) { - // EBCDIC, but which variety? - // Let's trim out prefix to make comparison easier: - String type = StringUtil.trimEncoding(csName, true).substring(8); - // Note: these are suggested encodings of Xerces - if (type.equals("US") || type.equals("CA") - || type.equals("WT") || type.equals("NL")) { - return "IBM037"; - } - if (type.equals("DK") || type.equals("NO")) { // Denmark, Norway - return "IBM277"; - } - if (type.equals("FI") || type.equals("SE")) { // Finland, Sweden - return "IBM278"; - } - if (type.equals("ROECE") || type.equals("YU")) { - return "IBM870"; - } - if (type.equals("IT")) return "IBM280"; - if (type.equals("ES")) return "IBM284"; - if (type.equals("GB")) return "IBM285"; - if (type.equals("FR")) return "IBM297"; - if (type.equals("AR1")) return "IBM420"; - if (type.equals("AR2")) return "IBM918"; - if (type.equals("HE")) return "IBM424"; - if (type.equals("CH")) return "IBM500"; - if (type.equals("IS")) return "IBM871"; - - // Dunno... let's just default to 037? - return CS_EBCDIC_SUBSET; - } - break; - case 'i': - case 'I': - if (StringUtil.equalEncodings(csName, "ISO-8859-1") - || StringUtil.equalEncodings(csName, "ISO-Latin1")) { - return CS_ISO_LATIN1; - } - if (StringUtil.encodingStartsWith(csName, "ISO-10646")) { - /* Hmmh. There are boatloads of alternatives here, it - * seems (see http://www.iana.org/assignments/character-sets - * for details) - */ - int ix = csName.indexOf("10646"); - String suffix = csName.substring(ix+5); - if (StringUtil.equalEncodings(suffix, "UCS-Basic")) { - return CS_US_ASCII; - } - if (StringUtil.equalEncodings(suffix, "Unicode-Latin1")) { - return CS_ISO_LATIN1; - } - if (StringUtil.equalEncodings(suffix, "UCS-2")) { - return CS_UTF16; // endianness? - } - if (StringUtil.equalEncodings(suffix, "UCS-4")) { - return CS_UTF32; // endianness? - } - if (StringUtil.equalEncodings(suffix, "UTF-1")) { - // "Universal Transfer Format (1), this is the multibyte encoding, that subsets ASCII-7"??? - return CS_US_ASCII; - } - if (StringUtil.equalEncodings(suffix, "J-1")) { - // Name: ISO-10646-J-1, Source: ISO 10646 Japanese, see RFC 1815. - // ... so what does that really mean? let's consider it ascii - return CS_US_ASCII; - } - if (StringUtil.equalEncodings(suffix, "US-ASCII")) { - return CS_US_ASCII; - } - } else if (StringUtil.encodingStartsWith(csName, "IBM")) { - // EBCDIC of some kind... what (if anything) to do? - // ... for now, return as is - return csName; - } - break; - case 'j': - case 'J': - if (StringUtil.equalEncodings(csName, "JIS_Encoding")) { - return CS_SHIFT_JIS; - } - break; - case 's': - case 'S': - if (StringUtil.equalEncodings(csName, "Shift_JIS")) { - return CS_SHIFT_JIS; - } - break; - case 'u': - case 'U': - if (csName.length() < 2) { // sanity check - break; - } - switch (csName.charAt(1)) { - case 'c': - case 'C': - if (StringUtil.equalEncodings(csName, "UCS-2")) { - return CS_UTF16; - } - if (StringUtil.equalEncodings(csName, "UCS-4")) { - return CS_UTF32; - } - break; - case 'n': // csUnicodeXxx, - case 'N': - if (gotCsPrefix) { - if (StringUtil.equalEncodings(csName, "Unicode")) { - return CS_UTF16; // need BOM - } - if (StringUtil.equalEncodings(csName, "UnicodeAscii")) { - return CS_ISO_LATIN1; - } - if (StringUtil.equalEncodings(csName, "UnicodeAscii")) { - return CS_US_ASCII; - } - } - break; - case 's': - case 'S': - if (StringUtil.equalEncodings(csName, "US-ASCII")) { - return CS_US_ASCII; - } - break; - case 't': - case 'T': - if (StringUtil.equalEncodings(csName, "UTF-8")) { - return CS_UTF8; - } - if (StringUtil.equalEncodings(csName, "UTF-16BE")) { - return CS_UTF16BE; - } - if (StringUtil.equalEncodings(csName, "UTF-16LE")) { - return CS_UTF16LE; - } - if (StringUtil.equalEncodings(csName, "UTF-16")) { - return CS_UTF16; - } - if (StringUtil.equalEncodings(csName, "UTF-32BE")) { - return CS_UTF32BE; - } - if (StringUtil.equalEncodings(csName, "UTF-32LE")) { - return CS_UTF32LE; - } - if (StringUtil.equalEncodings(csName, "UTF-32")) { - return CS_UTF32; - } - if (StringUtil.equalEncodings(csName, "UTF")) { - // 21-Jan-2006, TSa: ??? What is this to do... ? - return CS_UTF16; - } - } - break; - } - - return csName; - } - - /** - * Because of legacy encodings used by earlier JDK versions, we - * need to be careful when accessing encoding names via JDK - * classes. - */ - public static String findEncodingFor(Writer w) - { - if (w instanceof OutputStreamWriter) { - String enc = ((OutputStreamWriter) w).getEncoding(); - /* [WSTX-146]: It is important that we normalize this, since - * older JDKs return legacy encoding names ("UTF8" instead of - * canonical "UTF-8") - */ - return normalize(enc); - } - return null; - } -} diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/io/CompletelyCloseable.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/io/CompletelyCloseable.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/io/CompletelyCloseable.java 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/io/CompletelyCloseable.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,8 +0,0 @@ -package com.ctc.wstx.io; - -import java.io.IOException; - -public interface CompletelyCloseable -{ - public void closeCompletely() throws IOException; -} diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/io/DefaultInputResolver.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/io/DefaultInputResolver.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/io/DefaultInputResolver.java 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/io/DefaultInputResolver.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,323 +0,0 @@ -package com.ctc.wstx.io; - -import java.io.*; -import java.net.URL; - -import javax.xml.stream.XMLResolver; -import javax.xml.stream.XMLStreamException; -import javax.xml.transform.Source; -import javax.xml.transform.stream.StreamSource; - -import com.ctc.wstx.api.ReaderConfig; -import com.ctc.wstx.cfg.XmlConsts; -import com.ctc.wstx.util.URLUtil; - -/** - * Static utility class that implements the entity (external DTD subset, - * external parsed entities) resolution logics. - */ -public final class DefaultInputResolver -{ - /* - //////////////////////////// - // Life-cycle - //////////////////////////// - */ - - private DefaultInputResolver() { } - - /* - //////////////////////////// - // Public API - //////////////////////////// - */ - - /** - * Basic external resource resolver implementation; usable both with - * DTD and entity resolution. - * - * @param parent Input source that contains reference to be expanded. - * @param pathCtxt Reference context to use for resolving path, if - * known. If null, reference context of the parent will - * be used; and if that is null (which is possible), the - * current working directory will be assumed. - * @param entityName Name/id of the entity being expanded, if this is an - * entity expansion; null otherwise (for example, when resolving external - * subset). - * @param publicId Public identifier of the resource, if known; null/empty - * otherwise. Default implementation just ignores the identifier. - * @param systemId System identifier of the resource. Although interface - * allows null/empty, default implementation considers this an error. - * @param xmlVersion Xml version as declared by the main parsed - * document. Currently only relevant for checking that XML 1.0 document - * does not include XML 1.1 external parsed entities. - * If XML_V_UNKNOWN, no checks will be done. - * @param customResolver Custom resolver to use first for resolution, - * if any (may be null). - * @param cfg Reader configuration object used by the parser that is - * resolving the entity - * - * @return Input source, if entity could be resolved; null if it could - * not be resolved. In latter case processor may use its own default - * resolution mechanism. - */ - public static WstxInputSource resolveEntity - (WstxInputSource parent, URL pathCtxt, String entityName, - String publicId, String systemId, - XMLResolver customResolver, ReaderConfig cfg, int xmlVersion) - throws IOException, XMLStreamException - { - if (pathCtxt == null) { - pathCtxt = parent.getSource(); - if (pathCtxt == null) { - pathCtxt = URLUtil.urlFromCurrentDir(); - } - } - - // Do we have a custom resolver that may be able to resolve it? - if (customResolver != null) { - Object source = customResolver.resolveEntity(publicId, systemId, pathCtxt.toExternalForm(), entityName); - if (source != null) { - return sourceFrom(parent, cfg, entityName, xmlVersion, source); - } - } - - // Have to have a system id, then... - if (systemId == null) { - throw new XMLStreamException("Can not resolve " - +((entityName == null) ? "[External DTD subset]" : ("entity '"+entityName+"'"))+" without a system id (public id '" - +publicId+"')"); - } - URL url = URLUtil.urlFromSystemId(systemId, pathCtxt); - return sourceFromURL(parent, cfg, entityName, xmlVersion, url, publicId); - } - - /** - * A very simple utility expansion method used generally when the - * only way to resolve an entity is via passed resolver; and where - * failing to resolve it is not fatal. - */ - public static WstxInputSource resolveEntityUsing - (WstxInputSource refCtxt, String entityName, - String publicId, String systemId, - XMLResolver resolver, ReaderConfig cfg, int xmlVersion) - throws IOException, XMLStreamException - { - URL ctxt = (refCtxt == null) ? null : refCtxt.getSource(); - if (ctxt == null) { - ctxt = URLUtil.urlFromCurrentDir(); - } - Object source = resolver.resolveEntity(publicId, systemId, ctxt.toExternalForm(), entityName); - return (source == null) ? null : sourceFrom(refCtxt, cfg, entityName, xmlVersion, source); - } - - /** - * Factory method that accepts various types of Objects, and tries to - * create a {@link WstxInputSource} from it. Currently it's only called - * to locate external DTD subsets, when overriding default DOCTYPE - * declarations; not for entity expansion or for locating the main - * document entity. - * - * @param parent Input source context active when resolving a new - * "sub-source"; usually the main document source. - * @param refName Name of the entity to be expanded, if any; may be - * null (and currently always is) - * @param o Object that should provide the new input source; non-type safe - */ - protected static WstxInputSource sourceFrom(WstxInputSource parent, - ReaderConfig cfg, String refName, - int xmlVersion, - Object o) - throws IllegalArgumentException, IOException, XMLStreamException - { - if (o instanceof Source) { - if (o instanceof StreamSource) { - return sourceFromSS(parent, cfg, refName, xmlVersion, (StreamSource) o); - } - /* !!! 05-Feb-2006, TSa: Could check if SAXSource actually has - * stream/reader available... ? - */ - throw new IllegalArgumentException("Can not use other Source objects than StreamSource: got "+o.getClass()); - } - if (o instanceof URL) { - return sourceFromURL(parent, cfg, refName, xmlVersion, (URL) o, null); - } - if (o instanceof InputStream) { - return sourceFromIS(parent, cfg, refName, xmlVersion, (InputStream) o, null, null); - } - if (o instanceof Reader) { - return sourceFromR(parent, cfg, refName, xmlVersion, (Reader) o, null, null); - } - if (o instanceof String) { - return sourceFromString(parent, cfg, refName, xmlVersion, (String) o); - } - if (o instanceof File) { - URL u = ((File) o).toURL(); - return sourceFromURL(parent, cfg, refName, xmlVersion, u, null); - } - - throw new IllegalArgumentException("Unrecognized input argument type for sourceFrom(): "+o.getClass()); - } - - public static Reader constructOptimizedReader(ReaderConfig cfg, InputStream in, boolean isXml11, String encoding) - throws XMLStreamException - { - /* 03-Jul-2005, TSa: Since Woodstox' implementations of specialized - * readers are faster than default JDK ones (at least for 1.4, UTF-8 - * reader is especially fast...), let's use them if possible - */ - /* 17-Feb-2006, TSa: These should actually go via InputBootstrapper, - * since BOM may need to be skipped; xml 1.0 vs. 1.1 should be - * checked, and so on. Given encoding could be just verified - * against suggested one. - */ - int inputBufLen = cfg.getInputBufferLength(); - String normEnc = CharsetNames.normalize(encoding); - BaseReader r; - - // All of these use real InputStream, and use recyclable buffer - boolean recycleBuffer = true; - if (normEnc == CharsetNames.CS_UTF8) { - r = new UTF8Reader(cfg, in, cfg.allocFullBBuffer(inputBufLen), 0, 0, recycleBuffer); - } else if (normEnc == CharsetNames.CS_ISO_LATIN1) { - r = new ISOLatinReader(cfg, in, cfg.allocFullBBuffer(inputBufLen), 0, 0, recycleBuffer); - } else if (normEnc == CharsetNames.CS_US_ASCII) { - r = new AsciiReader(cfg, in, cfg.allocFullBBuffer(inputBufLen), 0, 0, recycleBuffer); - } else if (normEnc.startsWith(CharsetNames.CS_UTF32)) { - boolean isBE = (normEnc == CharsetNames.CS_UTF32BE); - r = new UTF32Reader(cfg, in, cfg.allocFullBBuffer(inputBufLen), 0, 0, recycleBuffer, isBE); - } else { - try { - return new InputStreamReader(in, encoding); - } catch (UnsupportedEncodingException ex) { - throw new XMLStreamException("[unsupported encoding]: "+ex); - } - } - - if (isXml11) { // only need to set if we are xml 1.1 compliant (1.0 is the default) - r.setXmlCompliancy(XmlConsts.XML_V_11); - } - - return r; - } - - /* - //////////////////////////// - // Internal methods - //////////////////////////// - */ - - private static WstxInputSource sourceFromSS(WstxInputSource parent, ReaderConfig cfg, - String refName, int xmlVersion, - StreamSource ssrc) - throws IOException, XMLStreamException - { - InputBootstrapper bs; - Reader r = ssrc.getReader(); - String pubId = ssrc.getPublicId(); - String sysId = ssrc.getSystemId(); - URL ctxt = (parent == null) ? null : parent.getSource(); - URL url = (sysId == null || sysId.length() == 0) ? null - : URLUtil.urlFromSystemId(sysId, ctxt); - - if (r == null) { - InputStream in = ssrc.getInputStream(); - if (in == null) { // Need to try just resolving the system id then - if (url == null) { - throw new IllegalArgumentException("Can not create Stax reader for a StreamSource -- neither reader, input stream nor system id was set."); - } - in = URLUtil.inputStreamFromURL(url); - } - bs = StreamBootstrapper.getInstance(pubId, sysId, in); - } else { - bs = ReaderBootstrapper.getInstance(pubId, sysId, r, null); - } - - Reader r2 = bs.bootstrapInput(cfg, false, xmlVersion); - return InputSourceFactory.constructEntitySource - (cfg, parent, refName, bs, pubId, sysId, xmlVersion, - ((url == null) ? ctxt : url), r2); - } - - private static WstxInputSource sourceFromURL(WstxInputSource parent, ReaderConfig cfg, - String refName, int xmlVersion, - URL url, - String pubId) - throws IOException, XMLStreamException - { - /* And then create the input source. Note that by default URL's - * own input stream creation creates buffered reader -- for us - * that's useless and wasteful (adds one unnecessary level of - * caching, halving the speed due to copy operations needed), so - * let's avoid it. - */ - InputStream in = URLUtil.inputStreamFromURL(url); - String sysId = url.toExternalForm(); - StreamBootstrapper bs = StreamBootstrapper.getInstance(pubId, sysId, in); - Reader r = bs.bootstrapInput(cfg, false, xmlVersion); - return InputSourceFactory.constructEntitySource - (cfg, parent, refName, bs, pubId, sysId, xmlVersion, url, r); - } - - /** - * We have multiple ways to look at what would it mean to get a String - * as the resolved result. The most straight-forward is to consider - * it literal replacement (with possible embedded entities), so let's - * use that (alternative would be to consider it to be a reference - * like URL -- those need to be returned as appropriate objects - * instead). - *

- * Note: public to give access for unit tests that need it... - */ - public static WstxInputSource sourceFromString(WstxInputSource parent, ReaderConfig cfg, - String refName, int xmlVersion, - String refContent) - throws IOException, XMLStreamException - { - /* Last null -> no app-provided encoding (doesn't matter for non- - * main-level handling) - */ - return sourceFromR(parent, cfg, refName, xmlVersion, - new StringReader(refContent), - null, refName); - } - - private static WstxInputSource sourceFromIS(WstxInputSource parent, - ReaderConfig cfg, - String refName, int xmlVersion, - InputStream is, - String pubId, String sysId) - throws IOException, XMLStreamException - { - StreamBootstrapper bs = StreamBootstrapper.getInstance(pubId, sysId, is); - Reader r = bs.bootstrapInput(cfg, false, xmlVersion); - URL ctxt = parent.getSource(); - - // If we got a real sys id, we do know the source... - if (sysId != null && sysId.length() > 0) { - ctxt = URLUtil.urlFromSystemId(sysId, ctxt); - } - return InputSourceFactory.constructEntitySource - (cfg, parent, refName, bs, pubId, sysId, xmlVersion, ctxt, r); - } - - private static WstxInputSource sourceFromR(WstxInputSource parent, ReaderConfig cfg, - String refName, int xmlVersion, - Reader r, - String pubId, String sysId) - throws IOException, XMLStreamException - { - /* Last null -> no app-provided encoding (doesn't matter for non- - * main-level handling) - */ - ReaderBootstrapper rbs = ReaderBootstrapper.getInstance(pubId, sysId, r, null); - // null -> no xml reporter... should have one? - Reader r2 = rbs.bootstrapInput(cfg, false, xmlVersion); - URL ctxt = (parent == null) ? null : parent.getSource(); - if (sysId != null && sysId.length() > 0) { - ctxt = URLUtil.urlFromSystemId(sysId, ctxt); - } - return InputSourceFactory.constructEntitySource - (cfg, parent, refName, rbs, pubId, sysId, xmlVersion, ctxt, r2); - } -} diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/io/EBCDICCodec.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/io/EBCDICCodec.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/io/EBCDICCodec.java 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/io/EBCDICCodec.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,322 +0,0 @@ -/* Woodstox XML processor - * - * Copyright (c) 2004 Tatu Saloranta, tatu.saloranta@iki.fi - * - * Licensed under the License specified in file LICENSE, included with - * the source code. - * You may not use this file except in compliance with the License. - * - * 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 com.ctc.wstx.io; - -/** - * This is a container class for EBCDIC code page(s) that we need - * to properly bootstrap EBCDIC encoded xml documents. - */ -public final class EBCDICCodec -{ - final static int[] sCodePage037; - static { - /* First, let's fill these in as per: - * - * http://www.unicode.org/Public/MAPPINGS/VENDORS/MICSFT/EBCDIC/CP037.TXT - */ - int[] ch = new int[256]; - ch[0] = 0x0000; - ch[0x01] = 0x0001; - ch[0x02] = 0x0002; - ch[0x03] = 0x0003; - ch[0x04] = 0x009C; - ch[0x05] = 0x0009; - ch[0x06] = 0x0086; - ch[0x07] = 0x007F; - ch[0x08] = 0x0097; - ch[0x09] = 0x008D; - ch[0x0A] = 0x008E; - ch[0x0B] = 0x000B; - ch[0x0C] = 0x000C; - ch[0x0D] = 0x000D; - ch[0x0E] = 0x000E; - ch[0x0F] = 0x000F; - ch[0x10] = 0x0010; - ch[0x11] = 0x0011; - ch[0x12] = 0x0012; - ch[0x13] = 0x0013; - ch[0x14] = 0x009D; - ch[0x15] = 0x0085; - ch[0x16] = 0x0008; - ch[0x17] = 0x0087; - ch[0x18] = 0x0018; - ch[0x19] = 0x0019; - ch[0x1A] = 0x0092; - ch[0x1B] = 0x008F; - ch[0x1C] = 0x001C; - ch[0x1D] = 0x001D; - ch[0x1E] = 0x001E; - ch[0x1F] = 0x001F; - ch[0x20] = 0x0080; - ch[0x21] = 0x0081; - ch[0x22] = 0x0082; - ch[0x23] = 0x0083; - ch[0x24] = 0x0084; - ch[0x25] = 0x000A; - ch[0x26] = 0x0017; - ch[0x27] = 0x001B; - ch[0x28] = 0x0088; - ch[0x29] = 0x0089; - ch[0x2A] = 0x008A; - ch[0x2B] = 0x008B; - ch[0x2C] = 0x008C; - ch[0x2D] = 0x0005; - ch[0x2E] = 0x0006; - ch[0x2F] = 0x0007; - ch[0x30] = 0x0090; - ch[0x31] = 0x0091; - ch[0x32] = 0x0016; - ch[0x33] = 0x0093; - ch[0x34] = 0x0094; - ch[0x35] = 0x0095; - ch[0x36] = 0x0096; - ch[0x37] = 0x0004; - ch[0x38] = 0x0098; - ch[0x39] = 0x0099; - ch[0x3A] = 0x009A; - ch[0x3B] = 0x009B; - ch[0x3C] = 0x0014; - ch[0x3D] = 0x0015; - ch[0x3E] = 0x009E; - ch[0x3F] = 0x001A; - ch[0x40] = 0x0020; - ch[0x41] = 0x00A0; - ch[0x42] = 0x00E2; - ch[0x43] = 0x00E4; - ch[0x44] = 0x00E0; - ch[0x45] = 0x00E1; - ch[0x46] = 0x00E3; - ch[0x47] = 0x00E5; - ch[0x48] = 0x00E7; - ch[0x49] = 0x00F1; - ch[0x4A] = 0x00A2; - ch[0x4B] = 0x002E; - ch[0x4C] = 0x003C; - ch[0x4D] = 0x0028; - ch[0x4E] = 0x002B; - ch[0x4F] = 0x007C; - ch[0x50] = 0x0026; - ch[0x51] = 0x00E9; - ch[0x52] = 0x00EA; - ch[0x53] = 0x00EB; - ch[0x54] = 0x00E8; - ch[0x55] = 0x00ED; - ch[0x56] = 0x00EE; - ch[0x57] = 0x00EF; - ch[0x58] = 0x00EC; - ch[0x59] = 0x00DF; - ch[0x5A] = 0x0021; - ch[0x5B] = 0x0024; - ch[0x5C] = 0x002A; - ch[0x5D] = 0x0029; - ch[0x5E] = 0x003B; - ch[0x5F] = 0x00AC; - ch[0x60] = 0x002D; - ch[0x61] = 0x002F; - ch[0x62] = 0x00C2; - ch[0x63] = 0x00C4; - ch[0x64] = 0x00C0; - ch[0x65] = 0x00C1; - ch[0x66] = 0x00C3; - ch[0x67] = 0x00C5; - ch[0x68] = 0x00C7; - ch[0x69] = 0x00D1; - ch[0x6A] = 0x00A6; - ch[0x6B] = 0x002C; - ch[0x6C] = 0x0025; - ch[0x6D] = 0x005F; - ch[0x6E] = 0x003E; - ch[0x6F] = 0x003F; - ch[0x70] = 0x00F8; - ch[0x71] = 0x00C9; - ch[0x72] = 0x00CA; - ch[0x73] = 0x00CB; - ch[0x74] = 0x00C8; - ch[0x75] = 0x00CD; - ch[0x76] = 0x00CE; - ch[0x77] = 0x00CF; - ch[0x78] = 0x00CC; - ch[0x79] = 0x0060; - ch[0x7A] = 0x003A; - ch[0x7B] = 0x0023; - ch[0x7C] = 0x0040; - ch[0x7D] = 0x0027; - ch[0x7E] = 0x003D; - ch[0x7F] = 0x0022; - - ch[0x80] = 0x00D8; - ch[0x81] = 0x0061; - ch[0x82] = 0x0062; - ch[0x83] = 0x0063; - ch[0x84] = 0x0064; - ch[0x85] = 0x0065; - ch[0x86] = 0x0066; - ch[0x87] = 0x0067; - ch[0x88] = 0x0068; - ch[0x89] = 0x0069; - ch[0x8A] = 0x00AB; - ch[0x8B] = 0x00BB; - ch[0x8C] = 0x00F0; - ch[0x8D] = 0x00FD; - ch[0x8E] = 0x00FE; - ch[0x8F] = 0x00B1; - ch[0x90] = 0x00B0; - ch[0x91] = 0x006A; - ch[0x92] = 0x006B; - ch[0x93] = 0x006C; - ch[0x94] = 0x006D; - ch[0x95] = 0x006E; - ch[0x96] = 0x006F; - ch[0x97] = 0x0070; - ch[0x98] = 0x0071; - ch[0x99] = 0x0072; - ch[0x9A] = 0x00AA; - ch[0x9B] = 0x00BA; - ch[0x9C] = 0x00E6; - ch[0x9D] = 0x00B8; - ch[0x9E] = 0x00C6; - ch[0x9F] = 0x00A4; - ch[0xA0] = 0x00B5; - ch[0xA1] = 0x007E; - ch[0xA2] = 0x0073; - ch[0xA3] = 0x0074; - ch[0xA4] = 0x0075; - ch[0xA5] = 0x0076; - ch[0xA6] = 0x0077; - ch[0xA7] = 0x0078; - ch[0xA8] = 0x0079; - ch[0xA9] = 0x007A; - ch[0xAA] = 0x00A1; - ch[0xAB] = 0x00BF; - ch[0xAC] = 0x00D0; - ch[0xAD] = 0x00DD; - ch[0xAE] = 0x00DE; - ch[0xAF] = 0x00AE; - ch[0xB0] = 0x005E; - ch[0xB1] = 0x00A3; - ch[0xB2] = 0x00A5; - ch[0xB3] = 0x00B7; - ch[0xB4] = 0x00A9; - ch[0xB5] = 0x00A7; - ch[0xB6] = 0x00B6; - ch[0xB7] = 0x00BC; - ch[0xB8] = 0x00BD; - ch[0xB9] = 0x00BE; - ch[0xBA] = 0x005B; - ch[0xBB] = 0x005D; - ch[0xBC] = 0x00AF; - ch[0xBD] = 0x00A8; - ch[0xBE] = 0x00B4; - ch[0xBF] = 0x00D7; - ch[0xC0] = 0x007B; - ch[0xC1] = 0x0041; - ch[0xC2] = 0x0042; - ch[0xC3] = 0x0043; - ch[0xC4] = 0x0044; - ch[0xC5] = 0x0045; - ch[0xC6] = 0x0046; - ch[0xC7] = 0x0047; - ch[0xC8] = 0x0048; - ch[0xC9] = 0x0049; - ch[0xCA] = 0x00AD; - ch[0xCB] = 0x00F4; - ch[0xCC] = 0x00F6; - ch[0xCD] = 0x00F2; - ch[0xCE] = 0x00F3; - ch[0xCF] = 0x00F5; - ch[0xD0] = 0x007D; - ch[0xD1] = 0x004A; - ch[0xD2] = 0x004B; - ch[0xD3] = 0x004C; - ch[0xD4] = 0x004D; - ch[0xD5] = 0x004E; - ch[0xD6] = 0x004F; - ch[0xD7] = 0x0050; - ch[0xD8] = 0x0051; - ch[0xD9] = 0x0052; - ch[0xDA] = 0x00B9; - ch[0xDB] = 0x00FB; - ch[0xDC] = 0x00FC; - ch[0xDD] = 0x00F9; - ch[0xDE] = 0x00FA; - ch[0xDF] = 0x00FF; - ch[0xE0] = 0x005C; - ch[0xE1] = 0x00F7; - ch[0xE2] = 0x0053; - ch[0xE3] = 0x0054; - ch[0xE4] = 0x0055; - ch[0xE5] = 0x0056; - ch[0xE6] = 0x0057; - ch[0xE7] = 0x0058; - ch[0xE8] = 0x0059; - ch[0xE9] = 0x005A; - ch[0xEA] = 0x00B2; - ch[0xEB] = 0x00D4; - ch[0xEC] = 0x00D6; - ch[0xED] = 0x00D2; - ch[0xEE] = 0x00D3; - ch[0xEF] = 0x00D5; - ch[0xF0] = 0x0030; - ch[0xF1] = 0x0031; - ch[0xF2] = 0x0032; - ch[0xF3] = 0x0033; - ch[0xF4] = 0x0034; - ch[0xF5] = 0x0035; - ch[0xF6] = 0x0036; - ch[0xF7] = 0x0037; - ch[0xF8] = 0x0038; - ch[0xF9] = 0x0039; - ch[0xFA] = 0x00B3; - ch[0xFB] = 0x00DB; - ch[0xFC] = 0x00DC; - ch[0xFD] = 0x00D9; - ch[0xFE] = 0x00DA; - ch[0xFF] = 0x009F; - - /* And then massage it so we can catch problems with control - * chars same way as we'd do with, say, Latin1 input. - */ - for (int i = 0, len = ch.length; i < len; ++i) { - int c = ch[i]; - if (c >= 0x7F && c <= 0x9F) { - /* 21-Sep-2007, TSa: Hmmh. In a way, it should be dealt - * as per xml rules, and not allowed in xml declaration - * before encoding declaration. But that won't work well - * with real docs. Converting it earlier works better... - * so for now that seems the way it needs to be done. ;-/ - */ - if (c == 0x85) { - ch[i] = BaseReader.CONVERT_NEL_TO; - } else { - ch[i] = -c; - } - } - } - - sCodePage037 = ch; - } - - private EBCDICCodec() { } - - /** - * @return Code table for EBCDIC code page 037 (US, Canada etc) - */ - public static int[] getCp037Mapping() - { - return sCodePage037; - } -} - diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/io/InputBootstrapper.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/io/InputBootstrapper.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/io/InputBootstrapper.java 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/io/InputBootstrapper.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,529 +0,0 @@ -package com.ctc.wstx.io; - -import java.io.*; - -import javax.xml.stream.Location; -import javax.xml.stream.XMLStreamException; - -import com.ctc.wstx.api.ReaderConfig; -import com.ctc.wstx.cfg.ErrorConsts; -import com.ctc.wstx.cfg.XmlConsts; -import com.ctc.wstx.exc.*; - -/** - * Abstract base class that defines common API used with both stream and - * reader-based input sources. Class is responsible for opening the physical - * input source, figure out encoding (if necessary; only for streams), and - * then handle (optional) XML declaration. - */ -public abstract class InputBootstrapper -{ - /* - //////////////////////////////////////////////////////////// - // Shared string consts - //////////////////////////////////////////////////////////// - */ - - protected final static String ERR_XMLDECL_KW_VERSION = "; expected keyword '"+XmlConsts.XML_DECL_KW_VERSION+"'"; - protected final static String ERR_XMLDECL_KW_ENCODING = "; expected keyword '"+XmlConsts.XML_DECL_KW_ENCODING+"'"; - protected final static String ERR_XMLDECL_KW_STANDALONE = "; expected keyword '"+XmlConsts.XML_DECL_KW_STANDALONE+"'"; - - protected final static String ERR_XMLDECL_END_MARKER = "; expected \"?>\" end marker"; - - protected final static String ERR_XMLDECL_EXP_SPACE = "; expected a white space"; - protected final static String ERR_XMLDECL_EXP_EQ = "; expected '=' after "; - protected final static String ERR_XMLDECL_EXP_ATTRVAL = "; expected a quote character enclosing value for "; - - /* - //////////////////////////////////////////////////////////// - // Other consts - //////////////////////////////////////////////////////////// - */ - - public final static char CHAR_NULL = (char) 0; - public final static char CHAR_SPACE = (char) 0x0020; - - public final static char CHAR_NEL = (char) 0x0085; - - public final static byte CHAR_CR = '\r'; - public final static byte CHAR_LF = '\n'; - - public final static byte BYTE_NULL = (byte) 0; - - public final static byte BYTE_CR = (byte) '\r'; - public final static byte BYTE_LF = (byte) '\n'; - - /* - //////////////////////////////////////////////////////////// - // Input source info - //////////////////////////////////////////////////////////// - */ - - protected final String mPublicId; - - protected final String mSystemId; - - /* - //////////////////////////////////////////////////////////// - // Input location data (similar to one in WstxInputData) - //////////////////////////////////////////////////////////// - */ - - /** - * Current number of characters that were processed in previous blocks, - * before contents of current input buffer. - */ - protected int mInputProcessed = 0; - - /** - * Current row location of current point in input buffer, starting - * from 1 - */ - protected int mInputRow = 1; - - /** - * Current index of the first character of the current row in input - * buffer. Needed to calculate column position, if necessary; benefit - * of not having column itself is that this only has to be updated - * once per line. - */ - protected int mInputRowStart = 0; - - /* - //////////////////////////////////////// - // Info from XML declaration - //////////////////////////////////////// - */ - - //boolean mHadDeclaration = false; - - /** - * XML declaration from the input (1.0, 1.1 or 'unknown') - */ - int mDeclaredXmlVersion = XmlConsts.XML_V_UNKNOWN; - - /** - * Value of encoding pseudo-attribute from xml declaration, if - * one was found; null otherwise. - */ - String mFoundEncoding; - - String mStandalone; - - /** - * Flag that indicates whether input read from this input source - * needs to be xml 1.1 compliant or not; if not, xml 1.0 is assumed. - * State of this flag depends on parent context (if one existed), or if - * not, on xml declaration of this input source. - */ - boolean mXml11Handling = false; - - /* - //////////////////////////////////////// - // Temporary data - //////////////////////////////////////// - */ - - /** - * Need a short buffer to read in values of pseudo-attributes (version, - * encoding, standalone). Don't really need tons of space; just enough - * for the longest anticipated encoding id... and maybe few chars just - * in case (for additional white space that we ignore) - */ - final char[] mKeyword = new char[60]; - - /* - //////////////////////////////////////// - // Life-cycle - //////////////////////////////////////// - */ - - protected InputBootstrapper(String pubId, String sysId) - { - mPublicId = pubId; - mSystemId = sysId; - } - - protected void initFrom(InputBootstrapper src) - { - mInputProcessed = src.mInputProcessed; - mInputRow = src.mInputRow; - mInputRowStart = src.mInputRowStart; - mDeclaredXmlVersion = src.mDeclaredXmlVersion; - mFoundEncoding = src.mFoundEncoding; - mStandalone = src.mStandalone; - mXml11Handling = src.mXml11Handling; - } - - /* - //////////////////////////////////////// - // Public API - //////////////////////////////////////// - */ - - /** - * @param xmlVersion Optional xml version identifier of the main parsed - * document (if not bootstrapping the main document). - * Currently only relevant for checking that XML 1.0 document does not - * include XML 1.1 external parsed entities. - * If null, no checks will be done; when bootstrapping parsing of the - * main document, null should be passed for this argument. - */ - public abstract Reader bootstrapInput(ReaderConfig cfg, boolean mainDoc, - int xmlVersion) - throws IOException, XMLStreamException; - - // // // Source information: - - public String getPublicId() { return mPublicId; } - public String getSystemId() { return mSystemId; } - - // // // XML declaration data: - - public int getDeclaredVersion() - { - return mDeclaredXmlVersion; - } - - /** - * @return True, if the input bootstrapped declared that it conforms - * to xml 1.1 (independent of where it was included from) - */ - public boolean declaredXml11() { - return (mDeclaredXmlVersion == XmlConsts.XML_V_11); - } - - public String getStandalone() { - return mStandalone; - } - - /** - * @return Encoding declaration found from the xml declaration, if any; - * null if none. - */ - public String getDeclaredEncoding() { - return mFoundEncoding; - } - - // // // Location/position info: - - /** - * @return Total number of characters read from bootstrapped input - * (stream, reader) - */ - public abstract int getInputTotal(); - - public int getInputRow() { - return mInputRow; - } - - public abstract int getInputColumn(); - - - // // // Misc other info - - /** - * Actual character encoding used by the underlying input source; - * may have been passed by the application, or auto-detected - * by byte stream boot strapper (can not be determined from a - * Reader source). - * - * @return Input encoding in use, if it could be determined or was - * passed by the calling application - */ - public abstract String getInputEncoding(); - - /* - //////////////////////////////////////// - // Package methods, parsing - //////////////////////////////////////// - */ - - /** - * @param xmlVersion Optional xml version identifier of the main parsed - * document (if not bootstrapping the main document). - * Currently only relevant for checking that XML 1.0 document does not - * include XML 1.1 external parsed entities. - * If null, no checks will be done; when bootstrapping parsing of the - * main document, null should be passed for this argument. - */ - protected void readXmlDecl(boolean isMainDoc, int xmlVersion) - throws IOException, WstxException - { - int c = getNextAfterWs(false); - - // First, version pseudo-attribute: - - if (c != 'v') { // version info obligatory for main docs - if (isMainDoc) { - reportUnexpectedChar(c, ERR_XMLDECL_KW_VERSION); - } - } else { // ok, should be version - mDeclaredXmlVersion = readXmlVersion(); - c = getWsOrChar('?'); - } - - /* 17-Feb-2006, TSa: Whether we are to be xml 1.1 compliant or not - * depends on parent context, if any; and if not, on actual - * xml declaration. But in former case, it is illegal to include - * xml 1.1 declared entities from xml 1.0 context. - */ - boolean thisIs11 = (mDeclaredXmlVersion == XmlConsts.XML_V_11); - if (xmlVersion != XmlConsts.XML_V_UNKNOWN) { // happens when reading main doc - mXml11Handling = (XmlConsts.XML_V_11 == xmlVersion); - // Can not refer to xml 1.1 entities from 1.0 doc: - if (thisIs11 && !mXml11Handling) { - reportXmlProblem(ErrorConsts.ERR_XML_10_VS_11); - } - } else { - mXml11Handling = thisIs11; - } - - // Then, 'encoding' - if (c != 'e') { // obligatory for external entities - if (!isMainDoc) { - reportUnexpectedChar(c, ERR_XMLDECL_KW_ENCODING); - } - } else { - mFoundEncoding = readXmlEncoding(); - c = getWsOrChar('?'); - } - - // Then, 'standalone' (for main doc) - if (isMainDoc && c == 's') { - mStandalone = readXmlStandalone(); - c = getWsOrChar('?'); - } - - // And finally, need to have closing markers - - if (c != '?') { - reportUnexpectedChar(c, ERR_XMLDECL_END_MARKER); - } - c = getNext(); - if (c != '>') { - reportUnexpectedChar(c, ERR_XMLDECL_END_MARKER); - } - } - - /** - * @return Xml version declaration read - */ - private final int readXmlVersion() - throws IOException, WstxException - { - int c = checkKeyword(XmlConsts.XML_DECL_KW_VERSION); - if (c != CHAR_NULL) { - reportUnexpectedChar(c, XmlConsts.XML_DECL_KW_VERSION); - } - c = handleEq(XmlConsts.XML_DECL_KW_VERSION); - int len = readQuotedValue(mKeyword, c); - - if (len == 3) { - if (mKeyword[0] == '1' && mKeyword[1] == '.') { - c = mKeyword[2]; - if (c == '0') { - return XmlConsts.XML_V_10; - } - if (c == '1') { - return XmlConsts.XML_V_11; - } - } - } - - // Nope; error. -1 indicates run off... - String got; - - if (len < 0) { - got = "'"+new String(mKeyword)+"[..]'"; - } else if (len == 0) { - got = ""; - } else { - got = "'"+new String(mKeyword, 0, len)+"'"; - } - reportPseudoAttrProblem(XmlConsts.XML_DECL_KW_VERSION, got, - XmlConsts.XML_V_10_STR, XmlConsts.XML_V_11_STR); - return XmlConsts.XML_V_UNKNOWN; // never gets here, but compiler needs it - } - - private final String readXmlEncoding() - throws IOException, WstxException - { - int c = checkKeyword(XmlConsts.XML_DECL_KW_ENCODING); - if (c != CHAR_NULL) { - reportUnexpectedChar(c, XmlConsts.XML_DECL_KW_ENCODING); - } - c = handleEq(XmlConsts.XML_DECL_KW_ENCODING); - - int len = readQuotedValue(mKeyword, c); - - /* Hmmh. How about "too long" encodings? Maybe just truncate them, - * for now? - */ - if (len == 0) { // let's still detect missing value... - reportPseudoAttrProblem(XmlConsts.XML_DECL_KW_ENCODING, null, - null, null); - } - - if (len < 0) { // will be truncated... - return new String(mKeyword); - } - return new String(mKeyword, 0, len); - } - - private final String readXmlStandalone() - throws IOException, WstxException - { - int c = checkKeyword(XmlConsts.XML_DECL_KW_STANDALONE); - if (c != CHAR_NULL) { - reportUnexpectedChar(c, XmlConsts.XML_DECL_KW_STANDALONE); - } - c = handleEq(XmlConsts.XML_DECL_KW_STANDALONE); - int len = readQuotedValue(mKeyword, c); - - if (len == 2) { - if (mKeyword[0] == 'n' && mKeyword[1] == 'o') { - return XmlConsts.XML_SA_NO; - } - } else if (len == 3) { - if (mKeyword[0] == 'y' && mKeyword[1] == 'e' - && mKeyword[2] == 's') { - return XmlConsts.XML_SA_YES; - } - } - - // Nope; error. -1 indicates run off... - String got; - - if (len < 0) { - got = "'"+new String(mKeyword)+"[..]'"; - } else if (len == 0) { - got = ""; - } else { - got = "'"+new String(mKeyword, 0, len)+"'"; - } - - reportPseudoAttrProblem(XmlConsts.XML_DECL_KW_STANDALONE, got, - XmlConsts.XML_SA_YES, XmlConsts.XML_SA_NO); - return got; // never gets here, but compiler can't figure it out - } - - private final int handleEq(String attr) - throws IOException, WstxException - { - int c = getNextAfterWs(false); - if (c != '=') { - reportUnexpectedChar(c, ERR_XMLDECL_EXP_EQ+"'"+attr+"'"); - } - - c = getNextAfterWs(false); - if (c != '"' && c != '\'') { - reportUnexpectedChar(c, ERR_XMLDECL_EXP_ATTRVAL+"'"+attr+"'"); - } - return c; - } - - /** - * Method that should get next character, which has to be either specified - * character (usually end marker), OR, any character as long as there' - * at least one space character before it. - */ - private final int getWsOrChar(int ok) - throws IOException, WstxException - { - int c = getNext(); - if (c == ok) { - return c; - } - if (c > CHAR_SPACE) { - reportUnexpectedChar(c, "; expected either '"+((char) ok)+"' or white space"); - } - if (c == CHAR_LF || c == CHAR_CR) { - // Need to push it back to be processed properly - pushback(); - } - return getNextAfterWs(false); - } - - /* - //////////////////////////////////////////////////////// - // Abstract parsing methods for sub-classes to implement - //////////////////////////////////////////////////////// - */ - - protected abstract void pushback(); - - protected abstract int getNext() - throws IOException, WstxException; - - protected abstract int getNextAfterWs(boolean reqWs) - throws IOException, WstxException; - - /** - * @return First character that does not match expected, if any; - * CHAR_NULL if match succeeded - */ - protected abstract int checkKeyword(String exp) - throws IOException, WstxException; - - protected abstract int readQuotedValue(char[] kw, int quoteChar) - throws IOException, WstxException; - - protected abstract Location getLocation(); - - /* - //////////////////////////////////////////////////////// - // Package methods available to sub-classes: - //////////////////////////////////////////////////////// - */ - - protected void reportNull() - throws WstxException - { - throw new WstxException("Illegal null byte in input stream", - getLocation()); - } - - protected void reportXmlProblem(String msg) - throws WstxException - { - throw new WstxParsingException(msg, getLocation()); - } - - protected void reportUnexpectedChar(int i, String msg) - throws WstxException - { - char c = (char) i; - String excMsg; - - // WTF? JDK thinks null char is just fine as?! - if (Character.isISOControl(c)) { - excMsg = "Unexpected character (CTRL-CHAR, code "+i+")"+msg; - } else { - excMsg = "Unexpected character '"+c+"' (code "+i+")"+msg; - } - Location loc = getLocation(); - throw new WstxUnexpectedCharException(excMsg, loc, c); - } - - /* - //////////////////////////////////////// - // Other private methods: - //////////////////////////////////////// - */ - - private final void reportPseudoAttrProblem(String attrName, String got, - String expVal1, String expVal2) - throws WstxException - { - String expStr = (expVal1 == null) ? "" : - ("; expected \""+expVal1+"\" or \""+expVal2+"\""); - - if (got == null || got.length() == 0) { - throw new WstxParsingException("Missing XML pseudo-attribute '"+attrName+"' value"+expStr, - getLocation()); - } - throw new WstxParsingException("Invalid XML pseudo-attribute '"+attrName+"' value "+got+expStr, - getLocation()); - } -} diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/io/InputSourceFactory.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/io/InputSourceFactory.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/io/InputSourceFactory.java 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/io/InputSourceFactory.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,77 +0,0 @@ -package com.ctc.wstx.io; - -import java.io.Reader; -import java.net.URL; - -import javax.xml.stream.Location; - -import com.ctc.wstx.api.ReaderConfig; - -/** - * Factory class that creates instances of {@link WstxInputSource} to allow - * reading input from various sources. - */ -public final class InputSourceFactory -{ - //final static int DEFAULT_BUFFER_LENGTH = 4000; - - /** - * @param parent - * @param entityName Name of the entity expanded to create this input - * source: null when source created for the (main level) external - * DTD subset entity. - * @param xmlVersion Optional xml version identifier of the main parsed - * document. Currently only relevant for checking that XML 1.0 document - * does not include XML 1.1 external parsed entities. - * If unknown, no checks will be done. - */ - public static ReaderSource constructEntitySource - (ReaderConfig cfg, WstxInputSource parent, String entityName, InputBootstrapper bs, - String pubId, String sysId, int xmlVersion, - URL src, Reader r) - { - // true -> do close the underlying Reader at EOF - ReaderSource rs = new ReaderSource - (cfg, parent, entityName, pubId, sysId, src, r, true); - if (bs != null) { - rs.setInputOffsets(bs.getInputTotal(), bs.getInputRow(), - -bs.getInputColumn()); - } - return rs; - } - - /** - * Factory method used for creating the main-level document reader - * source. - */ - public static BranchingReaderSource constructDocumentSource - (ReaderConfig cfg, InputBootstrapper bs, String pubId, String sysId, URL src, - Reader r, boolean realClose) - { - /* To resolve [WSTX-50] need to ensure that P_BASE_URL overrides - * the defaults if/as necessary - */ - URL url = cfg.getBaseURL(); - if (url != null) { - src = url; - } - BranchingReaderSource rs = new BranchingReaderSource(cfg, pubId, sysId, src, r, realClose); - if (bs != null) { - rs.setInputOffsets(bs.getInputTotal(), bs.getInputRow(), - -bs.getInputColumn()); - } - return rs; - } - - /** - * Factory method usually used to expand internal parsed entities; in - * which case context remains mostly the same. - */ - public static WstxInputSource constructCharArraySource - (WstxInputSource parent, String fromEntity, - char[] text, int offset, int len, Location loc, URL src) - { - return new CharArraySource(parent, fromEntity, text, offset, len, - loc, src); - } -} diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/io/ISOLatinReader.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/io/ISOLatinReader.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/io/ISOLatinReader.java 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/io/ISOLatinReader.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,133 +0,0 @@ -/* Woodstox XML processor - * - * Copyright (c) 2004- Tatu Saloranta, tatu.saloranta@iki.fi - * - * Licensed under the License specified in file LICENSE, included with - * the source code. - * You may not use this file except in compliance with the License. - * - * 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 com.ctc.wstx.io; - -import java.io.*; - -import com.ctc.wstx.api.ReaderConfig; -import com.ctc.wstx.cfg.XmlConsts; - -/** - * Optimized Reader that reads ISO-Latin (aka ISO-8859-1) content from an - * input stream. - * In addition to doing (hopefully) optimal conversion, it can also take - * array of "pre-read" (leftover) bytes; this is necessary when preliminary - * stream/reader is trying to figure out XML encoding. - */ -public final class ISOLatinReader - extends BaseReader -{ - boolean mXml11 = false; - - /** - * Total read byte (and char) count; used for error reporting purposes - */ - int mByteCount = 0; - - /* - //////////////////////////////////////// - // Life-cycle - //////////////////////////////////////// - */ - - public ISOLatinReader(ReaderConfig cfg, InputStream in, byte[] buf, int ptr, int len, - boolean recycleBuffer) - { - super(cfg, in, buf, ptr, len, recycleBuffer); - } - - public void setXmlCompliancy(int xmlVersion) - { - mXml11 = (xmlVersion == XmlConsts.XML_V_11); - } - - /* - //////////////////////////////////////// - // Public API - //////////////////////////////////////// - */ - - public int read(char[] cbuf, int start, int len) - throws IOException - { - // Let's then ensure there's enough room... - if (start < 0 || (start+len) > cbuf.length) { - reportBounds(cbuf, start, len); - } - // Already EOF? - if (mByteBuffer == null) { - return -1; - } - if (len < 1) { // dummy call? - return 0; - } - - // Need to load more data? - int avail = mByteBufferEnd - mBytePtr; - if (avail <= 0) { - mByteCount += mByteBufferEnd; - // Let's always (try to) read full buffers - int count = readBytes(); - if (count <= 0) { - if (count == 0) { - reportStrangeStream(); - } - /* Let's actually then free the buffer right away; shouldn't - * yet close the underlying stream though? - */ - freeBuffers(); // to help GC? - return -1; - } - avail = count; - } - - /* K, have at least one byte == char, good enough; requiring more - * could block the calling thread too early - */ - - if (len > avail) { - len = avail; - } - int i = mBytePtr; - int last = i + len; - - if (mXml11) { - for (; i < last; ) { - char c = (char) (mByteBuffer[i++] & 0xFF); - if (c >= CHAR_DEL) { - if (c <= 0x9F) { - if (c == 0x85) { // NEL, let's convert? - c = CONVERT_NEL_TO; - } else if (c >= 0x7F) { // DEL, ctrl chars - int pos = mByteCount + i; - reportInvalidXml11(c, pos, pos); - } - } - } - cbuf[start++] = c; - - } - } else { - for (; i < last; ) { - cbuf[start++] = (char) (mByteBuffer[i++] & 0xFF); - } - } - - mBytePtr = last; - return len; - } -} - diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/io/MergedReader.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/io/MergedReader.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/io/MergedReader.java 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/io/MergedReader.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,155 +0,0 @@ -package com.ctc.wstx.io; - -import java.io.*; - -import com.ctc.wstx.api.ReaderConfig; - -/** - * Simple {@link Reader} implementation that is used to "unwind" some - * data previously read from a Reader; so that as long as some of - * that data remains, it's returned; but as long as it's read, we'll - * just use data from the underlying original Reader. - * This is similar to {@link java.io.PushbackReader}, but with this class - * there's only one implicit pushback, when instance is constructed; not - * general pushback buffer and methods to use it. - */ -public final class MergedReader - extends Reader -{ - final ReaderConfig mConfig; - - final Reader mIn; - - /** - * This buffer contains the partially read remains left over after - * bootstrapper has consumed xml declaration (if one found). - * It is generally recycled and can be returned after having been - * read. - */ - char[] mData; - - int mPtr; - - final int mEnd; - - public MergedReader(ReaderConfig cfg, Reader in, char[] buf, int start, int end) - { - mConfig = cfg; - mIn = in; - mData = buf; - mPtr = start; - mEnd = end; - // sanity check: should not pass empty buffer - if (buf != null && start >= end) { - throw new IllegalArgumentException("Trying to construct MergedReader with empty contents (start "+start+", end "+end+")"); - } - } - - public void close() - throws IOException - { - freeMergedBuffer(); - mIn.close(); - } - - public void mark(int readlimit) - throws IOException - { - if (mData == null) { - mIn.mark(readlimit); - } - } - - public boolean markSupported() - { - /* Only supports marks past the initial rewindable section... - */ - return (mData == null) && mIn.markSupported(); - } - - public int read() - throws IOException - { - if (mData != null) { - int c = mData[mPtr++] & 0xFF; - if (mPtr >= mEnd) { - freeMergedBuffer(); - } - return c; - } - return mIn.read(); - } - - public int read(char[] cbuf) - throws IOException - { - return read(cbuf, 0, cbuf.length); - } - - public int read(char[] cbuf, int off, int len) - throws IOException - { - if (mData != null) { - int avail = mEnd - mPtr; - if (len > avail) { - len = avail; - } - System.arraycopy(mData, mPtr, cbuf, off, len); - mPtr += len; - if (mPtr >= mEnd) { - freeMergedBuffer(); - } - return len; - } - - return mIn.read(cbuf, off, len); - } - - public boolean ready() - throws IOException - { - return (mData != null) || mIn.ready(); - } - - public void reset() - throws IOException - { - if (mData == null) { - mIn.reset(); - } - } - - public long skip(long n) - throws IOException - { - long count = 0L; - - if (mData != null) { - int amount = mEnd - mPtr; - - if (amount > n) { // all in pushed back segment? - mPtr += (int) n; - return amount; - } - freeMergedBuffer(); - count += amount; - n -= amount; - } - - if (n > 0) { - count += mIn.skip(n); - } - return count; - } - - private void freeMergedBuffer() - { - if (mData != null) { - char[] data = mData; - mData = null; - if (mConfig != null) { - mConfig.freeSmallCBuffer(data); - } - } - } -} diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/io/MergedStream.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/io/MergedStream.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/io/MergedStream.java 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/io/MergedStream.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,146 +0,0 @@ -package com.ctc.wstx.io; - -import java.io.*; - -import com.ctc.wstx.api.ReaderConfig; - -/** - * Simple {@link InputStream} implementation that is used to "unwind" some - * data previously read from an input stream; so that as long as some of - * that data remains, it's returned; but as long as it's read, we'll - * just use data from the underlying original stream. - * This is similar to {@link java.io.PushbackInputStream}, but here there's - * only one implicit pushback, when instance is constructed. - */ -public final class MergedStream - extends InputStream -{ - final ReaderConfig mConfig; - - final InputStream mIn; - - byte[] mData; - - int mPtr; - - final int mEnd; - - public MergedStream(ReaderConfig cfg, - InputStream in, byte[] buf, int start, int end) - { - mConfig = cfg; - mIn = in; - mData = buf; - mPtr = start; - mEnd = end; - } - - public int available() - throws IOException - { - if (mData != null) { - return mEnd - mPtr; - } - return mIn.available(); - } - - public void close() - throws IOException - { - freeMergedBuffer(); - mIn.close(); - } - - public void mark(int readlimit) - { - if (mData == null) { - mIn.mark(readlimit); - } - } - - public boolean markSupported() - { - /* Only supports marks past the initial rewindable section... - */ - return (mData == null) && mIn.markSupported(); - } - - public int read() - throws IOException - { - if (mData != null) { - int c = mData[mPtr++] & 0xFF; - if (mPtr >= mEnd) { - freeMergedBuffer(); - } - return c; - } - return mIn.read(); - } - - public int read(byte[] b) - throws IOException - { - return read(b, 0, b.length); - } - - public int read(byte[] b, int off, int len) - throws IOException - { - if (mData != null) { - int avail = mEnd - mPtr; - if (len > avail) { - len = avail; - } - System.arraycopy(mData, mPtr, b, off, len); - mPtr += len; - if (mPtr >= mEnd) { - freeMergedBuffer(); - } - return len; - } - return mIn.read(b, off, len); - } - - public void reset() - throws IOException - { - if (mData == null) { - mIn.reset(); - } - } - - public long skip(long n) - throws IOException - { - long count = 0L; - - if (mData != null) { - int amount = mEnd - mPtr; - - if (amount > n) { // all in pushed back segment? - mPtr += (int) n; - return n; - } - freeMergedBuffer(); - count += amount; - n -= amount; - } - - if (n > 0) { - count += mIn.skip(n); - } - return count; - } - - private void freeMergedBuffer() - { - if (mData != null) { - byte[] data = mData; - mData = null; - if (mConfig != null) { - mConfig.freeFullBBuffer(data); - } - } - } -} diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/io/package.html libwoodstox-java-5.1.0/src/java/com/ctc/wstx/io/package.html --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/io/package.html 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/io/package.html 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ - -Low-level classes that are used to abstract most details of stream I/O -access from actual parsing classes. Input source abstraction is used -to allow nested input necessary for proper entity expansion functionality. - diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/io/ReaderBootstrapper.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/io/ReaderBootstrapper.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/io/ReaderBootstrapper.java 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/io/ReaderBootstrapper.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,403 +0,0 @@ -/* Woodstox XML processor - * - * Copyright (c) 2004- Tatu Saloranta, tatu.saloranta@iki.fi - * - * Licensed under the License specified in file LICENSE, included with - * the source code. - * You may not use this file except in compliance with the License. - * - * 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 com.ctc.wstx.io; - -import java.io.*; -import java.text.MessageFormat; - -import javax.xml.stream.Location; -import javax.xml.stream.XMLReporter; -import javax.xml.stream.XMLStreamException; - -import org.codehaus.stax2.validation.XMLValidationProblem; - -import com.ctc.wstx.api.ReaderConfig; -import com.ctc.wstx.cfg.ErrorConsts; -import com.ctc.wstx.cfg.ParsingErrorMsgs; -import com.ctc.wstx.exc.*; -import com.ctc.wstx.util.StringUtil; - -/** - * Input bootstrap class used when input comes from a Reader; in this case, - * encoding is already known, and thus encoding from XML declaration (if - * any) is only double-checked, not really used. - *

- * Note: since the actual Reader to use after bootstrapping is pre-constructed, - * the local input buffer can (and should) be quite small. - */ -public final class ReaderBootstrapper - extends InputBootstrapper -{ - final static char CHAR_BOM_MARKER = (char) 0xFEFF; - - /* - //////////////////////////////////////// - // Configuration - //////////////////////////////////////// - */ - - /** - * Underlying Reader to use for reading content. - */ - final Reader mIn; - - /** - * Encoding identifier processing application passed in; if not null, - * will be compared to actual xml declaration based encoding (if - * declaration found) - */ - final String mInputEncoding; - - /* - /////////////////////////////////////////////////////////////// - // Input buffering - /////////////////////////////////////////////////////////////// - */ - - private char[] mCharBuffer; - - private int mInputPtr; - - private int mInputEnd; - - /* - //////////////////////////////////////// - // Life-cycle - //////////////////////////////////////// - */ - - private ReaderBootstrapper(String pubId, String sysId, Reader r, String appEncoding) - { - super(pubId, sysId); - mIn = r; - if (appEncoding == null) { // may still be able to figure it out - if (r instanceof InputStreamReader) { - appEncoding = ((InputStreamReader) r).getEncoding(); - } - } - mInputEncoding = appEncoding; - } - - /* - //////////////////////////////////////// - // Public API - //////////////////////////////////////// - */ - - /** - * @param r Eventual reader that will be reading actual content, after - * bootstrapping finishes - * @param appEncoding Encoding that application declared; may be null. - * If not null, will be compared to actual declaration found; and - * incompatibility reported as a potential (but not necessarily fatal) - * problem. - */ - public static ReaderBootstrapper getInstance(String pubId, String sysId, - Reader r, String appEncoding) - { - return new ReaderBootstrapper(pubId, sysId, r, appEncoding); - } - - /** - * Method called to do actual bootstrapping. - * - * @return Actual reader to use for reading xml content - */ - public Reader bootstrapInput(ReaderConfig cfg, boolean mainDoc, int xmlVersion) - throws IOException, XMLStreamException - { - /* First order of business: allocate input buffer. Not done during - * construction for simplicity; that way config object need not be - * passed before actual bootstrap method is called - */ - /* Let's make sure buffer is at least 6 chars (to know '") - */ - if (mInputEnd >= 7) { - char c = mCharBuffer[mInputPtr]; - - // BOM to skip? - if (c == CHAR_BOM_MARKER) { - c = mCharBuffer[++mInputPtr]; - } - if (c == '<') { - if (mCharBuffer[mInputPtr+1] == '?' - && mCharBuffer[mInputPtr+2] == 'x' - && mCharBuffer[mInputPtr+3] == 'm' - && mCharBuffer[mInputPtr+4] == 'l' - && mCharBuffer[mInputPtr+5] <= CHAR_SPACE) { - // Yup, got the declaration ok! - mInputPtr += 6; // skip declaration - readXmlDecl(mainDoc, xmlVersion); - - if (mFoundEncoding != null && mInputEncoding != null) { - verifyXmlEncoding(cfg); - } - } - } else { - /* We may also get something that would be invalid xml - * ("garbage" char; neither '<' nor space). If so, and - * it's one of "well-known" cases, we can not only throw - * an exception but also indicate a clue as to what is likely - * to be wrong. - */ - /* Specifically, UTF-8 read via, say, ISO-8859-1 reader, can - * "leak" marker (0xEF, 0xBB, 0xBF). While we could just eat - * it, there's bound to be other problems cropping up, so let's - * inform about the problem right away. - */ - if (c == 0xEF) { - throw new WstxIOException("Unexpected first character (char code 0xEF), not valid in xml document: could be mangled UTF-8 BOM marker. Make sure that the Reader uses correct encoding or pass an InputStream instead"); - } - } - } - - /* Ok, now; do we have unused chars we have read that need to - * be merged in? - */ - if (mInputPtr < mInputEnd) { - return new MergedReader(cfg, mIn, mCharBuffer, mInputPtr, mInputEnd); - } - - return mIn; - } - - public String getInputEncoding() { - return mInputEncoding; - } - - public int getInputTotal() { - return mInputProcessed + mInputPtr; - } - - public int getInputColumn() { - return (mInputPtr - mInputRowStart); - } - - /* - //////////////////////////////////////// - // Internal methods, parsing - //////////////////////////////////////// - */ - - protected void verifyXmlEncoding(ReaderConfig cfg) - throws XMLStreamException - { - String inputEnc = mInputEncoding; - - // Close enough? - if (StringUtil.equalEncodings(inputEnc, mFoundEncoding)) { - return; - } - - /* Ok, maybe the difference is just with endianness indicator? - * (UTF-16BE vs. UTF-16)? - */ - // !!! TBI - - XMLReporter rep = cfg.getXMLReporter(); - if (rep != null) { - Location loc = getLocation(); - String msg = MessageFormat.format(ErrorConsts.W_MIXED_ENCODINGS, - new Object[] { mFoundEncoding, - inputEnc }); - String type = ErrorConsts.WT_XML_DECL; - /* 30-May-2008, tatus: Should wrap all the info as XMValidationProblem - * since that's Woodstox' contract wrt. relatedInformation field. - */ - XMLValidationProblem prob = new XMLValidationProblem(loc, msg, XMLValidationProblem.SEVERITY_WARNING, type); - rep.report(msg, type, prob, loc); - } - } - - /* - ///////////////////////////////////////////////////// - // Internal methods, loading input data - ///////////////////////////////////////////////////// - */ - - protected boolean initialLoad(int minimum) - throws IOException - { - mInputPtr = 0; - mInputEnd = 0; - - while (mInputEnd < minimum) { - int count = mIn.read(mCharBuffer, mInputEnd, - mCharBuffer.length - mInputEnd); - if (count < 1) { - return false; - } - mInputEnd += count; - } - return true; - } - - protected void loadMore() - throws IOException, WstxException - { - /* Need to make sure offsets are properly updated for error - * reporting purposes, and do this now while previous amounts - * are still known. - */ - mInputProcessed += mInputEnd; - mInputRowStart -= mInputEnd; - - mInputPtr = 0; - mInputEnd = mIn.read(mCharBuffer, 0, mCharBuffer.length); - if (mInputEnd < 1) { - throw new WstxEOFException(ParsingErrorMsgs.SUFFIX_IN_XML_DECL, - getLocation()); - } - } - - /* - ///////////////////////////////////////////////////// - // Implementations of abstract parsing methods - ///////////////////////////////////////////////////// - */ - - protected void pushback() { - --mInputPtr; - } - - protected int getNext() - throws IOException, WstxException - { - return (mInputPtr < mInputEnd) ? - mCharBuffer[mInputPtr++] : nextChar(); - } - - - protected int getNextAfterWs(boolean reqWs) - throws IOException, WstxException - { - int count = 0; - - while (true) { - char c = (mInputPtr < mInputEnd) ? - mCharBuffer[mInputPtr++] : nextChar(); - - if (c > CHAR_SPACE) { - if (reqWs && count == 0) { - reportUnexpectedChar(c, ERR_XMLDECL_EXP_SPACE); - } - return c; - } - if (c == CHAR_CR || c == CHAR_LF) { - skipCRLF(c); - } else if (c == CHAR_NULL) { - reportNull(); - } - ++count; - } - } - - /** - * @return First character that does not match expected, if any; - * CHAR_NULL if match succeeded - */ - protected int checkKeyword(String exp) - throws IOException, WstxException - { - int len = exp.length(); - - for (int ptr = 1; ptr < len; ++ptr) { - char c = (mInputPtr < mInputEnd) ? - mCharBuffer[mInputPtr++] : nextChar(); - - if (c != exp.charAt(ptr)) { - return c; - } - if (c == CHAR_NULL) { - reportNull(); - } - } - - return CHAR_NULL; - } - - protected int readQuotedValue(char[] kw, int quoteChar) - throws IOException, WstxException - { - int i = 0; - int len = kw.length; - - while (true) { - char c = (mInputPtr < mInputEnd) ? - mCharBuffer[mInputPtr++] : nextChar(); - if (c == CHAR_CR || c == CHAR_LF) { - skipCRLF(c); - } else if (c == CHAR_NULL) { - reportNull(); - } - if (c == quoteChar) { - return (i < len) ? i : -1; - } - // Let's just truncate longer values, but match quote - if (i < len) { - kw[i++] = c; - } - } - } - - protected Location getLocation() - { - return new WstxInputLocation(null, mPublicId, mSystemId, - mInputProcessed + mInputPtr - 1, - mInputRow, mInputPtr - mInputRowStart); - } - - /* - ///////////////////////////////////////////////////// - // Internal methods, single-byte access methods - ///////////////////////////////////////////////////// - */ - - protected char nextChar() - throws IOException, WstxException - { - if (mInputPtr >= mInputEnd) { - loadMore(); - } - return mCharBuffer[mInputPtr++]; - } - - protected void skipCRLF(char lf) - throws IOException, WstxException - { - if (lf == CHAR_CR) { - char c = (mInputPtr < mInputEnd) ? - mCharBuffer[mInputPtr++] : nextChar(); - if (c != BYTE_LF) { - --mInputPtr; // pushback if not 2-char/byte lf - } - } - ++mInputRow; - mInputRowStart = mInputPtr; - } -} diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/io/ReaderSource.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/io/ReaderSource.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/io/ReaderSource.java 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/io/ReaderSource.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,205 +0,0 @@ -package com.ctc.wstx.io; - -import java.io.IOException; -import java.io.Reader; -import java.net.URL; - -import javax.xml.stream.XMLStreamException; - -import com.ctc.wstx.api.ReaderConfig; -import com.ctc.wstx.exc.WstxException; - -/** - * Input source that reads input via a Reader. - */ -public class ReaderSource - extends BaseInputSource -{ - final ReaderConfig mConfig; - - /** - * Underlying Reader to read character data from - */ - Reader mReader; - - /** - * If true, will close the underlying Reader when this source is closed; - * if false will leave it open. - */ - final boolean mDoRealClose; - - int mInputProcessed = 0; - int mInputRow = 1; - int mInputRowStart = 0; - - public ReaderSource(ReaderConfig cfg, WstxInputSource parent, String fromEntity, - String pubId, String sysId, URL src, - Reader r, boolean realClose) - { - super(parent, fromEntity, pubId, sysId, src); - mConfig = cfg; - mReader = r; - mDoRealClose = realClose; - int bufSize = cfg.getInputBufferLength(); - mBuffer = cfg.allocFullCBuffer(bufSize); - } - - /** - * Method called to change the default offsets this source has. Generally - * done when the underlying Reader had been partially read earlier (like - * reading the xml declaration before starting real parsing). - */ - public void setInputOffsets(int proc, int row, int rowStart) - { - mInputProcessed = proc; - mInputRow = row; - mInputRowStart = rowStart; - } - - /** - * Input location is easy to set, as we'll start from the beginning - * of a File. - */ - protected void doInitInputLocation(WstxInputData reader) - { - reader.mCurrInputProcessed = mInputProcessed; - reader.mCurrInputRow = mInputRow; - reader.mCurrInputRowStart = mInputRowStart; - } - - /** - * This is a hard-coded assumption, for now this source is - * only created from external entities - */ - public boolean fromInternalEntity() { - return false; - } - - public int readInto(WstxInputData reader) - throws IOException, XMLStreamException - { - /* Shouldn't really try to read after closing, but it may be easier - * for caller not to have to keep track of closure... - */ - if (mBuffer == null) { - return -1; - } - int count = mReader.read(mBuffer, 0, mBuffer.length); - if (count < 1) { - /* Let's prevent caller from accidentally being able to access - * data, first. - */ - mInputLast = 0; - reader.mInputPtr = 0; - reader.mInputEnd = 0; - if (count == 0) { - /* Sanity check; should never happen with correctly written - * Readers: - */ - throw new WstxException("Reader (of type "+mReader.getClass().getName()+") returned 0 characters, even when asked to read up to "+mBuffer.length, getLocation()); - } - return -1; - } - reader.mInputBuffer = mBuffer; - reader.mInputPtr = 0; - mInputLast = count; - reader.mInputEnd = count; - - return count; - } - - public boolean readMore(WstxInputData reader, int minAmount) - throws IOException, XMLStreamException - { - /* Shouldn't really try to read after closing, but it may be easier - * for caller not to have to keep track of closure... - */ - if (mBuffer == null) { - return false; - } - - int ptr = reader.mInputPtr; - int currAmount = mInputLast - ptr; - - // Let's first adjust caller's data appropriately: - /* Since we are essentially removing 'ptr' chars that we - * have used already, they count as past chars. Also, since - * offsets are reduced by 'ptr', need to adjust linefeed offset - * marker as well. - */ - reader.mCurrInputProcessed += ptr; - reader.mCurrInputRowStart -= ptr; - - // Existing data to move? - if (currAmount > 0) { - System.arraycopy(mBuffer, ptr, mBuffer, 0, currAmount); - minAmount -= currAmount; - } - reader.mInputBuffer = mBuffer; - reader.mInputPtr = 0; - mInputLast = currAmount; - - while (minAmount > 0) { - int amount = mBuffer.length - currAmount; - int actual = mReader.read(mBuffer, currAmount, amount); - if (actual < 1) { - if (actual == 0) { // sanity check: - throw new WstxException("Reader (of type "+mReader.getClass().getName()+") returned 0 characters, even when asked to read up to "+amount, getLocation()); - } - reader.mInputEnd = mInputLast = currAmount; - return false; - } - currAmount += actual; - minAmount -= actual; - } - reader.mInputEnd = mInputLast = currAmount; - return true; - } - - public void close() - throws IOException - { - /* Buffer gets nullified by call to close() or closeCompletely(), - * no need to call second time - */ - if (mBuffer != null) { // so that it's ok to call multiple times - closeAndRecycle(mDoRealClose); - } - } - - public void closeCompletely() - throws IOException - { - /* Only need to call if the Reader is not yet null... since - * buffer may have been cleaned by a call to close() - */ - if (mReader != null) { // so that it's ok to call multiple times - closeAndRecycle(true); - } - } - - private void closeAndRecycle(boolean fullClose) - throws IOException - { - char[] buf = mBuffer; - - // Can we recycle buffers? - if (buf != null) { - mBuffer = null; - mConfig.freeFullCBuffer(buf); - } - - // How about Reader; close and/or recycle its buffers? - if (mReader != null) { - if (mReader instanceof BaseReader) { - ((BaseReader) mReader).freeBuffers(); - } - if (fullClose) { - Reader r = mReader; - mReader = null; - r.close(); - } - } - } -} - diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/io/StreamBootstrapper.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/io/StreamBootstrapper.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/io/StreamBootstrapper.java 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/io/StreamBootstrapper.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,1011 +0,0 @@ -package com.ctc.wstx.io; - -import java.io.*; - -import javax.xml.stream.Location; -import javax.xml.stream.XMLStreamException; - -import com.ctc.wstx.api.ReaderConfig; -import com.ctc.wstx.cfg.ParsingErrorMsgs; -import com.ctc.wstx.cfg.XmlConsts; -import com.ctc.wstx.exc.*; - -/** - * Input bootstrap class used with streams, when encoding is not known - * (when encoding is specified by application, a reader is constructed, - * and then reader-based bootstrapper is used). - *

after last valid byte in the buffer - */ - private StreamBootstrapper(String pubId, String sysId, byte[] data, int start, int end) - { - super(pubId, sysId); - mIn = null; - mRecycleBuffer = false; - mByteBuffer = data; - mInputPtr = start; - mInputEnd = end; - } - - /* - //////////////////////////////////////// - // Public API - //////////////////////////////////////// - */ - - /** - * Factory method used when the underlying data provider is an - * actual stream. - */ - public static StreamBootstrapper getInstance(String pubId, String sysId, InputStream in) - { - return new StreamBootstrapper(pubId, sysId, in); - } - - /** - * Factory method used when the underlying data provider is a pre-allocated - * block source, and no stream is used. - * Additionally the buffer passed is not owned by the bootstrapper - * or Reader that is created, so it is not to be recycled. - */ - public static StreamBootstrapper getInstance(String pubId, String sysId, byte[] data, int start, int end) - { - return new StreamBootstrapper(pubId, sysId, data, start, end); - } - - public Reader bootstrapInput(ReaderConfig cfg, boolean mainDoc, int xmlVersion) - throws IOException, XMLStreamException - { - String normEnc = null; - - // First, let's get the buffers... - int bufSize = cfg.getInputBufferLength(); - if (bufSize < MIN_BUF_SIZE) { - bufSize = MIN_BUF_SIZE; - } - if (mByteBuffer == null) { // non-null if we were passed a buffer - mByteBuffer = cfg.allocFullBBuffer(bufSize); - } - - resolveStreamEncoding(); - - if (hasXmlDecl()) { - // note: readXmlDecl will set mXml11Handling too - readXmlDecl(mainDoc, xmlVersion); - if (mFoundEncoding != null) { - normEnc = verifyXmlEncoding(mFoundEncoding); - } - } else { - /* We'll actually then just inherit whatever main doc had... - * (or in case there was no parent, just copy the 'unknown') - */ - mXml11Handling = (XmlConsts.XML_V_11 == xmlVersion); - } - - // Now, have we figured out the encoding? - - if (normEnc == null) { // not via xml declaration - /* 21-Sep-2007, TSa: As with any non-UTF-8 encoding, declaration - * isn't optional any more. Besides, we need that information - * anyway to know which variant it is. - */ - if (mEBCDIC) { - if (mFoundEncoding == null || mFoundEncoding.length() == 0) { - reportXmlProblem("Missing encoding declaration: underlying encoding looks like an EBCDIC variant, but no xml encoding declaration found"); - } - // Hmmh. What should be the canonical name? Let's just use found encoding? - normEnc = mFoundEncoding; - } else if (mBytesPerChar == 2) { // UTF-16, BE/LE - normEnc = mBigEndian ? CharsetNames.CS_UTF16BE : CharsetNames.CS_UTF16LE; - } else if (mBytesPerChar == 4) { // UCS-4... ? - /* 22-Mar-2005, TSa: JDK apparently has no way of dealing - * with these encodings... not sure if and how it should - * be dealt with, really. Name could be UCS-4xx... or - * perhaps UTF-32xx - */ - normEnc = mBigEndian ? CharsetNames.CS_UTF32BE : CharsetNames.CS_UTF32LE; - } else { - // Ok, default has to be UTF-8, as per XML specs - normEnc = CharsetNames.CS_UTF8; - } - } - - mInputEncoding = normEnc; - - /* And then the reader. Let's figure out if we can use our own fast - * implementations first: - */ - BaseReader r; - - // Normalized, can thus use straight equality checks now - if (normEnc == CharsetNames.CS_UTF8) { - r = new UTF8Reader(cfg, mIn, mByteBuffer, mInputPtr, mInputEnd, mRecycleBuffer); - } else if (normEnc == CharsetNames.CS_ISO_LATIN1) { - r = new ISOLatinReader(cfg, mIn, mByteBuffer, mInputPtr, mInputEnd, mRecycleBuffer); - } else if (normEnc == CharsetNames.CS_US_ASCII) { - r = new AsciiReader(cfg, mIn, mByteBuffer, mInputPtr, mInputEnd, mRecycleBuffer); - } else if (normEnc.startsWith(CharsetNames.CS_UTF32)) { - // let's augment with actual endianness info - if (normEnc == CharsetNames.CS_UTF32) { - mInputEncoding = mBigEndian ? CharsetNames.CS_UTF32BE : CharsetNames.CS_UTF32LE; - } - r = new UTF32Reader(cfg, mIn, mByteBuffer, mInputPtr, mInputEnd, - mRecycleBuffer, mBigEndian); - } else { - // Nah, JDK needs to try it - // Ok; first, do we need to merge stuff back? - InputStream in = mIn; - if (mInputPtr < mInputEnd) { - in = new MergedStream(cfg, in, mByteBuffer, mInputPtr, mInputEnd); - } - /* 20-Jan-2006, TSa: Ok; although it is possible to declare - * stream as 'UTF-16', JDK may need help in figuring out - * the right order, so let's be explicit: - */ - if (normEnc == CharsetNames.CS_UTF16) { - mInputEncoding = normEnc = mBigEndian ? CharsetNames.CS_UTF16BE : CharsetNames.CS_UTF16LE; - } - try { - return new InputStreamReader(in, normEnc); - } catch (UnsupportedEncodingException usex) { - throw new WstxIOException("Unsupported encoding: "+usex.getMessage()); - } - } - - if (mXml11Handling) { - r.setXmlCompliancy(XmlConsts.XML_V_11); - } - - return r; - } - - /** - * Since this class only gets used when encoding is not explicitly - * passed, need use the encoding that was auto-detected... - */ - public String getInputEncoding() { - return mInputEncoding; - } - - public int getInputTotal() { - int total = mInputProcessed + mInputPtr; - if (mBytesPerChar > 1) { - total /= mBytesPerChar; - } - return total; - } - - public int getInputColumn() { - int col = mInputPtr - mInputRowStart; - if (mBytesPerChar > 1) { - col /= mBytesPerChar; - } - return col; - } - - /* - //////////////////////////////////////// - // Internal methods, parsing - //////////////////////////////////////// - */ - - /** - * Method called to try to figure out physical encoding the underlying - * input stream uses. - */ - protected void resolveStreamEncoding() - throws IOException, WstxException - { - // Let's first set defaults: - mBytesPerChar = 0; - mBigEndian = true; - - /* Ok; first just need 4 bytes for determining bytes-per-char from - * BOM or first char(s) of likely xml declaration: - */ - if (ensureLoaded(4)) { - bomblock: - do { // BOM/auto-detection block - int quartet = (mByteBuffer[0] << 24) - | ((mByteBuffer[1] & 0xFF) << 16) - | ((mByteBuffer[2] & 0xFF) << 8) - | (mByteBuffer[3] & 0xFF); - - /* Handling of (usually) optional BOM (required for - * multi-byte formats); first 32-bit charsets: - */ - switch (quartet) { - case 0x0000FEFF: - mBigEndian = true; - mInputPtr = mBytesPerChar = 4; - break bomblock; - case 0xFFFE0000: // UCS-4, LE? - mInputPtr = mBytesPerChar = 4; - mBigEndian = false; - break bomblock; - case 0x0000FFFE: // UCS-4, in-order... - reportWeirdUCS4("2143"); - break bomblock; - case 0x0FEFF0000: // UCS-4, in-order... - reportWeirdUCS4("3412"); - break bomblock; - } - - // Ok, if not, how about 16-bit encoding BOMs? - int msw = quartet >>> 16; - if (msw == 0xFEFF) { // UTF-16, BE - mInputPtr = mBytesPerChar = 2; - mBigEndian = true; - break; - } - if (msw == 0xFFFE) { // UTF-16, LE - mInputPtr = mBytesPerChar = 2; - mBigEndian = false; - break; - } - - // And if not, then UTF-8 BOM? - if ((quartet >>> 8) == 0xEFBBBF) { // UTF-8 - mInputPtr = 3; - mBytesPerChar = 1; - mBigEndian = true; // doesn't really matter - break; - } - - /* And if that wasn't succesful, how about auto-detection - * for ' 0); - - // Let's update location markers to ignore BOM. - mInputProcessed = -mInputPtr; - mInputRowStart = mInputPtr; - } - - /* Hmmh. If we haven't figured it out, let's just assume - * UTF-8 as per XML specs: - */ - mByteSizeFound = (mBytesPerChar != 0); - if (!mByteSizeFound) { - mBytesPerChar = 1; - mBigEndian = true; // doesn't matter - } - } - - /** - * @return Normalized encoding name - */ - protected String verifyXmlEncoding(String enc) - throws WstxException - { - enc = CharsetNames.normalize(enc); - - // Let's actually verify we got matching information: - if (enc == CharsetNames.CS_UTF8) { - verifyEncoding(enc, 1); - } else if (enc == CharsetNames.CS_ISO_LATIN1) { - verifyEncoding(enc, 1); - } else if (enc == CharsetNames.CS_US_ASCII) { - verifyEncoding(enc, 1); - } else if (enc == CharsetNames.CS_UTF16) { - // BOM is obligatory, to know the ordering - /* 22-Mar-2005, TSa: Actually, since we don't have a - * custom decoder, so the underlying JDK Reader may - * have dealt with it transparently... so we can not - * really throw an exception here. - */ - //if (!mHadBOM) { - //reportMissingBOM(enc); - //} - verifyEncoding(enc, 2); - } else if (enc == CharsetNames.CS_UTF16LE) { - verifyEncoding(enc, 2, false); - } else if (enc == CharsetNames.CS_UTF16BE) { - verifyEncoding(enc, 2, true); - - } else if (enc == CharsetNames.CS_UTF32) { - // Do we require a BOM here? we can live without it... - //if (!mHadBOM) { - // reportMissingBOM(enc); - //} - verifyEncoding(enc, 4); - } else if (enc == CharsetNames.CS_UTF32LE) { - verifyEncoding(enc, 4, false); - } else if (enc == CharsetNames.CS_UTF32BE) { - verifyEncoding(enc, 4, true); - } - return enc; - } - - /* - ///////////////////////////////////////////////////// - // Internal methods, loading input data - ///////////////////////////////////////////////////// - */ - - protected boolean ensureLoaded(int minimum) - throws IOException - { - /* Let's assume here buffer has enough room -- this will always - * be true for the limited used this method gets - */ - int gotten = (mInputEnd - mInputPtr); - while (gotten < minimum) { - int count = (mIn == null) ? -1 : mIn.read(mByteBuffer, mInputEnd, mByteBuffer.length - mInputEnd); - if (count < 1) { - return false; - } - mInputEnd += count; - gotten += count; - } - return true; - } - - protected void loadMore() - throws IOException, WstxException - { - /* Need to make sure offsets are properly updated for error - * reporting purposes, and do this now while previous amounts - * are still known. - */ - /* Note: at this point these are all in bytes, not chars (for multibyte - * encodings) - */ - mInputProcessed += mInputEnd; - mInputRowStart -= mInputEnd; - - mInputPtr = 0; - mInputEnd = (mIn == null) ? -1 : mIn.read(mByteBuffer, 0, mByteBuffer.length); - if (mInputEnd < 1) { - throw new WstxEOFException(ParsingErrorMsgs.SUFFIX_IN_XML_DECL, - getLocation()); - } - } - - /* - ///////////////////////////////////////////////////// - // Implementations of abstract parsing methods - ///////////////////////////////////////////////////// - */ - - protected void pushback() { - if (mBytesPerChar < 0) { - mInputPtr += mBytesPerChar; - } else { - mInputPtr -= mBytesPerChar; - } - } - - protected int getNext() - throws IOException, WstxException - { - if (mBytesPerChar != 1) { - if (mBytesPerChar == -1) { // need to translate - return nextTranslated(); - } - return nextMultiByte(); - } - byte b = (mInputPtr < mInputEnd) ? - mByteBuffer[mInputPtr++] : nextByte(); - return (b & 0xFF); - } - - - protected int getNextAfterWs(boolean reqWs) - throws IOException, WstxException - { - int count; - - if (mBytesPerChar == 1) { // single byte - count = skipSbWs(); - } else { - if (mBytesPerChar == -1) { // translated - count = skipTranslatedWs(); - } else { // multi byte - count = skipMbWs(); - } - } - - if (reqWs && count == 0) { - reportUnexpectedChar(getNext(), ERR_XMLDECL_EXP_SPACE); - } - - // inlined getNext() - if (mBytesPerChar != 1) { - if (mBytesPerChar == -1) { // translated - return nextTranslated(); - } - return nextMultiByte(); - } - byte b = (mInputPtr < mInputEnd) ? - mByteBuffer[mInputPtr++] : nextByte(); - return (b & 0xFF); - } - - /** - * @return First character that does not match expected, if any; - * CHAR_NULL if match succeeded - */ - protected int checkKeyword(String exp) - throws IOException, WstxException - { - if (mBytesPerChar != 1) { - if (mBytesPerChar == -1) { - return checkTranslatedKeyword(exp); - } - return checkMbKeyword(exp); - } - return checkSbKeyword(exp); - } - - protected int readQuotedValue(char[] kw, int quoteChar) - throws IOException, WstxException - { - int i = 0; - int len = kw.length; - boolean simple = (mBytesPerChar == 1); - boolean mb = !simple && (mBytesPerChar > 1); - - while (i < len) { - int c; - - if (simple) { - byte b = (mInputPtr < mInputEnd) ? - mByteBuffer[mInputPtr++] : nextByte(); - if (b == BYTE_NULL) { - reportNull(); - } - if (b == BYTE_CR || b == BYTE_LF) { - skipSbLF(b); - b = BYTE_LF; - } - c = (b & 0xFF); - } else { - if (mb) { - c = nextMultiByte(); - if (c == CHAR_CR || c == CHAR_LF) { - skipMbLF(c); - c = CHAR_LF; - } - } else { - c = nextTranslated(); - if (c == CHAR_CR || c == CHAR_LF) { - skipTranslatedLF(c); - c = CHAR_LF; - } - } - } - - if (c == quoteChar) { - return (i < len) ? i : -1; - } - - if (i < len) { - kw[i++] = (char) c; - } - } - - /* If we end up this far, we ran out of buffer space... let's let - * caller figure that out, though - */ - return -1; - } - - protected boolean hasXmlDecl() - throws IOException, WstxException - { - /* Separate handling for common and fast case; 1/variable byte - * encodings that have ASCII subset: - */ - if (mBytesPerChar == 1) { - /* However... there has to be at least 6 bytes available; and if - * so, can check the 'signature' easily: - */ - if (ensureLoaded(6)) { - if (mByteBuffer[mInputPtr] == '<' - && mByteBuffer[mInputPtr+1] == '?' - && mByteBuffer[mInputPtr+2] == 'x' - && mByteBuffer[mInputPtr+3] == 'm' - && mByteBuffer[mInputPtr+4] == 'l' - && ((mByteBuffer[mInputPtr+5] & 0xFF) <= CHAR_SPACE)) { - - // Let's skip stuff so far: - mInputPtr += 6; - return true; - } - } - } else if (mBytesPerChar == -1) { // translated (EBCDIC) - if (ensureLoaded(6)) { - int start = mInputPtr; // if we have to 'unread' chars - if (nextTranslated() == '<' - && nextTranslated() == '?' - && nextTranslated() == 'x' - && nextTranslated() == 'm' - && nextTranslated() == 'l' - && nextTranslated() <= CHAR_SPACE) { - return true; - } - mInputPtr = start; // push data back - } - } else { - // ... and then for slower fixed-multibyte encodings: - - // Is there enough data for checks? - if (ensureLoaded (6 * mBytesPerChar)) { - int start = mInputPtr; // if we have to 'unread' chars - if (nextMultiByte() == '<' - && nextMultiByte() == '?' - && nextMultiByte() == 'x' - && nextMultiByte() == 'm' - && nextMultiByte() == 'l' - && nextMultiByte() <= CHAR_SPACE) { - return true; - } - mInputPtr = start; // push data back - } - } - - return false; - } - - protected Location getLocation() - { - /* Ok; for fixed-size multi-byte encodings, need to divide numbers - * to get character locations. For variable-length encodings the - * good thing is that xml declaration only uses shortest codepoints, - * ie. char count == byte count. - */ - int total = mInputProcessed + mInputPtr; - int col = mInputPtr - mInputRowStart; - - if (mBytesPerChar > 1) { - total /= mBytesPerChar; - col /= mBytesPerChar; - } - - return new WstxInputLocation(null, mPublicId, mSystemId, - total - 1, // 0-based - mInputRow, col); - } - - /* - ///////////////////////////////////////////////////// - // Internal methods, single-byte access methods - ///////////////////////////////////////////////////// - */ - - protected byte nextByte() - throws IOException, WstxException - { - if (mInputPtr >= mInputEnd) { - loadMore(); - } - return mByteBuffer[mInputPtr++]; - } - - protected int skipSbWs() - throws IOException, WstxException - { - int count = 0; - - while (true) { - byte b = (mInputPtr < mInputEnd) ? - mByteBuffer[mInputPtr++] : nextByte(); - - if ((b & 0xFF) > CHAR_SPACE) { - --mInputPtr; - break; - } - if (b == BYTE_CR || b == BYTE_LF) { - skipSbLF(b); - } else if (b == BYTE_NULL) { - reportNull(); - } - ++count; - } - return count; - } - - protected void skipSbLF(byte lfByte) - throws IOException, WstxException - { - if (lfByte == BYTE_CR) { - byte b = (mInputPtr < mInputEnd) ? - mByteBuffer[mInputPtr++] : nextByte(); - if (b != BYTE_LF) { - --mInputPtr; // pushback if not 2-char/byte lf - } - } - ++mInputRow; - mInputRowStart = mInputPtr; - } - - /** - * @return First character that does not match expected, if any; - * CHAR_NULL if match succeeded - */ - protected int checkSbKeyword(String expected) - throws IOException, WstxException - { - int len = expected.length(); - - for (int ptr = 1; ptr < len; ++ptr) { - byte b = (mInputPtr < mInputEnd) ? - mByteBuffer[mInputPtr++] : nextByte(); - - if (b == BYTE_NULL) { - reportNull(); - } - if ((b & 0xFF) != expected.charAt(ptr)) { - return (b & 0xFF); - } - } - - return CHAR_NULL; - } - - /* - ///////////////////////////////////////////////////// - // Internal methods, multi-byte/translated access/checks - ///////////////////////////////////////////////////// - */ - - protected int nextMultiByte() - throws IOException, WstxException - { - byte b = (mInputPtr < mInputEnd) ? - mByteBuffer[mInputPtr++] : nextByte(); - byte b2 = (mInputPtr < mInputEnd) ? - mByteBuffer[mInputPtr++] : nextByte(); - int c; - - if (mBytesPerChar == 2) { - if (mBigEndian) { - c = ((b & 0xFF) << 8) | (b2 & 0xFF); - } else { - c = (b & 0xFF) | ((b2 & 0xFF) << 8); - } - } else { - // Has to be 4 bytes - byte b3 = (mInputPtr < mInputEnd) ? - mByteBuffer[mInputPtr++] : nextByte(); - byte b4 = (mInputPtr < mInputEnd) ? - mByteBuffer[mInputPtr++] : nextByte(); - - if (mBigEndian) { - c = (b << 24) | ((b2 & 0xFF) << 16) - | ((b3 & 0xFF) << 8) | (b4 & 0xFF); - } else { - c = (b4 << 24) | ((b3 & 0xFF) << 16) - | ((b2 & 0xFF) << 8) | (b & 0xFF); - } - } - - // Let's catch null chars early - if (c == 0) { - reportNull(); - } - return c; - } - - protected int nextTranslated() - throws IOException, WstxException - { - byte b = (mInputPtr < mInputEnd) ? - mByteBuffer[mInputPtr++] : nextByte(); - int ch = mSingleByteTranslation[b & 0xFF]; - if (ch < 0) { // special char... won't care for now - ch = -ch; - } - return ch; - } - - protected int skipMbWs() - throws IOException, WstxException - { - int count = 0; - - while (true) { - int c = nextMultiByte(); - - if (c > CHAR_SPACE) { - mInputPtr -= mBytesPerChar; - break; - } - if (c == CHAR_CR || c == CHAR_LF) { - skipMbLF(c); - } else if (c == CHAR_NULL) { - reportNull(); - } - ++count; - } - return count; - } - - protected int skipTranslatedWs() - throws IOException, WstxException - { - int count = 0; - - while (true) { - int c = nextTranslated(); - - // Hmmh. Are we to accept NEL (0x85)? - if (c > CHAR_SPACE && c != CHAR_NEL) { - --mInputPtr; - break; - } - if (c == CHAR_CR || c == CHAR_LF) { - skipTranslatedLF(c); - } else if (c == CHAR_NULL) { - reportNull(); - } - ++count; - } - return count; - } - - protected void skipMbLF(int lf) - throws IOException, WstxException - { - if (lf == CHAR_CR) { - int c = nextMultiByte(); - if (c != CHAR_LF) { - mInputPtr -= mBytesPerChar; - } - } - ++mInputRow; - mInputRowStart = mInputPtr; - } - - protected void skipTranslatedLF(int lf) - throws IOException, WstxException - { - if (lf == CHAR_CR) { - int c = nextTranslated(); - if (c != CHAR_LF) { - mInputPtr -= 1; - } - } - ++mInputRow; - mInputRowStart = mInputPtr; - } - - /** - * @return First character that does not match expected, if any; - * CHAR_NULL if match succeeded - */ - protected int checkMbKeyword(String expected) - throws IOException, WstxException - { - int len = expected.length(); - - for (int ptr = 1; ptr < len; ++ptr) { - int c = nextMultiByte(); - if (c == BYTE_NULL) { - reportNull(); - } - if (c != expected.charAt(ptr)) { - return c; - } - } - - return CHAR_NULL; - } - - protected int checkTranslatedKeyword(String expected) - throws IOException, WstxException - { - int len = expected.length(); - - for (int ptr = 1; ptr < len; ++ptr) { - int c = nextTranslated(); - if (c == BYTE_NULL) { - reportNull(); - } - if (c != expected.charAt(ptr)) { - return c; - } - } - - return CHAR_NULL; - } - - /* - //////////////////////////////////////// - // Other private methods: - //////////////////////////////////////// - */ - - private void verifyEncoding(String id, int bpc) - throws WstxException - { - if (mByteSizeFound) { - /* Let's verify that if we matched an encoding, it's the same - * as what was declared... - */ - if (bpc != mBytesPerChar) { - // [WSTX-138]: Needs to detect EBCDIC discrepancy - if (mEBCDIC) { - reportXmlProblem("Declared encoding '"+id+"' incompatible with auto-detected physical encoding (EBCDIC variant), can not decode input since actual code page not known"); - } - reportXmlProblem("Declared encoding '"+id+"' uses "+bpc - +" bytes per character; but physical encoding appeared to use "+mBytesPerChar+"; cannot decode"); - } - } - } - - private void verifyEncoding(String id, int bpc, boolean bigEndian) - throws WstxException - { - if (mByteSizeFound) { - verifyEncoding(id, bpc); - - if (bigEndian != mBigEndian) { - String bigStr = bigEndian ? "big" : "little"; - reportXmlProblem - ("Declared encoding '"+id+"' has different endianness (" - +bigStr+" endian) than what physical ordering appeared to be; cannot decode"); - } - } - } - - private void reportWeirdUCS4(String type) - throws IOException - { - throw new CharConversionException("Unsupported UCS-4 endianness ("+type+") detected"); - } - - /* - private void reportMissingBOM(String enc) - throws WstxException - { - throw new WstxException("Missing BOM for encoding '"+enc+"'; can not be omitted", - getLocation()); - } - */ -} diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/io/TextEscaper.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/io/TextEscaper.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/io/TextEscaper.java 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/io/TextEscaper.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,88 +0,0 @@ -package com.ctc.wstx.io; - -import java.io.*; - -public final class TextEscaper -{ - private TextEscaper() { } - - /* - ///////////////////////////////////////////////////////////// - // Static utility methods, for non-state-aware escaping - ///////////////////////////////////////////////////////////// - */ - - public static void writeEscapedAttrValue(Writer w, String value) - throws IOException - { - int i = 0; - int len = value.length(); - do { - int start = i; - char c = '\u0000'; - - for (; i < len; ++i) { - c = value.charAt(i); - if (c == '<' || c == '&' || c == '"') { - break; - } - } - int outLen = i - start; - if (outLen > 0) { - w.write(value, start, outLen); - } - if (i < len) { - if (c == '<') { - w.write("<"); - } else if (c == '&') { - w.write("&"); - } else if (c == '"') { - w.write("""); - - } - } - } while (++i < len); - } - - /** - * Quoting method used when outputting content that will be part of - * DTD (internal/external subset). Additional quoting is needed for - * percentage char, which signals parameter entities. - */ - public static void outputDTDText(Writer w, char[] ch, int offset, int len) - throws IOException - { - int i = offset; - len += offset; - do { - int start = i; - char c = '\u0000'; - - for (; i < len; ++i) { - c = ch[i]; - if (c == '&' || c == '%' || c == '"') { - break; - } - } - int outLen = i - start; - if (outLen > 0) { - w.write(ch, start, outLen); - } - if (i < len) { - if (c == '&') { - /* Only need to quote to prevent it from being accidentally - * taken as part of char entity... - */ - w.write("&"); - } else if (c == '%') { - // Need to quote, to prevent use as Param Entity marker - w.write("%"); - } else if (c == '"') { - // Need to quote assuming it encloses entity value - w.write("""); - } - } - } while (++i < len); - } -} - diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/io/UTF32Reader.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/io/UTF32Reader.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/io/UTF32Reader.java 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/io/UTF32Reader.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,258 +0,0 @@ -/* Woodstox XML processor - * - * Copyright (c) 2004 Tatu Saloranta, tatu.saloranta@iki.fi - * - * Licensed under the License specified in file LICENSE, included with - * the source code. - * You may not use this file except in compliance with the License. - * - * 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 com.ctc.wstx.io; - -import java.io.*; - -import com.ctc.wstx.api.ReaderConfig; -import com.ctc.wstx.cfg.XmlConsts; - -/** - * Since JDK does not come with UTF-32/UCS-4, let's implement a simple - * decoder to use. - */ -public final class UTF32Reader - extends BaseReader -{ - final boolean mBigEndian; - - boolean mXml11; - - /** - * Although input is fine with full Unicode set, Java still uses - * 16-bit chars, so we may have to split high-order chars into - * surrogate pairs. - */ - char mSurrogate = NULL_CHAR; - - /** - * Total read character count; used for error reporting purposes - */ - int mCharCount = 0; - - /** - * Total read byte count; used for error reporting purposes - */ - int mByteCount = 0; - - /* - //////////////////////////////////////// - // Life-cycle - //////////////////////////////////////// - */ - - public UTF32Reader(ReaderConfig cfg, InputStream in, byte[] buf, int ptr, int len, - boolean recycleBuffer, - boolean isBigEndian) - { - super(cfg, in, buf, ptr, len, recycleBuffer); - mBigEndian = isBigEndian; - } - - public void setXmlCompliancy(int xmlVersion) - { - mXml11 = (xmlVersion == XmlConsts.XML_V_11); - } - - /* - //////////////////////////////////////// - // Public API - //////////////////////////////////////// - */ - - public int read(char[] cbuf, int start, int len) - throws IOException - { - // Let's first ensure there's enough room... - if (start < 0 || (start+len) > cbuf.length) { - reportBounds(cbuf, start, len); - } - // Already EOF? - if (mByteBuffer == null) { - return -1; - } - if (len < 1) { - return 0; - } - - len += start; - int outPtr = start; - - // Ok, first; do we have a surrogate from last round? - if (mSurrogate != NULL_CHAR) { - cbuf[outPtr++] = mSurrogate; - mSurrogate = NULL_CHAR; - // No need to load more, already got one char - } else { - /* Note: we'll try to avoid blocking as much as possible. As a - * result, we only need to get 4 bytes for a full char. - */ - int left = (mByteBufferEnd - mBytePtr); - if (left < 4) { - if (!loadMore(left)) { // (legal) EOF? - return -1; - } - } - } - - byte[] buf = mByteBuffer; - - main_loop: - while (outPtr < len) { - int ptr = mBytePtr; - int ch; - - if (mBigEndian) { - ch = (buf[ptr] << 24) | ((buf[ptr+1] & 0xFF) << 16) - | ((buf[ptr+2] & 0xFF) << 8) | (buf[ptr+3] & 0xFF); - } else { - ch = (buf[ptr] & 0xFF) | ((buf[ptr+1] & 0xFF) << 8) - | ((buf[ptr+2] & 0xFF) << 16) | (buf[ptr+3] << 24); - } - mBytePtr += 4; - - // Does it need to be split to surrogates? - // (also, we can and need to verify illegal chars) - if (ch >= 0x7F) { - if (ch <= 0x9F) { - if (mXml11) { // high-order ctrl char detection... - if (ch != 0x85) { - reportInvalid(ch, outPtr-start, "(can only be included via entity in xml 1.1)"); - } - ch = CONVERT_NEL_TO; - } - } else if (ch >= 0xD800) { - // Illegal? - if (ch > XmlConsts.MAX_UNICODE_CHAR) { - reportInvalid(ch, outPtr-start, - "(above "+Integer.toHexString(XmlConsts.MAX_UNICODE_CHAR)+") "); - } - if (ch > 0xFFFF) { // need to split into surrogates? - ch -= 0x10000; // to normalize it starting with 0x0 - cbuf[outPtr++] = (char) (0xD800 + (ch >> 10)); - // hmmh. can this ever be 0? (not legal, at least?) - ch = (0xDC00 | (ch & 0x03FF)); - // Room for second part? - if (outPtr >= len) { // nope - mSurrogate = (char) ch; - break main_loop; - } - } else { // in 16-bit range... just need validity checks - if (ch < 0xE000) { - reportInvalid(ch, outPtr-start, "(a surrogate char) "); - } else if (ch >= 0xFFFE) { - reportInvalid(ch, outPtr-start, ""); - } - } - } else if (ch == 0x2028 && mXml11) { // LSEP - ch = CONVERT_LSEP_TO; - } - } - cbuf[outPtr++] = (char) ch; - if (mBytePtr >= mByteBufferEnd) { - break main_loop; - } - } - - len = outPtr - start; - mCharCount += len; - return len; - } - - /* - //////////////////////////////////////// - // Internal methods - //////////////////////////////////////// - */ - - private void reportUnexpectedEOF(int gotBytes, int needed) - throws IOException - { - int bytePos = mByteCount + gotBytes; - int charPos = mCharCount; - - throw new CharConversionException("Unexpected EOF in the middle of a 4-byte UTF-32 char: got " - +gotBytes+", needed "+needed - +", at char #"+charPos+", byte #"+bytePos+")"); - } - - private void reportInvalid(int value, int offset, String msg) - throws IOException - { - int bytePos = mByteCount + mBytePtr - 1; - int charPos = mCharCount + offset; - - throw new CharConversionException("Invalid UTF-32 character 0x" - +Integer.toHexString(value) - +msg+" at char #"+charPos+", byte #"+bytePos+")"); - } - - /** - * @param available Number of "unused" bytes in the input buffer - * - * @return True, if enough bytes were read to allow decoding of at least - * one full character; false if EOF was encountered instead. - */ - private boolean loadMore(int available) - throws IOException - { - mByteCount += (mByteBufferEnd - available); - - // Bytes that need to be moved to the beginning of buffer? - if (available > 0) { - /* 11-Nov-2008, TSa: can only move if we own the buffer; otherwise - * we are stuck with the data. - */ - if (mBytePtr > 0 && canModifyBuffer()) { - for (int i = 0; i < available; ++i) { - mByteBuffer[i] = mByteBuffer[mBytePtr+i]; - } - mBytePtr = 0; - mByteBufferEnd = available; - } - } else { - /* Ok; here we can actually reasonably expect an EOF, - * so let's do a separate read right away: - */ - int count = readBytes(); - if (count < 1) { - if (count < 0) { // -1 - freeBuffers(); // to help GC? - return false; - } - // 0 count is no good; let's err out - reportStrangeStream(); - } - } - - /* Need at least 4 bytes; if we don't get that many, it's an - * error. - */ - while (mByteBufferEnd < 4) { - int count = readBytesAt(mByteBufferEnd); - if (count < 1) { - if (count < 0) { // -1, EOF... no good! - freeBuffers(); // to help GC? - reportUnexpectedEOF(mByteBufferEnd, 4); - } - // 0 count is no good; let's err out - reportStrangeStream(); - } - } - return true; - } -} - diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/io/UTF8Reader.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/io/UTF8Reader.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/io/UTF8Reader.java 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/io/UTF8Reader.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,420 +0,0 @@ -/* Woodstox XML processor - * - * Copyright (c) 2004 Tatu Saloranta, tatu.saloranta@iki.fi - * - * Licensed under the License specified in file LICENSE, included with - * the source code. - * You may not use this file except in compliance with the License. - * - * 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 com.ctc.wstx.io; - -import java.io.*; - -import com.ctc.wstx.api.ReaderConfig; -import com.ctc.wstx.cfg.XmlConsts; - -/** - * Optimized Reader that reads UTF-8 encoded content from an input stream. - * In addition to doing (hopefully) optimal conversion, it can also take - * array of "pre-read" (leftover) bytes; this is necessary when preliminary - * stream/reader is trying to figure out XML encoding. - */ -public final class UTF8Reader - extends BaseReader -{ - boolean mXml11 = false; - - char mSurrogate = NULL_CHAR; - - /** - * Total read character count; used for error reporting purposes - */ - int mCharCount = 0; - - /** - * Total read byte count; used for error reporting purposes - */ - int mByteCount = 0; - - /* - //////////////////////////////////////// - // Life-cycle - //////////////////////////////////////// - */ - - public UTF8Reader(ReaderConfig cfg, InputStream in, byte[] buf, int ptr, int len, - boolean recycleBuffer) - { - super(cfg, in, buf, ptr, len, recycleBuffer); - } - - public void setXmlCompliancy(int xmlVersion) - { - mXml11 = (xmlVersion == XmlConsts.XML_V_11); - } - - /* - //////////////////////////////////////// - // Public API - //////////////////////////////////////// - */ - - public int read(char[] cbuf, int start, int len) - throws IOException - { - // Let's first ensure there's enough room... - if (start < 0 || (start+len) > cbuf.length) { - reportBounds(cbuf, start, len); - } - // Already EOF? - if (mByteBuffer == null) { - return -1; - } - if (len < 1) { // dummy call? - return 0; - } - - len += start; - int outPtr = start; - - // Ok, first; do we have a surrogate from last round? - if (mSurrogate != NULL_CHAR) { - cbuf[outPtr++] = mSurrogate; - mSurrogate = NULL_CHAR; - // No need to load more, already got one char - } else { - /* To prevent unnecessary blocking (esp. with network streams), - * we'll only require decoding of a single char - */ - int left = (mByteBufferEnd - mBytePtr); - - /* So; only need to load more if we can't provide at least - * one more character. We need not do thorough check here, - * but let's check the common cases here: either completely - * empty buffer (left == 0), or one with less than max. byte - * count for a single char, and starting of a multi-byte - * encoding (this leaves possibility of a 2/3-byte char - * that is still fully accessible... but that can be checked - * by the load method) - */ - - if (left < 4) { - // Need to load more? - if (left < 1 || mByteBuffer[mBytePtr] < 0) { - if (!loadMore(left)) { // (legal) EOF? - return -1; - } - } - } - } - - /* This may look silly, but using a local var is indeed faster - * (if and when HotSpot properly gets things running) than - * member variable... - */ - byte[] buf = mByteBuffer; - int inPtr = mBytePtr; - int inBufLen = mByteBufferEnd; - - main_loop: - while (outPtr < len) { - // At this point we have at least one byte available - int c = (int) buf[inPtr++]; - - /* Let's first do the quickie loop for common case; 7-bit - * ascii: - */ - if (c >= 0) { // ascii? can probably loop, then - if (c == 0x7F && mXml11) { // DEL illegal in xml1.1 - int bytePos = mByteCount + inPtr - 1; - int charPos = mCharCount + (outPtr-start); - reportInvalidXml11(c, bytePos, charPos); - } - cbuf[outPtr++] = (char) c; // ok since MSB is never on - - /* Ok, how many such chars could we safely process - * without overruns? (will combine 2 in-loop comparisons - * into just one) - */ - int outMax = (len - outPtr); // max output - int inMax = (inBufLen - inPtr); // max input - int inEnd = inPtr + ((inMax < outMax) ? inMax : outMax); - - ascii_loop: - while (true) { - if (inPtr >= inEnd) { - break main_loop; - } - c = ((int) buf[inPtr++]) & 0xFF; - if (c >= 0x7F) { // DEL, or multi-byte - break ascii_loop; - } - cbuf[outPtr++] = (char) c; - } - if (c == 0x7F) { - if (mXml11) { // DEL illegal in xml1.1 - int bytePos = mByteCount + inPtr - 1; - int charPos = mCharCount + (outPtr-start); - reportInvalidXml11(c, bytePos, charPos); - } // but not in xml 1.0 - cbuf[outPtr++] = (char) c; - if(inPtr >= inEnd){ - break main_loop; - } - continue main_loop; - } - } - - int needed; - - // Ok; if we end here, we got multi-byte combination - if ((c & 0xE0) == 0xC0) { // 2 bytes (0x0080 - 0x07FF) - c = (c & 0x1F); - needed = 1; - } else if ((c & 0xF0) == 0xE0) { // 3 bytes (0x0800 - 0xFFFF) - c = (c & 0x0F); - needed = 2; - } else if ((c & 0xF8) == 0xF0) { - // 4 bytes; double-char BS, with surrogates and all... - c = (c & 0x0F); - needed = 3; - } else { - reportInvalidInitial(c & 0xFF, outPtr-start); - // never gets here... - needed = 1; - } - /* Do we have enough bytes? If not, let's just push back the - * byte and leave, since we have already gotten at least one - * char decoded. This way we will only block (with read from - * input stream) when absolutely necessary. - */ - if ((inBufLen - inPtr) < needed) { - --inPtr; - break main_loop; - } - - int d = (int) buf[inPtr++]; - if ((d & 0xC0) != 0x080) { - reportInvalidOther(d & 0xFF, outPtr-start); - } - c = (c << 6) | (d & 0x3F); - - if (needed > 1) { // needed == 1 means 2 bytes total - d = buf[inPtr++]; // 3rd byte - if ((d & 0xC0) != 0x080) { - reportInvalidOther(d & 0xFF, outPtr-start); - } - c = (c << 6) | (d & 0x3F); - if (needed > 2) { // 4 bytes? (need surrogates) - d = buf[inPtr++]; - if ((d & 0xC0) != 0x080) { - reportInvalidOther(d & 0xFF, outPtr-start); - } - c = (c << 6) | (d & 0x3F); - if (c > XmlConsts.MAX_UNICODE_CHAR) { - reportInvalid(c, outPtr-start, - "(above "+Integer.toHexString(XmlConsts.MAX_UNICODE_CHAR)+") "); - } - /* Ugh. Need to mess with surrogates. Ok; let's inline them - * there, then, if there's room: if only room for one, - * need to save the surrogate for the rainy day... - */ - c -= 0x10000; // to normalize it starting with 0x0 - cbuf[outPtr++] = (char) (0xD800 + (c >> 10)); - // hmmh. can this ever be 0? (not legal, at least?) - c = (0xDC00 | (c & 0x03FF)); - - // Room for second part? - if (outPtr >= len) { // nope - mSurrogate = (char) c; - break main_loop; - } - // sure, let's fall back to normal processing: - } else { - /* Otherwise, need to check that 3-byte chars are - * legal ones (should not expand to surrogates; - * 0xFFFE and 0xFFFF are illegal) - */ - if (c >= 0xD800) { - // But first, let's check max chars: - if (c < 0xE000) { - reportInvalid(c, outPtr-start, "(a surrogate character) "); - } else if (c >= 0xFFFE) { - reportInvalid(c, outPtr-start, ""); - } - } else if (mXml11 && c == 0x2028) { // LSEP? - /* 10-May-2006, TSa: Since LSEP is "non-associative", - * it needs additional handling. One way to do - * this is to convert preceding \r to \n. This - * should be implemented better when integrating - * decoder and tokenizer. - */ - if (outPtr > start && cbuf[outPtr-1] == '\r') { - cbuf[outPtr-1] = '\n'; - } - c = CONVERT_LSEP_TO; - } - } - } else { // (needed == 1) - if (mXml11) { // high-order ctrl char detection... - if (c <= 0x9F) { - if (c == 0x85) { // NEL, let's convert? - c = CONVERT_NEL_TO; - } else if (c >= 0x7F) { // DEL, ctrl chars - int bytePos = mByteCount + inPtr - 1; - int charPos = mCharCount + (outPtr-start); - reportInvalidXml11(c, bytePos, charPos); - } - } - } - } - cbuf[outPtr++] = (char) c; - if (inPtr >= inBufLen) { - break main_loop; - } - } - - mBytePtr = inPtr; - len = outPtr - start; - mCharCount += len; - return len; - } - - /* - //////////////////////////////////////// - // Internal methods - //////////////////////////////////////// - */ - - private void reportInvalidInitial(int mask, int offset) - throws IOException - { - // input (byte) ptr has been advanced by one, by now: - int bytePos = mByteCount + mBytePtr - 1; - int charPos = mCharCount + offset + 1; - - throw new CharConversionException("Invalid UTF-8 start byte 0x" - +Integer.toHexString(mask) - +" (at char #"+charPos+", byte #"+bytePos+")"); - } - - private void reportInvalidOther(int mask, int offset) - throws IOException - { - int bytePos = mByteCount + mBytePtr - 1; - int charPos = mCharCount + offset; - - throw new CharConversionException("Invalid UTF-8 middle byte 0x" - +Integer.toHexString(mask) - +" (at char #"+charPos+", byte #"+bytePos+")"); - } - - private void reportUnexpectedEOF(int gotBytes, int needed) - throws IOException - { - int bytePos = mByteCount + gotBytes; - int charPos = mCharCount; - - throw new CharConversionException("Unexpected EOF in the middle of a multi-byte char: got " - +gotBytes+", needed "+needed - +", at char #"+charPos+", byte #"+bytePos+")"); - } - - private void reportInvalid(int value, int offset, String msg) - throws IOException - { - int bytePos = mByteCount + mBytePtr - 1; - int charPos = mCharCount + offset; - - throw new CharConversionException("Invalid UTF-8 character 0x" - +Integer.toHexString(value)+msg - +" at char #"+charPos+", byte #"+bytePos+")"); - } - - /** - * @param available Number of "unused" bytes in the input buffer - * - * @return True, if enough bytes were read to allow decoding of at least - * one full character; false if EOF was encountered instead. - */ - private boolean loadMore(int available) - throws IOException - { - mByteCount += (mByteBufferEnd - available); - - // Bytes that need to be moved to the beginning of buffer? - if (available > 0) { - /* 11-Nov-2008, TSa: can only move if we own the buffer; otherwise - * we are stuck with the data. - */ - if (mBytePtr > 0 && canModifyBuffer()) { - for (int i = 0; i < available; ++i) { - mByteBuffer[i] = mByteBuffer[mBytePtr+i]; - } - mBytePtr = 0; - mByteBufferEnd = available; - } - } else { - /* Ok; here we can actually reasonably expect an EOF, - * so let's do a separate read right away: - */ - int count = readBytes(); - if (count < 1) { - if (count < 0) { // -1 - freeBuffers(); // to help GC? - return false; - } - // 0 count is no good; let's err out - reportStrangeStream(); - } - } - - /* We now have at least one byte... and that allows us to - * calculate exactly how many bytes we need! - */ - int c = (int) mByteBuffer[mBytePtr]; - if (c >= 0) { // single byte (ascii) char... cool, can return - return true; - } - - // Ok, a multi-byte char, let's check how many bytes we'll need: - int needed; - if ((c & 0xE0) == 0xC0) { // 2 bytes (0x0080 - 0x07FF) - needed = 2; - } else if ((c & 0xF0) == 0xE0) { // 3 bytes (0x0800 - 0xFFFF) - needed = 3; - } else if ((c & 0xF8) == 0xF0) { - // 4 bytes; double-char BS, with surrogates and all... - needed = 4; - } else { - reportInvalidInitial(c & 0xFF, 0); - // never gets here... but compiler whines without this: - needed = 1; - } - - /* And then we'll just need to load up to that many bytes; - * if an EOF is hit, that'll be an error. But we need not do - * actual decoding here, just load enough bytes. - */ - while ((mBytePtr + needed) > mByteBufferEnd) { - int count = readBytesAt(mByteBufferEnd); - if (count < 1) { - if (count < 0) { // -1, EOF... no good! - freeBuffers(); - reportUnexpectedEOF(mByteBufferEnd, needed); - } - // 0 count is no good; let's err out - reportStrangeStream(); - } - } - return true; - } -} - diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/io/UTF8Writer.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/io/UTF8Writer.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/io/UTF8Writer.java 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/io/UTF8Writer.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,423 +0,0 @@ -package com.ctc.wstx.io; - -import java.io.*; - -import com.ctc.wstx.api.WriterConfig; - -/** - * Specialized buffering UTF-8 writer used by - * {@link com.ctc.wstx.sw.XmlWriter}. - * The main reason for custom version is to allow for efficient - * buffer recycling; the second benefit is that encoder has less - * overhead for short content encoding (compared to JDK default - * codecs). - */ -public final class UTF8Writer - extends Writer - implements CompletelyCloseable -{ - private final static int DEFAULT_BUF_LEN = 4000; - - final static int SURR1_FIRST = 0xD800; - final static int SURR1_LAST = 0xDBFF; - final static int SURR2_FIRST = 0xDC00; - final static int SURR2_LAST = 0xDFFF; - - final WriterConfig mConfig; - - final boolean mAutoCloseOutput; - - final OutputStream mOut; - - byte[] mOutBuffer; - - final int mOutBufferLast; - - int mOutPtr; - - /** - * When outputting chars from BMP, surrogate pairs need to be coalesced. - * To do this, both pairs must be known first; and since it is possible - * pairs may be split, we need temporary storage for the first half - */ - int mSurrogate = 0; - - public UTF8Writer(WriterConfig cfg, OutputStream out, boolean autoclose) - { - mConfig = cfg; - mAutoCloseOutput = autoclose; - mOut = out; - mOutBuffer = (mConfig == null) ? new byte[DEFAULT_BUF_LEN] : cfg.allocFullBBuffer(DEFAULT_BUF_LEN); - /* Max. expansion for a single char (in unmodified UTF-8) is - * 4 bytes (or 3 depending on how you view it -- 4 when recombining - * surrogate pairs) - */ - mOutBufferLast = mOutBuffer.length - 4; - mOutPtr = 0; - } - - /* - //////////////////////////////////////////////////////// - // CompletelyCloseable impl - //////////////////////////////////////////////////////// - */ - - public void closeCompletely() throws IOException - { - _close(true); - } - - /* - //////////////////////////////////////////////////////// - // java.io.Writer implementation - //////////////////////////////////////////////////////// - */ - - /* !!! 30-Nov-2006, TSa: Due to co-variance between Appendable and - * Writer, this would not compile with javac 1.5, in 1.4 mode - * (source and target set to "1.4". Not a huge deal, but since - * the base impl is just fine, no point in overriding it. - */ - /* - public Writer append(char c) - throws IOException - // note: this is a JDK 1.5 method - { - write(c); - return this; - } - */ - - public void close() throws IOException - { - _close(mAutoCloseOutput); - } - - public void flush() - throws IOException - { - if (mOutPtr > 0 && mOutBuffer != null) { - mOut.write(mOutBuffer, 0, mOutPtr); - mOutPtr = 0; - } - mOut.flush(); - } - - public void write(char[] cbuf) - throws IOException - { - write(cbuf, 0, cbuf.length); - } - - public void write(char[] cbuf, int off, int len) - throws IOException - { - if (len < 2) { - if (len == 1) { - write(cbuf[off]); - } - return; - } - - // First: do we have a leftover surrogate to deal with? - if (mSurrogate > 0) { - char second = cbuf[off++]; - --len; - write(_convertSurrogate(second)); - // will have at least one more char - } - - int outPtr = mOutPtr; - byte[] outBuf = mOutBuffer; - int outBufLast = mOutBufferLast; // has 4 'spare' bytes - - // All right; can just loop it nice and easy now: - len += off; // len will now be the end of input buffer - - output_loop: - for (; off < len; ) { - /* First, let's ensure we can output at least 4 bytes - * (longest UTF-8 encoded codepoint): - */ - if (outPtr >= outBufLast) { - mOut.write(outBuf, 0, outPtr); - outPtr = 0; - } - - int c = cbuf[off++]; - // And then see if we have an Ascii char: - if (c < 0x80) { // If so, can do a tight inner loop: - outBuf[outPtr++] = (byte)c; - // Let's calc how many ascii chars we can copy at most: - int maxInCount = (len - off); - int maxOutCount = (outBufLast - outPtr); - - if (maxInCount > maxOutCount) { - maxInCount = maxOutCount; - } - maxInCount += off; - ascii_loop: - while (true) { - if (off >= maxInCount) { // done with max. ascii seq - continue output_loop; - } - c = cbuf[off++]; - if (c >= 0x80) { - break ascii_loop; - } - outBuf[outPtr++] = (byte) c; - } - } - - // Nope, multi-byte: - if (c < 0x800) { // 2-byte - outBuf[outPtr++] = (byte) (0xc0 | (c >> 6)); - outBuf[outPtr++] = (byte) (0x80 | (c & 0x3f)); - } else { // 3 or 4 bytes - // Surrogates? - if (c < SURR1_FIRST || c > SURR2_LAST) { - outBuf[outPtr++] = (byte) (0xe0 | (c >> 12)); - outBuf[outPtr++] = (byte) (0x80 | ((c >> 6) & 0x3f)); - outBuf[outPtr++] = (byte) (0x80 | (c & 0x3f)); - continue; - } - // Yup, a surrogate: - if (c > SURR1_LAST) { // must be from first range - mOutPtr = outPtr; - throwIllegal(c); - } - mSurrogate = c; - // and if so, followed by another from next range - if (off >= len) { // unless we hit the end? - break; - } - c = _convertSurrogate(cbuf[off++]); - if (c > 0x10FFFF) { // illegal, as per RFC 3629 - mOutPtr = outPtr; - throwIllegal(c); - } - outBuf[outPtr++] = (byte) (0xf0 | (c >> 18)); - outBuf[outPtr++] = (byte) (0x80 | ((c >> 12) & 0x3f)); - outBuf[outPtr++] = (byte) (0x80 | ((c >> 6) & 0x3f)); - outBuf[outPtr++] = (byte) (0x80 | (c & 0x3f)); - } - } - mOutPtr = outPtr; - } - - public void write(int c) - throws IOException - { - // First; do we have a left over surrogate? - if (mSurrogate > 0) { - c = _convertSurrogate(c); - // If not, do we start with a surrogate? - } else if (c >= SURR1_FIRST && c <= SURR2_LAST) { - // Illegal to get second part without first: - if (c > SURR1_LAST) { - throwIllegal(c); - } - // First part just needs to be held for now - mSurrogate = c; - return; - } - - if (mOutPtr >= mOutBufferLast) { // let's require enough room, first - mOut.write(mOutBuffer, 0, mOutPtr); - mOutPtr = 0; - } - - if (c < 0x80) { // ascii - mOutBuffer[mOutPtr++] = (byte) c; - } else { - int ptr = mOutPtr; - if (c < 0x800) { // 2-byte - mOutBuffer[ptr++] = (byte) (0xc0 | (c >> 6)); - mOutBuffer[ptr++] = (byte) (0x80 | (c & 0x3f)); - } else if (c <= 0xFFFF) { // 3 bytes - mOutBuffer[ptr++] = (byte) (0xe0 | (c >> 12)); - mOutBuffer[ptr++] = (byte) (0x80 | ((c >> 6) & 0x3f)); - mOutBuffer[ptr++] = (byte) (0x80 | (c & 0x3f)); - } else { // 4 bytes - if (c > 0x10FFFF) { // illegal, as per RFC 3629 - throwIllegal(c); - } - mOutBuffer[ptr++] = (byte) (0xf0 | (c >> 18)); - mOutBuffer[ptr++] = (byte) (0x80 | ((c >> 12) & 0x3f)); - mOutBuffer[ptr++] = (byte) (0x80 | ((c >> 6) & 0x3f)); - mOutBuffer[ptr++] = (byte) (0x80 | (c & 0x3f)); - } - mOutPtr = ptr; - } - } - - public void write(String str) - throws IOException - { - write(str, 0, str.length()); - } - - public void write(String str, int off, int len) - throws IOException - { - if (len < 2) { - if (len == 1) { - write(str.charAt(off)); - } - return; - } - - // First: do we have a leftover surrogate to deal with? - if (mSurrogate > 0) { - char second = str.charAt(off++); - --len; - write(_convertSurrogate(second)); - // will have at least one more char (case of 1 char was checked earlier on) - } - - int outPtr = mOutPtr; - byte[] outBuf = mOutBuffer; - int outBufLast = mOutBufferLast; // has 4 'spare' bytes - - // All right; can just loop it nice and easy now: - len += off; // len will now be the end of input buffer - - output_loop: - for (; off < len; ) { - /* First, let's ensure we can output at least 4 bytes - * (longest UTF-8 encoded codepoint): - */ - if (outPtr >= outBufLast) { - mOut.write(outBuf, 0, outPtr); - outPtr = 0; - } - - int c = str.charAt(off++); - // And then see if we have an Ascii char: - if (c < 0x80) { // If so, can do a tight inner loop: - outBuf[outPtr++] = (byte)c; - // Let's calc how many ascii chars we can copy at most: - int maxInCount = (len - off); - int maxOutCount = (outBufLast - outPtr); - - if (maxInCount > maxOutCount) { - maxInCount = maxOutCount; - } - maxInCount += off; - ascii_loop: - while (true) { - if (off >= maxInCount) { // done with max. ascii seq - continue output_loop; - } - c = str.charAt(off++); - if (c >= 0x80) { - break ascii_loop; - } - outBuf[outPtr++] = (byte) c; - } - } - - // Nope, multi-byte: - if (c < 0x800) { // 2-byte - outBuf[outPtr++] = (byte) (0xc0 | (c >> 6)); - outBuf[outPtr++] = (byte) (0x80 | (c & 0x3f)); - } else { // 3 or 4 bytes - // Surrogates? - if (c < SURR1_FIRST || c > SURR2_LAST) { - outBuf[outPtr++] = (byte) (0xe0 | (c >> 12)); - outBuf[outPtr++] = (byte) (0x80 | ((c >> 6) & 0x3f)); - outBuf[outPtr++] = (byte) (0x80 | (c & 0x3f)); - continue; - } - // Yup, a surrogate: - if (c > SURR1_LAST) { // must be from first range - mOutPtr = outPtr; - throwIllegal(c); - } - mSurrogate = c; - // and if so, followed by another from next range - if (off >= len) { // unless we hit the end? - break; - } - c = _convertSurrogate(str.charAt(off++)); - if (c > 0x10FFFF) { // illegal, as per RFC 3629 - mOutPtr = outPtr; - throwIllegal(c); - } - outBuf[outPtr++] = (byte) (0xf0 | (c >> 18)); - outBuf[outPtr++] = (byte) (0x80 | ((c >> 12) & 0x3f)); - outBuf[outPtr++] = (byte) (0x80 | ((c >> 6) & 0x3f)); - outBuf[outPtr++] = (byte) (0x80 | (c & 0x3f)); - } - } - mOutPtr = outPtr; - } - - /* - //////////////////////////////////////////////////////////// - // Internal methods - //////////////////////////////////////////////////////////// - */ - - private final void _close(boolean forceClosing) - throws IOException - { - byte[] buf = mOutBuffer; - if (buf != null) { - mOutBuffer = null; - if (mOutPtr > 0) { - mOut.write(buf, 0, mOutPtr); - mOutPtr = 0; - } - if (mConfig != null) { - mConfig.freeFullBBuffer(buf); - } - } - - if (forceClosing) { - mOut.close(); - } - - /* Let's 'flush' orphan surrogate, no matter what; but only - * after cleanly closing everything else. - */ - int code = mSurrogate; - if (code > 0) { - mSurrogate = 0; - throwIllegal(code); - } - } - - /** - * Method called to calculate UTF codepoint, from a surrogate pair. - */ - private final int _convertSurrogate(int secondPart) - throws IOException - { - int firstPart = mSurrogate; - mSurrogate = 0; - - // Ok, then, is the second part valid? - if (secondPart < SURR2_FIRST || secondPart > SURR2_LAST) { - throw new IOException("Broken surrogate pair: first char 0x"+Integer.toHexString(firstPart)+", second 0x"+Integer.toHexString(secondPart)+"; illegal combination"); - } - return 0x10000 + ((firstPart - SURR1_FIRST) << 10) + (secondPart - SURR2_FIRST); - } - - private void throwIllegal(int code) - throws IOException - { - if (code > 0x10FFFF) { // over max? - throw new IOException("Illegal character point (0x"+Integer.toHexString(code)+") to output; max is 0x10FFFF as per RFC 3629"); - } - if (code >= SURR1_FIRST) { - if (code <= SURR1_LAST) { // Unmatched first part (closing without second part?) - throw new IOException("Unmatched first part of surrogate pair (0x"+Integer.toHexString(code)+")"); - } - throw new IOException("Unmatched second part of surrogate pair (0x"+Integer.toHexString(code)+")"); - } - - // should we ever get this? - throw new IOException("Illegal character point (0x"+Integer.toHexString(code)+") to output"); - } -} diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/io/WstxInputData.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/io/WstxInputData.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/io/WstxInputData.java 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/io/WstxInputData.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,469 +0,0 @@ -/* Woodstox XML processor - * - * Copyright (c) 2004 Tatu Saloranta, tatu.saloranta@iki.fi - * - * Licensed under the License specified in file LICENSE, included with - * the source code. - * You may not use this file except in compliance with the License. - * - * 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 com.ctc.wstx.io; - -import com.ctc.wstx.util.XmlChars; - -/** - * Base class used by readers (specifically, by - * {@link com.ctc.wstx.sr.StreamScanner}, and its sub-classes) - * to encapsulate input buffer portion of the class. Philosophically - * this should probably be done via containment (composition), not - * sub-classing but for performance reason, this "core" class is generally - * extended from instead. - *

- * Main reason for the input data portion to be factored out of main - * class is that this way it can also be passed to nested input handling - * Objects, which can then manipulate input buffers of the caller, - * efficiently. - */ -public class WstxInputData -{ - // // // Some well-known chars: - - /** - * Null-character is used as return value from some method(s), since - * it is not a legal character in an XML document. - */ - public final static char CHAR_NULL = '\u0000'; - public final static char INT_NULL = 0; - - public final static char CHAR_SPACE = (char) 0x0020; - public final static char INT_SPACE = 0x0020; - - /** - * This constant defines the highest Unicode character allowed - * in XML content. - */ - public final static int MAX_UNICODE_CHAR = 0x10FFFF; - - /* - //////////////////////////////////////////////////// - // Character validity constants, structs - //////////////////////////////////////////////////// - */ - - /** - * We will only use validity array for first 256 characters, mostly - * because after those characters it's easier to do fairly simple - * block checks. - */ - private final static int VALID_CHAR_COUNT = 0x100; - - // These are the same for both 1.0 and 1.1... -// private final static int FIRST_VALID_FOR_FIRST = 0x0041; // 'A' -// private final static int FIRST_VALID_FOR_REST = 0x002D; // '.' - - private final static byte NAME_CHAR_INVALID_B = (byte) 0; - private final static byte NAME_CHAR_ALL_VALID_B = (byte) 1; - private final static byte NAME_CHAR_VALID_NONFIRST_B = (byte) -1; - - private final static byte[] sCharValidity = new byte[VALID_CHAR_COUNT]; - - static { - /* First, since all valid-as-first chars are also valid-as-other chars, - * we'll initialize common chars: - */ - sCharValidity['_'] = NAME_CHAR_ALL_VALID_B; - for (int i = 0, last = ('z' - 'a'); i <= last; ++i) { - sCharValidity['A' + i] = NAME_CHAR_ALL_VALID_B; - sCharValidity['a' + i] = NAME_CHAR_ALL_VALID_B; - } - // not all are fully valid, but - for (int i = 0xC0; i < VALID_CHAR_COUNT; ++i) { - sCharValidity[i] = NAME_CHAR_ALL_VALID_B; - } - // ... now we can 'revert' ones not fully valid: - sCharValidity[0xD7] = NAME_CHAR_INVALID_B; - sCharValidity[0xF7] = NAME_CHAR_INVALID_B; - - /* And then we can proceed with ones only valid-as-other. - */ - sCharValidity['-'] = NAME_CHAR_VALID_NONFIRST_B; - sCharValidity['.'] = NAME_CHAR_VALID_NONFIRST_B; - sCharValidity[0xB7] = NAME_CHAR_VALID_NONFIRST_B; - for (int i = '0'; i <= '9'; ++i) { - sCharValidity[i] = NAME_CHAR_VALID_NONFIRST_B; - } - } - - /** - * Public identifiers only use 7-bit ascii range. - */ - private final static int VALID_PUBID_CHAR_COUNT = 0x80; - private final static byte[] sPubidValidity = new byte[VALID_PUBID_CHAR_COUNT]; -// private final static byte PUBID_CHAR_INVALID_B = (byte) 0; - private final static byte PUBID_CHAR_VALID_B = (byte) 1; - static { - for (int i = 0, last = ('z' - 'a'); i <= last; ++i) { - sPubidValidity['A' + i] = PUBID_CHAR_VALID_B; - sPubidValidity['a' + i] = PUBID_CHAR_VALID_B; - } - for (int i = '0'; i <= '9'; ++i) { - sPubidValidity[i] = PUBID_CHAR_VALID_B; - } - - // 3 main white space types are valid - sPubidValidity[0x0A] = PUBID_CHAR_VALID_B; - sPubidValidity[0x0D] = PUBID_CHAR_VALID_B; - sPubidValidity[0x20] = PUBID_CHAR_VALID_B; - - // And many of punctuation/separator ascii chars too: - sPubidValidity['-'] = PUBID_CHAR_VALID_B; - sPubidValidity['\''] = PUBID_CHAR_VALID_B; - sPubidValidity['('] = PUBID_CHAR_VALID_B; - sPubidValidity[')'] = PUBID_CHAR_VALID_B; - sPubidValidity['+'] = PUBID_CHAR_VALID_B; - sPubidValidity[','] = PUBID_CHAR_VALID_B; - sPubidValidity['.'] = PUBID_CHAR_VALID_B; - sPubidValidity['/'] = PUBID_CHAR_VALID_B; - sPubidValidity[':'] = PUBID_CHAR_VALID_B; - sPubidValidity['='] = PUBID_CHAR_VALID_B; - sPubidValidity['?'] = PUBID_CHAR_VALID_B; - sPubidValidity[';'] = PUBID_CHAR_VALID_B; - sPubidValidity['!'] = PUBID_CHAR_VALID_B; - sPubidValidity['*'] = PUBID_CHAR_VALID_B; - sPubidValidity['#'] = PUBID_CHAR_VALID_B; - sPubidValidity['@'] = PUBID_CHAR_VALID_B; - sPubidValidity['$'] = PUBID_CHAR_VALID_B; - sPubidValidity['_'] = PUBID_CHAR_VALID_B; - sPubidValidity['%'] = PUBID_CHAR_VALID_B; - } - - /* - //////////////////////////////////////////////////// - // Configuration - //////////////////////////////////////////////////// - */ - - /** - * Flag that indicates whether XML content is to be treated as per - * XML 1.1 specification or not (if not, it'll use xml 1.0). - */ - protected boolean mXml11 = false; - - /* - //////////////////////////////////////////////////// - // Current input data - //////////////////////////////////////////////////// - */ - - /** - * Current buffer from which data is read; generally data is read into - * buffer from input source, but not always (especially when using nested - * input contexts when expanding parsed entity references etc). - */ - protected char[] mInputBuffer; - - /** - * Pointer to next available character in buffer - */ - protected int mInputPtr = 0; - - /** - * Index of character after last available one in the buffer. - */ - protected int mInputEnd = 0; - - /* - //////////////////////////////////////////////////// - // Current input location information - //////////////////////////////////////////////////// - */ - - /** - * Number of characters that were contained in previous blocks - * (blocks that were already processed prior to the current buffer). - */ - protected long mCurrInputProcessed = 0L; - - /** - * Current row location of current point in input buffer, starting - * from 1 - */ - protected int mCurrInputRow = 1; - - /** - * Current index of the first character of the current row in input - * buffer. Needed to calculate column position, if necessary; benefit - * of not having column itself is that this only has to be updated - * once per line. - */ - protected int mCurrInputRowStart = 0; - - /* - //////////////////////////////////////////////////// - // Life-cycle - //////////////////////////////////////////////////// - */ - - protected WstxInputData() { - } - - /** - * Note: Only public due to sub-classes needing to call this on - * base class instance from different package (confusing?) - */ - public void copyBufferStateFrom(WstxInputData src) - { - mInputBuffer = src.mInputBuffer; - mInputPtr = src.mInputPtr; - mInputEnd = src.mInputEnd; - - mCurrInputProcessed = src.mCurrInputProcessed; - mCurrInputRow = src.mCurrInputRow; - mCurrInputRowStart = src.mCurrInputRowStart; - } - - /* - //////////////////////////////////////////////////// - // Public/package API, character classes - //////////////////////////////////////////////////// - */ - - /** - * Method that can be used to check whether specified character - * is a valid first character of an XML 1.0/1.1 name; except that - * colon (:) is not recognized as a start char here: caller has - * to verify it separately (since it generally affects namespace - * mapping of a qualified name). - */ - protected final boolean isNameStartChar(char c) - { - /* First, let's handle 7-bit ascii range (identical between xml - * 1.0 and 1.1) - */ - if (c <= 0x7A) { // 'z' or earlier - if (c >= 0x61) { // 'a' - 'z' are ok - return true; - } - if (c < 0x41) { // before 'A' just white space - return false; - } - return (c <= 0x5A) || (c == '_'); // 'A' - 'Z' and '_' are ok - } - /* Ok, otherwise need to use a big honking bit sets... which - * differ between 1.0 and 1.1 - */ - return mXml11 ? XmlChars.is11NameStartChar(c) : XmlChars.is10NameStartChar(c); - } - - /** - * Method that can be used to check whether specified character - * is a valid character of an XML 1.0/1.1 name as any other char than - * the first one; except that colon (:) is not recognized as valid here: - * caller has to verify it separately (since it generally affects namespace - * mapping of a qualified name). - */ - protected final boolean isNameChar(char c) - { - // First, let's handle 7-bit ascii range - if (c <= 0x7A) { // 'z' or earlier - if (c >= 0x61) { // 'a' - 'z' are ok - return true; - } - if (c <= 0x5A) { - if (c >= 0x41) { // 'A' - 'Z' ok too - return true; - } - // As are 0-9, '.' and '-' - return (c >= 0x30 && c <= 0x39) || (c == '.') || (c == '-'); - } - return (c == 0x5F); // '_' is ok too - } - return mXml11 ? XmlChars.is11NameChar(c) : XmlChars.is10NameChar(c); - } - - public final static boolean isNameStartChar(char c, boolean nsAware, boolean xml11) - { - /* First, let's handle 7-bit ascii range (identical between xml - * 1.0 and 1.1) - */ - if (c <= 0x7A) { // 'z' or earlier - if (c >= 0x61) { // 'a' - 'z' are ok - return true; - } - if (c < 0x41) { // before 'A' just white space (and colon) - if (c == ':' && !nsAware) { - return true; - } - return false; - } - return (c <= 0x5A) || (c == '_'); // 'A' - 'Z' and '_' are ok - } - /* Ok, otherwise need to use a big honking bit sets... which - * differ between 1.0 and 1.1 - */ - return xml11 ? XmlChars.is11NameStartChar(c) : XmlChars.is10NameStartChar(c); - } - - public final static boolean isNameChar(char c, boolean nsAware, boolean xml11) - { - // First, let's handle 7-bit ascii range - if (c <= 0x7A) { // 'z' or earlier - if (c >= 0x61) { // 'a' - 'z' are ok - return true; - } - if (c <= 0x5A) { - if (c >= 0x41) { // 'A' - 'Z' ok too - return true; - } - // As are 0-9, '.' and '-' - return (c >= 0x30 && c <= 0x39) || (c == '.') || (c == '-') - || (c == ':' && !nsAware); - } - return (c == 0x5F); // '_' is ok too - } - return xml11 ? XmlChars.is11NameChar(c) : XmlChars.is10NameChar(c); - } - - /** - * Method that can be called to check whether given String contains - * any characters that are not legal XML names. - * - * @return Index of the first illegal xml name characters, if any; - * -1 if the name is completely legal - */ - public final static int findIllegalNameChar(String name, boolean nsAware, boolean xml11) - { - int len = name.length(); - if (len < 1) { - return -1; - } - - char c = name.charAt(0); - - // First char legal? - if (c <= 0x7A) { // 'z' or earlier - if (c < 0x61) { // 'a' - 'z' (0x61 - 0x7A) are ok - if (c < 0x41) { // before 'A' just white space (except colon) - if (c != ':' || nsAware) { // ':' == 0x3A - return 0; - } - } else if ((c > 0x5A) && (c != '_')) { - // 'A' - 'Z' and '_' are ok - return 0; - } - } - } else { - if (xml11) { - if (!XmlChars.is11NameStartChar(c)) { - return 0; - } - } else { - if (!XmlChars.is10NameStartChar(c)) { - return 0; - } - } - } - - for (int i = 1; i < len; ++i) { - c = name.charAt(i); - if (c <= 0x7A) { // 'z' or earlier - if (c >= 0x61) { // 'a' - 'z' are ok - continue; - } - if (c <= 0x5A) { - if (c >= 0x41) { // 'A' - 'Z' ok too - continue; - } - // As are 0-9, '.' and '-' - if ((c >= 0x30 && c <= 0x39) || (c == '.') || (c == '-')) { - continue; - } - // And finally, colon, in non-ns-aware mode - if (c == ':' && !nsAware) { // ':' == 0x3A - continue; - } - } else if (c == 0x5F) { // '_' is ok too - continue; - } - } else { - if (xml11) { - if (XmlChars.is11NameChar(c)) { - continue; - } - } else { - if (XmlChars.is10NameChar(c)) { - continue; - } - } - } - return i; - } - - return -1; - } - - public final static int findIllegalNmtokenChar(String nmtoken, boolean nsAware, boolean xml11) - { - int len = nmtoken.length(); - // No special handling for the first char, just the loop - for (int i = 1; i < len; ++i) { - char c = nmtoken.charAt(i); - if (c <= 0x7A) { // 'z' or earlier - if (c >= 0x61) { // 'a' - 'z' are ok - continue; - } - if (c <= 0x5A) { - if (c >= 0x41) { // 'A' - 'Z' ok too - continue; - } - // As are 0-9, '.' and '-' - if ((c >= 0x30 && c <= 0x39) || (c == '.') || (c == '-')) { - continue; - } - // And finally, colon, in non-ns-aware mode - if (c == ':' && !nsAware) { // ':' == 0x3A - continue; - } - } else if (c == 0x5F) { // '_' is ok too - continue; - } - } else { - if (xml11) { - if (XmlChars.is11NameChar(c)) { - continue; - } - } else { - if (XmlChars.is10NameChar(c)) { - continue; - } - } - } - return i; - } - return -1; - } - - public final static boolean isSpaceChar(char c) - { - return (c <= CHAR_SPACE); - } - - public static String getCharDesc(char c) - { - int i = (int) c; - if (Character.isISOControl(c)) { - return "(CTRL-CHAR, code "+i+")"; - } - if (i > 255) { - return "'"+c+"' (code "+i+" / 0x"+Integer.toHexString(i)+")"; - } - return "'"+c+"' (code "+i+")"; - } - -} diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/io/WstxInputLocation.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/io/WstxInputLocation.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/io/WstxInputLocation.java 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/io/WstxInputLocation.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,176 +0,0 @@ -/* Woodstox XML processor - * - * Copyright (c) 2004 Tatu Saloranta, tatu.saloranta@iki.fi - * - * Licensed under the License specified in file LICENSE, included with - * the source code. - * You may not use this file except in compliance with the License. - * - * 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 com.ctc.wstx.io; - -import java.io.Serializable; -import javax.xml.stream.Location; - -import org.codehaus.stax2.XMLStreamLocation2; - -import com.ctc.wstx.util.StringUtil; - -/** - * Basic implementation of {@link Location}, used by Wstx readers. - */ -public class WstxInputLocation - implements Serializable, XMLStreamLocation2 -{ - private static final long serialVersionUID = 1L; - - private final static WstxInputLocation sEmptyLocation - = new WstxInputLocation(null, "", "", -1, -1, -1); - - /** - * Enclosing (parent) input location; location from which current - * location is derived. - */ - final protected WstxInputLocation mContext; - - final protected String mPublicId, mSystemId; - - final protected int mCharOffset; - final protected int mCol, mRow; - - transient protected String mDesc = null; - - /** - * @param ctxt Enclosing input location, if any - */ - public WstxInputLocation(WstxInputLocation ctxt, - String pubId, String sysId, - int charOffset, int row, int col) - { - mContext = ctxt; - mPublicId = pubId; - mSystemId = sysId; - /* Overflow? Can obviously only handle limited range of overflows, - * but let's do that at least? - */ - mCharOffset = (charOffset < 0) ? Integer.MAX_VALUE : charOffset; - mCol = col; - mRow = row; - } - - public static WstxInputLocation getEmptyLocation() { - return sEmptyLocation; - } - - public int getCharacterOffset() { return mCharOffset; } - public int getColumnNumber() { return mCol; } - public int getLineNumber() { return mRow; } - - public String getPublicId() { return mPublicId; } - public String getSystemId() { return mSystemId; } - - /* - //////////////////////////////////////////////////////// - // StAX 2 API: - //////////////////////////////////////////////////////// - */ - - public XMLStreamLocation2 getContext() { return mContext; } - - /* - //////////////////////////////////////////////////////// - // Overridden standard methods - //////////////////////////////////////////////////////// - */ - - public String toString() - { - if (mDesc == null) { - StringBuffer sb; - if (mContext != null) { - sb = new StringBuffer(200); - } else { - sb = new StringBuffer(80); - } - appendDesc(sb); - mDesc = sb.toString(); - } - return mDesc; - } - - public int hashCode() { - return mCharOffset ^ mRow ^ mCol + (mCol << 3); - } - - public boolean equals(Object o) { - if (!(o instanceof Location)) { - return false; - } - Location other = (Location) o; - // char offset should be good enough, without row/col: - if (other.getCharacterOffset() != getCharacterOffset()) { - return false; - } - String otherPub = other.getPublicId(); - if (otherPub == null) { - otherPub = ""; - } - if (!otherPub.equals(mPublicId)) { - return false; - } - String otherSys = other.getSystemId(); - if (otherSys == null) { - otherSys = ""; - } - return otherSys.equals(mSystemId); - } - - /* - //////////////////////////////////////////////////////// - // Internal methods: - //////////////////////////////////////////////////////// - */ - - private void appendDesc(StringBuffer sb) - { - String srcId; - - if (mSystemId != null) { - sb.append("[row,col,system-id]: "); - srcId = mSystemId; - } else if (mPublicId != null) { - sb.append("[row,col,public-id]: "); - srcId = mPublicId; - } else { - sb.append("[row,col {unknown-source}]: "); - srcId = null; - } - sb.append('['); - sb.append(mRow); - sb.append(','); - sb.append(mCol); - - // Uncomment for testing, to see the char offset: - //sb.append(" #").append(mCharOffset); - //sb.append("{").append(System.identityHashCode(this)).append("}"); - - if (srcId != null) { - sb.append(','); - sb.append('"'); - sb.append(srcId); - sb.append('"'); - } - sb.append(']'); - if (mContext != null) { - StringUtil.appendLF(sb); - sb.append(" from "); - mContext.appendDesc(sb); - } - } -} diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/io/WstxInputSource.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/io/WstxInputSource.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/io/WstxInputSource.java 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/io/WstxInputSource.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,230 +0,0 @@ -/* Woodstox XML processor - * - * Copyright (c) 2004- Tatu Saloranta, tatu.saloranta@iki.fi - * - * Licensed under the License specified in file LICENSE, included with - * the source code. - * You may not use this file except in compliance with the License. - * - * 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 com.ctc.wstx.io; - -import java.io.IOException; -import java.net.URL; - -import javax.xml.stream.XMLStreamException; - -/** - * Interface that defines API actual parsers (stream readers) - * can use to read input from various input sources. - * Needed to abstract out details of getting input from primary input - * files, secondary (potentially cached) referenced documents, and from - * parsed entities, as well as for allowing hierarchic location - * information for error reporting. - */ -public abstract class WstxInputSource -{ - /** - * Parent in input source stack - */ - protected final WstxInputSource mParent; - - /** - * Name/id of the entity that was expanded to produce this input source; - * null if not entity-originated. Used for catching recursive expansions - * of entities. - */ - protected final String mFromEntity; - - /** - * Scope of the reader when this entity was initially expanded. Snapshot - * that will generally be used by the reader to match scoping - * limitations, such as proper nesting entity expansion with respect - * to element and declaration nesting. - */ - protected int mScopeId = 0; - - /* - ////////////////////////////////////////////////////////// - // Life-cycle: - ////////////////////////////////////////////////////////// - */ - - protected WstxInputSource(WstxInputSource parent, String fromEntity) - { - mParent = parent; - mFromEntity = fromEntity; - } - - /** - * Method that can be called to override originally defined source. - * - * @param url New base URL to set; may be null. - * - * @since 4.0 - */ - public abstract void overrideSource(URL url); - - /* - ////////////////////////////////////////////////////////// - // Basic accessors: - ////////////////////////////////////////////////////////// - */ - - public final WstxInputSource getParent() { - return mParent; - } - - /** - * Method that checks if this input source expanded from the specified - * entity id, directly or by ancestor. - *

- * Note that entity ids are expected to have been interned (using - * whatever uniqueness mechanism used), and thus can be simply - * identity checked. - */ - public boolean isOrIsExpandedFrom(String entityId) - { - if (entityId != null) { // should always be true - WstxInputSource curr = this; - while (curr != null) { - if (entityId == curr.mFromEntity) { - return true; - } - curr = curr.mParent; - } - } - return false; - } - - /** - * @return True, if this input source was directly expanded from an - * internal entity (general, parsed); false if not (from external - * entity, DTD ext. subset, main document) - */ - public abstract boolean fromInternalEntity(); - - /* - ////////////////////////////////////////////////////////// - // Location info: - ////////////////////////////////////////////////////////// - */ - - public abstract URL getSource(); - - public abstract String getPublicId(); - - public abstract String getSystemId(); - - /** - * Method usually called to get a parent location for another input - * source. Works since at this point context (line, row, chars) information - * has already been saved to this object. - */ - protected abstract WstxInputLocation getLocation(); - - public abstract WstxInputLocation getLocation(long total, int row, int col); - - public String getEntityId() { return mFromEntity; } - - public int getScopeId() { return mScopeId; } - - /* - ////////////////////////////////////////////////////////// - // Actual input handling - ////////////////////////////////////////////////////////// - */ - - /** - * Method called by Reader when current input has changed to come - * from this input source. Should reset/initialize input location - * information Reader keeps, for error messages to work ok. - * - * @param reader Reader whose data structures are to be used for - * returning data read - * @param currScopeId - */ - public final void initInputLocation(WstxInputData reader, int currScopeId) { - mScopeId = currScopeId; - doInitInputLocation(reader); - } - - protected abstract void doInitInputLocation(WstxInputData reader); - - /** - * Method called to read at least one more char from input source, and - * update input data appropriately. - * - * @return Number of characters read from the input source (at least 1), - * if it had any input; -1 if input source has no more input. - */ - public abstract int readInto(WstxInputData reader) - throws IOException, XMLStreamException; - - /** - * Method called by reader when it has to have at least specified number - * of consequtive input characters in its buffer, and it currently does - * not have. If so, it asks input source to do whatever it has to do - * to try to get more data, if possible (including moving stuff in - * input buffer if necessary and possible). - * - * @return True if input source was able to provide specific number of - * characters or more; false if not. In latter case, source is free - * to return zero or more characters any way. - */ - public abstract boolean readMore(WstxInputData reader, int minAmount) - throws IOException, XMLStreamException; - - /** - * Method Reader calls when this input source is being stored, when - * a nested input source gets used instead (due to entity expansion). - * Needs to get location info from Reader and store it in this Object. - */ - public abstract void saveContext(WstxInputData reader); - - /** - * Method Reader calls when this input source is resumed as the - * current source. Needs to update Reader's input location data - * used for error messages etc. - */ - public abstract void restoreContext(WstxInputData reader); - - /** - * Method reader calls for this input source when it has encountered - * EOF. This may or may not close the underlying stream/reader; what - * happens depends on configuration - */ - public abstract void close() throws IOException; - - /** - * Method reader MAY call to force full closing of the underlying - * input stream(s)/reader(s). No checks are done regarding configuration, - * but input source object is to deal gracefully with multiple calls - * (ie. it's not an error for reader to call this more than once). - */ - public abstract void closeCompletely() throws IOException; - - /* - ////////////////////////////////////////////////////////// - // Overridden standard methods: - ////////////////////////////////////////////////////////// - */ - - public String toString() { - StringBuffer sb = new StringBuffer(80); - sb.append("'); - return sb.toString(); - } -} diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/msv/AttributeProxy.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/msv/AttributeProxy.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/msv/AttributeProxy.java 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/msv/AttributeProxy.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,137 +0,0 @@ -/* Woodstox XML processor - * - * Copyright (c) 2004- Tatu Saloranta, tatu.saloranta@iki.fi - * - * Licensed under the License specified in the file LICENSE which is - * included with the source code. - * You may not use this file except in compliance with the License. - * - * 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 com.ctc.wstx.msv; - -import org.codehaus.stax2.validation.ValidationContext; - -/** - * This is an implementation of SAX Attributes interface, that proxies - * requests to the {@link ValidationContext}. - * It is needed by some MSV components (specifically, W3C Schema Validator) - * for limited access to attribute values during start element validation. - */ -final class AttributeProxy - implements org.xml.sax.Attributes -{ - private final ValidationContext mContext; - - public AttributeProxy(ValidationContext ctxt) - { - mContext = ctxt; - } - - /* - /////////////////////////////////////////////// - // Attributes implementation - /////////////////////////////////////////////// - */ - - public int getIndex(String qName) - { - int cix = qName.indexOf(':'); - int acount = mContext.getAttributeCount(); - if (cix < 0) { // no prefix - for (int i = 0; i < acount; ++i) { - if (qName.equals(mContext.getAttributeLocalName(i))) { - String prefix = mContext.getAttributePrefix(i); - if (prefix == null || prefix.length() == 0) { - return i; - } - } - } - } else { - String prefix = qName.substring(0, cix); - String ln = qName.substring(cix+1); - - for (int i = 0; i < acount; ++i) { - if (ln.equals(mContext.getAttributeLocalName(i))) { - String p2 = mContext.getAttributePrefix(i); - if (p2 != null && prefix.equals(p2)) { - return i; - } - } - } - } - return -1; - } - - public int getIndex(String uri, String localName) - { - return mContext.findAttributeIndex(uri, localName); - } - - public int getLength() - { - return mContext.getAttributeCount(); - } - - public String getLocalName(int index) - { - return mContext.getAttributeLocalName(index); - } - - public String getQName(int index) - { - String prefix = mContext.getAttributePrefix(index); - String ln = mContext.getAttributeLocalName(index); - - if (prefix == null || prefix.length() == 0) { - return ln; - } - StringBuffer sb = new StringBuffer(prefix.length() + 1 + ln.length()); - sb.append(prefix); - sb.append(':'); - sb.append(ln); - return sb.toString(); - } - - public String getType(int index) - { - return mContext.getAttributeType(index); - } - - public String getType(String qName) - { - return getType(getIndex(qName)); - } - - public String getType(String uri, String localName) - { - return getType(getIndex(uri, localName)); - } - - public String getURI(int index) - { - return mContext.getAttributeNamespace(index); - } - - public String getValue(int index) - { - return mContext.getAttributeValue(index); - } - - public String getValue(String qName) - { - return getValue(getIndex(qName)); - } - - public String getValue(String uri, String localName) - { - return mContext.getAttributeValue(uri, localName); - } -} - - diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/msv/BaseSchemaFactory.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/msv/BaseSchemaFactory.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/msv/BaseSchemaFactory.java 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/msv/BaseSchemaFactory.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,176 +0,0 @@ -/* Woodstox XML processor - * - * Copyright (c) 2004- Tatu Saloranta, tatu.saloranta@iki.fi - * - * Licensed under the License specified in the file LICENSE which is - * included with the source code. - * You may not use this file except in compliance with the License. - * - * 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 com.ctc.wstx.msv; - -import java.io.*; -import java.net.URL; - -import javax.xml.parsers.SAXParserFactory; -import javax.xml.stream.*; - -import org.xml.sax.InputSource; -import org.xml.sax.Locator; - -import org.codehaus.stax2.validation.*; - -import com.ctc.wstx.api.ValidatorConfig; -import com.ctc.wstx.exc.WstxIOException; -import com.ctc.wstx.util.URLUtil; - -/** - * Shared base class extended by concrete schema factory implementations. - */ -public abstract class BaseSchemaFactory - extends XMLValidationSchemaFactory -{ - protected static SAXParserFactory sSaxFactory; - - /** - * Current configurations for this factory - */ - protected final ValidatorConfig mConfig; - - protected BaseSchemaFactory(String schemaType) - { - super(schemaType); - mConfig = ValidatorConfig.createDefaults(); - } - - /* - /////////////////////////////////////////////////////////////////////// - // Stax2, Configuration methods - /////////////////////////////////////////////////////////////////////// - */ - - public boolean isPropertySupported(String propName) - { - return mConfig.isPropertySupported(propName); - } - - public boolean setProperty(String propName, Object value) - { - return mConfig.setProperty(propName, value); - } - - public Object getProperty(String propName) - { - return mConfig.getProperty(propName); - } - - /* - /////////////////////////////////////////////////////////////////////// - // Stax2, Factory methods - /////////////////////////////////////////////////////////////////////// - */ - - public XMLValidationSchema createSchema(InputStream in, String encoding, - String publicId, String systemId) - throws XMLStreamException - { - InputSource src = new InputSource(in); - src.setEncoding(encoding); - src.setPublicId(publicId); - src.setSystemId(systemId); - return loadSchema(src, systemId); - } - - public XMLValidationSchema createSchema(Reader r, String publicId, - String systemId) - throws XMLStreamException - { - InputSource src = new InputSource(r); - src.setPublicId(publicId); - src.setSystemId(systemId); - return loadSchema(src, systemId); - } - - public XMLValidationSchema createSchema(URL url) - throws XMLStreamException - { - try { - InputStream in = URLUtil.inputStreamFromURL(url); - InputSource src = new InputSource(in); - src.setSystemId(url.toExternalForm()); - return loadSchema(src, url); - } catch (IOException ioe) { - throw new WstxIOException(ioe); - } - } - - public XMLValidationSchema createSchema(File f) - throws XMLStreamException - { - try { - return createSchema(f.toURL()); - } catch (IOException ioe) { - throw new WstxIOException(ioe); - } - } - - /* - /////////////////////////////////////////////////////////////////////// - // Methods sub-classes need to implement - /////////////////////////////////////////////////////////////////////// - */ - - protected abstract XMLValidationSchema loadSchema(InputSource src, Object sysRef) - throws XMLStreamException; - - /* - /////////////////////////////////////////////////////////////////////// - // Internal/package methods - /////////////////////////////////////////////////////////////////////// - */ - - /** - * We will essentially share a singleton sax parser factory; - * the reason being that constructing (or, rather, locating - * implementation class) is bit expensive. - */ - protected synchronized static SAXParserFactory getSaxFactory() - { - if (sSaxFactory == null) { - sSaxFactory = SAXParserFactory.newInstance(); - sSaxFactory.setNamespaceAware(true); - } - return sSaxFactory; - } - - /* - /////////////////////////////////////////////////////////////////////// - // Helper classes - /////////////////////////////////////////////////////////////////////// - */ - - final static class MyGrammarController - extends com.sun.msv.reader.util.IgnoreController - { - public String mErrorMsg = null; - - public MyGrammarController() { } - - //public void warning(Locator[] locs, String errorMessage) { } - - public void error(Locator[] locs, String msg, Exception nestedException ) - { - if (mErrorMsg == null) { - mErrorMsg = msg; - } else { - mErrorMsg = mErrorMsg + "; " + msg; - } - } - } -} diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/msv/GenericMsvValidator.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/msv/GenericMsvValidator.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/msv/GenericMsvValidator.java 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/msv/GenericMsvValidator.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,540 +0,0 @@ -/* Woodstox XML processor - * - * Copyright (c) 2004- Tatu Saloranta, tatu.saloranta@iki.fi - * - * Licensed under the License specified in the file LICENSE which is - * included with the source code. - * You may not use this file except in compliance with the License. - * - * 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 com.ctc.wstx.msv; - -import java.util.*; - -import javax.xml.stream.Location; -import javax.xml.stream.XMLStreamException; - -import org.codehaus.stax2.validation.*; - -import org.relaxng.datatype.Datatype; - -import com.sun.msv.grammar.IDContextProvider2; -import com.sun.msv.util.DatatypeRef; -import com.sun.msv.util.StartTagInfo; -import com.sun.msv.util.StringRef; -import com.sun.msv.verifier.Acceptor; -import com.sun.msv.verifier.DocumentDeclaration; -import com.sun.msv.verifier.regexp.StringToken; - -import com.ctc.wstx.util.ElementId; -import com.ctc.wstx.util.ElementIdMap; -import com.ctc.wstx.util.PrefixedName; -import com.ctc.wstx.util.TextAccumulator; - -/** - * Generic validator instance to be used for all Multi-Schema Validator - * backed implementations. A common class can be used since functionality - * is almost identical between variants (RNG, W3C SChema); minor - * differences that exist can be configured by settings provided. - *

- * Note about id context provider interface: while it'd be nice to - * separate that part out, it is unfortunately closely tied to the - * validation process. Hence it's directly implemented by this class. - */ -public final class GenericMsvValidator - extends XMLValidator - implements com.sun.msv.grammar.IDContextProvider2 -{ - /* - /////////////////////////////////////////////////////////////////////// - // Configuration - /////////////////////////////////////////////////////////////////////// - */ - - final protected XMLValidationSchema mParentSchema; - - final protected ValidationContext mContext; - - final protected DocumentDeclaration mVGM; - - /* - /////////////////////////////////////////////////////////////////////// - // State, helper objects - /////////////////////////////////////////////////////////////////////// - */ - - final protected ArrayList mAcceptors = new ArrayList(); - - protected Acceptor mCurrAcceptor = null; - - final protected TextAccumulator mTextAccumulator = new TextAccumulator(); - - /** - * Map that contains information about element id (values of attributes - * or textual content with type ID) declarations and references - */ - protected ElementIdMap mIdDefs; - - /* - /////////////////////////////////////////////////////////////////////// - // State, positions - /////////////////////////////////////////////////////////////////////// - */ - - protected String mCurrAttrPrefix; - - protected String mCurrAttrLocalName; - - /** - * Sometimes a problem object has to be temporarily - * stored, and only reported later on. This happens - * when exceptions can not be thrown via code outside - * of Woodstox (like validation methods in MSV that do - * callbacks). - */ - protected XMLValidationProblem mProblem; - - /* - /////////////////////////////////////////////////////////////////////// - // Helper objects - /////////////////////////////////////////////////////////////////////// - */ - - final StringRef mErrorRef = new StringRef(); - - /** - * StartTagInfo instance need not be thread-safe, and it is not immutable - * so let's reuse one instance during a single validation. - */ - final StartTagInfo mStartTag = new StartTagInfo("", "", "", null, (IDContextProvider2) null); - - /** - * This object provides limited access to attribute values of the - * currently validated element. - */ - final AttributeProxy mAttributeProxy; - - /* - /////////////////////////////////////////////////////////////////////// - // Construction, configuration - /////////////////////////////////////////////////////////////////////// - */ - - public GenericMsvValidator(XMLValidationSchema parent, ValidationContext ctxt, - DocumentDeclaration vgm) - { - mParentSchema = parent; - mContext = ctxt; - mVGM = vgm; - - mCurrAcceptor = mVGM.createAcceptor(); - mAttributeProxy = new AttributeProxy(ctxt); - } - - /* - /////////////////////////////////////////////////////////////////////// - // IDContextProvider2 implementation: - // - // Core RelaxNG ValidationContext implementation - // (org.relaxng.datatype.ValidationContext, base interface - // of the id provider context) - /////////////////////////////////////////////////////////////////////// - */ - - public String getBaseUri() - { - return mContext.getBaseUri(); - } - - public boolean isNotation(String notationName) - { - return mContext.isNotationDeclared(notationName); - } - - public boolean isUnparsedEntity(String entityName) - { - return mContext.isUnparsedEntityDeclared(entityName); - } - - public String resolveNamespacePrefix(String prefix) - { - return mContext.getNamespaceURI(prefix); - } - - /* - /////////////////////////////////////////////////////////////////////// - // IDContextProvider2 implementation, extensions over - // core ValidationContext - /////////////////////////////////////////////////////////////////////// - */ - - /** - *

- * Note: we have to throw a dummy marker exception, which merely - * signals that a validation problem is to be reported. - * This is obviously messy, but has to do for now. - */ - public void onID(Datatype datatype, StringToken idToken) - throws IllegalArgumentException - { - if (mIdDefs == null) { - mIdDefs = new ElementIdMap(); - } - - int idType = datatype.getIdType(); - Location loc = mContext.getValidationLocation(); - PrefixedName elemPName = getElementPName(); - PrefixedName attrPName = getAttrPName(); - - if (idType == Datatype.ID_TYPE_ID) { - String idStr = idToken.literal.trim(); - ElementId eid = mIdDefs.addDefined(idStr, loc, elemPName, attrPName); - // We can detect dups by checking if Location is the one we passed: - if (eid.getLocation() != loc) { - mProblem = new XMLValidationProblem(loc, "Duplicate id '"+idStr+"', first declared at "+eid.getLocation()); - mProblem.setReporter(this); - } - } else if (idType == Datatype.ID_TYPE_IDREF) { - String idStr = idToken.literal.trim(); - mIdDefs.addReferenced(idStr, loc, elemPName, attrPName); - } else if (idType == Datatype.ID_TYPE_IDREFS) { - StringTokenizer tokens = new StringTokenizer(idToken.literal); - while (tokens.hasMoreTokens()) { - mIdDefs.addReferenced(tokens.nextToken(), loc, elemPName, attrPName); - } - } else { // sanity check - throw new IllegalStateException("Internal error: unexpected ID datatype: "+datatype); - } - } - - /* - /////////////////////////////////////////////////////////////////////// - // XMLValidator implementation - /////////////////////////////////////////////////////////////////////// - */ - - public XMLValidationSchema getSchema() { - return mParentSchema; - } - - /** - * Method called to update information about the newly encountered (start) - * element. At this point namespace information has been resolved, but - * no DTD validation has been done. Validator is to do these validations, - * including checking for attribute value (and existence) compatibility. - */ - public void validateElementStart(String localName, String uri, String prefix) - throws XMLStreamException - { - - /* [WSTX-200]: If sub-tree we were to validate has ended, we - * have no current acceptor, and must quite. Ideally we would - * really handle this more cleanly but... - */ - if (mCurrAcceptor == null) { - return; - } - - // Very first thing: do we have text collected? - if (mTextAccumulator.hasText()) { - doValidateText(mTextAccumulator); - } - - /* 31-Mar-2006, TSa: MSV seems to require empty String for empty/no - * namespace, not null. - */ - if (uri == null) { - uri = ""; - } - - /* Do we need to properly fill it? Or could we just put local name? - * Looking at code, I do believe it's only used for error reporting - * purposes... - */ - //String qname = (prefix == null || prefix.length() == 0) ? localName : (prefix + ":" +localName); - String qname = localName; - mStartTag.reinit(uri, localName, qname, mAttributeProxy, this); - - mCurrAcceptor = mCurrAcceptor.createChildAcceptor(mStartTag, mErrorRef); - /* As per documentation, the side-effect of getting the error message - * is that we also get a recoverable non-null acceptor... thus, should - * never (?) see null acceptor being returned - */ - if (mErrorRef.str != null) { - reportError(mErrorRef); - } - if (mProblem != null) { // pending problems (to throw exception on)? - XMLValidationProblem p = mProblem; - mProblem = null; - mContext.reportProblem(p); - } - mAcceptors.add(mCurrAcceptor); - } - - public String validateAttribute(String localName, String uri, - String prefix, String value) - throws XMLStreamException - { - mCurrAttrLocalName = localName; - mCurrAttrPrefix = prefix; - if (mCurrAcceptor != null) { - - String qname = localName; // for now, let's assume we don't need prefixed version - DatatypeRef typeRef = null; // for now, let's not care - - /* 31-Mar-2006, TSa: MSV seems to require empty String for empty/no - * namespace, not null. - */ - if (uri == null) { - uri = ""; - } - - if (!mCurrAcceptor.onAttribute2(uri, localName, qname, value, this, mErrorRef, typeRef) - || mErrorRef.str != null) { - reportError(mErrorRef); - } - if (mProblem != null) { // pending problems (to throw exception on)? - XMLValidationProblem p = mProblem; - mProblem = null; - mContext.reportProblem(p); - } - } - /* No normalization done by RelaxNG, is there? (at least nothing - * visible to callers that is) - */ - return null; - } - - public String validateAttribute(String localName, String uri, - String prefix, - char[] valueChars, int valueStart, - int valueEnd) - throws XMLStreamException - { - int len = valueEnd - valueStart; - /* This is very sub-optimal... but MSV doesn't deal with char - * arrays. - */ - return validateAttribute(localName, uri, prefix, - new String(valueChars, valueStart, len)); - } - - public int validateElementAndAttributes() - throws XMLStreamException - { - // Not handling any attributes - mCurrAttrLocalName = mCurrAttrPrefix = ""; - if (mCurrAcceptor != null) { - /* start tag info is still intact here (only attributes sent - * since child acceptor was created) - */ - if (!mCurrAcceptor.onEndAttributes(mStartTag, mErrorRef) - || mErrorRef.str != null) { - reportError(mErrorRef); - } - - int stringChecks = mCurrAcceptor.getStringCareLevel(); - switch (stringChecks) { - case Acceptor.STRING_PROHIBITED: // only WS - return XMLValidator.CONTENT_ALLOW_WS; - case Acceptor.STRING_IGNORE: // anything (mixed content models) - return XMLValidator.CONTENT_ALLOW_ANY_TEXT; - case Acceptor.STRING_STRICT: // validatable (data-oriented) - return XMLValidator.CONTENT_ALLOW_VALIDATABLE_TEXT; - default: - throw new IllegalArgumentException("Internal error: unexpected string care level value return by MSV: "+stringChecks); - } - } - - // If no acceptor, we are recovering, no need or use to validate text - return CONTENT_ALLOW_ANY_TEXT; - } - - /** - * @return Validation state that should be effective for the parent - * element state - */ - public int validateElementEnd(String localName, String uri, String prefix) - throws XMLStreamException - { - // Very first thing: do we have text collected? - /* 27-Feb-2009, TSa: [WSTX-191]: Actually MSV expects us to call - * validation anyway, in case there might be restriction(s) on - * textual content. Otherwise we'll get an error. - */ - doValidateText(mTextAccumulator); - - /* [WSTX-200]: need to avoid problems when doing sub-tree - * validation... not a proper solution, but has to do for - * now - */ - int lastIx = mAcceptors.size()-1; - if (lastIx < 0) { - return XMLValidator.CONTENT_ALLOW_WS; - } - - Acceptor acc = (Acceptor)mAcceptors.remove(lastIx); - if (acc != null) { // may be null during error recovery? or not? - if (!acc.isAcceptState(mErrorRef) || mErrorRef.str != null) { - reportError(mErrorRef); - } - } - if (lastIx == 0) { // root closed - mCurrAcceptor = null; - } else { - mCurrAcceptor = (Acceptor) mAcceptors.get(lastIx-1); - } - if (mCurrAcceptor != null && acc != null) { - if (!mCurrAcceptor.stepForward(acc, mErrorRef) - || mErrorRef.str != null) { - reportError(mErrorRef); - } - int stringChecks = mCurrAcceptor.getStringCareLevel(); - switch (stringChecks) { - case Acceptor.STRING_PROHIBITED: // only WS - return XMLValidator.CONTENT_ALLOW_WS; - case Acceptor.STRING_IGNORE: // anything (mixed content models) - return XMLValidator.CONTENT_ALLOW_ANY_TEXT; - case Acceptor.STRING_STRICT: // validatable (data-oriented) - return XMLValidator.CONTENT_ALLOW_VALIDATABLE_TEXT; - default: - throw new IllegalArgumentException("Internal error: unexpected string care level value return by MSV: "+stringChecks); - } - } - return XMLValidator.CONTENT_ALLOW_ANY_TEXT; - } - - public void validateText(String text, boolean lastTextSegment) - throws XMLStreamException - { - /* If we got here, then it's likely we do need to call onText2(). - * (not guaranteed, though; in case of multiple parallel validators, - * only one of them may actually be interested) - */ - mTextAccumulator.addText(text); - if (lastTextSegment) { - doValidateText(mTextAccumulator); - } - } - - public void validateText(char[] cbuf, int textStart, int textEnd, - boolean lastTextSegment) - throws XMLStreamException - { - /* If we got here, then it's likely we do need to call onText(). - * (not guaranteed, though; in case of multiple parallel validators, - * only one of them may actually be interested) - */ - mTextAccumulator.addText(cbuf, textStart, textEnd); - if (lastTextSegment) { - doValidateText(mTextAccumulator); - } - } - - public void validationCompleted(boolean eod) - throws XMLStreamException - { - /* Ok, so, we should verify that there are no undefined - * IDREF/IDREFS references. But only if we hit EOF, not - * if validation was cancelled. - */ - if (eod) { - if (mIdDefs != null) { - ElementId ref = mIdDefs.getFirstUndefined(); - if (ref != null) { // problem! - String msg = "Undefined ID '"+ref.getId() - +"': referenced from element <" - +ref.getElemName()+">, attribute '" - +ref.getAttrName()+"'"; - reportError(msg, ref.getLocation()); - } - } - } - } - - /* - /////////////////////////////////////////////////////////////////////// - // Attribute info access - /////////////////////////////////////////////////////////////////////// - */ - - // // // Access to type info - - public String getAttributeType(int index) - { - // !!! TBI - return null; - } - - public int getIdAttrIndex() - { - // !!! TBI - return -1; - } - - public int getNotationAttrIndex() - { - // !!! TBI - return -1; - } - - /* - /////////////////////////////////////////////////////////////////////// - // Internal methods - /////////////////////////////////////////////////////////////////////// - */ - - PrefixedName getElementPName() - { - return PrefixedName.valueOf(mContext.getCurrentElementName()); - } - - PrefixedName getAttrPName() - { - return new PrefixedName(mCurrAttrPrefix, mCurrAttrLocalName); - } - - void doValidateText(TextAccumulator textAcc) - throws XMLStreamException - { - if (mCurrAcceptor != null) { - String str = textAcc.getAndClear(); - DatatypeRef typeRef = null; - if (!mCurrAcceptor.onText2(str, this, mErrorRef, typeRef) - || mErrorRef.str != null) { - reportError(mErrorRef); - } - } - } - - private void reportError(StringRef errorRef) - throws XMLStreamException - { - String msg = errorRef.str; - errorRef.str = null; - if (msg == null) { - msg = "Unknown reason"; - } - reportError(msg); - } - - private void reportError(String msg) - throws XMLStreamException - { - reportError(msg, mContext.getValidationLocation()); - } - - private void reportError(String msg, Location loc) - throws XMLStreamException - { - XMLValidationProblem prob = new XMLValidationProblem(loc, msg, XMLValidationProblem.SEVERITY_ERROR); - prob.setReporter(this); - mContext.reportProblem(prob); - } -} diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/msv/package.html libwoodstox-java-5.1.0/src/java/com/ctc/wstx/msv/package.html --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/msv/package.html 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/msv/package.html 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ - -Package that contains Multi-Schema Validator (MSV) based validator -implementations for schema languages other than DTD. - - diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/msv/RelaxNGSchemaFactory.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/msv/RelaxNGSchemaFactory.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/msv/RelaxNGSchemaFactory.java 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/msv/RelaxNGSchemaFactory.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,82 +0,0 @@ -/* Woodstox XML processor - * - * Copyright (c) 2004- Tatu Saloranta, tatu.saloranta@iki.fi - * - * Licensed under the License specified in the file LICENSE which is - * included with the source code. - * You may not use this file except in compliance with the License. - * - * 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 com.ctc.wstx.msv; - -import javax.xml.parsers.SAXParserFactory; -import javax.xml.stream.*; - -import org.xml.sax.InputSource; - -import org.codehaus.stax2.validation.*; - -import com.sun.msv.grammar.trex.TREXGrammar; -import com.sun.msv.reader.GrammarReaderController; -import com.sun.msv.reader.trex.ng.RELAXNGReader; - -/** - * This is a StAX2 schema factory that can parse and create schema instances - * for creating validators that validate documents to check their validity - * against specific Relax NG specifications. It requires - * Sun Multi-Schema Validator - * (http://www.sun.com/software/xml/developers/multischema/) - * to work, and acts as a quite thin wrapper layer (although not a completely - * trivial one, since MSV only exports SAX API, some adapting is needed) - */ -public class RelaxNGSchemaFactory - extends BaseSchemaFactory -{ - /** - * For now, there's no need for fine-grained error/problem reporting - * infrastructure, so let's just use a dummy controller. - */ - protected final GrammarReaderController mDummyController = - new com.sun.msv.reader.util.IgnoreController(); - - public RelaxNGSchemaFactory() - { - super(XMLValidationSchema.SCHEMA_ID_RELAXNG); - } - - /* - /////////////////////////////////////////////////////////////////////// - // Non-public methods - /////////////////////////////////////////////////////////////////////// - */ - - protected XMLValidationSchema loadSchema(InputSource src, Object sysRef) - throws XMLStreamException - { - /* 26-Oct-2007, TSa: Are sax parser factories safe to share? - * If not, should just create new instances for each - * parsed schema. - */ - /* Another thing; should we use a controller to get notified about - * errors in parsing? - */ - SAXParserFactory saxFactory = getSaxFactory(); - MyGrammarController ctrl = new MyGrammarController(); - TREXGrammar grammar = RELAXNGReader.parse(src, saxFactory, ctrl); - if (grammar == null) { - String msg = "Failed to load RelaxNG schema from '"+sysRef+"'"; - String emsg = ctrl.mErrorMsg; - if (emsg != null) { - msg = msg + ": "+emsg; - } - throw new XMLStreamException(msg); - } - return new RelaxNGSchema(grammar); - } -} diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/msv/RelaxNGSchema.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/msv/RelaxNGSchema.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/msv/RelaxNGSchema.java 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/msv/RelaxNGSchema.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,54 +0,0 @@ -/* Woodstox XML processor - * - * Copyright (c) 2004- Tatu Saloranta, tatu.saloranta@iki.fi - * - * Licensed under the License specified in the file LICENSE which is - * included with the source code. - * You may not use this file except in compliance with the License. - * - * 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 com.ctc.wstx.msv; - -import javax.xml.stream.*; - -import org.codehaus.stax2.validation.*; - -import com.sun.msv.grammar.trex.TREXGrammar; -import com.sun.msv.verifier.regexp.REDocumentDeclaration; - -/** - * This is a validation schema instance based on a RELAX NG schema. It - * serves as a shareable "blueprint" for creating actual validator instances. - */ -public class RelaxNGSchema - implements XMLValidationSchema -{ - /** - * This is VGM (in MSV lingo); shareable schema blueprint, basically - * peer of this schema object. It will be used for creating actual - * validator peer, root Acceptor. - */ - protected final TREXGrammar mGrammar; - - public RelaxNGSchema(TREXGrammar grammar) - { - mGrammar = grammar; - } - - public String getSchemaType() { - return XMLValidationSchema.SCHEMA_ID_RELAXNG; - } - - public XMLValidator createValidator(ValidationContext ctxt) - throws XMLStreamException - { - REDocumentDeclaration dd = new REDocumentDeclaration(mGrammar); - return new GenericMsvValidator(this, ctxt, dd); - } -} diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/msv/W3CSchemaFactory.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/msv/W3CSchemaFactory.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/msv/W3CSchemaFactory.java 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/msv/W3CSchemaFactory.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,80 +0,0 @@ -/* Woodstox XML processor - * - * Copyright (c) 2004- Tatu Saloranta, tatu.saloranta@iki.fi - * - * Licensed under the License specified in the file LICENSE which is - * included with the source code. - * You may not use this file except in compliance with the License. - * - * 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 com.ctc.wstx.msv; - -import javax.xml.parsers.SAXParserFactory; -import javax.xml.stream.*; - -import org.xml.sax.InputSource; - -import org.codehaus.stax2.validation.*; - -import com.sun.msv.grammar.xmlschema.XMLSchemaGrammar; -import com.sun.msv.reader.GrammarReaderController; -import com.sun.msv.reader.xmlschema.XMLSchemaReader; - -/** - * This is a StAX2 schema factory that can parse and create schema instances - * for creating validators that validate documents to check their validity - * against specific W3C Schema instances. It requires - * Sun Multi-Schema Validator - * (http://www.sun.com/software/xml/developers/multischema/) - * to work, and acts as a quite thin wrapper layer, similar to - * how matching RelaxNG validator works - */ -public class W3CSchemaFactory - extends BaseSchemaFactory -{ - /** - * For now, there's no need for fine-grained error/problem reporting - * infrastructure, so let's just use a dummy controller. - */ - protected final GrammarReaderController mDummyController = - new com.sun.msv.reader.util.IgnoreController(); - - public W3CSchemaFactory() - { - super(XMLValidationSchema.SCHEMA_ID_RELAXNG); - } - - /* - /////////////////////////////////////////////////////////////////////// - // Non-public methods - /////////////////////////////////////////////////////////////////////// - */ - - protected XMLValidationSchema loadSchema(InputSource src, Object sysRef) - throws XMLStreamException - { - /* 26-Oct-2007, TSa: Are SAX parser factories safe to share? - * If not, should just create new instances for each - * parsed schema. - */ - SAXParserFactory saxFactory = getSaxFactory(); - - MyGrammarController ctrl = new MyGrammarController(); - XMLSchemaGrammar grammar = XMLSchemaReader.parse(src, saxFactory, ctrl); - if (grammar == null) { - String msg = "Failed to load W3C Schema from '"+sysRef+"'"; - String emsg = ctrl.mErrorMsg; - if (emsg != null) { - msg = msg + ": "+emsg; - } - throw new XMLStreamException(msg); - } - return new W3CSchema(grammar); - } -} diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/msv/W3CSchema.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/msv/W3CSchema.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/msv/W3CSchema.java 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/msv/W3CSchema.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,49 +0,0 @@ -/* Woodstox XML processor - * - * Copyright (c) 2004- Tatu Saloranta, tatu.saloranta@iki.fi - * - * Licensed under the License specified in the file LICENSE which is - * included with the source code. - * You may not use this file except in compliance with the License. - * - * 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 com.ctc.wstx.msv; - -import javax.xml.stream.*; - -import org.codehaus.stax2.validation.*; - -import com.sun.msv.grammar.xmlschema.XMLSchemaGrammar; -import com.sun.msv.verifier.regexp.xmlschema.XSREDocDecl; - -/** - * This is a validation schema instance based on a W3C schema. It - * serves as a shareable "blueprint" for creating actual validator instances. - */ -public class W3CSchema - implements XMLValidationSchema -{ - protected final XMLSchemaGrammar mGrammar; - - public W3CSchema(XMLSchemaGrammar grammar) - { - mGrammar = grammar; - } - - public String getSchemaType() { - return XMLValidationSchema.SCHEMA_ID_W3C_SCHEMA; - } - - public XMLValidator createValidator(ValidationContext ctxt) - throws XMLStreamException - { - XSREDocDecl dd = new XSREDocDecl(mGrammar); - return new GenericMsvValidator(this, ctxt, dd); - } -} diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/osgi/InputFactoryProviderImpl.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/osgi/InputFactoryProviderImpl.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/osgi/InputFactoryProviderImpl.java 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/osgi/InputFactoryProviderImpl.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,25 +0,0 @@ -package com.ctc.wstx.osgi; - -import java.util.Properties; - -import org.codehaus.stax2.XMLInputFactory2; -import org.codehaus.stax2.osgi.Stax2InputFactoryProvider; - -import com.ctc.wstx.api.ReaderConfig; -import com.ctc.wstx.stax.WstxInputFactory; - -public class InputFactoryProviderImpl - implements Stax2InputFactoryProvider -{ - public XMLInputFactory2 createInputFactory() { - return new WstxInputFactory(); - } - - protected Properties getProperties() - { - Properties props = new Properties(); - props.setProperty(OSGI_SVC_PROP_IMPL_NAME, ReaderConfig.getImplName()); - props.setProperty(OSGI_SVC_PROP_IMPL_VERSION, ReaderConfig.getImplVersion()); - return props; - } -} diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/osgi/OutputFactoryProviderImpl.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/osgi/OutputFactoryProviderImpl.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/osgi/OutputFactoryProviderImpl.java 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/osgi/OutputFactoryProviderImpl.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,25 +0,0 @@ -package com.ctc.wstx.osgi; - -import java.util.Properties; - -import org.codehaus.stax2.XMLOutputFactory2; -import org.codehaus.stax2.osgi.Stax2OutputFactoryProvider; - -import com.ctc.wstx.api.ReaderConfig; -import com.ctc.wstx.stax.WstxOutputFactory; - -public class OutputFactoryProviderImpl - implements Stax2OutputFactoryProvider -{ - public XMLOutputFactory2 createOutputFactory() { - return new WstxOutputFactory(); - } - - protected Properties getProperties() - { - Properties props = new Properties(); - props.setProperty(OSGI_SVC_PROP_IMPL_NAME, ReaderConfig.getImplName()); - props.setProperty(OSGI_SVC_PROP_IMPL_VERSION, ReaderConfig.getImplVersion()); - return props; - } -} diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/osgi/package.html libwoodstox-java-5.1.0/src/java/com/ctc/wstx/osgi/package.html --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/osgi/package.html 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/osgi/package.html 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ - -Contains classes that implement Stax2 OSGI providers for accessing -Stax2 input, output and validation scheme factories dynamically using -auto-discovery mechanism. - diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/osgi/ValidationSchemaFactoryProviderImpl.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/osgi/ValidationSchemaFactoryProviderImpl.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/osgi/ValidationSchemaFactoryProviderImpl.java 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/osgi/ValidationSchemaFactoryProviderImpl.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,79 +0,0 @@ -package com.ctc.wstx.osgi; - -import java.util.Properties; - -import org.codehaus.stax2.validation.XMLValidationSchema; -import org.codehaus.stax2.validation.XMLValidationSchemaFactory; -import org.codehaus.stax2.osgi.Stax2ValidationSchemaFactoryProvider; - -import com.ctc.wstx.api.ValidatorConfig; -import com.ctc.wstx.dtd.DTDSchemaFactory; -import com.ctc.wstx.msv.RelaxNGSchemaFactory; -import com.ctc.wstx.msv.W3CSchemaFactory; - -public abstract class ValidationSchemaFactoryProviderImpl - implements Stax2ValidationSchemaFactoryProvider -{ - final String mSchemaType; - - protected ValidationSchemaFactoryProviderImpl(String st) - { - mSchemaType = st; - } - - public static ValidationSchemaFactoryProviderImpl[] createAll() - { - return new ValidationSchemaFactoryProviderImpl[] { - new DTD(), new RelaxNG(), new W3CSchema() - }; - } - - public abstract XMLValidationSchemaFactory createValidationSchemaFactory(); - - public String getSchemaType() { return mSchemaType; } - - public Properties getProperties() - { - Properties props = new Properties(); - props.setProperty(OSGI_SVC_PROP_IMPL_NAME, ValidatorConfig.getImplName()); - props.setProperty(OSGI_SVC_PROP_IMPL_VERSION, ValidatorConfig.getImplVersion()); - props.setProperty(OSGI_SVC_PROP_SCHEMA_TYPE, mSchemaType); - return props; - } - - /* - //////////////////////////////////////////////////////// - // Actual provider instances, one per type supported - //////////////////////////////////////////////////////// - */ - - final static class DTD - extends ValidationSchemaFactoryProviderImpl - { - DTD() { super(XMLValidationSchema.SCHEMA_ID_DTD); } - - public XMLValidationSchemaFactory createValidationSchemaFactory() { - return new DTDSchemaFactory(); - } - } - - final static class RelaxNG - extends ValidationSchemaFactoryProviderImpl - { - RelaxNG() { super(XMLValidationSchema.SCHEMA_ID_RELAXNG); } - - public XMLValidationSchemaFactory createValidationSchemaFactory() { - return new RelaxNGSchemaFactory(); - } - } - - final static class W3CSchema - extends ValidationSchemaFactoryProviderImpl - { - W3CSchema() { super(XMLValidationSchema.SCHEMA_ID_W3C_SCHEMA); } - - public XMLValidationSchemaFactory createValidationSchemaFactory() { - return new W3CSchemaFactory(); - } - } -} diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/osgi/WstxBundleActivator.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/osgi/WstxBundleActivator.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/osgi/WstxBundleActivator.java 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/osgi/WstxBundleActivator.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,45 +0,0 @@ -package com.ctc.wstx.osgi; - -import org.osgi.framework.BundleActivator; -import org.osgi.framework.BundleContext; - -import org.codehaus.stax2.osgi.Stax2InputFactoryProvider; -import org.codehaus.stax2.osgi.Stax2OutputFactoryProvider; -import org.codehaus.stax2.osgi.Stax2ValidationSchemaFactoryProvider; - -/** - * This class is responsible for registering OSGi service(s) that Woodstox - * package provides. Currently it means registering all providers that are - * needed to instantiate input, output and validation schema factories; - * these are needed since JDK service-introspection (which is the standard - * Stax instance instantiation mechanism) does not work with OSGi. - */ -public class WstxBundleActivator - implements BundleActivator -{ - public WstxBundleActivator() { } - - /** - * Method called on activation. We need to register all providers we have at - * this point. - */ - public void start(BundleContext ctxt) - { - InputFactoryProviderImpl inputP = new InputFactoryProviderImpl(); - ctxt.registerService(Stax2InputFactoryProvider.class.getName(), inputP, inputP.getProperties()); - OutputFactoryProviderImpl outputP = new OutputFactoryProviderImpl(); - ctxt.registerService(Stax2OutputFactoryProvider.class.getName(), outputP, outputP.getProperties()); - ValidationSchemaFactoryProviderImpl[] impls = ValidationSchemaFactoryProviderImpl.createAll(); - for (int i = 0, len = impls.length; i < len; ++i) { - ValidationSchemaFactoryProviderImpl impl = impls[i]; - ctxt.registerService(Stax2ValidationSchemaFactoryProvider.class.getName(), impl, impl.getProperties()); - } - } - - public void stop(BundleContext ctxt) { - /* Nothing to do here: OSGi automatically de-registers services upon - * deactivation. - */ - } -} - diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/sax/package.html libwoodstox-java-5.1.0/src/java/com/ctc/wstx/sax/package.html --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/sax/package.html 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/sax/package.html 1970-01-01 00:00:00.000000000 +0000 @@ -1,4 +0,0 @@ - -Contains Woodstox SAX implementation. - - diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/sax/SAXFeature.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/sax/SAXFeature.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/sax/SAXFeature.java 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/sax/SAXFeature.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,75 +0,0 @@ -/* - * Copyright (c) 2004- Tatu Saloranta, tatu.saloranta@iki.fi - * - * Licensed under the License specified in file LICENSE, included with - * the source code. - * You may not use this file except in compliance with the License. - * - * 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 com.ctc.wstx.sax; - -import java.util.HashMap; - -/** - * Type safe (pre-Java5) enumeration for listing all currently (SAX 2.0.2) - * defined standard features - */ -public final class SAXFeature -{ - /** - * Since all standard features have same URI prefix, let's separate - * that prefix, from unique remainder of the feature URIs. - */ - public final static String STD_FEATURE_PREFIX = "http://xml.org/sax/features/"; - - final static HashMap sInstances = new HashMap(); - - // // // "Enum" values: - - final static SAXFeature EXTERNAL_GENERAL_ENTITIES = new SAXFeature("external-general-entities"); - final static SAXFeature EXTERNAL_PARAMETER_ENTITIES = new SAXFeature("external-parameter-entities"); - final static SAXFeature IS_STANDALONE = new SAXFeature("is-standalone"); - final static SAXFeature LEXICAL_HANDLER_PARAMETER_ENTITIES = new SAXFeature("lexical-handler/parameter-entities"); - final static SAXFeature NAMESPACES = new SAXFeature("namespaces"); - final static SAXFeature NAMESPACE_PREFIXES = new SAXFeature("namespace-prefixes"); - final static SAXFeature RESOLVE_DTD_URIS = new SAXFeature("resolve-dtd-uris"); - final static SAXFeature STRING_INTERNING = new SAXFeature("string-interning"); - final static SAXFeature UNICODE_NORMALIZATION_CHECKING = new SAXFeature("unicode-normalization-checking"); - final static SAXFeature USE_ATTRIBUTES2 = new SAXFeature("use-attributes2"); - final static SAXFeature USE_LOCATOR2 = new SAXFeature("use-locator2"); - final static SAXFeature USE_ENTITY_RESOLVER2 = new SAXFeature("use-entity-resolver2"); - final static SAXFeature VALIDATION = new SAXFeature("validation"); - final static SAXFeature XMLNS_URIS = new SAXFeature("xmlns-uris"); - final static SAXFeature XML_1_1 = new SAXFeature("xml-1.1"); - - private final String mSuffix; - - private SAXFeature(String suffix) - { - mSuffix = suffix; - sInstances.put(suffix, this); - } - - public static SAXFeature findByUri(String uri) - { - if (uri.startsWith(STD_FEATURE_PREFIX)) { - return findBySuffix(uri.substring(STD_FEATURE_PREFIX.length())); - } - return null; - } - - public static SAXFeature findBySuffix(String suffix) - { - return (SAXFeature) sInstances.get(suffix); - } - - public String getSuffix() { return mSuffix; } - - public String toString() { return STD_FEATURE_PREFIX + mSuffix; } -} diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/sax/SAXProperty.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/sax/SAXProperty.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/sax/SAXProperty.java 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/sax/SAXProperty.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,61 +0,0 @@ -/* - * Copyright (c) 2004- Tatu Saloranta, tatu.saloranta@iki.fi - * - * Licensed under the License specified in file LICENSE, included with - * the source code. - * You may not use this file except in compliance with the License. - * - * 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 com.ctc.wstx.sax; - -import java.util.HashMap; - -/** - * Type-safe (pre-Java5) enumeration of all currently (SAX 2.0.2) defined - * standard properties. - */ -public final class SAXProperty -{ - public final static String STD_PROPERTY_PREFIX = "http://xml.org/sax/properties/"; - - final static HashMap sInstances = new HashMap(); - - // // // "Enum" values: - - public final static SAXProperty DECLARATION_HANDLER = new SAXProperty("declaration-handler"); - public final static SAXProperty DOCUMENT_XML_VERSION = new SAXProperty("document-xml-version"); - public final static SAXProperty DOM_NODE = new SAXProperty("dom-node"); - public final static SAXProperty LEXICAL_HANDLER = new SAXProperty("lexical-handler"); - final static SAXProperty XML_STRING = new SAXProperty("xml-string"); - - private final String mSuffix; - - private SAXProperty(String suffix) - { - mSuffix = suffix; - sInstances.put(suffix, this); - } - - public static SAXProperty findByUri(String uri) - { - if (uri.startsWith(STD_PROPERTY_PREFIX)) { - return findBySuffix(uri.substring(STD_PROPERTY_PREFIX.length())); - } - return null; - } - - public static SAXProperty findBySuffix(String suffix) - { - return (SAXProperty) sInstances.get(suffix); - } - - public String getSuffix() { return mSuffix; } - - public String toString() { return STD_PROPERTY_PREFIX + mSuffix; } -} diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/sax/WrappedSaxException.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/sax/WrappedSaxException.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/sax/WrappedSaxException.java 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/sax/WrappedSaxException.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,39 +0,0 @@ -/* - * Copyright (c) 2004- Tatu Saloranta, tatu.saloranta@iki.fi - * - * Licensed under the License specified in file LICENSE, included with - * the source code. - * You may not use this file except in compliance with the License. - * - * 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 com.ctc.wstx.sax; - -import org.xml.sax.SAXException; - -/** - * Simple type-safe wrapper used for "tunneling" SAX exceptions - * through interfaces that do not allow them to be thrown. This - * is done by extending {@link RuntimeException}. - */ -public final class WrappedSaxException - extends RuntimeException -{ - private static final long serialVersionUID = 1L; - - protected final SAXException mCause; - - public WrappedSaxException(SAXException cause) - { - mCause = cause; - } - - public SAXException getSaxException() { return mCause; } - - public String toString() { return mCause.toString(); } -} diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/sax/WstxSAXParserFactory.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/sax/WstxSAXParserFactory.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/sax/WstxSAXParserFactory.java 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/sax/WstxSAXParserFactory.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,165 +0,0 @@ -/* - * Copyright (c) 2004- Tatu Saloranta, tatu.saloranta@iki.fi - * - * Licensed under the License specified in file LICENSE, included with - * the source code. - * You may not use this file except in compliance with the License. - * - * 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 com.ctc.wstx.sax; - -import javax.xml.parsers.SAXParser; -import javax.xml.parsers.SAXParserFactory; - -import org.xml.sax.SAXNotRecognizedException; -import org.xml.sax.SAXNotSupportedException; - -import com.ctc.wstx.stax.WstxInputFactory; - -/** - * This is implementation of the main JAXP SAX factory, and as such - * acts as the entry point from JAXP. - *

- * Note: most of the SAX features are not configurable as of yet. - * However, effort is made to recognize all existing standard features - * and properties, to allow using code to figure out existing - * capabilities automatically. - */ -public class WstxSAXParserFactory - extends SAXParserFactory -{ - protected final WstxInputFactory mStaxFactory; - - /** - * Sax feature that determines whether namespace declarations need - * to be also reported as attributes or not. - */ - protected boolean mFeatNsPrefixes = false; - - public WstxSAXParserFactory() - { - this(new WstxInputFactory()); - } - - /** - * @since 4.0.8 - */ - public WstxSAXParserFactory(WstxInputFactory f) - { - mStaxFactory = f; - /* defaults should be fine... except that for some weird - * reason, by default namespace support is defined to be off - */ - setNamespaceAware(true); - } - - public boolean getFeature(String name) - throws SAXNotRecognizedException, SAXNotSupportedException - { - SAXFeature stdFeat = SAXFeature.findByUri(name); - - if (stdFeat == SAXFeature.EXTERNAL_GENERAL_ENTITIES) { - return mStaxFactory.getConfig().willSupportExternalEntities(); - } else if (stdFeat == SAXFeature.EXTERNAL_PARAMETER_ENTITIES) { - return mStaxFactory.getConfig().willSupportExternalEntities(); - } else if (stdFeat == SAXFeature.IS_STANDALONE) { - // Not known at this point... - return false; - } else if (stdFeat == SAXFeature.LEXICAL_HANDLER_PARAMETER_ENTITIES) { - // !!! TODO: - return false; - } else if (stdFeat == SAXFeature.NAMESPACES) { - return mStaxFactory.getConfig().willSupportNamespaces(); - } else if (stdFeat == SAXFeature.NAMESPACE_PREFIXES) { - return mFeatNsPrefixes; - } else if (stdFeat == SAXFeature.RESOLVE_DTD_URIS) { - // !!! TODO: - return false; - } else if (stdFeat == SAXFeature.STRING_INTERNING) { - return mStaxFactory.getConfig().willInternNames(); - } else if (stdFeat == SAXFeature.UNICODE_NORMALIZATION_CHECKING) { - return false; - } else if (stdFeat == SAXFeature.USE_ATTRIBUTES2) { - return true; - } else if (stdFeat == SAXFeature.USE_LOCATOR2) { - return true; - } else if (stdFeat == SAXFeature.USE_ENTITY_RESOLVER2) { - return true; - } else if (stdFeat == SAXFeature.VALIDATION) { - return mStaxFactory.getConfig().willValidateWithDTD(); - } else if (stdFeat == SAXFeature.XMLNS_URIS) { - /* !!! TODO: default value should be false... but not sure - * if implementing that mode makes sense - */ - return true; - } else if (stdFeat == SAXFeature.XML_1_1) { - return true; - } else { - throw new SAXNotRecognizedException("Feature '"+name+"' not recognized"); - } - } - - public SAXParser newSAXParser() - { - return new WstxSAXParser(mStaxFactory, mFeatNsPrefixes); - } - - public void setFeature(String name, boolean value) - throws SAXNotRecognizedException, SAXNotSupportedException - { - boolean invalidValue = false; - boolean readOnly = false; - SAXFeature stdFeat = SAXFeature.findByUri(name); - - if (stdFeat == SAXFeature.EXTERNAL_GENERAL_ENTITIES) { - mStaxFactory.getConfig().doSupportExternalEntities(value); - } else if (stdFeat == SAXFeature.EXTERNAL_PARAMETER_ENTITIES) { - // !!! TODO - } else if (stdFeat == SAXFeature.IS_STANDALONE) { - readOnly = true; - } else if (stdFeat == SAXFeature.LEXICAL_HANDLER_PARAMETER_ENTITIES) { - // !!! TODO - } else if (stdFeat == SAXFeature.NAMESPACES) { - mStaxFactory.getConfig().doSupportNamespaces(value); - } else if (stdFeat == SAXFeature.NAMESPACE_PREFIXES) { - mFeatNsPrefixes = value; - } else if (stdFeat == SAXFeature.RESOLVE_DTD_URIS) { - // !!! TODO - } else if (stdFeat == SAXFeature.STRING_INTERNING) { - invalidValue = !value; - } else if (stdFeat == SAXFeature.UNICODE_NORMALIZATION_CHECKING) { - invalidValue = value; - } else if (stdFeat == SAXFeature.USE_ATTRIBUTES2) { - readOnly = true; - } else if (stdFeat == SAXFeature.USE_LOCATOR2) { - readOnly = true; - } else if (stdFeat == SAXFeature.USE_ENTITY_RESOLVER2) { - readOnly = true; - } else if (stdFeat == SAXFeature.VALIDATION) { - mStaxFactory.getConfig().doValidateWithDTD(value); - } else if (stdFeat == SAXFeature.XMLNS_URIS) { - invalidValue = !value; - } else if (stdFeat == SAXFeature.XML_1_1) { - readOnly = true; - } else { - throw new SAXNotRecognizedException("Feature '"+name+"' not recognized"); - } - - // Trying to modify read-only properties? - if (readOnly) { - throw new SAXNotSupportedException("Feature '"+name+"' is read-only, can not be modified"); - } - if (invalidValue) { - throw new SAXNotSupportedException("Trying to set invalid value for feature '"+name+"', '"+value+"'"); - } - } -} - - - diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/sax/WstxSAXParser.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/sax/WstxSAXParser.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/sax/WstxSAXParser.java 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/sax/WstxSAXParser.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,1378 +0,0 @@ -/* - * Copyright (c) 2004- Tatu Saloranta, tatu.saloranta@iki.fi - * - * Licensed under the License specified in file LICENSE, included with - * the source code. - * You may not use this file except in compliance with the License. - * - * 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 com.ctc.wstx.sax; - -import java.io.*; -import java.net.URL; -import javax.xml.XMLConstants; -import javax.xml.parsers.SAXParser; -import javax.xml.stream.Location; -import javax.xml.stream.XMLResolver; -import javax.xml.stream.XMLStreamConstants; -import javax.xml.stream.XMLStreamException; - -import org.xml.sax.*; -import org.xml.sax.helpers.DefaultHandler; -import org.xml.sax.ext.Attributes2; -import org.xml.sax.ext.DeclHandler; -import org.xml.sax.ext.LexicalHandler; -import org.xml.sax.ext.Locator2; - -//import org.codehaus.stax2.DTDInfo; - -import com.ctc.wstx.api.ReaderConfig; -import com.ctc.wstx.dtd.DTDEventListener; -import com.ctc.wstx.exc.WstxIOException; -import com.ctc.wstx.io.DefaultInputResolver; -import com.ctc.wstx.io.InputBootstrapper; -import com.ctc.wstx.io.ReaderBootstrapper; -import com.ctc.wstx.io.StreamBootstrapper; -import com.ctc.wstx.sr.*; -import com.ctc.wstx.stax.WstxInputFactory; -import com.ctc.wstx.util.ExceptionUtil; -import com.ctc.wstx.util.URLUtil; - -/** - * This class implements parser part of JAXP and SAX interfaces; and - * effectively offers an alternative to using Stax input factory / - * stream reader combination. - */ -public class WstxSAXParser - extends SAXParser - implements Parser // SAX1 - ,XMLReader // SAX2 - ,Attributes2 // SAX2 - ,Locator2 // SAX2 - ,DTDEventListener // Woodstox-internal -{ - final static boolean FEAT_DEFAULT_NS_PREFIXES = false; - - /** - * We will need the factory reference mostly for constructing - * underlying stream reader we use. - */ - protected final WstxInputFactory mStaxFactory; - - protected final ReaderConfig mConfig; - - protected boolean mFeatNsPrefixes; - - /** - * Since the stream reader would mostly be just a wrapper around - * the underlying scanner (its main job is to implement Stax - * interface), we can and should just use the scanner. In effect, - * this class is then a replacement of BasicStreamReader, when - * using SAX interfaces. - */ - protected BasicStreamReader mScanner; - - protected AttributeCollector mAttrCollector; - - protected InputElementStack mElemStack; - - // // // Info from xml declaration - - protected String mEncoding; - protected String mXmlVersion; - protected boolean mStandalone; - - // // // Listeners attached: - - protected ContentHandler mContentHandler; - protected DTDHandler mDTDHandler; - private EntityResolver mEntityResolver; - private ErrorHandler mErrorHandler; - - private LexicalHandler mLexicalHandler; - private DeclHandler mDeclHandler; - - // // // State: - - /** - * Number of attributes accessible via {@link Attributes} and - * {@link Attributes2} interfaces, for the current start element. - *

- * Note: does not include namespace declarations, even they are to - * be reported as attributes. - */ - protected int mAttrCount; - - /** - * Need to keep track of number of namespaces, if namespace declarations - * are to be reported along with attributes (see - * {@link #mFeatNsPrefixes}). - */ - protected int mNsCount = 0; - - /* - /////////////////////////////////////////////////////////////////////// - // Life-cycle - /////////////////////////////////////////////////////////////////////// - */ - - /** - *

- * NOTE: this was a protected constructor for versions 4.0 - * and 3.2; changed to public in 4.1 - */ - public WstxSAXParser(WstxInputFactory sf, boolean nsPrefixes) - { - mStaxFactory = sf; - mFeatNsPrefixes = nsPrefixes; - mConfig = sf.createPrivateConfig(); - mConfig.doSupportDTDs(true); - /* Lazy parsing is a tricky thing: although most of the time - * it's useless with SAX, it is actually necessary to be able - * to properly model internal DTD subsets, for example. So, - * we can not really easily determine defaults. - */ - ResolverProxy r = new ResolverProxy(); - /* SAX doesn't distinguish between DTD (ext. subset, PEs) and - * entity (external general entities) resolvers, so let's - * assign them both: - */ - mConfig.setDtdResolver(r); - mConfig.setEntityResolver(r); - mConfig.setDTDEventListener(this); - - /* These settings do not make sense as generic defaults, but - * are helpful when using some test frameworks. Specifically, - * - DTD caching may remove calls to resolvers, changing - * observed behavior - * - Using min. segment length of 1 will force flushing of - * all content before entity expansion, which will - * completely serialize entity resolution calls wrt. - * CHARACTERS events. - */ - // !!! TEST - //mConfig.setShortestReportedTextSegment(1); - //mConfig.doCacheDTDs(false); - } - - /* - * This constructor is provided for two main use cases: testing, - * and introspection via SAX classes (as opposed to JAXP-based - * introspection). - */ - public WstxSAXParser() - { - this(new WstxInputFactory(), FEAT_DEFAULT_NS_PREFIXES); - } - - public final Parser getParser() - { - return this; - } - - public final XMLReader getXMLReader() - { - return this; - } - - /** - * Accessor used to allow configuring all standard Stax configuration - * settings that the underlying reader uses. - * - * @since 4.0.8 - */ - public final ReaderConfig getStaxConfig() { - return mConfig; - } - - /* - /////////////////////////////////////////////////////////////////////// - // Configuration, SAXParser - /////////////////////////////////////////////////////////////////////// - */ - - public boolean isNamespaceAware() { - return mConfig.willSupportNamespaces(); - } - - public boolean isValidating() { - return mConfig.willValidateWithDTD(); - } - - public Object getProperty(String name) - throws SAXNotRecognizedException, SAXNotSupportedException - { - SAXProperty prop = SAXProperty.findByUri(name); - if (prop == SAXProperty.DECLARATION_HANDLER) { - return mDeclHandler; - } else if (prop == SAXProperty.DOCUMENT_XML_VERSION) { - return mXmlVersion; - } else if (prop == SAXProperty.DOM_NODE) { - return null; - } else if (prop == SAXProperty.LEXICAL_HANDLER) { - return mLexicalHandler; - } else if (prop == SAXProperty.XML_STRING) { - return null; - } - - throw new SAXNotRecognizedException("Property '"+name+"' not recognized"); - } - - public void setProperty(String name, Object value) - throws SAXNotRecognizedException, SAXNotSupportedException - { - SAXProperty prop = SAXProperty.findByUri(name); - if (prop == SAXProperty.DECLARATION_HANDLER) { - mDeclHandler = (DeclHandler) value; - return; - } else if (prop == SAXProperty.DOCUMENT_XML_VERSION) { - ; // read-only - } else if (prop == SAXProperty.DOM_NODE) { - ; // read-only - } else if (prop == SAXProperty.LEXICAL_HANDLER) { - mLexicalHandler = (LexicalHandler) value; - return; - } else if (prop == SAXProperty.XML_STRING) { - ; // read-only - } else { - throw new SAXNotRecognizedException("Property '"+name+"' not recognized"); - } - - // Trying to modify read-only properties? - throw new SAXNotSupportedException("Property '"+name+"' is read-only, can not be modified"); - } - - /* - /////////////////////////////////////////////////////////////////////// - // Overrides, SAXParser - /////////////////////////////////////////////////////////////////////// - */ - - /* Have to override some methods from SAXParser; JDK - * implementation is sucky, as it tries to override - * many things it really should not... - */ - - public void parse(InputSource is, HandlerBase hb) - throws SAXException, IOException - { - if (hb != null) { - /* Ok: let's ONLY set if there are no explicit sets... not - * extremely clear, but JDK tries to set them always so - * let's at least do damage control. - */ - if (mContentHandler == null) { - setDocumentHandler(hb); - } - if (mEntityResolver == null) { - setEntityResolver(hb); - } - if (mErrorHandler == null) { - setErrorHandler(hb); - } - if (mDTDHandler == null) { - setDTDHandler(hb); - } - } - parse(is); - } - - public void parse(InputSource is, DefaultHandler dh) - throws SAXException, IOException - { - if (dh != null) { - /* Ok: let's ONLY set if there are no explicit sets... not - * extremely clear, but JDK tries to set them always so - * let's at least do damage control. - */ - if (mContentHandler == null) { - setContentHandler(dh); - } - if (mEntityResolver == null) { - setEntityResolver(dh); - } - if (mErrorHandler == null) { - setErrorHandler(dh); - } - if (mDTDHandler == null) { - setDTDHandler(dh); - } - } - parse(is); - } - - /* - /////////////////////////////////////////////////////////////////////// - // XLMReader (SAX2) implementation: cfg access - /////////////////////////////////////////////////////////////////////// - */ - - public ContentHandler getContentHandler() - { - return mContentHandler; - } - - public DTDHandler getDTDHandler() - { - return mDTDHandler; - } - - public EntityResolver getEntityResolver() - { - return mEntityResolver; - } - - public ErrorHandler getErrorHandler() - { - return mErrorHandler; - } - - public boolean getFeature(String name) - throws SAXNotRecognizedException - { - SAXFeature stdFeat = SAXFeature.findByUri(name); - - if (stdFeat == SAXFeature.EXTERNAL_GENERAL_ENTITIES) { - return mConfig.willSupportExternalEntities(); - } else if (stdFeat == SAXFeature.EXTERNAL_PARAMETER_ENTITIES) { - return mConfig.willSupportExternalEntities(); - } else if (stdFeat == SAXFeature.IS_STANDALONE) { - return mStandalone; - } else if (stdFeat == SAXFeature.LEXICAL_HANDLER_PARAMETER_ENTITIES) { - // !!! TODO: - return false; - } else if (stdFeat == SAXFeature.NAMESPACES) { - return mConfig.willSupportNamespaces(); - } else if (stdFeat == SAXFeature.NAMESPACE_PREFIXES) { - return !mConfig.willSupportNamespaces(); - } else if (stdFeat == SAXFeature.RESOLVE_DTD_URIS) { - // !!! TODO: - return false; - } else if (stdFeat == SAXFeature.STRING_INTERNING) { - return true; - } else if (stdFeat == SAXFeature.UNICODE_NORMALIZATION_CHECKING) { - return false; - } else if (stdFeat == SAXFeature.USE_ATTRIBUTES2) { - return true; - } else if (stdFeat == SAXFeature.USE_LOCATOR2) { - return true; - } else if (stdFeat == SAXFeature.USE_ENTITY_RESOLVER2) { - return true; - } else if (stdFeat == SAXFeature.VALIDATION) { - return mConfig.willValidateWithDTD(); - } else if (stdFeat == SAXFeature.XMLNS_URIS) { - /* !!! TODO: default value should be false... but not sure - * if implementing that mode makes sense - */ - return true; - } else if (stdFeat == SAXFeature.XML_1_1) { - return true; - } - - throw new SAXNotRecognizedException("Feature '"+name+"' not recognized"); - } - - // Already implemented for SAXParser - //public Object getProperty(String name) - - /* - /////////////////////////////////////////////////////////////////////// - // XLMReader (SAX2) implementation: cfg changing - /////////////////////////////////////////////////////////////////////// - */ - - public void setContentHandler(ContentHandler handler) - { - mContentHandler = handler; - } - - public void setDTDHandler(DTDHandler handler) - { - mDTDHandler = handler; - } - - public void setEntityResolver(EntityResolver resolver) - { - mEntityResolver = resolver; - } - - public void setErrorHandler(ErrorHandler handler) - { - mErrorHandler = handler; - } - - public void setFeature(String name, boolean value) - throws SAXNotRecognizedException, SAXNotSupportedException - { - boolean invalidValue = false; - boolean readOnly = false; - SAXFeature stdFeat = SAXFeature.findByUri(name); - - if (stdFeat == SAXFeature.EXTERNAL_GENERAL_ENTITIES) { - mConfig.doSupportExternalEntities(value); - } else if (stdFeat == SAXFeature.EXTERNAL_PARAMETER_ENTITIES) { - // !!! TODO - } else if (stdFeat == SAXFeature.IS_STANDALONE) { - readOnly = true; - } else if (stdFeat == SAXFeature.LEXICAL_HANDLER_PARAMETER_ENTITIES) { - // !!! TODO - } else if (stdFeat == SAXFeature.NAMESPACES) { - mConfig.doSupportNamespaces(value); - } else if (stdFeat == SAXFeature.NAMESPACE_PREFIXES) { - mFeatNsPrefixes = value; - } else if (stdFeat == SAXFeature.RESOLVE_DTD_URIS) { - // !!! TODO - } else if (stdFeat == SAXFeature.STRING_INTERNING) { - invalidValue = !value; - } else if (stdFeat == SAXFeature.UNICODE_NORMALIZATION_CHECKING) { - invalidValue = value; - } else if (stdFeat == SAXFeature.USE_ATTRIBUTES2) { - readOnly = true; - } else if (stdFeat == SAXFeature.USE_LOCATOR2) { - readOnly = true; - } else if (stdFeat == SAXFeature.USE_ENTITY_RESOLVER2) { - readOnly = true; - } else if (stdFeat == SAXFeature.VALIDATION) { - mConfig.doValidateWithDTD(value); - } else if (stdFeat == SAXFeature.XMLNS_URIS) { - invalidValue = !value; - } else if (stdFeat == SAXFeature.XML_1_1) { - readOnly = true; - } else { - throw new SAXNotRecognizedException("Feature '"+name+"' not recognized"); - } - - // Trying to modify read-only properties? - if (readOnly) { - throw new SAXNotSupportedException("Feature '"+name+"' is read-only, can not be modified"); - } - if (invalidValue) { - throw new SAXNotSupportedException("Trying to set invalid value for feature '"+name+"', '"+value+"'"); - } - } - - // Already implemented for SAXParser - //public void setProperty(String name, Object value) - - /* - /////////////////////////////////////////////////////////////////////// - // XLMReader (SAX2) implementation: parsing - /////////////////////////////////////////////////////////////////////// - */ - - public void parse(InputSource input) - throws SAXException - { - mScanner = null; - String systemId = input.getSystemId(); - ReaderConfig cfg = mConfig; - URL srcUrl = null; - - // Let's figure out input, first, before sending start-doc event - InputStream is = null; - Reader r = input.getCharacterStream(); - if (r == null) { - is = input.getByteStream(); - if (is == null) { - if (systemId == null) { - throw new SAXException("Invalid InputSource passed: neither character or byte stream passed, nor system id specified"); - } - try { - srcUrl = URLUtil.urlFromSystemId(systemId); - is = URLUtil.inputStreamFromURL(srcUrl); - } catch (IOException ioe) { - SAXException saxe = new SAXException(ioe); - ExceptionUtil.setInitCause(saxe, ioe); - throw saxe; - } - } - } - - if (mContentHandler != null) { - mContentHandler.setDocumentLocator(this); - mContentHandler.startDocument(); - } - - /* Note: since we are reusing the same config instance, need to - * make sure state is not carried forward. Thus: - */ - cfg.resetState(); - - try { - String inputEnc = input.getEncoding(); - String publicId = input.getPublicId(); - - // Got an InputStream and encoding? Can create a Reader: - if (r == null && (inputEnc != null && inputEnc.length() > 0)) { - r = DefaultInputResolver.constructOptimizedReader(cfg, is, false, inputEnc); - } - InputBootstrapper bs; - if (r != null) { - bs = ReaderBootstrapper.getInstance(publicId, systemId, r, inputEnc); - // false -> not for event reader; false -> no auto-closing - mScanner = (BasicStreamReader) mStaxFactory.createSR(cfg, systemId, bs, false, false); - } else { - bs = StreamBootstrapper.getInstance(publicId, systemId, is); - mScanner = (BasicStreamReader) mStaxFactory.createSR(cfg, systemId, bs, false, false); - } - - // Need to get xml declaration stuff out now: - { - String enc2 = mScanner.getEncoding(); - if (enc2 == null) { - enc2 = mScanner.getCharacterEncodingScheme(); - } - mEncoding = enc2; - } - mXmlVersion = mScanner.getVersion(); - mStandalone = mScanner.standaloneSet(); - mAttrCollector = mScanner.getAttributeCollector(); - mElemStack = mScanner.getInputElementStack(); - fireEvents(); - } catch (IOException io) { - throwSaxException(io); - } catch (XMLStreamException strex) { - throwSaxException(strex); - } finally { - if (mContentHandler != null) { - mContentHandler.endDocument(); - } - // Could try holding onto the buffers, too... but - // maybe it's better to allow them to be reclaimed, if - // needed by GC - if (mScanner != null) { - BasicStreamReader sr = mScanner; - mScanner = null; - try { - sr.close(); - } catch (XMLStreamException sex) { } - } - if (r != null) { - try { - r.close(); - } catch (IOException ioe) { } - } - if (is != null) { - try { - is.close(); - } catch (IOException ioe) { } - } - } - } - - public void parse(String systemId) - throws SAXException - { - InputSource src = new InputSource(systemId); - parse(src); - } - - /* - /////////////////////////////////////////////////////////////////////// - // Parsing loop, helper methods - /////////////////////////////////////////////////////////////////////// - */ - - /** - * This is the actual "tight event loop" that will send all events - * between start and end document events. Although we could - * use the stream reader here, there's not much as it mostly - * just forwards requests to the scanner: and so we can as well - * just copy the little code stream reader's next() method has. - */ - private final void fireEvents() - throws IOException, SAXException, XMLStreamException - { - // First we are in prolog: - int type; - - /* Need to enable lazy parsing, to get DTD start events before - * its content events. Plus, can skip more efficiently too. - */ - mConfig.doParseLazily(false); - - while ((type = mScanner.next()) != XMLStreamConstants.START_ELEMENT) { - fireAuxEvent(type, false); - } - - // Now just starting the tree, need to process the START_ELEMENT - fireStartTag(); - - int depth = 1; - while (true) { - type = mScanner.next(); - if (type == XMLStreamConstants.START_ELEMENT) { - fireStartTag(); - ++depth; - } else if (type == XMLStreamConstants.END_ELEMENT) { - mScanner.fireSaxEndElement(mContentHandler); - if (--depth < 1) { - break; - } - } else if (type == XMLStreamConstants.CHARACTERS) { - mScanner.fireSaxCharacterEvents(mContentHandler); - } else { - fireAuxEvent(type, true); - } - } - - // And then epilog: - while (true) { - type = mScanner.next(); - if (type == XMLStreamConstants.END_DOCUMENT) { - break; - } - if (type == XMLStreamConstants.SPACE) { - // Not to be reported via SAX interface (which may or may not - // be different from Stax) - continue; - } - fireAuxEvent(type, false); - } - } - - private final void fireAuxEvent(int type, boolean inTree) - throws IOException, SAXException, XMLStreamException - { - switch (type) { - case XMLStreamConstants.COMMENT: - mScanner.fireSaxCommentEvent(mLexicalHandler); - break; - case XMLStreamConstants.CDATA: - if (mLexicalHandler != null) { - mLexicalHandler.startCDATA(); - mScanner.fireSaxCharacterEvents(mContentHandler); - mLexicalHandler.endCDATA(); - } else { - mScanner.fireSaxCharacterEvents(mContentHandler); - } - break; - case XMLStreamConstants.DTD: - if (mLexicalHandler != null) { - /* Note: this is bit tricky, since calling getDTDInfo() will - * trigger full reading of the subsets... but we need to - * get some info first, to be able to send dtd-start event, - * and only then get the rest. Thus, need to call separate - * accessors first: - */ - String rootName = mScanner.getDTDRootName(); - String sysId = mScanner.getDTDSystemId(); - String pubId = mScanner.getDTDPublicId(); - mLexicalHandler.startDTD(rootName, pubId, sysId); - // Ok, let's get rest (if any) read: - try { - /*DTDInfo dtdInfo =*/ mScanner.getDTDInfo(); - } catch (WrappedSaxException wse) { - throw wse.getSaxException(); - } - mLexicalHandler.endDTD(); - } - break; - case XMLStreamConstants.PROCESSING_INSTRUCTION: - mScanner.fireSaxPIEvent(mContentHandler); - break; - case XMLStreamConstants.SPACE: - // With SAX, only to be sent as an event if inside the - // tree, not from within prolog/epilog - if (inTree) { - mScanner.fireSaxSpaceEvents(mContentHandler); - } - break; - case XMLStreamConstants.ENTITY_REFERENCE: - /* Only occurs in non-entity-expanding mode; so effectively - * we are skipping the entity? - */ - if (mContentHandler != null) { - mContentHandler.skippedEntity(mScanner.getLocalName()); - } - break; - default: - if (type == XMLStreamConstants.END_DOCUMENT) { - throwSaxException("Unexpected end-of-input in "+(inTree ? "tree" : "prolog")); - } - throw new RuntimeException("Internal error: unexpected type, "+type); - } - } - - private final void fireStartTag() - throws SAXException - { - mAttrCount = mAttrCollector.getCount(); - if (mFeatNsPrefixes) { - /* 15-Dec-2006, TSa: Note: apparently namespace bindings that - * are added via defaulting are only visible via element - * stack. Thus, we MUST access things via element stack, - * not attribute collector; even though latter seems like - * the more direct route. See - * {@link NsInputElementStack#addNsBinding} for the method - * that injects such special namespace bindings (yes, it's - * a hack, afterthought) - */ - //mNsCount = mAttrCollector.getNsCount(); - mNsCount = mElemStack.getCurrentNsCount(); - } - mScanner.fireSaxStartElement(mContentHandler, this); - } - - /* - /////////////////////////////////////////////////////////////////////// - // Parser (SAX1) implementation - /////////////////////////////////////////////////////////////////////// - */ - - // Already implemented for XMLReader: - //public void parse(InputSource source) - //public void parse(String systemId) - //public void setEntityResolver(EntityResolver resolver) - //public void setErrorHandler(ErrorHandler handler) - - public void setDocumentHandler(DocumentHandler handler) - { - setContentHandler(new DocHandlerWrapper(handler)); - } - - public void setLocale(java.util.Locale locale) - { - // Not supported, let's just ignore - } - - /* - /////////////////////////////////////////////////////////////////////// - // Attributes (SAX2) implementation - /////////////////////////////////////////////////////////////////////// - */ - - public int getIndex(String qName) - { - if (mElemStack == null) { - return -1; - } - int ix = mElemStack.findAttributeIndex(null, qName); - // !!! In ns-as-attrs mode, should also match ns decls? - return ix; - } - - public int getIndex(String uri, String localName) - { - if (mElemStack == null) { - return -1; - } - int ix = mElemStack.findAttributeIndex(uri, localName); - // !!! In ns-as-attrs mode, should also match ns decls? - return ix; - } - - public int getLength() - { - return mAttrCount + mNsCount; - } - - public String getLocalName(int index) - { - if (index < mAttrCount) { - return (index < 0) ? null : mAttrCollector.getLocalName(index); - } - index -= mAttrCount; - if (index < mNsCount) { - /* As discussed in fireStartTag, we must use - * element stack, not attribute collector: - */ - //String prefix = mAttrCollector.getNsPrefix(index); - String prefix = mElemStack.getLocalNsPrefix(index); - return (prefix == null || prefix.length() == 0) ? - "xmlns" : prefix; - } - return null; - } - - public String getQName(int index) - { - if (index < mAttrCount) { - if (index < 0) { - return null; - } - String prefix = mAttrCollector.getPrefix(index); - String ln = mAttrCollector.getLocalName(index); - return (prefix == null || prefix.length() == 0) ? - ln : (prefix + ":" + ln); - } - index -= mAttrCount; - if (index < mNsCount) { - /* As discussed in fireStartTag, we must use - * element stack, not attribute collector: - */ - //String prefix = mAttrCollector.getNsPrefix(index); - String prefix = mElemStack.getLocalNsPrefix(index); - if (prefix == null || prefix.length() == 0) { - return "xmlns"; - } - return "xmlns:"+prefix; - } - return null; - } - - public String getType(int index) - { - if (index < mAttrCount) { - if (index < 0) { - return null; - } - /* Note: Woodstox will have separate type for enumerated values; - * SAX considers these NMTOKENs, so may need to convert (but - * note: some SAX impls also use "ENUMERATED") - */ - String type = mElemStack.getAttributeType(index); - // Let's count on it being interned: - if (type == "ENUMERATED") { - type = "NMTOKEN"; - } - return type; - } - // But how about namespace declarations... let's just call them CDATA? - index -= mAttrCount; - if (index < mNsCount) { - return "CDATA"; - } - return null; - } - - public String getType(String qName) - { - return getType(getIndex(qName)); - } - - public String getType(String uri, String localName) - { - return getType(getIndex(uri, localName)); - } - - public String getURI(int index) - { - if (index < mAttrCount) { - if (index < 0) { - return null; - } - String uri = mAttrCollector.getURI(index); - return (uri == null) ? "" : uri; - } - if ((index - mAttrCount) < mNsCount) { - return XMLConstants.XMLNS_ATTRIBUTE_NS_URI; - } - return null; - } - - public String getValue(int index) - { - if (index < mAttrCount) { - return (index < 0) ? null : mAttrCollector.getValue(index); - } - index -= mAttrCount; - if (index < mNsCount) { - /* As discussed in fireStartTag, we must use - * element stack, not attribute collector: - */ - //String uri = mAttrCollector.getNsURI(index); - String uri = mElemStack.getLocalNsURI(index); - return (uri == null) ? "" : uri; - } - return null; - } - - public String getValue(String qName) - { - return getValue(getIndex(qName)); - } - - public String getValue(String uri, String localName) - { - return getValue(getIndex(uri, localName)); - } - - /* - /////////////////////////////////////////////////////////////////////// - // Attributes2 (SAX2) implementation - /////////////////////////////////////////////////////////////////////// - */ - - public boolean isDeclared(int index) - { - if (index < mAttrCount) { - if (index >= 0) { - // !!! TODO: implement properly - return true; - } - } else { - index -= mAttrCount; - if (index < mNsCount) { - /* DTD and namespaces don't really play nicely together; - * and in general xmlns: pseudo-attributes are not declared... - * so not quite sure what to return here. For now, let's - * return true, to indicate they ought to be valid - */ - return true; - } - } - throwNoSuchAttribute(index); - return false; // never gets here - } - - public boolean isDeclared(String qName) - { - return false; - } - - public boolean isDeclared(String uri, String localName) - { - return false; - } - - public boolean isSpecified(int index) - { - if (index < mAttrCount) { - if (index >= 0) { - return mAttrCollector.isSpecified(index); - } - } else { - index -= mAttrCount; - if (index < mNsCount) { - /* Determining default-attr - based namespace declarations - * would need new accessors on Woodstox... but they are - * extremely rare, too - */ - return true; - } - } - throwNoSuchAttribute(index); - return false; // never gets here - } - - public boolean isSpecified(String qName) - { - int ix = getIndex(qName); - if (ix < 0) { - throw new IllegalArgumentException("No attribute with qName '"+qName+"'"); - } - return isSpecified(ix); - } - - public boolean isSpecified(String uri, String localName) - { - int ix = getIndex(uri, localName); - if (ix < 0) { - throw new IllegalArgumentException("No attribute with uri "+uri+", local name '"+localName+"'"); - } - return isSpecified(ix); - } - - /* - /////////////////////////////////////////////////////////////////////// - // Locator (SAX1) implementation - /////////////////////////////////////////////////////////////////////// - */ - - public int getColumnNumber() - { - if (mScanner != null) { - Location loc = mScanner.getLocation(); - return loc.getColumnNumber(); - } - return -1; - } - - public int getLineNumber() - { - if (mScanner != null) { - Location loc = mScanner.getLocation(); - return loc.getLineNumber(); - } - return -1; - } - - public String getPublicId() - { - if (mScanner != null) { - Location loc = mScanner.getLocation(); - return loc.getPublicId(); - } - return null; - } - - public String getSystemId() - { - if (mScanner != null) { - Location loc = mScanner.getLocation(); - return loc.getSystemId(); - } - return null; - } - - /* - /////////////////////////////////////////////////////////////////////// - // Locator2 (SAX2) implementation - /////////////////////////////////////////////////////////////////////// - */ - - public String getEncoding() - { - return mEncoding; - } - - public String getXMLVersion() - { - return mXmlVersion; - } - - /* - /////////////////////////////////////////////////////////////////////// - // DTDEventListener (woodstox internal API) impl - /////////////////////////////////////////////////////////////////////// - */ - - public boolean dtdReportComments() - { - return (mLexicalHandler != null); - } - - public void dtdComment(char[] data, int offset, int len) - { - if (mLexicalHandler != null) { - try { - mLexicalHandler.comment(data, offset, len); - } catch (SAXException sex) { - throw new WrappedSaxException(sex); - } - } - } - - public void dtdProcessingInstruction(String target, String data) - { - if (mContentHandler != null) { - try { - mContentHandler.processingInstruction(target, data); - } catch (SAXException sex) { - throw new WrappedSaxException(sex); - } - } - } - - public void dtdSkippedEntity(String name) - { - if (mContentHandler != null) { - try { - mContentHandler.skippedEntity(name); - } catch (SAXException sex) { - throw new WrappedSaxException(sex); - } - } - } - - // DTD declarations that must be exposed - public void dtdNotationDecl(String name, String publicId, String systemId, URL baseURL) - throws XMLStreamException - { - if (mDTDHandler != null) { - /* 24-Nov-2006, TSa: Note: SAX expects system identifiers to - * be fully resolved when reported... - */ - if (systemId != null && systemId.indexOf(':') < 0) { - try { - systemId = URLUtil.urlFromSystemId(systemId, baseURL).toExternalForm(); - } catch (IOException ioe) { - throw new WstxIOException(ioe); - } - } - try { - mDTDHandler.notationDecl(name, publicId, systemId); - } catch (SAXException sex) { - throw new WrappedSaxException(sex); - } - } - } - - public void dtdUnparsedEntityDecl(String name, String publicId, String systemId, String notationName, URL baseURL) - throws XMLStreamException - { - if (mDTDHandler != null) { - // SAX expects system id to be fully resolved? - if (systemId.indexOf(':') < 0) { // relative path... - try { - systemId = URLUtil.urlFromSystemId(systemId, baseURL).toExternalForm(); - } catch (IOException ioe) { - throw new WstxIOException(ioe); - } - } - try { - mDTDHandler.unparsedEntityDecl(name, publicId, systemId, notationName); - } catch (SAXException sex) { - throw new WrappedSaxException(sex); - } - } - } - - // DTD declarations that can be exposed - - public void attributeDecl(String eName, String aName, String type, String mode, String value) - { - if (mDeclHandler != null) { - try { - mDeclHandler.attributeDecl(eName, aName, type, mode, value); - } catch (SAXException sex) { - throw new WrappedSaxException(sex); - } - } - } - - public void dtdElementDecl(String name, String model) - { - if (mDeclHandler != null) { - try { - mDeclHandler.elementDecl(name, model); - } catch (SAXException sex) { - throw new WrappedSaxException(sex); - } - } - } - - public void dtdExternalEntityDecl(String name, String publicId, String systemId) - { - if (mDeclHandler != null) { - try { - mDeclHandler.externalEntityDecl(name, publicId, systemId); - } catch (SAXException sex) { - throw new WrappedSaxException(sex); - } - } - } - - public void dtdInternalEntityDecl(String name, String value) - { - if (mDeclHandler != null) { - try { - mDeclHandler.internalEntityDecl(name, value); - } catch (SAXException sex) { - throw new WrappedSaxException(sex); - } - } - } - - /* - /////////////////////////////////////////////////////////////////////// - // Internal methods - /////////////////////////////////////////////////////////////////////// - */ - - private void throwSaxException(Exception src) - throws SAXException - { - SAXParseException se = new SAXParseException(src.getMessage(), /*(Locator)*/ this, src); - ExceptionUtil.setInitCause(se, src); - if (mErrorHandler != null) { - mErrorHandler.fatalError(se); - } - throw se; - } - - private void throwSaxException(String msg) - throws SAXException - { - SAXParseException se = new SAXParseException(msg, /*(Locator)*/ this); - if (mErrorHandler != null) { - mErrorHandler.fatalError(se); - } - throw se; - } - - private void throwNoSuchAttribute(int index) - { - throw new IllegalArgumentException("No attribute with index "+index+" (have "+(mAttrCount+mNsCount)+" attributes)"); - } - - /* - ///////////////////////////////////////////////// - // Helper class for dealing with entity resolution - ///////////////////////////////////////////////// - */ - - /** - * Simple helper class that converts from Stax API into SAX - * EntityResolver call(s) - */ - final class ResolverProxy - implements XMLResolver - { - public ResolverProxy() { } - - public Object resolveEntity(String publicID, String systemID, String baseURI, String namespace) - throws XMLStreamException - { - if (mEntityResolver != null) { - try { - /* Hmmh. SAX expects system id to have been mangled prior - * to call... this may work, depending on stax impl: - */ - URL url = new URL(baseURI); - String ref = new URL(url, systemID).toExternalForm(); - InputSource isrc = mEntityResolver.resolveEntity(publicID, ref); - if (isrc != null) { - //System.err.println("Debug: succesfully resolved '"+publicID+"', '"+systemID+"'"); - InputStream in = isrc.getByteStream(); - if (in != null) { - return in; - } - Reader r = isrc.getCharacterStream(); - if (r != null) { - return r; - } - } - - // Returning null should be fine, actually... - return null; - } catch (IOException ex) { - throw new WstxIOException(ex); - } catch (Exception ex) { - throw new XMLStreamException(ex.getMessage(), ex); - } - } - return null; - } - } - - /* - /////////////////////////////////////////////////////////////////////// - // Helper classes for SAX1 support - /////////////////////////////////////////////////////////////////////// - */ - - final static class DocHandlerWrapper - implements ContentHandler - { - final DocumentHandler mDocHandler; - - final AttributesWrapper mAttrWrapper = new AttributesWrapper(); - - DocHandlerWrapper(DocumentHandler h) - { - mDocHandler = h; - } - - public void characters(char[] ch, int start, int length) - throws SAXException - { - mDocHandler.characters(ch, start, length); - } - - public void endDocument() throws SAXException - { - mDocHandler.endDocument(); - } - - public void endElement(String uri, String localName, String qName) - throws SAXException - { - if (qName == null) { - qName = localName; - } - mDocHandler.endElement(qName); - } - - public void endPrefixMapping(String prefix) - { - // no equivalent in SAX1, ignore - } - - public void ignorableWhitespace(char[] ch, int start, int length) - throws SAXException - { - mDocHandler.ignorableWhitespace(ch, start, length); - } - - public void processingInstruction(String target, String data) - throws SAXException - { - mDocHandler.processingInstruction(target, data); - } - - public void setDocumentLocator(Locator locator) - { - mDocHandler.setDocumentLocator(locator); - } - - public void skippedEntity(String name) - { - // no equivalent in SAX1, ignore - } - - public void startDocument() - throws SAXException - { - mDocHandler.startDocument(); - } - - public void startElement(String uri, String localName, String qName, - Attributes attrs) - throws SAXException - { - if (qName == null) { - qName = localName; - } - // Also, need to wrap Attributes to look like AttributeLost - mAttrWrapper.setAttributes(attrs); - mDocHandler.startElement(qName, mAttrWrapper); - } - - public void startPrefixMapping(String prefix, String uri) - { - // no equivalent in SAX1, ignore - } - } - - final static class AttributesWrapper - implements AttributeList - { - Attributes mAttrs; - - public AttributesWrapper() { } - - public void setAttributes(Attributes a) { - mAttrs = a; - } - - public int getLength() - { - return mAttrs.getLength(); - } - - public String getName(int i) - { - String n = mAttrs.getQName(i); - return (n == null) ? mAttrs.getLocalName(i) : n; - } - - public String getType(int i) - { - return mAttrs.getType(i); - } - - public String getType(String name) - { - return mAttrs.getType(name); - } - - public String getValue(int i) - { - return mAttrs.getValue(i); - } - - public String getValue(String name) - { - return mAttrs.getValue(name); - } - } -} - diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/sr/AttributeCollector.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/sr/AttributeCollector.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/sr/AttributeCollector.java 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/sr/AttributeCollector.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,1145 +0,0 @@ -/* Woodstox XML processor - * - * Copyright (c) 2004- Tatu Saloranta, tatu.saloranta@iki.fi - * - * Licensed under the License specified in file LICENSE, included with - * the source code. - * You may not use this file except in compliance with the License. - * - * 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 com.ctc.wstx.sr; - -import java.io.IOException; -import java.util.Arrays; - -import javax.xml.XMLConstants; -import javax.xml.stream.Location; -import javax.xml.stream.XMLStreamException; -import javax.xml.namespace.QName; - -import org.codehaus.stax2.ri.typed.CharArrayBase64Decoder; -import org.codehaus.stax2.ri.typed.ValueDecoderFactory; -import org.codehaus.stax2.typed.Base64Variant; -import org.codehaus.stax2.typed.TypedArrayDecoder; -import org.codehaus.stax2.typed.TypedValueDecoder; -import org.codehaus.stax2.typed.TypedXMLStreamException; -import org.codehaus.stax2.validation.XMLValidator; - -import com.ctc.wstx.api.ReaderConfig; -import com.ctc.wstx.cfg.ErrorConsts; -import com.ctc.wstx.sw.XmlWriter; -import com.ctc.wstx.util.*; - -/** - * Shared base class that defines API stream reader uses to communicate - * with the attribute collector implementation, independent of whether it's - * operating in namespace-aware or non-namespace modes. - * Collector class is used to build up attribute lists; for the most part - * will just hold references to few specialized {@link TextBuilder}s that - * are used to create efficient semi-shared value Strings. - */ -public final class AttributeCollector -{ - final static int INT_SPACE = 0x0020; - - /** - * Threshold value that indicates minimum length for lists instances - * that need a Map structure, for fast attribute access by fully-qualified - * name. - */ - protected final static int LONG_ATTR_LIST_LEN = 4; - - /** - * Expected typical maximum number of attributes for any element; - * chosen to minimize need to resize, while trying not to waste space. - * Dynamically grown; better not to set too high to avoid excessive - * overhead for small attribute-less documents. - */ - protected final static int EXP_ATTR_COUNT = 12; - - protected final static int EXP_NS_COUNT = 6; - - /** - * This value is used to indicate that we shouldn't keep track - * of index of xml:id attribute -- generally done when Xml:id - * support is disabled - */ - protected final static int XMLID_IX_DISABLED = -2; - - protected final static int XMLID_IX_NONE = -1; - - protected final static InternCache sInternCache = InternCache.getInstance(); - - /* - /////////////////////////////////////////////////////////// - // Configuration - /////////////////////////////////////////////////////////// - */ - - // // Settings for matching Xml:id attribute - - final String mXmlIdPrefix; - final String mXmlIdLocalName; - - /* - /////////////////////////////////////////////////////////// - // Collected attribute (incl namespace attrs) information: - /////////////////////////////////////////////////////////// - */ - - /** - * Array of attributes collected for this element. - */ - protected Attribute[] mAttributes; - - /** - * Actual number of attributes collected, including attributes - * added via default values. - */ - protected int mAttrCount; - - /** - * Number of attribute values actually parsed, not including - * ones created via default value expansion. Equal to or less than - * {@link #mAttrCount}. - */ - protected int mNonDefCount; - - /** - * Array of namespace declaration attributes collected for this element; - * not used in non-namespace-aware mode - */ - protected Attribute[] mNamespaces; - - /** - * Number of valid namespace declarations in {@link #mNamespaces}. - */ - protected int mNsCount; - - /** - * Flag to indicate whether the default namespace has already been declared - * for the current element. - */ - protected boolean mDefaultNsDeclared = false; - - /** - * Index of "xml:id" attribute, if one exists for the current - * element; {@link #XMLID_IX_NONE} if none. - */ - protected int mXmlIdAttrIndex; - - /* - /////////////////////////////////////////////////////////// - // Attribute (and ns) value builders - /////////////////////////////////////////////////////////// - */ - - /** - * TextBuilder into which values of all attributes are appended - * to, including default valued ones (defaults are added after - * explicit ones). - * Constructed lazily, if and when needed (not needed - * for short attribute-less docs) - */ - protected TextBuilder mValueBuilder = null; - - /** - * TextBuilder into which values of namespace URIs are added (including - * URI for the default namespace, if one defined). - */ - private final TextBuilder mNamespaceBuilder = new TextBuilder(EXP_NS_COUNT); - - /* - ////////////////////////////////////////////////////////////// - // Information that defines "Map-like" data structure used for - // quick access to attribute values by fully-qualified name - ////////////////////////////////////////////////////////////// - */ - - /** - * Encoding of a data structure that contains mapping from - * attribute names to attribute index in main attribute name arrays. - *

- * Data structure contains two separate areas; main hash area (with - * size mAttrHashSize), and remaining spillover area - * that follows hash area up until (but not including) - * mAttrSpillEnd index. - * Main hash area only contains indexes (index+1; 0 signifying empty slot) - * to actual attributes; spillover area has both hash and index for - * any spilled entry. Spilled entries are simply stored in order - * added, and need to be searched using linear search. In case of both - * primary hash hits and spills, eventual comparison with the local - * name needs to be done with actual name array. - */ - protected int[] mAttrMap = null; - - /** - * Size of hash area in mAttrMap; generally at least 20% - * more than number of attributes (mAttrCount). - */ - protected int mAttrHashSize; - - /** - * Pointer to int slot right after last spill entr, in - * mAttrMap array. - */ - protected int mAttrSpillEnd; - - /* - /////////////////////////////////////////////// - // Life-cycle: - /////////////////////////////////////////////// - */ - - protected AttributeCollector(ReaderConfig cfg, boolean nsAware) - { - mXmlIdAttrIndex = cfg.willDoXmlIdTyping() ? XMLID_IX_NONE : XMLID_IX_DISABLED; - if (nsAware) { - mXmlIdPrefix = "xml"; - mXmlIdLocalName = "id"; - } else { - mXmlIdPrefix = null; - mXmlIdLocalName = "xml:id"; - } - } - - /** - * Method called to allow reusing of collector, usually right before - * starting collecting attributes for a new start tag. - */ - /** - * Method called to allow reusing of collector, usually right before - * starting collecting attributes for a new start tag. - *

- * Note: public only so that it can be called by unit tests. - */ - public void reset() - { - if (mNsCount > 0) { - mNamespaceBuilder.reset(); - mDefaultNsDeclared = false; - mNsCount = 0; - } - - /* No need to clear attr name, or NS prefix Strings; they are - * canonicalized and will be referenced by symbol table in any - * case... so we can save trouble of cleaning them up. This Object - * will get GC'ed soon enough, after parser itself gets disposed of. - */ - if (mAttrCount > 0) { - mValueBuilder.reset(); - mAttrCount = 0; - if (mXmlIdAttrIndex >= 0) { - mXmlIdAttrIndex = XMLID_IX_NONE; - } - } - /* Note: attribute values will be cleared later on, when validating - * namespaces. This so that we know how much to clean up; and - * occasionally can also just avoid clean up (when resizing) - */ - } - - /** - * Method that can be called to force space normalization (remove - * leading/trailing spaces, replace non-spaces white space with - * spaces, collapse spaces to one) on specified attribute. - * Currently called by {@link InputElementStack} to force - * normalization of Xml:id attribute - */ - public void normalizeSpacesInValue(int index) - { - // StringUtil has a method, but it works on char arrays... - char[] attrCB = mValueBuilder.getCharBuffer(); - String normValue = StringUtil.normalizeSpaces - (attrCB, getValueStartOffset(index), getValueStartOffset(index+1)); - if (normValue != null) { - mAttributes[index].setValue(normValue); - } - } - - /* - /////////////////////////////////////////////// - // Public accesors (for stream reader) - /////////////////////////////////////////////// - */ - - /** - * @return Number of namespace declarations collected, including - * possible default namespace declaration - */ - protected int getNsCount() { - return mNsCount; - } - - public boolean hasDefaultNs() { - return mDefaultNsDeclared; - } - - // // // Direct access to attribute/NS prefixes/localnames/URI - - public final int getCount() { - return mAttrCount; - } - - /** - * @return Number of attributes that were explicitly specified; may - * be less than the total count due to attributes created using - * attribute default values - */ - public int getSpecifiedCount() { - return mNonDefCount; - } - - public String getNsPrefix(int index) { - if (index < 0 || index >= mNsCount) { - throwIndex(index); - } - // for NS decls, local name is stored in prefix - return mNamespaces[index].mLocalName; - } - - public String getNsURI(int index) { - if (index < 0 || index >= mNsCount) { - throwIndex(index); - } - return mNamespaces[index].mNamespaceURI; - } - - // // // Direct access to attribute/NS prefixes/localnames/URI - - public String getPrefix(int index) { - if (index < 0 || index >= mAttrCount) { - throwIndex(index); - } - return mAttributes[index].mPrefix; - } - - public String getLocalName(int index) { - if (index < 0 || index >= mAttrCount) { - throwIndex(index); - } - return mAttributes[index].mLocalName; - } - - public String getURI(int index) { - if (index < 0 || index >= mAttrCount) { - throwIndex(index); - } - return mAttributes[index].mNamespaceURI; - } - - public QName getQName(int index) { - if (index < 0 || index >= mAttrCount) { - throwIndex(index); - } - return mAttributes[index].getQName(); - } - - /** - *

- * Note: the main reason this method is defined at this level, and - * made final, is performance. JIT may be able to fully inline this - * method, even when reference is via this base class. This is important - * since this is likely to be the most often called method of the - * collector instances. - */ - public final String getValue(int index) - { - if (index < 0 || index >= mAttrCount) { - throwIndex(index); - } - String full = mValueBuilder.getAllValues(); - Attribute attr = mAttributes[index]; - ++index; - if (index < mAttrCount) { // not last - int endOffset = mAttributes[index].mValueStartOffset; - return attr.getValue(full, endOffset); - } - // last can be optimized bit more: - return attr.getValue(full); - } - - public String getValue(String nsURI, String localName) - { - // Primary hit? - int hashSize = mAttrHashSize; - if (hashSize == 0) { // sanity check, for 'no attributes' - return null; - } - int hash = localName.hashCode(); - if (nsURI != null) { - if (nsURI.length() == 0) { - nsURI = null; - } else { - hash ^= nsURI.hashCode(); - } - } - int ix = mAttrMap[hash & (hashSize-1)]; - if (ix == 0) { // nothing in here; no spills either - return null; - } - --ix; - - // Is primary candidate match? - if (mAttributes[ix].hasQName(nsURI, localName)) { - return getValue(ix); - } - - /* Nope, need to traverse spill list, which has 2 entries for - * each spilled attribute id; first for hash value, second index. - */ - for (int i = hashSize, len = mAttrSpillEnd; i < len; i += 2) { - if (mAttrMap[i] != hash) { - continue; - } - /* Note: spill indexes are not off-by-one, since there's no need - * to mask 0 - */ - ix = mAttrMap[i+1]; - if (mAttributes[ix].hasQName(nsURI, localName)) { - return getValue(ix); - } - } - - return null; - } - - public int findIndex(String localName) { - return findIndex(null, localName); - } - - public int findIndex(String nsURI, String localName) - { - /* Note: most of the code is from getValue().. could refactor - * code, performance is bit of concern (one more method call - * if index access was separate). - * See comments on that method, for logics. - */ - - // Primary hit? - int hashSize = mAttrHashSize; - if (hashSize == 0) { // sanity check, for 'no attributes' - return -1; - } - int hash = localName.hashCode(); - if (nsURI != null) { - if (nsURI.length() == 0) { - nsURI = null; - } else { - hash ^= nsURI.hashCode(); - } - } - int ix = mAttrMap[hash & (hashSize-1)]; - if (ix == 0) { // nothing in here; no spills either - return -1; - } - --ix; - - // Is primary candidate match? - if (mAttributes[ix].hasQName(nsURI, localName)) { - return ix; - } - - /* Nope, need to traverse spill list, which has 2 entries for - * each spilled attribute id; first for hash value, second index. - */ - for (int i = hashSize, len = mAttrSpillEnd; i < len; i += 2) { - if (mAttrMap[i] != hash) { - continue; - } - /* Note: spill indexes are not off-by-one, since there's no need - * to mask 0 - */ - ix = mAttrMap[i+1]; - if (mAttributes[ix].hasQName(nsURI, localName)) { - return ix; - } - } - return -1; - } - - public final boolean isSpecified(int index) { - return (index < mNonDefCount); - } - - public final int getXmlIdAttrIndex() { - return mXmlIdAttrIndex; - } - - /* - ////////////////////////////////////////////////////// - // Type-safe accessors to support TypedXMLStreamReader - ////////////////////////////////////////////////////// - */ - - /** - * Method called to decode the whole attribute value as a single - * typed value. - * Decoding is done using the decoder provided. - */ - public final void decodeValue(int index, TypedValueDecoder tvd) - throws IllegalArgumentException - { - if (index < 0 || index >= mAttrCount) { - throwIndex(index); - } - /* Should be faster to pass the char array even if we might - * have a String - */ - // Either way, need to trim before passing: - char[] buf = mValueBuilder.getCharBuffer(); - int start = mAttributes[index].mValueStartOffset; - int end = getValueStartOffset(index+1); - - while (true) { - if (start >= end) { - tvd.handleEmptyValue(); - return; - } - if (!StringUtil.isSpace(buf[start])) { - break; - } - ++start; - } - // Trailing space? - while (--end > start && StringUtil.isSpace(buf[end])) { } - tvd.decode(buf, start, end+1); - } - - /** - * Method called to decode the attribute value that consists of - * zero or more space-separated tokens. - * Decoding is done using the decoder provided. - * @return Number of tokens decoded - */ - public final int decodeValues(int index, TypedArrayDecoder tad, - InputProblemReporter rep) - throws XMLStreamException - { - if (index < 0 || index >= mAttrCount) { - throwIndex(index); - } - // Char[] faster than String... and no need to trim here: - return decodeValues(tad, rep, - mValueBuilder.getCharBuffer(), - mAttributes[index].mValueStartOffset, - getValueStartOffset(index+1)); - } - - public final byte[] decodeBinary(int index, Base64Variant v, CharArrayBase64Decoder dec, - InputProblemReporter rep) - throws XMLStreamException - { - if (index < 0 || index >= mAttrCount) { - throwIndex(index); - } - /* No point in trying to use String representation, even if one - * available, faster to process from char[] - */ - Attribute attr = mAttributes[index]; - char[] cbuf = mValueBuilder.getCharBuffer(); - int start = attr.mValueStartOffset; - int end = getValueStartOffset(index+1); - int len = end-start; - dec.init(v, true, cbuf, start, len, null); - try { - return dec.decodeCompletely(); - } catch (IllegalArgumentException iae) { - // Need to convert to a checked stream exception - String lexical = new String(cbuf, start, len); - throw new TypedXMLStreamException(lexical, iae.getMessage(), rep.getLocation(), iae); - } - } - - private final static int decodeValues(TypedArrayDecoder tad, - InputProblemReporter rep, - final char[] buf, int ptr, final int end) - throws XMLStreamException - { - int start = ptr; - int count = 0; - - try { - decode_loop: - while (ptr < end) { - // First, any space to skip? - while (buf[ptr] <= INT_SPACE) { - if (++ptr >= end) { - break decode_loop; - } - } - // Then let's figure out non-space char (token) - start = ptr; - ++ptr; - while (ptr < end && buf[ptr] > INT_SPACE) { - ++ptr; - } - int tokenEnd = ptr; - ++ptr; // to skip trailing space (or, beyond end) - // Ok, decode... any more room? - ++count; - if (tad.decodeValue(buf, start, tokenEnd)) { - if (!checkExpand(tad)) { - break; - } - } - } - } catch (IllegalArgumentException iae) { - // Need to convert to a checked stream exception - Location loc = rep.getLocation(); - String lexical = new String(buf, start, (ptr-start)); - throw new TypedXMLStreamException(lexical, iae.getMessage(), loc, iae); - } - return count; - } - - /** - * Internal method used to see if we can expand the buffer that - * the array decoder has. Bit messy, but simpler than having - * separately typed instances; and called rarely so that performance - * downside of instanceof is irrelevant. - */ - private final static boolean checkExpand(TypedArrayDecoder tad) - { - if (tad instanceof ValueDecoderFactory.BaseArrayDecoder) { - ((ValueDecoderFactory.BaseArrayDecoder) tad).expand(); - return true; - } - return false; - } - - /* - /////////////////////////////////////////////// - // Accessors for accessing helper objects - /////////////////////////////////////////////// - */ - - /** - * Method for getting start pointer within shared value buffer - * for given attribute. It is also the same as end pointer - * for preceding attribute, if any. - */ - protected int getValueStartOffset(int index) - { - if (index < mAttrCount) { - return mAttributes[index].mValueStartOffset; - } - return mValueBuilder.getCharSize(); - } - - protected char[] getSharedValueBuffer() - { - return mValueBuilder.getCharBuffer(); - } - - /** - * Method called to resolve and initialize specified collected - * namespace declaration - * - * @return Attribute that contains specified namespace declaration - */ - protected Attribute resolveNamespaceDecl(int index, boolean internURI) - { - Attribute ns = mNamespaces[index]; - String full = mNamespaceBuilder.getAllValues(); - String uri; - - if (mNsCount == 0) { - uri = full; - } else { - ++index; - if (index < mNsCount) { // not last - int endOffset = mNamespaces[index].mValueStartOffset; - uri = ns.getValue(full, endOffset); - } else { // is last - uri = ns.getValue(full); - } - } - if (internURI && uri.length() > 0) { - uri = sInternCache.intern(uri); - } - ns.mNamespaceURI = uri; - return ns; - } - - /** - * Method needed by event creating code, to build a non-transient - * attribute container, to use with XMLEvent objects (specifically - * implementation of StartElement event). - */ - public ElemAttrs buildAttrOb() - { - int count = mAttrCount; - if (count == 0) { - return null; - } - /* If we have actual attributes, let's first just create the - * raw array that has all attribute information: - */ - String[] raw = new String[count << 2]; - for (int i = 0; i < count; ++i) { - Attribute attr = mAttributes[i]; - int ix = (i << 2); - raw[ix] = attr.mLocalName; - raw[ix+1] = attr.mNamespaceURI; - raw[ix+2] = attr.mPrefix; - raw[ix+3] = getValue(i); - } - - // Do we have a "short" list? - if (count < LONG_ATTR_LIST_LEN) { - return new ElemAttrs(raw, mNonDefCount); - } - - // Ok, nope; we need to also pass the Map information... - /* 02-Feb-2009, TSa: Must make a copy of the Map array now, - * otherwise could get overwritten. - */ - int amapLen = mAttrMap.length; - int[] amap = new int[amapLen]; - // TODO: JDK 1.6 has Arrays.copyOf(), should use with Woodstox 6 - System.arraycopy(mAttrMap, 0, amap, 0, amapLen); - return new ElemAttrs(raw, mNonDefCount, - amap, mAttrHashSize, mAttrSpillEnd); - } - - protected void validateAttribute(int index, XMLValidator vld) - throws XMLStreamException - { - Attribute attr = mAttributes[index]; - String normValue = vld.validateAttribute - (attr.mLocalName, attr.mNamespaceURI, attr.mPrefix, - mValueBuilder.getCharBuffer(), - getValueStartOffset(index), - getValueStartOffset(index+1)); - - if (normValue != null) { - attr.setValue(normValue); - } - } - - /* - /////////////////////////////////////////////// - // Attribute, namespace decl building - /////////////////////////////////////////////// - */ - - /** - * Low-level accessor method that attribute validation code may call - * for certain types of attributes; generally only for id and idref/idrefs - * attributes. It returns the underlying 'raw' attribute value buffer - * for direct access. - */ - public final TextBuilder getAttrBuilder(String attrPrefix, String attrLocalName) - { - /* Ok: we have parsed prefixed-name of a regular - * attribute. So let's initialize the instance... - */ - if (mAttrCount == 0) { - if (mAttributes == null) { - allocBuffers(); - } - mAttributes[0] = new Attribute(attrPrefix, attrLocalName, 0); - } else { - int valueStart = mValueBuilder.getCharSize(); - if (mAttrCount >= mAttributes.length) { - mAttributes = (Attribute[]) DataUtil.growArrayBy50Pct(mAttributes); - } - Attribute curr = mAttributes[mAttrCount]; - if (curr == null) { - mAttributes[mAttrCount] = new Attribute(attrPrefix, attrLocalName, valueStart); - } else { - curr.reset(attrPrefix, attrLocalName, valueStart); - } - } - ++mAttrCount; - // 25-Sep-2006, TSa: Need to keep track of xml:id attribute? - if (attrLocalName == mXmlIdLocalName) { - if (attrPrefix == mXmlIdPrefix) { - if (mXmlIdAttrIndex != XMLID_IX_DISABLED) { - mXmlIdAttrIndex = mAttrCount - 1; - } - } - } - /* Can't yet create attribute map by name, since we only know - * name prefix, not necessarily matching URI. - */ - return mValueBuilder; - } - - /** - * Method called by validator to insert an attribute that has a default - * value and wasn't yet included in collector's attribute set. - * - * @return Index of the newly added attribute, if added; -1 to indicate - * this was a duplicate - */ - public int addDefaultAttribute(String localName, String uri, String prefix, - String value) - { - int attrIndex = mAttrCount; - if (attrIndex < 1) { - /* had no explicit attributes... better initialize now, then. - * Let's just use hash area of 4, and - */ - initHashArea(); - } - - /* Ok, first, since we do want to verify that we can not accidentally - * add duplicates, let's first try to add entry to Map, since that - * will catch dups. - */ - int hash = localName.hashCode(); - if (uri != null && uri.length() > 0) { - hash ^= uri.hashCode(); - } - int index = hash & (mAttrHashSize - 1); - int[] map = mAttrMap; - if (map[index] == 0) { // whoa, have room... - map[index] = attrIndex+1; // add 1 to get 1-based index (0 is empty marker) - } else { // nah, collision... - int currIndex = map[index]-1; // Index of primary collision entry - int spillIndex = mAttrSpillEnd; - map = spillAttr(uri, localName, map, currIndex, spillIndex, - attrIndex, hash, mAttrHashSize); - if (map == null) { // dup! - return -1; // could return negation (-(index+1)) of the prev index? - } - map[++spillIndex] = attrIndex; // no need to specifically avoid 0 - mAttrMap = map; - mAttrSpillEnd = ++spillIndex; - } - - /* Can reuse code; while we don't really need the builder, - * we need to add/reset attribute - */ - getAttrBuilder(prefix, localName); - Attribute attr = mAttributes[mAttrCount-1]; - attr.mNamespaceURI = uri; - attr.setValue(value); - // attribute count has been updated; index is one less than count - return (mAttrCount-1); - } - - /** - * Low-level mutator method that attribute validation code may call - * for certain types of attributes, when it wants to handle the whole - * validation and normalization process by itself. It is generally - * only called for id and idref/idrefs attributes, as those values - * are usually normalized. - */ - public final void setNormalizedValue(int index, String value) - { - mAttributes[index].setValue(value); - } - - /** - * @return null if the default namespace URI has been already declared - * for the current element; TextBuilder to add URI to if not. - */ - public TextBuilder getDefaultNsBuilder() - { - if (mDefaultNsDeclared) { - return null; - } - mDefaultNsDeclared = true; - return getNsBuilder(null); - } - - /** - * @return null if prefix has been already declared; TextBuilder to - * add value to if not. - */ - public TextBuilder getNsBuilder(String prefix) - { - // first: must verify that it's not a dup - if (mNsCount == 0) { - if (mNamespaces == null) { - mNamespaces = new Attribute[EXP_NS_COUNT]; - } - mNamespaces[0] = new Attribute(null, prefix, 0); - } else { - int len = mNsCount; - /* Ok: must ensure that there are no duplicate namespace - * declarations (ie. decls with same prefix being bound) - */ - if (prefix != null) { // null == default ns - for (int i = 0; i < len; ++i) { - // note: for ns decls, bound prefix is in 'local name' - if (prefix == mNamespaces[i].mLocalName) { - return null; - } - } - } - if (len >= mNamespaces.length) { - mNamespaces = (Attribute[]) DataUtil.growArrayBy50Pct(mNamespaces); - } - int uriStart = mNamespaceBuilder.getCharSize(); - Attribute curr = mNamespaces[len]; - if (curr == null) { - mNamespaces[len] = new Attribute(null, prefix, uriStart); - } else { - curr.reset(null, prefix, uriStart); - } - } - ++mNsCount; - return mNamespaceBuilder; - } - - /** - * Method called to resolve namespace URIs from attribute prefixes. - *

- * Note: public only so that it can be called by unit tests. - * - * @param rep Reporter to use for reporting well-formedness problems - * @param ns Namespace prefix/URI mappings active for this element - * - * @return Index of xml:id attribute, if any, -1 if not - */ - public int resolveNamespaces(InputProblemReporter rep, StringVector ns) - throws XMLStreamException - { - int attrCount = mAttrCount; - - /* Let's now set number of 'real' attributes, to allow figuring - * out number of attributes created via default value expansion - */ - mNonDefCount = attrCount; - - if (attrCount < 1) { - // Checked if doing access by FQN: - mAttrHashSize = mAttrSpillEnd = 0; - // And let's just bail out, too... - return mXmlIdAttrIndex; - } - for (int i = 0; i < attrCount; ++i) { - Attribute attr = mAttributes[i]; - String prefix = attr.mPrefix; - // Attributes' ns URI is null after reset, so can skip setting "no namespace" - if (prefix != null) { - if (prefix == "xml") { - attr.mNamespaceURI = XMLConstants.XML_NS_URI; - } else { - String uri = ns.findLastFromMap(prefix); - if (uri == null) { - rep.throwParseError(ErrorConsts.ERR_NS_UNDECLARED_FOR_ATTR, - prefix, attr.mLocalName); - } - attr.mNamespaceURI = uri; - } - } - } - - /* Ok, finally, let's create attribute map, to allow efficient - * access by prefix+localname combination. Could do it on-demand, - * but this way we can check for duplicates right away. - */ - int[] map = mAttrMap; - - /* What's minimum size to contain at most 80% full hash area, - * plus 1/8 spill area (12.5% spilled entries, two ints each)? - */ - int hashCount = 4; - { - int min = attrCount + (attrCount >> 2); // == 80% fill rate - /* Need to get 2^N size that can contain all elements, with - * 80% fill rate - */ - while (hashCount < min) { - hashCount += hashCount; // 2x - } - // And then add the spill area - mAttrHashSize = hashCount; - min = hashCount + (hashCount >> 4); // 12.5 x 2 ints - if (map == null || map.length < min) { - map = new int[min]; - } else { - /* Need to clear old hash entries (if any). But note that - * spilled entries we can leave alone -- they are just ints, - * and get overwritten if and as needed - */ - Arrays.fill(map, 0, hashCount, 0); - } - } - - { - int mask = hashCount-1; - int spillIndex = hashCount; - - // Ok, array's fine, let's hash 'em in! - for (int i = 0; i < attrCount; ++i) { - Attribute attr = mAttributes[i]; - String name = attr.mLocalName; - int hash = name.hashCode(); - String uri = attr.mNamespaceURI; - if (uri != null) { - hash ^= uri.hashCode(); - } - int index = hash & mask; - // Hash slot available? - if (map[index] == 0) { - map[index] = i+1; // since 0 is marker - } else { - int currIndex = map[index]-1; - /* nope, need to spill; let's extract most of that code to - * a separate method for clarity (and maybe it'll be - * easier to inline by JVM too) - */ - map = spillAttr(uri, name, map, currIndex, spillIndex, - attrCount, hash, hashCount); - if (map == null) { - throwDupAttr(rep, currIndex); - // never returns here... - } else { // let's use else to keep FindBugs happy - map[++spillIndex] = i; // no need to specifically avoid 0 - ++spillIndex; - } - } - } - mAttrSpillEnd = spillIndex; - } - mAttrMap = map; - return mXmlIdAttrIndex; - } - - /* - /////////////////////////////////////////////// - // Package/core methods: - /////////////////////////////////////////////// - */ - - protected void throwIndex(int index) { - throw new IllegalArgumentException("Invalid index "+index+"; current element has only "+getCount()+" attributes"); - } - - /** - * Method that basically serializes the specified (read-in) attribute - * using Writers provided. Serialization is done by - * writing out (fully-qualified) name - * of the attribute, followed by the equals sign and quoted value. - */ - - public void writeAttribute(int index, XmlWriter xw) - throws IOException, XMLStreamException - { - // Note: here we assume index checks have been done by caller - Attribute attr = mAttributes[index]; - String ln = attr.mLocalName; - String prefix = attr.mPrefix; - if (prefix == null || prefix.length() == 0) { - xw.writeAttribute(ln, getValue(index)); - } else { - xw.writeAttribute(prefix, ln, getValue(index)); - } - } - - /** - * Method called to initialize buffers that need not be immediately - * initialized - */ - protected final void allocBuffers() - { - if (mAttributes == null) { - mAttributes = new Attribute[8]; - } - if (mValueBuilder == null) { - mValueBuilder = new TextBuilder(EXP_ATTR_COUNT); - } - } - - /* - /////////////////////////////////////////////// - // Internal methods: - /////////////////////////////////////////////// - */ - - /** - * @return Null, if attribute is a duplicate (to indicate error); - * map itself, or resized version, otherwise. - */ - private int[] spillAttr(String uri, String name, - int[] map, int currIndex, int spillIndex, int attrCount, - int hash, int hashCount) - { - // Do we have a dup with primary entry? - /* Can do equality comp for local name, as they - * are always canonicalized: - */ - Attribute oldAttr = mAttributes[currIndex]; - if (oldAttr.mLocalName == name) { - // URIs may or may not be interned though: - String currURI = oldAttr.mNamespaceURI; - if (currURI == uri || (currURI != null && currURI.equals(uri))) { - return null; - } - } - - /* Is there room to spill into? (need to 2 int spaces; one for hash, - * the other for index) - */ - if ((spillIndex + 1)>= map.length) { - // Let's just add room for 4 spills... - map = DataUtil.growArrayBy(map, 8); - } - // Let's first ensure we aren't adding a dup: - for (int j = hashCount; j < spillIndex; j += 2) { - if (map[j] == hash) { - currIndex = map[j+1]; - Attribute attr = mAttributes[currIndex]; - if (oldAttr.mLocalName == name) { - String currURI = attr.mNamespaceURI; - if (currURI == uri || (currURI != null && currURI.equals(uri))) { - return null; - } - } - } - } - map[spillIndex] = hash; - return map; - } - - /** - * Method called to ensure hash area will be properly set up in - * cases where initially no room was needed, but default attribute(s) - * is being added. - */ - private void initHashArea() - { - /* Let's use small hash area of size 4, and one spill; don't - * want too big (need to clear up room), nor too small (only - * collisions) - */ - mAttrHashSize = mAttrSpillEnd = 4; - if (mAttrMap == null || mAttrMap.length < mAttrHashSize) { - mAttrMap = new int[mAttrHashSize+1]; - } - mAttrMap[0] = mAttrMap[1] = mAttrMap[2] = mAttrMap[3] = 0; - allocBuffers(); - } - - /** - * Method that can be used to get the specified attribute value, - * by getting it written using Writer passed in. Can potentially - * save one String allocation, since no (temporary) Strings need - * to be created. - */ - /* - protected final void writeValue(int index, Writer w) - throws IOException - { - mValueBuilder.getEntry(index, w); - } - */ - - protected void throwDupAttr(InputProblemReporter rep, int index) - throws XMLStreamException - { - rep.throwParseError("Duplicate attribute '"+getQName(index)+"'."); - } -} diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/sr/Attribute.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/sr/Attribute.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/sr/Attribute.java 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/sr/Attribute.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,153 +0,0 @@ -/* Woodstox XML processor - * - * Copyright (c) 2004- Tatu Saloranta, tatu.saloranta@iki.fi - * - * Licensed under the License specified in file LICENSE, included with - * the source code. - * You may not use this file except in compliance with the License. - * - * 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 com.ctc.wstx.sr; - -import javax.xml.namespace.QName; - -import com.ctc.wstx.compat.QNameCreator; - -/** - * Container for information collected regarding a single element - * attribute instance. Used for both regular explicit attributes - * and values added via attribute value defaulting. - *

- * This class is not exposed outside of the package and is considered - * part of internal implementation. - * - * @since 4.1 - */ -final class Attribute -{ - // // // Name information - - protected String mLocalName; - - protected String mPrefix; - - protected String mNamespaceURI; - - // // // Value information - - /** - * Numeric offset within text builder that denotes pointer - * to the first character of the value for this attribute - * (or namespace). End offset is derived by looking at - * start pointer of the following attribute; or total - * length for the last entry - */ - protected int mValueStartOffset; - - /** - * Value as a String iff it has been requested once; stored - * here in case it will be accessed again. - */ - protected String mReusableValue; - - /* - ////////////////////////////////////////////////// - // Life-cycle - ////////////////////////////////////////////////// - */ - - public Attribute(String prefix, String localName, int valueStart) - { - mLocalName = localName; - mPrefix = prefix; - mValueStartOffset = valueStart; - } - - public void reset(String prefix, String localName, int valueStart) - { - mLocalName = localName; - mPrefix = prefix; - mValueStartOffset = valueStart; - mNamespaceURI = null; - mReusableValue = null; - } - - /** - * Method called to inject specific value for this attribute. - */ - public void setValue(String value) { - mReusableValue = value; - } - - /* - ////////////////////////////////////////////////// - // Accessors - ////////////////////////////////////////////////// - */ - - /** - * @param uri Namespace URI of the attribute, if any; MUST be - * given as null if no namespace - * @param localName Local name to match. Note: is NOT guaranteed - * to have been interned - * - * @return True if qualified name of this attribute is the same - * as what arguments describe - */ - protected boolean hasQName(String uri, String localName) - { - if (localName != mLocalName && !localName.equals(mLocalName)) { - return false; - } - if (mNamespaceURI == uri) { - return true; - } - if (uri == null) { - return (mNamespaceURI == null) || mNamespaceURI.length() == 0; - } - return (mNamespaceURI != null && uri.equals(mNamespaceURI)); - } - - public QName getQName() - { - if (mPrefix == null) { - if (mNamespaceURI == null) { - return new QName(mLocalName); - } - return new QName(mNamespaceURI, mLocalName); - } - String uri = mNamespaceURI; - if (uri == null) { // Some QName impls (older JDKs) don't like nulls - uri = ""; - } - // For [WSTX-174] need to use indirection: - return QNameCreator.create(uri, mLocalName, mPrefix); - } - - /** - * Method called if this attribute is the last one with value - * in the buffer. If so, end value is implied - */ - public String getValue(String allValues) - { - if (mReusableValue == null) { - mReusableValue = (mValueStartOffset == 0) ? - allValues : allValues.substring(mValueStartOffset); - } - return mReusableValue; - } - - public String getValue(String allValues, int endOffset) - { - if (mReusableValue == null) { - mReusableValue = allValues.substring(mValueStartOffset, endOffset); - } - return mReusableValue; - } -} diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/sr/BasicStreamReader.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/sr/BasicStreamReader.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/sr/BasicStreamReader.java 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/sr/BasicStreamReader.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,5512 +0,0 @@ -/* Woodstox XML processor - * - * Copyright (c) 2004- Tatu Saloranta, tatu.saloranta@iki.fi - * - * Licensed under the License specified in file LICENSE, included with - * the source code. - * You may not use this file except in compliance with the License. - * - * 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 com.ctc.wstx.sr; - -import java.io.*; -import java.text.MessageFormat; -import java.util.Map; - -import org.xml.sax.Attributes; -import org.xml.sax.ContentHandler; -import org.xml.sax.SAXException; -import org.xml.sax.ext.LexicalHandler; - -import javax.xml.namespace.NamespaceContext; -import javax.xml.namespace.QName; -import javax.xml.stream.Location; -import javax.xml.stream.XMLStreamException; - -import org.codehaus.stax2.AttributeInfo; -import org.codehaus.stax2.DTDInfo; -import org.codehaus.stax2.LocationInfo; -import org.codehaus.stax2.XMLStreamLocation2; -import org.codehaus.stax2.XMLStreamProperties; -import org.codehaus.stax2.XMLStreamReader2; -import org.codehaus.stax2.typed.TypedXMLStreamException; -import org.codehaus.stax2.validation.*; - -import com.ctc.wstx.api.ReaderConfig; -import com.ctc.wstx.api.WstxInputProperties; -import com.ctc.wstx.cfg.ErrorConsts; -import com.ctc.wstx.cfg.XmlConsts; -import com.ctc.wstx.dtd.MinimalDTDReader; -import com.ctc.wstx.ent.EntityDecl; -import com.ctc.wstx.exc.WstxException; -import com.ctc.wstx.io.*; -import com.ctc.wstx.util.DefaultXmlSymbolTable; -import com.ctc.wstx.util.TextBuffer; -import com.ctc.wstx.util.TextBuilder; - -/** - * Partial implementation of {@link XMLStreamReader2} consisting of - * all functionality other than DTD-validation-specific parts, and - * Typed Access API (Stax2 v3.0), which are implemented at - * sub-classes. - *

- * - * @author Tatu Saloranta - */ -public abstract class BasicStreamReader - extends StreamScanner - implements StreamReaderImpl, DTDInfo, LocationInfo -{ - - /* - /////////////////////////////////////////////////////////////////////// - // Constants - /////////////////////////////////////////////////////////////////////// - */ - - // // // Standalone values: - - final static int DOC_STANDALONE_UNKNOWN = 0; - final static int DOC_STANDALONE_YES = 1; - final static int DOC_STANDALONE_NO = 2; - - // // // Main state consts: - - final static int STATE_PROLOG = 0; // Before root element - final static int STATE_TREE = 1; // Parsing actual XML tree - final static int STATE_EPILOG = 2; // After root element has been closed - final static int STATE_MULTIDOC_HACK = 3; // State "between" multiple documents (in multi-doc mode) - final static int STATE_CLOSED = 4; // After reader has been closed - - // // // Tokenization state consts: - - // no idea as to what comes next (unknown type): - final static int TOKEN_NOT_STARTED = 0; - - // token type figured out, but not long enough: - final static int TOKEN_STARTED = 1; - - /* minimum token length returnable achieved; only used for CDATA and - * CHARACTERS events which allow fragments to be returned - */ - final static int TOKEN_PARTIAL_SINGLE = 2; - - /* a single physical event has been succesfully tokenized; as with - * partial, only used with CDATA and CHARACTERS (meaningless for others, - * which should only use TOKEN_FULL_COALESCED, TOKEN_NOT_STARTED or - * TOKEN_STARTED. - */ - final static int TOKEN_FULL_SINGLE = 3; - - /* all adjacent (text) events have been tokenized and coalesced (for - * CDATA and CHARACTERS), or that the full event has been parsed (for - * others) - */ - final static int TOKEN_FULL_COALESCED = 4; - - // // // Bit masks used for quick type comparisons - - /** - * This mask covers all types for which basic {@link #getText} method - * can be called. - */ - final protected static int MASK_GET_TEXT = - (1 << CHARACTERS) | (1 << CDATA) | (1 << SPACE) - | (1 << COMMENT) | (1 << DTD) | (1 << ENTITY_REFERENCE); - - /** - * This mask covers all types for which extends getTextXxx - * methods can be called; which is less than those for which - * {@link #getText} can be called. Specifically, DTD and - * ENTITY_REFERENCE types do not support these extended - */ - final protected static int MASK_GET_TEXT_XXX = - (1 << CHARACTERS) | (1 << CDATA) | (1 << SPACE) | (1 << COMMENT); - - /** - * This mask is used with Stax2 getText() method (one that takes - * Writer as an argument): accepts even wider range of event types. - */ - final protected static int MASK_GET_TEXT_WITH_WRITER = - (1 << CHARACTERS) | (1 << CDATA) | (1 << SPACE) - | (1 << COMMENT) | (1 << DTD) | (1 << ENTITY_REFERENCE) - | (1 << PROCESSING_INSTRUCTION); - - final protected static int MASK_GET_ELEMENT_TEXT = - (1 << CHARACTERS) | (1 << CDATA) | (1 << SPACE) - | (1 << ENTITY_REFERENCE); - - - // // // Indicator of type of text in text event (WRT white space) - - final static int ALL_WS_UNKNOWN = 0x0000; - final static int ALL_WS_YES = 0x0001; - final static int ALL_WS_NO = 0x0002; - - /* 2 magic constants used for enabling/disabling indentation checks: - * (to minimize negative impact for both small docs, and large - * docs with non-regular white space) - */ - - private final static int INDENT_CHECK_START = 16; - - private final static int INDENT_CHECK_MAX = 40; - - // // // Shared namespace symbols - - final protected static String sPrefixXml = DefaultXmlSymbolTable.getXmlSymbol(); - - final protected static String sPrefixXmlns = DefaultXmlSymbolTable.getXmlnsSymbol(); - - /* - /////////////////////////////////////////////////////////////////////// - // Configuration - /////////////////////////////////////////////////////////////////////// - */ - - // note: mConfig defined in base class - - /** - * Set of locally stored configuration flags - */ - protected final int mConfigFlags; - - // // // Various extracted settings: - - protected final boolean mCfgCoalesceText; - - protected final boolean mCfgReportTextAsChars; - protected final boolean mCfgLazyParsing; - - /** - * Minimum number of characters parser can return as partial text - * segment, IF it's not required to coalesce adjacent text - * segments. - */ - protected final int mShortestTextSegment; - - /* - /////////////////////////////////////////////////////////////////////// - // Symbol handling: - /////////////////////////////////////////////////////////////////////// - */ - - /** - * Object to notify about shared stuff, such as symbol tables, as well - * as to query for additional config settings if necessary. - */ - final protected ReaderCreator mOwner; - - /* - /////////////////////////////////////////////////////////////////////// - // Additional XML document information, in addition - // to what StreamScanner has - /////////////////////////////////////////////////////////////////////// - */ - - /** - * Status about "stand-aloneness" of document; set to 'yes'/'no'/'unknown' - * based on whether there was xml declaration, and if so, whether - * it had standalone attribute. - */ - protected int mDocStandalone = DOC_STANDALONE_UNKNOWN; - - /* - /////////////////////////////////////////////////////////////////////// - // DOCTYPE information from document type declaration - // (if any found) - /////////////////////////////////////////////////////////////////////// - */ - - /** - * Prefix of root element, as dictated by DOCTYPE declaration; null - * if no DOCTYPE declaration, or no root prefix - */ - String mRootPrefix; - - /** - * Local name of root element, as dictated by DOCTYPE declaration; null - * if no DOCTYPE declaration. - */ - String mRootLName; - - /** - * Public id of the DTD, if one exists and has been parsed. - */ - protected String mDtdPublicId; - - /** - * System id of the DTD, if one exists and has been parsed. - */ - protected String mDtdSystemId; - - /* - /////////////////////////////////////////////////////////////////////// - // Information about currently open subtree, content - /////////////////////////////////////////////////////////////////////// - */ - - /** - * TextBuffer mostly used to collect non-element textual content - * (text, CDATA, comment content, pi data) - */ - final protected TextBuffer mTextBuffer; - - /** - * Currently open element tree - */ - final protected InputElementStack mElementStack; - - /** - * Object that stores information about currently accessible attributes. - */ - final protected AttributeCollector mAttrCollector; - - /* - /////////////////////////////////////////////////////////////////////// - // Tokenization state - //////////////////////////////////////////////////// - */ - - /// Flag set when DOCTYPE declaration has been parsed - protected boolean mStDoctypeFound = false; - - /** - * State of the current token; one of M_ - constants from above. - *

- * Initially set to fully tokenized, since it's the virtual - * START_DOCUMENT event that we fully know by now (parsed by - * bootstrapper) - */ - protected int mTokenState = TOKEN_FULL_COALESCED; - - /** - * Threshold value that defines tokenization state that needs to be - * achieved to "finish" current logical text segment (which - * may consist of adjacent CDATA and text segments; or be a complete - * physical segment; or just even a fragment of such a segment) - */ - protected final int mStTextThreshold; - - /// Flag that indicates current start element is an empty element - protected boolean mStEmptyElem = false; - - /** - * Main parsing/tokenization state (STATE_xxx) - */ - protected int mParseState; - - /** - * Current state of the stream, ie token value returned by - * {@link #getEventType}. Needs to be initialized to START_DOCUMENT, - * since that's the state it starts in. - */ - protected int mCurrToken = START_DOCUMENT; - - /** - * Additional information sometimes stored (when generating dummy - * events in multi-doc mode, for example) temporarily when - * {@link #mCurrToken} is already populated. - */ - protected int mSecondaryToken = START_DOCUMENT; - - /** - * Status of current (text) token's "whitespaceness", that is, - * whether it is or is not all white space. - */ - protected int mWsStatus; - - /** - * Flag that indicates that textual content (CDATA, CHARACTERS) is to - * be validated within current element's scope. Enabled if one of - * validators returns {@link XMLValidator#CONTENT_ALLOW_VALIDATABLE_TEXT}, - * and will prevent lazy parsing of text. - */ - protected boolean mValidateText = false; - - /** - * Counter used for determining whether we are to try to heuristically - * "intern" white space that seems to be used for indentation purposes - */ - protected int mCheckIndentation; - - /** - * Due to the way Stax API does not allow throwing stream exceptions - * from many methods for which Woodstox would need to throw one - * (especially getText and its variations), we may need - * to delay throwing an exception until {@link #next} is called next - * time. If so, this variable holds the pending stream exception. - */ - protected XMLStreamException mPendingException = null; - - /* - /////////////////////////////////////////////////////////////////////// - // DTD information (entities, content spec stub) - /////////////////////////////////////////////////////////////////////// - */ - - /** - * Entities parsed from internal/external DTD subsets. Although it - * will remain null for this class, extended classes make use of it, - * plus, to be able to share some of entity resolution code, instance - * is left here even though it semantically belongs to the sub-class. - */ - protected Map mGeneralEntities = null; - - /** - * Mode information needed at this level; mostly to check what kind - * of textual content (if any) is allowed in current element - * context. Constants come from - * {@link XMLValidator}, - * (like {@link XMLValidator#CONTENT_ALLOW_VALIDATABLE_TEXT}). - * Only used inside tree; ignored for prolog/epilog (which - * have straight-forward static rules). - */ - protected int mVldContent = XMLValidator.CONTENT_ALLOW_ANY_TEXT; - - /** - * Configuration from {@link XMLStreamProperties.RETURN_NULL_FOR_DEFAULT_NAMESPACE} - * - * @since 4.1.2 - */ - protected boolean mReturnNullForDefaultNamespace; - - /* - /////////////////////////////////////////////////////////////////////// - // Instance construction, initialization - /////////////////////////////////////////////////////////////////////// - */ - - /** - * @param elemStack Input element stack to use; if null, will create - * instance locally. - * @param forER Override indicator; if true, this stream reader will be - * used by an event reader, and should modify some of the base config - * settings appropriately. If false, configuration settings are to - * be used as is. - */ - protected BasicStreamReader(InputBootstrapper bs, - BranchingReaderSource input, ReaderCreator owner, - ReaderConfig cfg, InputElementStack elemStack, - boolean forER) - throws XMLStreamException - { - super(input, cfg, cfg.getEntityResolver()); - - mOwner = owner; - - mTextBuffer = TextBuffer.createRecyclableBuffer(cfg); - - // // // First, configuration settings: - - mConfigFlags = cfg.getConfigFlags(); - mCfgCoalesceText = (mConfigFlags & CFG_COALESCE_TEXT) != 0; - mCfgReportTextAsChars = (mConfigFlags & CFG_REPORT_CDATA) == 0; - mXml11 = cfg.isXml11(); - - // Can only use canonical white space if we are normalizing lfs - mCheckIndentation = mNormalizeLFs ? 16 : 0; - - /* 30-Sep-2005, TSa: Let's not do lazy parsing when access is via - * Event API. Reason is that there will be no performance benefit - * (event objects always access full info right after traversal), - * but the wrapping of stream exceptions within runtime exception - * wrappers would happen, which is inconvenient (loss of stack trace, - * not catching all exceptions as expected) - */ - mCfgLazyParsing = !forER && ((mConfigFlags & CFG_LAZY_PARSING) != 0); - - /* There are a few derived settings used during tokenization that - * need to be initialized now... - */ - if (mCfgCoalesceText) { - mStTextThreshold = TOKEN_FULL_COALESCED; - mShortestTextSegment = Integer.MAX_VALUE; - } else { - mStTextThreshold = TOKEN_PARTIAL_SINGLE; - if (forER) { - /* 30-Sep-2005, TSa: No point in returning runt segments for - * event readers (due to event object overhead, less - * convenient); let's just force returning of full length - * segments. - */ - mShortestTextSegment = Integer.MAX_VALUE; - } else { - mShortestTextSegment = cfg.getShortestReportedTextSegment(); - } - } - - // // // Then handling of xml declaration data: - - mDocXmlVersion = bs.getDeclaredVersion(); - mDocInputEncoding = bs.getInputEncoding(); - mDocXmlEncoding = bs.getDeclaredEncoding(); - - String sa = bs.getStandalone(); - if (sa == null) { - mDocStandalone = DOC_STANDALONE_UNKNOWN; - } else { - if (XmlConsts.XML_SA_YES.equals(sa)) { - mDocStandalone = DOC_STANDALONE_YES; - } else { - mDocStandalone = DOC_STANDALONE_NO; - } - } - - /* Ok; either we got declaration or not, but in either case we can - * now initialize prolog parsing settings, without having to really - * parse anything more. - */ - /* 07-Oct-2005, TSa: Except, if we are in fragment mode, in which - * case we are kind of "in tree" mode... - */ - mParseState = mConfig.inputParsingModeFragment() ? - STATE_TREE : STATE_PROLOG; - - // // // And then connecting element stack and attribute collector - - mElementStack = elemStack; - mAttrCollector = elemStack.getAttrCollector(); - - // And finally, location information may have offsets: - input.initInputLocation(this, mCurrDepth); - - elemStack.connectReporter(this); - - Object value = getProperty(WstxInputProperties.P_RETURN_NULL_FOR_DEFAULT_NAMESPACE); - mReturnNullForDefaultNamespace = (value instanceof Boolean) && ((Boolean) value).booleanValue(); - } - - protected static InputElementStack createElementStack(ReaderConfig cfg) - { - return new InputElementStack(cfg, cfg.willSupportNamespaces()); - } - - /* - /////////////////////////////////////////////////////////////////////// - // XMLStreamReader, document info - /////////////////////////////////////////////////////////////////////// - */ - - /** - * As per Stax (1.0) specs, needs to return whatever xml declaration - * claimed encoding is, if any; or null if no xml declaration found. - *

- * Note: method name is rather confusing (compare to {@link #getEncoding}). - */ - public String getCharacterEncodingScheme() { - return mDocXmlEncoding; - } - - /** - * As per Stax (1.0) specs, needs to return whatever parser determined - * the encoding was, if it was able to figure it out. If not (there are - * cases where this can not be found; specifically when being passed a - * {@link Reader}), it should return null. - */ - public String getEncoding() { - return mDocInputEncoding; - } - - public String getVersion() - { - if (mDocXmlVersion == XmlConsts.XML_V_10) { - return XmlConsts.XML_V_10_STR; - } - if (mDocXmlVersion == XmlConsts.XML_V_11) { - return XmlConsts.XML_V_11_STR; - } - return null; // unknown - } - - public boolean isStandalone() { - return mDocStandalone == DOC_STANDALONE_YES; - } - - public boolean standaloneSet() { - return mDocStandalone != DOC_STANDALONE_UNKNOWN; - } - - /* - /////////////////////////////////////////////////////////////////////// - // Public API, configuration - /////////////////////////////////////////////////////////////////////// - */ - - public Object getProperty(String name) - { - /* 18-Nov-2008, TSa: As per [WSTX-50], should report the - * actual Base URL. It can be overridden by matching - * setProperty, but if not, is set to actual source - * of content being parsed. - */ - if (WstxInputProperties.P_BASE_URL.equals(name)) { - return mInput.getSource(); - } - /* 23-Apr-2008, TSa: Let's NOT throw IllegalArgumentException - * for unknown property; JavaDocs do not suggest it needs - * to be done (different from that of XMLInputFactory - * and XMLStreamWriter specification) - */ - return mConfig.safeGetProperty(name); - } - - /* - /////////////////////////////////////////////////////////////////////// - // XMLStreamReader, current state - /////////////////////////////////////////////////////////////////////// - */ - - // // // Attribute access: - - public int getAttributeCount() { - if (mCurrToken != START_ELEMENT) { - throw new IllegalStateException(ErrorConsts.ERR_STATE_NOT_STELEM); - } - return mAttrCollector.getCount(); - } - - public String getAttributeLocalName(int index) { - if (mCurrToken != START_ELEMENT) { - throw new IllegalStateException(ErrorConsts.ERR_STATE_NOT_STELEM); - } - return mAttrCollector.getLocalName(index); - } - - public QName getAttributeName(int index) { - if (mCurrToken != START_ELEMENT) { - throw new IllegalStateException(ErrorConsts.ERR_STATE_NOT_STELEM); - } - return mAttrCollector.getQName(index); - } - - public String getAttributeNamespace(int index) { - if (mCurrToken != START_ELEMENT) { - throw new IllegalStateException(ErrorConsts.ERR_STATE_NOT_STELEM); - } - // Internally it's marked as null, externally need to see "" - String uri = mAttrCollector.getURI(index); - return (uri == null) ? XmlConsts.ATTR_NO_NS_URI : uri; - } - - public String getAttributePrefix(int index) { - if (mCurrToken != START_ELEMENT) { - throw new IllegalStateException(ErrorConsts.ERR_STATE_NOT_STELEM); - } - // Internally it's marked as null, externally need to see "" - String p = mAttrCollector.getPrefix(index); - return (p == null) ? XmlConsts.ATTR_NO_PREFIX : p; - } - - public String getAttributeType(int index) { - if (mCurrToken != START_ELEMENT) { - throw new IllegalStateException(ErrorConsts.ERR_STATE_NOT_STELEM); - } - // Attr. collector doesn't know it, elem stack does: - return mElementStack.getAttributeType(index); - } - - public String getAttributeValue(int index) { - if (mCurrToken != START_ELEMENT) { - throw new IllegalStateException(ErrorConsts.ERR_STATE_NOT_STELEM); - } - return mAttrCollector.getValue(index); - } - - public String getAttributeValue(String nsURI, String localName) { - if (mCurrToken != START_ELEMENT) { - throw new IllegalStateException(ErrorConsts.ERR_STATE_NOT_STELEM); - } - return mAttrCollector.getValue(nsURI, localName); - } - - /** - * From StAX specs: - *

- * Reads the content of a text-only element, an exception is thrown if - * this is not a text-only element. - * Regardless of value of javax.xml.stream.isCoalescing this method always - * returns coalesced content. - *
Precondition: the current event is START_ELEMENT. - *
Postcondition: the current event is the corresponding END_ELEMENT. - *
- */ - public String getElementText() - throws XMLStreamException - { - if (mCurrToken != START_ELEMENT) { - throwParseError(ErrorConsts.ERR_STATE_NOT_STELEM, null, null); - } - /* Ok, now: with START_ELEMENT we know that it's not partially - * processed; that we are in-tree (not prolog or epilog). - * The only possible complication would be: - */ - if (mStEmptyElem) { - /* And if so, we'll then get 'virtual' close tag; things - * are simple as location info was set when dealing with - * empty start element; and likewise, validation (if any) - * has been taken care of - */ - mStEmptyElem = false; - mCurrToken = END_ELEMENT; - return ""; - } - // First need to find a textual event - while (true) { - int type = next(); - if (type == END_ELEMENT) { - return ""; - } - if (type == COMMENT || type == PROCESSING_INSTRUCTION) { - continue; - } - if (((1 << type) & MASK_GET_ELEMENT_TEXT) == 0) { - throw _constructUnexpectedInTyped(type); - } - break; - } - if (mTokenState < TOKEN_FULL_SINGLE) { - readCoalescedText(mCurrToken, false); - } - /* Ok: then a quick check; if it looks like we are directly - * followed by the end tag, we need not construct String - * quite yet. - */ - if ((mInputPtr + 1) < mInputEnd && - mInputBuffer[mInputPtr] == '<' && mInputBuffer[mInputPtr+1] == '/') { - // Note: next() has validated text, no need for more validation - mInputPtr += 2; - mCurrToken = END_ELEMENT; - // must first get text, as call to readEndElem may break it: - String result = mTextBuffer.contentsAsString(); - // Can by-pass next(), nextFromTree(), in this case: - readEndElem(); - // and then return results - return result; - } - - // Otherwise, we'll need to do slower processing - int extra = 1 + (mTextBuffer.size() >> 1); // let's add 50% space - StringBuffer sb = mTextBuffer.contentsAsStringBuffer(extra); - int type; - - while ((type = next()) != END_ELEMENT) { - if (((1 << type) & MASK_GET_ELEMENT_TEXT) != 0) { - if (mTokenState < mStTextThreshold) { - finishToken(false); - } - mTextBuffer.contentsToStringBuffer(sb); - continue; - } - if (type != COMMENT && type != PROCESSING_INSTRUCTION) { - throw _constructUnexpectedInTyped(type); - } - } - // Note: calls next() have validated text, no need for more validation - return sb.toString(); - } - - /** - * Returns type of the last event returned; or START_DOCUMENT before - * any events has been explicitly returned. - */ - public int getEventType() - { - /* Only complication -- multi-part coalesced text is to be reported - * as CHARACTERS always, never as CDATA (StAX specs). - */ - if (mCurrToken == CDATA) { - if (mCfgCoalesceText || mCfgReportTextAsChars) { - return CHARACTERS; - } - } - return mCurrToken; - } - - public String getLocalName() - { - // Note: for this we need not (yet) finish reading element - if (mCurrToken == START_ELEMENT || mCurrToken == END_ELEMENT) { - return mElementStack.getLocalName(); - } - if (mCurrToken == ENTITY_REFERENCE) { - /* 30-Sep-2005, TSa: Entity will be null in non-expanding mode - * if no definition was found: - */ - return (mCurrEntity == null) ? mCurrName: mCurrEntity.getName(); - } - throw new IllegalStateException("Current state not START_ELEMENT, END_ELEMENT or ENTITY_REFERENCE"); - } - - // // // getLocation() defined in StreamScanner - - public QName getName() - { - if (mCurrToken != START_ELEMENT && mCurrToken != END_ELEMENT) { - throw new IllegalStateException(ErrorConsts.ERR_STATE_NOT_ELEM); - } - return mElementStack.getCurrentElementName(); - } - - // // // Namespace access - - public NamespaceContext getNamespaceContext() { - /* Unlike other getNamespaceXxx methods, this is available - * for all events. - * Note that the context is "live", ie. remains active (but not - * static) even through calls to next(). StAX compliant apps - * should not count on this behaviour, however. - */ - return mElementStack; - } - - public int getNamespaceCount() { - if (mCurrToken != START_ELEMENT && mCurrToken != END_ELEMENT) { - throw new IllegalStateException(ErrorConsts.ERR_STATE_NOT_ELEM); - } - return mElementStack.getCurrentNsCount(); - } - - public String getNamespacePrefix(int index) { - if (mCurrToken != START_ELEMENT && mCurrToken != END_ELEMENT) { - throw new IllegalStateException(ErrorConsts.ERR_STATE_NOT_ELEM); - } - // Internally it's marked as null, externally need to see "" or null, depending - String p = mElementStack.getLocalNsPrefix(index); - if (p == null) { - return mReturnNullForDefaultNamespace ? null : XmlConsts.ATTR_NO_PREFIX; - } - return p; - } - - public String getNamespaceURI() { - if (mCurrToken != START_ELEMENT && mCurrToken != END_ELEMENT) { - throw new IllegalStateException(ErrorConsts.ERR_STATE_NOT_ELEM); - } - // Internally it's marked as null, externally need to see "" - String uri = mElementStack.getNsURI(); - return (uri == null) ? XmlConsts.ELEM_NO_NS_URI : uri; - } - - public String getNamespaceURI(int index) - { - if (mCurrToken != START_ELEMENT && mCurrToken != END_ELEMENT) { - throw new IllegalStateException(ErrorConsts.ERR_STATE_NOT_ELEM); - } - // Internally it's marked as null, externally need to see "" - String uri = mElementStack.getLocalNsURI(index); - return (uri == null) ? XmlConsts.ATTR_NO_NS_URI : uri; - } - - public String getNamespaceURI(String prefix) - { - if (mCurrToken != START_ELEMENT && mCurrToken != END_ELEMENT) { - throw new IllegalStateException(ErrorConsts.ERR_STATE_NOT_ELEM); - } - /* Note: this will need to return null if no URI found for - * the prefix, so we can't mask it. - */ - return mElementStack.getNamespaceURI(prefix); - } - - public String getPIData() { - if (mCurrToken != PROCESSING_INSTRUCTION) { - throw new IllegalStateException(ErrorConsts.ERR_STATE_NOT_PI); - } - if (mTokenState <= TOKEN_STARTED) { - safeFinishToken(); - } - return mTextBuffer.contentsAsString(); - } - - public String getPITarget() { - if (mCurrToken != PROCESSING_INSTRUCTION) { - throw new IllegalStateException(ErrorConsts.ERR_STATE_NOT_PI); - } - // Target is always parsed automatically, not lazily... - return mCurrName; - } - - public String getPrefix() { - if (mCurrToken != START_ELEMENT && mCurrToken != END_ELEMENT) { - throw new IllegalStateException(ErrorConsts.ERR_STATE_NOT_ELEM); - } - // Internally it's marked as null, externally need to see "" - String p = mElementStack.getPrefix(); - return (p == null) ? XmlConsts.ELEM_NO_PREFIX : p; - } - - public String getText() - { - if (((1 << mCurrToken) & MASK_GET_TEXT) == 0) { - throwNotTextual(mCurrToken); - } - if (mTokenState < mStTextThreshold) { - safeFinishToken(); - } - if (mCurrToken == ENTITY_REFERENCE) { - return (mCurrEntity == null) ? null : mCurrEntity.getReplacementText(); - } - if (mCurrToken == DTD) { - /* 16-Aug-2004, TSa: Hmmh. Specs are bit ambiguous on whether this - * should return just the internal subset, or the whole - * thing... - */ - return getDTDInternalSubset(); - } - return mTextBuffer.contentsAsString(); - } - - public char[] getTextCharacters() - { - if (((1 << mCurrToken) & MASK_GET_TEXT_XXX) == 0) { - throwNotTextXxx(mCurrToken); - } - if (mTokenState < mStTextThreshold) { - safeFinishToken(); - } - if (mCurrToken == ENTITY_REFERENCE) { - return mCurrEntity.getReplacementChars(); - } - if (mCurrToken == DTD) { - return getDTDInternalSubsetArray(); - } - return mTextBuffer.getTextBuffer(); - } - - public int getTextCharacters(int sourceStart, char[] target, int targetStart, int len) - { - if (((1 << mCurrToken) & MASK_GET_TEXT_XXX) == 0) { - throwNotTextXxx(mCurrToken); - } - if (mTokenState < mStTextThreshold) { - safeFinishToken(); - } - return mTextBuffer.contentsToArray(sourceStart, target, targetStart, len); - } - - public int getTextLength() - { - if (((1 << mCurrToken) & MASK_GET_TEXT_XXX) == 0) { - throwNotTextXxx(mCurrToken); - } - if (mTokenState < mStTextThreshold) { - safeFinishToken(); - } - return mTextBuffer.size(); - } - - public int getTextStart() - { - if (((1 << mCurrToken) & MASK_GET_TEXT_XXX) == 0) { - throwNotTextXxx(mCurrToken); - } - if (mTokenState < mStTextThreshold) { - safeFinishToken(); - } - return mTextBuffer.getTextStart(); - } - - public boolean hasName() { - return (mCurrToken == START_ELEMENT) || (mCurrToken == END_ELEMENT); - } - - public boolean hasNext() { - /* 08-Oct-2005, TSa: In multi-doc mode, we have different - * criteria... - */ - return (mCurrToken != END_DOCUMENT) - || (mParseState == STATE_MULTIDOC_HACK); - } - - public boolean hasText() { - return (((1 << mCurrToken) & MASK_GET_TEXT) != 0); - } - - public boolean isAttributeSpecified(int index) - { - /* No need to check for ATTRIBUTE since we never return that... - */ - if (mCurrToken != START_ELEMENT) { - throw new IllegalStateException(ErrorConsts.ERR_STATE_NOT_STELEM); - } - return mAttrCollector.isSpecified(index); - } - - public boolean isCharacters() - { - /* 21-Dec-2005, TSa: Changed for 3.0 to work the same way as stax - * ref impl. - */ - //return (mCurrToken == CHARACTERS || mCurrToken == CDATA || mCurrToken == SPACE); - /* 21-Apr-2009, TSa: As per [WSTX-201], should be consistent with - * what getEventType() returns (affects CDATA, SPACE, in - * coalescing mode or when explicitly asked to return CDATA - * as CHARACTERS) - */ - return (getEventType() == CHARACTERS); - } - - public boolean isEndElement() { - return (mCurrToken == END_ELEMENT); - } - - public boolean isStartElement() { - return (mCurrToken == START_ELEMENT); - } - - /** - *

- * 05-Apr-2004, TSa: Could try to determine status when text is actually - * read. That'd prevent double reads... but would it slow down that - * one reading so that net effect would be negative? - */ - public boolean isWhiteSpace() - { - if (mCurrToken == CHARACTERS || mCurrToken == CDATA) { - if (mTokenState < mStTextThreshold) { - safeFinishToken(); - } - if (mWsStatus == ALL_WS_UNKNOWN) { - mWsStatus = mTextBuffer.isAllWhitespace() ? - ALL_WS_YES : ALL_WS_NO; - } - return mWsStatus == ALL_WS_YES; - } - return (mCurrToken == SPACE); - } - - public void require(int type, String nsUri, String localName) - throws XMLStreamException - { - int curr = mCurrToken; - - /* There are some special cases; specifically, CDATA - * is sometimes reported as CHARACTERS. Let's be lenient by - * allowing both 'real' and reported types, for now. - */ - if (curr != type) { - if (curr == CDATA) { - if (mCfgCoalesceText || mCfgReportTextAsChars) { - curr = CHARACTERS; - } - } else if (curr == SPACE) { - // Hmmh. Should we require it to be empty or something? - //curr = CHARACTERS; - // For now, let's not change the check - } - } - - if (type != curr) { - throwParseError("Expected type "+tokenTypeDesc(type) - +", current type " - +tokenTypeDesc(curr)); - } - - if (localName != null) { - if (curr != START_ELEMENT && curr != END_ELEMENT - && curr != ENTITY_REFERENCE) { - throwParseError("Expected non-null local name, but current token not a START_ELEMENT, END_ELEMENT or ENTITY_REFERENCE (was "+tokenTypeDesc(mCurrToken)+")"); - } - String n = getLocalName(); - if (n != localName && !n.equals(localName)) { - throwParseError("Expected local name '"+localName+"'; current local name '"+n+"'."); - } - } - if (nsUri != null) { - if (curr != START_ELEMENT && curr != END_ELEMENT) { - throwParseError("Expected non-null NS URI, but current token not a START_ELEMENT or END_ELEMENT (was "+tokenTypeDesc(curr)+")"); - } - String uri = mElementStack.getNsURI(); - // No namespace? - if (nsUri.length() == 0) { - if (uri != null && uri.length() > 0) { - throwParseError("Expected empty namespace, instead have '"+uri+"'."); - } - } else { - if ((nsUri != uri) && !nsUri.equals(uri)) { - throwParseError("Expected namespace '"+nsUri+"'; have '" - +uri+"'."); - } - } - } - // Ok, fine, all's good - } - - /* - //////////////////////////////////////////////////// - // XMLStreamReader, iterating - //////////////////////////////////////////////////// - */ - - public final int next() - throws XMLStreamException - { - /* 24-Sep-2006, TSa: We may have deferred an exception that occurred - * during parsing of the previous event. If so, now it needs to - * be thrown. - */ - if (mPendingException != null) { - XMLStreamException strEx = mPendingException; - mPendingException = null; - throw strEx; - } - - /* Note: can not yet accurately record the location, since the - * previous event might not yet be completely finished... - */ - if (mParseState == STATE_TREE) { - int type = nextFromTree(); - mCurrToken = type; - if (mTokenState < mStTextThreshold) { // incomplete? - /* Can remain incomplete if lazy parsing is enabled, - * and this is not a validatable text segment; otherwise - * must finish - */ - if (!mCfgLazyParsing || - (mValidateText && (type == CHARACTERS || type == CDATA))) { - finishToken(false); - } - } - - /* Special cases -- sometimes (when coalescing text, or - * when specifically configured to do so), CDATA and SPACE are - * to be reported as CHARACTERS, although we still will - * internally keep track of the real type. - */ - if (type == CDATA) { - if (mValidateText) { - mElementStack.validateText(mTextBuffer, false); - } - if (mCfgCoalesceText || mCfgReportTextAsChars) { - return CHARACTERS; - } - /* - } else if (type == SPACE) { - //if (mValidateText) { throw new IllegalStateException("Internal error: trying to validate SPACE event"); } - */ - } else if (type == CHARACTERS) { - if (mValidateText) { - /* We may be able to determine that there will be - * no more text coming for this element: but only - * seeing the end tag marker (" - * Note: as per StAX 1.0 specs, this method does NOT close the underlying - * input reader. That is, unless the new StAX2 property - * {@link org.codehaus.stax2.XMLInputFactory2#P_AUTO_CLOSE_INPUT} is - * set to true. - */ - public void close() - throws XMLStreamException - { - if (mParseState != STATE_CLOSED) { - mParseState = STATE_CLOSED; - /* Let's see if we should notify factory that symbol table - * has new entries, and may want to reuse this symbol table - * instead of current root. - */ - if (mCurrToken != END_DOCUMENT) { - mCurrToken = mSecondaryToken = END_DOCUMENT; - if (mSymbols.isDirty()) { - mOwner.updateSymbolTable(mSymbols); - } - } - /* Hmmh. Actually, we need to close all the dependant input - * sources, first, and then also call close() - * on the root input source object; it - * will only do real close if that was enabled earlier. - * The root input source also prevents multiple close() calls - * for the underlying source, so we need not check that here. - */ - closeAllInput(false); - // And finally, can now recycle low-level (text) buffers - mTextBuffer.recycle(true); - } - } - - /* - //////////////////////////////////////////////////// - // XMLStreamReader2 (StAX2) implementation - //////////////////////////////////////////////////// - */ - - // // // StAX2, per-reader configuration - - public Object getFeature(String name) - { - // No readable features defined yet... - throw new IllegalArgumentException(MessageFormat.format(ErrorConsts.ERR_UNKNOWN_FEATURE, new Object[] { name })); - } - - public void setFeature(String name, Object value) - { - // Base-class has no settable features at this point. - throw new IllegalArgumentException(MessageFormat.format(ErrorConsts.ERR_UNKNOWN_FEATURE, new Object[] { name })); - } - - // NOTE: getProperty() defined in Stax 1.0 interface - - public boolean isPropertySupported(String name) { - // !!! TBI: not all these properties are really supported - return mConfig.isPropertySupported(name); - } - - /** - * @param name Name of the property to set - * @param value Value to set property to. - * - * @return True, if the specified property was succesfully - * set to specified value; false if its value was not changed - */ - public boolean setProperty(String name, Object value) - { - boolean ok = mConfig.setProperty(name, value); - /* To make [WSTX-50] work fully dynamically (i.e. allow - * setting BASE_URL after stream reader has been constructed) - * need to force - */ - if (ok && WstxInputProperties.P_BASE_URL.equals(name)) { - // Easiest to just access from config: may come in as a String etc - mInput.overrideSource(mConfig.getBaseURL()); - } - return ok; - } - - // // // StAX2, additional traversal methods - - public void skipElement() throws XMLStreamException - { - if (mCurrToken != START_ELEMENT) { - throw new IllegalStateException(ErrorConsts.ERR_STATE_NOT_STELEM); - } - int nesting = 1; // need one more end elements than start elements - - while (true) { - int type = next(); - if (type == START_ELEMENT) { - ++nesting; - } else if (type == END_ELEMENT) { - if (--nesting == 0) { - break; - } - } - } - } - - // // // StAX2, additional attribute access - - public AttributeInfo getAttributeInfo() throws XMLStreamException - { - if (mCurrToken != START_ELEMENT) { - throw new IllegalStateException(ErrorConsts.ERR_STATE_NOT_STELEM); - } - /* Although attribute collector knows about specific parsed - * information, the element stack has DTD-derived information (if - * any)... and knows how to call attribute collector when necessary. - */ - return mElementStack; - } - - // // // StAX2, Additional DTD access - - /** - * Since this class implements {@link DTDInfo}, method can just - * return this. - */ - public DTDInfo getDTDInfo() throws XMLStreamException - { - /* Let's not allow it to be accessed during other events -- that - * way callers won't count on it being available afterwards. - */ - if (mCurrToken != DTD) { - return null; - } - if (mTokenState < TOKEN_FULL_SINGLE) { // need to fully read it in now - finishToken(false); - } - return this; - } - - // // // StAX2, Additional location information - - /** - * Location information is always accessible, for this reader. - */ - public final LocationInfo getLocationInfo() { - return this; - } - - // // // StAX2, Pass-through text accessors - - - /** - * Method similar to {@link #getText()}, except - * that it just uses provided Writer to write all textual content. - * For further optimization, it may also be allowed to do true - * pass-through, thus possibly avoiding one temporary copy of the - * data. - *

- * TODO: try to optimize to allow completely streaming pass-through: - * currently will still read all data in memory buffers before - * outputting - * - * @param w Writer to use for writing textual contents - * @param preserveContents If true, reader has to preserve contents - * so that further calls to getText will return - * proper conntets. If false, reader is allowed to skip creation - * of such copies: this can improve performance, but it also means - * that further calls to getText is not guaranteed to - * return meaningful data. - * - * @return Number of characters written to the reader - */ - public int getText(Writer w, boolean preserveContents) - throws IOException, XMLStreamException - { - if (((1 << mCurrToken) & MASK_GET_TEXT_WITH_WRITER) == 0) { - throwNotTextual(mCurrToken); - } - /* May need to be able to do fully streaming... but only for - * text events that have not yet been fully read; for other - * types there's less benefit, and for fully read ones, we - * already have everything ready. - */ - if (!preserveContents) { - if (mCurrToken == CHARACTERS) { - int count = mTextBuffer.rawContentsTo(w); - /* Let's also clear whatever was collected (as allowed by - * method contract) previously, to both save memory, and - * to ensure caller doesn't accidentally try to access it - * (and get otherwise 'random' results). - */ - mTextBuffer.resetWithEmpty(); - if (mTokenState < TOKEN_FULL_SINGLE) { - count += readAndWriteText(w); - } - if (mCfgCoalesceText && - (mTokenState < TOKEN_FULL_COALESCED)) { - if (mCfgCoalesceText) { - count += readAndWriteCoalesced(w, false); - } - } - return count; - } else if (mCurrToken == CDATA) { - int count = mTextBuffer.rawContentsTo(w); - mTextBuffer.resetWithEmpty(); // same as with CHARACTERS - if (mTokenState < TOKEN_FULL_SINGLE) { - count += readAndWriteCData(w); - } - if (mCfgCoalesceText && - (mTokenState < TOKEN_FULL_COALESCED)) { - if (mCfgCoalesceText) { - count += readAndWriteCoalesced(w, true); - } - } - return count; - } - } - if (mTokenState < mStTextThreshold) { - /* Otherwise, let's just finish the token; and due to guarantee - * by streaming method, let's try ensure we get it all. - */ - finishToken(false); // false -> shouldn't defer errors - } - if (mCurrToken == ENTITY_REFERENCE) { - return mCurrEntity.getReplacementText(w); - } - if (mCurrToken == DTD) { - char[] ch = getDTDInternalSubsetArray(); - if (ch != null) { - w.write(ch); - return ch.length; - } - return 0; - } - return mTextBuffer.rawContentsTo(w); - } - - // // // StAX 2, Other accessors - - /** - * @return Number of open elements in the stack; 0 when parser is in - * prolog/epilog, 1 inside root element and so on. - */ - public int getDepth() { - /* Note: we can not necessarily use mCurrDepth, since it is - * directly synchronized to the input (to catch unbalanced entity - * expansion WRT element nesting), and not to actual token values - * returned. - */ - return mElementStack.getDepth(); - } - - /** - * @return True, if cursor points to a start or end element that is - * constructed from 'empty' element (ends with '/>'); - * false otherwise. - */ - public boolean isEmptyElement() throws XMLStreamException - { - return (mCurrToken == START_ELEMENT) ? mStEmptyElem : false; - } - - public NamespaceContext getNonTransientNamespaceContext() - { - // null -> no Location info, not needed with basic API - return mElementStack.createNonTransientNsContext(null); - } - - public String getPrefixedName() - { - switch (mCurrToken) { - case START_ELEMENT: - case END_ELEMENT: - { - String prefix = mElementStack.getPrefix(); - String ln = mElementStack.getLocalName(); - - if (prefix == null) { - return ln; - } - StringBuffer sb = new StringBuffer(ln.length() + 1 + prefix.length()); - sb.append(prefix); - sb.append(':'); - sb.append(ln); - return sb.toString(); - } - case ENTITY_REFERENCE: - return getLocalName(); - case PROCESSING_INSTRUCTION: - return getPITarget(); - case DTD: - return getDTDRootName(); - - } - throw new IllegalStateException("Current state not START_ELEMENT, END_ELEMENT, ENTITY_REFERENCE, PROCESSING_INSTRUCTION or DTD"); - } - - public void closeCompletely() throws XMLStreamException - { - closeAllInput(true); - } - - /* - //////////////////////////////////////////////////// - // DTDInfo implementation (StAX 2) - //////////////////////////////////////////////////// - */ - - /** - *

- * Note: DTD-handling sub-classes need to override this method. - */ - public Object getProcessedDTD() { - return null; - } - - public String getDTDRootName() { - if (mRootPrefix == null) { - return mRootLName; - } - return mRootPrefix + ":" + mRootLName; - } - - public String getDTDPublicId() { - return mDtdPublicId; - } - - public String getDTDSystemId() { - return mDtdSystemId; - } - - /** - * @return Internal subset portion of the DOCTYPE declaration, if any; - * empty String if none - */ - public String getDTDInternalSubset() { - if (mCurrToken != DTD) { - return null; - } - return mTextBuffer.contentsAsString(); - } - - /** - * Internal method used by implementation - */ - private char[] getDTDInternalSubsetArray() { - /* Note: no checks for current state, but only because it's - * an internal method and callers are known to ensure it's ok - * to call this - */ - return mTextBuffer.contentsAsArray(); - } - - // // StAX2, v2.0 - - /** - * Sub-class will override this method - */ - public DTDValidationSchema getProcessedDTDSchema() { - return null; - } - - /* - //////////////////////////////////////////////////// - // LocationInfo implementation (StAX 2) - //////////////////////////////////////////////////// - */ - - // // // First, the "raw" offset accessors: - - public long getStartingByteOffset() { - /* 15-Apr-2005, TSa: No way to reliably keep track of byte offsets, - * at least for variable-length encodings... so let's just - * return -1 for now - */ - return -1L; - } - - public long getStartingCharOffset() { - return mTokenInputTotal; - } - - public long getEndingByteOffset() throws XMLStreamException - { - /* 15-Apr-2005, TSa: No way to reliably keep track of byte offsets, - * at least for variable-length encodings... so let's just - * return -1 for now - */ - return -1; - } - - public long getEndingCharOffset() throws XMLStreamException - { - // Need to get to the end of the token, if not there yet - if (mTokenState < mStTextThreshold) { - finishToken(false); - } - return mCurrInputProcessed + mInputPtr; - } - - // // // and then the object-based access methods: - - public final Location getLocation() { - return getStartLocation(); - } - - // public XMLStreamLocation2 getStartLocation() // from base class - // public XMLStreamLocation2 getCurrentLocation() // - "" - - - public final XMLStreamLocation2 getEndLocation() - throws XMLStreamException - { - // Need to get to the end of the token, if not there yet - if (mTokenState < mStTextThreshold) { - finishToken(false); - } - // And then we just need the current location! - return getCurrentLocation(); - } - - /* - //////////////////////////////////////////////////// - // Stax2 validation - //////////////////////////////////////////////////// - */ - - public XMLValidator validateAgainst(XMLValidationSchema schema) - throws XMLStreamException - { - // Not implemented by the basic reader: - return null; - } - - public XMLValidator stopValidatingAgainst(XMLValidationSchema schema) - throws XMLStreamException - { - // Not implemented by the basic reader: - return null; - } - - public XMLValidator stopValidatingAgainst(XMLValidator validator) - throws XMLStreamException - { - // Not implemented by the basic reader: - return null; - } - - public ValidationProblemHandler setValidationProblemHandler(ValidationProblemHandler h) - { - // Not implemented by the basic reader: - return null; - } - - /* - ////////////////////////////////////////////////////// - // StreamReaderImpl implementation - ////////////////////////////////////////////////////// - */ - - public EntityDecl getCurrentEntityDecl() { - return mCurrEntity; - } - - /** - * Method called by {@link com.ctc.wstx.evt.DefaultEventAllocator} - * to get double-indirection necessary for constructing start element - * events. - * - * @return Null, if stream does not point to start element; whatever - * callback returns otherwise. - */ - public Object withStartElement(ElemCallback cb, Location loc) - { - if (mCurrToken != START_ELEMENT) { - return null; - } - return cb.withStartElement(loc, getName(), - mElementStack.createNonTransientNsContext(loc), - mAttrCollector.buildAttrOb(), - mStEmptyElem); - } - - public boolean isNamespaceAware() { - return mCfgNsEnabled; - } - - /** - * Method needed by classes (like stream writer implementations) - * that want to have efficient direct access to element stack - * implementation - */ - public InputElementStack getInputElementStack() { - return mElementStack; - } - - /** - * Method needed by classes (like stream writer implementations) - * that want to have efficient direct access to attribute collector - * Object, for optimal attribute name and value access. - */ - public AttributeCollector getAttributeCollector() { - return mAttrCollector; - } - - /* - ////////////////////////////////////////////////////// - // Support for SAX XMLReader implementation - ////////////////////////////////////////////////////// - */ - - public void fireSaxStartElement(ContentHandler h, Attributes attrs) - throws SAXException - { - if (h != null) { - // First; any ns declarations? - int nsCount = mElementStack.getCurrentNsCount(); - for (int i = 0; i < nsCount; ++i) { - String prefix = mElementStack.getLocalNsPrefix(i); - String uri = mElementStack.getLocalNsURI(i); - h.startPrefixMapping((prefix == null) ? "" : prefix, uri); - } - - // Then start-elem event itself: - String uri = mElementStack.getNsURI(); - // Sax requires "" (not null) for ns uris... - h.startElement((uri == null) ? "" : uri, - mElementStack.getLocalName(), getPrefixedName(), attrs); - } - } - - public void fireSaxEndElement(ContentHandler h) - throws SAXException - { - if (h != null) { - /* Order of events is reversed (wrt. start-element): first - * the end tag event, then unbound prefixes - */ - String uri = mElementStack.getNsURI(); - // Sax requires "" (not null) for ns uris... - h.endElement((uri == null) ? "" : uri, - mElementStack.getLocalName(), getPrefixedName()); - // Any expiring ns declarations? - int nsCount = mElementStack.getCurrentNsCount(); - for (int i = 0; i < nsCount; ++i) { - String prefix = mElementStack.getLocalNsPrefix(i); - //String nsUri = mElementStack.getLocalNsURI(i); - h.endPrefixMapping((prefix == null) ? "" : prefix); - } - } - } - - public void fireSaxCharacterEvents(ContentHandler h) - throws XMLStreamException, SAXException - { - if (h != null) { - if (mPendingException != null) { - XMLStreamException sex = mPendingException; - mPendingException = null; - throw sex; - } - /* Let's not defer errors; SAXTest implies - * it's expected errors are thrown right away - */ - if (mTokenState < mStTextThreshold) { - finishToken(false); - } - mTextBuffer.fireSaxCharacterEvents(h); - } - } - - public void fireSaxSpaceEvents(ContentHandler h) - throws XMLStreamException, SAXException - { - if (h != null) { - if (mTokenState < mStTextThreshold) { - finishToken(false); // no error deferring - } - mTextBuffer.fireSaxSpaceEvents(h); - } - } - - public void fireSaxCommentEvent(LexicalHandler h) - throws XMLStreamException, SAXException - { - if (h != null) { - if (mTokenState < mStTextThreshold) { - finishToken(false); // no error deferring - } - mTextBuffer.fireSaxCommentEvent(h); - } - } - - public void fireSaxPIEvent(ContentHandler h) - throws XMLStreamException, SAXException - { - if (h != null) { - if (mTokenState < mStTextThreshold) { - finishToken(false); // no error deferring - } - h.processingInstruction(mCurrName, mTextBuffer.contentsAsString()); - } - } - - /* - //////////////////////////////////////////////////// - // Internal methods, config access - //////////////////////////////////////////////////// - */ - - protected final boolean hasConfigFlags(int flags) { - return (mConfigFlags & flags) == flags; - } - - /* - //////////////////////////////////////////////////// - // Internal methods, parsing helper methods - //////////////////////////////////////////////////// - */ - - /** - * @return Null, if keyword matches ok; String that contains erroneous - * keyword if not. - */ - protected String checkKeyword(char c, String expected) - throws XMLStreamException - { - int ptr = 0; - int len = expected.length(); - - while (expected.charAt(ptr) == c && ++ptr < len) { - if (mInputPtr < mInputEnd) { - c = mInputBuffer[mInputPtr++]; - } else { - int ci = getNext(); - if (ci < 0) { // EOF - break; - } - c = (char) ci; - } - } - - if (ptr == len) { - // Probable match... but let's make sure keyword is finished: - int i = peekNext(); - if (i < 0 || (!isNameChar((char) i) && i != ':')) { - return null; - } - // Nope, continues, need to find the rest: - } - - StringBuffer sb = new StringBuffer(expected.length() + 16); - sb.append(expected.substring(0, ptr)); - if (ptr < len) { - sb.append(c); - } - - while (true) { - if (mInputPtr < mInputEnd) { - c = mInputBuffer[mInputPtr++]; - } else { - int ci = getNext(); - if (ci < 0) { // EOF - break; - } - c = (char) ci; - } - if (!isNameChar(c)) { - // Let's push it back then - --mInputPtr; - break; - } - sb.append(c); - } - - return sb.toString(); - } - - protected void checkCData() - throws XMLStreamException - { - String wrong = checkKeyword(getNextCharFromCurrent(SUFFIX_IN_CDATA), "CDATA"); - if (wrong != null) { - throwParseError("Unrecognized XML directive '"+wrong+"'; expected 'CDATA'."); - } - // Plus, need the bracket too: - char c = getNextCharFromCurrent(SUFFIX_IN_CDATA); - if (c != '[') { - throwUnexpectedChar(c, "excepted '[' after '= 3 - && (ch = resolveSimpleEntity(true)) != 0) { - // Ok, fine, c is whatever it is - ; - } else { // full entity just changes buffer... - ch = fullyResolveEntity(false); - if (ch == 0) { - // need to skip output, thusly (expanded to new input source) - continue; - } - } - if (ch <= 0xFFFF) { - c = (char) ch; - } else { - ch -= 0x10000; - if (outPtr >= outLen) { - outBuf = tb.bufferFull(1); - outLen = outBuf.length; - } - outBuf[outPtr++] = (char) ((ch >> 10) + 0xD800); - c = (char) ((ch & 0x3FF) + 0xDC00); - } - } - } else if (c == '<') { - throwParseError("Unexpected '<' "+SUFFIX_IN_ATTR_VALUE); - } - - // Ok, let's just add char in, whatever it was - if (outPtr >= outLen) { - outBuf = tb.bufferFull(1); - outLen = outBuf.length; - } - outBuf[outPtr++] = c; - } - - // Fine; let's tell TextBuild we're done: - tb.setBufferSize(outPtr); - } - - /* - ///////////////////////////////////////////////////// - // Internal methods, parsing prolog (before root) and - // epilog - ///////////////////////////////////////////////////// - */ - - /** - * Method called to find type of next token in prolog; either reading - * just enough information to know the type (lazy parsing), or the - * full contents (non-lazy) - * - * @return True if we hit EOI, false otherwise - */ - private boolean nextFromProlog(boolean isProlog) - throws XMLStreamException - { - int i; - - // First, do we need to finish currently open token? - if (mTokenState < mStTextThreshold) { - mTokenState = TOKEN_FULL_COALESCED; - i = skipToken(); - // note: skipToken() updates the start location - } else { - // Need to update the start location... - mTokenInputTotal = mCurrInputProcessed + mInputPtr; - mTokenInputRow = mCurrInputRow; - mTokenInputCol = mInputPtr - mCurrInputRowStart; - i = getNext(); - } - - // Any white space to parse or skip? - if (i <= CHAR_SPACE && i >= 0) { - // Need to return as an event? - if (hasConfigFlags(CFG_REPORT_PROLOG_WS)) { - mCurrToken = SPACE; - if (readSpacePrimary((char) i, true)) { - /* no need to worry about coalescing, since CDATA is not - * allowed at this level... - */ - mTokenState = TOKEN_FULL_COALESCED; - } else { - if (mCfgLazyParsing) { - /* Let's not even bother checking if it's - * "long enough"; shouldn't usually matter, but few - * apps care to get multiple adjacent SPACE events... - */ - mTokenState = TOKEN_STARTED; - } else { - readSpaceSecondary(true); - mTokenState = TOKEN_FULL_COALESCED; - } - } - return false; - } - // If not, can skip it right away - --mInputPtr; // to handle linefeeds gracefully - i = getNextAfterWS(); - if (i >= 0) { - // ... after which location has to be reset properly: - /* 11-Apr-2005, TSa: But note that we need to "move back" - * column and total offset values by one, to compensate - * for the char that was read (row can not have changed, - * since it's non-WS, and thus non-lf/cr char) - */ - mTokenInputTotal = mCurrInputProcessed + mInputPtr - 1; - mTokenInputRow = mCurrInputRow; - mTokenInputCol = mInputPtr - mCurrInputRowStart - 1; - } - } - - // Did we hit EOI? - if (i < 0) { - handleEOF(isProlog); - mParseState = STATE_CLOSED; - return true; - } - - // Now we better have a lt... - if (i != '<') { - throwUnexpectedChar(i, (isProlog ? SUFFIX_IN_PROLOG : SUFFIX_IN_EPILOG) - +"; expected '<'"); - } - - // And then it should be easy to figure out type: - char c = getNextChar(isProlog ? SUFFIX_IN_PROLOG : SUFFIX_IN_EPILOG); - - if (c == '?') { // proc. inst - mCurrToken = readPIPrimary(); - } else if (c == '!') { // DOCTYPE or comment (or CDATA, but not legal here) - // Need to figure out bit more first... - nextFromPrologBang(isProlog); - } else if (c == '/') { // end tag not allowed... - if (isProlog) { - throwParseError("Unexpected character combination ' clean'n recycle - // It's ok to get EOF from epilog but not from prolog - if (isProlog) { - throwUnexpectedEOF(SUFFIX_IN_PROLOG); - } - return mCurrToken; - } - - /** - * Method called if a root-level element is found after the main - * root element was closed. This is legal in multi-doc parsing - * mode (and in fragment mode), but not in the default single-doc - * mode. - * - * @return Token to return - */ - private int handleExtraRoot(char c) - throws XMLStreamException - { - if (!mConfig.inputParsingModeDocuments()) { - /* Has to be single-doc mode, since fragment mode - * should never get here (since fragment mode never has epilog - * or prolog modes) - */ - throwParseError("Illegal to have multiple roots (start tag in epilog?)."); - } - // Need to push back the char, since it is the first char of elem name - --mInputPtr; - return handleMultiDocStart(START_ELEMENT); - } - - /** - * Method called when an event was encountered that indicates document - * boundary in multi-doc mode. Needs to trigger dummy - * END_DOCUMENT/START_DOCUMENT event combination, followed by the - * handling of the original event. - * - * @return Event type to return - */ - protected int handleMultiDocStart(int nextEvent) - { - mParseState = STATE_MULTIDOC_HACK; - mTokenState = TOKEN_FULL_COALESCED; // this is a virtual event after all... - mSecondaryToken = nextEvent; - return END_DOCUMENT; - } - - /** - * Method called to get the next event when we are "multi-doc hack" mode, - * during which extra END_DOCUMENT/START_DOCUMENT events need to be - * returned. - */ - private int nextFromMultiDocState() - throws XMLStreamException - { - if (mCurrToken == END_DOCUMENT) { - /* Ok; this is the initial step; need to advance: need to parse - * xml declaration if that was the cause, otherwise just clear - * up values. - */ - if (mSecondaryToken == START_DOCUMENT) { - handleMultiDocXmlDecl(); - } else { // Nah, DOCTYPE or start element... just need to clear decl info: - mDocXmlEncoding = null; - mDocXmlVersion = XmlConsts.XML_V_UNKNOWN; - mDocStandalone = DOC_STANDALONE_UNKNOWN; - } - return START_DOCUMENT; - } - if (mCurrToken == START_DOCUMENT) { - mParseState = STATE_PROLOG; // yup, we are now officially in prolog again... - - // Had an xml decl (ie. "real" START_DOCUMENT event) - if (mSecondaryToken == START_DOCUMENT) { // was a real xml decl - nextFromProlog(true); - return mCurrToken; - } - // Nah, start elem or DOCTYPE - if (mSecondaryToken == START_ELEMENT) { - handleRootElem(getNextChar(SUFFIX_IN_ELEMENT)); - return START_ELEMENT; - } - if (mSecondaryToken == DTD) { - mStDoctypeFound = true; - startDTD(); - return DTD; - } - } - throw new IllegalStateException("Internal error: unexpected state; current event " - +tokenTypeDesc(mCurrToken)+", sec. state: "+tokenTypeDesc(mSecondaryToken)); - } - - protected void handleMultiDocXmlDecl() - throws XMLStreamException - { - // Let's default these first - mDocStandalone = DOC_STANDALONE_UNKNOWN; - mDocXmlEncoding = null; - - char c = getNextInCurrAfterWS(SUFFIX_IN_XML_DECL); - String wrong = checkKeyword(c, XmlConsts.XML_DECL_KW_VERSION); - if (wrong != null) { - throwParseError(ErrorConsts.ERR_UNEXP_KEYWORD, wrong, XmlConsts.XML_DECL_KW_VERSION); - } - c = skipEquals(XmlConsts.XML_DECL_KW_VERSION, SUFFIX_IN_XML_DECL); - TextBuffer tb = mTextBuffer; - tb.resetInitialized(); - parseQuoted(XmlConsts.XML_DECL_KW_VERSION, c, tb); - - if (tb.equalsString(XmlConsts.XML_V_10_STR)) { - mDocXmlVersion = XmlConsts.XML_V_10; - mXml11 = false; - } else if (tb.equalsString(XmlConsts.XML_V_11_STR)) { - mDocXmlVersion = XmlConsts.XML_V_11; - mXml11 = true; - } else { - mDocXmlVersion = XmlConsts.XML_V_UNKNOWN; - mXml11 = false; - throwParseError("Unexpected xml version '"+tb.toString()+"'; expected '"+XmlConsts.XML_V_10_STR+"' or '"+XmlConsts.XML_V_11_STR+"'"); - } - - c = getNextInCurrAfterWS(SUFFIX_IN_XML_DECL); - - if (c != '?') { // '?' signals end... - if (c == 'e') { // encoding - wrong = checkKeyword(c, XmlConsts.XML_DECL_KW_ENCODING); - if (wrong != null) { - throwParseError(ErrorConsts.ERR_UNEXP_KEYWORD, wrong, XmlConsts.XML_DECL_KW_ENCODING); - } - c = skipEquals(XmlConsts.XML_DECL_KW_ENCODING, SUFFIX_IN_XML_DECL); - tb.resetWithEmpty(); - parseQuoted(XmlConsts.XML_DECL_KW_ENCODING, c, tb); - mDocXmlEncoding = tb.toString(); - /* should we verify encoding at this point? let's not, for now; - * since it's for information only, first declaration from - * bootstrapper is used for the whole stream. - */ - c = getNextInCurrAfterWS(SUFFIX_IN_XML_DECL); - } else if (c != 's') { - throwUnexpectedChar(c, " in xml declaration; expected either 'encoding' or 'standalone' pseudo-attribute"); - } - - // Standalone? - if (c == 's') { - wrong = checkKeyword(c, XmlConsts.XML_DECL_KW_STANDALONE); - if (wrong != null) { - throwParseError(ErrorConsts.ERR_UNEXP_KEYWORD, wrong, XmlConsts.XML_DECL_KW_STANDALONE); - } - c = skipEquals(XmlConsts.XML_DECL_KW_STANDALONE, SUFFIX_IN_XML_DECL); - tb.resetWithEmpty(); - parseQuoted(XmlConsts.XML_DECL_KW_STANDALONE, c, tb); - if (tb.equalsString(XmlConsts.XML_SA_YES)) { - mDocStandalone = DOC_STANDALONE_YES; - } else if (tb.equalsString(XmlConsts.XML_SA_NO)) { - mDocStandalone = DOC_STANDALONE_NO; - } else { - throwParseError("Unexpected xml '"+XmlConsts.XML_DECL_KW_STANDALONE+"' pseudo-attribute value '" - +tb.toString()+"'; expected '"+XmlConsts.XML_SA_YES+"' or '"+ - XmlConsts.XML_SA_NO+"'"); - } - c = getNextInCurrAfterWS(SUFFIX_IN_XML_DECL); - } - } - - if (c != '?') { - throwUnexpectedChar(c, " in xml declaration; expected '?>' as the end marker"); - } - c = getNextCharFromCurrent(SUFFIX_IN_XML_DECL); - if (c != '>') { - throwUnexpectedChar(c, " in xml declaration; expected '>' to close the declaration"); - } - } - - /** - * Method that checks that input following is of form - * '[S]* '=' [S]*' (as per XML specs, production #25). - * Will push back non-white space characters as necessary, in - * case no equals char is encountered. - */ - protected final char skipEquals(String name, String eofMsg) - throws XMLStreamException - { - char c = getNextInCurrAfterWS(eofMsg); - if (c != '=') { - throwUnexpectedChar(c, " in xml declaration; expected '=' to follow pseudo-attribute '"+name+"'"); - } - // trailing space? - return getNextInCurrAfterWS(eofMsg); - } - - /** - * Method called to parse quoted xml declaration pseudo-attribute values. - * Works similar to attribute value parsing, except no entities can be - * included, and in general need not be as picky (since caller is to - * verify contents). One exception is that we do check for linefeeds - * and lt chars, since they generally would indicate problems and - * are useful to catch early on (can happen if a quote is missed etc) - *

- * Note: since it'll be called at most 3 times per document, this method - * is not optimized too much. - */ - protected final void parseQuoted(String name, char quoteChar, TextBuffer tbuf) - throws XMLStreamException - { - if (quoteChar != '"' && quoteChar != '\'') { - throwUnexpectedChar(quoteChar, " in xml declaration; waited ' or \" to start a value for pseudo-attribute '"+name+"'"); - } - char[] outBuf = tbuf.getCurrentSegment(); - int outPtr = 0; - - while (true) { - char c = (mInputPtr < mInputEnd) ? mInputBuffer[mInputPtr++] - : getNextChar(SUFFIX_IN_XML_DECL); - - if (c == quoteChar) { - break; - } - if (c < CHAR_SPACE || c == '<') { - throwUnexpectedChar(c, SUFFIX_IN_XML_DECL); - } else if (c == CHAR_NULL) { - throwNullChar(); - } - if (outPtr >= outBuf.length) { - outBuf = tbuf.finishCurrentSegment(); - outPtr = 0; - } - outBuf[outPtr++] = c; - } - tbuf.setCurrentLength(outPtr); - } - - /** - * Called after character sequence '<!' has been found; expectation is - * that it'll either be DOCTYPE declaration (if we are in prolog and - * haven't yet seen one), or a comment. CDATA is not legal here; - * it would start same way otherwise. - */ - private void nextFromPrologBang(boolean isProlog) - throws XMLStreamException - { - int i = getNext(); - if (i < 0) { - throwUnexpectedEOF(SUFFIX_IN_PROLOG); - } - if (i == 'D') { // Doctype declaration? - String keyw = checkKeyword('D', "DOCTYPE"); - if (keyw != null) { - throwParseError("Unrecognized XML directive ' - * - *. And we have already read the DOCTYPE token. - */ - - char c = getNextInCurrAfterWS(SUFFIX_IN_DTD); - if (mCfgNsEnabled) { - String str = parseLocalName(c); - c = getNextChar(SUFFIX_IN_DTD); - if (c == ':') { // Ok, got namespace and local name - mRootPrefix = str; - mRootLName = parseLocalName(getNextChar(SUFFIX_EOF_EXP_NAME)); - } else if (c <= CHAR_SPACE || c == '[' || c == '>') { - // ok to get white space or '[', or closing '>' - --mInputPtr; // pushback - mRootPrefix = null; - mRootLName = str; - } else { - throwUnexpectedChar(c, " in DOCTYPE declaration; expected '[' or white space."); - } - } else { - mRootLName = parseFullName(c); - mRootPrefix = null; - } - - // Ok, fine, what next? - c = getNextInCurrAfterWS(SUFFIX_IN_DTD); - if (c != '[' && c != '>') { - String keyw = null; - - if (c == 'P') { - keyw = checkKeyword(getNextChar(SUFFIX_IN_DTD), "UBLIC"); - if (keyw != null) { - keyw = "P" + keyw; - } else { - if (!skipWS(getNextChar(SUFFIX_IN_DTD))) { - throwUnexpectedChar(c, SUFFIX_IN_DTD+"; expected a space between PUBLIC keyword and public id"); - } - c = getNextCharFromCurrent(SUFFIX_IN_DTD); - if (c != '"' && c != '\'') { - throwUnexpectedChar(c, SUFFIX_IN_DTD+"; expected a public identifier."); - } - mDtdPublicId = parsePublicId(c, SUFFIX_IN_DTD); - if (mDtdPublicId.length() == 0) { - // According to XML specs, this isn't illegal? - // however, better report it as empty, not null. - //mDtdPublicId = null; - } - if (!skipWS(getNextChar(SUFFIX_IN_DTD))) { - throwUnexpectedChar(c, SUFFIX_IN_DTD+"; expected a space between public and system identifiers"); - } - c = getNextCharFromCurrent(SUFFIX_IN_DTD); - if (c != '"' && c != '\'') { - throwParseError(SUFFIX_IN_DTD+"; expected a system identifier."); - } - mDtdSystemId = parseSystemId(c, mNormalizeLFs, SUFFIX_IN_DTD); - if (mDtdSystemId.length() == 0) { - // According to XML specs, this isn't illegal? - // however, better report it as empty, not null. - //mDtdSystemId = null; - } - } - } else if (c == 'S') { - mDtdPublicId = null; - keyw = checkKeyword(getNextChar(SUFFIX_IN_DTD), "YSTEM"); - if (keyw != null) { - keyw = "S" + keyw; - } else { - c = getNextInCurrAfterWS(SUFFIX_IN_DTD); - if (c != '"' && c != '\'') { - throwUnexpectedChar(c, SUFFIX_IN_DTD+"; expected a system identifier."); - } - mDtdSystemId = parseSystemId(c, mNormalizeLFs, SUFFIX_IN_DTD); - if (mDtdSystemId.length() == 0) { - // According to XML specs, this isn't illegal? - mDtdSystemId = null; - } - } - } else { - if (!isNameStartChar(c)) { - throwUnexpectedChar(c, SUFFIX_IN_DTD+"; expected keywords 'PUBLIC' or 'SYSTEM'."); - } else { - --mInputPtr; - keyw = checkKeyword(c, "SYSTEM"); // keyword passed in doesn't matter - } - } - - if (keyw != null) { // error: - throwParseError("Unexpected keyword '"+keyw+"'; expected 'PUBLIC' or 'SYSTEM'"); - } - - // Ok, should be done with external DTD identifier: - c = getNextInCurrAfterWS(SUFFIX_IN_DTD); - } - - if (c == '[') { // internal subset - ; - } else { - if (c != '>') { - throwUnexpectedChar(c, SUFFIX_IN_DTD+"; expected closing '>'."); - } - } - - /* Actually, let's just push whatever char it is, back; this way - * we can lazily initialize text buffer with DOCTYPE declaration - * if/as necessary, even if there's no internal subset. - */ - --mInputPtr; // pushback - mTokenState = TOKEN_STARTED; - } - - /** - * This method gets called to handle remainder of DOCTYPE declaration, - * essentially the optional internal subset. This class implements the - * basic "ignore it" functionality, but can optionally still store copy - * of the contents to the read buffer. - *

- * NOTE: Since this default implementation will be overridden by - * some sub-classes, make sure you do NOT change the method signature. - * - * @param copyContents If true, will copy contents of the internal - * subset of DOCTYPE declaration - * in the text buffer; if false, will just completely ignore the - * subset (if one found). - */ - protected void finishDTD(boolean copyContents) - throws XMLStreamException - { - /* We know there are no spaces, as this char was read and pushed - * back earlier... - */ - char c = getNextChar(SUFFIX_IN_DTD); - if (c == '[') { - // Do we need to get contents as text too? - if (copyContents) { - ((BranchingReaderSource) mInput).startBranch(mTextBuffer, mInputPtr, mNormalizeLFs); - } - - try { - MinimalDTDReader.skipInternalSubset(this, mInput, mConfig); - } finally { - /* Let's close branching in any and every case (may allow - * graceful recovery in error cases in future - */ - if (copyContents) { - /* Need to "push back" ']' got in the succesful case - * (that's -1 part below); - * in error case it'll just be whatever last char was. - */ - ((BranchingReaderSource) mInput).endBranch(mInputPtr-1); - } - } - - // And then we need closing '>' - c = getNextCharAfterWS(SUFFIX_IN_DTD_INTERNAL); - } - - if (c != '>') { - throwUnexpectedChar(c, "; expected '>' to finish DOCTYPE declaration."); - } - } - - /* - //////////////////////////////////////////////////// - // Internal methods, main parsing (inside root) - //////////////////////////////////////////////////// - */ - - /** - * Method called to parse beginning of the next event within - * document tree, and return its type. - */ - private final int nextFromTree() - throws XMLStreamException - { - int i; - - // First, do we need to finish currently open token? - if (mTokenState < mStTextThreshold) { - // No need to update state... will get taken care of - /* 03-Mar-2006, TSa: Let's add a sanity check here, temporarily, - * to ensure we never skip any textual content when it is - * to be validated - */ - if (mVldContent == XMLValidator.CONTENT_ALLOW_VALIDATABLE_TEXT) { - if (mCurrToken == CHARACTERS || mCurrToken == CDATA) { // should never happen - throwParseError("Internal error: skipping validatable text"); - } - } - i = skipToken(); - // note: skipToken() updates the start location - } else { - /* Start/end elements are never unfinished (ie. are always - * completely read in) - */ - if (mCurrToken == START_ELEMENT) { - // Start tag may be an empty tag: - if (mStEmptyElem) { - // and if so, we'll then get 'virtual' close tag: - mStEmptyElem = false; - // ... and location info is correct already - /* 27-Feb-2009, TSa: but we do have to handle validation - * of the end tag now - */ - int vld = mElementStack.validateEndElement(); - mVldContent = vld; - mValidateText = (vld == XMLValidator.CONTENT_ALLOW_VALIDATABLE_TEXT); - return END_ELEMENT; - } - } else if (mCurrToken == END_ELEMENT) { - // Close tag removes current element from stack - if (!mElementStack.pop()) { // false if root closed - // if so, we'll get to epilog, unless in fragment mode - if (!mConfig.inputParsingModeFragment()) { - return closeContentTree(); - } - // in fragment mode, fine, we'll just continue - } - } else if (mCurrToken == CDATA && mTokenState <= TOKEN_PARTIAL_SINGLE) { - /* Just returned a partial CDATA... that's ok, just need to - * know we won't get opening marker etc. - * The tricky part here is just to ensure there's at least - * one character; if not, need to just discard the empty - * 'event' (note that it is possible to have an initial - * empty CDATA event for truly empty CDATA block; but not - * partial ones!). Let's just read it like a new - * CData section first: - */ - // First, need to update the start location... - mTokenInputTotal = mCurrInputProcessed + mInputPtr; - mTokenInputRow = mCurrInputRow; - mTokenInputCol = mInputPtr - mCurrInputRowStart; - char c = (mInputPtr < mInputEnd) ? mInputBuffer[mInputPtr++] - : getNextChar(SUFFIX_IN_CDATA); - if (readCDataPrimary(c)) { // got it all! - /* note: can not be in coalescing mode at this point; - * as we can never have partial cdata without unfinished - * token - */ - // ... still need to have gotten at least 1 char though: - if (mTextBuffer.size() > 0) { - return CDATA; - } - // otherwise need to continue and parse the next event - } else { - /* Hmmh. Have to verify we get at least one char from - * CData section; if so, we are good to go for now; - * if not, need to get that damn char first: - */ - if (mTextBuffer.size() == 0 - && readCDataSecondary(mCfgLazyParsing - ? 1 : mShortestTextSegment)) { - // Ok, all of it read - if (mTextBuffer.size() > 0) { - // And had some contents - mTokenState = TOKEN_FULL_SINGLE; - return CDATA; - } - // if nothing read, we'll just fall back (see below) - } else { // good enough! - mTokenState = TOKEN_PARTIAL_SINGLE; - return CDATA; - } - } - - /* If we get here, it was the end of the section, without - * any more text inside CDATA, so let's just continue - */ - } - // Once again, need to update the start location info: - mTokenInputTotal = mCurrInputProcessed + mInputPtr; - mTokenInputRow = mCurrInputRow; - mTokenInputCol = mInputPtr - mCurrInputRowStart; - i = getNext(); - } - - if (i < 0) { - /* 07-Oct-2005, TSa: May be ok in fragment mode (not otherwise), - * but we can just check if element stack has anything, as that - * handles all cases - */ - if (!mElementStack.isEmpty()) { - throwUnexpectedEOF(); - } - return handleEOF(false); - } - - /* 26-Aug-2004, TSa: We have to deal with entities, usually, if - * they are the next thing; even in non-expanding mode there - * are entities and then there are entities... :-) - * Let's start with char entities; they can be expanded right away. - */ - while (i == '&') { - mWsStatus = ALL_WS_UNKNOWN; - - /* 30-Aug-2004, TSa: In some contexts entities are not - * allowed in any way, shape or form: - */ - if (mVldContent == XMLValidator.CONTENT_ALLOW_NONE) { - /* May be char entity, general entity; whatever it is it's - * invalid! - */ - reportInvalidContent(ENTITY_REFERENCE); - } - - /* Need to call different methods based on whether we can do - * automatic entity expansion or not: - */ - int ch = mCfgReplaceEntities ? - fullyResolveEntity(true) : resolveCharOnlyEntity(true); - - if (ch != 0) { - /* Char-entity... need to initialize text output buffer, then; - * independent of whether it'll be needed or not. - */ - /* 30-Aug-2004, TSa: In some contexts only white space is - * accepted... - */ - if (mVldContent <= XMLValidator.CONTENT_ALLOW_WS) { - // As per xml specs, only straight white space is legal - if (ch > CHAR_SPACE) { - /* 21-Sep-2008, TSa: Used to also require a call to - * 'mElementStack.reallyValidating', if only ws - * allowed, to cover the case where non-typing-dtd - * was only used to discover SPACE type. But - * now that we have CONTENT_ALLOW_WS_NONSTRICT, - * shouldn't be needed. - */ - //if (mVldContent < XMLValidator.CONTENT_ALLOW_WS || mElementStack.reallyValidating()) { - reportInvalidContent(CHARACTERS); - } - } - TextBuffer tb = mTextBuffer; - tb.resetInitialized(); - if (ch <= 0xFFFF) { - tb.append((char) ch); - } else { - ch -= 0x10000; - tb.append((char) ((ch >> 10) + 0xD800)); - tb.append((char) ((ch & 0x3FF) + 0xDC00)); - } - mTokenState = TOKEN_STARTED; - return CHARACTERS; - } - - /* Nope; was a general entity... in auto-mode, it's now been - * expanded; in non-auto, need to figure out entity itself. - */ - if (!mCfgReplaceEntities|| mCfgTreatCharRefsAsEntities) { - if (!mCfgTreatCharRefsAsEntities) { - final EntityDecl ed = resolveNonCharEntity(); - // Note: ed may still be null at this point - mCurrEntity = ed; - } - // Note: ed may still be null at this point - mTokenState = TOKEN_FULL_COALESCED; - /* - // let's not worry about non-parsed entities, since this is unexpanded mode - // ... although it'd be an error either way? Should we report it? - if (ed != null && !ed.isParsed()) { - throwParseError("Reference to unparsed entity '"+ed.getName()+"' from content not allowed."); - } - */ - return ENTITY_REFERENCE; - } - - // Otherwise automatic expansion fine; just need the next char: - i = getNextChar(SUFFIX_IN_DOC); - } - - if (i == '<') { // Markup - // And then it should be easy to figure out type: - char c = getNextChar(SUFFIX_IN_ELEMENT); - if (c == '?') { // proc. inst - // 30-Aug-2004, TSa: Not legal for EMPTY elements - if (mVldContent == XMLValidator.CONTENT_ALLOW_NONE) { - reportInvalidContent(PROCESSING_INSTRUCTION); - } - return readPIPrimary(); - } - - if (c == '!') { // CDATA or comment - // Need to figure out bit more first... - int type = nextFromTreeCommentOrCData(); - // 30-Aug-2004, TSa: Not legal for EMPTY elements - if (mVldContent == XMLValidator.CONTENT_ALLOW_NONE) { - reportInvalidContent(type); - } - return type; - } - if (c == '/') { // always legal (if name matches etc) - readEndElem(); - return END_ELEMENT; - } - - if (c == ':' || isNameStartChar(c)) { - /* Note: checking for EMPTY content type is done by the - * validator, no need to check here - */ - handleStartElem(c); - return START_ELEMENT; - } - if (c == '[') { - throwUnexpectedChar(c, " in content after '<' (malformed = mShortestTextSegment) { - mTokenState = TOKEN_PARTIAL_SINGLE; - } else { - mTokenState = TOKEN_STARTED; - } - } - return CHARACTERS; - } - - /** - * Method called when advacing stream past the end tag that closes - * the root element of the open document. - * Document can be either the singular one, in regular mode, or one of - * possibly multiple, in multi-doc mode: this method is never called - * in fragment mode. Method needs to update state properly and - * parse following epilog event (if any). - * - * @return Event following end tag of the root elemennt, if any; - * END_DOCUMENT otherwis.e - */ - private int closeContentTree() - throws XMLStreamException - { - mParseState = STATE_EPILOG; - // this call will update the location too... - if (nextFromProlog(false)) { - mSecondaryToken = 0; - } - /* 10-Apr-2006, TSa: Let's actually try to update - * SymbolTable here (after main xml tree); caller - * may not continue parsing after this. - */ - if (mSymbols.isDirty()) { - mOwner.updateSymbolTable(mSymbols); - } - /* May be able to recycle, but not certain; and - * definitely can not just clean contents (may - * contain space(s) read) - */ - mTextBuffer.recycle(false); - return mCurrToken; - } - - /** - * Method that takes care of parsing of start elements; including - * full parsing of namespace declarations and attributes, as well as - * namespace resolution. - */ - private final void handleStartElem(char c) - throws XMLStreamException - { - mTokenState = TOKEN_FULL_COALESCED; - boolean empty; - - if (mCfgNsEnabled) { - String str = parseLocalName(c); - c = (mInputPtr < mInputEnd) ? - mInputBuffer[mInputPtr++] : getNextCharFromCurrent(SUFFIX_EOF_EXP_NAME); - if (c == ':') { // Ok, got namespace and local name - c = (mInputPtr < mInputEnd) ? - mInputBuffer[mInputPtr++] : getNextCharFromCurrent(SUFFIX_EOF_EXP_NAME); - mElementStack.push(str, parseLocalName(c)); - c = (mInputPtr < mInputEnd) ? - mInputBuffer[mInputPtr++] : getNextCharFromCurrent(SUFFIX_IN_ELEMENT); - } else { - mElementStack.push(null, str); - // c is fine as - } - /* Enough about element name itself; let's then parse attributes - * and namespace declarations. Split into another method for clarity, - * and so that maybe JIT has easier time to optimize it separately. - */ - /* 04-Jul-2005, TSa: But hold up: we can easily check for a fairly - * common case of no attributes showing up, and us getting the - * closing '>' right away. Let's do that, since it can save - * a call to a rather long method. - */ - empty = (c == '>') ? false : handleNsAttrs(c); - } else { // Namespace handling not enabled: - mElementStack.push(null, parseFullName(c)); - c = (mInputPtr < mInputEnd) ? - mInputBuffer[mInputPtr++] : getNextCharFromCurrent(SUFFIX_IN_ELEMENT); - empty = (c == '>') ? false : handleNonNsAttrs(c); - } - if (!empty) { - ++mCurrDepth; // needed to match nesting with entity expansion - } - mStEmptyElem = empty; - - /* 27-Feb-2009, TSa: [WSTX-191]: We used to validate virtual - * end element here for empty elements, but it really should - * occur later on when actually returning that end element. - */ - int vld = mElementStack.resolveAndValidateElement(); - mVldContent = vld; - mValidateText = (vld == XMLValidator.CONTENT_ALLOW_VALIDATABLE_TEXT); - } - - /** - * @return True if this is an empty element; false if not - */ - private final boolean handleNsAttrs(char c) - throws XMLStreamException - { - AttributeCollector ac = mAttrCollector; - - while (true) { - if (c <= CHAR_SPACE) { - c = getNextInCurrAfterWS(SUFFIX_IN_ELEMENT, c); - } else if (c != '/' && c != '>') { - throwUnexpectedChar(c, " excepted space, or '>' or \"/>\""); - } - - if (c == '/') { - c = getNextCharFromCurrent(SUFFIX_IN_ELEMENT); - if (c != '>') { - throwUnexpectedChar(c, " expected '>'"); - } - return true; - } else if (c == '>') { - return false; - } else if (c == '<') { - throwParseError("Unexpected '<' character in element (missing closing '>'?)"); - } - - String prefix, localName; - String str = parseLocalName(c); - c = (mInputPtr < mInputEnd) ? - mInputBuffer[mInputPtr++] : getNextCharFromCurrent(SUFFIX_EOF_EXP_NAME); - if (c == ':') { // Ok, got namespace and local name - prefix = str; - c = (mInputPtr < mInputEnd) ? - mInputBuffer[mInputPtr++] : getNextCharFromCurrent(SUFFIX_EOF_EXP_NAME); - localName = parseLocalName(c); - } else { - --mInputPtr; // pushback - prefix = null; - localName = str; - } - - c = (mInputPtr < mInputEnd) ? - mInputBuffer[mInputPtr++] : getNextCharFromCurrent(SUFFIX_IN_ELEMENT); - if (c <= CHAR_SPACE) { - c = getNextInCurrAfterWS(SUFFIX_IN_ELEMENT, c); - } - if (c != '=') { - throwUnexpectedChar(c, " expected '='"); - } - c = (mInputPtr < mInputEnd) ? - mInputBuffer[mInputPtr++] : getNextCharFromCurrent(SUFFIX_IN_ELEMENT); - if (c <= CHAR_SPACE) { - c = getNextInCurrAfterWS(SUFFIX_IN_ELEMENT, c); - } - - // And then a quote: - if (c != '"' && c != '\'') { - throwUnexpectedChar(c, SUFFIX_IN_ELEMENT+" Expected a quote"); - } - - // And then the actual value - int startLen = -1; - TextBuilder tb; - - if (prefix == sPrefixXmlns) { // non-default namespace declaration - tb = ac.getNsBuilder(localName); - // returns null if it's a dupe: - if (null == tb) { - throwParseError("Duplicate declaration for namespace prefix '"+localName+"'."); - } - startLen = tb.getCharSize(); - } else if (localName == sPrefixXmlns && prefix == null) { - tb = ac.getDefaultNsBuilder(); - // returns null if default ns was already declared - if (null == tb) { - throwParseError("Duplicate default namespace declaration."); - } - } else { - tb = ac.getAttrBuilder(prefix, localName); - } - parseAttrValue(c, tb); - - /* 19-Jul-2004, TSa: Need to check that non-default namespace - * URI is NOT empty, as per XML namespace specs, #2, - * ("...In such declarations, the namespace name may not - * be empty.") - */ - /* (note: startLen is only set to first char position for - * non-default NS declarations, see above...) - */ - /* 04-Feb-2005, TSa: Namespaces 1.1 does allow this, though, - * so for xml 1.1 documents we need to allow it - */ - if (!mXml11) { - if (startLen >= 0 && tb.getCharSize() == startLen) { // is empty! - throwParseError(ErrorConsts.ERR_NS_EMPTY); - } - } - - // and then we need to iterate some more - c = (mInputPtr < mInputEnd) ? - mInputBuffer[mInputPtr++] : getNextCharFromCurrent(SUFFIX_IN_ELEMENT); - } - // never gets here - } - - /** - * @return True if this is an empty element; false if not - */ - private final boolean handleNonNsAttrs(char c) - throws XMLStreamException - { - AttributeCollector ac = mAttrCollector; - - while (true) { - if (c <= CHAR_SPACE) { - c = getNextInCurrAfterWS(SUFFIX_IN_ELEMENT, c); - } else if (c != '/' && c != '>') { - throwUnexpectedChar(c, " excepted space, or '>' or \"/>\""); - } - if (c == '/') { - c = getNextCharFromCurrent(SUFFIX_IN_ELEMENT); - if (c != '>') { - throwUnexpectedChar(c, " expected '>'"); - } - return true; - } else if (c == '>') { - return false; - } else if (c == '<') { - throwParseError("Unexpected '<' character in element (missing closing '>'?)"); - } - - String name = parseFullName(c); - TextBuilder tb = ac.getAttrBuilder(null, name); - c = (mInputPtr < mInputEnd) ? - mInputBuffer[mInputPtr++] : getNextCharFromCurrent(SUFFIX_IN_ELEMENT); - if (c <= CHAR_SPACE) { - c = getNextInCurrAfterWS(SUFFIX_IN_ELEMENT, c); - } - if (c != '=') { - throwUnexpectedChar(c, " expected '='"); - } - c = (mInputPtr < mInputEnd) ? - mInputBuffer[mInputPtr++] : getNextCharFromCurrent(SUFFIX_IN_ELEMENT); - if (c <= CHAR_SPACE) { - c = getNextInCurrAfterWS(SUFFIX_IN_ELEMENT, c); - } - - // And then a quote: - if (c != '"' && c != '\'') { - throwUnexpectedChar(c, SUFFIX_IN_ELEMENT+" Expected a quote"); - } - - // And then the actual value - parseAttrValue(c, tb); - // and then we need to iterate some more - c = (mInputPtr < mInputEnd) ? - mInputBuffer[mInputPtr++] : getNextCharFromCurrent(SUFFIX_IN_ELEMENT); - } - // never gets here - } - - /** - * Method called to completely read a close tag, and update element - * stack appropriately (including checking that tag matches etc). - */ - protected final void readEndElem() - throws XMLStreamException - { - mTokenState = TOKEN_FULL_COALESCED; // will be read completely - - if (mElementStack.isEmpty()) { - // Let's just offline this for clarity - reportExtraEndElem(); - return; // never gets here - } - - char c = (mInputPtr < mInputEnd) ? mInputBuffer[mInputPtr++] - : getNextCharFromCurrent(SUFFIX_IN_CLOSE_ELEMENT); - // Quick check first; missing name? - if (!isNameStartChar(c) && c != ':') { - if (c <= CHAR_SPACE) { // space - throwUnexpectedChar(c, "; missing element name?"); - } - throwUnexpectedChar(c, "; expected an element name."); - } - - /* Ok, now; good thing is we know exactly what to compare - * against... - */ - String expPrefix = mElementStack.getPrefix(); - String expLocalName = mElementStack.getLocalName(); - - // Prefix to match? - if (expPrefix != null && expPrefix.length() > 0) { - int len = expPrefix.length(); - int i = 0; - - while (true){ - if (c != expPrefix.charAt(i)) { - reportWrongEndPrefix(expPrefix, expLocalName, i); - return; // never gets here - } - if (++i >= len) { - break; - } - c = (mInputPtr < mInputEnd) ? mInputBuffer[mInputPtr++] - : getNextCharFromCurrent(SUFFIX_IN_CLOSE_ELEMENT); - } - // And then we should get a colon - c = (mInputPtr < mInputEnd) ? mInputBuffer[mInputPtr++] - : getNextCharFromCurrent(SUFFIX_IN_CLOSE_ELEMENT); - if (c != ':') { - reportWrongEndPrefix(expPrefix, expLocalName, i); - return; - } - c = (mInputPtr < mInputEnd) ? mInputBuffer[mInputPtr++] - : getNextCharFromCurrent(SUFFIX_IN_CLOSE_ELEMENT); - } - - // Ok, then, does the local name match? - int len = expLocalName.length(); - int i = 0; - - while (true){ - if (c != expLocalName.charAt(i)) { - // Not a match... - reportWrongEndElem(expPrefix, expLocalName, i); - return; // never gets here - } - if (++i >= len) { - break; - } - c = (mInputPtr < mInputEnd) ? mInputBuffer[mInputPtr++] - : getNextCharFromCurrent(SUFFIX_IN_CLOSE_ELEMENT); - } - - // Let's see if end element still continues, however? - c = (mInputPtr < mInputEnd) ? mInputBuffer[mInputPtr++] - : getNextCharFromCurrent(SUFFIX_IN_CLOSE_ELEMENT); - if (c <= CHAR_SPACE) { - c = getNextInCurrAfterWS(SUFFIX_IN_CLOSE_ELEMENT, c); - } else if (c == '>') { - ; - } else if (c == ':' || isNameChar(c)) { - reportWrongEndElem(expPrefix, expLocalName, len); - } - - // Ok, fine, match ok; now we just need the closing gt char. - if (c != '>') { - throwUnexpectedChar(c, SUFFIX_IN_CLOSE_ELEMENT+" Expected '>'."); - } - - // Finally, let's let validator detect if things are ok - int vld = mElementStack.validateEndElement(); - mVldContent = vld; - mValidateText = (vld == XMLValidator.CONTENT_ALLOW_VALIDATABLE_TEXT); - - // Plus verify WFC that start and end tags came from same entity - /* 13-Feb-2006, TSa: Are we about to close an element that - * started within a parent element? - * That's a GE/element nesting WFC violation... - */ - if (mCurrDepth == mInputTopDepth) { - handleGreedyEntityProblem(mInput); - } - --mCurrDepth; - } - - private void reportExtraEndElem() - throws XMLStreamException - { - String name = parseFNameForError(); - throwParseError("Unbalanced close tag ; no open start tag."); - } - - private void reportWrongEndPrefix(String prefix, String localName, int done) - throws XMLStreamException - { - --mInputPtr; // pushback - String fullName = prefix + ":" + localName; - String rest = parseFNameForError(); - String actName = fullName.substring(0, done) + rest; - throwParseError("Unexpected close tag ; expected ."); - } - - private void reportWrongEndElem(String prefix, String localName, int done) - throws XMLStreamException - { - --mInputPtr; // pushback - String fullName; - if (prefix != null && prefix.length() > 0) { - fullName = prefix + ":" + localName; - done += 1 + prefix.length(); - } else { - fullName = localName; - } - String rest = parseFNameForError(); - String actName = fullName.substring(0, done) + rest; - throwParseError("Unexpected close tag ; expected ."); - } - - /** - *

- * Note: According to StAX 1.0, coalesced text events are always to be - * returned as CHARACTERS, never as CDATA. And since at this point we - * don't really know if there's anything to coalesce (but there may - * be), let's convert CDATA if necessary. - */ - private int nextFromTreeCommentOrCData() - throws XMLStreamException - { - char c = getNextCharFromCurrent(SUFFIX_IN_DOC); - if (c == '[') { - checkCData(); - /* Good enough; it is a CDATA section... but let's just also - * parse the easy ("free") stuff: - */ - c = (mInputPtr < mInputEnd) ? mInputBuffer[mInputPtr++] - : getNextCharFromCurrent(SUFFIX_IN_CDATA); - readCDataPrimary(c); // sets token state appropriately... - return CDATA; - } - if (c == '-' && getNextCharFromCurrent(SUFFIX_IN_DOC) == '-') { - mTokenState = TOKEN_STARTED; - return COMMENT; - } - throwParseError("Unrecognized XML directive; expected CDATA or comment (' - * Note: this method is to accurately update the location information - * to reflect where the next event will start (or, in case of EOF, where - * EOF was encountered, ie. where event would start, if there was one). - * - * @return Next character after node has been skipped, or -1 if EOF - * follows - */ - private int skipToken() - throws XMLStreamException - { - int result; - - main_switch: - switch (mCurrToken) { - case CDATA: - { - /* 30-Aug-2004, TSa: Need to be careful here: we may - * actually have finished with CDATA, but are just - * coalescing... if so, need to skip first part of - * skipping - */ - if (mTokenState <= TOKEN_PARTIAL_SINGLE) { - // Skipping CDATA is easy; just need to spot closing ]]> - skipCommentOrCData(SUFFIX_IN_CDATA, ']', false); - } - result = getNext(); - // ... except if coalescing, may need to skip more: - if (mCfgCoalesceText) { - result = skipCoalescedText(result); - } - } - break; - - case COMMENT: - skipCommentOrCData(SUFFIX_IN_COMMENT, '-', true); - result = 0; - break; - - case CHARACTERS: - { - result = skipTokenText(getNext()); - // ... except if coalescing, need to skip more: - if (mCfgCoalesceText) { - result = skipCoalescedText(result); - } - } - break; - - case DTD: - finishDTD(false); - result = 0; - break; - - case PROCESSING_INSTRUCTION: - while (true) { - char c = (mInputPtr < mInputEnd) - ? mInputBuffer[mInputPtr++] : getNextCharFromCurrent(SUFFIX_IN_PROC_INSTR); - if (c == '?') { - do { - c = (mInputPtr < mInputEnd) - ? mInputBuffer[mInputPtr++] : getNextCharFromCurrent(SUFFIX_IN_PROC_INSTR); - } while (c == '?'); - if (c == '>') { - result = 0; - break main_switch; - } - } - if (c < CHAR_SPACE) { - if (c == '\n' || c == '\r') { - skipCRLF(c); - } else if (c != '\t') { - throwInvalidSpace(c); - } - } - } - // never gets in here - - case SPACE: - - while (true) { - // Fairly easy to skip through white space... - while (mInputPtr < mInputEnd) { - char c = mInputBuffer[mInputPtr++]; - if (c > CHAR_SPACE) { // non-EOF non-WS? - result = c; - break main_switch; - } - if (c == '\n' || c == '\r') { - skipCRLF(c); - } else if (c != CHAR_SPACE && c != '\t') { - throwInvalidSpace(c); - } - } - if (!loadMore()) { - result = -1; - break main_switch; - } - } - // never gets in here - - case ENTITY_REFERENCE: // these should never end up in here... - case ENTITY_DECLARATION: - case NOTATION_DECLARATION: - case START_DOCUMENT: - case END_DOCUMENT: - // As are start/end document - throw new IllegalStateException("skipToken() called when current token is "+tokenTypeDesc(mCurrToken)); - - case ATTRIBUTE: - case NAMESPACE: - // These two are never returned by this class - case START_ELEMENT: - case END_ELEMENT: - /* Never called for elements tokens; start token handled - * differently, end token always completely read in the first place - */ - - default: - throw new IllegalStateException("Internal error: unexpected token "+tokenTypeDesc(mCurrToken)); - - } - - /* Ok; now we have 3 possibilities; result is: - * - * + 0 -> could reliably read the prev event, now need the - * following char/EOF - * + -1 -> hit EOF; can return it - * + something else -> this is the next char, return it. - * - * In first 2 cases, next event start offset is the current location; - * in third case, it needs to be backtracked by one char - */ - if (result < 1) { - mTokenInputRow = mCurrInputRow; - mTokenInputTotal = mCurrInputProcessed + mInputPtr; - mTokenInputCol = mInputPtr - mCurrInputRowStart; - return (result < 0) ? result : getNext(); - } - - // Ok, need to offset location, and return whatever we got: - mTokenInputRow = mCurrInputRow; - mTokenInputTotal = mCurrInputProcessed + mInputPtr - 1; - mTokenInputCol = mInputPtr - mCurrInputRowStart - 1; - return result; - } - - private void skipCommentOrCData(String errorMsg, char endChar, boolean preventDoubles) - throws XMLStreamException - { - /* Let's skip all chars except for double-ending chars in - * question (hyphen for comments, right brack for cdata) - */ - while (true) { - char c; - do { - c = (mInputPtr < mInputEnd) - ? mInputBuffer[mInputPtr++] : getNextCharFromCurrent(errorMsg); - if (c < CHAR_SPACE) { - if (c == '\n' || c == '\r') { - skipCRLF(c); - } else if (c != '\t') { - throwInvalidSpace(c); - } - } - } while (c != endChar); - - // Now, we may be getting end mark; first need second marker char:. - c = getNextChar(errorMsg); - if (c == endChar) { // Probably? - // Now; we should be getting a '>', most likely. - c = getNextChar(errorMsg); - if (c == '>') { - break; - } - if (preventDoubles) { // if not, it may be a problem... - throwParseError("String '--' not allowed in comment (missing '>'?)"); - } - // Otherwise, let's loop to see if there is end - while (c == endChar) { - c = (mInputPtr < mInputEnd) - ? mInputBuffer[mInputPtr++] : getNextCharFromCurrent(errorMsg); - } - if (c == '>') { - break; - } - } - - // No match, did we get a linefeed? - if (c < CHAR_SPACE) { - if (c == '\n' || c == '\r') { - skipCRLF(c); - } else if (c != '\t') { - throwInvalidSpace(c); - } - } - - // Let's continue from beginning, then - } - } - - /** - * Method called to skip past all following text and CDATA segments, - * until encountering something else (including a general entity, - * which may in turn expand to text). - * - * @return Character following all the skipped text and CDATA segments, - * if any; or -1 to denote EOF - */ - private int skipCoalescedText(int i) - throws XMLStreamException - { - while (true) { - // Ok, plain text or markup? - if (i == '<') { // markup, maybe CDATA? - // Need to distinguish "= 3 - && resolveSimpleEntity(true) != 0) { - ; - } else { - i = fullyResolveEntity(true); - /* Either way, it's just fine; we don't care about - * returned single-char value. - */ - } - } else { - /* Can only skip character entities; others need to - * be returned separately. - */ - if (resolveCharOnlyEntity(true) == 0) { - /* Now points to the char after ampersand, and we need - * to return the ampersand itself - */ - return i; - } - } - } else if (i < CHAR_SPACE) { - if (i == '\r' || i == '\n') { - skipCRLF((char) i); - } else if (i < 0) { // EOF - return i; - } else if (i != '\t') { - throwInvalidSpace(i); - } - - } - - // Hmmh... let's do quick looping here: - while (mInputPtr < mInputEnd) { - char c = mInputBuffer[mInputPtr++]; - if (c < CHAR_FIRST_PURE_TEXT) { // need to check it - i = c; - continue main_loop; - } - } - - i = getNext(); - } - // never gets here... - } - - /* - //////////////////////////////////////////////////// - // Internal methods, parsing - //////////////////////////////////////////////////// - */ - - protected void ensureFinishToken() - throws XMLStreamException - { - if (mTokenState < mStTextThreshold) { - finishToken(false); - } - } - - protected void safeEnsureFinishToken() - { - if (mTokenState < mStTextThreshold) { - safeFinishToken(); - } - } - - protected void safeFinishToken() - { - try { - /* 24-Sep-2006, TSa: Let's try to reduce number of unchecked - * (wrapped) exceptions we throw, and defer some. For now, - * this is only for CHARACTERS (since it's always legal to - * split CHARACTERS segment); could be expanded in future. - */ - boolean deferErrors = (mCurrToken == CHARACTERS); - finishToken(deferErrors); - } catch (XMLStreamException strex) { - throwLazyError(strex); - } - } - - /** - * Method called to read in contents of the token completely, if not - * yet read. Generally called when caller needs to access anything - * other than basic token type (except for elements), text contents - * or such. - * - * @param deferErrors Flag to enable storing an exception to a - * variable, instead of immediately throwing it. If true, will - * just store the exception; if false, will not store, just throw. - */ - protected void finishToken(boolean deferErrors) - throws XMLStreamException - { - switch (mCurrToken) { - case CDATA: - if (mCfgCoalesceText) { - readCoalescedText(mCurrToken, deferErrors); - } else { - if (readCDataSecondary(mShortestTextSegment)) { - mTokenState = TOKEN_FULL_SINGLE; - } else { - mTokenState = TOKEN_PARTIAL_SINGLE; - } - } - return; - - case CHARACTERS: - if (mCfgCoalesceText) { - /* 21-Sep-2005, TSa: It is often possible to optimize - * here: if we get '<' NOT followed by '!', it can not - * be CDATA, and thus we are done. - */ - if (mTokenState == TOKEN_FULL_SINGLE - && (mInputPtr + 1) < mInputEnd - && mInputBuffer[mInputPtr+1] != '!') { - mTokenState = TOKEN_FULL_COALESCED; - return; - } - readCoalescedText(mCurrToken, deferErrors); - } else { - if (readTextSecondary(mShortestTextSegment, deferErrors)) { - mTokenState = TOKEN_FULL_SINGLE; - } else { - mTokenState = TOKEN_PARTIAL_SINGLE; - } - } - return; - - case SPACE: - { - /* Only need to ensure there's no non-whitespace text - * when parsing 'real' ignorable white space (in validating - * mode, but that's implicit here) - */ - boolean prolog = (mParseState != STATE_TREE); - readSpaceSecondary(prolog); - mTokenState = TOKEN_FULL_COALESCED; - } - return; - - case COMMENT: - readComment(); - mTokenState = TOKEN_FULL_COALESCED; - return; - - case DTD: - - /* 05-Jan-2006, TSa: Although we shouldn't have to use finally - * here, it's probably better to do that for robustness - * (specifically, in case of a parsing problem, we don't want - * to remain in 'DTD partially read' case -- it's better - * to get in panic mode and skip the rest) - */ - try { - finishDTD(true); - } finally { - mTokenState = TOKEN_FULL_COALESCED; - } - return; - - case PROCESSING_INSTRUCTION: - readPI(); - mTokenState = TOKEN_FULL_COALESCED; - return; - - case START_ELEMENT: - case END_ELEMENT: // these 2 should never end up in here... - case ENTITY_REFERENCE: - case ENTITY_DECLARATION: - case NOTATION_DECLARATION: - case START_DOCUMENT: - case END_DOCUMENT: - throw new IllegalStateException("finishToken() called when current token is "+tokenTypeDesc(mCurrToken)); - - case ATTRIBUTE: - case NAMESPACE: - // These two are never returned by this class - default: - } - - throw new IllegalStateException("Internal error: unexpected token "+tokenTypeDesc(mCurrToken)); - } - - private void readComment() - throws XMLStreamException - { - char[] inputBuf = mInputBuffer; - int inputLen = mInputEnd; - int ptr = mInputPtr; - int start = ptr; - - // Let's first see if we can just share input buffer: - while (ptr < inputLen) { - char c = inputBuf[ptr++]; - if (c > '-') { - continue; - } - - if (c < CHAR_SPACE) { - if (c == '\n') { - markLF(ptr); - } else if (c == '\r') { - if (!mNormalizeLFs && ptr < inputLen) { - if (inputBuf[ptr] == '\n') { - ++ptr; - } - markLF(ptr); - } else { - --ptr; // pushback - break; - } - } else if (c != '\t') { - throwInvalidSpace(c); - } - } else if (c == '-') { - // Ok; need to get '->', can not get '--' - - if ((ptr + 1) >= inputLen) { - /* Can't check next 2, let's push '-' back, for rest of - * code to take care of - */ - --ptr; - break; - } - - if (inputBuf[ptr] != '-') { - // Can't skip, might be LF/CR - continue; - } - // Ok; either get '>' or error: - c = inputBuf[ptr+1]; - if (c != '>') { - throwParseError("String '--' not allowed in comment (missing '>'?)"); - } - mTextBuffer.resetWithShared(inputBuf, start, ptr-start-1); - mInputPtr = ptr + 2; - return; - } - } - - mInputPtr = ptr; - mTextBuffer.resetWithCopy(inputBuf, start, ptr-start); - readComment2(mTextBuffer); - } - - private void readComment2(TextBuffer tb) - throws XMLStreamException - { - /* Output pointers; calls will also ensure that the buffer is - * not shared, AND has room for at least one more char - */ - char[] outBuf = mTextBuffer.getCurrentSegment(); - int outPtr = mTextBuffer.getCurrentSegmentSize(); - int outLen = outBuf.length; - - while (true) { - char c = (mInputPtr < mInputEnd) ? - mInputBuffer[mInputPtr++] : getNextCharFromCurrent(SUFFIX_IN_COMMENT); - - if (c < CHAR_SPACE) { - if (c == '\n') { - markLF(); - } else if (c == '\r') { - if (skipCRLF(c)) { // got 2 char LF - if (!mNormalizeLFs) { - if (outPtr >= outLen) { // need more room? - outBuf = mTextBuffer.finishCurrentSegment(); - outLen = outBuf.length; - outPtr = 0; - } - outBuf[outPtr++] = c; - } - // And let's let default output the 2nd char - c = '\n'; - } else if (mNormalizeLFs) { // just \r, but need to convert - c = '\n'; // For Mac text - } - } else if (c != '\t') { - throwInvalidSpace(c); - } - } else if (c == '-') { // Ok; need to get '->', can not get '--' - c = getNextCharFromCurrent(SUFFIX_IN_COMMENT); - if (c == '-') { // Ok, has to be end marker then: - // Either get '>' or error: - c = getNextCharFromCurrent(SUFFIX_IN_COMMENT); - if (c != '>') { - throwParseError(ErrorConsts.ERR_HYPHENS_IN_COMMENT); - } - break; - } - - /* Not the end marker; let's just output the first hyphen, - * push the second char back , and let main - * code handle it. - */ - c = '-'; - --mInputPtr; - } - - // Need more room? - if (outPtr >= outLen) { - outBuf = mTextBuffer.finishCurrentSegment(); - outLen = outBuf.length; - outPtr = 0; - } - // Ok, let's add char to output: - outBuf[outPtr++] = c; - } - - // Ok, all done, then! - mTextBuffer.setCurrentLength(outPtr); - } - - /** - * Method that reads the primary part of a PI, ie. target, and also - * skips white space between target and data (if any data) - * - * @return Usually PROCESSING_INSTRUCTION; but may be - * different in multi-doc mode, if we actually hit a secondary - * xml declaration. - */ - private final int readPIPrimary() - throws XMLStreamException - { - // Ok, first we need the name: - String target = parseFullName(); - mCurrName = target; - - if (target.length() == 0) { - throwParseError(ErrorConsts.ERR_WF_PI_MISSING_TARGET); - } - - // As per XML specs, #17, case-insensitive 'xml' is illegal: - if (target.equalsIgnoreCase("xml")) { - // 07-Oct-2005, TSa: Still legal in multi-doc mode... - if (!mConfig.inputParsingModeDocuments()) { - throwParseError(ErrorConsts.ERR_WF_PI_XML_TARGET, target, null); - } - // Ok, let's just verify we get space then - char c = getNextCharFromCurrent(SUFFIX_IN_XML_DECL); - if (!isSpaceChar(c)) { - throwUnexpectedChar(c, "excepted a space in xml declaration after 'xml'"); - } - return handleMultiDocStart(START_DOCUMENT); - } - - // And then either white space before data, or end marker: - char c = (mInputPtr < mInputEnd) ? - mInputBuffer[mInputPtr++] : getNextCharFromCurrent(SUFFIX_IN_PROC_INSTR); - if (isSpaceChar(c)) { // Ok, space to skip - mTokenState = TOKEN_STARTED; - // Need to skip the WS... - skipWS(c); - } else { // Nope; apparently finishes right away... - mTokenState = TOKEN_FULL_COALESCED; - mTextBuffer.resetWithEmpty(); - // or does it? - if (c != '?' || getNextCharFromCurrent(SUFFIX_IN_PROC_INSTR) != '>') { - throwUnexpectedChar(c, ErrorConsts.ERR_WF_PI_XML_MISSING_SPACE); - } - } - - return PROCESSING_INSTRUCTION; - } - - /** - * Method that parses a processing instruction's data portion; at this - * point target has been parsed. - */ - private void readPI() - throws XMLStreamException - { - int ptr = mInputPtr; - int start = ptr; - char[] inputBuf = mInputBuffer; - int inputLen = mInputEnd; - - outer_loop: - while (ptr < inputLen) { - char c = inputBuf[ptr++]; - if (c < CHAR_SPACE) { - if (c == '\n') { - markLF(ptr); - } else if (c == '\r') { - if (ptr < inputLen && !mNormalizeLFs) { - if (inputBuf[ptr] == '\n') { - ++ptr; - } - markLF(ptr); - } else { - --ptr; // pushback - break; - } - } else if (c != '\t') { - throwInvalidSpace(c); - } - } else if (c == '?') { - // K; now just need '>' after zero or more '?'s - while (true) { - if (ptr >= inputLen) { - /* end of buffer; need to push back at least one of - * question marks (not all, since just one is needed - * to close the PI) - */ - --ptr; - break outer_loop; - } - c = inputBuf[ptr++]; - if (c == '>') { - mInputPtr = ptr; - // Need to discard trailing '?>' - mTextBuffer.resetWithShared(inputBuf, start, ptr-start-2); - return; - } - if (c != '?') { - // Not end, can continue, but need to push back last char, in case it's LF/CR - --ptr; - break; - } - } - } - } - - mInputPtr = ptr; - // No point in trying to share... let's just append - mTextBuffer.resetWithCopy(inputBuf, start, ptr-start); - readPI2(mTextBuffer); - } - - private void readPI2(TextBuffer tb) - throws XMLStreamException - { - char[] inputBuf = mInputBuffer; - int inputLen = mInputEnd; - int inputPtr = mInputPtr; - - /* Output pointers; calls will also ensure that the buffer is - * not shared, AND has room for one more char - */ - char[] outBuf = tb.getCurrentSegment(); - int outPtr = tb.getCurrentSegmentSize(); - - main_loop: - while (true) { - // Let's first ensure we have some data in there... - if (inputPtr >= inputLen) { - loadMoreFromCurrent(SUFFIX_IN_PROC_INSTR); - inputBuf = mInputBuffer; - inputPtr = mInputPtr; - inputLen = mInputEnd; - } - - // And then do chunks - char c = inputBuf[inputPtr++]; - if (c < CHAR_SPACE) { - if (c == '\n') { - markLF(inputPtr); - } else if (c == '\r') { - mInputPtr = inputPtr; - if (skipCRLF(c)) { // got 2 char LF - if (!mNormalizeLFs) { - // Special handling, to output 2 chars at a time: - if (outPtr >= outBuf.length) { // need more room? - outBuf = mTextBuffer.finishCurrentSegment(); - outPtr = 0; - } - outBuf[outPtr++] = c; - } - // And let's let default output the 2nd char, either way - c = '\n'; - } else if (mNormalizeLFs) { // just \r, but need to convert - c = '\n'; // For Mac text - } - /* Since skipCRLF() needs to peek(), buffer may have - * changed, even if there was no CR+LF. - */ - inputPtr = mInputPtr; - inputBuf = mInputBuffer; - inputLen = mInputEnd; - } else if (c != '\t') { - throwInvalidSpace(c); - } - } else if (c == '?') { // Ok, just need '>' after zero or more '?'s - mInputPtr = inputPtr; // to allow us to call getNextChar - - qmLoop: - while (true) { - c = (mInputPtr < mInputEnd) ? mInputBuffer[mInputPtr++] - : getNextCharFromCurrent(SUFFIX_IN_PROC_INSTR); - if (c == '>') { // got it! - break main_loop; - } else if (c == '?') { - if (outPtr >= outBuf.length) { // need more room? - outBuf = tb.finishCurrentSegment(); - outPtr = 0; - } - outBuf[outPtr++] = c; - } else { - /* Hmmh. Wasn't end mark after all. Thus, need to - * fall back to normal processing, with one more - * question mark (first one matched that wasn't - * yet output), - * reset variables, and go back to main loop. - */ - inputPtr = --mInputPtr; // push back last char - inputBuf = mInputBuffer; - inputLen = mInputEnd; - c = '?'; - break qmLoop; - } - } - } // if (c == '?) - - // Need more room? - if (outPtr >= outBuf.length) { - outBuf = tb.finishCurrentSegment(); - outPtr = 0; - } - // Ok, let's add char to output: - outBuf[outPtr++] = c; - - } // while (true) - - tb.setCurrentLength(outPtr); - } - - /** - * Method called to read the content of both current CDATA/CHARACTERS - * events, and all following consequtive events into the text buffer. - * At this point the current type is known, prefix (for CDATA) skipped, - * and initial consequtive contents (if any) read in. - * - * @param deferErrors Flag to enable storing an exception to a - * variable, instead of immediately throwing it. If true, will - * just store the exception; if false, will not store, just throw. - */ - protected void readCoalescedText(int currType, boolean deferErrors) - throws XMLStreamException - { - boolean wasCData; - - // Ok; so we may need to combine adjacent text/CDATA chunks. - if (currType == CHARACTERS || currType == SPACE) { - readTextSecondary(Integer.MAX_VALUE, deferErrors); - wasCData = false; - } else if (currType == CDATA) { - /* We may have actually really finished it, but just left - * the 'unfinished' flag due to need to coalesce... - */ - if (mTokenState <= TOKEN_PARTIAL_SINGLE) { - readCDataSecondary(Integer.MAX_VALUE); - } - wasCData = true; - } else { - throw new IllegalStateException("Internal error: unexpected token "+tokenTypeDesc(mCurrToken)+"; expected CHARACTERS, CDATA or SPACE."); - } - - // But how about additional text? - while (!deferErrors || (mPendingException == null)) { - if (mInputPtr >= mInputEnd) { - mTextBuffer.ensureNotShared(); - if (!loadMore()) { - // ??? Likely an error but let's just break - break; - } - } - // Let's peek, ie. not advance it yet - char c = mInputBuffer[mInputPtr]; - if (c == '<') { // CDATA, maybe? - // Need to distinguish ") or until - * first 'hole' in text (buffer end, 2-char lf to convert, entity). - *

- * When the method is called, it's expected that the first character - * has been read as is in the current input buffer just before current - * pointer - * - * @param c First character in the CDATA segment (possibly part of end - * marker for empty segments - * - * @return True if the whole CDATA segment was completely read; this - * happens only if lt-char is hit; false if it's possible that - * it wasn't read (ie. end-of-buffer or entity encountered). - */ - private final boolean readCDataPrimary(char c) - throws XMLStreamException - { - mWsStatus = (c <= CHAR_SPACE) ? ALL_WS_UNKNOWN : ALL_WS_NO; - - int ptr = mInputPtr; - int inputLen = mInputEnd; - char[] inputBuf = mInputBuffer; - int start = ptr-1; - - while (true) { - if (c < CHAR_SPACE) { - if (c == '\n') { - markLF(ptr); - } else if (c == '\r') { - if (ptr >= inputLen) { // can't peek? - --ptr; - break; - } - if (mNormalizeLFs) { // can we do in-place Mac replacement? - if (inputBuf[ptr] == '\n') { // nope, 2 char lf - --ptr; - break; - } - inputBuf[ptr-1] = '\n'; // yup - } else { - // No LF normalization... can we just skip it? - if (inputBuf[ptr] == '\n') { - ++ptr; - } - } - markLF(ptr); - } else if (c != '\t') { - throwInvalidSpace(c); - } - } else if (c == ']') { - // Ok; need to get one or more ']'s, then '>' - if ((ptr + 1) >= inputLen) { // not enough room? need to push it back - --ptr; - break; - } - - // Needs to be followed by another ']'... - if (inputBuf[ptr] == ']') { - ++ptr; - inner_loop: - while (true) { - if (ptr >= inputLen) { - /* Need to push back last 2 right brackets; it may - * be end marker divided by input buffer boundary - */ - ptr -= 2; - break inner_loop; - } - c = inputBuf[ptr++]; - if (c == '>') { // Ok, got it! - mInputPtr = ptr; - ptr -= (start+3); - mTextBuffer.resetWithShared(inputBuf, start, ptr); - mTokenState = TOKEN_FULL_SINGLE; - return true; - } - if (c != ']') { - // Need to re-check this char (may be linefeed) - --ptr; - break inner_loop; - } - // Fall through to next round - } - } - } - - if (ptr >= inputLen) { // end-of-buffer? - break; - } - c = inputBuf[ptr++]; - } - - mInputPtr = ptr; - - /* If we end up here, we either ran out of input, or hit something - * which would leave 'holes' in buffer... fine, let's return then; - * we can still update shared buffer copy: would be too early to - * make a copy since caller may not even be interested in the - * stuff. - */ - int len = ptr - start; - mTextBuffer.resetWithShared(inputBuf, start, len); - if (mCfgCoalesceText || - (mTextBuffer.size() < mShortestTextSegment)) { - mTokenState = TOKEN_STARTED; - } else { - mTokenState = TOKEN_PARTIAL_SINGLE; - } - return false; - } - - /** - * @return True if the whole CData section was completely read (we - * hit the end marker); false if a shorter segment was returned. - */ - protected boolean readCDataSecondary(int shortestSegment) - throws XMLStreamException - { - // Input pointers - char[] inputBuf = mInputBuffer; - int inputLen = mInputEnd; - int inputPtr = mInputPtr; - - /* Output pointers; calls will also ensure that the buffer is - * not shared, AND has room for one more char - */ - char[] outBuf = mTextBuffer.getCurrentSegment(); - int outPtr = mTextBuffer.getCurrentSegmentSize(); - - while (true) { - if (inputPtr >= inputLen) { - loadMore(SUFFIX_IN_CDATA); - inputBuf = mInputBuffer; - inputPtr = mInputPtr; - inputLen = mInputEnd; - } - char c = inputBuf[inputPtr++]; - - if (c < CHAR_SPACE) { - if (c == '\n') { - markLF(inputPtr); - } else if (c == '\r') { - mInputPtr = inputPtr; - if (skipCRLF(c)) { // got 2 char LF - if (!mNormalizeLFs) { - // Special handling, to output 2 chars at a time: - outBuf[outPtr++] = c; - if (outPtr >= outBuf.length) { // need more room? - outBuf = mTextBuffer.finishCurrentSegment(); - outPtr = 0; - } - } - // And let's let default output the 2nd char, either way - c = '\n'; - } else if (mNormalizeLFs) { // just \r, but need to convert - c = '\n'; // For Mac text - } - /* Since skipCRLF() needs to peek(), buffer may have - * changed, even if there was no CR+LF. - */ - inputPtr = mInputPtr; - inputBuf = mInputBuffer; - inputLen = mInputEnd; - } else if (c != '\t') { - throwInvalidSpace(c); - } - } else if (c == ']') { - // Ok; need to get ']>' - mInputPtr = inputPtr; - if (checkCDataEnd(outBuf, outPtr)) { - return true; - } - inputPtr = mInputPtr; - inputBuf = mInputBuffer; - inputLen = mInputEnd; - - outBuf = mTextBuffer.getCurrentSegment(); - outPtr = mTextBuffer.getCurrentSegmentSize(); - continue; // need to re-process last (non-bracket) char - } - - // Ok, let's add char to output: - outBuf[outPtr++] = c; - - // Need more room? - if (outPtr >= outBuf.length) { - TextBuffer tb = mTextBuffer; - // Perhaps we have now enough to return? - if (!mCfgCoalesceText) { - tb.setCurrentLength(outBuf.length); - if (tb.size() >= shortestSegment) { - mInputPtr = inputPtr; - return false; - } - } - // If not, need more buffer space: - outBuf = tb.finishCurrentSegment(); - outPtr = 0; - } - } - // never gets here - } - - /** - * Method that will check, given the starting ']', whether there is - * ending ']]>' (including optional extra ']'s); if so, will updated - * output buffer with extra ]s, if not, will make sure input and output - * are positioned for further checking. - * - * @return True, if we hit the end marker; false if not. - */ - private boolean checkCDataEnd(char[] outBuf, int outPtr) - throws XMLStreamException - { - int bracketCount = 0; - char c; - do { - ++bracketCount; - c = (mInputPtr < mInputEnd) ? mInputBuffer[mInputPtr++] - : getNextCharFromCurrent(SUFFIX_IN_CDATA); - } while (c == ']'); - - boolean match = (bracketCount >= 2 && c == '>'); - if (match) { - bracketCount -= 2; - } - while (bracketCount > 0) { - --bracketCount; - outBuf[outPtr++] = ']'; - if (outPtr >= outBuf.length) { - /* Can't really easily return, even if we have enough - * stuff here, since we've more than one char... - */ - outBuf = mTextBuffer.finishCurrentSegment(); - outPtr = 0; - } - } - mTextBuffer.setCurrentLength(outPtr); - // Match? Can break, then: - if (match) { - return true; - } - // No match, need to push the last char back and admit defeat... - --mInputPtr; - return false; - } - - /** - * Method called to read in consequtive beginning parts of a text - * segment, up to either end of the segment (lt char) or until - * first 'hole' in text (buffer end, 2-char lf to convert, entity). - *

- * When the method is called, it's expected that the first character - * has been read as is in the current input buffer just before current - * pointer - * - * @param c First character of the text segment - * - * @return True if the whole text segment was completely read; this - * happens only if lt-char is hit; false if it's possible that - * it wasn't read (ie. end-of-buffer or entity encountered). - */ - private final boolean readTextPrimary(char c) - throws XMLStreamException - { - int ptr = mInputPtr; - int start = ptr-1; - - // First: can we heuristically canonicalize ws used for indentation? - if (c <= CHAR_SPACE) { - int len = mInputEnd; - /* Even without indentation removal, it's good idea to - * 'convert' \r or \r\n into \n (by replacing or skipping first - * char): this may allow reusing the buffer. - * But note that conversion MUST be enabled -- this is toggled - * by code that includes internal entities, to prevent replacement - * of CRs from int. general entities, as applicable. - */ - do { - // We'll need at least one char, no matter what: - if (ptr < len && mNormalizeLFs) { - if (c == '\r') { - c = '\n'; - if (mInputBuffer[ptr] == c) { - /* Ok, whatever happens, can 'skip' \r, to - * point to following \n: - */ - ++start; - // But if that's buffer end, can't skip that - if (++ptr >= len) { - break; - } - } else { - mInputBuffer[start] = c; - } - } else if (c != '\n') { - break; - } - markLF(ptr); - if (mCheckIndentation > 0) { - ptr = readIndentation(c, ptr); - if (ptr < 0) { // success! - return true; - } - } - // If we got this far, we skipped a lf, need to read next char - c = mInputBuffer[ptr++]; - } - } while (false); - - // can we figure out indentation? - mWsStatus = ALL_WS_UNKNOWN; - } else { - mWsStatus = ALL_WS_NO; - } - - char[] inputBuf = mInputBuffer; - int inputLen = mInputEnd; - - // Let's first see if we can just share input buffer: - while (true) { - if (c < CHAR_FIRST_PURE_TEXT) { - if (c == '<') { - mInputPtr = --ptr; - mTextBuffer.resetWithShared(inputBuf, start, ptr-start); - return true; - } - if (c < CHAR_SPACE) { - if (c == '\n') { - markLF(ptr); - } else if (c == '\r') { - if (ptr >= inputLen) { // can't peek? - --ptr; - break; - } - if (mNormalizeLFs) { // can we do in-place Mac replacement? - if (inputBuf[ptr] == '\n') { // nope, 2 char lf - --ptr; - break; - } - /* This would otherwise be risky (may modify value - * of a shared entity value), but since DTDs are - * cached/accessed based on properties including - * lf-normalization there's no harm in 'fixing' it - * in place. - */ - inputBuf[ptr-1] = '\n'; // yup - } else { - // No LF normalization... can we just skip it? - if (inputBuf[ptr] == '\n') { - ++ptr; - } - } - markLF(ptr); - } else if (c != '\t') { - // Should consume invalid char, but not include in result - mInputPtr = ptr; - mTextBuffer.resetWithShared(inputBuf, start, ptr-start-1); - /* Let's defer exception, provided we got at least - * one valid character (if not, better throw - * exception right away) - */ - boolean deferErrors = (ptr - start) > 1; - mPendingException = throwInvalidSpace(c, deferErrors); - return true; - } - } else if (c == '&') { - // Let's push it back and break - --ptr; - break; - } else if (c == '>') { - // Let's see if we got ']]>'? - if ((ptr - start) >= 3) { - if (inputBuf[ptr-3] == ']' && inputBuf[ptr-2] == ']') { - /* Let's include ']]' in there, not '>' (since that - * makes it non-wellformed): but need to consume - * that char nonetheless - */ - mInputPtr = ptr; - mTextBuffer.resetWithShared(inputBuf, start, ptr-start-1); - mPendingException = throwWfcException(ErrorConsts.ERR_BRACKET_IN_TEXT, true); - return true; // and we are fully done - } - } - } - } // if (char in lower code range) - - if (ptr >= inputLen) { // end-of-buffer? - break; - } - c = inputBuf[ptr++]; - } - mInputPtr = ptr; - - /* If we end up here, we either ran out of input, or hit something - * which would leave 'holes' in buffer... fine, let's return then; - * we can still update shared buffer copy: would be too early to - * make a copy since caller may not even be interested in the - * stuff. - */ - mTextBuffer.resetWithShared(inputBuf, start, ptr - start); - return false; - } - - /** - * - * @param deferErrors Flag to enable storing an exception to a - * variable, instead of immediately throwing it. If true, will - * just store the exception; if false, will not store, just throw. - * - * @return True if the text segment was completely read ('<' was hit, - * or in non-entity-expanding mode, a non-char entity); false if - * it may still continue - */ - protected final boolean readTextSecondary(int shortestSegment, boolean deferErrors) - throws XMLStreamException - { - /* Output pointers; calls will also ensure that the buffer is - * not shared, AND has room for at least one more char - */ - char[] outBuf = mTextBuffer.getCurrentSegment(); - int outPtr = mTextBuffer.getCurrentSegmentSize(); - int inputPtr = mInputPtr; - char[] inputBuffer = mInputBuffer; - int inputLen = mInputEnd; - - while (true) { - if (inputPtr >= inputLen) { - /* 07-Oct-2005, TSa: Let's not throw an exception for EOF from - * here -- in fragment mode, it shouldn't be thrown, and in - * other modes we might as well first return text, and only - * then throw an exception: no need to do that yet. - */ - mInputPtr = inputPtr; - if (!loadMore()) { - break; - } - inputPtr = mInputPtr; - inputBuffer = mInputBuffer; - inputLen = mInputEnd; - } - char c = inputBuffer[inputPtr++]; - - // Most common case is we don't have special char, thus: - if (c < CHAR_FIRST_PURE_TEXT) { - if (c < CHAR_SPACE) { - if (c == '\n') { - markLF(inputPtr); - } else if (c == '\r') { - mInputPtr = inputPtr; - if (skipCRLF(c)) { // got 2 char LF - if (!mNormalizeLFs) { - // Special handling, to output 2 chars at a time: - outBuf[outPtr++] = c; - if (outPtr >= outBuf.length) { // need more room? - outBuf = mTextBuffer.finishCurrentSegment(); - outPtr = 0; - } - } - // And let's let default output the 2nd char - c = '\n'; - } else if (mNormalizeLFs) { // just \r, but need to convert - c = '\n'; // For Mac text - } - /* note: skipCRLF() may change ptr and len, but since - * it does not close input source, it won't change - * actual buffer object: - */ - //inputBuffer = mInputBuffer; - inputLen = mInputEnd; - inputPtr = mInputPtr; - } else if (c != '\t') { - mTextBuffer.setCurrentLength(outPtr); - mInputPtr = inputPtr; - mPendingException = throwInvalidSpace(c, deferErrors); - break; - } - } else if (c == '<') { // end is nigh! - mInputPtr = inputPtr-1; - break; - } else if (c == '&') { - mInputPtr = inputPtr; - int ch; - if (mCfgReplaceEntities) { // can we expand all entities? - if ((inputLen - inputPtr) >= 3 - && (ch = resolveSimpleEntity(true)) != 0) { - // Ok, it's fine then - } else { - ch = fullyResolveEntity(true); - if (ch == 0) { - // Input buffer changed, nothing to output quite yet: - inputBuffer = mInputBuffer; - inputLen = mInputEnd; - inputPtr = mInputPtr; - continue; - } - // otherwise char is now fine... - } - } else { - /* Nope, can only expand char entities; others need - * to be separately handled. - */ - ch = resolveCharOnlyEntity(true); - if (ch == 0) { // some other entity... - /* can't expand; underlying pointer now points to - * char after ampersand, need to rewind - */ - --mInputPtr; - break; - } - // .. otherwise we got char we needed - } - if (ch <= 0xFFFF) { - c = (char) ch; - } else { - ch -= 0x10000; - // need more room? - if (outPtr >= outBuf.length) { - outBuf = mTextBuffer.finishCurrentSegment(); - outPtr = 0; - } - outBuf[outPtr++] = (char) ((ch >> 10) + 0xD800); - c = (char) ((ch & 0x3FF) + 0xDC00); - } - inputPtr = mInputPtr; - // not quite sure why this is needed... but it is: - inputLen = mInputEnd; - } else if (c == '>') { - // Let's see if we got ']]>'? - /* 21-Apr-2005, TSa: But we can NOT check the output buffer - * as it contains _expanded_ stuff... only input side. - * For now, 98% accuracy has to do, as we may not be able - * to access previous buffer's contents. But at least we - * won't produce false positives from entity expansion - */ - if (inputPtr > 2) { // can we do it here? - // Since mInputPtr has been advanced, -1 refers to '>' - if (inputBuffer[inputPtr-3] == ']' - && inputBuffer[inputPtr-2] == ']') { - mInputPtr = inputPtr; - /* We have already added ']]' into output buffer... - * should be ok, since only with '>' does it become - * non-wellformed. - */ - mTextBuffer.setCurrentLength(outPtr); - mPendingException = throwWfcException(ErrorConsts.ERR_BRACKET_IN_TEXT, deferErrors); - break; - } - } else { - /* 21-Apr-2005, TSa: No good way to verify it, - * at this point. Should come back and think of how - * to properly handle this (rare) possibility. - */ - ; - } - } - } - // Ok, let's add char to output: - outBuf[outPtr++] = c; - - // Need more room? - if (outPtr >= outBuf.length) { - TextBuffer tb = mTextBuffer; - // Perhaps we have now enough to return? - tb.setCurrentLength(outBuf.length); - if (tb.size() >= shortestSegment) { - mInputPtr = inputPtr; - return false; - } - // If not, need more buffer space: - outBuf = tb.finishCurrentSegment(); - outPtr = 0; - } - } - - mTextBuffer.setCurrentLength(outPtr); - return true; - } - - /** - * Method called to try to parse and canonicalize white space that - * has a good chance of being white space with somewhat regular - * structure; specifically, something that looks like typical - * indentation. - *

- * Note: Caller guarantees that there will be at least 2 characters - * available in the input buffer. And method has to ensure that if - * it does not find a match, it will return pointer value such - * that there is at least one valid character remaining. - * - * @return -1, if the content was determined to be canonicalizable - * (indentation) white space; and thus fully parsed. Otherwise - * pointer (value to set to mInputPtr) to the next character - * to process (not processed by this method) - */ - private final int readIndentation(char c, int ptr) - throws XMLStreamException - { - /* We need to verify that: - * (a) we can read enough contiguous data to do determination - * (b) sequence is a linefeed, with either zero or more following - * spaces, or zero or more tabs; and followed by non-directive - * tag (start/end tag) - * and if so, we can use a canonical shared representation of - * this even. - */ - final int inputLen = mInputEnd; - final char[] inputBuf = mInputBuffer; - int start = ptr-1; - final char lf = c; - - // Note: caller guarantees at least one more char in the input buffer - ws_loop: - do { // dummy loop to allow for break (which indicates failure) - c = inputBuf[ptr++]; - if (c == ' ' || c == '\t') { // indentation? - // Need to limit to maximum - int lastIndCharPos = (c == ' ') ? TextBuffer.MAX_INDENT_SPACES : TextBuffer.MAX_INDENT_TABS; - lastIndCharPos += ptr; - if (lastIndCharPos > inputLen) { - lastIndCharPos = inputLen; - } - - inner_loop: - while (true) { - if (ptr >= lastIndCharPos) { // overflow; let's backtrack - --ptr; - break ws_loop; - } - char d = inputBuf[ptr++]; - if (d != c) { - if (d == '<') { // yup, got it! - break inner_loop; - } - --ptr; // caller needs to reprocess it - break ws_loop; // nope, blew it - } - } - // This means we had success case; let's fall through - } else if (c != '<') { // nope, can not be - --ptr; // simpler if we just push it back; needs to be processed later on - break ws_loop; - } - - // Ok; we got '<'... just need any other char than '!'... - if (ptr < inputLen && inputBuf[ptr] != '!') { - // Voila! - mInputPtr = --ptr; // need to push back that '<' too - mTextBuffer.resetWithIndentation(ptr - start - 1, c); - // One more thing: had a positive match, need to note it - if (mCheckIndentation < INDENT_CHECK_MAX) { - mCheckIndentation += INDENT_CHECK_START; - } - mWsStatus = ALL_WS_YES; - return -1; - } - // Nope: need to push '<' back, then - --ptr; - } while (false); - - // Ok, nope... caller can/need to take care of it: - /* Also, we may need to subtract indentation check count to possibly - * disable this check if it doesn't seem to work. - */ - --mCheckIndentation; - /* Also; if lf we got was \r, need to convert it now (this - * method only gets called in lf converting mode) - * (and yes, it is safe to modify input buffer at this point; - * see calling method for details) - */ - if (lf == '\r') { - inputBuf[start] = '\n'; - } - return ptr; - } - - /** - * Reading whitespace should be very similar to reading normal text; - * although couple of simplifications can be made. Further, since this - * method is very unlikely to be of much performance concern, some - * optimizations are left out, where it simplifies code. - * - * @param c First white space characters; known to contain white space - * at this point - * @param prologWS If true, is reading white space outside XML tree, - * and as such can get EOF. If false, should not get EOF, nor be - * followed by any other char than < - * - * @return True if the whole white space segment was read; false if - * something prevented that (end of buffer, replaceable 2-char lf) - */ - private final boolean readSpacePrimary(char c, boolean prologWS) - throws XMLStreamException - { - int ptr = mInputPtr; - char[] inputBuf = mInputBuffer; - int inputLen = mInputEnd; - int start = ptr-1; - - // Let's first see if we can just share input buffer: - while (true) { - /* 30-Aug-2006, TSa: Let's not check for validity errors yet, - * even if we could detect problems at this point. - * This because it's not always - * an error (in dtd-aware, non-validating mode); but also since - * that way we can first return all space we got, and only - * indicate error when next token is to be accessed. - */ - if (c > CHAR_SPACE) { // End of whitespace - mInputPtr = --ptr; - mTextBuffer.resetWithShared(mInputBuffer, start, ptr-start); - return true; - } - - if (c == '\n') { - markLF(ptr); - } else if (c == '\r') { - if (ptr >= mInputEnd) { // can't peek? - --ptr; - break; - } - if (mNormalizeLFs) { // can we do in-place Mac replacement? - if (inputBuf[ptr] == '\n') { // nope, 2 char lf - --ptr; - break; - } - inputBuf[ptr-1] = '\n'; // yup - } else { - // No LF normalization... can we just skip it? - if (inputBuf[ptr] == '\n') { - ++ptr; - } - } - markLF(ptr); - } else if (c != CHAR_SPACE && c != '\t') { - throwInvalidSpace(c); - } - if (ptr >= inputLen) { // end-of-buffer? - break; - } - c = inputBuf[ptr++]; - } - - mInputPtr = ptr; - - /* Ok, couldn't read it completely, let's just return whatever - * we did get as shared data - */ - mTextBuffer.resetWithShared(inputBuf, start, ptr - start); - return false; - } - - /** - * This is very similar to readSecondaryText(); called when we need - * to read in rest of (ignorable) white space segment. - * - * @param prologWS True if the ignorable white space is within prolog - * (or epilog); false if it's within xml tree. - */ - private void readSpaceSecondary(boolean prologWS) - throws XMLStreamException - { - /* Let's not bother optimizing input. However, we can easily optimize - * output, since it's easy to do, yet has more effect on performance - * than localizing input variables. - */ - char[] outBuf = mTextBuffer.getCurrentSegment(); - int outPtr = mTextBuffer.getCurrentSegmentSize(); - - while (true) { - if (mInputPtr >= mInputEnd) { - /* 07-Oct-2005, TSa: Let's not throw an exception yet -- - * can return SPACE, and let exception be thrown - * when trying to fetch next event. - */ - if (!loadMore()) { - break; - } - } - char c = mInputBuffer[mInputPtr]; - if (c > CHAR_SPACE) { // end of WS? - break; - } - ++mInputPtr; - if (c == '\n') { - markLF(); - } else if (c == '\r') { - if (skipCRLF(c)) { - if (!mNormalizeLFs) { - // Special handling, to output 2 chars at a time: - outBuf[outPtr++] = c; - if (outPtr >= outBuf.length) { // need more room? - outBuf = mTextBuffer.finishCurrentSegment(); - outPtr = 0; - } - } - c = '\n'; - } else if (mNormalizeLFs) { - c = '\n'; // For Mac text - } - } else if (c != CHAR_SPACE && c != '\t') { - throwInvalidSpace(c); - } - - // Ok, let's add char to output: - outBuf[outPtr++] = c; - - // Need more room? - if (outPtr >= outBuf.length) { - outBuf = mTextBuffer.finishCurrentSegment(); - outPtr = 0; - } - } - mTextBuffer.setCurrentLength(outPtr); - } - - /** - * Method called to read the contents of the current CHARACTERS - * event, and write all contents using the specified Writer. - * - * @param w Writer to use for writing out textual content parsed - * - * @return Total number of characters written using the writer - */ - private int readAndWriteText(Writer w) - throws IOException, XMLStreamException - { - mTokenState = TOKEN_FULL_SINGLE; // we'll read it all - - /* We should be able to mostly just use the input buffer at this - * point; exceptions being two-char linefeeds (when converting - * to single ones) and entities (which likewise can expand or - * shrink), both of which require flushing and/or single byte - * output. - */ - int start = mInputPtr; - int count = 0; - - main_loop: - while (true) { - char c; - // Reached the end of buffer? Need to flush, then - if (mInputPtr >= mInputEnd) { - int len = mInputPtr - start; - if (len > 0) { - w.write(mInputBuffer, start, len); - count += len; - } - c = getNextChar(SUFFIX_IN_TEXT); - start = mInputPtr-1; // needs to be prior to char we got - } else { - c = mInputBuffer[mInputPtr++]; - } - // Most common case is we don't have a special char, thus: - if (c < CHAR_FIRST_PURE_TEXT) { - if (c < CHAR_SPACE) { - if (c == '\n') { - markLF(); - } else if (c == '\r') { - char d; - if (mInputPtr >= mInputEnd) { - /* If we can't peek easily, let's flush past stuff - * and load more... (have to flush, since new read - * will overwrite inbut buffers) - */ - int len = mInputPtr - start; - if (len > 0) { - w.write(mInputBuffer, start, len); - count += len; - } - d = getNextChar(SUFFIX_IN_TEXT); - start = mInputPtr; // to mark 'no past content' - } else { - d = mInputBuffer[mInputPtr++]; - } - if (d == '\n') { - if (mNormalizeLFs) { - /* Let's flush content prior to 2-char LF, and - * start the new segment on the second char... - * this way, no mods are needed for the buffer, - * AND it'll also work on split 2-char lf! - */ - int len = mInputPtr - 2 - start; - if (len > 0) { - w.write(mInputBuffer, start, len); - count += len; - } - start = mInputPtr-1; // so '\n' is the first char - } else { - ; // otherwise it's good as is - } - } else { // not 2-char... need to replace? - --mInputPtr; - if (mNormalizeLFs) { - mInputBuffer[mInputPtr-1] = '\n'; - } - } - markLF(); - } else if (c != '\t') { - throwInvalidSpace(c); - } - } else if (c == '<') { // end is nigh! - break main_loop; - } else if (c == '&') { - /* Have to flush all stuff, since entities pretty much - * force it; input buffer won't be contiguous - */ - int len = mInputPtr - 1 - start; // -1 to remove ampersand - if (len > 0) { - w.write(mInputBuffer, start, len); - count += len; - } - int ch; - if (mCfgReplaceEntities) { // can we expand all entities? - if ((mInputEnd - mInputPtr) < 3 - || (ch = resolveSimpleEntity(true)) == 0) { - ch = fullyResolveEntity(true); - } - } else { - ch = resolveCharOnlyEntity(true); - if (ch == 0) { // some other entity... - /* can't expand, so, let's just bail out... but - * let's also ensure no text is added twice, as - * all prev text was just flushed, but resolve - * may have moved input buffer around. - */ - start = mInputPtr; - break main_loop; - } - } - if (ch != 0) { - if (ch <= 0xFFFF) { - c = (char) ch; - } else { - ch -= 0x10000; - w.write((char) ((ch >> 10) + 0xD800)); - c = (char) ((ch & 0x3FF) + 0xDC00); - } - w.write(c); - ++count; - } - start = mInputPtr; - } else if (c == '>') { // did we get ']]>'? - /* 21-Apr-2005, TSa: But we can NOT check the output buffer - * (see comments in readTextSecondary() for details) - */ - if (mInputPtr >= 2) { // can we do it here? - if (mInputBuffer[mInputPtr-2] == ']' - && mInputBuffer[mInputPtr-1] == ']') { - // Anything to flush? - int len = mInputPtr - start; - if (len > 0) { - w.write(mInputBuffer, start, len); - } - throwParseError(ErrorConsts.ERR_BRACKET_IN_TEXT); - } - } else { - ; // !!! TBI: how to check past boundary? - } - } else if (c == CHAR_NULL) { - throwNullChar(); - } - } - } // while (true) - - /* Need to push back '<' or '&', whichever caused us to - * get out... - */ - --mInputPtr; - - // Anything left to flush? - int len = mInputPtr - start; - if (len > 0) { - w.write(mInputBuffer, start, len); - count += len; - } - return count; - } - - /** - * Method called to read the contents of the current (possibly partially - * read) CDATA - * event, and write all contents using the specified Writer. - * - * @param w Writer to use for writing out textual content parsed - * - * @return Total number of characters written using the writer for - * the current CDATA event - */ - private int readAndWriteCData(Writer w) - throws IOException, XMLStreamException - { - mTokenState = TOKEN_FULL_SINGLE; // we'll read it all - - /* Ok; here we can basically have 2 modes; first the big loop to - * gather all data up until a ']'; and then another loop to see - * if ']' is part of ']]>', and after this if no end marker found, - * go back to the first part. - */ - char c = (mInputPtr < mInputEnd) ? - mInputBuffer[mInputPtr++] : getNextChar(SUFFIX_IN_CDATA); - int count = 0; - - main_loop: - while (true) { - int start = mInputPtr-1; - - quick_loop: - while (true) { - if (c > CHAR_CR_LF_OR_NULL) { - if (c == ']') { - break quick_loop; - } - } else { - if (c < CHAR_SPACE) { - if (c == '\n') { - markLF(); - } else if (c == '\r') { - char d; - if (mInputPtr >= mInputEnd) { - /* If we can't peek easily, let's flush past stuff - * and load more... (have to flush, since new read - * will overwrite inbut buffers) - */ - int len = mInputPtr - start; - if (len > 0) { - w.write(mInputBuffer, start, len); - count += len; - } - d = getNextChar(SUFFIX_IN_CDATA); - start = mInputPtr; // to mark 'no past content' - } else { - d = mInputBuffer[mInputPtr++]; - } - if (d == '\n') { - if (mNormalizeLFs) { - /* Let's flush content prior to 2-char LF, and - * start the new segment on the second char... - * this way, no mods are needed for the buffer, - * AND it'll also work on split 2-char lf! - */ - int len = mInputPtr - 2 - start; - if (len > 0) { - w.write(mInputBuffer, start, len); - count += len; - } - start = mInputPtr-1; // so '\n' is the first char - } else { - // otherwise it's good as is - } - } else { // not 2-char... need to replace? - --mInputPtr; - if (mNormalizeLFs) { - mInputBuffer[mInputPtr-1] = '\n'; - } - } - markLF(); - } else if (c != '\t') { - throwInvalidSpace(c); - } - } - } - // Reached the end of buffer? Need to flush, then - if (mInputPtr >= mInputEnd) { - int len = mInputPtr - start; - if (len > 0) { - w.write(mInputBuffer, start, len); - count += len; - } - start = 0; - c = getNextChar(SUFFIX_IN_CDATA); - } else { - c = mInputBuffer[mInputPtr++]; - } - } // while (true) - - // Anything to flush once we hit ']'? - { - /* -1 since the last char in there (a '[') is NOT to be - * output at this point - */ - int len = mInputPtr - start - 1; - if (len > 0) { - w.write(mInputBuffer, start, len); - count += len; - } - } - - /* Ok; we only get this far when we hit a ']'. We got one, - * so let's see if we can find at least one more bracket, - * immediately followed by '>'... - */ - int bracketCount = 0; - do { - ++bracketCount; - c = (mInputPtr < mInputEnd) ? mInputBuffer[mInputPtr++] - : getNextCharFromCurrent(SUFFIX_IN_CDATA); - } while (c == ']'); - - boolean match = (bracketCount >= 2 && c == '>'); - if (match) { - bracketCount -= 2; - } - while (bracketCount > 0) { - --bracketCount; - w.write(']'); - ++count; - } - if (match) { - break main_loop; - } - /* Otherwise we'll just loop; now c is properly set to be - * the next char as well. - */ - } // while (true) - - return count; - } - - /** - * @return Number of characters written to Writer during the call - */ - private int readAndWriteCoalesced(Writer w, boolean wasCData) - throws IOException, XMLStreamException - { - mTokenState = TOKEN_FULL_COALESCED; - int count = 0; - - /* Ok, so what do we have next? CDATA, CHARACTERS, or something - * else? - */ - main_loop: - while (true) { - if (mInputPtr >= mInputEnd) { - if (!loadMore()) { - /* Shouldn't normally happen, but let's just let - * caller deal with it... - */ - break main_loop; - } - } - // Let's peek, ie. not advance it yet - char c = mInputBuffer[mInputPtr]; - if (c == '<') { // CDATA, maybe? - // Need to distinguish " CHAR_SPACE) { - return false; - } - while (true) { - // Linefeed? - if (c == '\n' || c == '\r') { - skipCRLF(c); - } else if (c != CHAR_SPACE && c != '\t') { - throwInvalidSpace(c); - } - if (mInputPtr >= mInputEnd) { - // Let's see if current source has more - if (!loadMoreFromCurrent()) { - return true; - } - } - c = mInputBuffer[mInputPtr]; - if (c > CHAR_SPACE) { // not WS? Need to return - return true; - } - ++mInputPtr; - } - } - - /* - /////////////////////////////////////////////////////////////////////// - // Abstract method implementations - /////////////////////////////////////////////////////////////////////// - */ - - // @Override - protected EntityDecl findEntity(String id, Object arg) - throws XMLStreamException - { - EntityDecl ed = (EntityDecl) mConfig.findCustomInternalEntity(id); - if (ed == null && mGeneralEntities != null) { - ed = (EntityDecl) mGeneralEntities.get(id); - } - /* 05-Mar-2006, TSa: Externally declared entities are illegal - * if we were declared as "standalone='yes'"... - */ - if (mDocStandalone == DOC_STANDALONE_YES) { - if (ed != null && ed.wasDeclaredExternally()) { - throwParseError(ErrorConsts.ERR_WF_ENTITY_EXT_DECLARED, ed.getName(), null); - } - } - return ed; - } - - protected void handleUndeclaredEntity(String id) - throws XMLStreamException - { - throwParseError(((mDocStandalone == DOC_STANDALONE_YES) ? - ErrorConsts.ERR_WF_GE_UNDECLARED_SA : - ErrorConsts.ERR_WF_GE_UNDECLARED), - id, null); - } - - protected void handleIncompleteEntityProblem(WstxInputSource closing) - throws XMLStreamException - { - String top = mElementStack.isEmpty() ? "[ROOT]" : mElementStack.getTopElementDesc(); - throwParseError("Unexpected end of entity expansion for entity &{0}; was expecting a close tag for element <{1}>", - closing.getEntityId(), top); - } - - /* - /////////////////////////////////////////////////////////////////////// - // Internal methods, validation, error handling and reporting - /////////////////////////////////////////////////////////////////////// - */ - - /** - * This problem gets reported if an entity tries to expand to - * a close tag matching start tag that did not came from the same - * entity (but from parent). - */ - protected void handleGreedyEntityProblem(WstxInputSource input) - throws XMLStreamException - { - String top = mElementStack.isEmpty() ? "[ROOT]" : mElementStack.getTopElementDesc(); - throwParseError("Improper GE/element nesting: entity &" - +input.getEntityId()+" contains closing tag for <"+top+">"); - } - - private void throwNotTextual(int type) - { - throw new IllegalStateException("Not a textual event (" - +tokenTypeDesc(mCurrToken)+")"); - } - - private void throwNotTextXxx(int type) - { - throw new IllegalStateException("getTextXxx() methods can not be called on " - +tokenTypeDesc(mCurrToken)); - } - - protected void throwNotTextualOrElem(int type) - { - throw new IllegalStateException(MessageFormat.format(ErrorConsts.ERR_STATE_NOT_ELEM_OR_TEXT, new Object[] { tokenTypeDesc(type) })); - } - - - /** - * Method called when we get an EOF within content tree - */ - protected void throwUnexpectedEOF() - throws WstxException - { - throwUnexpectedEOF("; was expecting a close tag for element <"+mElementStack.getTopElementDesc()+">"); - } - - /** - * Method called to report a problem with - */ - protected XMLStreamException _constructUnexpectedInTyped(int nextToken) - { - if (nextToken == START_ELEMENT) { - return _constructTypeException("Element content can not contain child START_ELEMENT when using Typed Access methods", null); - } - return _constructTypeException("Expected a text token, got "+tokenTypeDesc(nextToken), null); - } - - protected TypedXMLStreamException _constructTypeException(String msg, String lexicalValue) - { - return new TypedXMLStreamException(lexicalValue, msg, getStartLocation()); - } - - /** - * Stub method implemented by validating parsers, to report content - * that's not valid for current element context. Defined at this - * level since some such problems need to be caught at low-level; - * however, details of error reports are not needed here. - */ - protected void reportInvalidContent(int evtType) - throws XMLStreamException - { - // should never happen; sub-class has to override: - throwParseError("Internal error: sub-class should override method"); - } -} diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/sr/CompactNsContext.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/sr/CompactNsContext.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/sr/CompactNsContext.java 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/sr/CompactNsContext.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,250 +0,0 @@ -package com.ctc.wstx.sr; - -import java.io.IOException; -import java.io.Writer; -import java.util.ArrayList; -import java.util.Iterator; - -import javax.xml.XMLConstants; -import javax.xml.stream.Location; -import javax.xml.stream.XMLStreamException; -import javax.xml.stream.XMLStreamWriter; - -import org.codehaus.stax2.ri.EmptyIterator; -import org.codehaus.stax2.ri.SingletonIterator; -// This is unfortunate dependency, but... -import org.codehaus.stax2.ri.evt.NamespaceEventImpl; - -import com.ctc.wstx.util.BaseNsContext; - -/** - * Simple implementation of separate non-transient namespace context - * object. Created for start-element event by transient namespace - * instance updated by stream reader. - *

- * Note about implementation: Location information is only needed (and - * only needs to passed) if access is made via extended interface; one - * that can return information about actual Namespace event objects. - */ -public final class CompactNsContext - extends BaseNsContext -{ - final Location mLocation; - - /** - * Array that contains 2 Strings for each declared default namespace - * (including default namespace declarations); first is the prefix, - * second URI. - */ - final String[] mNamespaces; - - /** - * Number of entries in {@link #mNamespaces} (which is twice the number - * of bindings) - */ - final int mNsLength; - - /** - * Index of first namespace pair in mNamespaces that is declared - * in scope of element for which this context was constructed. May be - * equal to {@link #mNsLength} (which indicates there are no local - * bindings). - */ - final int mFirstLocalNs; - - /** - * List only needed to support List accessor from start-element event; - * created lazily if/as needed. - */ - transient ArrayList mNsList; - - public CompactNsContext(Location loc, String defaultNsURI, - String[] namespaces, int nsLen, - int firstLocal) - { - mLocation = loc; - mNamespaces = namespaces; - mNsLength = nsLen; - mFirstLocalNs = firstLocal; - } - - /** - * @param prefix Non-null, non-empty prefix (base-class verifies these - * constraints) to find namespace URI for. - */ - public String doGetNamespaceURI(String prefix) - { - /* Let's search from beginning towards end; this way we'll first - * find the innermost (or, in case of same-level declaration, last) - * declaration for prefix. - */ - // (note: default namespace will be there too) - String[] ns = mNamespaces; - if (prefix.length() == 0) { - for (int i = mNsLength-2; i >= 0; i -= 2) { - if (ns[i] == null) { - return ns[i+1]; - } - } - return null; // default ns not bound - } - for (int i = mNsLength-2; i >= 0; i -= 2) { - if (prefix.equals(ns[i])) { - return ns[i+1]; - } - } - return null; - } - - public String doGetPrefix(String nsURI) - { - // Note: base class checks for 'known' problems and prefixes: - - String[] ns = mNamespaces; - int len = mNsLength; - - main_loop: - for (int i = len-1; i > 0; i -= 2) { - if (nsURI.equals(ns[i])) { - /* 29-Sep-2004, TSa: Actually, need to make sure that this - * declaration is not masked by a later declaration. - * This happens when same prefix is declared on a later - * entry (ie. for child element) - */ - String prefix = ns[i-1]; - for (int j = i+1; j < len; j += 2) { - // Prefixes are interned, can do straight equality check - if (ns[j] == prefix) { - continue main_loop; // was masked! - } - } - String uri = ns[i-1]; - /* 19-Mar-2006, TSa: Empty namespaces are represented by - * null prefixes; but need to be represented as empty - * strings (to distinguish from unbound URIs). - */ - return (uri == null) ? "" : uri; - } - } - return null; - } - - public Iterator doGetPrefixes(String nsURI) - { - // Note: base class checks for 'known' problems and prefixes: - - String[] ns = mNamespaces; - int len = mNsLength; - String first = null; - ArrayList all = null; - - main_loop: - for (int i = len-1; i > 0; i -= 2) { - String currNS = ns[i]; - if (currNS == nsURI || currNS.equals(nsURI)) { - /* 29-Sep-2004, TSa: Need to ensure it's not masked by - * a later ns declaration in a child element. - */ - String prefix = ns[i-1]; - for (int j = i+1; j < len; j += 2) { - // Prefixes are interned, can do straight equality check - if (ns[j] == prefix) { - continue main_loop; // was masked, need to ignore - } - } - /* 19-Mar-2006, TSa: Empty namespaces are represented by - * null prefixes; but need to be represented as empty - * strings (to distinguish from unbound URIs). - */ - if (prefix == null) { - prefix = ""; - } - if (first == null) { - first = prefix; - } else { - if (all == null) { - all = new ArrayList(); - all.add(first); - } - all.add(prefix); - } - } - } - if (all != null) { - return all.iterator(); - } - if (first != null) { - return new SingletonIterator(first); - } - return EmptyIterator.getInstance(); - } - - /* - /////////////////////////////////////////////////////// - // Extended API, needed by Wstx classes - /////////////////////////////////////////////////////// - */ - - public Iterator getNamespaces() - { - if (mNsList == null) { - int firstLocal = mFirstLocalNs; - int len = mNsLength - firstLocal; - if (len == 0) { // can this happen? - return EmptyIterator.getInstance(); - } - if (len == 2) { // only one NS - return new SingletonIterator(NamespaceEventImpl.constructNamespace - (mLocation, - mNamespaces[firstLocal], - mNamespaces[firstLocal+1])); - } - ArrayList l = new ArrayList(len >> 1); - String[] ns = mNamespaces; - for (len = mNsLength; firstLocal < len; - firstLocal += 2) { - l.add(NamespaceEventImpl.constructNamespace(mLocation, ns[firstLocal], - ns[firstLocal+1])); - } - mNsList = l; - } - return mNsList.iterator(); - } - - /** - * Method called by {@link com.ctc.wstx.evt.CompactStartElement} - * to output all 'local' namespace declarations active in current - * namespace scope, if any. Local means that declaration was done in - * scope of current element, not in a parent element. - */ - public void outputNamespaceDeclarations(Writer w) throws IOException - { - String[] ns = mNamespaces; - for (int i = mFirstLocalNs, len = mNsLength; i < len; i += 2) { - w.write(' '); - w.write(XMLConstants.XMLNS_ATTRIBUTE); - String prefix = ns[i]; - if (prefix != null && prefix.length() > 0) { - w.write(':'); - w.write(prefix); - } - w.write("=\""); - w.write(ns[i+1]); - w.write('"'); - } - } - - public void outputNamespaceDeclarations(XMLStreamWriter w) throws XMLStreamException - { - String[] ns = mNamespaces; - for (int i = mFirstLocalNs, len = mNsLength; i < len; i += 2) { - String nsURI = ns[i+1]; - String prefix = ns[i]; - if (prefix != null && prefix.length() > 0) { - w.writeNamespace(prefix, nsURI); - } else { - w.writeDefaultNamespace(nsURI); - } - } - } -} diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/sr/ElemAttrs.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/sr/ElemAttrs.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/sr/ElemAttrs.java 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/sr/ElemAttrs.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,228 +0,0 @@ -package com.ctc.wstx.sr; - -import javax.xml.namespace.QName; - -/** - * Container class that is constructed with enough raw attribute information, - * to be able to lazily construct full attribute objects, to be accessed - * via Iterator, or fully-qualified name. - *

- * Implementation note: code for using Map-like structure is unfortunately - * cut'n pasted from {@link AttributeCollector}. Problem - * with refactoring is that it's 90% the same code, but not 100%. - *

- * Although instances of this class are constructed by stream readers, - * it is actually used by element event objects. - */ -public final class ElemAttrs -{ - //private final static int OFFSET_LOCAL_NAME = 0; - private final static int OFFSET_NS_URI = 1; - //private final static int OFFSET_NS_PREFIX = 2; - //private final static int OFFSET_VALUE = 3; - - /** - * Array that contains 4 Strings for each attribute; - * localName, URI, prefix, value. Can be used to lazily construct - * structure(s) needed to return Iterator for accessing all - * attributes. - */ - private final String[] mRawAttrs; - - /** - * Raw offset (in mRawAttrs) of the first attribute - * instance that was created through default value expansion. - */ - private final int mDefaultOffset; - - /* - ////////////////////////////////////////////////////////////// - // Information that defines "Map-like" data structure used for - // quick access to attribute values by fully-qualified name - // (only used for "long" lists) - ////////////////////////////////////////////////////////////// - */ - - // // // For full explanation, see source for AttributeCollector - - private final int[] mAttrMap; - - private final int mAttrHashSize; - - private final int mAttrSpillEnd; - - /** - * Method called to create "short" attribute list; list that has - * only few entries, and can thus be searched for attributes using - * linear search, without using any kind of Map structure. - *

- * Currently the limit is 4 attributes; 1, 2 or 3 attribute lists are - * considered short, 4 or more 'long'. - * - * @param rawAttrs Array that contains 4 Strings for each attribute; - * localName, URI, prefix, value. Can be used to lazily construct - * structure(s) needed to return Iterator for accessing all - * attributes. - * @param defOffset Index of the first default attribute, if any; - * number of all attributes if none - */ - public ElemAttrs(String[] rawAttrs, int defOffset) - { - mRawAttrs = rawAttrs; - mAttrMap = null; - mAttrHashSize = 0; - mAttrSpillEnd = 0; - mDefaultOffset = (defOffset << 2); - } - - /** - * Method called to create "long" attribute list; list that has - * a few entries, and efficient access by fully-qualified name should - * not be done by linear search. - * - * @param rawAttrs Array that contains 4 Strings for each attribute; - * localName, URI, prefix, value. Can be used to lazily construct - * structure(s) needed to return Iterator for accessing all - * attributes. - */ - public ElemAttrs(String[] rawAttrs, int defOffset, - int[] attrMap, int hashSize, int spillEnd) - { - mRawAttrs = rawAttrs; - mDefaultOffset = (defOffset << 2); - mAttrMap = attrMap; - mAttrHashSize = hashSize; - mAttrSpillEnd = spillEnd; - } - - /* - //////////////////////////////////////////////////// - // Public API - //////////////////////////////////////////////////// - */ - - public String[] getRawAttrs() { - return mRawAttrs; - } - - public int findIndex(QName name) - { - // Do we have a Map to do lookup against? - if (mAttrMap != null) { // yup - return findMapIndex(name.getNamespaceURI(), name.getLocalPart()); - } - - // Nope, linear search: - String ln = name.getLocalPart(); - String uri = name.getNamespaceURI(); - boolean defaultNs = (uri == null || uri.length() == 0); - String[] raw = mRawAttrs; - - for (int i = 0, len = raw.length; i < len; i += 4) { - if (!ln.equals(raw[i])) { - continue; - } - String thisUri = raw[i+OFFSET_NS_URI]; - if (defaultNs) { - if (thisUri == null || thisUri.length() == 0) { - return i; - } - } else { // non-default NS - if (thisUri != null && - (thisUri == uri || thisUri.equals(uri))) { - return i; - } - } - } - return -1; - } - - public int getFirstDefaultOffset() { - return mDefaultOffset; - } - - public boolean isDefault(int ix) { - return (ix >= mDefaultOffset); - } - - /* - //////////////////////////////////////////////////// - // Internal methods - //////////////////////////////////////////////////// - */ - - /** - *

- * Note: this method is very similar to - * {@link com.ctc.wstx.sr.AttributeCollector#getAttrValue}; basically - * most of it was cut'n pasted. Would be nice to refactor, but it's - * bit hard to do that since data structures are not 100% identical - * (mostly attribute storage, not Map structure itself). - */ - private final int findMapIndex(String nsURI, String localName) - { - // Primary hit? - int hash = localName.hashCode(); - if (nsURI == null) { - nsURI = ""; // just to simplify comparisons -- array contains nulls - } else if (nsURI.length() > 0) { - hash ^= nsURI.hashCode(); - } - int ix = mAttrMap[hash & (mAttrHashSize - 1)]; - if (ix == 0) { // nothing in here; no spills either - return -1; - } - // Index is "one off" (since 0 indicates 'null), 4 Strings per attr - ix = (ix - 1) << 2; - - // Is primary candidate match? - String[] raw = mRawAttrs; - String thisName = raw[ix]; - /* Equality first, since although equals() checks that too, it's - * very likely to match (if interning Strings), and we can save - * a method call. - */ - if (thisName == localName || thisName.equals(localName)) { - String thisURI = raw[ix+OFFSET_NS_URI]; - if (thisURI == nsURI) { - return ix; - } - if (thisURI == null) { - if (nsURI.length() == 0) { - return ix; - } - } else if (thisURI.equals(nsURI)) { - return ix; - } - } - - /* Nope, need to traverse spill list, which has 2 entries for - * each spilled attribute id; first for hash value, second index. - */ - for (int i = mAttrHashSize, len = mAttrSpillEnd; i < len; i += 2) { - if (mAttrMap[i] != hash) { - continue; - } - /* Note: spill indexes are not off-by-one, since there's no need - * to mask 0 - */ - ix = mAttrMap[i+1] << 2; // ... but there are 4 Strings for each attr - thisName = raw[ix]; - if (thisName == localName || thisName.equals(localName)) { - String thisURI = raw[ix+1]; - if (thisURI == nsURI) { - return ix; - } - if (thisURI == null) { - if (nsURI.length() == 0) { - return ix; - } - } else if (thisURI.equals(nsURI)) { - return ix; - } - } - } - - return -1; - } -} diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/sr/ElemCallback.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/sr/ElemCallback.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/sr/ElemCallback.java 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/sr/ElemCallback.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,18 +0,0 @@ -package com.ctc.wstx.sr; - -import javax.xml.stream.Location; -import javax.xml.namespace.QName; - -import com.ctc.wstx.util.BaseNsContext; - -/** - * Abstract base class that defines set of simple callbacks to be - * called by the stream reader, passing information about element - * that the stream currently points to, if any. - */ -public abstract class ElemCallback -{ - public abstract Object withStartElement(Location loc, QName name, - BaseNsContext nsCtxt, ElemAttrs attrs, - boolean wasEmpty); -} diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/sr/Element.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/sr/Element.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/sr/Element.java 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/sr/Element.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,93 +0,0 @@ -/* Woodstox XML processor - * - * Copyright (c) 2004- Tatu Saloranta, tatu.saloranta@iki.fi - * - * Licensed under the License specified in file LICENSE, included with - * the source code. - * You may not use this file except in compliance with the License. - * - * 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 com.ctc.wstx.sr; - -/** - * Container for information collected regarding a single - * (start) element instance. - *

- * This class is not exposed outside of the package and is considered - * part of internal implementation. - * - * @since 4.1 - */ -final class Element -{ - // // // Element name - - protected String mLocalName; - - /** - * Prefix this element has, if any; null if none - */ - protected String mPrefix; - - /** - * Namespace this element is in - */ - protected String mNamespaceURI; - - /** - * Default namespace for this element. - */ - protected String mDefaultNsURI; - - // // // Namespace support - - /** - * Offset within namespace array, maintained by - * {@link InputElementStack} that owns this element. - */ - protected int mNsOffset; - - // // // Back links to parent element(s) - - /** - * Parent element, if any; null for root - */ - protected Element mParent; - - /* - ///////////////////////////////////////////////////////// - // Life-cycle - ///////////////////////////////////////////////////////// - */ - - public Element(Element parent, int nsOffset, String prefix, String ln) - { - mParent = parent; - mNsOffset = nsOffset; - mPrefix = prefix; - mLocalName = ln; - } - - public void reset(Element parent, int nsOffset, String prefix, String ln) - { - mParent = parent; - mNsOffset = nsOffset; - mPrefix = prefix; - mLocalName = ln; - } - - /** - * Method called to temporarily "store" this Element for later reuse. - */ - public void relink(Element next) - { - mParent = next; - } -} - diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/sr/InputElementStack.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/sr/InputElementStack.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/sr/InputElementStack.java 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/sr/InputElementStack.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,1049 +0,0 @@ -/* Woodstox XML processor - * - * Copyright (c) 2004- Tatu Saloranta, tatu.saloranta@iki.fi - * - * Licensed under the License specified in file LICENSE, included with - * the source code. - * You may not use this file except in compliance with the License. - * - * 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 com.ctc.wstx.sr; - -import java.util.*; - -import javax.xml.XMLConstants; -import javax.xml.namespace.NamespaceContext; -import javax.xml.namespace.QName; -import javax.xml.stream.Location; -import javax.xml.stream.XMLStreamException; - -import org.codehaus.stax2.AttributeInfo; -import org.codehaus.stax2.ri.EmptyIterator; -import org.codehaus.stax2.ri.SingletonIterator; -import org.codehaus.stax2.validation.ValidationContext; -import org.codehaus.stax2.validation.XMLValidator; -import org.codehaus.stax2.validation.XMLValidationProblem; -import org.codehaus.stax2.validation.XMLValidationSchema; -import org.codehaus.stax2.validation.ValidatorPair; - -import com.ctc.wstx.api.ReaderConfig; -import com.ctc.wstx.api.WstxInputProperties; -import com.ctc.wstx.cfg.ErrorConsts; -import com.ctc.wstx.cfg.XmlConsts; -import com.ctc.wstx.compat.QNameCreator; -import com.ctc.wstx.dtd.DTDValidatorBase; // unfortunate dependency -import com.ctc.wstx.util.*; - -/** - * Shared base class that defines API stream reader uses to communicate - * with the element stack implementation, independent of whether it's - * operating in namespace-aware or non-namespace modes. - * Element stack class is used for storing nesting information about open - * elements, and for namespace-aware mode, also information about - * namespaces active (including default namespace), during parsing of - * XML input. - *

- * This class also implements {@link NamespaceContext}, since it has all - * the information necessary, so parser can just return element stack - * instance as necesary. - */ -public final class InputElementStack - implements AttributeInfo, NamespaceContext, ValidationContext -{ - final static int ID_ATTR_NONE = -1; - - /* - ////////////////////////////////////////////////// - // Configuration - ////////////////////////////////////////////////// - */ - - protected final boolean mNsAware; - - protected final AttributeCollector mAttrCollector; - - protected final ReaderConfig mConfig; - - protected InputProblemReporter mReporter = null; - - /** - * Object that will need to be consulted about namespace bindings, - * since it has some knowledge about default namespace declarations - * (has default attribute value expansion). - */ - protected NsDefaultProvider mNsDefaultProvider; - - /* - ////////////////////////////////////////////////// - // Element, namespace information - ////////////////////////////////////////////////// - */ - - protected int mDepth = 0; - - /** - * Vector that contains all currently active namespaces; one String for - * prefix, another for matching URI. Does also include default name - * spaces (at most one per level). - */ - protected final StringVector mNamespaces = new StringVector(64); - - /** - * Currently open element, if any; null outside root element. - */ - protected Element mCurrElement; - - protected boolean mMayHaveNsDefaults = false; - - /* - ////////////////////////////////////////////////// - // Element validation (optional), attribute typing - ////////////////////////////////////////////////// - */ - - /** - * Optional validator object that will get called if set, - * and that can validate xml content. Note that it is possible - * that this is set to a proxy object that calls multiple - * validators in sequence. - */ - protected XMLValidator mValidator = null; - - /** - * Index of the attribute with type of ID, if known (most likely - * due to Xml:id support); -1 if not available, or no ID attribute - * for current element. - */ - protected int mIdAttrIndex = ID_ATTR_NONE; - - /* - ////////////////////////////////////////////////// - // Simple 1-slot QName cache; used for improving - // efficiency of code that uses QNames extensively - // (like StAX Event API implementation) - ////////////////////////////////////////////////// - */ - - protected String mLastLocalName = null; - protected String mLastPrefix = null; - protected String mLastNsURI = null; - - protected QName mLastName = null; - - /* - ///////////////////////////////////////////////////// - // Other simple caching - ///////////////////////////////////////////////////// - */ - - // Non-transient NamespaceContext caching; mostly for event API - - /** - * Last potentially shareable NamespaceContext created by - * this stack. This reference is cleared each time bindings - * change (either due to a start element with new bindings, or due - * to the matching end element that closes scope of such binding(s)). - */ - protected BaseNsContext mLastNsContext = null; - - // Chain of reusable Element instances - - protected Element mFreeElement = null; - - /* - ////////////////////////////////////////////////// - // Life-cycle (create, update state) - ////////////////////////////////////////////////// - */ - - protected InputElementStack(ReaderConfig cfg, boolean nsAware) - { - mConfig = cfg; - mNsAware = nsAware; - mAttrCollector = new AttributeCollector(cfg, nsAware); - } - - protected void connectReporter(InputProblemReporter rep) - { - mReporter = rep; - } - - protected XMLValidator addValidator(XMLValidator vld) - { - if (mValidator == null) { - mValidator = vld; - } else { - mValidator = new ValidatorPair(mValidator, vld); - } - return vld; - } - - /** - * Method called to connect the automatically handled DTD validator - * (one detected from DOCTYPE, loaded and completely handled by - * the stream reader without application calling validation methods). - * Handled separately, since its behaviour is potentially different - * from that of explicitly added validators. - */ - protected void setAutomaticDTDValidator(XMLValidator validator, NsDefaultProvider nsDefs) - { - mNsDefaultProvider = nsDefs; - addValidator(validator); - } - - /* - ////////////////////////////////////////////////// - // Start/stop validation - ////////////////////////////////////////////////// - */ - - public XMLValidator validateAgainst(XMLValidationSchema schema) - throws XMLStreamException - { - /* Should we first check if we maybe already have a validator - * for the schema? - */ - return addValidator(schema.createValidator(this)); - } - - - - public XMLValidator stopValidatingAgainst(XMLValidationSchema schema) - throws XMLStreamException - { - XMLValidator[] results = new XMLValidator[2]; - if (ValidatorPair.removeValidator(mValidator, schema, results)) { // found - XMLValidator found = results[0]; - mValidator = results[1]; - found.validationCompleted(false); - return found; - } - return null; - } - - public XMLValidator stopValidatingAgainst(XMLValidator validator) - throws XMLStreamException - { - XMLValidator[] results = new XMLValidator[2]; - if (ValidatorPair.removeValidator(mValidator, validator, results)) { // found - XMLValidator found = results[0]; - mValidator = results[1]; - found.validationCompleted(false); - return found; - } - return null; - } - - /* - ////////////////////////////////////////////////// - // Accessors: - ////////////////////////////////////////////////// - */ - - /** - * This is a method called by the reader to ensure that we have at - * least one 'real' validator. This is only needed to ensure that - * validation problems that the reader can detect (illegal textual - * content) can be reported as validity errors. Since the validator - * API does not have a good way to cleanly deal with such a possibility, - * the check is rather fragile, but should work for now: essentially - * we need at least one validator object that either is not a sub-class - * of DTDValidatorBase or returns true for - * reallyValidating. - *

- * !!! TODO: remove need for this method (and method itself) with - * Woodstox 4.0, by adding necessary support in Stax2 XMLValidator - * interface. - */ - protected boolean reallyValidating() - { - if (mValidator == null) { // no validators, no validation - // (although, should never get called if no validators) - return false; - } - if (!(mValidator instanceof DTDValidatorBase)) { - // note: happens for validator pair, for one - return true; - } - return ((DTDValidatorBase) mValidator).reallyValidating(); - } - - /** - * Method called by {@link BasicStreamReader}, to retrieve the - * attribute collector it needs for some direct access. - */ - public final AttributeCollector getAttrCollector() { - return mAttrCollector; - } - - /** - * Method called to construct a non-transient NamespaceContext instance; - * generally needed when creating events to return from event-based - * iterators. - */ - public BaseNsContext createNonTransientNsContext(Location loc) - { - // Have an instance we can reuse? Great! - if (mLastNsContext != null) { - return mLastNsContext; - } - - // No namespaces declared at this point? Easy, as well: - int totalNsSize = mNamespaces.size(); - if (totalNsSize < 1) { - return (mLastNsContext = EmptyNamespaceContext.getInstance()); - } - - // Otherwise, we need to create a new non-empty context: - int localCount = getCurrentNsCount() << 1; - BaseNsContext nsCtxt = new CompactNsContext - (loc, getDefaultNsURI(), - mNamespaces.asArray(), totalNsSize, - totalNsSize - localCount); - /* And it can be shared if there are no new ('local', ie. included - * within this start element) bindings -- if there are, underlying - * array might be shareable, but offsets wouldn't be) - */ - if (localCount == 0) { - mLastNsContext = nsCtxt; - } - return nsCtxt; -} - - /** - * Method called by the stream reader to add new (start) element - * into the stack in namespace-aware mode; called when a start element - * is encountered during parsing, but only in ns-aware mode. - */ - public final void push(String prefix, String localName) - { - ++mDepth; - String defaultNs = (mCurrElement == null) ? - XmlConsts.DEFAULT_NAMESPACE_URI : mCurrElement.mDefaultNsURI; - - if (mFreeElement == null) { - mCurrElement = new Element(mCurrElement, mNamespaces.size(), prefix, localName); - } else { - Element newElem = mFreeElement; - mFreeElement = newElem.mParent; - newElem.reset(mCurrElement, mNamespaces.size(), prefix, localName); - mCurrElement = newElem; - } - mCurrElement.mDefaultNsURI = defaultNs; - mAttrCollector.reset(); - - /* 20-Feb-2006, TSa: Hmmh. Namespace default provider unfortunately - * needs an advance warning... - */ - if (mNsDefaultProvider != null) { - mMayHaveNsDefaults = mNsDefaultProvider.mayHaveNsDefaults(prefix, localName); - } - } - - /** - * Method called by the stream reader to remove the topmost (start) - * element from the stack; - * called when an end element is encountered during parsing. - * - * @return True if stack has more elements; false if not (that is, - * root element closed) - */ - public final boolean pop() - throws XMLStreamException - { - if (mCurrElement == null) { - throw new IllegalStateException("Popping from empty stack"); - } - --mDepth; - - Element child = mCurrElement; - Element parent = child.mParent; - mCurrElement = parent; - - // Let's do simple recycling of Element instances... - child.relink(mFreeElement); - mFreeElement = child; - - // Need to purge namespaces? - int nsCount = mNamespaces.size() - child.mNsOffset; - if (nsCount > 0) { // 2 entries for each NS mapping: - mLastNsContext = null; // let's invalidate ns ctxt too, if we had one - mNamespaces.removeLast(nsCount); - } - return (parent != null); - } - - /** - * Method called to resolve element and attribute namespaces (in - * namespace-aware mode), and do optional validation using pluggable - * validator object. - * - * @return Text content validation state that should be effective - * for the fully resolved element context - */ - public int resolveAndValidateElement() - throws XMLStreamException - { - if (mDepth == 0) { // just a simple sanity check - throw new IllegalStateException("Calling validate() on empty stack."); - } - AttributeCollector ac = mAttrCollector; - - // Any namespace declarations? - { - int nsCount = ac.getNsCount(); - if (nsCount > 0) { - /* let's first invalidate old (possibly) shared ns ctxt too, - * if we had one; new one can be created at a later point - */ - mLastNsContext = null; - - boolean internNsUris = mConfig.willInternNsURIs(); - for (int i = 0; i < nsCount; ++i) { - Attribute ns = ac.resolveNamespaceDecl(i, internNsUris); - String nsUri = ns.mNamespaceURI; - // note: for namespaces, prefix is stored as local name - String prefix = ns.mLocalName; - - /* 18-Jul-2004, TSa: Need to check that 'xml' and 'xmlns' - * prefixes are not re-defined (and 'xmlns' not even - * defined to its correct ns). - */ - if (prefix == "xmlns") { - // xmlns can never be declared, even to its correct URI - mReporter.throwParseError(ErrorConsts.ERR_NS_REDECL_XMLNS); - } else if (prefix == "xml") { - // whereas xml is ok, as long as it's same URI: - if (!nsUri.equals(XMLConstants.XML_NS_URI)) { - mReporter.throwParseError(ErrorConsts.ERR_NS_REDECL_XML, - nsUri, null); - } - /* 09-Feb-2006, TSa: Hmmh. Now, should this explicit - * xml declaration be visible to the app? SAX API - * seem to ignore it. - */ - //mNamespaces.addStrings(prefix, nsUri); - } else { // ok, valid prefix, so far - /* 17-Mar-2006, TSa: Unbinding default NS needs to - * result in null being added: - */ - if (nsUri == null || nsUri.length() == 0) { - nsUri = XmlConsts.DEFAULT_NAMESPACE_URI; - } - // The default ns binding needs special handling: - if (prefix == null) { - mCurrElement.mDefaultNsURI = nsUri; - } - - /* But then let's ensure that URIs matching xml - * and xmlns are not being bound to anything else - */ - if (internNsUris) { // identity comparison is ok: - if (nsUri == XMLConstants.XML_NS_URI) { - mReporter.throwParseError(ErrorConsts.ERR_NS_REDECL_XML_URI, prefix, null); - } else if (nsUri == XMLConstants.XMLNS_ATTRIBUTE_NS_URI) { - mReporter.throwParseError(ErrorConsts.ERR_NS_REDECL_XMLNS_URI); - } - } else { // need to check equals() - if (nsUri.equals(XMLConstants.XML_NS_URI)) { - mReporter.throwParseError(ErrorConsts.ERR_NS_REDECL_XML_URI, prefix, null); - } else if (nsUri.equals(XMLConstants.XMLNS_ATTRIBUTE_NS_URI)) { - mReporter.throwParseError(ErrorConsts.ERR_NS_REDECL_XMLNS_URI); - } - } - /* and at any rate, binding needs to be added, to - * be visible to the app (including def ns): - */ - mNamespaces.addStrings(prefix, nsUri); - } - } - } - } - - /* 20-Feb-2006, TSa: Any attribute defaults for namespace declaration - * pseudo-attributes? - */ - if (mMayHaveNsDefaults) { - mNsDefaultProvider.checkNsDefaults(this); - } - - // Then, let's set element's namespace, if any: - String prefix = mCurrElement.mPrefix; - String ns; - - if (prefix == null) { // use default NS, if any - ns = mCurrElement.mDefaultNsURI; - } else if (prefix == "xml") { - ns = XMLConstants.XML_NS_URI; - } else { - // Need to find namespace with the prefix: - ns = mNamespaces.findLastFromMap(prefix); - /* 07-Sep-2007, TSa: "no namespace" should now be indicated - * by an empty string, however, due to historical reasons - * let's be bit defensive and allow nulls for the same too - */ - if (ns == null || ns.length() == 0) { - mReporter.throwParseError(ErrorConsts.ERR_NS_UNDECLARED, prefix, null); - } - } - mCurrElement.mNamespaceURI = ns; - - // And finally, resolve attributes' namespaces too: - int xmlidIx = ac.resolveNamespaces(mReporter, mNamespaces); - mIdAttrIndex = xmlidIx; - - XMLValidator vld = mValidator; - /* If we have no validator(s), nothing more to do, - * except perhaps little bit of Xml:id handling: - */ - if (vld == null) { // no validator in use - if (xmlidIx >= 0) { // need to normalize xml:id, still? - ac.normalizeSpacesInValue(xmlidIx); - } - return XMLValidator.CONTENT_ALLOW_ANY_TEXT; - } - - // Otherwise need to call relevant validation methods. - - /* First, a call to check if the element itself may be acceptable - * within structure: - */ - vld.validateElementStart - (mCurrElement.mLocalName, mCurrElement.mNamespaceURI, mCurrElement.mPrefix); - - // Then attributes, if any: - int attrLen = ac.getCount(); - if (attrLen > 0) { - for (int i = 0; i < attrLen; ++i) { - ac.validateAttribute(i, mValidator); - } - } - - /* And finally let's wrap things up to see what textual content - * is allowed as child content, if any: - */ - return mValidator.validateElementAndAttributes(); - } - - /** - * Method called after parsing (but before returning) end element, - * to allow for pluggable validators to verify correctness of - * the content model for the closing element. - * - * @return Validation state that should be effective for the parent - * element state - */ - public int validateEndElement() - throws XMLStreamException - { - if (mValidator == null) { // should never be null if we get here - return XMLValidator.CONTENT_ALLOW_ANY_TEXT; - } - int result = mValidator.validateElementEnd - (mCurrElement.mLocalName, mCurrElement.mNamespaceURI, mCurrElement.mPrefix); - if (mDepth == 1) { // root closing - mValidator.validationCompleted(true); - } - return result; - } - - /* - /////////////////////////////////////////////////// - // AttributeInfo methods (StAX2) - /////////////////////////////////////////////////// - */ - - public final int getAttributeCount() - { - return mAttrCollector.getCount(); - } - - public final int findAttributeIndex(String nsURI, String localName) - { - return mAttrCollector.findIndex(nsURI, localName); - } - - /** - * Default implementation just indicates it does not know of such - * attributes; this because that requires DTD information that only - * some implementations have. - */ - public final int getIdAttributeIndex() - { - if (mIdAttrIndex >= 0) { - return mIdAttrIndex; - } - return (mValidator == null) ? -1 : mValidator.getIdAttrIndex(); - } - - /** - * Default implementation just indicates it does not know of such - * attributes; this because that requires DTD information that only - * some implementations have. - */ - public final int getNotationAttributeIndex() - { - return (mValidator == null) ? -1 : - mValidator.getNotationAttrIndex(); - } - - /* - /////////////////////////////////////////////////// - // Implementation of NamespaceContext: - /////////////////////////////////////////////////// - */ - - public final String getNamespaceURI(String prefix) - { - if (prefix == null) { - throw new IllegalArgumentException(ErrorConsts.ERR_NULL_ARG); - } - if (prefix.length() == 0) { - if (mDepth == 0) { // unexpected... but let's not err at this point - /* 07-Sep-2007, TSa: Default/"no namespace" does map to - * "URI" of empty String. - */ - return XmlConsts.DEFAULT_NAMESPACE_URI; - } - return mCurrElement.mDefaultNsURI; - } - if (prefix.equals(XMLConstants.XML_NS_PREFIX)) { - return XMLConstants.XML_NS_URI; - } - if (prefix.equals(XMLConstants.XMLNS_ATTRIBUTE)) { - return XMLConstants.XMLNS_ATTRIBUTE_NS_URI; - } - /* Ok, need to find the match, if any; starting from end of the - * list of active namespaces. Note that we can not count on prefix - * being interned/canonicalized. - */ - return mNamespaces.findLastNonInterned(prefix); - } - - public final String getPrefix(String nsURI) - { - if (nsURI == null || nsURI.length() == 0) { - throw new IllegalArgumentException("Illegal to pass null/empty prefix as argument."); - } - if (nsURI.equals(XMLConstants.XML_NS_URI)) { - return XMLConstants.XML_NS_PREFIX; - } - if (nsURI.equals(XMLConstants.XMLNS_ATTRIBUTE_NS_URI)) { - return XMLConstants.XMLNS_ATTRIBUTE; - } - - /* Ok, need to find the match, if any; starting from end of the - * list of active namespaces. Note that we can not count on prefix - * being interned/canonicalized. - */ - String prefix = null; - - // 29-Sep-2004, TSa: Need to check for namespace masking, too... - String[] strs = mNamespaces.getInternalArray(); - int len = mNamespaces.size(); - - main_loop: - for (int index = len-1; index > 0; index -= 2) { - if (nsURI.equals(strs[index])) { - // Ok, is prefix masked? - prefix = strs[index-1]; - for (int j = index+1; j < len; j += 2) { - if (strs[j] == prefix) { // masked! - prefix = null; - continue main_loop; - } - } - // nah, it's good - // 17-Mar-2006, TSa: ... but default NS has prefix null... - if (prefix == null) { - prefix = ""; - } - break main_loop; - } - } - - return prefix; - } - - public final Iterator getPrefixes(String nsURI) - { - if (nsURI == null || nsURI.length() == 0) { - throw new IllegalArgumentException("Illegal to pass null/empty prefix as argument."); - } - if (nsURI.equals(XMLConstants.XML_NS_URI)) { - return new SingletonIterator(XMLConstants.XML_NS_PREFIX); - } - if (nsURI.equals(XMLConstants.XMLNS_ATTRIBUTE_NS_URI)) { - return new SingletonIterator(XMLConstants.XMLNS_ATTRIBUTE); - } - - // 29-Sep-2004, TSa: Need to check for namespace masking, too... - String[] strs = mNamespaces.getInternalArray(); - int len = mNamespaces.size(); - ArrayList l = null; - - main_loop: - for (int index = len-1; index > 0; index -= 2) { - if (nsURI.equals(strs[index])) { - // Ok, is prefix masked? - String prefix = strs[index-1]; - for (int j = index+1; j < len; j += 2) { - if (strs[j] == prefix) { // masked! - continue main_loop; - } - } - // nah, it's good! - if (l == null) { - l = new ArrayList(); - } - l.add(prefix); - } - } - - return (l == null) ? EmptyIterator.getInstance() : l.iterator(); - } - - /* - /////////////////////////////////////////////////// - // ValidationContext - /////////////////////////////////////////////////// - */ - - public final String getXmlVersion() - { - return mConfig.isXml11() ? XmlConsts.XML_V_11_STR : XmlConsts.XML_V_10_STR; - } - - // Part of Stax2, see above: - //public int getAttributeCount(); - - public String getAttributeLocalName(int index) { - return getAttrCollector().getLocalName(index); - } - - public String getAttributeNamespace(int index) { - return getAttrCollector().getURI(index); - } - - public String getAttributePrefix(int index) { - return getAttrCollector().getPrefix(index); - } - - public String getAttributeValue(int index) { - return getAttrCollector().getValue(index); - } - - public String getAttributeValue(String nsURI, String localName) - { - int ix = findAttributeIndex(nsURI, localName); - return (ix < 0) ? null : getAttributeValue(ix); - } - - // Part of Stax2, see above: - //public int findAttributeIndex(String nsURI, String localName); - - public boolean isNotationDeclared(String name) - { - // !!! TBI - return false; - } - - public boolean isUnparsedEntityDeclared(String name) - { - // !!! TBI - return false; - } - - public String getBaseUri() - { - // !!! TBI - return null; - } - - public final QName getCurrentElementName() - { - if (mDepth == 0) { - return null; - } - String prefix = mCurrElement.mPrefix; - /* 17-Mar-2006, TSa: We only map prefix to empty String because - * some QName impls barf on nulls. Otherwise we will always - * use null to indicate missing prefixes. - */ - if (prefix == null) { - prefix = ""; - } - /* 03-Dec-2004, TSa: Maybe we can just reuse the last QName - * object created, if we have same data? (happens if - * state hasn't changed, or we got end element for a leaf - * element, or repeating leaf elements) - */ - String nsURI = mCurrElement.mNamespaceURI; - String ln = mCurrElement.mLocalName; - - /* Since we generally intern most Strings, can do identity - * comparisons here: - */ - if (ln != mLastLocalName) { - mLastLocalName = ln; - mLastPrefix = prefix; - mLastNsURI = nsURI; - } else if (prefix != mLastPrefix) { - mLastPrefix = prefix; - mLastNsURI = nsURI; - } else if (nsURI != mLastNsURI) { - mLastNsURI = nsURI; - } else { - return mLastName; - } - QName n = QNameCreator.create(nsURI, ln, prefix); - mLastName = n; - return n; - } - - // This was defined above for NamespaceContext - //public String getNamespaceURI(String prefix); - - public Location getValidationLocation() - { - return mReporter.getLocation(); - } - - public void reportProblem(XMLValidationProblem problem) - throws XMLStreamException - { - mReporter.reportValidationProblem(problem); - } - - /** - * Method called by actual validator instances when attributes with - * default values have no explicit values for the element; if so, - * default value needs to be added as if it was parsed from the - * element. - */ - public int addDefaultAttribute(String localName, String uri, String prefix, - String value) - { - return mAttrCollector.addDefaultAttribute(localName, uri, prefix, value); - } - - /* - /////////////////////////////////////////////////// - // Support for NsDefaultProvider - /////////////////////////////////////////////////// - */ - - public boolean isPrefixLocallyDeclared(String internedPrefix) - { - if (internedPrefix != null && internedPrefix.length() == 0) { // default ns - internedPrefix = null; - } - - int offset = mCurrElement.mNsOffset; - for (int len = mNamespaces.size(); offset < len; offset += 2) { - // both interned, can use identity comparison - String thisPrefix = mNamespaces.getString(offset); - if (thisPrefix == internedPrefix) { - return true; - } - } - return false; - } - - /** - * Callback method called by the namespace default provider. At - * this point we can trust it to only call this method with somewhat - * valid arguments (no dups etc). - */ - public void addNsBinding(String prefix, String uri) - { - // Unbind? (xml 1.1...) - if ((uri == null) || (uri.length() == 0)) { - uri = null; - } - - // Default ns declaration? - if ((prefix == null) || (prefix.length() == 0)) { - prefix = null; - mCurrElement.mDefaultNsURI = uri; - } - mNamespaces.addStrings(prefix, uri); - } - - /* - /////////////////////////////////////////////////// - // Support for validation: - /////////////////////////////////////////////////// - */ - - public final void validateText(TextBuffer tb, boolean lastTextSegment) - throws XMLStreamException - { - tb.validateText(mValidator, lastTextSegment); - } - - public final void validateText(String contents, boolean lastTextSegment) - throws XMLStreamException - { - mValidator.validateText(contents, lastTextSegment); - } - - /* - /////////////////////////////////////////////////// - // Accessors: - /////////////////////////////////////////////////// - */ - - // // // Generic stack information: - - public final boolean isNamespaceAware() { - return mNsAware; - } - - // // // Generic stack information: - - public final boolean isEmpty() { - return mDepth == 0; - } - - /** - * @return Number of open elements in the stack; 0 when parser is in - * prolog/epilog, 1 inside root element and so on. - */ - public final int getDepth() { return mDepth; } - - // // // Information about element at top of stack: - - public final String getDefaultNsURI() { - if (mDepth == 0) { - throw new IllegalStateException("Illegal access, empty stack."); - } - return mCurrElement.mDefaultNsURI; - } - - public final String getNsURI() { - if (mDepth == 0) { - throw new IllegalStateException("Illegal access, empty stack."); - } - return mCurrElement.mNamespaceURI; - } - - public final String getPrefix() { - if (mDepth == 0) { - throw new IllegalStateException("Illegal access, empty stack."); - } - return mCurrElement.mPrefix; - } - - public final String getLocalName() { - if (mDepth == 0) { - throw new IllegalStateException("Illegal access, empty stack."); - } - return mCurrElement.mLocalName; - } - - public final boolean matches(String prefix, String localName) - { - if (mDepth == 0) { - throw new IllegalStateException("Illegal access, empty stack."); - } - String thisPrefix = mCurrElement.mPrefix; - if (prefix == null || prefix.length() == 0) { // no name space - if (thisPrefix != null && thisPrefix.length() > 0) { - return false; - } - } else { - if (thisPrefix != prefix && !thisPrefix.equals(prefix)) { - return false; - } - } - - String thisName = mCurrElement.mLocalName; - return (thisName == localName) || thisName.equals(localName); - } - - public final String getTopElementDesc() - { - if (mDepth == 0) { - throw new IllegalStateException("Illegal access, empty stack."); - } - String name = mCurrElement.mLocalName; - String prefix = mCurrElement.mPrefix; - if (prefix == null) { // no name space - return name; - } - return prefix + ":" + name; - } - - // // // Namespace information: - - /** - * @return Number of active prefix/namespace mappings for current scope, - * including mappings from enclosing elements. - */ - public final int getTotalNsCount() { - return mNamespaces.size() >> 1; - } - - /** - * @return Number of active prefix/namespace mappings for current scope, - * NOT including mappings from enclosing elements. - */ - public final int getCurrentNsCount() - { - // Need not check for empty stack; should return 0 properly - return (mNamespaces.size() - mCurrElement.mNsOffset) >> 1; - } - - public final String getLocalNsPrefix(int index) - { - int offset = mCurrElement.mNsOffset; - int localCount = (mNamespaces.size() - offset); - index <<= 1; // 2 entries, prefix/URI for each NS - if (index < 0 || index >= localCount) { - throwIllegalIndex(index >> 1, localCount >> 1); - } - return mNamespaces.getString(offset + index); - } - - public final String getLocalNsURI(int index) - { - int offset = mCurrElement.mNsOffset; - int localCount = (mNamespaces.size() - offset); - index <<= 1; // 2 entries, prefix/URI for each NS - if (index < 0 || index >= localCount) { - throwIllegalIndex(index >> 1, localCount >> 1); - } - return mNamespaces.getString(offset + index + 1); - } - - private void throwIllegalIndex(int index, int localCount) - { - throw new IllegalArgumentException("Illegal namespace index " - +(index >> 1) - +"; current scope only has " - +(localCount >> 1) - +" namespace declarations."); - } - - // // // DTD-derived attribute information: - - /** - * @return Schema (DTD, RNG, W3C Schema) based type of the attribute - * in specified index - */ - public final String getAttributeType(int index) - { - if (index == mIdAttrIndex && index >= 0) { // second check to ensure -1 is not passed - return "ID"; - } - return (mValidator == null) ? WstxInputProperties.UNKNOWN_ATTR_TYPE : - mValidator.getAttributeType(index); - } -} diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/sr/InputProblemReporter.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/sr/InputProblemReporter.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/sr/InputProblemReporter.java 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/sr/InputProblemReporter.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,53 +0,0 @@ -package com.ctc.wstx.sr; - -import javax.xml.stream.Location; -import javax.xml.stream.XMLStreamException; - -import org.codehaus.stax2.validation.XMLValidationProblem; - -/** - * Interface implemented by input reader, and used by other components to - * report problem that are related to current input position. - */ -public interface InputProblemReporter -{ - /* - //////////////////////////////////////////////////// - // Methods for reporting "hard" errors: - //////////////////////////////////////////////////// - */ - - public void throwParseError(String msg) throws XMLStreamException; - public void throwParseError(String msg, Object arg, Object arg2) - throws XMLStreamException; - - /* - /////////////////////////////////////////////////////// - // Reporting validation problems - /////////////////////////////////////////////////////// - */ - - public void reportValidationProblem(XMLValidationProblem prob) - throws XMLStreamException; - public void reportValidationProblem(String msg) - throws XMLStreamException; - public void reportValidationProblem(String msg, Object arg, Object arg2) - throws XMLStreamException; - - /* - /////////////////////////////////////////////////////// - // Methods for reporting other "soft" (recoverable) problems - /////////////////////////////////////////////////////// - */ - - public void reportProblem(Location loc, String probType, String format, Object arg, Object arg2) - throws XMLStreamException; - - /* - //////////////////////////////////////////////////// - // Supporting methods needed by reporting - //////////////////////////////////////////////////// - */ - - public Location getLocation(); -} diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/sr/NsDefaultProvider.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/sr/NsDefaultProvider.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/sr/NsDefaultProvider.java 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/sr/NsDefaultProvider.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,44 +0,0 @@ -/* Woodstox XML processor - * - * Copyright (c) 2004- Tatu Saloranta, tatu.saloranta@iki.fi - * - * Licensed under the License specified in file LICENSE, included with - * the source code. - * You may not use this file except in compliance with the License. - * - * 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 com.ctc.wstx.sr; - -import javax.xml.stream.XMLStreamException; - -/** - * Interface only used by Woodstox core. The main reason for the interface - * is to reduce coupling with the input element stack and dtd validator - * instances: while dtd validator needs to be able to inject namespace - * declarations based on attribute default values, it should not have to - * know too much about element stack implementation, and vice versa. - * As a result, this interface defines API input element stack calls - * on the dtd validator instance. Validator instance then refers to the - * input element stack base class to do callbacks if and as necessary. - */ -public interface NsDefaultProvider -{ - public boolean mayHaveNsDefaults(String elemPrefix, String elemLN); - - /** - * Method called by the input element stack to indicate that - * it has just added local namespace declarations from the - * current element, and is about to start resolving element - * and attribute namespace bindings. This provider instance is - * to add namespace declarations from attribute defaults, if - * any, using callbacks to the input element stack. - */ - public void checkNsDefaults(InputElementStack nsStack) - throws XMLStreamException; -} diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/sr/package.html libwoodstox-java-5.1.0/src/java/com/ctc/wstx/sr/package.html --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/sr/package.html 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/sr/package.html 1970-01-01 00:00:00.000000000 +0000 @@ -1,4 +0,0 @@ - -This package contains supporting code for handling namespace information; -element stacks that keep track of elements parsed and such. - diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/sr/ReaderCreator.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/sr/ReaderCreator.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/sr/ReaderCreator.java 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/sr/ReaderCreator.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,34 +0,0 @@ -package com.ctc.wstx.sr; - -import com.ctc.wstx.dtd.DTDId; -import com.ctc.wstx.dtd.DTDSubset; -import com.ctc.wstx.util.SymbolTable; - -/** - * Interface that defines callbacks readers can use to access settings - * of the input factory that created them, as well as update cached - * data factory may store (shared symbol tables, cached DTDs etc). - *

- * Note that readers in general should only access the configuration info - * when they are created (from constructor). - */ -public interface ReaderCreator -{ - /* - /////////////////////////////////////////////////////// - // Methods for accessing configuration info - /////////////////////////////////////////////////////// - */ - - public DTDSubset findCachedDTD(DTDId id); - - /* - /////////////////////////////////////////////////////// - // Methods for updating information factory has - /////////////////////////////////////////////////////// - */ - - public void updateSymbolTable(SymbolTable t); - - public void addCachedDTD(DTDId id, DTDSubset extSubset); -} diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/sr/StreamReaderImpl.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/sr/StreamReaderImpl.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/sr/StreamReaderImpl.java 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/sr/StreamReaderImpl.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,28 +0,0 @@ -package com.ctc.wstx.sr; - -import javax.xml.stream.*; - -import org.codehaus.stax2.XMLStreamReader2; - -import com.ctc.wstx.ent.EntityDecl; - -/** - * Interface that defines "internal Woodstox API". It is used to decouple - * parts of the Woodstox that need to know something more about woodstox - * stream reader implementation, but not about implementation details. - * Specifically, there are some simple dependencies from the stream - * writer; they should only need to refer to this interface. - */ -public interface StreamReaderImpl - extends XMLStreamReader2 -{ - public EntityDecl getCurrentEntityDecl(); - - public Object withStartElement(ElemCallback cb, Location loc); - - public boolean isNamespaceAware(); - - public AttributeCollector getAttributeCollector(); - - public InputElementStack getInputElementStack(); -} diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/sr/StreamScanner.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/sr/StreamScanner.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/sr/StreamScanner.java 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/sr/StreamScanner.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,2444 +0,0 @@ -/* Woodstox XML processor - * - * Copyright (c) 2004- Tatu Saloranta, tatu.saloranta@iki.fi - * - * Licensed under the License specified in file LICENSE, included with - * the source code. - * You may not use this file except in compliance with the License. - * - * 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 com.ctc.wstx.sr; - -import java.io.FileNotFoundException; -import java.io.IOException; -import java.net.URL; -import java.text.MessageFormat; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; - -import javax.xml.stream.Location; -import javax.xml.stream.XMLInputFactory; -import javax.xml.stream.XMLReporter; -import javax.xml.stream.XMLResolver; -import javax.xml.stream.XMLStreamException; - -import org.codehaus.stax2.XMLReporter2; -import org.codehaus.stax2.XMLStreamLocation2; -import org.codehaus.stax2.validation.XMLValidationProblem; - -import com.ctc.wstx.api.ReaderConfig; -import com.ctc.wstx.cfg.ErrorConsts; -import com.ctc.wstx.cfg.InputConfigFlags; -import com.ctc.wstx.cfg.ParsingErrorMsgs; -import com.ctc.wstx.cfg.XmlConsts; -import com.ctc.wstx.dtd.MinimalDTDReader; -import com.ctc.wstx.ent.EntityDecl; -import com.ctc.wstx.ent.IntEntity; -import com.ctc.wstx.exc.*; -import com.ctc.wstx.io.DefaultInputResolver; -import com.ctc.wstx.io.WstxInputData; -import com.ctc.wstx.io.WstxInputLocation; -import com.ctc.wstx.io.WstxInputSource; -import com.ctc.wstx.util.ExceptionUtil; -import com.ctc.wstx.util.SymbolTable; -import com.ctc.wstx.util.TextBuffer; - -/** - * Abstract base class that defines some basic functionality that all - * Woodstox reader classes (main XML reader, DTD reader) extend from. - */ - -public abstract class StreamScanner - extends WstxInputData - implements InputProblemReporter, - InputConfigFlags, ParsingErrorMsgs -{ - - // // // Some well-known chars: - - /** - * Last (highest) char code of the three, LF, CR and NULL - */ - public final static char CHAR_CR_LF_OR_NULL = (char) 13; - - public final static int INT_CR_LF_OR_NULL = 13; - - /** - * Character that allows quick check of whether a char can potentially - * be some kind of markup, WRT input stream processing; - * has to contain linefeeds, &, < and > (">" only matters when - * quoting text, as part of "]]>") - */ - protected final static char CHAR_FIRST_PURE_TEXT = (char) ('>' + 1); - - - /** - * First character in Unicode (ie one with lowest id) that is legal - * as part of a local name (all valid name chars minus ':'). Used - * for doing quick check for local name end; usually name ends in - * a whitespace or equals sign. - */ - protected final static char CHAR_LOWEST_LEGAL_LOCALNAME_CHAR = '-'; - - /* - /////////////////////////////////////////////////////////// - // Character validity constants, structs - /////////////////////////////////////////////////////////// - */ - - /** - * We will only use validity array for first 256 characters, mostly - * because after those characters it's easier to do fairly simple - * block checks. - */ - private final static int VALID_CHAR_COUNT = 0x100; - - private final static byte NAME_CHAR_INVALID_B = (byte) 0; - private final static byte NAME_CHAR_ALL_VALID_B = (byte) 1; - private final static byte NAME_CHAR_VALID_NONFIRST_B = (byte) -1; - - private final static byte[] sCharValidity = new byte[VALID_CHAR_COUNT]; - - static { - /* First, since all valid-as-first chars are also valid-as-other chars, - * we'll initialize common chars: - */ - sCharValidity['_'] = NAME_CHAR_ALL_VALID_B; - for (int i = 0, last = ('z' - 'a'); i <= last; ++i) { - sCharValidity['A' + i] = NAME_CHAR_ALL_VALID_B; - sCharValidity['a' + i] = NAME_CHAR_ALL_VALID_B; - } - for (int i = 0xC0; i < 0xF6; ++i) { // not all are fully valid, but - sCharValidity[i] = NAME_CHAR_ALL_VALID_B; - } - // ... now we can 'revert' ones not fully valid: - sCharValidity[0xD7] = NAME_CHAR_INVALID_B; - sCharValidity[0xF7] = NAME_CHAR_INVALID_B; - - /* And then we can proceed with ones only valid-as-other. - */ - sCharValidity['-'] = NAME_CHAR_VALID_NONFIRST_B; - sCharValidity['.'] = NAME_CHAR_VALID_NONFIRST_B; - sCharValidity[0xB7] = NAME_CHAR_VALID_NONFIRST_B; - for (int i = '0'; i <= '9'; ++i) { - sCharValidity[i] = NAME_CHAR_VALID_NONFIRST_B; - } - } - - /** - * Public identifiers only use 7-bit ascii range. - */ - private final static int VALID_PUBID_CHAR_COUNT = 0x80; - private final static byte[] sPubidValidity = new byte[VALID_PUBID_CHAR_COUNT]; -// private final static byte PUBID_CHAR_INVALID_B = (byte) 0; - private final static byte PUBID_CHAR_VALID_B = (byte) 1; - static { - for (int i = 0, last = ('z' - 'a'); i <= last; ++i) { - sPubidValidity['A' + i] = PUBID_CHAR_VALID_B; - sPubidValidity['a' + i] = PUBID_CHAR_VALID_B; - } - for (int i = '0'; i <= '9'; ++i) { - sPubidValidity[i] = PUBID_CHAR_VALID_B; - } - - // 3 main white space types are valid - sPubidValidity[0x0A] = PUBID_CHAR_VALID_B; - sPubidValidity[0x0D] = PUBID_CHAR_VALID_B; - sPubidValidity[0x20] = PUBID_CHAR_VALID_B; - - // And many of punctuation/separator ascii chars too: - sPubidValidity['-'] = PUBID_CHAR_VALID_B; - sPubidValidity['\''] = PUBID_CHAR_VALID_B; - sPubidValidity['('] = PUBID_CHAR_VALID_B; - sPubidValidity[')'] = PUBID_CHAR_VALID_B; - sPubidValidity['+'] = PUBID_CHAR_VALID_B; - sPubidValidity[','] = PUBID_CHAR_VALID_B; - sPubidValidity['.'] = PUBID_CHAR_VALID_B; - sPubidValidity['/'] = PUBID_CHAR_VALID_B; - sPubidValidity[':'] = PUBID_CHAR_VALID_B; - sPubidValidity['='] = PUBID_CHAR_VALID_B; - sPubidValidity['?'] = PUBID_CHAR_VALID_B; - sPubidValidity[';'] = PUBID_CHAR_VALID_B; - sPubidValidity['!'] = PUBID_CHAR_VALID_B; - sPubidValidity['*'] = PUBID_CHAR_VALID_B; - sPubidValidity['#'] = PUBID_CHAR_VALID_B; - sPubidValidity['@'] = PUBID_CHAR_VALID_B; - sPubidValidity['$'] = PUBID_CHAR_VALID_B; - sPubidValidity['_'] = PUBID_CHAR_VALID_B; - sPubidValidity['%'] = PUBID_CHAR_VALID_B; - } - - /* - /////////////////////////////////////////////////////////// - // Basic configuration - /////////////////////////////////////////////////////////// - */ - - /** - * Copy of the configuration object passed by the factory. - * Contains immutable settings for this reader (or in case - * of DTD parsers, reader that uses it) - */ - protected final ReaderConfig mConfig; - - // // // Various extracted settings: - - /** - * If true, Reader is namespace aware, and should do basic checks - * (usually enforcing limitations on having colons in names) - */ - protected final boolean mCfgNsEnabled; - - // Extracted standard on/off settings: - - /** - * note: left non-final on purpose: sub-class may need to modify - * the default value after construction. - */ - protected boolean mCfgReplaceEntities; - - /* - /////////////////////////////////////////////////////////// - // Symbol handling, if applicable - /////////////////////////////////////////////////////////// - */ - - final SymbolTable mSymbols; - - /** - * Local full name for the event, if it has one (note: element events - * do NOT use this variable; those names are stored in element stack): - * target for processing instructions. - *

- * Currently used for proc. instr. target, and entity name (at least - * when current entity reference is null). - *

- * Note: this variable is generally not cleared, since it comes from - * a symbol table, ie. this won't be the only reference. - */ - protected String mCurrName; - - /* - /////////////////////////////////////////////////////////// - // Input handling - /////////////////////////////////////////////////////////// - */ - - /** - * Currently active input source; contains link to parent (nesting) input - * sources, if any. - */ - protected WstxInputSource mInput; - - /** - * Top-most input source this reader can use; due to input source - * chaining, this is not necessarily the root of all input; for example, - * external DTD subset reader's root input still has original document - * input as its parent. - */ - protected final WstxInputSource mRootInput; - - /** - * Custom resolver used to handle external entities that are to be expanded - * by this reader (external param/general entity expander) - */ - XMLResolver mEntityResolver = null; - - /** - * This is the current depth of the input stack (same as what input - * element stack would return as its depth). - * It is used to enforce input scope constraints for nesting of - * elements (for xml reader) and dtd declaration (for dtd reader) - * with regards to input block (entity expansion) boundaries. - *

- * Basically this value is compared to {@link #mInputTopDepth}, which - * indicates what was the depth at the point where the currently active - * input scope/block was started. - */ - protected int mCurrDepth = 0; - - protected int mInputTopDepth = 0; - - /** - * Flag that indicates whether linefeeds in the input data are to - * be normalized or not. - * Xml specs mandate that the line feeds are only normalized - * when they are from the external entities (main doc, external - * general/parsed entities), so normalization has to be - * suppressed when expanding internal general/parsed entities. - */ - protected boolean mNormalizeLFs; - - /* - /////////////////////////////////////////////////////////// - // Buffer(s) for local name(s) and text content - /////////////////////////////////////////////////////////// - */ - - /** - * Temporary buffer used if local name can not be just directly - * constructed from input buffer (name is on a boundary or such). - */ - protected char[] mNameBuffer = null; - - /* - /////////////////////////////////////////////////////////// - // Information about starting location of event - // Reader is pointing to; updated on-demand - /////////////////////////////////////////////////////////// - */ - - // // // Location info at point when current token was started - - /** - * Total number of characters read before start of current token. - * For big (gigabyte-sized) sizes are possible, needs to be long, - * unlike pointers and sizes related to in-memory buffers. - */ - protected long mTokenInputTotal = 0; - - /** - * Input row on which current token starts, 1-based - */ - protected int mTokenInputRow = 1; - - /** - * Column on input row that current token starts; 0-based (although - * in the end it'll be converted to 1-based) - */ - protected int mTokenInputCol = 0; - - /* - /////////////////////////////////////////////////////////// - // XML document information (from doc decl if one - // was found) common to all entities (main xml - // document, external DTD subset) - /////////////////////////////////////////////////////////// - */ - - /** - * Input stream encoding, if known (passed in, or determined by - * auto-detection); null if not. - */ - String mDocInputEncoding = null; - - /** - * Character encoding from xml declaration, if any; null if no - * declaration, or it didn't specify encoding. - */ - String mDocXmlEncoding = null; - - /** - * XML version as declared by the document; one of constants - * from {@link XmlConsts} (like {@link XmlConsts#XML_V_10}). - */ - protected int mDocXmlVersion = XmlConsts.XML_V_UNKNOWN; - - /** - * Cache of internal character entities; - */ - protected Map mCachedEntities; - - /** - * Flag for whether or not character references should be treated as entities - */ - protected boolean mCfgTreatCharRefsAsEntities; - - /** - * Entity reference stream currently points to. - */ - protected EntityDecl mCurrEntity; - - /* - /////////////////////////////////////////////////////////// - // Life-cycle - /////////////////////////////////////////////////////////// - */ - - /** - * Constructor used when creating a complete new (main-level) reader that - * does not share its input buffers or state with another reader. - */ - protected StreamScanner(WstxInputSource input, ReaderConfig cfg, - XMLResolver res) - { - super(); - mInput = input; - // 17-Jun-2004, TSa: Need to know root-level input source - mRootInput = input; - - mConfig = cfg; - mSymbols = cfg.getSymbols(); - int cf = cfg.getConfigFlags(); - mCfgNsEnabled = (cf & CFG_NAMESPACE_AWARE) != 0; - mCfgReplaceEntities = (cf & CFG_REPLACE_ENTITY_REFS) != 0; - - mNormalizeLFs = mConfig.willNormalizeLFs(); - mInputBuffer = null; - mInputPtr = mInputEnd = 0; - mEntityResolver = res; - - mCfgTreatCharRefsAsEntities = mConfig.willTreatCharRefsAsEnts(); - mCachedEntities = mCfgTreatCharRefsAsEntities ? new HashMap() : Collections.EMPTY_MAP; - } - - /* - /////////////////////////////////////////////////////////// - // Package API - /////////////////////////////////////////////////////////// - */ - - /** - * Method that returns location of the last character returned by this - * reader; that is, location "one less" than the currently pointed to - * location. - */ - protected WstxInputLocation getLastCharLocation() - { - return mInput.getLocation(mCurrInputProcessed + mInputPtr - 1, - mCurrInputRow, - mInputPtr - mCurrInputRowStart); - } - - protected URL getSource() { - return mInput.getSource(); - } - - protected String getSystemId() { - return mInput.getSystemId(); - } - - /* - /////////////////////////////////////////////////////////// - // Partial LocationInfo implementation (not implemented - // by this base class, but is by some sub-classes) - /////////////////////////////////////////////////////////// - */ - - /** - * Returns location of last properly parsed token; as per StAX specs, - * apparently needs to be the end of current event, which is the same - * as the start of the following event (or EOF if that's next). - */ - public abstract Location getLocation(); - - public XMLStreamLocation2 getStartLocation() - { - // note: +1 is used as columns are 1-based... - return mInput.getLocation(mTokenInputTotal, mTokenInputRow, - mTokenInputCol + 1); - } - - public XMLStreamLocation2 getCurrentLocation() - { - return mInput.getLocation(mCurrInputProcessed + mInputPtr, - mCurrInputRow, - mInputPtr - mCurrInputRowStart + 1); - } - - /* - /////////////////////////////////////////////////////////// - // InputProblemReporter implementation - /////////////////////////////////////////////////////////// - */ - - public WstxException throwWfcException(String msg, boolean deferErrors) - throws WstxException - { - WstxException ex = constructWfcException(msg); - if (!deferErrors) { - throw ex; - } - return ex; - } - - public void throwParseError(String msg) throws XMLStreamException - { - throwParseError(msg, null, null); - } - - /** - * Throws generic parse error with specified message and current parsing - * location. - *

- * Note: public access only because core code in other packages needs - * to access it. - */ - public void throwParseError(String format, Object arg, Object arg2) - throws XMLStreamException - { - String msg = (arg != null || arg2 != null) ? - MessageFormat.format(format, new Object[] { arg, arg2 }) : format; - throw constructWfcException(msg); - } - - public void reportProblem(String probType, String format, Object arg, Object arg2) - throws XMLStreamException - { - XMLReporter rep = mConfig.getXMLReporter(); - if (rep != null) { - _reportProblem(rep, probType, - MessageFormat.format(format, new Object[] { arg, arg2 }), null); - } - } - - public void reportProblem(Location loc, String probType, - String format, Object arg, Object arg2) - throws XMLStreamException - { - XMLReporter rep = mConfig.getXMLReporter(); - if (rep != null) { - String msg = (arg != null || arg2 != null) ? - MessageFormat.format(format, new Object[] { arg, arg2 }) : format; - _reportProblem(rep, probType, msg, loc); - } - } - - protected void _reportProblem(XMLReporter rep, String probType, String msg, Location loc) - throws XMLStreamException - { - if (loc == null) { - loc = getLastCharLocation(); - } - _reportProblem(rep, new XMLValidationProblem(loc, msg, XMLValidationProblem.SEVERITY_ERROR, probType)); - } - - protected void _reportProblem(XMLReporter rep, XMLValidationProblem prob) - throws XMLStreamException - { - if (rep != null) { - Location loc = prob.getLocation(); - if (loc == null) { - loc = getLastCharLocation(); - prob.setLocation(loc); - } - // Backwards-compatibility fix: add non-null type, if missing: - if (prob.getType() == null) { - prob.setType(ErrorConsts.WT_VALIDATION); - } - // [WSTX-154]: was catching and dropping thrown exception: shouldn't. - // [WTSX-157]: need to support XMLReporter2 - if (rep instanceof XMLReporter2) { - ((XMLReporter2) rep).report(prob); - } else { - rep.report(prob.getMessage(), prob.getType(), prob, loc); - } - } - } - - /** - *

- * Note: this is the base implementation used for implementing - * ValidationContext - */ - public void reportValidationProblem(XMLValidationProblem prob) - throws XMLStreamException - { - // !!! TBI: Fail-fast vs. deferred modes? - /* For now let's implement basic functionality: warnings get - * reported via XMLReporter, errors and fatal errors result in - * immediate exceptions. - */ - /* 27-May-2008, TSa: [WSTX-153] Above is incorrect: as per Stax - * javadocs for XMLReporter, both warnings and non-fatal errors - * (which includes all validation errors) should be reported via - * XMLReporter interface, and only fatals should cause an - * immediate stream exception (by-passing reporter) - */ - if (prob.getSeverity() > XMLValidationProblem.SEVERITY_ERROR) { - throw WstxValidationException.create(prob); - } - XMLReporter rep = mConfig.getXMLReporter(); - if (rep != null) { - _reportProblem(rep, prob); - } else { - /* If no reporter, regular non-fatal errors are to be reported - * as exceptions as well, for backwards compatibility - */ - if (prob.getSeverity() >= XMLValidationProblem.SEVERITY_ERROR) { - throw WstxValidationException.create(prob); - } - } - } - - public void reportValidationProblem(String msg, int severity) - throws XMLStreamException - { - reportValidationProblem(new XMLValidationProblem(getLastCharLocation(), - msg, severity)); - } - - public void reportValidationProblem(String msg) - throws XMLStreamException - { - reportValidationProblem(new XMLValidationProblem(getLastCharLocation(), - msg, - XMLValidationProblem.SEVERITY_ERROR)); - } - - public void reportValidationProblem(Location loc, String msg) - throws XMLStreamException - { - reportValidationProblem(new XMLValidationProblem(loc, msg)); - } - - public void reportValidationProblem(String format, Object arg, Object arg2) - throws XMLStreamException - { - reportValidationProblem(MessageFormat.format(format, new Object[] { arg, arg2 })); - } - - /* - /////////////////////////////////////////////////////////// - // Other error reporting methods - /////////////////////////////////////////////////////////// - */ - - protected WstxException constructWfcException(String msg) - { - return new WstxParsingException(msg, getLastCharLocation()); - } - - /** - * Construct and return a {@link XMLStreamException} to throw - * as a result of a failed Typed Access operation (but one not - * caused by a Well-Formedness Constraint or Validation Constraint - * problem) - */ - /* - protected WstxException _constructTypeException(String msg) - { - // Hmmh. Should there be a distinct sub-type? - return new WstxParsingException(msg, getLastCharLocation()); - } - */ - - protected WstxException constructFromIOE(IOException ioe) - { - return new WstxIOException(ioe); - } - - protected WstxException constructNullCharException() - { - return new WstxUnexpectedCharException("Illegal character (NULL, unicode 0) encountered: not valid in any content", - getLastCharLocation(), CHAR_NULL); - } - - protected void throwUnexpectedChar(int i, String msg) - throws WstxException - { - char c = (char) i; - String excMsg = "Unexpected character "+getCharDesc(c)+msg; - throw new WstxUnexpectedCharException(excMsg, getLastCharLocation(), c); - } - - protected void throwNullChar() - throws WstxException - { - throw constructNullCharException(); - } - - protected void throwInvalidSpace(int i) - throws WstxException - { - throwInvalidSpace(i, false); - } - - protected WstxException throwInvalidSpace(int i, boolean deferErrors) - throws WstxException - { - char c = (char) i; - WstxException ex; - if (c == CHAR_NULL) { - ex = constructNullCharException(); - } else { - String msg = "Illegal character ("+getCharDesc(c)+")"; - if (mXml11) { - msg += " [note: in XML 1.1, it could be included via entity expansion]"; - } - ex = new WstxUnexpectedCharException(msg, getLastCharLocation(), c); - } - if (!deferErrors) { - throw ex; - } - return ex; - } - - protected void throwUnexpectedEOF(String msg) - throws WstxException - { - throw new WstxEOFException("Unexpected EOF" - +(msg == null ? "" : msg), - getLastCharLocation()); - } - - /** - * Similar to {@link #throwUnexpectedEOF}, but only indicates ending - * of an input block. Used when reading a token that can not span - * input block boundaries (ie. can not continue past end of an - * entity expansion). - */ - protected void throwUnexpectedEOB(String msg) - throws WstxException - { - throw new WstxEOFException("Unexpected end of input block" - +(msg == null ? "" : msg), - getLastCharLocation()); - } - - protected void throwFromIOE(IOException ioe) - throws WstxException - { - throw new WstxIOException(ioe); - } - - protected void throwFromStrE(XMLStreamException strex) - throws WstxException - { - if (strex instanceof WstxException) { - throw (WstxException) strex; - } - WstxException newEx = new WstxException(strex); - ExceptionUtil.setInitCause(newEx, strex); - throw newEx; - } - - /** - * Method called to report an error, when caller's signature only - * allows runtime exceptions to be thrown. - */ - protected void throwLazyError(Exception e) - { - if (e instanceof XMLStreamException) { - WstxLazyException.throwLazily((XMLStreamException) e); - } - ExceptionUtil.throwRuntimeException(e); - } - - protected String tokenTypeDesc(int type) - { - return ErrorConsts.tokenTypeDesc(type); - } - - /* - /////////////////////////////////////////////////////////// - // Input buffer handling - /////////////////////////////////////////////////////////// - */ - - /** - * Returns current input source this source uses. - *

- * Note: public only because some implementations are on different - * package. - */ - public final WstxInputSource getCurrentInput() { - return mInput; - } - - protected final int inputInBuffer() { - return mInputEnd - mInputPtr; - } - - protected final int getNext() - throws XMLStreamException - { - if (mInputPtr >= mInputEnd) { - if (!loadMore()) { - return -1; - } - } - return (int) mInputBuffer[mInputPtr++]; - } - - /** - * Similar to {@link #getNext}, but does not advance pointer - * in input buffer. - *

- * Note: this method only peeks within current input source; - * it does not close it and check nested input source (if any). - * This is necessary when checking keywords, since they can never - * cross input block boundary. - */ - protected final int peekNext() - throws XMLStreamException - { - if (mInputPtr >= mInputEnd) { - if (!loadMoreFromCurrent()) { - return -1; - } - } - return (int) mInputBuffer[mInputPtr]; - } - - protected final char getNextChar(String errorMsg) - throws XMLStreamException - { - if (mInputPtr >= mInputEnd) { - loadMore(errorMsg); - } - return mInputBuffer[mInputPtr++]; - } - - /** - * Similar to {@link #getNextChar}, but will not read more characters - * from parent input source(s) if the current input source doesn't - * have more content. This is often needed to prevent "runaway" content, - * such as comments that start in an entity but do not have matching - * close marker inside entity; XML specification specifically states - * such markup is not legal. - */ - protected final char getNextCharFromCurrent(String errorMsg) - throws XMLStreamException - { - if (mInputPtr >= mInputEnd) { - loadMoreFromCurrent(errorMsg); - } - return mInputBuffer[mInputPtr++]; - } - - /** - * Method that will skip through zero or more white space characters, - * and return either the character following white space, or -1 to - * indicate EOF (end of the outermost input source)/ - */ - protected final int getNextAfterWS() - throws XMLStreamException - { - if (mInputPtr >= mInputEnd) { - if (!loadMore()) { - return -1; - } - } - char c = mInputBuffer[mInputPtr++]; - while (c <= CHAR_SPACE) { - // Linefeed? - if (c == '\n' || c == '\r') { - skipCRLF(c); - } else if (c != CHAR_SPACE && c != '\t') { - throwInvalidSpace(c); - } - // Still a white space? - if (mInputPtr >= mInputEnd) { - if (!loadMore()) { - return -1; - } - } - c = mInputBuffer[mInputPtr++]; - } - return (int) c; - } - - protected final char getNextCharAfterWS(String errorMsg) - throws XMLStreamException - { - if (mInputPtr >= mInputEnd) { - loadMore(errorMsg); - } - - char c = mInputBuffer[mInputPtr++]; - while (c <= CHAR_SPACE) { - // Linefeed? - if (c == '\n' || c == '\r') { - skipCRLF(c); - } else if (c != CHAR_SPACE && c != '\t') { - throwInvalidSpace(c); - } - - // Still a white space? - if (mInputPtr >= mInputEnd) { - loadMore(errorMsg); - } - c = mInputBuffer[mInputPtr++]; - } - return c; - } - - protected final char getNextInCurrAfterWS(String errorMsg) - throws XMLStreamException - { - return getNextInCurrAfterWS(errorMsg, getNextCharFromCurrent(errorMsg)); - } - - protected final char getNextInCurrAfterWS(String errorMsg, char c) - throws XMLStreamException - { - while (c <= CHAR_SPACE) { - // Linefeed? - if (c == '\n' || c == '\r') { - skipCRLF(c); - } else if (c != CHAR_SPACE && c != '\t') { - throwInvalidSpace(c); - } - - // Still a white space? - if (mInputPtr >= mInputEnd) { - loadMoreFromCurrent(errorMsg); - } - c = mInputBuffer[mInputPtr++]; - } - return c; - } - - /** - * Method called when a CR has been spotted in input; checks if next - * char is LF, and if so, skips it. Note that next character has to - * come from the current input source, to qualify; it can never come - * from another (nested) input source. - * - * @return True, if passed in char is '\r' and next one is '\n'. - */ - protected final boolean skipCRLF(char c) - throws XMLStreamException - { - boolean result; - - if (c == '\r' && peekNext() == '\n') { - ++mInputPtr; - result = true; - } else { - result = false; - } - ++mCurrInputRow; - mCurrInputRowStart = mInputPtr; - return result; - } - - protected final void markLF() { - ++mCurrInputRow; - mCurrInputRowStart = mInputPtr; - } - - protected final void markLF(int inputPtr) { - ++mCurrInputRow; - mCurrInputRowStart = inputPtr; - } - - /** - * Method to push back last character read; can only be called once, - * that is, no more than one char can be guaranteed to be succesfully - * returned. - */ - protected final void pushback() { --mInputPtr; } - - /* - /////////////////////////////////////////////////////////// - // Sub-class overridable input handling methods - /////////////////////////////////////////////////////////// - */ - - /** - * Method called when an entity has been expanded (new input source - * has been created). Needs to initialize location information and change - * active input source. - * - * @param entityId Name of the entity being expanded - */ - protected void initInputSource(WstxInputSource newInput, boolean isExt, - String entityId) - throws XMLStreamException - { - mInput = newInput; - // Let's make sure new input will be read next time input is needed: - mInputPtr = 0; - mInputEnd = 0; - /* Plus, reset the input location so that'll be accurate for - * error reporting etc. - */ - mInputTopDepth = mCurrDepth; - mInput.initInputLocation(this, mCurrDepth); - - /* 21-Feb-2006, TSa: Linefeeds are NOT normalized when expanding - * internal entities (XML, 2.11) - */ - if (isExt) { - mNormalizeLFs = true; - } else { - mNormalizeLFs = false; - } - } - - /** - * Method that will try to read one or more characters from currently - * open input sources; closing input sources if necessary. - * - * @return true if reading succeeded (or may succeed), false if - * we reached EOF. - */ - protected boolean loadMore() - throws XMLStreamException - { - WstxInputSource input = mInput; - do { - /* Need to make sure offsets are properly updated for error - * reporting purposes, and do this now while previous amounts - * are still known. - */ - mCurrInputProcessed += mInputEnd; - mCurrInputRowStart -= mInputEnd; - int count; - try { - count = input.readInto(this); - if (count > 0) { - return true; - } - input.close(); - } catch (IOException ioe) { - throw constructFromIOE(ioe); - } - if (input == mRootInput) { - /* Note: no need to check entity/input nesting in this - * particular case, since it will be handled by higher level - * parsing code (results in an unexpected EOF) - */ - return false; - } - WstxInputSource parent = input.getParent(); - if (parent == null) { // sanity check! - throwNullParent(input); - } - /* 13-Feb-2006, TSa: Ok, do we violate a proper nesting constraints - * with this input block closure? - */ - if (mCurrDepth != input.getScopeId()) { - handleIncompleteEntityProblem(input); - } - - mInput = input = parent; - input.restoreContext(this); - mInputTopDepth = input.getScopeId(); - /* 21-Feb-2006, TSa: Since linefeed normalization needs to be - * suppressed for internal entity expansion, we may need to - * change the state... - */ - if (!mNormalizeLFs) { - mNormalizeLFs = !input.fromInternalEntity(); - } - // Maybe there are leftovers from that input in buffer now? - } while (mInputPtr >= mInputEnd); - - return true; - } - - protected final boolean loadMore(String errorMsg) - throws XMLStreamException - { - if (!loadMore()) { - throwUnexpectedEOF(errorMsg); - } - return true; - } - - protected boolean loadMoreFromCurrent() - throws XMLStreamException - { - // Need to update offsets properly - mCurrInputProcessed += mInputEnd; - mCurrInputRowStart -= mInputEnd; - try { - int count = mInput.readInto(this); - return (count > 0); - } catch (IOException ie) { - throw constructFromIOE(ie); - } - } - - protected final boolean loadMoreFromCurrent(String errorMsg) - throws XMLStreamException - { - if (!loadMoreFromCurrent()) { - throwUnexpectedEOB(errorMsg); - } - return true; - } - - /** - * Method called to make sure current main-level input buffer has at - * least specified number of characters available consequtively, - * without having to call {@link #loadMore}. It can only be called - * when input comes from main-level buffer; further, call can shift - * content in input buffer, so caller has to flush any data still - * pending. In short, caller has to know exactly what it's doing. :-) - *

- * Note: method does not check for any other input sources than the - * current one -- if current source can not fulfill the request, a - * failure is indicated. - * - * @return true if there's now enough data; false if not (EOF) - */ - protected boolean ensureInput(int minAmount) - throws XMLStreamException - { - int currAmount = mInputEnd - mInputPtr; - if (currAmount >= minAmount) { - return true; - } - try { - return mInput.readMore(this, minAmount); - } catch (IOException ie) { - throw constructFromIOE(ie); - } - } - - protected void closeAllInput(boolean force) - throws XMLStreamException - { - WstxInputSource input = mInput; - while (true) { - try { - if (force) { - input.closeCompletely(); - } else { - input.close(); - } - } catch (IOException ie) { - throw constructFromIOE(ie); - } - if (input == mRootInput) { - break; - } - WstxInputSource parent = input.getParent(); - if (parent == null) { // sanity check! - throwNullParent(input); - } - mInput = input = parent; - } - } - - protected void throwNullParent(WstxInputSource curr) - { - throw new IllegalStateException(ErrorConsts.ERR_INTERNAL); - //throw new IllegalStateException("Internal error: null parent for input source '"+curr+"'; should never occur (should have stopped at root input '"+mRootInput+"')."); - } - - /* - /////////////////////////////////////////////////////////// - // Entity resolution - /////////////////////////////////////////////////////////// - */ - - /** - * Method that tries to resolve a character entity, or (if caller so - * specifies), a pre-defined internal entity (lt, gt, amp, apos, quot). - * It will succeed iff: - *

    - *
  1. Entity in question is a simple character entity (either one of - * 5 pre-defined ones, or using decimal/hex notation), AND - *
  2. - *
  3. Entity fits completely inside current input buffer. - *
  4. - *
- * If so, character value of entity is returned. Character 0 is returned - * otherwise; if so, caller needs to do full resolution. - *

- * Note: On entry we are guaranteed there are at least 3 more characters - * in this buffer; otherwise we shouldn't be called. - * - * @param checkStd If true, will check pre-defined internal entities - * (gt, lt, amp, apos, quot); if false, will only check actual - * character entities. - * - * @return (Valid) character value, if entity is a character reference, - * and could be resolved from current input buffer (does not span - * buffer boundary); null char (code 0) if not (either non-char - * entity, or spans input buffer boundary). - */ - protected int resolveSimpleEntity(boolean checkStd) - throws XMLStreamException - { - char[] buf = mInputBuffer; - int ptr = mInputPtr; - char c = buf[ptr++]; - - // Numeric reference? - if (c == '#') { - c = buf[ptr++]; - int value = 0; - int inputLen = mInputEnd; - if (c == 'x') { // hex - while (ptr < inputLen) { - c = buf[ptr++]; - if (c == ';') { - break; - } - value = value << 4; - if (c <= '9' && c >= '0') { - value += (c - '0'); - } else if (c >= 'a' && c <= 'f') { - value += (10 + (c - 'a')); - } else if (c >= 'A' && c <= 'F') { - value += (10 + (c - 'A')); - } else { - mInputPtr = ptr; // so error points to correct char - throwUnexpectedChar(c, "; expected a hex digit (0-9a-fA-F)."); - } - /* Need to check for overflow; easiest to do right as - * it happens... - */ - if (value > MAX_UNICODE_CHAR) { - reportUnicodeOverflow(); - } - } - } else { // numeric (decimal) - while (c != ';') { - if (c <= '9' && c >= '0') { - value = (value * 10) + (c - '0'); - // Overflow? - if (value > MAX_UNICODE_CHAR) { - reportUnicodeOverflow(); - } - } else { - mInputPtr = ptr; // so error points to correct char - throwUnexpectedChar(c, "; expected a decimal number."); - } - if (ptr >= inputLen) { - break; - } - c = buf[ptr++]; - } - } - /* We get here either if we got it all, OR if we ran out of - * input in current buffer. - */ - if (c == ';') { // got the full thing - mInputPtr = ptr; - validateChar(value); - return value; - } - - /* If we ran out of input, need to just fall back, gets - * resolved via 'full' resolution mechanism. - */ - } else if (checkStd) { - /* Caller may not want to resolve these quite yet... - * (when it wants separate events for non-char entities) - */ - if (c == 'a') { // amp or apos? - c = buf[ptr++]; - - if (c == 'm') { // amp? - if (buf[ptr++] == 'p') { - if (ptr < mInputEnd && buf[ptr++] == ';') { - mInputPtr = ptr; - return '&'; - } - } - } else if (c == 'p') { // apos? - if (buf[ptr++] == 'o') { - int len = mInputEnd; - if (ptr < len && buf[ptr++] == 's') { - if (ptr < len && buf[ptr++] == ';') { - mInputPtr = ptr; - return '\''; - } - } - } - } - } else if (c == 'g') { // gt? - if (buf[ptr++] == 't' && buf[ptr++] == ';') { - mInputPtr = ptr; - return '>'; - } - } else if (c == 'l') { // lt? - if (buf[ptr++] == 't' && buf[ptr++] == ';') { - mInputPtr = ptr; - return '<'; - } - } else if (c == 'q') { // quot? - if (buf[ptr++] == 'u' && buf[ptr++] == 'o') { - int len = mInputEnd; - if (ptr < len && buf[ptr++] == 't') { - if (ptr < len && buf[ptr++] == ';') { - mInputPtr = ptr; - return '"'; - } - } - } - } - } - return 0; - } - - /** - * Method called to resolve character entities, and only character - * entities (except that pre-defined char entities -- amp, apos, lt, - * gt, quote -- MAY be "char entities" in this sense, depending on - * arguments). - * Otherwise it is to return the null char; if so, - * the input pointer will point to the same point as when method - * entered (char after ampersand), plus the ampersand itself is - * guaranteed to be in the input buffer (so caller can just push it - * back if necessary). - *

- * Most often this method is called when reader is not to expand - * non-char entities automatically, but to return them as separate - * events. - *

- * Main complication here is that we need to do 5-char lookahead. This - * is problematic if chars are on input buffer boundary. This is ok - * for the root level input buffer, but not for some nested buffers. - * However, according to XML specs, such split entities are actually - * illegal... so we can throw an exception in those cases. - * - * @param checkStd If true, will check pre-defined internal entities - * (gt, lt, amp, apos, quot) as character entities; if false, will only - * check actual 'real' character entities. - * - * @return (Valid) character value, if entity is a character reference, - * and could be resolved from current input buffer (does not span - * buffer boundary); null char (code 0) if not (either non-char - * entity, or spans input buffer boundary). - */ - protected int resolveCharOnlyEntity(boolean checkStd) - throws XMLStreamException - { - //int avail = inputInBuffer(); - int avail = mInputEnd - mInputPtr; - if (avail < 6) { - // split entity, or buffer boundary - /* Don't want to lose leading '&' (in case we can not expand - * the entity), so let's push it back first - */ - --mInputPtr; - /* Shortest valid reference would be 3 chars ('&a;'); which - * would only be legal from an expanded entity... - */ - if (!ensureInput(6)) { - avail = inputInBuffer(); - if (avail < 3) { - throwUnexpectedEOF(SUFFIX_IN_ENTITY_REF); - } - } else { - avail = 6; - } - // ... and now we can move pointer back as well: - ++mInputPtr; - } - - /* Ok, now we have one more character to check, and that's enough - * to determine type decisively. - */ - char c = mInputBuffer[mInputPtr]; - - // A char reference? - if (c == '#') { // yup - ++mInputPtr; - return resolveCharEnt(null); - } - - // nope... except may be a pre-def? - if (checkStd) { - if (c == 'a') { - char d = mInputBuffer[mInputPtr+1]; - if (d == 'm') { - if (avail >= 4 - && mInputBuffer[mInputPtr+2] == 'p' - && mInputBuffer[mInputPtr+3] == ';') { - mInputPtr += 4; - return '&'; - } - } else if (d == 'p') { - if (avail >= 5 - && mInputBuffer[mInputPtr+2] == 'o' - && mInputBuffer[mInputPtr+3] == 's' - && mInputBuffer[mInputPtr+4] == ';') { - mInputPtr += 5; - return '\''; - } - } - } else if (c == 'l') { - if (avail >= 3 - && mInputBuffer[mInputPtr+1] == 't' - && mInputBuffer[mInputPtr+2] == ';') { - mInputPtr += 3; - return '<'; - } - } else if (c == 'g') { - if (avail >= 3 - && mInputBuffer[mInputPtr+1] == 't' - && mInputBuffer[mInputPtr+2] == ';') { - mInputPtr += 3; - return '>'; - } - } else if (c == 'q') { - if (avail >= 5 - && mInputBuffer[mInputPtr+1] == 'u' - && mInputBuffer[mInputPtr+2] == 'o' - && mInputBuffer[mInputPtr+3] == 't' - && mInputBuffer[mInputPtr+4] == ';') { - mInputPtr += 5; - return '"'; - } - } - } - return 0; - } - - /** - * Reverse of {@link #resolveCharOnlyEntity}; will only resolve entity - * if it is NOT a character entity (or pre-defined 'generic' entity; - * amp, apos, lt, gt or quot). Only used in cases where entities - * are to be separately returned unexpanded (in non-entity-replacing - * mode); which means it's never called from dtd handler. - */ - protected EntityDecl resolveNonCharEntity() - throws XMLStreamException - { - //int avail = inputInBuffer(); - int avail = mInputEnd - mInputPtr; - if (avail < 6) { - // split entity, or buffer boundary - /* Don't want to lose leading '&' (in case we can not expand - * the entity), so let's push it back first - */ - --mInputPtr; - - /* Shortest valid reference would be 3 chars ('&a;'); which - * would only be legal from an expanded entity... - */ - if (!ensureInput(6)) { - avail = inputInBuffer(); - if (avail < 3) { - throwUnexpectedEOF(SUFFIX_IN_ENTITY_REF); - } - } else { - avail = 6; - } - // ... and now we can move pointer back as well: - ++mInputPtr; - } - - // We don't care about char entities: - char c = mInputBuffer[mInputPtr]; - if (c == '#') { - return null; - } - - /* 19-Aug-2004, TSa: Need special handling for pre-defined - * entities; they are not counted as 'real' general parsed - * entities, but more as character entities... - */ - - // have chars at least up to mInputPtr+4 by now - if (c == 'a') { - char d = mInputBuffer[mInputPtr+1]; - if (d == 'm') { - if (avail >= 4 - && mInputBuffer[mInputPtr+2] == 'p' - && mInputBuffer[mInputPtr+3] == ';') { - // If not automatically expanding: - //return sEntityAmp; - // mInputPtr += 4; - return null; - } - } else if (d == 'p') { - if (avail >= 5 - && mInputBuffer[mInputPtr+2] == 'o' - && mInputBuffer[mInputPtr+3] == 's' - && mInputBuffer[mInputPtr+4] == ';') { - return null; - } - } - } else if (c == 'l') { - if (avail >= 3 - && mInputBuffer[mInputPtr+1] == 't' - && mInputBuffer[mInputPtr+2] == ';') { - return null; - } - } else if (c == 'g') { - if (avail >= 3 - && mInputBuffer[mInputPtr+1] == 't' - && mInputBuffer[mInputPtr+2] == ';') { - return null; - } - } else if (c == 'q') { - if (avail >= 5 - && mInputBuffer[mInputPtr+1] == 'u' - && mInputBuffer[mInputPtr+2] == 'o' - && mInputBuffer[mInputPtr+3] == 't' - && mInputBuffer[mInputPtr+4] == ';') { - return null; - } - } - - // Otherwise, let's just parse in generic way: - ++mInputPtr; // since we already read the first letter - String id = parseEntityName(c); - mCurrName = id; - - return findEntity(id, null); - } - - /** - * Method that does full resolution of an entity reference, be it - * character entity, internal entity or external entity, including - * updating of input buffers, and depending on whether result is - * a character entity (or one of 5 pre-defined entities), returns - * char in question, or null character (code 0) to indicate it had - * to change input source. - * - * @param allowExt If true, is allowed to expand external entities - * (expanding text); if false, is not (expanding attribute value). - * - * @return Either single-character replacement (which is NOT to be - * reparsed), or null char (0) to indicate expansion is done via - * input source. - */ - protected int fullyResolveEntity(boolean allowExt) - throws XMLStreamException - { - char c = getNextCharFromCurrent(SUFFIX_IN_ENTITY_REF); - // Do we have a (numeric) character entity reference? - if (c == '#') { // numeric - final StringBuffer originalSurface = new StringBuffer("#"); - int ch = resolveCharEnt(originalSurface); - if (mCfgTreatCharRefsAsEntities) { - final char[] originalChars = new char[originalSurface.length()]; - originalSurface.getChars(0, originalSurface.length(), originalChars, 0); - mCurrEntity = getIntEntity(ch, originalChars); - return 0; - } - return ch; - } - - String id = parseEntityName(c); - - // Perhaps we have a pre-defined char reference? - c = id.charAt(0); - /* - * 16-May-2004, TSa: Should custom entities (or ones defined in int/ext subset) override - * pre-defined settings for these? - */ - char d = CHAR_NULL; - if (c == 'a') { // amp or apos? - if (id.equals("amp")) { - d = '&'; - } else if (id.equals("apos")) { - d = '\''; - } - } else if (c == 'g') { // gt? - if (id.length() == 2 && id.charAt(1) == 't') { - d = '>'; - } - } else if (c == 'l') { // lt? - if (id.length() == 2 && id.charAt(1) == 't') { - d = '<'; - } - } else if (c == 'q') { // quot? - if (id.equals("quot")) { - d = '"'; - } - } - - if (d != CHAR_NULL) { - if (mCfgTreatCharRefsAsEntities) { - final char[] originalChars = new char[id.length()]; - id.getChars(0, id.length(), originalChars, 0); - mCurrEntity = getIntEntity(d, originalChars); - return 0; - } - return d; - } - - final EntityDecl e = expandEntity(id, allowExt, null); - if (mCfgTreatCharRefsAsEntities) { - mCurrEntity = e; - } - return 0; - } - - /** - * Returns an entity (possibly from cache) for the argument character using the encoded - * representation in mInputBuffer[entityStartPos ... mInputPtr-1]. - */ - protected EntityDecl getIntEntity(int ch, final char[] originalChars) - { - String cacheKey = new String(originalChars); - - IntEntity entity = (IntEntity) mCachedEntities.get(cacheKey); - if (entity == null) { - String repl; - if (ch <= 0xFFFF) { - repl = Character.toString((char) ch); - } else { - StringBuffer sb = new StringBuffer(2); - ch -= 0x10000; - sb.append((char) ((ch >> 10) + 0xD800)); - sb.append((char) ((ch & 0x3FF) + 0xDC00)); - repl = sb.toString(); - } - entity = IntEntity.create(new String(originalChars), repl); - mCachedEntities.put(cacheKey, entity); - } - return entity; - } - - - /** - * Helper method that will try to expand a parsed entity (parameter or - * generic entity). - *

- * note: called by sub-classes (dtd parser), needs to be protected. - * - * @param id Name of the entity being expanded - * @param allowExt Whether external entities can be expanded or not; if - * not, and the entity to expand would be external one, an exception - * will be thrown - */ - protected EntityDecl expandEntity(String id, boolean allowExt, - Object extraArg) - throws XMLStreamException - { - mCurrName = id; - - EntityDecl ed = findEntity(id, extraArg); - - if (ed == null) { - /* 30-Sep-2005, TSa: As per [WSTX-5], let's only throw exception - * if we have to resolve it (otherwise it's just best-effort, - * and null is ok) - */ - /* 02-Oct-2005, TSa: Plus, [WSTX-4] adds "undeclared entity - * resolver" - */ - if (mCfgReplaceEntities) { - mCurrEntity = expandUnresolvedEntity(id); - } - return null; - } - - if (!mCfgTreatCharRefsAsEntities || this instanceof MinimalDTDReader) { - expandEntity(ed, allowExt); - } - - return ed; - } - - /** - * - *

- * note: defined as private for documentation, ie. it's just called - * from within this class (not sub-classes), from one specific method - * (see above) - * - * @param ed Entity to be expanded - * @param allowExt Whether external entities are allowed or not. - */ - private void expandEntity(EntityDecl ed, boolean allowExt) - throws XMLStreamException - { - String id = ed.getName(); - - /* Very first thing; we can immediately check if expanding - * this entity would result in infinite recursion: - */ - if (mInput.isOrIsExpandedFrom(id)) { - throwRecursionError(id); - } - - /* Should not refer unparsed entities from attribute values - * or text content (except via notation mechanism, but that's - * not parsed here) - */ - if (!ed.isParsed()) { - throwParseError("Illegal reference to unparsed external entity \"{0}\"", id, null); - } - - // 28-Jun-2004, TSa: Do we support external entity expansion? - boolean isExt = ed.isExternal(); - if (isExt) { - if (!allowExt) { // never ok in attribute value... - throwParseError("Encountered a reference to external parsed entity \"{0}\" when expanding attribute value: not legal as per XML 1.0/1.1 #3.1", id, null); - } - if (!mConfig.willSupportExternalEntities()) { - throwParseError("Encountered a reference to external entity \"{0}\", but stream reader has feature \"{1}\" disabled", - id, XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES); - } - } - - // First, let's give current context chance to save its stuff - WstxInputSource oldInput = mInput; - oldInput.saveContext(this); - WstxInputSource newInput = null; - try { - newInput = ed.expand(oldInput, mEntityResolver, mConfig, mDocXmlVersion); - } catch (FileNotFoundException fex) { - /* Let's catch and rethrow this just so we get more meaningful - * description (with input source position etc) - */ - throwParseError("(was {0}) {1}", fex.getClass().getName(), fex.getMessage()); - } catch (IOException ioe) { - throw constructFromIOE(ioe); - } - /* And then we'll need to make sure new input comes from the new - * input source - */ - initInputSource(newInput, isExt, id); - } - - /** - *

- * note: only called from the local expandEntity() method - */ - private EntityDecl expandUnresolvedEntity(String id) - throws XMLStreamException - { - XMLResolver resolver = mConfig.getUndeclaredEntityResolver(); - if (resolver != null) { - /* Ok, we can check for recursion here; but let's only do that - * if there is any chance that it might get resolved by - * the special resolver (it must have been resolved this way - * earlier, too...) - */ - if (mInput.isOrIsExpandedFrom(id)) { - throwRecursionError(id); - } - - WstxInputSource oldInput = mInput; - oldInput.saveContext(this); - // null, null -> no public or system ids - int xmlVersion = mDocXmlVersion; - // 05-Feb-2006, TSa: If xmlVersion not explicitly known, defaults to 1.0 - if (xmlVersion == XmlConsts.XML_V_UNKNOWN) { - xmlVersion = XmlConsts.XML_V_10; - } - WstxInputSource newInput; - try { - newInput = DefaultInputResolver.resolveEntityUsing - (oldInput, id, null, null, resolver, mConfig, xmlVersion); - if (mCfgTreatCharRefsAsEntities) { - return new IntEntity(WstxInputLocation.getEmptyLocation(), newInput.getEntityId(), - newInput.getSource(), new char[]{}, WstxInputLocation.getEmptyLocation()); - } - } catch (IOException ioe) { - throw constructFromIOE(ioe); - } - if (newInput != null) { - // true -> is external - initInputSource(newInput, true, id); - return null; - } - } - handleUndeclaredEntity(id); - return null; - } - - /* - /////////////////////////////////////////////////////////// - // Abstract methods for sub-classes to implement - /////////////////////////////////////////////////////////// - */ - - /** - * Abstract method for sub-classes to implement, for finding - * a declared general or parsed entity. - * - * @param id Identifier of the entity to find - * @param arg Optional argument passed from caller; needed by DTD - * reader. - */ - protected abstract EntityDecl findEntity(String id, Object arg) - throws XMLStreamException; - - /** - * This method gets called if a declaration for an entity was not - * found in entity expanding mode (enabled by default for xml reader, - * always enabled for dtd reader). - */ - protected abstract void handleUndeclaredEntity(String id) - throws XMLStreamException; - - protected abstract void handleIncompleteEntityProblem(WstxInputSource closing) - throws XMLStreamException; - - /* - /////////////////////////////////////////////////////////// - // Basic tokenization - /////////////////////////////////////////////////////////// - */ - - /** - * Method that will parse name token (roughly equivalent to XML specs; - * although bit lenier for more efficient handling); either uri prefix, - * or local name. - *

- * Much of complexity in this method has to do with the intention to - * try to avoid any character copies. In this optimal case algorithm - * would be fairly simple. However, this only works if all data is - * already in input buffer... if not, copy has to be made halfway - * through parsing, and that complicates things. - *

- * One thing to note is that String returned has been canonicalized - * and (if necessary) added to symbol table. It can thus be compared - * against other such (usually id) Strings, with simple equality operator. - * - * @param c First character of the name; not yet checked for validity - * - * @return Canonicalized name String (which may have length 0, if - * EOF or non-name-start char encountered) - */ - protected String parseLocalName(char c) - throws XMLStreamException - { - /* Has to start with letter, or '_' (etc); we won't allow ':' as that - * is taken as namespace separator; no use trying to optimize - * heavily as it's 98% likely it is a valid char... - */ - if (!isNameStartChar(c)) { - if (c == ':') { - throwUnexpectedChar(c, " (missing namespace prefix?)"); - } - throwUnexpectedChar(c, " (expected a name start character)"); - } - - int ptr = mInputPtr; - int hash = (int) c; - final int inputLen = mInputEnd; - int startPtr = ptr-1; // already read previous char - final char[] inputBuf = mInputBuffer; - - /* After which there may be zero or more name chars - * we have to consider - */ - while (true) { - if (ptr >= inputLen) { - /* Ok, identifier may continue past buffer end, need - * to continue with part 2 (separate method, as this is - * not as common as having it all in buffer) - */ - mInputPtr = ptr; - return parseLocalName2(startPtr, hash); - } - // Ok, we have the char... is it a name char? - c = inputBuf[ptr]; - if (c < CHAR_LOWEST_LEGAL_LOCALNAME_CHAR) { - break; - } - if (!isNameChar(c)) { - break; - } - hash = (hash * 31) + (int) c; - ++ptr; - } - mInputPtr = ptr; - return mSymbols.findSymbol(mInputBuffer, startPtr, ptr - startPtr, hash); - } - - /** - * Second part of name token parsing; called when name can continue - * past input buffer end (so only part was read before calling this - * method to read the rest). - *

- * Note that this isn't heavily optimized, on assumption it's not - * called very often. - */ - protected String parseLocalName2(int start, int hash) - throws XMLStreamException - { - int ptr = mInputEnd - start; - // Let's assume fairly short names - char[] outBuf = getNameBuffer(ptr+8); - - if (ptr > 0) { - System.arraycopy(mInputBuffer, start, outBuf, 0, ptr); - } - - int outLen = outBuf.length; - while (true) { - // note: names can not cross input block (entity) boundaries... - if (mInputPtr >= mInputEnd) { - if (!loadMoreFromCurrent()) { - break; - } - } - char c = mInputBuffer[mInputPtr]; - if (c < CHAR_LOWEST_LEGAL_LOCALNAME_CHAR) { - break; - } - if (!isNameChar(c)) { - break; - } - ++mInputPtr; - if (ptr >= outLen) { - mNameBuffer = outBuf = expandBy50Pct(outBuf); - outLen = outBuf.length; - } - outBuf[ptr++] = c; - hash = (hash * 31) + (int) c; - } - // Still need to canonicalize the name: - return mSymbols.findSymbol(outBuf, 0, ptr, hash); - } - - /** - * Method that will parse 'full' name token; what full means depends on - * whether reader is namespace aware or not. If it is, full name means - * local name with no namespace prefix (PI target, entity/notation name); - * if not, name can contain arbitrary number of colons. Note that - * element and attribute names are NOT parsed here, so actual namespace - * prefix separation can be handled properly there. - *

- * Similar to {@link #parseLocalName}, much of complexity stems from - * trying to avoid copying name characters from input buffer. - *

- * Note that returned String will be canonicalized, similar to - * {@link #parseLocalName}, but without separating prefix/local name. - * - * @return Canonicalized name String (which may have length 0, if - * EOF or non-name-start char encountered) - */ - protected String parseFullName() - throws XMLStreamException - { - if (mInputPtr >= mInputEnd) { - loadMoreFromCurrent(); - } - return parseFullName(mInputBuffer[mInputPtr++]); - } - - protected String parseFullName(char c) - throws XMLStreamException - { - // First char has special handling: - if (!isNameStartChar(c)) { - if (c == ':') { // no name.... generally an error: - if (mCfgNsEnabled) { - throwNsColonException(parseFNameForError()); - } - // Ok, that's fine actually - } else { - if (c <= CHAR_SPACE) { - throwUnexpectedChar(c, " (missing name?)"); - } - throwUnexpectedChar(c, " (expected a name start character)"); - } - } - - int ptr = mInputPtr; - int hash = (int) c; - int inputLen = mInputEnd; - int startPtr = ptr-1; // to account for the first char - - /* After which there may be zero or more name chars - * we have to consider - */ - while (true) { - if (ptr >= inputLen) { - /* Ok, identifier may continue past buffer end, need - * to continue with part 2 (separate method, as this is - * not as common as having it all in buffer) - */ - mInputPtr = ptr; - return parseFullName2(startPtr, hash); - } - c = mInputBuffer[ptr]; - if (c == ':') { // colon only allowed in non-NS mode - if (mCfgNsEnabled) { - mInputPtr = ptr; - throwNsColonException(new String(mInputBuffer, startPtr, ptr - startPtr) + parseFNameForError()); - } - } else { - if (c < CHAR_LOWEST_LEGAL_LOCALNAME_CHAR) { - break; - } - if (!isNameChar(c)) { - break; - } - } - hash = (hash * 31) + (int) c; - ++ptr; - } - mInputPtr = ptr; - return mSymbols.findSymbol(mInputBuffer, startPtr, ptr - startPtr, hash); - } - - protected String parseFullName2(int start, int hash) - throws XMLStreamException - { - int ptr = mInputEnd - start; - // Let's assume fairly short names - char[] outBuf = getNameBuffer(ptr+8); - - if (ptr > 0) { - System.arraycopy(mInputBuffer, start, outBuf, 0, ptr); - } - - int outLen = outBuf.length; - while (true) { - /* 06-Sep-2004, TSa: Name tokens are not allowed to continue - * past entity expansion ranges... that is, all characters - * have to come from the same input source. Thus, let's only - * load things from same input level - */ - if (mInputPtr >= mInputEnd) { - if (!loadMoreFromCurrent()) { - break; - } - } - char c = mInputBuffer[mInputPtr]; - if (c == ':') { // colon only allowed in non-NS mode - if (mCfgNsEnabled) { - throwNsColonException(new String(outBuf, 0, ptr) + c + parseFNameForError()); - } - } else if (c < CHAR_LOWEST_LEGAL_LOCALNAME_CHAR) { - break; - } else if (!isNameChar(c)) { - break; - } - ++mInputPtr; - - if (ptr >= outLen) { - mNameBuffer = outBuf = expandBy50Pct(outBuf); - outLen = outBuf.length; - } - outBuf[ptr++] = c; - hash = (hash * 31) + (int) c; - } - - // Still need to canonicalize the name: - return mSymbols.findSymbol(outBuf, 0, ptr, hash); - } - - /** - * Method called to read in full name, including unlimited number of - * namespace separators (':'), for the purpose of displaying name in - * an error message. Won't do any further validations, and parsing - * is not optimized: main need is just to get more meaningful error - * messages. - */ - protected String parseFNameForError() - throws XMLStreamException - { - StringBuffer sb = new StringBuffer(100); - while (true) { - char c; - - if (mInputPtr < mInputEnd) { - c = mInputBuffer[mInputPtr++]; - } else { // can't error here, so let's accept EOF for now: - int i = getNext(); - if (i < 0) { - break; - } - c = (char) i; - } - if (c != ':' && !isNameChar(c)) { - --mInputPtr; - break; - } - sb.append(c); - } - return sb.toString(); - } - - protected final String parseEntityName(char c) - throws XMLStreamException - { - String id = parseFullName(c); - // Needs to be followed by a semi-colon, too.. from same input source: - if (mInputPtr >= mInputEnd) { - if (!loadMoreFromCurrent()) { - throwParseError("Missing semicolon after reference for entity \"{0}\"", id, null); - } - } - c = mInputBuffer[mInputPtr++]; - if (c != ';') { - throwUnexpectedChar(c, "; expected a semi-colon after the reference for entity '"+id+"'"); - } - return id; - } - - /** - * Note: does not check for number of colons, amongst other things. - * Main idea is to skip through what superficially seems like a valid - * id, nothing more. This is only done when really skipping through - * something we do not care about at all: not even whether names/ids - * would be valid (for example, when ignoring internal DTD subset). - * - * @return Length of skipped name. - */ - protected int skipFullName(char c) - throws XMLStreamException - { - if (!isNameStartChar(c)) { - --mInputPtr; - return 0; - } - - /* After which there may be zero or more name chars - * we have to consider - */ - int count = 1; - while (true) { - c = (mInputPtr < mInputEnd) ? - mInputBuffer[mInputPtr++] : getNextChar(SUFFIX_EOF_EXP_NAME); - if (c != ':' && !isNameChar(c)) { - break; - } - ++count; - } - return count; - } - - /** - * Simple parsing method that parses system ids, which are generally - * used in entities (from DOCTYPE declaration to internal/external - * subsets). - *

- * NOTE: returned String is not canonicalized, on assumption that - * external ids may be longish, and are not shared all that often, as - * they are generally just used for resolving paths, if anything. - *
- * Also note that this method is not heavily optimized, as it's not - * likely to be a bottleneck for parsing. - */ - protected final String parseSystemId(char quoteChar, boolean convertLFs, - String errorMsg) - throws XMLStreamException - { - char[] buf = getNameBuffer(-1); - int ptr = 0; - - while (true) { - char c = (mInputPtr < mInputEnd) ? - mInputBuffer[mInputPtr++] : getNextChar(errorMsg); - if (c == quoteChar) { - break; - } - /* ??? 14-Jun-2004, TSa: Should we normalize linefeeds or not? - * It seems like we should, for all input... so that's the way it - * works. - */ - if (c == '\n') { - markLF(); - } else if (c == '\r') { - if (peekNext() == '\n') { - ++mInputPtr; - if (!convertLFs) { - /* The only tricky thing; need to preserve 2-char LF; need to - * output one char from here, then can fall back to default: - */ - if (ptr >= buf.length) { - buf = expandBy50Pct(buf); - } - buf[ptr++] = '\r'; - } - c = '\n'; - } else if (convertLFs) { - c = '\n'; - } - } - - // Other than that, let's just append it: - if (ptr >= buf.length) { - buf = expandBy50Pct(buf); - } - buf[ptr++] = c; - } - - return (ptr == 0) ? "" : new String(buf, 0, ptr); - } - - /** - * Simple parsing method that parses system ids, which are generally - * used in entities (from DOCTYPE declaration to internal/external - * subsets). - *

- * As per xml specs, the contents are actually normalized. - *

- * NOTE: returned String is not canonicalized, on assumption that - * external ids may be longish, and are not shared all that often, as - * they are generally just used for resolving paths, if anything. - *
- * Also note that this method is not heavily optimized, as it's not - * likely to be a bottleneck for parsing. - */ - protected final String parsePublicId(char quoteChar, String errorMsg) - throws XMLStreamException - { - char[] buf = getNameBuffer(-1); - int ptr = 0; - boolean spaceToAdd = false; - - while (true) { - char c = (mInputPtr < mInputEnd) ? - mInputBuffer[mInputPtr++] : getNextChar(errorMsg); - if (c == quoteChar) { - break; - } - if (c == '\n') { - markLF(); - spaceToAdd = true; - continue; - } else if (c == '\r') { - if (peekNext() == '\n') { - ++mInputPtr; - } - spaceToAdd = true; - continue; - } else if (c == CHAR_SPACE) { - spaceToAdd = true; - continue; - } else { - // Verify it's a legal pubid char (see XML spec, #13, from 2.3) - if ((c >= VALID_PUBID_CHAR_COUNT) - || sPubidValidity[c] != PUBID_CHAR_VALID_B) { - throwUnexpectedChar(c, " in public identifier"); - } - } - - // Other than that, let's just append it: - if (ptr >= buf.length) { - buf = expandBy50Pct(buf); - } - /* Space-normalization means scrapping leading and trailing - * white space, and coalescing remaining ws into single spaces. - */ - if (spaceToAdd) { // pending white space to add? - if (c == CHAR_SPACE) { // still a space; let's skip - continue; - } - /* ok: if we have non-space, we'll either forget about - * space(s) (if nothing has been output, ie. leading space), - * or output a single space (in-between non-white space) - */ - spaceToAdd = false; - if (ptr > 0) { - buf[ptr++] = CHAR_SPACE; - if (ptr >= buf.length) { - buf = expandBy50Pct(buf); - } - } - } - buf[ptr++] = c; - } - - return (ptr == 0) ? "" : new String(buf, 0, ptr); - } - - protected final void parseUntil(TextBuffer tb, char endChar, boolean convertLFs, - String errorMsg) - throws XMLStreamException - { - // Let's first ensure we have some data in there... - if (mInputPtr >= mInputEnd) { - loadMore(errorMsg); - } - while (true) { - // Let's loop consequtive 'easy' spans: - char[] inputBuf = mInputBuffer; - int inputLen = mInputEnd; - int ptr = mInputPtr; - int startPtr = ptr; - while (ptr < inputLen) { - char c = inputBuf[ptr++]; - if (c == endChar) { - int thisLen = ptr - startPtr - 1; - if (thisLen > 0) { - tb.append(inputBuf, startPtr, thisLen); - } - mInputPtr = ptr; - return; - } - if (c == '\n') { - mInputPtr = ptr; // markLF() requires this - markLF(); - } else if (c == '\r') { - if (!convertLFs && ptr < inputLen) { - if (inputBuf[ptr] == '\n') { - ++ptr; - } - mInputPtr = ptr; - markLF(); - } else { - int thisLen = ptr - startPtr - 1; - if (thisLen > 0) { - tb.append(inputBuf, startPtr, thisLen); - } - mInputPtr = ptr; - c = getNextChar(errorMsg); - if (c != '\n') { - --mInputPtr; // pusback - tb.append(convertLFs ? '\n' : '\r'); - } else { - if (convertLFs) { - tb.append('\n'); - } else { - tb.append('\r'); - tb.append('\n'); - } - } - startPtr = ptr = mInputPtr; - markLF(); - } - } - } - int thisLen = ptr - startPtr; - if (thisLen > 0) { - tb.append(inputBuf, startPtr, thisLen); - } - loadMore(errorMsg); - startPtr = ptr = mInputPtr; - inputBuf = mInputBuffer; - inputLen = mInputEnd; - } - } - - /* - /////////////////////////////////////////////////////////// - // Internal methods - /////////////////////////////////////////////////////////// - */ - - private int resolveCharEnt(StringBuffer originalCharacters) - throws XMLStreamException - { - int value = 0; - char c = getNextChar(SUFFIX_IN_ENTITY_REF); - - if (originalCharacters != null) { - originalCharacters.append(c); - } - - if (c == 'x') { // hex - while (true) { - c = (mInputPtr < mInputEnd) ? mInputBuffer[mInputPtr++] - : getNextCharFromCurrent(SUFFIX_IN_ENTITY_REF); - if (c == ';') { - break; - } - - if (originalCharacters != null) { - originalCharacters.append(c); - } - value = value << 4; - if (c <= '9' && c >= '0') { - value += (c - '0'); - } else if (c >= 'a' && c <= 'f') { - value += 10 + (c - 'a'); - } else if (c >= 'A' && c <= 'F') { - value += 10 + (c - 'A'); - } else { - throwUnexpectedChar(c, "; expected a hex digit (0-9a-fA-F)."); - } - // Overflow? - if (value > MAX_UNICODE_CHAR) { - reportUnicodeOverflow(); - } - } - } else { // numeric (decimal) - while (c != ';') { - if (c <= '9' && c >= '0') { - value = (value * 10) + (c - '0'); - // Overflow? - if (value > MAX_UNICODE_CHAR) { - reportUnicodeOverflow(); - } - } else { - throwUnexpectedChar(c, "; expected a decimal number."); - } - c = (mInputPtr < mInputEnd) ? mInputBuffer[mInputPtr++] - : getNextCharFromCurrent(SUFFIX_IN_ENTITY_REF); - - if (originalCharacters != null && c != ';') { - originalCharacters.append(c); - } - } - } - validateChar(value); - return value; - } - - /** - * Method that will verify that expanded Unicode codepoint is a valid - * XML content character. - */ - private final void validateChar(int value) - throws XMLStreamException - { - /* 24-Jan-2006, TSa: Ok, "high" Unicode chars are problematic, - * need to be reported by a surrogate pair.. - */ - if (value >= 0xD800) { - if (value < 0xE000) { // no surrogates via entity expansion - reportIllegalChar(value); - } - if (value > 0xFFFF) { - // Within valid range at all? - if (value > MAX_UNICODE_CHAR) { - reportUnicodeOverflow(); - } - } else if (value >= 0xFFFE) { // 0xFFFE and 0xFFFF are illegal too - reportIllegalChar(value); - } - // Ok, fine as is - } else if (value < 32) { - if (value == 0) { - throwParseError("Invalid character reference: null character not allowed in XML content."); - } - // XML 1.1 allows most other chars; 1.0 does not: - if (!mXml11 && - (value != 0x9 && value != 0xA && value != 0xD)) { - reportIllegalChar(value); - } - } - } - - protected final char[] getNameBuffer(int minSize) - { - char[] buf = mNameBuffer; - - if (buf == null) { - mNameBuffer = buf = new char[(minSize > 48) ? (minSize+16) : 64]; - } else if (minSize >= buf.length) { // let's allow one char extra... - int len = buf.length; - len += (len >> 1); // grow by 50% - mNameBuffer = buf = new char[(minSize >= len) ? (minSize+16) : len]; - } - return buf; - } - - protected final char[] expandBy50Pct(char[] buf) - { - int len = buf.length; - char[] newBuf = new char[len + (len >> 1)]; - System.arraycopy(buf, 0, newBuf, 0, len); - return newBuf; - } - - /** - * Method called to throw an exception indicating that a name that - * should not be namespace-qualified (PI target, entity/notation name) - * is one, and reader is namespace aware. - */ - private void throwNsColonException(String name) - throws XMLStreamException - { - throwParseError("Illegal name \"{0}\" (PI target, entity/notation name): can not contain a colon (XML Namespaces 1.0#6)", name, null); - } - - private void throwRecursionError(String entityName) - throws XMLStreamException - { - throwParseError("Illegal entity expansion: entity \"{0}\" expands itself recursively.", entityName, null); - } - - private void reportUnicodeOverflow() - throws XMLStreamException - { - throwParseError("Illegal character entity: value higher than max allowed (0x{0})", Integer.toHexString(MAX_UNICODE_CHAR), null); - } - - private void reportIllegalChar(int value) - throws XMLStreamException - { - throwParseError("Illegal character entity: expansion character (code 0x{0}", Integer.toHexString(value), null); - } -} diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/sr/TypedStreamReader.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/sr/TypedStreamReader.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/sr/TypedStreamReader.java 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/sr/TypedStreamReader.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,754 +0,0 @@ -/* Woodstox XML processor - * - * Copyright (c) 2004- Tatu Saloranta, tatu.saloranta@iki.fi - * - * Licensed under the License specified in file LICENSE, included with - * the source code. - * You may not use this file except in compliance with the License. - * - * 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 com.ctc.wstx.sr; - -import java.math.BigDecimal; -import java.math.BigInteger; - -import javax.xml.namespace.QName; -import javax.xml.stream.XMLStreamException; - -import org.codehaus.stax2.typed.Base64Variant; -import org.codehaus.stax2.typed.Base64Variants; -import org.codehaus.stax2.typed.TypedArrayDecoder; -import org.codehaus.stax2.typed.TypedValueDecoder; -import org.codehaus.stax2.typed.TypedXMLStreamException; - -import org.codehaus.stax2.ri.Stax2Util; -import org.codehaus.stax2.ri.typed.ValueDecoderFactory; -import org.codehaus.stax2.ri.typed.CharArrayBase64Decoder; - -import com.ctc.wstx.api.ReaderConfig; -import com.ctc.wstx.cfg.ErrorConsts; -import com.ctc.wstx.io.BranchingReaderSource; -import com.ctc.wstx.io.InputBootstrapper; -import com.ctc.wstx.io.WstxInputData; - -/** - * Complete implementation of {@link org.codehaus.stax2.XMLStreamReader2}, - * including Typed Access API (Stax2 v3.0) implementation. - * Only functionality missing is DTD validation, which is provided by a - * specialized sub-class. - */ -public class TypedStreamReader - extends BasicStreamReader -{ - /** - * Mask of event types that are legal (starting) states - * to call Typed Access API from. - * - */ - final protected static int MASK_TYPED_ACCESS_ARRAY = - (1 << START_ELEMENT) - | (1 << END_ELEMENT) // for convenience - | (1 << CHARACTERS) | (1 << CDATA) | (1 << SPACE) - // Not ok for PI or COMMENT? Let's assume so - ; - - final protected static int MASK_TYPED_ACCESS_BINARY = - (1 << START_ELEMENT) // note: END_ELEMENT handled separately - | (1 << CHARACTERS) | (1 << CDATA) | (1 << SPACE) - ; - - /** - * Minimum length of text chunks to parse before base64 decoding. - * Will try to limit it to fit within regular result buffers. - */ - final static int MIN_BINARY_CHUNK = 2000; - - /** - * Factory used for constructing decoders we need for typed access - */ - protected ValueDecoderFactory _decoderFactory; - - /** - * Lazily-constructed decoder object for decoding base64 encoded - * element binary content. - */ - protected CharArrayBase64Decoder _base64Decoder = null; - - /* - //////////////////////////////////////////////////// - // Instance construction - //////////////////////////////////////////////////// - */ - - protected TypedStreamReader(InputBootstrapper bs, - BranchingReaderSource input, ReaderCreator owner, - ReaderConfig cfg, InputElementStack elemStack, - boolean forER) - throws XMLStreamException - { - super(bs, input, owner, cfg, elemStack, forER); - } - - /** - * Factory method for constructing readers. - * - * @param owner "Owner" of this reader, factory that created the reader; - * needed for returning updated symbol table information after parsing. - * @param input Input source used to read the XML document. - * @param cfg Object that contains reader configuration info. - */ - public static TypedStreamReader createStreamReader - (BranchingReaderSource input, ReaderCreator owner, ReaderConfig cfg, - InputBootstrapper bs, boolean forER) - throws XMLStreamException - { - - TypedStreamReader sr = new TypedStreamReader - (bs, input, owner, cfg, createElementStack(cfg), forER); - return sr; - } - - - /* - //////////////////////////////////////////////////////// - // TypedXMLStreamReader2 implementation, scalar elements - //////////////////////////////////////////////////////// - */ - - public boolean getElementAsBoolean() throws XMLStreamException - { - ValueDecoderFactory.BooleanDecoder dec = _decoderFactory().getBooleanDecoder(); - getElementAs(dec); - return dec.getValue(); - } - - public int getElementAsInt() throws XMLStreamException - { - ValueDecoderFactory.IntDecoder dec = _decoderFactory().getIntDecoder(); - getElementAs(dec); - return dec.getValue(); - } - - public long getElementAsLong() throws XMLStreamException - { - ValueDecoderFactory.LongDecoder dec = _decoderFactory().getLongDecoder(); - getElementAs(dec); - return dec.getValue(); - } - - public float getElementAsFloat() throws XMLStreamException - { - ValueDecoderFactory.FloatDecoder dec = _decoderFactory().getFloatDecoder(); - getElementAs(dec); - return dec.getValue(); - } - - public double getElementAsDouble() throws XMLStreamException - { - ValueDecoderFactory.DoubleDecoder dec = _decoderFactory().getDoubleDecoder(); - getElementAs(dec); - return dec.getValue(); - } - - public BigInteger getElementAsInteger() throws XMLStreamException - { - ValueDecoderFactory.IntegerDecoder dec = _decoderFactory().getIntegerDecoder(); - getElementAs(dec); - return dec.getValue(); - } - - public BigDecimal getElementAsDecimal() throws XMLStreamException - { - ValueDecoderFactory.DecimalDecoder dec = _decoderFactory().getDecimalDecoder(); - getElementAs(dec); - return dec.getValue(); - } - - public QName getElementAsQName() throws XMLStreamException - { - ValueDecoderFactory.QNameDecoder dec = _decoderFactory().getQNameDecoder(getNamespaceContext()); - getElementAs(dec); - return _verifyQName(dec.getValue()); - } - - public final byte[] getElementAsBinary() throws XMLStreamException - { - return getElementAsBinary(Base64Variants.getDefaultVariant()); - } - - public byte[] getElementAsBinary(Base64Variant v) throws XMLStreamException - { - // note: code here is similar to Base64DecoderBase.aggregateAll(), see comments there - Stax2Util.ByteAggregator aggr = _base64Decoder().getByteAggregator(); - byte[] buffer = aggr.startAggregation(); - while (true) { - int offset = 0; - int len = buffer.length; - - do { - int readCount = readElementAsBinary(buffer, offset, len, v); - if (readCount < 1) { // all done! - return aggr.aggregateAll(buffer, offset); - } - offset += readCount; - len -= readCount; - } while (len > 0); - buffer = aggr.addFullBlock(buffer); - } - } - - public void getElementAs(TypedValueDecoder tvd) throws XMLStreamException - { - if (mCurrToken != START_ELEMENT) { - throwParseError(ErrorConsts.ERR_STATE_NOT_STELEM); - } - /* Ok, now: with START_ELEMENT we know that it's not partially - * processed; that we are in-tree (not prolog or epilog). - * The only possible complication would be: - */ - if (mStEmptyElem) { - /* And if so, we'll then get 'virtual' close tag; things - * are simple as location info was set when dealing with - * empty start element; and likewise, validation (if any) - * has been taken care of - */ - mStEmptyElem = false; - mCurrToken = END_ELEMENT; - _handleEmptyValue(tvd); - return; - } - // First need to find a textual event - while (true) { - int type = next(); - if (type == END_ELEMENT) { - _handleEmptyValue(tvd); - return; - } - if (type == COMMENT || type == PROCESSING_INSTRUCTION) { - continue; - } - if (((1 << type) & MASK_GET_ELEMENT_TEXT) == 0) { - throwParseError("Expected a text token, got "+tokenTypeDesc(type)+"."); - } - break; - } - if (mTokenState < TOKEN_FULL_SINGLE) { - readCoalescedText(mCurrToken, false); - } - /* Ok: then a quick check; if it looks like we are directly - * followed by the end tag, we need not construct String - * quite yet. - */ - if ((mInputPtr + 1) < mInputEnd && - mInputBuffer[mInputPtr] == '<' && mInputBuffer[mInputPtr+1] == '/') { - // Note: next() has validated text, no need for more validation - mInputPtr += 2; - mCurrToken = END_ELEMENT; - /* Can by-pass next(), nextFromTree(), in this case. - * However, must do decoding first, and only then call - * readEndElem(), since this latter call may invalidate - * underlying input buffer (when end tag is at buffer - * boundary) - */ - try { // buffer now has all the data - mTextBuffer.decode(tvd); - } catch (IllegalArgumentException iae) { - throw _constructTypeException(iae, mTextBuffer.contentsAsString()); - } - readEndElem(); - return; - } - - // Otherwise, we'll need to do slower processing - int extra = 1 + (mTextBuffer.size() >> 1); // let's add 50% space - StringBuffer sb = mTextBuffer.contentsAsStringBuffer(extra); - int type; - - while ((type = next()) != END_ELEMENT) { - if (((1 << type) & MASK_GET_ELEMENT_TEXT) != 0) { - if (mTokenState < TOKEN_FULL_SINGLE) { - readCoalescedText(type, false); - } - mTextBuffer.contentsToStringBuffer(sb); - continue; - } - if (type != COMMENT && type != PROCESSING_INSTRUCTION) { - throwParseError("Expected a text token, got "+tokenTypeDesc(type)+"."); - } - } - // Note: calls next() have validated text, no need for more validation - String str = sb.toString(); - String tstr = Stax2Util.trimSpaces(str); - if (tstr == null) { - _handleEmptyValue(tvd); - } else { - try { - tvd.decode(tstr); - } catch (IllegalArgumentException iae) { - throw _constructTypeException(iae, str); - } - } - } - - /* - //////////////////////////////////////////////////////// - // TypedXMLStreamReader2 implementation, array elements - //////////////////////////////////////////////////////// - */ - - public int readElementAsIntArray(int[] value, int from, int length) throws XMLStreamException - { - return readElementAsArray(_decoderFactory().getIntArrayDecoder(value, from, length)); - } - - public int readElementAsLongArray(long[] value, int from, int length) throws XMLStreamException - { - return readElementAsArray(_decoderFactory().getLongArrayDecoder(value, from, length)); - } - - public int readElementAsFloatArray(float[] value, int from, int length) throws XMLStreamException - { - return readElementAsArray(_decoderFactory().getFloatArrayDecoder(value, from, length)); - } - - public int readElementAsDoubleArray(double[] value, int from, int length) throws XMLStreamException - { - return readElementAsArray(_decoderFactory().getDoubleArrayDecoder(value, from, length)); - } - - /** - * Method called to parse array of primitives. - *

- * !!! 05-Sep-2008, tatu: Current implementation is not optimal - * either performance-wise, or from getting accurate Location - * for decoding problems. But it works otherwise, and we need - * to get Woodstox 4.0 out by the end of the year... so it'll - * do, for now. - * - * @return Number of elements decoded (if any were decoded), or - * -1 to indicate that no more values can be decoded. - */ - public final int readElementAsArray(TypedArrayDecoder dec) - throws XMLStreamException - { - int type = mCurrToken; - // First things first: must be acceptable start state: - if (((1 << type) & MASK_TYPED_ACCESS_ARRAY) == 0) { - throwNotTextualOrElem(type); - } - - // Are we just starting (START_ELEMENT)? - if (type == START_ELEMENT) { - // Empty? Not common, but can short-cut handling if occurs - if (mStEmptyElem) { - mStEmptyElem = false; - mCurrToken = END_ELEMENT; - return -1; - } - // Otherwise let's just find the first text segment - while (true) { - type = next(); - if (type == END_ELEMENT) { - // Simple... no textul content - return -1; - } - if (type == COMMENT || type == PROCESSING_INSTRUCTION) { - continue; - } - if (type == CHARACTERS || type == CDATA) { - break; - } - // otherwise just not legal (how about SPACE, unexpanded entities?) - throw _constructUnexpectedInTyped(type); - } - } - - int count = 0; - while (type != END_ELEMENT) { - /* Ok then: we will have a valid textual type. Just need to - * ensure current segment is completed. Plus, for current impl, - * also need to coalesce to prevent artificial CDATA/text - * boundary from splitting tokens - */ - if (type == CHARACTERS || type == CDATA || type == SPACE) { - if (mTokenState < TOKEN_FULL_SINGLE) { - readCoalescedText(type, false); - } - } else if (type == COMMENT || type == PROCESSING_INSTRUCTION) { - type = next(); - continue; - } else { - throw _constructUnexpectedInTyped(type); - } - count += mTextBuffer.decodeElements(dec, this); - if (!dec.hasRoom()) { - break; - } - type = next(); - } - - // If nothing was found, needs to be indicated via -1, not 0 - return (count > 0) ? count : -1; - } - - /* - //////////////////////////////////////////////////////// - // TypedXMLStreamReader2 implementation, binary data - //////////////////////////////////////////////////////// - */ - - public final int readElementAsBinary(byte[] resultBuffer, int offset, int maxLength) - throws XMLStreamException - { - return readElementAsBinary(resultBuffer, offset, maxLength, Base64Variants.getDefaultVariant()); - } - - public int readElementAsBinary(byte[] resultBuffer, int offset, int maxLength, Base64Variant v) - throws XMLStreamException - { - if (resultBuffer == null) { - throw new IllegalArgumentException("resultBuffer is null"); - } - if (offset < 0) { - throw new IllegalArgumentException("Illegal offset ("+offset+"), must be [0, "+resultBuffer.length+"["); - } - if (maxLength < 1 || (offset + maxLength) > resultBuffer.length) { - if (maxLength == 0) { // special case, allowed, but won't do anything - return 0; - } - throw new IllegalArgumentException("Illegal maxLength ("+maxLength+"), has to be positive number, and offset+maxLength can not exceed"+resultBuffer.length); - } - - final CharArrayBase64Decoder dec = _base64Decoder(); - int type = mCurrToken; - // First things first: must be acceptable start state: - if (((1 << type) & MASK_TYPED_ACCESS_BINARY) == 0) { - if (type == END_ELEMENT) { - // Minor complication: may have unflushed stuff (non-padded versions) - if (!dec.hasData()) { - return -1; - } - } else { - throwNotTextualOrElem(type); - } - } else if (type == START_ELEMENT) { // just starting (START_ELEMENT)? - if (mStEmptyElem) { // empty element? simple... - mStEmptyElem = false; - mCurrToken = END_ELEMENT; - return -1; - } - // Otherwise let's just find the first text segment - while (true) { - type = next(); - if (type == END_ELEMENT) { - // Simple... no textual content - return -1; - } - if (type == COMMENT || type == PROCESSING_INSTRUCTION) { - continue; - } - /* 12-Dec-2009, tatu: Important: in coalescing mode we may - * have incomplete segment that needs to be completed - */ - if (mTokenState < mStTextThreshold) { - finishToken(false); - } - _initBinaryChunks(v, dec, type, true); - break; - } - } - - int totalCount = 0; - - main_loop: - while (true) { - // Ok, decode: - int count; - try { - count = dec.decode(resultBuffer, offset, maxLength); - } catch (IllegalArgumentException iae) { - // !!! 26-Sep-2008, tatus: should try to figure out which char (etc) triggered problem to pass with typed exception - throw _constructTypeException(iae.getMessage(), ""); - } - offset += count; - totalCount += count; - maxLength -= count; - - /* And if we filled the buffer we are done. Or, an edge - * case: reached END_ELEMENT (for non-padded variant) - */ - if (maxLength < 1 || mCurrToken == END_ELEMENT) { - break; - } - // Otherwise need to advance to the next event - while (true) { - type = next(); - if (type == COMMENT || type == PROCESSING_INSTRUCTION - || type == SPACE) { // space is ignorable too - continue; - } - if (type == END_ELEMENT) { - /* Just need to verify we don't have partial stuff - * (missing one to three characters of a full quartet - * that encodes 1 - 3 bytes). Also: non-padding - * variants can be in incomplete state, from which - * data may need to be flushed... - */ - int left = dec.endOfContent(); - if (left < 0) { // incomplete, error - throw _constructTypeException("Incomplete base64 triplet at the end of decoded content", ""); - } else if (left > 0) { // 1 or 2 more bytes of data, loop some more - continue main_loop; - } - // Otherwise, no more data, we are done - break main_loop; - } - /* 12-Dec-2009, tatu: Important: in coalescing mode we may - * have incomplete segment that needs to be completed - */ - if (mTokenState < mStTextThreshold) { - finishToken(false); - } - _initBinaryChunks(v, dec, type, false); - break; - } - } - - // If nothing was found, needs to be indicated via -1, not 0 - return (totalCount > 0) ? totalCount : -1; - } - - private final void _initBinaryChunks(Base64Variant v, CharArrayBase64Decoder dec, int type, boolean isFirst) - throws XMLStreamException - { - if (type == CHARACTERS) { - if (mTokenState < mStTextThreshold) { - mTokenState = readTextSecondary(MIN_BINARY_CHUNK, false) - ? TOKEN_FULL_SINGLE : TOKEN_PARTIAL_SINGLE; - } - } else if (type == CDATA) { - if (mTokenState < mStTextThreshold) { - mTokenState = readCDataSecondary(MIN_BINARY_CHUNK) - ? TOKEN_FULL_SINGLE : TOKEN_PARTIAL_SINGLE; - } - } else { - throw _constructUnexpectedInTyped(type); - } - mTextBuffer.initBinaryChunks(v, dec, isFirst); - } - - /* - /////////////////////////////////////////////////////////// - // TypedXMLStreamReader2 implementation, scalar attributes - /////////////////////////////////////////////////////////// - */ - - public int getAttributeIndex(String namespaceURI, String localName) - { - // Note: cut'n pasted from "getAttributeInfo()" - if (mCurrToken != START_ELEMENT) { - throw new IllegalStateException(ErrorConsts.ERR_STATE_NOT_STELEM); - } - return mElementStack.findAttributeIndex(namespaceURI, localName); - } - - public boolean getAttributeAsBoolean(int index) throws XMLStreamException - { - ValueDecoderFactory.BooleanDecoder dec = _decoderFactory().getBooleanDecoder(); - getAttributeAs(index, dec); - return dec.getValue(); - } - - public int getAttributeAsInt(int index) throws XMLStreamException - { - ValueDecoderFactory.IntDecoder dec = _decoderFactory().getIntDecoder(); - getAttributeAs(index, dec); - return dec.getValue(); - } - - public long getAttributeAsLong(int index) throws XMLStreamException - { - ValueDecoderFactory.LongDecoder dec = _decoderFactory().getLongDecoder(); - getAttributeAs(index, dec); - return dec.getValue(); - } - - public float getAttributeAsFloat(int index) throws XMLStreamException - { - ValueDecoderFactory.FloatDecoder dec = _decoderFactory().getFloatDecoder(); - getAttributeAs(index, dec); - return dec.getValue(); - } - - public double getAttributeAsDouble(int index) throws XMLStreamException - { - ValueDecoderFactory.DoubleDecoder dec = _decoderFactory().getDoubleDecoder(); - getAttributeAs(index, dec); - return dec.getValue(); - } - - public BigInteger getAttributeAsInteger(int index) throws XMLStreamException - { - ValueDecoderFactory.IntegerDecoder dec = _decoderFactory().getIntegerDecoder(); - getAttributeAs(index, dec); - return dec.getValue(); - } - - public BigDecimal getAttributeAsDecimal(int index) throws XMLStreamException - { - ValueDecoderFactory.DecimalDecoder dec = _decoderFactory().getDecimalDecoder(); - getAttributeAs(index, dec); - return dec.getValue(); - } - - public QName getAttributeAsQName(int index) throws XMLStreamException - { - ValueDecoderFactory.QNameDecoder dec = _decoderFactory().getQNameDecoder(getNamespaceContext()); - getAttributeAs(index, dec); - return _verifyQName(dec.getValue()); - } - - public void getAttributeAs(int index, TypedValueDecoder tvd) throws XMLStreamException - { - if (mCurrToken != START_ELEMENT) { - throw new IllegalStateException(ErrorConsts.ERR_STATE_NOT_STELEM); - } - try { - mAttrCollector.decodeValue(index, tvd); - } catch (IllegalArgumentException iae) { - throw _constructTypeException(iae, mAttrCollector.getValue(index)); - } - } - - public int[] getAttributeAsIntArray(int index) throws XMLStreamException - { - ValueDecoderFactory.IntArrayDecoder dec = _decoderFactory().getIntArrayDecoder(); - getAttributeAsArray(index, dec); - return dec.getValues(); - } - - public long[] getAttributeAsLongArray(int index) throws XMLStreamException - { - ValueDecoderFactory.LongArrayDecoder dec = _decoderFactory().getLongArrayDecoder(); - getAttributeAsArray(index, dec); - return dec.getValues(); - } - - public float[] getAttributeAsFloatArray(int index) throws XMLStreamException - { - ValueDecoderFactory.FloatArrayDecoder dec = _decoderFactory().getFloatArrayDecoder(); - getAttributeAsArray(index, dec); - return dec.getValues(); - } - - public double[] getAttributeAsDoubleArray(int index) throws XMLStreamException - { - ValueDecoderFactory.DoubleArrayDecoder dec = _decoderFactory().getDoubleArrayDecoder(); - getAttributeAsArray(index, dec); - return dec.getValues(); - } - - /** - * Method that allows reading contents of an attribute as an array - * of whitespace-separate tokens, decoded using specified decoder. - * - * @return Number of tokens decoded, 0 if none found - */ - public int getAttributeAsArray(int index, TypedArrayDecoder tad) throws XMLStreamException - { - if (mCurrToken != START_ELEMENT) { - throw new IllegalStateException(ErrorConsts.ERR_STATE_NOT_STELEM); - } - return mAttrCollector.decodeValues(index, tad, this); - } - - public byte[] getAttributeAsBinary(int index) throws XMLStreamException - { - return getAttributeAsBinary(index, Base64Variants.getDefaultVariant()); - } - - public byte[] getAttributeAsBinary(int index, Base64Variant v) throws XMLStreamException - { - return mAttrCollector.decodeBinary(index, v, _base64Decoder(), this); - } - - /* - ///////////////////////////////////////////////////// - // Internal helper methods - ///////////////////////////////////////////////////// - */ - - /** - * Method called to verify validity of the parsed QName element - * or attribute value. At this point binding of a prefixed name - * (if qname has a prefix) has been verified, and thereby prefix - * also must be valid (since there must have been a preceding - * declaration). But local name might still not be a legal - * well-formed xml name, so let's verify that. - */ - protected QName _verifyQName(QName n) - throws TypedXMLStreamException - { - String ln = n.getLocalPart(); - int ix = WstxInputData.findIllegalNameChar(ln, mCfgNsEnabled, mXml11); - if (ix >= 0) { - String prefix = n.getPrefix(); - String pname = (prefix != null && prefix.length() > 0) ? - (prefix + ":" +ln) : ln; - throw _constructTypeException("Invalid local name \""+ln+"\" (character at #"+ix+" is invalid)", pname); - } - return n; - } - - protected ValueDecoderFactory _decoderFactory() - { - if (_decoderFactory == null) { - _decoderFactory = new ValueDecoderFactory(); - } - return _decoderFactory; - } - - protected CharArrayBase64Decoder _base64Decoder() - { - if (_base64Decoder == null) { - _base64Decoder = new CharArrayBase64Decoder(); - } - return _base64Decoder; - } - - /** - * Method called to handle value that has empty String - * as representation. This will usually either lead to an - * exception, or parsing to the default value for the - * type in question (null for nullable types and so on). - */ - private void _handleEmptyValue(TypedValueDecoder dec) - throws XMLStreamException - { - try { // default action is to throw an exception - dec.handleEmptyValue(); - } catch (IllegalArgumentException iae) { - throw _constructTypeException(iae, ""); - } - } - - /** - * Method called to wrap or convert given conversion-fail exception - * into a full {@link TypedXMLStreamException}, - * - * @param iae Problem as reported by converter - * @param lexicalValue Lexical value (element content, attribute value) - * that could not be converted succesfully. - */ - protected TypedXMLStreamException _constructTypeException(IllegalArgumentException iae, String lexicalValue) - { - return new TypedXMLStreamException(lexicalValue, iae.getMessage(), getStartLocation(), iae); - } -} - diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/sr/ValidatingStreamReader.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/sr/ValidatingStreamReader.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/sr/ValidatingStreamReader.java 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/sr/ValidatingStreamReader.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,641 +0,0 @@ -/* Woodstox XML processor - * - * Copyright (c) 2004- Tatu Saloranta, tatu.saloranta@iki.fi - * - * Licensed under the License specified in the file LICENSE which is - * included with the source code. - * You may not use this file except in compliance with the License. - * - * 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 com.ctc.wstx.sr; - -import java.io.FileNotFoundException; -import java.io.IOException; -import java.net.URI; -import java.net.URISyntaxException; -import java.net.URL; -import java.util.*; - -import javax.xml.stream.XMLStreamException; - -import org.codehaus.stax2.XMLInputFactory2; -import org.codehaus.stax2.validation.*; - -import com.ctc.wstx.api.ReaderConfig; -import com.ctc.wstx.cfg.ErrorConsts; -import com.ctc.wstx.cfg.XmlConsts; -import com.ctc.wstx.io.*; -import com.ctc.wstx.dtd.DTDId; -import com.ctc.wstx.dtd.DTDSubset; -import com.ctc.wstx.dtd.DTDValidatorBase; -import com.ctc.wstx.dtd.FullDTDReader; -import com.ctc.wstx.util.URLUtil; - -/** - * Implementation of {@link org.codehaus.stax2.XMLStreamReader2} - * that builds on {@link TypedStreamReader} and adds full DTD-handling - * including DTD validation - * - * @author Tatu Saloranta - * @author Benson Margulies - */ -public class ValidatingStreamReader - extends TypedStreamReader -{ - /* - /////////////////////////////////////////////////////////////////////// - // Constants for standard StAX properties: - /////////////////////////////////////////////////////////////////////// - */ - - final static String STAX_PROP_ENTITIES = "javax.xml.stream.entities"; - - final static String STAX_PROP_NOTATIONS = "javax.xml.stream.notations"; - - /* - /////////////////////////////////////////////////////////////////////// - // Validation (DTD) information (entities, ...) - /////////////////////////////////////////////////////////////////////// - */ - - // // // Note: some members that logically belong here, are actually - // // // part of superclass - - /** - * Combined DTD set, constructed from parsed internal and external - * entities (which may have been set via override DTD functionality). - */ - DTDValidationSchema mDTD = null; - - /** - * Validating reader keeps of automatically created DTD-based - * validator, since its handling may differ from that of application - * managed validators. - */ - XMLValidator mAutoDtdValidator = null; - - /** - * Flag that indicates whether a DTD validator has been automatically - * set (as per DOCTYPE declaration or override) - */ - boolean mDtdValidatorSet = false; - - /** - * Custom validation problem handler, if any. - */ - protected ValidationProblemHandler mVldProbHandler = null; - - /* - /////////////////////////////////////////////////////////////////////// - // Life-cycle (ctors) - /////////////////////////////////////////////////////////////////////// - */ - - private ValidatingStreamReader(InputBootstrapper bs, - BranchingReaderSource input, ReaderCreator owner, - ReaderConfig cfg, InputElementStack elemStack, - boolean forER) - throws XMLStreamException - { - super(bs, input, owner, cfg, elemStack, forER); - } - - /** - * Factory method for constructing readers. - * - * @param owner "Owner" of this reader, factory that created the reader; - * needed for returning updated symbol table information after parsing. - * @param input Input source used to read the XML document. - * @param cfg Object that contains reader configuration info. - * @param bs Bootstrapper to use, for reading xml declaration etc. - * @param forER True if this reader is to be (configured to be) used by - * an event reader. Will cause some changes to default settings, as - * required by contracts Woodstox XMLEventReader implementation has - * (with respect to lazy parsing, short text segments etc) - */ - public static ValidatingStreamReader createValidatingStreamReader - (BranchingReaderSource input, ReaderCreator owner, - ReaderConfig cfg, InputBootstrapper bs, boolean forER) - throws XMLStreamException - { - ValidatingStreamReader sr = new ValidatingStreamReader - (bs, input, owner, cfg, createElementStack(cfg), forER); - return sr; - } - - /* - /////////////////////////////////////////////////////////////////////// - // Public API, configuration - /////////////////////////////////////////////////////////////////////// - */ - - public Object getProperty(String name) - { - // DTD-specific properties... - if (name.equals(STAX_PROP_ENTITIES)) { - safeEnsureFinishToken(); - if (mDTD == null || !(mDTD instanceof DTDSubset)) { - return null; - } - List l = ((DTDSubset) mDTD).getGeneralEntityList(); - /* Let's make a copy, so that caller can not modify - * DTD's internal list instance - */ - return new ArrayList(l); - } - if (name.equals(STAX_PROP_NOTATIONS)) { - safeEnsureFinishToken(); - if (mDTD == null || !(mDTD instanceof DTDSubset)) { - return null; - } - /* Let's make a copy, so that caller can not modify - * DTD's internal list instance - */ - List l = ((DTDSubset) mDTD).getNotationList(); - return new ArrayList(l); - } - return super.getProperty(name); - } - - /* - /////////////////////////////////////////////////////////////////////// - // XMLStreamReader2 (StAX2) implementation - /////////////////////////////////////////////////////////////////////// - */ - - // // // StAX2, per-reader configuration - - // no additional readable features - //public Object getFeature(String name) - - public void setFeature(String name, Object value) - { - // Referring to DTD-related features? - if (name.equals(FEATURE_DTD_OVERRIDE)) { - /* !!! 06-Feb-2007, TSa: Null with 4.0 will actually mean - * 'remove any overrides'; which is different from earlier - * meaning (which was use a dummy/empty override). - * Should we throw an exception, or warn, or something...? - */ - if (value != null && !(value instanceof DTDValidationSchema)) { - throw new IllegalArgumentException("Value to set for feature "+name+" not of type DTDValidationSchema"); - } - mConfig.setProperty(XMLInputFactory2.P_DTD_OVERRIDE, (DTDValidationSchema) value); - } else { - super.setFeature(name, value); - } - } - - /* - /////////////////////////////////////////////////////////////////////// - // DTDInfo implementation (StAX 2) - /////////////////////////////////////////////////////////////////////// - */ - - public Object getProcessedDTD() { - return getProcessedDTDSchema(); - } - - public DTDValidationSchema getProcessedDTDSchema() { - DTDValidationSchema dtd = mConfig.getDTDOverride(); - if (dtd == null) { - dtd = mDTD; - } - return mDTD; - } - - /* - /////////////////////////////////////////////////////////////////////// - // Stax2 validation - /////////////////////////////////////////////////////////////////////// - */ - - // @Override - public XMLValidator validateAgainst(XMLValidationSchema schema) - throws XMLStreamException - { - return mElementStack.validateAgainst(schema); - } - - // @Override - public XMLValidator stopValidatingAgainst(XMLValidationSchema schema) - throws XMLStreamException - { - return mElementStack.stopValidatingAgainst(schema); - } - - // @Override - public XMLValidator stopValidatingAgainst(XMLValidator validator) - throws XMLStreamException - { - return mElementStack.stopValidatingAgainst(validator); - } - - // @Override - public ValidationProblemHandler setValidationProblemHandler(ValidationProblemHandler h) - { - ValidationProblemHandler oldH = mVldProbHandler; - mVldProbHandler = h; - return oldH; - } - - /* - /////////////////////////////////////////////////////////////////////// - // Private methods, DOCTYPE handling - /////////////////////////////////////////////////////////////////////// - */ - - /** - * This method gets called to handle remainder of DOCTYPE declaration, - * essentially the optional internal subset. Internal subset, if such - * exists, is always read, but whether its contents are added to the - * read buffer depend on passed-in argument. - *

- * NOTE: Since this method overrides the default implementation, make - * sure you do NOT change the method signature. - * - * @param copyContents If true, will copy contents of the internal - * subset of DOCTYPE declaration - * in the text buffer (in addition to parsing it for actual use); if - * false, will only do parsing. - */ - protected void finishDTD(boolean copyContents) - throws XMLStreamException - { - if (!hasConfigFlags(CFG_SUPPORT_DTD)) { - super.finishDTD(copyContents); - return; - } - - /* We know there are no spaces, as this char was read and pushed - * back earlier... - */ - char c = getNextChar(SUFFIX_IN_DTD); - DTDSubset intSubset = null; - - /* Do we have an internal subset? Note that we have earlier checked - * that it has to be either '[' or closing '>'. - */ - if (c == '[') { - // Do we need to copy the contents of int. subset in the buffer? - if (copyContents) { - ((BranchingReaderSource) mInput).startBranch(mTextBuffer, mInputPtr, mNormalizeLFs); - } - - try { - intSubset = FullDTDReader.readInternalSubset(this, mInput, mConfig, - hasConfigFlags(CFG_VALIDATE_AGAINST_DTD), - mDocXmlVersion); - } finally { - /* Let's close branching in any and every case (may allow - * graceful recovery in error cases in future - */ - if (copyContents) { - /* Need to "push back" ']' got in the succesful case - * (that's -1 part below); - * in error case it'll just be whatever last char was. - */ - ((BranchingReaderSource) mInput).endBranch(mInputPtr-1); - } - } - - // And then we need closing '>' - c = getNextCharAfterWS(SUFFIX_IN_DTD_INTERNAL); - } - - if (c != '>') { - throwUnexpectedChar(c, "; expected '>' to finish DOCTYPE declaration."); - } - - /* But, then, we also may need to read the external subset, if - * one was defined: - */ - /* 19-Sep-2004, TSa: That does not need to be done, however, if - * there's a DTD override set. - */ - - mDTD = mConfig.getDTDOverride(); - if (mDTD != null) { - // We have earlier override that's already parsed - } else { // Nope, no override - DTDSubset extSubset = null; - - /* 05-Mar-2006, TSa: If standalone was specified as "yes", we - * should not rely on any external declarations, so shouldn't - * we really just skip the external subset? - */ - /* Alas: SAX (Xerces) still tries to read it... should we - * do the Right Thing, or follow the leader? For now, let's - * just follow the wrong example. - */ - - //if (mDocStandalone != DOC_STANDALONE_YES) { - if (true) { - if (mDtdPublicId != null || mDtdSystemId != null) { - extSubset = findDtdExtSubset(mDtdPublicId, mDtdSystemId, intSubset); - } - } - if (intSubset == null) { - mDTD = extSubset; - } else if (extSubset == null) { - mDTD = intSubset; - } else { - mDTD = intSubset.combineWithExternalSubset(this, extSubset); - } - } - - - if (mDTD == null) { // only if specifically overridden not to have any - mGeneralEntities = null; - } else { - if (mDTD instanceof DTDSubset) { - mGeneralEntities = ((DTDSubset) mDTD).getGeneralEntityMap(); - } else { - /* Also, let's warn if using non-native DTD implementation, - * since entities and notations can not be accessed - */ - _reportProblem(mConfig.getXMLReporter(), ErrorConsts.WT_DT_DECL, - "Value to set for feature "+FEATURE_DTD_OVERRIDE+" not a native Woodstox DTD implementation (but "+mDTD.getClass()+"): can not access full entity or notation information", null); - } - /* 16-Jan-2006, TSa: Actually, we have both fully-validating mode, - * and non-validating-but-DTD-aware mode. In latter case, we'll - * still need to add a validator, but just to get type info - * and to add attribute default values if necessary. - */ - mAutoDtdValidator = mDTD.createValidator(/*(ValidationContext)*/ mElementStack); - mDtdValidatorSet = true; // so we won't get nags - NsDefaultProvider nsDefs = null; - if (mAutoDtdValidator instanceof DTDValidatorBase) { - DTDValidatorBase dtdv = (DTDValidatorBase) mAutoDtdValidator; - dtdv.setAttrValueNormalization(true); - // Do we have any attribute defaults for 'xmlns' or 'xmlns:*'? - if (dtdv.hasNsDefaults()) { - nsDefs = dtdv; - } - } - mElementStack.setAutomaticDTDValidator(mAutoDtdValidator, nsDefs); - } - } - - /** - * If there is an error handler established, call it. - */ - // @Override - public void reportValidationProblem(XMLValidationProblem prob) - throws XMLStreamException - { - if (mVldProbHandler != null) { - // Fix for [WSTX-209] - mVldProbHandler.reportProblem(prob); - } else { - super.reportValidationProblem(prob); - } - } - - /** - * Method called right before handling the root element, by the base - * class. This allows for some initialization and checks to be done - * (not including ones that need access to actual element name) - */ - protected void initValidation() - throws XMLStreamException - { - if (hasConfigFlags(CFG_VALIDATE_AGAINST_DTD) - && !mDtdValidatorSet) { - /* It's ok to miss it, but it may not be what caller wants. Either - * way, let's pass the info and continue - */ - reportProblem(null, ErrorConsts.WT_DT_DECL, ErrorConsts.W_MISSING_DTD, null, null); - } - } - - /* - /////////////////////////////////////////////////////////////////////// - // Private methods, external subset access - /////////////////////////////////////////////////////////////////////// - */ - - /** - * Method called by finishDTD, to locate the specified - * external DTD subset. Subset may be obtained from a cache, if cached - * copy exists and is compatible; if not, it will be read from the - * source identified by the public and/or system identifier passed. - */ - private DTDSubset findDtdExtSubset(String pubId, String sysId, - DTDSubset intSubset) - throws XMLStreamException - { - boolean cache = hasConfigFlags(CFG_CACHE_DTDS); - DTDId dtdId; - try { - dtdId = constructDtdId(pubId, sysId); - } catch (IOException ioe) { - throw constructFromIOE(ioe); - } - - if (cache) { - DTDSubset extSubset = findCachedSubset(dtdId, intSubset); - if (extSubset != null) { - return extSubset; - } - } - - // No useful cached copy? Need to read it then. - /* For now, we do require system identifier; otherwise we don't - * know how to resolve DTDs by public id. In future should - * probably also have some simple catalog resolving facility? - */ - if (sysId == null) { - throwParseError("Can not resolve DTD with public id \"{0}\"; missing system identifier", mDtdPublicId, null); - } - WstxInputSource src = null; - - try { - int xmlVersion = mDocXmlVersion; - // 05-Feb-2006, TSa: If xmlVersion not explicitly known, defaults to 1.0 - if (xmlVersion == XmlConsts.XML_V_UNKNOWN) { - xmlVersion = XmlConsts.XML_V_10; - } - /* null -> no explicit path context, use parent's - * null -> not an entity expansion, no name. - * Note, too, that we can NOT just pass mEntityResolver, since - * that's the one used for general entities, whereas ext subset - * should be resolved by the param entity resolver. - */ - src = DefaultInputResolver.resolveEntity - (mInput, null, null, pubId, sysId, mConfig.getDtdResolver(), - mConfig, xmlVersion); - } catch (FileNotFoundException fex) { - /* Let's catch and rethrow this just so we get more meaningful - * description (with input source position etc) - */ - throwParseError("(was {0}) {1}", fex.getClass().getName(), fex.getMessage()); - } catch (IOException ioe) { - throwFromIOE(ioe); - } - - DTDSubset extSubset = FullDTDReader.readExternalSubset(src, mConfig, intSubset, - hasConfigFlags(CFG_VALIDATE_AGAINST_DTD), - mDocXmlVersion); - - if (cache) { - /* Ok; can be cached, but only if it does NOT refer to - * parameter entities defined in the internal subset (if - * it does, there's no easy/efficient to check if it could - * be used later on, plus it's unlikely it could be) - */ - if (extSubset.isCachable()) { - mOwner.addCachedDTD(dtdId, extSubset); - } - } - - return extSubset; - } - - private DTDSubset findCachedSubset(DTDId id, DTDSubset intSubset) - throws XMLStreamException - { - DTDSubset extSubset = mOwner.findCachedDTD(id); - /* Ok, now; can use the cached copy iff it does not refer to - * any parameter entities internal subset (if one exists) - * defines: - */ - if (extSubset != null) { - if (intSubset == null || extSubset.isReusableWith(intSubset)) { - return extSubset; - } - } - return null; - } - - /** - * Method called to resolve path to external DTD subset, given - * system identifier. - */ - private URI resolveExtSubsetPath(String systemId) throws IOException - { - // Do we have a context to use for resolving? - URL ctxt = (mInput == null) ? null : mInput.getSource(); - - /* Ok, either got a context or not; let's create the URL based on - * the id, and optional context: - */ - if (ctxt == null) { - /* Call will try to figure out if system id has the protocol - * in it; if not, create a relative file, if it does, try to - * resolve it. - */ - return URLUtil.uriFromSystemId(systemId); - } - URL url = URLUtil.urlFromSystemId(systemId, ctxt); - try { - return new URI(url.toExternalForm()); - } catch (URISyntaxException e) { // should never occur... - throw new IOException("Failed to construct URI for external subset, URL = "+url.toExternalForm()+": "+e.getMessage()); - } - } - - protected DTDId constructDtdId(String pubId, String sysId) - throws IOException - { - /* Following settings will change what gets stored as DTD, so - * they need to separate cached instances too: - */ - int significantFlags = mConfigFlags & - (CFG_NAMESPACE_AWARE - /* Let's optimize non-validating case; DTD info we need - * is less if so (no need to store content specs for one)... - * plus, eventual functionality may be different too. - */ - | CFG_VALIDATE_AGAINST_DTD - /* Also, whether we support dtd++ or not may change construction - * of settings... (currently does not, but could) - */ - | CFG_SUPPORT_DTDPP - /* Also, basic xml:id support does matter -- xml:id attribute - * type is verified only if it's enabled - */ - | CFG_XMLID_TYPING - ); - URI sysRef = (sysId == null || sysId.length() == 0) ? null : - resolveExtSubsetPath(sysId); - - /* 29-Mar-2006, TSa: Apparently public ids are not always very - * unique and/or can be mismatched with system ids, resulting - * in false matches if using public ids. As a result, by default - * Woodstox does NOT rely on public ids, when matching. - */ - boolean usePublicId = (mConfigFlags & CFG_CACHE_DTDS_BY_PUBLIC_ID) != 0; - if (usePublicId && pubId != null && pubId.length() > 0) { - return DTDId.construct(pubId, sysRef, significantFlags, mXml11); - } - if (sysRef == null) { - return null; - } - return DTDId.constructFromSystemId(sysRef, significantFlags, mXml11); - } - - protected DTDId constructDtdId(URI sysId) - throws IOException - { - int significantFlags = mConfigFlags & - (CFG_NAMESPACE_AWARE - /* Let's optimize non-validating case; DTD info we need - * is less if so (no need to store content specs for one) - */ - | CFG_VALIDATE_AGAINST_DTD - /* Also, whether we support dtd++ or not may change construction - * of settings... (currently does not, but could) - */ - | CFG_SUPPORT_DTDPP - ); - return DTDId.constructFromSystemId(sysId, significantFlags, mXml11); - } - - /* - /////////////////////////////////////////////////////////////////////// - // Private methods, DTD validation support - /////////////////////////////////////////////////////////////////////// - */ - - /** - * Method called by lower-level parsing code when invalid content - * (anything inside element with 'empty' content spec; text inside - * non-mixed element etc) is found during basic scanning. Note - * that actual DTD element structure problems are not reported - * through this method. - */ - protected void reportInvalidContent(int evtType) - throws XMLStreamException - { - switch (mVldContent) { - case XMLValidator.CONTENT_ALLOW_NONE: - reportValidationProblem(ErrorConsts.ERR_VLD_EMPTY, - mElementStack.getTopElementDesc(), - ErrorConsts.tokenTypeDesc(evtType)); - break; - case XMLValidator.CONTENT_ALLOW_WS: - case XMLValidator.CONTENT_ALLOW_WS_NONSTRICT: // should this ever occur? - reportValidationProblem(ErrorConsts.ERR_VLD_NON_MIXED, - mElementStack.getTopElementDesc(), null); - break; - case XMLValidator.CONTENT_ALLOW_VALIDATABLE_TEXT: - case XMLValidator.CONTENT_ALLOW_ANY_TEXT: - /* Not 100% sure if this should ever happen... depends on - * interpretation of 'any' content model? - */ - reportValidationProblem(ErrorConsts.ERR_VLD_ANY, - mElementStack.getTopElementDesc(), - ErrorConsts.tokenTypeDesc(evtType)); - break; - default: // should never occur: - throwParseError("Internal error: trying to report invalid content for "+evtType); - } - } -} diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/stax/package.html libwoodstox-java-5.1.0/src/java/com/ctc/wstx/stax/package.html --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/stax/package.html 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/stax/package.html 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ - -This package contains miscellaneous classes that implement Woodstox. - diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/stax/WstxEventFactory.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/stax/WstxEventFactory.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/stax/WstxEventFactory.java 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/stax/WstxEventFactory.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,118 +0,0 @@ -/* Woodstox XML processor - * - * Copyright (c) 2004 Tatu Saloranta, tatu.saloranta@iki.fi - * - * Licensed under the License specified in file LICENSE, included with - * the source code. - * You may not use this file except in compliance with the License. - * - * 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 com.ctc.wstx.stax; - -import java.util.Iterator; - -import javax.xml.namespace.NamespaceContext; -import javax.xml.namespace.QName; -import javax.xml.stream.*; -import javax.xml.stream.events.*; - -import org.codehaus.stax2.ri.Stax2EventFactoryImpl; - -import com.ctc.wstx.compat.QNameCreator; -import com.ctc.wstx.evt.*; - -/** - * Implementation of {@link XMLEventFactory} to be used with - * Woodstox. Contains minimal additions on top of Stax2 RI. - */ -public final class WstxEventFactory - extends Stax2EventFactoryImpl -{ - public WstxEventFactory() { - super(); - } - - /* - ///////////////////////////////////////////////////////////// - // XMLEventFactory API - ///////////////////////////////////////////////////////////// - */ - - //public Attribute createAttribute(QName name, String value) - //public Attribute createAttribute(String localName, String value) - //public Attribute createAttribute(String prefix, String nsURI, String localName, String value) - //public Characters createCData(String content); - //public Characters createCharacters(String content); - //public Comment createComment(String text); - - /** - * Note: constructing DTD events this way means that there will be no - * internal presentation of actual DTD; no parsing is implied by - * construction. - */ - public DTD createDTD(String dtd) { - return new WDTD(mLocation, dtd); - } - - //public EndDocument createEndDocument() - - //public EndElement createEndElement(QName name, Iterator namespaces) - //public EndElement createEndElement(String prefix, String nsURI, String localName) - //public EndElement createEndElement(String prefix, String nsURI, String localName, Iterator ns) - - //public EntityReference createEntityReference(String name, EntityDeclaration decl) - - //public Characters createIgnorableSpace(String content) - - //public Namespace createNamespace(String nsURI) - //public Namespace createNamespace(String prefix, String nsUri) - - //public ProcessingInstruction createProcessingInstruction(String target, String data) - - //public Characters createSpace(String content) - - //public StartDocument createStartDocument() - //public StartDocument createStartDocument(String encoding) - //public StartDocument createStartDocument(String encoding, String version) - //public StartDocument createStartDocument(String encoding, String version, boolean standalone) - - //public StartElement createStartElement(QName name, Iterator attr, Iterator ns) - - //public StartElement createStartElement(String prefix, String nsURI, String localName) - - //public StartElement createStartElement(String prefix, String nsURI, String localName, Iterator attr, Iterator ns) - - //public StartElement createStartElement(String prefix, String nsURI, String localName, Iterator attr, Iterator ns, NamespaceContext nsCtxt) - - /* - ///////////////////////////////////////////////////////////// - // Internal/helper methods - ///////////////////////////////////////////////////////////// - */ - - protected QName createQName(String nsURI, String localName) { - return new QName(nsURI, localName); - } - - protected QName createQName(String nsURI, String localName, String prefix) { - // [WSTX-174]: some old app servers missing 3-arg QName ctor - return QNameCreator.create(nsURI, localName, prefix); - } - - /** - * Must override this method to use a more efficient StartElement - * implementation - */ - //@Override - protected StartElement createStartElement(QName name, Iterator attr, - Iterator ns, NamespaceContext ctxt) - { - return SimpleStartElement.construct(mLocation, name, attr, ns, ctxt); - } -} diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/stax/WstxInputFactory.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/stax/WstxInputFactory.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/stax/WstxInputFactory.java 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/stax/WstxInputFactory.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,805 +0,0 @@ -/* Woodstox XML processor - * - * Copyright (c) 2004- Tatu Saloranta, tatu.saloranta@iki.fi - * - * Licensed under the License specified in the file LICENSE which is - * included with the source code. - * You may not use this file except in compliance with the License. - * - * 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 com.ctc.wstx.stax; - -import java.io.*; -import java.net.URL; - -import javax.xml.stream.*; -import javax.xml.stream.util.XMLEventAllocator; -import javax.xml.transform.dom.DOMSource; -import javax.xml.transform.sax.SAXSource; -import javax.xml.transform.stream.StreamSource; - -import org.xml.sax.InputSource; - -import org.codehaus.stax2.XMLEventReader2; -import org.codehaus.stax2.XMLInputFactory2; -import org.codehaus.stax2.XMLStreamReader2; -import org.codehaus.stax2.io.Stax2Source; -import org.codehaus.stax2.io.Stax2ByteArraySource; -import org.codehaus.stax2.ri.Stax2FilteredStreamReader; -import org.codehaus.stax2.ri.Stax2ReaderAdapter; -import org.codehaus.stax2.ri.evt.Stax2EventReaderAdapter; -import org.codehaus.stax2.ri.evt.Stax2FilteredEventReader; - -import com.ctc.wstx.api.ReaderConfig; -import com.ctc.wstx.api.WstxInputProperties; -import com.ctc.wstx.cfg.InputConfigFlags; -import com.ctc.wstx.cfg.XmlConsts; -import com.ctc.wstx.dtd.DTDId; -import com.ctc.wstx.dtd.DTDSubset; -import com.ctc.wstx.dom.WstxDOMWrappingReader; -import com.ctc.wstx.evt.DefaultEventAllocator; -import com.ctc.wstx.evt.WstxEventReader; -import com.ctc.wstx.exc.WstxIOException; -import com.ctc.wstx.io.*; -import com.ctc.wstx.sr.ValidatingStreamReader; -import com.ctc.wstx.sr.ReaderCreator; -import com.ctc.wstx.util.DefaultXmlSymbolTable; -import com.ctc.wstx.util.SimpleCache; -import com.ctc.wstx.util.SymbolTable; -import com.ctc.wstx.util.URLUtil; - -/** - * Factory for creating various Stax objects (stream/event reader, - * writer). - * - *

- * Currently supported configuration options fall into two categories. First, - * all properties from {@link XMLInputFactory} (such as, say, - * {@link XMLInputFactory#IS_NAMESPACE_AWARE}) are at least recognized, and - * most are supported. Second, there are additional properties, defined in - * constant class {@link WstxInputProperties}, that are supported. - * See {@link WstxInputProperties} for further explanation of these 'custom' - * properties. - * - * @author Tatu Saloranta - */ -public class WstxInputFactory - extends XMLInputFactory2 - implements ReaderCreator, - InputConfigFlags -{ - /** - * Let's limit max size to 3/4 of 16k, since this corresponds - * to 64k main hash index. This should not be too low, but could - * perhaps be further lowered? - */ - final static int MAX_SYMBOL_TABLE_SIZE = 12000; - - /** - * Number of generations should not matter as much as raw - * size... but let's still cap it at some number. 500 generations - * seems reasonable for flushing (note: does not count uses - * where no new symbols were added). - */ - final static int MAX_SYMBOL_TABLE_GENERATIONS = 500; - - /* - /////////////////////////////////////////////////////////// - // Actual storage of configuration settings - /////////////////////////////////////////////////////////// - */ - - /** - * Current configurations for this factory - */ - protected final ReaderConfig mConfig; - - // // // Stax - mandated objects: - - protected XMLEventAllocator mAllocator = null; - - // // // Other configuration objects: - - protected SimpleCache mDTDCache = null; - - /* - /////////////////////////////////////////////////////////// - // Objects shared by actual parsers - /////////////////////////////////////////////////////////// - */ - - /** - * 'Root' symbol table, used for creating actual symbol table instances, - * but never as is. - */ - final static SymbolTable mRootSymbols = DefaultXmlSymbolTable.getInstance(); - static { - /* By default, let's enable intern()ing of names (element, attribute, - * prefixes) added to symbol table. This is likely to make some - * access (attr by QName) and comparison of element/attr names - * more efficient. Although it will add some overhead on adding - * new symbols to symbol table that should be rather negligible. - * - * Also note that always doing intern()ing allows for more efficient - * access during DTD validation. - */ - mRootSymbols.setInternStrings(true); - } - - /** - * Actual current 'parent' symbol table; concrete instances will be - * created from this instance using makeChild method - */ - SymbolTable mSymbols = mRootSymbols; - - /* - /////////////////////////////////////////////////////////// - // Life-cycle: - /////////////////////////////////////////////////////////// - */ - - public WstxInputFactory() { - mConfig = ReaderConfig.createFullDefaults(); - } - - /* - /////////////////////////////////////////////////////////// - // ReaderCreator implementation - /////////////////////////////////////////////////////////// - */ - - // // // Configuration access methods: - - /** - * Method readers created by this factory call, if DTD caching is - * enabled, to see if an external DTD (subset) has been parsed - * and cached earlier. - */ - public synchronized DTDSubset findCachedDTD(DTDId id) - { - return (mDTDCache == null) ? - null : (DTDSubset) mDTDCache.find(id); - } - - // // // Callbacks for updating shared information - - /** - * Method individual parsers call to pass back symbol table that - * they updated, which may be useful for other parser to reuse, instead - * of previous base symbol table. - *

- * Note: parser is only to call this method, if passed-in symbol - * table was modified, ie new entry/ies were added in addition to - * whatever was in root table. - */ - public synchronized void updateSymbolTable(SymbolTable t) - { - SymbolTable curr = mSymbols; - /* Let's only add if table was direct descendant; this prevents - * siblings from keeping overwriting settings (multiple direct - * children have additional symbols added) - */ - if (t.isDirectChildOf(curr)) { - /* 07-Apr-2006, TSa: Actually, since huge symbol tables - * might become hindrance more than benefit (either in - * pathological cases with random names; or with very - * long running processes), let's actually limit both - * number of generations, and, more imporantly, maximum - * size of the symbol table - */ - if (t.size() > MAX_SYMBOL_TABLE_SIZE || - t.version() > MAX_SYMBOL_TABLE_GENERATIONS) { - // If so, we'll reset from bare defaults - mSymbols = mRootSymbols; -//System.err.println("DEBUG: !!!! XXXXX Symbol Table Flush: size: "+t.size()+"; version: "+t.version()); - } else { - mSymbols.mergeChild(t); -//System.err.println("Debug: new symbol table: size: "+t.size()+"; version: "+t.version()); - } - } -//else System.err.println("Debug: skipping symbol table update"); - } - - public synchronized void addCachedDTD(DTDId id, DTDSubset extSubset) - { - if (mDTDCache == null) { - mDTDCache = new SimpleCache(mConfig.getDtdCacheSize()); - } - mDTDCache.add(id, extSubset); - } - - /* - ///////////////////////////////////////////////////// - // Stax, XMLInputFactory; factory methods - ///////////////////////////////////////////////////// - */ - - // // // Filtered reader factory methods - - public XMLEventReader createFilteredReader(XMLEventReader reader, EventFilter filter) - { - return new Stax2FilteredEventReader(Stax2EventReaderAdapter.wrapIfNecessary(reader), filter); - } - - public XMLStreamReader createFilteredReader(XMLStreamReader reader, StreamFilter filter) - throws XMLStreamException - { - Stax2FilteredStreamReader fr = new Stax2FilteredStreamReader(reader, filter); - /* [WSTX-111] As per Stax 1.0 TCK, apparently the filtered - * reader is expected to be automatically forwarded to the first - * acceptable event. This is different from the way RI works, but - * since specs don't say anything about filtered readers, let's - * consider TCK to be "more formal" for now, and implement that - * behavior. - */ - if (!filter.accept(fr)) { // START_DOCUMENT ok? - // Ok, nope, this should do the trick: - fr.next(); - } - return fr; - } - - // // // Event reader factory methods - - public XMLEventReader createXMLEventReader(InputStream in) - throws XMLStreamException - { - // false for auto-close, since caller has access to the input stream - return new WstxEventReader(createEventAllocator(), - createSR(null, in, null, true, false)); - } - - public XMLEventReader createXMLEventReader(InputStream in, String enc) - throws XMLStreamException - { - // false for auto-close, since caller has access to the input stream - return new WstxEventReader(createEventAllocator(), - createSR(null, in, enc, true, false)); - } - - public XMLEventReader createXMLEventReader(Reader r) - throws XMLStreamException - { - // false for auto-close, since caller has access to the input stream - return new WstxEventReader(createEventAllocator(), - createSR(null, r, true, false)); - } - - public XMLEventReader createXMLEventReader(javax.xml.transform.Source source) - throws XMLStreamException - { - return new WstxEventReader(createEventAllocator(), - createSR(source, true)); - } - - public XMLEventReader createXMLEventReader(String systemId, InputStream in) - throws XMLStreamException - { - // false for auto-close, since caller has access to the input stream - return new WstxEventReader(createEventAllocator(), - createSR(systemId, in, null, true, false)); - } - - public XMLEventReader createXMLEventReader(String systemId, Reader r) - throws XMLStreamException - { - // false for auto-close, since caller has access to the reader - return new WstxEventReader(createEventAllocator(), - createSR(systemId, r, true, false)); - } - - public XMLEventReader createXMLEventReader(XMLStreamReader sr) - throws XMLStreamException - { - return new WstxEventReader(createEventAllocator(), Stax2ReaderAdapter.wrapIfNecessary(sr)); - } - - // // // Stream reader factory methods - - public XMLStreamReader createXMLStreamReader(InputStream in) - throws XMLStreamException - { - // false for auto-close, since caller has access to the input stream - return createSR(null, in, null, false, false); - } - - public XMLStreamReader createXMLStreamReader(InputStream in, String enc) - throws XMLStreamException - { - // false for auto-close, since caller has access to the input stream - return createSR(null, in, enc, false, false); - } - - public XMLStreamReader createXMLStreamReader(Reader r) - throws XMLStreamException - { - // false for auto-close, since caller has access to the reader - return createSR(null, r, false, false); - } - - public XMLStreamReader createXMLStreamReader(javax.xml.transform.Source src) - throws XMLStreamException - { - // false -> not for event. No definition for auto-close; called method will decide - return createSR(src, false); - } - - public XMLStreamReader createXMLStreamReader(String systemId, InputStream in) - throws XMLStreamException - { - // false for auto-close, since caller has access to the input stream - return createSR(systemId, in, null, false, false); - } - - public XMLStreamReader createXMLStreamReader(String systemId, Reader r) - throws XMLStreamException - { - // false for auto-close, since caller has access to the Reader - return createSR(systemId, r, false, false); - } - - /* - /////////////////////////////////////////////////////////// - // Stax, XMLInputFactory; generic accessors/mutators - /////////////////////////////////////////////////////////// - */ - - public Object getProperty(String name) - { - Object ob = mConfig.getProperty(name); - - if (ob == null) { - if (name.equals(XMLInputFactory.ALLOCATOR)) { - // Event allocator not available via J2ME subset... - return getEventAllocator(); - } - } - return ob; - } - - public void setProperty(String propName, Object value) - { - if (!mConfig.setProperty(propName, value)) { - if (XMLInputFactory.ALLOCATOR.equals(propName)) { - setEventAllocator((XMLEventAllocator) value); - } - } - } - - public XMLEventAllocator getEventAllocator() { - return mAllocator; - } - - public XMLReporter getXMLReporter() { - return mConfig.getXMLReporter(); - } - - public XMLResolver getXMLResolver() { - return mConfig.getXMLResolver(); - } - - public boolean isPropertySupported(String name) { - return mConfig.isPropertySupported(name); - } - - public void setEventAllocator(XMLEventAllocator allocator) { - mAllocator = allocator; - } - - public void setXMLReporter(XMLReporter r) { - mConfig.setXMLReporter(r); - } - - /** - * Note: it's preferable to use Wstx-specific - * {@link ReaderConfig#setEntityResolver} - * instead, if possible, since this just wraps passed in resolver. - */ - public void setXMLResolver(XMLResolver r) - { - mConfig.setXMLResolver(r); - } - - /* - /////////////////////////////////////////////////////////// - // Stax2 implementation - /////////////////////////////////////////////////////////// - */ - - // // // Stax2, additional factory methods: - - public XMLEventReader2 createXMLEventReader(URL src) - throws XMLStreamException - { - /* true for auto-close, since caller has no access to the underlying - * input stream created from the URL - */ - return new WstxEventReader(createEventAllocator(), - createSR(createPrivateConfig(), src, true, true)); - } - - public XMLEventReader2 createXMLEventReader(File f) - throws XMLStreamException - { - /* true for auto-close, since caller has no access to the underlying - * input stream created from the File - */ - return new WstxEventReader(createEventAllocator(), - createSR(f, true, true)); - } - - public XMLStreamReader2 createXMLStreamReader(URL src) - throws XMLStreamException - { - /* true for auto-close, since caller has no access to the underlying - * input stream created from the URL - */ - return createSR(createPrivateConfig(), src, false, true); - } - - /** - * Convenience factory method that allows for parsing a document - * stored in the specified file. - */ - public XMLStreamReader2 createXMLStreamReader(File f) - throws XMLStreamException - { - /* true for auto-close, since caller has no access to the underlying - * input stream created from the File - */ - return createSR(f, false, true); - } - - // // // Stax2 "Profile" mutators - - public void configureForXmlConformance() - { - mConfig.configureForXmlConformance(); - } - - public void configureForConvenience() - { - mConfig.configureForConvenience(); - } - - public void configureForSpeed() - { - mConfig.configureForSpeed(); - } - - public void configureForLowMemUsage() - { - mConfig.configureForLowMemUsage(); - } - - public void configureForRoundTripping() - { - mConfig.configureForRoundTripping(); - } - - /* - /////////////////////////////////////////////////////////// - // Woodstox-specific configuration access - /////////////////////////////////////////////////////////// - */ - - public ReaderConfig getConfig() { - return mConfig; - } - - /* - /////////////////////////////////////////////////////////// - // Internal methods: - /////////////////////////////////////////////////////////// - */ - - /** - * Bottleneck method used for creating ALL full stream reader instances - * (via other createSR() methods and directly) - * - * @param forER True, if the reader is being constructed to be used - * by an event reader; false if it is not (or the purpose is not known) - * @param autoCloseInput Whether the underlying input source should be - * actually closed when encountering EOF, or when close() - * is called. Will be true for input sources that are automatically - * managed by stream reader (input streams created for - * {@link java.net.URL} and {@link java.io.File} arguments, or when - * configuration settings indicate auto-closing is to be enabled - * (the default value is false as per Stax 1.0 specs). - */ - private XMLStreamReader2 doCreateSR(ReaderConfig cfg, String systemId, InputBootstrapper bs, - URL src, boolean forER, - boolean autoCloseInput) - throws XMLStreamException - { - /* Automatic closing of input: will happen always for some input - * types (ones application has no direct access to; but can also - * be explicitly enabled. - */ - if (!autoCloseInput) { - autoCloseInput = cfg.willAutoCloseInput(); - } - - Reader r; - try { - r = bs.bootstrapInput(cfg, true, XmlConsts.XML_V_UNKNOWN); - if (bs.declaredXml11()) { - cfg.enableXml11(true); - } - } catch (IOException ie) { - throw new WstxIOException(ie); - } - - /* null -> no public id available - * false -> don't close the reader when scope is closed. - */ - BranchingReaderSource input = InputSourceFactory.constructDocumentSource - (cfg, bs, null, systemId, src, r, autoCloseInput); - - return ValidatingStreamReader.createValidatingStreamReader(input, this, cfg, bs, forER); - } - - /** - * Method that is eventually called to create a (full) stream read - * instance. - *

- * Note: defined as public method because it needs to be called by - * SAX implementation. - * - * @param systemId System id used for this reader (if any) - * @param bs Bootstrapper to use for creating actual underlying - * physical reader - * @param forER Flag to indicate whether it will be used via - * Event API (will affect some configuration settings), true if it - * will be, false if not (or not known) - * @param autoCloseInput Whether the underlying input source should be - * actually closed when encountering EOF, or when close() - * is called. Will be true for input sources that are automatically - * managed by stream reader (input streams created for - * {@link java.net.URL} and {@link java.io.File} arguments, or when - * configuration settings indicate auto-closing is to be enabled - * (the default value is false as per Stax 1.0 specs). - */ - public XMLStreamReader2 createSR(ReaderConfig cfg, String systemId, InputBootstrapper bs, - boolean forER, - boolean autoCloseInput) - throws XMLStreamException - { - // 16-Aug-2004, TSa: Maybe we have a context? - URL src = cfg.getBaseURL(); - - // If not, maybe we can derive it from system id? - if ((src == null) && (systemId != null && systemId.length() > 0)) { - try { - src = URLUtil.urlFromSystemId(systemId); - } catch (IOException ie) { - throw new WstxIOException(ie); - } - } - return doCreateSR(cfg, systemId, bs, src, forER, autoCloseInput); - } - - protected XMLStreamReader2 createSR(String systemId, InputStream in, String enc, - boolean forER, - boolean autoCloseInput) - throws XMLStreamException - { - // sanity check: - if (in == null) { - throw new IllegalArgumentException("Null InputStream is not a valid argument"); - } - - ReaderConfig cfg = createPrivateConfig(); - if (enc == null || enc.length() == 0) { - return createSR(cfg, systemId, StreamBootstrapper.getInstance - (null, systemId, in), forER, autoCloseInput); - } - - /* !!! 17-Feb-2006, TSa: We don't yet know if it's xml 1.0 or 1.1; - * so have to specify 1.0 (which is less restrictive WRT input - * streams). Would be better to let bootstrapper deal with it - * though: - */ - Reader r = DefaultInputResolver.constructOptimizedReader(cfg, in, false, enc); - return createSR(cfg, systemId, ReaderBootstrapper.getInstance - (null, systemId, r, enc), forER, autoCloseInput); - } - - protected XMLStreamReader2 createSR(ReaderConfig cfg, URL src, boolean forER, boolean autoCloseInput) - throws XMLStreamException - { - try { - return createSR(cfg, src, URLUtil.inputStreamFromURL(src), - forER, autoCloseInput); - } catch (IOException ioe) { - throw new WstxIOException(ioe); - } - } - - private XMLStreamReader2 createSR(ReaderConfig cfg, URL src, InputStream in, - boolean forER, - boolean autoCloseInput) - throws XMLStreamException - { - String systemId = src.toExternalForm(); - return doCreateSR(cfg, systemId, - StreamBootstrapper.getInstance(null, systemId, in), - src, forER, autoCloseInput); - } - - protected XMLStreamReader2 createSR(String systemId, Reader r, - boolean forER, - boolean autoCloseInput) - throws XMLStreamException - { - return createSR(createPrivateConfig(), systemId, - ReaderBootstrapper.getInstance - (null, systemId, r, null), forER, autoCloseInput); - } - - protected XMLStreamReader2 createSR(File f, boolean forER, boolean autoCloseInput) - throws XMLStreamException - { - ReaderConfig cfg = createPrivateConfig(); - try { - /* 18-Nov-2008, TSa: If P_BASE_URL is set, and File reference is - * relative, let's resolve against base... - */ - if (!f.isAbsolute()) { - URL base = cfg.getBaseURL(); - if (base != null) { - URL src = new URL(base, f.getPath()); - return createSR(cfg, src, URLUtil.inputStreamFromURL(src), forER, autoCloseInput); - } - } - return createSR(cfg, f.toURL(), new FileInputStream(f), forER, autoCloseInput); - } catch (IOException ie) { - throw new WstxIOException(ie); - } - } - - /** - * Another internal factory method, used when dealing with a generic - * Source base type. One thing worth noting is that 'auto-closing' - * will be enabled if the input source or Reader is constructed (and - * thus owned) by Woodstox. - * - * @param forER True, if the reader is being constructed to be used - * by an event reader; false if it is not (or the purpose is not known) - */ - protected XMLStreamReader2 createSR(javax.xml.transform.Source src, - boolean forER) - throws XMLStreamException - { - ReaderConfig cfg = createPrivateConfig(); - Reader r = null; - InputStream in = null; - String pubId = null; - String sysId = null; - String encoding = null; - boolean autoCloseInput; - - InputBootstrapper bs = null; - - if (src instanceof Stax2Source) { - Stax2Source ss = (Stax2Source) src; - sysId = ss.getSystemId(); - pubId = ss.getPublicId(); - encoding = ss.getEncoding(); - - try { - /* 11-Nov-2008, TSa: Let's add optimized handling for byte-block - * source - */ - if (src instanceof Stax2ByteArraySource) { - Stax2ByteArraySource bas = (Stax2ByteArraySource) src; - bs = StreamBootstrapper.getInstance(pubId, sysId, bas.getBuffer(), bas.getBufferStart(), bas.getBufferEnd()); - } else { - in = ss.constructInputStream(); - if (in == null) { - r = ss.constructReader(); - } - } - } catch (IOException ioe) { - throw new WstxIOException(ioe); - } - /* Caller has no direct access to stream/reader, Woodstox - * owns it and thus has to close too - */ - autoCloseInput = true; - } else if (src instanceof StreamSource) { - StreamSource ss = (StreamSource) src; - sysId = ss.getSystemId(); - pubId = ss.getPublicId(); - in = ss.getInputStream(); - if (in == null) { - r = ss.getReader(); - } - /* Caller still has access to stream/reader; no need to - * force auto-close-input - */ - autoCloseInput = cfg.willAutoCloseInput(); - } else if (src instanceof SAXSource) { - SAXSource ss = (SAXSource) src; - /* 28-Jan-2006, TSa: Not a complete implementation, but maybe - * even this might help... - */ - sysId = ss.getSystemId(); - InputSource isrc = ss.getInputSource(); - if (isrc != null) { - encoding = isrc.getEncoding(); - in = isrc.getByteStream(); - if (in == null) { - r = isrc.getCharacterStream(); - } - } - /* Caller still has access to stream/reader; no need to - * force auto-close-input - */ - autoCloseInput = cfg.willAutoCloseInput(); - } else if (src instanceof DOMSource) { - DOMSource domSrc = (DOMSource) src; - // SymbolTable not used by the DOM-based 'reader': - return WstxDOMWrappingReader.createFrom(domSrc, cfg); - } else { - throw new IllegalArgumentException("Can not instantiate Stax reader for XML source type "+src.getClass()+" (unrecognized type)"); - } - if (bs == null) { // may have already created boostrapper... - if (r != null) { - bs = ReaderBootstrapper.getInstance(pubId, sysId, r, encoding); - } else if (in != null) { - bs = StreamBootstrapper.getInstance(pubId, sysId, in); - } else if (sysId != null && sysId.length() > 0) { - /* 26-Dec-2008, TSa: If we must construct URL from system id, - * it means caller will not have access to resulting - * stream, thus we will force auto-closing. - */ - autoCloseInput = true; - try { - return createSR(cfg, URLUtil.urlFromSystemId(sysId), - forER, autoCloseInput); - } catch (IOException ioe) { - throw new WstxIOException(ioe); - } - } else { - throw new XMLStreamException("Can not create Stax reader for the Source passed -- neither reader, input stream nor system id was accessible; can not use other types of sources (like embedded SAX streams)"); - } - } - return createSR(cfg, sysId, bs, forER, autoCloseInput); - } - - protected XMLEventAllocator createEventAllocator() - { - // Explicitly set allocate? - if (mAllocator != null) { - return mAllocator.newInstance(); - } - - /* Complete or fast one? Note: standard allocator is designed - * in such a way that newInstance() need not be called (calling - * it wouldn't do anything, anyway) - */ - return mConfig.willPreserveLocation() ? - DefaultEventAllocator.getDefaultInstance() - : DefaultEventAllocator.getFastInstance(); - } - - /** - * Method called to construct a copy of the factory's configuration - * object, such that two will be unlinked (changes to one are not - * reflect in the other). - *

- * Note: only public so that other woodstox components outside of - * this package can access it. - */ - public ReaderConfig createPrivateConfig() - { - return mConfig.createNonShared(mSymbols.makeChild()); - } -} diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/stax/WstxOutputFactory.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/stax/WstxOutputFactory.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/stax/WstxOutputFactory.java 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/stax/WstxOutputFactory.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,372 +0,0 @@ -/* Woodstox XML processor - * - * Copyright (c) 2004- Tatu Saloranta, tatu.saloranta@iki.fi - * - * Licensed under the License specified in the file LICENSE which is - * included with the source code. - * You may not use this file except in compliance with the License. - * - * 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 com.ctc.wstx.stax; - -import java.io.IOException; -import java.io.OutputStream; -import java.io.OutputStreamWriter; -import java.io.Writer; - -import javax.xml.stream.XMLEventWriter; -import javax.xml.stream.XMLOutputFactory; -import javax.xml.stream.XMLStreamException; -import javax.xml.stream.XMLStreamWriter; -import javax.xml.transform.Result; -import javax.xml.transform.dom.DOMResult; -import javax.xml.transform.sax.SAXResult; -import javax.xml.transform.stream.StreamResult; - -import org.codehaus.stax2.XMLOutputFactory2; -import org.codehaus.stax2.XMLStreamWriter2; -import org.codehaus.stax2.io.Stax2Result; -import org.codehaus.stax2.ri.Stax2EventWriterImpl; -import org.codehaus.stax2.ri.Stax2WriterAdapter; - -import com.ctc.wstx.api.WriterConfig; -import com.ctc.wstx.api.WstxOutputProperties; -import com.ctc.wstx.cfg.OutputConfigFlags; -import com.ctc.wstx.dom.WstxDOMWrappingWriter; -import com.ctc.wstx.exc.WstxIOException; -import com.ctc.wstx.io.CharsetNames; -import com.ctc.wstx.io.UTF8Writer; -import com.ctc.wstx.sw.AsciiXmlWriter; -import com.ctc.wstx.sw.BufferingXmlWriter; -import com.ctc.wstx.sw.ISOLatin1XmlWriter; -import com.ctc.wstx.sw.NonNsStreamWriter; -import com.ctc.wstx.sw.RepairingNsStreamWriter; -import com.ctc.wstx.sw.SimpleNsStreamWriter; -import com.ctc.wstx.sw.XmlWriter; -import com.ctc.wstx.util.URLUtil; - -/** - * Implementation of {@link XMLOutputFactory} for Wstx. - *

- * TODO: - *

    - *
  • Implement outputter that creates SAX events (DOM-backed - * writer exists as of Woodstox 3.2) - *
  • - *
- */ -public class WstxOutputFactory - extends XMLOutputFactory2 - implements OutputConfigFlags -{ - /* - /////////////////////////////////////////////////////////// - // Actual storage of configuration settings - /////////////////////////////////////////////////////////// - */ - - protected final WriterConfig mConfig; - - /* - /////////////////////////////////////////////////////////// - // Life-cycle - /////////////////////////////////////////////////////////// - */ - - public WstxOutputFactory() { - mConfig = WriterConfig.createFullDefaults(); - } - - /* - /////////////////////////////////////////////////////////// - // XMLOutputFactory API - /////////////////////////////////////////////////////////// - */ - - public XMLEventWriter createXMLEventWriter(OutputStream out) - throws XMLStreamException - { - return createXMLEventWriter(out, null); - } - - public XMLEventWriter createXMLEventWriter(OutputStream out, String enc) - throws XMLStreamException - { - if (out == null) { - throw new IllegalArgumentException("Null OutputStream is not a valid argument"); - } - return new Stax2EventWriterImpl(createSW(out, null, enc, false)); - } - - public XMLEventWriter createXMLEventWriter(javax.xml.transform.Result result) - throws XMLStreamException - { - return new Stax2EventWriterImpl(createSW(result)); - } - - public XMLEventWriter createXMLEventWriter(Writer w) - throws XMLStreamException - { - if (w == null) { - throw new IllegalArgumentException("Null Writer is not a valid argument"); - } - return new Stax2EventWriterImpl(createSW(null, w, null, false)); - } - - public XMLStreamWriter createXMLStreamWriter(OutputStream out) - throws XMLStreamException - { - return createXMLStreamWriter(out, null); - } - - public XMLStreamWriter createXMLStreamWriter(OutputStream out, String enc) - throws XMLStreamException - { - if (out == null) { - throw new IllegalArgumentException("Null OutputStream is not a valid argument"); - } - return createSW(out, null, enc, false); - } - - public XMLStreamWriter createXMLStreamWriter(javax.xml.transform.Result result) - throws XMLStreamException - { - return createSW(result); - } - - public XMLStreamWriter createXMLStreamWriter(Writer w) - throws XMLStreamException - { - if (w == null) { - throw new IllegalArgumentException("Null Writer is not a valid argument"); - } - return createSW(null, w, null, false); - } - - public Object getProperty(String name) - { - return mConfig.getProperty(name); - } - - public boolean isPropertySupported(String name) { - return mConfig.isPropertySupported(name); - } - - public void setProperty(String name, Object value) - { - mConfig.setProperty(name, value); - } - - /* - /////////////////////////////////////////////////////////// - // Stax2 extensions - /////////////////////////////////////////////////////////// - */ - - // // // Stax2 additional (encoding-aware) factory methods - - public XMLEventWriter createXMLEventWriter(Writer w, String enc) - throws XMLStreamException - { - return new Stax2EventWriterImpl(createSW(null, w, enc, false)); - } - - public XMLEventWriter createXMLEventWriter(XMLStreamWriter sw) - throws XMLStreamException - { - XMLStreamWriter2 sw2 = Stax2WriterAdapter.wrapIfNecessary(sw); - return new Stax2EventWriterImpl(sw2); - } - - public XMLStreamWriter2 createXMLStreamWriter(Writer w, String enc) - throws XMLStreamException - { - return createSW(null, w, enc, false); - } - - // // // Stax2 "Profile" mutators - - public void configureForXmlConformance() - { - mConfig.configureForXmlConformance(); - } - - public void configureForRobustness() - { - mConfig.configureForRobustness(); - } - - public void configureForSpeed() - { - mConfig.configureForSpeed(); - } - - /* - /////////////////////////////////////////////////////////// - // Woodstox-specific configuration access - /////////////////////////////////////////////////////////// - */ - - public WriterConfig getConfig() { - return mConfig; - } - - /* - /////////////////////////////////////////////////////////// - // Internal methods: - /////////////////////////////////////////////////////////// - */ - - /** - * Bottleneck factory method used internally; needs to take care of passing - * proper settings to stream writer. - * - * @param requireAutoClose Whether this result will always require - * auto-close be enabled (true); or only if application has - * requested it (false) - */ - private XMLStreamWriter2 createSW(OutputStream out, Writer w, String enc, - boolean requireAutoClose) - throws XMLStreamException - { - /* Need to ensure that the configuration object is not shared - * any more; otherwise later changes via factory could be - * visible half-way through output... - */ - WriterConfig cfg = mConfig.createNonShared(); - XmlWriter xw; - - boolean autoCloseOutput = requireAutoClose || mConfig.willAutoCloseOutput(); - - if (w == null) { - if (enc == null) { - enc = WstxOutputProperties.DEFAULT_OUTPUT_ENCODING; - } else { - /* Canonical ones are interned, so we may have - * normalized encoding already... - */ - if (enc != CharsetNames.CS_UTF8 - && enc != CharsetNames.CS_ISO_LATIN1 - && enc != CharsetNames.CS_US_ASCII) { - enc = CharsetNames.normalize(enc); - } - } - - try { - if (enc == CharsetNames.CS_UTF8) { - w = new UTF8Writer(cfg, out, autoCloseOutput); - xw = new BufferingXmlWriter(w, cfg, enc, autoCloseOutput, out, 16); - } else if (enc == CharsetNames.CS_ISO_LATIN1) { - xw = new ISOLatin1XmlWriter(out, cfg, autoCloseOutput); - } else if (enc == CharsetNames.CS_US_ASCII) { - xw = new AsciiXmlWriter(out, cfg, autoCloseOutput); - } else { - w = new OutputStreamWriter(out, enc); - xw = new BufferingXmlWriter(w, cfg, enc, autoCloseOutput, out, -1); - } - } catch (IOException ex) { - throw new XMLStreamException(ex); - } - } else { - // we may still be able to figure out the encoding: - if (enc == null) { - enc = CharsetNames.findEncodingFor(w); - } - try { - xw = new BufferingXmlWriter(w, cfg, enc, autoCloseOutput, null, -1); - } catch (IOException ex) { - throw new XMLStreamException(ex); - } - } - - return createSW(enc, cfg, xw); - } - - /** - * Called by {@link #createSW(OutputStream, Writer, String, boolean)} after all of the nessesary configuration - * logic is complete. - */ - protected XMLStreamWriter2 createSW(String enc, WriterConfig cfg, XmlWriter xw) { - if (cfg.willSupportNamespaces()) { - if (cfg.automaticNamespacesEnabled()) { - return new RepairingNsStreamWriter(xw, enc, cfg); - } - return new SimpleNsStreamWriter(xw, enc, cfg); - } - return new NonNsStreamWriter(xw, enc, cfg); - } - - private XMLStreamWriter2 createSW(Result res) - throws XMLStreamException - { - OutputStream out = null; - Writer w = null; - String encoding = null; - boolean requireAutoClose; - String sysId = null; - - if (res instanceof Stax2Result) { - Stax2Result sr = (Stax2Result) res; - try { - out = sr.constructOutputStream(); - if (out == null) { - w = sr.constructWriter(); - } - } catch (IOException ioe) { - throw new WstxIOException(ioe); - } - // yes, it's required since caller has no access to stream/writer: - requireAutoClose = true; - } else if (res instanceof StreamResult) { - StreamResult sr = (StreamResult) res; - out = sr.getOutputStream(); - sysId = sr.getSystemId(); - if (out == null) { - w = sr.getWriter(); - } - /* Caller owns it, only auto-close if requested to do so: - * (except that for system-id-only, it'll still be required, - * see code below) - */ - requireAutoClose = false; - } else if (res instanceof SAXResult) { - SAXResult sr = (SAXResult) res; - sysId = sr.getSystemId(); - if (sysId == null || sysId.length() == 0) { - throw new XMLStreamException("Can not create a stream writer for a SAXResult that does not have System Id (support for using SAX input source not implemented)"); - } - requireAutoClose = true; - } else if (res instanceof DOMResult) { - return WstxDOMWrappingWriter.createFrom(mConfig.createNonShared(), (DOMResult) res); - } else { - throw new IllegalArgumentException("Can not instantiate a writer for XML result type "+res.getClass()+" (unrecognized type)"); - } - - if (out != null) { - return createSW(out, null, encoding, requireAutoClose); - } - if (w != null) { - return createSW(null, w, encoding, requireAutoClose); - } - if (sysId != null && sysId.length() > 0) { - /* 26-Dec-2008, TSa: If we must construct URL from system id, - * it means caller will not have access to resulting - * stream, thus we will force auto-closing. - */ - requireAutoClose = true; - try { - out = URLUtil.outputStreamFromURL(URLUtil.urlFromSystemId(sysId)); - } catch (IOException ioe) { - throw new WstxIOException(ioe); - } - return createSW(out, null, encoding, requireAutoClose); - } - throw new XMLStreamException("Can not create Stax writer for passed-in Result -- neither writer, output stream or system id was accessible"); - } -} diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/sw/AsciiXmlWriter.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/sw/AsciiXmlWriter.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/sw/AsciiXmlWriter.java 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/sw/AsciiXmlWriter.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,758 +0,0 @@ -/* Woodstox XML processor - * - * Copyright (c) 2004- Tatu Saloranta, tatu.saloranta@iki.fi - * - * Licensed under the License specified in file LICENSE, included with - * the source code. - * You may not use this file except in compliance with the License. - * - * 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 com.ctc.wstx.sw; - -import java.io.*; - -import javax.xml.stream.XMLStreamException; - -import com.ctc.wstx.api.WriterConfig; -import com.ctc.wstx.io.CharsetNames; - -/** - * Concrete implementation of {@link EncodingXmlWriter} used when output - * is to be encoded using 7-bit ascii (US-ASCII) encoding. - */ -public final class AsciiXmlWriter - extends EncodingXmlWriter -{ - public AsciiXmlWriter(OutputStream out, WriterConfig cfg, boolean autoclose) - throws IOException - { - super(out, cfg, CharsetNames.CS_US_ASCII, autoclose); - } - - public void writeRaw(char[] cbuf, int offset, int len) - throws IOException - { - if (mSurrogate != 0) { - throwUnpairedSurrogate(); - } - - int ptr = mOutputPtr; - while (len > 0) { - int max = mOutputBuffer.length - ptr; - if (max < 1) { // output buffer full? - mOutputPtr = ptr; - flushBuffer(); - ptr = 0; - max = mOutputBuffer.length; - } - // How much can we output? - if (max > len) { - max = len; - } - if (mCheckContent) { - for (int inEnd = offset + max; offset < inEnd; ++offset) { - int c = cbuf[offset]; - if (c < 32) { - if (c == '\n') { - // !!! TBI: line nr - } else if (c == '\r') { - // !!! TBI: line nr (and skipping \n that may follow) - } else if (c != '\t') { - mOutputPtr = ptr; - c = handleInvalidChar(c); - } - } else if (c > 0x7E) { - mOutputPtr = ptr; - if (c > 0x7F) { // 0x7F invalid in xml11 - handleInvalidAsciiChar(c); - } else if (mXml11) { - c = handleInvalidChar(c); - } - } - mOutputBuffer[ptr++] = (byte) c; - } - } else { - for (int inEnd = offset + max; offset < inEnd; ++offset) { - mOutputBuffer[ptr++] = (byte) cbuf[offset]; - } - } - len -= max; - } - mOutputPtr = ptr; - } - - public void writeRaw(String str, int offset, int len) - throws IOException - { - if (mSurrogate != 0) { - throwUnpairedSurrogate(); - } - int ptr = mOutputPtr; - while (len > 0) { - int max = mOutputBuffer.length - ptr; - if (max < 1) { // output buffer full? - mOutputPtr = ptr; - flushBuffer(); - ptr = 0; - max = mOutputBuffer.length; - } - // How much can we output? - if (max > len) { - max = len; - } - if (mCheckContent) { - for (int inEnd = offset + max; offset < inEnd; ++offset) { - int c = str.charAt(offset); - if (c < 32) { - if (c == '\n') { - // !!! TBI: line nr - } else if (c == '\r') { - // !!! TBI: line nr (and skipping \n that may follow) - } else if (c != '\t') { - mOutputPtr = ptr; - c = handleInvalidChar(c); - } - } else if (c > 0x7E) { - mOutputPtr = ptr; - if (c > 0x7F) { // 0x7F invalid in xml11 - handleInvalidAsciiChar(c); - } else if (mXml11) { - c = handleInvalidChar(c); - } - } - mOutputBuffer[ptr++] = (byte) c; - } - } else { - for (int inEnd = offset + max; offset < inEnd; ++offset) { - mOutputBuffer[ptr++] = (byte) str.charAt(offset); - } - } - len -= max; - } - mOutputPtr = ptr; - } - - protected void writeAttrValue(String data) - throws IOException - { - int offset = 0; - int len = data.length(); - int ptr = mOutputPtr; - - main_loop: - while (len > 0) { - int max = mOutputBuffer.length - ptr; - if (max < 1) { // output buffer full? - mOutputPtr = ptr; - flushBuffer(); - ptr = 0; - max = mOutputBuffer.length; - } - // Do we start with a surrogate? - if (mSurrogate != 0) { - int sec = data.charAt(offset++); - sec = calcSurrogate(sec); - mOutputPtr = ptr; - ptr = writeAsEntity(sec); - --len; - continue main_loop; - } - // How much can we output? - if (max > len) { - max = len; - } - inner_loop: - for (int inEnd = offset + max; offset < inEnd; ) { - int c = data.charAt(offset++); - if (c < 32) { - /* Need to quote all white space except for regular - * space chars, to preserve them (round-tripping) - */ - if (c == '\r') { - if (!mEscapeCR) { - mOutputBuffer[ptr++] = (byte) c; - continue; - } - } else if (c != '\n' && c != '\t') { - if (mCheckContent) { - if (!mXml11 || c == 0) { - c = handleInvalidChar(c); - mOutputBuffer[ptr++] = (byte) c; - continue; - } - } - } - // fall-through to char entity output - } else if (c < 0x7F) { - if (c != '<' && c != '&' && c != '"') { - mOutputBuffer[ptr++] = (byte) c; - continue; - } - // otherwise fall back on quoting - } else { - // Surrogate? - if (c >= SURR1_FIRST && c <= SURR2_LAST) { - mSurrogate = c; - // Last char needs special handling: - if (offset == inEnd) { - break inner_loop; - } - c = calcSurrogate(data.charAt(offset++)); - // Let's fall down to entity output - } - } - /* Has to be escaped as char entity; as such, also need - * to re-calc max. continguous data we can output - */ - mOutputPtr = ptr; - ptr = writeAsEntity(c); - len = data.length() - offset; - continue main_loop; - } - len -= max; - } - mOutputPtr = ptr; - } - - protected void writeAttrValue(char[] data, int offset, int len) - throws IOException - { - int ptr = mOutputPtr; - - main_loop: - while (len > 0) { - int max = mOutputBuffer.length - ptr; - if (max < 1) { // output buffer full? - mOutputPtr = ptr; - flushBuffer(); - ptr = 0; - max = mOutputBuffer.length; - } - // Do we start with a surrogate? - if (mSurrogate != 0) { - int sec = data[offset++]; - sec = calcSurrogate(sec); - mOutputPtr = ptr; - ptr = writeAsEntity(sec); - --len; - continue main_loop; - } - // How much can we output? - if (max > len) { - max = len; - } - inner_loop: - for (int inEnd = offset + max; offset < inEnd; ) { - int c = data[offset++]; - if (c < 32) { - /* Need to quote all white space except for regular - * space chars, to preserve them (round-tripping) - */ - if (c == '\r') { - if (!mEscapeCR) { - mOutputBuffer[ptr++] = (byte) c; - continue; - } - } else if (c != '\n' && c != '\t') { - if (mCheckContent) { - if (!mXml11 || c == 0) { - c = handleInvalidChar(c); - mOutputBuffer[ptr++] = (byte) c; - continue; - } - } - } - // fall-through to char entity output - } else if (c < 0x7F) { - if (c != '<' && c != '&' && c != '"') { - mOutputBuffer[ptr++] = (byte) c; - continue; - } - // otherwise fall back on quoting - } else { - // Surrogate? - if (c >= SURR1_FIRST && c <= SURR2_LAST) { - mSurrogate = c; - // Last char needs special handling: - if (offset == inEnd) { - break inner_loop; - } - c = calcSurrogate(data[offset++]); - // Let's fall down to entity output - } - } - /* Has to be escaped as char entity; as such, also need - * to re-calc max. contiguous data we can output - */ - mOutputPtr = ptr; - ptr = writeAsEntity(c); - max -= (inEnd - offset); // since we didn't loop completely - break inner_loop; - } - len -= max; - } - mOutputPtr = ptr; - } - - protected int writeCDataContent(String data) - throws IOException - { - // Note: mSurrogate can not be non-zero at this point, no need to check - - int offset = 0; - int len = data.length(); - if (!mCheckContent) { - writeRaw(data, offset, len); - return -1; - } - int ptr = mOutputPtr; - - main_loop: - while (len > 0) { - int max = mOutputBuffer.length - ptr; - if (max < 1) { // output buffer full? - mOutputPtr = ptr; - flushBuffer(); - ptr = 0; - max = mOutputBuffer.length; - } - // How much can we output? - if (max > len) { - max = len; - } - for (int inEnd = offset + max; offset < inEnd; ) { - int c = data.charAt(offset++); - if (c < 32) { - if (c == '\n') { - // !!! TBI: line nr - } else if (c == '\r') { - // !!! TBI: line nr (and skipping \n that may follow) - } else if (c != '\t') { - mOutputPtr = ptr; - c = handleInvalidChar(c); - } - } else if (c > 0x7E) { - mOutputPtr = ptr; - if (c > 0x7F) { // 0x7F invalid in xml11 - handleInvalidAsciiChar(c); - } else if (mXml11) { - c = handleInvalidChar(c); - } - } else if (c == '>') { // embedded "]]>"? - if (offset > 2 && data.charAt(offset-2) == ']' - && data.charAt(offset-3) == ']') { - if (!mFixContent) { - return offset-3; - } - /* Relatively easy fix; just need to close this - * section, and open a new one... - */ - mOutputPtr = ptr; - writeCDataEnd(); - writeCDataStart(); - writeAscii(BYTE_GT); - ptr = mOutputPtr; - /* No guarantees there's as much free room in the - * output buffer, thus, need to restart loop: - */ - len = data.length() - offset; - continue main_loop; - } - } - mOutputBuffer[ptr++] = (byte) c; - } - len -= max; - } - mOutputPtr = ptr; - return -1; - } - - protected int writeCDataContent(char[] cbuf, int start, int len) - throws IOException - { - // Note: mSurrogate can not be non-zero at this point, no need to check - - if (!mCheckContent) { - writeRaw(cbuf, start, len); - return -1; - } - - int ptr = mOutputPtr; - int offset = start; - - while (len > 0) { - int max = mOutputBuffer.length - ptr; - if (max < 1) { // output buffer full? - mOutputPtr = ptr; - flushBuffer(); - ptr = 0; - max = mOutputBuffer.length; - } - // How much can we output? - if (max > len) { - max = len; - } - inner_loop: - for (int inEnd = offset + max; offset < inEnd; ) { - int c = cbuf[offset++]; - if (c < 32) { - if (c == '\n') { - // !!! TBI: line nr - } else if (c == '\r') { - // !!! TBI: line nr (and skipping \n that may follow) - } else if (c != '\t') { - mOutputPtr = ptr; - c = handleInvalidChar(c); - } - } else if (c > 0x7E) { - mOutputPtr = ptr; - if (c > 0x7F) { // 0x7F invalid in xml11 - handleInvalidAsciiChar(c); - } else if (mXml11) { - c = handleInvalidChar(c); - } - } else if (c == '>') { // embedded "]]>"? - if (offset >= (start+3) && cbuf[offset-2] == ']' - && cbuf[offset-3] == ']') { - if (!mFixContent) { - return offset-3; - } - /* Relatively easy fix; just need to close this - * section, and open a new one... - */ - mOutputPtr = ptr; - writeCDataEnd(); - writeCDataStart(); - writeAscii(BYTE_GT); - ptr = mOutputPtr; - /* No guarantees there's as much free room in the - * output buffer, thus, need to restart loop: - */ - max -= (inEnd - offset); - break inner_loop; - } - } - mOutputBuffer[ptr++] = (byte) c; - } - len -= max; - } - mOutputPtr = ptr; - return -1; - } - - protected int writeCommentContent(String data) - throws IOException - { - // Note: mSurrogate can not be non-zero at this point, no need to check - - int offset = 0; - int len = data.length(); - if (!mCheckContent) { - writeRaw(data, offset, len); - return -1; - } - - int ptr = mOutputPtr; - - while (len > 0) { - int max = mOutputBuffer.length - ptr; - if (max < 1) { // output buffer full? - mOutputPtr = ptr; - flushBuffer(); - ptr = 0; - max = mOutputBuffer.length; - } - // How much can we output? - if (max > len) { - max = len; - } - inner_loop: - for (int inEnd = offset + max; offset < inEnd; ) { - int c = data.charAt(offset++); - if (c < 32) { - if (c == '\n') { - // !!! TBI: line nr - } else if (c == '\r') { - // !!! TBI: line nr (and skipping \n that may follow) - } else if (c != '\t') { - mOutputPtr = ptr; - c = handleInvalidChar(c); - } - } else if (c > 0x7E) { - mOutputPtr = ptr; - if (c > 0x7F) { // 0x7F invalid in xml11 - handleInvalidAsciiChar(c); - } else if (mXml11) { - c = handleInvalidChar(c); - } - } else if (c == '-') { // embedded "--"? - if (offset > 1 && data.charAt(offset-2) == '-') { - if (!mFixContent) { - return offset-2; - } - /* Quite easy to fix: just add an extra space - * in front. There will be room for that char; - * but may need to take that the following '-' - * also fits. - */ - mOutputBuffer[ptr++] = ' '; - if (ptr >= mOutputBuffer.length) { // whops. need to flush - mOutputPtr = ptr; - flushBuffer(); - ptr = 0; - } - mOutputBuffer[ptr++] = BYTE_HYPHEN; - /* Also, since we did output an extra char, better - * restart the loop (since max calculation is now - * off) - */ - max -= (inEnd - offset); - break inner_loop; - } - } - mOutputBuffer[ptr++] = (byte) c; - } - len -= max; - } - mOutputPtr = ptr; - return -1; - } - - protected int writePIData(String data) - throws IOException, XMLStreamException - { - // Note: mSurrogate can not be non-zero at this point, no need to check - - int offset = 0; - int len = data.length(); - if (!mCheckContent) { - writeRaw(data, offset, len); - return -1; - } - - int ptr = mOutputPtr; - while (len > 0) { - int max = mOutputBuffer.length - ptr; - if (max < 1) { // output buffer full? - mOutputPtr = ptr; - flushBuffer(); - ptr = 0; - max = mOutputBuffer.length; - } - // How much can we output? - if (max > len) { - max = len; - } - for (int inEnd = offset + max; offset < inEnd; ++offset) { - int c = data.charAt(offset); - if (c < 32) { - if (c == '\n') { - // !!! TBI: line nr - } else if (c == '\r') { - // !!! TBI: line nr (and skipping \n that may follow) - } else if (c != '\t') { - mOutputPtr = ptr; - c = handleInvalidChar(c); - } - } else if (c > 0x7E) { - mOutputPtr = ptr; - if (c > 0x7F) { // 0x7F invalid in xml11 - handleInvalidAsciiChar(c); - } else if (mXml11) { - c = handleInvalidChar(c); - } - } else if (c == '>') { // enclosed end marker ("?>")? - if (offset > 0 && data.charAt(offset-1) == '?') { - return offset-2; - } - } - mOutputBuffer[ptr++] = (byte) c; - } - len -= max; - } - mOutputPtr = ptr; - return -1; - } - - protected void writeTextContent(String data) - throws IOException - { - int offset = 0; - int len = data.length(); - - main_loop: - while (len > 0) { - int max = mOutputBuffer.length - mOutputPtr; - if (max < 1) { // output buffer full? - flushBuffer(); - max = mOutputBuffer.length; - } - // Do we start with a surrogate? - if (mSurrogate != 0) { - int sec = data.charAt(offset++); - sec = calcSurrogate(sec); - writeAsEntity(sec); - --len; - continue main_loop; - } - // How much can we output? - if (max > len) { - max = len; - } - inner_loop: - for (int inEnd = offset + max; offset < inEnd; ) { - int c = data.charAt(offset++); - if (c < 32) { - if (c == '\n' || c == '\t') { // TODO: line count - mOutputBuffer[mOutputPtr++] = (byte) c; - continue; - } else if (c == '\r') { - if (!mEscapeCR) { - mOutputBuffer[mOutputPtr++] = (byte) c; - continue; - } - } else if (!mXml11 || c == 0) { // ok in xml1.1, as entity - if (mCheckContent) { - c = handleInvalidChar(c); - mOutputBuffer[mOutputPtr++] = (byte) c; - continue; - } - // otherwise... well, I guess we can just escape it - } - // \r, or xml1.1 + other whitespace, need to escape - } else if (c < 0x7F) { - if (c != '<' && c != '&') { - if (c != '>' || (offset > 1 && data.charAt(offset-2) != ']')) { - mOutputBuffer[mOutputPtr++] = (byte) c; - continue; - } - } - // otherwise fall back on quoting - } else { - // Surrogate? - if (c >= SURR1_FIRST && c <= SURR2_LAST) { - mSurrogate = c; - // Last char needs special handling: - if (offset == inEnd) { - break inner_loop; - } - c = calcSurrogate(data.charAt(offset++)); - // Let's fall down to entity output - } - } - /* Has to be escaped as char entity; as such, also need - * to re-calc max. continguous data we can output - */ - writeAsEntity(c); - len = data.length() - offset; - continue main_loop; - } - len -= max; - } - } - - protected void writeTextContent(char[] cbuf, int offset, int len) - throws IOException - { - main_loop: - while (len > 0) { - int max = mOutputBuffer.length - mOutputPtr; - if (max < 1) { // output buffer full? - flushBuffer(); - max = mOutputBuffer.length; - } - // Do we start with a surrogate? - if (mSurrogate != 0) { - int sec = cbuf[offset++]; - sec = calcSurrogate(sec); - writeAsEntity(sec); - --len; - continue main_loop; - } - // How much can we output? - if (max > len) { - max = len; - } - inner_loop: - for (int inEnd = offset + max; offset < inEnd; ) { - int c = cbuf[offset++]; - if (c < 32) { - if (c == '\n' || c == '\t') { // TODO: line count - mOutputBuffer[mOutputPtr++] = (byte) c; - continue; - } else if (c == '\r') { - if (!mEscapeCR) { - mOutputBuffer[mOutputPtr++] = (byte) c; - continue; - } - } else if (!mXml11 || c == 0) { // ok in xml1.1, as entity - if (mCheckContent) { - c = handleInvalidChar(c); - mOutputBuffer[mOutputPtr++] = (byte) c; - continue; - } - // otherwise... well, I guess we can just try to escape it - } - // \r, or xml1.1 + other whitespace, need to escape - } else if (c < 0x7F) { - if (c !='<' && c != '&') { - /* Since we can be conservative, it doesn't matter - * if second check is not exact - */ - if (c != '>' || (offset > 1 && cbuf[offset-2] != ']')) { - mOutputBuffer[mOutputPtr++] = (byte) c; - continue; - } - } - // otherwise fall back on quoting - } else { - // Surrogate? - if (c >= SURR1_FIRST && c <= SURR2_LAST) { - mSurrogate = c; - // Last char needs special handling: - if (offset == inEnd) { - break inner_loop; - } - c = calcSurrogate(cbuf[offset++]); - // Let's fall down to entity output - } - } - /* Has to be escaped as char entity; as such, also need - * to re-calc max. continguous data we can output - */ - writeAsEntity(c); - max -= (inEnd - offset); - break inner_loop; - } - len -= max; - } - } - - /* - //////////////////////////////////////////////////// - // Internal methods - //////////////////////////////////////////////////// - */ - - protected void handleInvalidAsciiChar(int c) - throws IOException - { - // First, let's flush any output we may have, to make debugging easier - flush(); - - /* 17-May-2006, TSa: Would really be useful if we could throw - * XMLStreamExceptions; esp. to indicate actual output location. - * However, this causes problem with methods that call us and - * can only throw IOExceptions (when invoked via Writer proxy). - * Need to figure out how to resolve this. - */ - throw new IOException("Invalid XML character (0x"+Integer.toHexString(c)+"); can only be output using character entity when using US-ASCII encoding"); - } -} - diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/sw/BaseNsStreamWriter.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/sw/BaseNsStreamWriter.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/sw/BaseNsStreamWriter.java 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/sw/BaseNsStreamWriter.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,753 +0,0 @@ -/* Woodstox XML processor - * - * Copyright (c) 2004- Tatu Saloranta, tatu.saloranta@iki.fi - * - * Licensed under the License specified in the file LICENSE, - * included with the source code. - * You may not use this file except in compliance with the License. - * - * 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 com.ctc.wstx.sw; - -import java.io.IOException; - -import javax.xml.XMLConstants; -import javax.xml.namespace.NamespaceContext; -import javax.xml.namespace.QName; -import javax.xml.stream.XMLStreamException; -import javax.xml.stream.events.StartElement; - -import org.codehaus.stax2.ri.typed.AsciiValueEncoder; - -import com.ctc.wstx.api.EmptyElementHandler; -import com.ctc.wstx.api.WriterConfig; -import com.ctc.wstx.cfg.ErrorConsts; -import com.ctc.wstx.cfg.XmlConsts; -import com.ctc.wstx.exc.WstxIOException; -import com.ctc.wstx.util.DefaultXmlSymbolTable; - -/** - * Mid-level base class of namespace-aware stream writers. Contains - * shared functionality between repairing and non-repairing implementations. - */ -public abstract class BaseNsStreamWriter - extends TypedStreamWriter -{ - /* - //////////////////////////////////////////////////// - // Constants - //////////////////////////////////////////////////// - */ - - final protected static String sPrefixXml = DefaultXmlSymbolTable.getXmlSymbol(); - - final protected static String sPrefixXmlns = DefaultXmlSymbolTable.getXmlnsSymbol(); - - final protected static String ERR_NSDECL_WRONG_STATE = - "Trying to write a namespace declaration when there is no open start element."; - - - /* - //////////////////////////////////////////////////// - // Configuration (options, features) - //////////////////////////////////////////////////// - */ - - // // // Additional specific config flags base class doesn't have - - /** - * True, if writer needs to automatically output namespace declarations - * (we are in repairing mode) - */ - final protected boolean mAutomaticNS; - - final protected EmptyElementHandler mEmptyElementHandler; - - /* - //////////////////////////////////////////////////// - // State information - //////////////////////////////////////////////////// - */ - - protected SimpleOutputElement mCurrElem = SimpleOutputElement.createRoot(); - - /** - * Optional "root" namespace context that application can set. If so, - * it can be used to lookup namespace/prefix mappings - */ - protected NamespaceContext mRootNsContext = null; - - /* - //////////////////////////////////////////////////// - // Pool for recycling SimpleOutputElement instances - //////////////////////////////////////////////////// - */ - - /* Note: although pooling of cheap objects like SimpleOutputElement - * is usually not a good idea, here profiling showed it to be a - * significant improvement. As long as instances are ONLY reused - * within context of a single writer, they stay in cheap ("Eden") - * GC area, and thus it should be a win. - */ - protected SimpleOutputElement mOutputElemPool = null; - - /** - * Although pooled objects are small, let's limit the pool size - * nonetheless, to optimize memory usage for deeply nested - * documents. In general, even just low number like 4 levels gets - * decent return, but 8 should get 99% hit rate. - */ - final static int MAX_POOL_SIZE = 8; - - protected int mPoolSize = 0; - - /* - //////////////////////////////////////////////////// - // Life-cycle (ctors) - //////////////////////////////////////////////////// - */ - - public BaseNsStreamWriter(XmlWriter xw, String enc, WriterConfig cfg, - boolean repairing) - { - super(xw, enc, cfg); - mAutomaticNS = repairing; - mEmptyElementHandler = cfg.getEmptyElementHandler(); - } - - /* - //////////////////////////////////////////////////// - // XMLStreamWriter API - //////////////////////////////////////////////////// - */ - - public NamespaceContext getNamespaceContext() { - return mCurrElem; - } - - public String getPrefix(String uri) { - return mCurrElem.getPrefix(uri); - } - - public abstract void setDefaultNamespace(String uri) - throws XMLStreamException; - - /** - *

- * Note: Root namespace context works best if automatic prefix - * creation ("namespace/prefix repairing" in StAX lingo) is enabled. - */ - public void setNamespaceContext(NamespaceContext ctxt) - throws XMLStreamException - { - // This is only allowed before root element output: - if (mState != STATE_PROLOG) { - throwOutputError("Called setNamespaceContext() after having already output root element."); - } - - mRootNsContext = ctxt; - mCurrElem.setRootNsContext(ctxt); - } - - public void setPrefix(String prefix, String uri) - throws XMLStreamException - { - if (prefix == null) { - throw new NullPointerException("Can not pass null 'prefix' value"); - } - // Are we actually trying to set the default namespace? - if (prefix.length() == 0) { - setDefaultNamespace(uri); - return; - } - if (uri == null) { - throw new NullPointerException("Can not pass null 'uri' value"); - } - - /* 25-Sep-2004, TSa: Let's check that "xml" and "xmlns" are not - * (re-)defined to any other value, nor that value they - * are bound to are bound to other prefixes. - */ - /* 01-Apr-2005, TSa: And let's not leave it optional: such - * bindings should never succeed. - */ - // ... perhaps it really should be optional though? - { - if (prefix.equals(sPrefixXml)) { // prefix "xml" - if (!uri.equals(XMLConstants.XML_NS_URI)) { - throwOutputError(ErrorConsts.ERR_NS_REDECL_XML, uri); - } - } else if (prefix.equals(sPrefixXmlns)) { // prefix "xmlns" - if (!uri.equals(XMLConstants.XMLNS_ATTRIBUTE_NS_URI)) { - throwOutputError(ErrorConsts.ERR_NS_REDECL_XMLNS, uri); - } - } else { - // Neither of prefixes.. but how about URIs? - if (uri.equals(XMLConstants.XML_NS_URI)) { - throwOutputError(ErrorConsts.ERR_NS_REDECL_XML_URI, prefix); - } else if (uri.equals(XMLConstants.XMLNS_ATTRIBUTE_NS_URI)) { - throwOutputError(ErrorConsts.ERR_NS_REDECL_XMLNS_URI, prefix); - } - } - - /* 05-Feb-2005, TSa: Also, as per namespace specs; the 'empty' - * namespace URI can not be bound as a non-default namespace - * (ie. for any actual prefix) - */ - /* 04-Feb-2005, TSa: Namespaces 1.1 does allow this, though, - * so for xml 1.1 documents we need to allow it - */ - if (!mXml11) { - if (uri.length() == 0) { - throwOutputError(ErrorConsts.ERR_NS_EMPTY); - } - } - } - - doSetPrefix(prefix, uri); - } - - /** - * It's assumed calling this method implies caller just wants to add - * an attribute that does not belong to any namespace; as such no - * namespace checking or prefix generation is needed. - */ - public void writeAttribute(String localName, String value) - throws XMLStreamException - { - // No need to set mAnyOutput, nor close the element - if (!mStartElementOpen && mCheckStructure) { - reportNwfStructure(ErrorConsts.WERR_ATTR_NO_ELEM); - } - doWriteAttr(localName, null, null, value); - } - - public abstract void writeAttribute(String nsURI, String localName, String value) - throws XMLStreamException; - - public abstract void writeAttribute(String prefix, String nsURI, - String localName, String value) - throws XMLStreamException; - - /** - *

- * Note: It is assumed caller just wants the element to belong to whatever - * is the current default namespace. - */ - public void writeEmptyElement(String localName) - throws XMLStreamException - { - checkStartElement(localName, null); - if (mValidator != null) { - mValidator.validateElementStart(localName, XmlConsts.ELEM_NO_NS_URI, XmlConsts.ELEM_NO_PREFIX); - } - mEmptyElement = true; - if (mOutputElemPool != null) { - SimpleOutputElement newCurr = mOutputElemPool; - mOutputElemPool = newCurr.reuseAsChild(mCurrElem, localName); - --mPoolSize; - mCurrElem = newCurr; - } else { - mCurrElem = mCurrElem.createChild(localName); - } - doWriteStartTag(localName); - - } - - public void writeEmptyElement(String nsURI, String localName) - throws XMLStreamException - { - writeStartOrEmpty(localName, nsURI); - mEmptyElement = true; - } - - public void writeEmptyElement(String prefix, String localName, String nsURI) - throws XMLStreamException - { - writeStartOrEmpty(prefix, localName, nsURI); - mEmptyElement = true; - } - - public void writeEndElement() - throws XMLStreamException - { - doWriteEndTag(null, mCfgAutomaticEmptyElems); - } - - /** - * This method is assumed to just use default namespace (if any), - * and no further checks should be done. - */ - public void writeStartElement(String localName) - throws XMLStreamException - { - checkStartElement(localName, null); - if (mValidator != null) { - mValidator.validateElementStart(localName, XmlConsts.ELEM_NO_NS_URI, XmlConsts.ELEM_NO_PREFIX); - } - mEmptyElement = false; - if (mOutputElemPool != null) { - SimpleOutputElement newCurr = mOutputElemPool; - mOutputElemPool = newCurr.reuseAsChild(mCurrElem, localName); - --mPoolSize; - mCurrElem = newCurr; - } else { - mCurrElem = mCurrElem.createChild(localName); - } - - doWriteStartTag(localName); - } - - public void writeStartElement(String nsURI, String localName) - throws XMLStreamException - { - writeStartOrEmpty(localName, nsURI); - mEmptyElement = false; - } - - public void writeStartElement(String prefix, String localName, String nsURI) - throws XMLStreamException - { - writeStartOrEmpty(prefix, localName, nsURI); - mEmptyElement = false; - } - - protected void writeTypedAttribute(String prefix, String nsURI, String localName, - AsciiValueEncoder enc) - throws XMLStreamException - { - if (!mStartElementOpen) { - throwOutputError(ErrorConsts.WERR_ATTR_NO_ELEM); - } - if (mCheckAttrs) { // still need to ensure no duplicate attrs? - mCurrElem.checkAttrWrite(nsURI, localName); - } - try { - if (mValidator == null) { - if (prefix == null || prefix.length() == 0) { - mWriter.writeTypedAttribute(localName, enc); - } else { - mWriter.writeTypedAttribute(prefix, localName, enc); - } - } else { - mWriter.writeTypedAttribute - (prefix, localName, nsURI, enc, mValidator, getCopyBuffer()); - } - } catch (IOException ioe) { - throw new WstxIOException(ioe); - } - } - - /* - //////////////////////////////////////////////////// - // Remaining XMLStreamWriter2 methods (StAX2) - //////////////////////////////////////////////////// - */ - - /** - * Similar to {@link #writeEndElement}, but never allows implicit - * creation of empty elements. - */ - public void writeFullEndElement() - throws XMLStreamException - { - doWriteEndTag(null, false); - } - - /* - //////////////////////////////////////////////////// - // Remaining ValidationContext methods (StAX2) - //////////////////////////////////////////////////// - */ - - public QName getCurrentElementName() - { - return mCurrElem.getName(); - } - - public String getNamespaceURI(String prefix) { - return mCurrElem.getNamespaceURI(prefix); - } - - /* - ////////////////////////////////////////////////////////// - // Implementations for base-class defined abstract methods - ////////////////////////////////////////////////////////// - */ - - /** - * Method called by {@link javax.xml.stream.XMLEventWriter} implementation - * (instead of the version - * that takes no argument), so that we can verify it does match the - * start element, if necessary - */ - public void writeEndElement(QName name) - throws XMLStreamException - { - doWriteEndTag(mCheckStructure ? name : null, mCfgAutomaticEmptyElems); - } - - /** - * Method called to close an open start element, when another - * main-level element (not namespace declaration or attribute) - * is being output; except for end element which is handled differently. - * - * @param emptyElem If true, the element being closed is an empty - * element; if false, a separate stand-alone start element. - */ - protected void closeStartElement(boolean emptyElem) - throws XMLStreamException - { - mStartElementOpen = false; - - try { - if (emptyElem) { - mWriter.writeStartTagEmptyEnd(); - } else { - mWriter.writeStartTagEnd(); - } - } catch (IOException ioe) { - throw new WstxIOException(ioe); - } - - if (mValidator != null) { - mVldContent = mValidator.validateElementAndAttributes(); - } - - // Need bit more special handling for empty elements... - if (emptyElem) { - SimpleOutputElement curr = mCurrElem; - mCurrElem = curr.getParent(); - if (mCurrElem.isRoot()) { // Did we close the root? (isRoot() returns true for the virtual "document node") - mState = STATE_EPILOG; - } - if (mValidator != null) { - mVldContent = mValidator.validateElementEnd - (curr.getLocalName(), curr.getNamespaceURI(), curr.getPrefix()); - } - if (mPoolSize < MAX_POOL_SIZE) { - curr.addToPool(mOutputElemPool); - mOutputElemPool = curr; - ++mPoolSize; - } - } - } - - protected String getTopElementDesc() { - return mCurrElem.getNameDesc(); - } - - /* - //////////////////////////////////////////////////// - // Package methods sub-classes may also need - //////////////////////////////////////////////////// - */ - - /** - * Method that is called to ensure that we can start writing an - * element, both from structural point of view, and from syntactic - * (close previously open start element, if any). - */ - protected void checkStartElement(String localName, String prefix) - throws XMLStreamException - { - // Need to finish an open start element? - if (mStartElementOpen) { - closeStartElement(mEmptyElement); - } else if (mState == STATE_PROLOG) { - verifyRootElement(localName, prefix); - } else if (mState == STATE_EPILOG) { - if (mCheckStructure) { - String name = (prefix == null || prefix.length() == 0) ? - localName : (prefix + ":" + localName); - reportNwfStructure(ErrorConsts.WERR_PROLOG_SECOND_ROOT, name); - } - /* When outputting a fragment, need to reset this to the - * tree. No point in trying to verify the root element? - */ - mState = STATE_TREE; - } - } - - protected final void doWriteAttr(String localName, String nsURI, String prefix, - String value) - throws XMLStreamException - { - if (mCheckAttrs) { // still need to ensure no duplicate attrs? - mCurrElem.checkAttrWrite(nsURI, localName); - } - - if (mValidator != null) { - /* No need to get it normalized... even if validator does normalize - * it, we don't use that for anything - */ - mValidator.validateAttribute(localName, nsURI, prefix, value); - } - try { - int vlen = value.length(); - // Worthwhile to make a local copy? - if (vlen >= ATTR_MIN_ARRAYCOPY) { - char[] buf = mCopyBuffer; - if (buf == null) { - mCopyBuffer = buf = mConfig.allocMediumCBuffer(DEFAULT_COPYBUFFER_LEN); - } - /* Ok, and in unlikely case of attribute values longer than - * buffer... for now, let's just skip those case - */ - if (vlen <= buf.length) { - value.getChars(0, vlen, buf, 0); - if (prefix != null && prefix.length() > 0) { - mWriter.writeAttribute(prefix, localName, buf, 0, vlen); - } else { - mWriter.writeAttribute(localName, buf, 0, vlen); - } - return; - } - } - if (prefix != null && prefix.length() > 0) { - mWriter.writeAttribute(prefix, localName, value); - } else { - mWriter.writeAttribute(localName, value); - } - } catch (IOException ioe) { - throw new WstxIOException(ioe); - } - } - - protected final void doWriteAttr(String localName, String nsURI, String prefix, - char[] buf, int start, int len) - throws XMLStreamException - { - if (mCheckAttrs) { // still need to ensure no duplicate attrs? - mCurrElem.checkAttrWrite(nsURI, localName); - } - - if (mValidator != null) { - /* No need to get it normalized... even if validator does normalize - * it, we don't use that for anything - */ - mValidator.validateAttribute(localName, nsURI, prefix, buf, start, len); - } - try { - if (prefix != null && prefix.length() > 0) { - mWriter.writeAttribute(prefix, localName, buf, start, len); - } else { - mWriter.writeAttribute(localName, buf, start, len); - } - } catch (IOException ioe) { - throw new WstxIOException(ioe); - } - } - - protected void doWriteNamespace(String prefix, String nsURI) - throws XMLStreamException - { - try { - int vlen = nsURI.length(); - // Worthwhile to make a local copy? - if (vlen >= ATTR_MIN_ARRAYCOPY) { - char[] buf = mCopyBuffer; - if (buf == null) { - mCopyBuffer = buf = mConfig.allocMediumCBuffer(DEFAULT_COPYBUFFER_LEN); - } - // Let's not bother with too long, though - if (vlen <= buf.length) { - nsURI.getChars(0, vlen, buf, 0); - mWriter.writeAttribute(XMLConstants.XMLNS_ATTRIBUTE, prefix, buf, 0, vlen); - return; - } - } - mWriter.writeAttribute(XMLConstants.XMLNS_ATTRIBUTE, prefix, nsURI); - } catch (IOException ioe) { - throw new WstxIOException(ioe); - } - } - - protected void doWriteDefaultNs(String nsURI) - throws XMLStreamException - { - try { - int vlen = (nsURI == null) ? 0 : nsURI.length(); - // Worthwhile to make a local copy? - if (vlen >= ATTR_MIN_ARRAYCOPY) { - char[] buf = mCopyBuffer; - if (buf == null) { - mCopyBuffer = buf = mConfig.allocMediumCBuffer(DEFAULT_COPYBUFFER_LEN); - } - // Let's not bother with too long, though - if (vlen <= buf.length) { - nsURI.getChars(0, vlen, buf, 0); - mWriter.writeAttribute(XMLConstants.XMLNS_ATTRIBUTE, buf, 0, vlen); - return; - } - } - mWriter.writeAttribute(XMLConstants.XMLNS_ATTRIBUTE, nsURI); - } catch (IOException ioe) { - throw new WstxIOException(ioe); - } - } - - protected final void doWriteStartTag(String localName) - throws XMLStreamException - { - mAnyOutput = true; - mStartElementOpen = true; - try { - mWriter.writeStartTagStart(localName); - } catch (IOException ioe) { - throw new WstxIOException(ioe); - } - } - - protected final void doWriteStartTag(String prefix, String localName) - throws XMLStreamException - { - mAnyOutput = true; - mStartElementOpen = true; - try { - boolean hasPrefix = (prefix != null && prefix.length() > 0); - if (hasPrefix) { - mWriter.writeStartTagStart(prefix, localName); - } else { - mWriter.writeStartTagStart(localName); - } - } catch (IOException ioe) { - throw new WstxIOException(ioe); - } - } - - /** - * - * @param expName Name that the closing element should have; null - * if whatever is in stack should be used - * @param allowEmpty If true, is allowed to create the empty element - * if the closing element was truly empty; if false, has to write - * the full empty element no matter what - */ - protected void doWriteEndTag(QName expName, boolean allowEmpty) - throws XMLStreamException - { - /* First of all, do we need to close up an earlier empty element? - * (open start element that was not created via call to - * writeEmptyElement gets handled later on) - */ - if (mStartElementOpen && mEmptyElement) { - mEmptyElement = false; - closeStartElement(true); - } - - // Better have something to close... (to figure out what to close) - if (mState != STATE_TREE) { - // Have to always throw exception... don't necessarily know the name - reportNwfStructure("No open start element, when trying to write end element"); - } - - SimpleOutputElement thisElem = mCurrElem; - String prefix = thisElem.getPrefix(); - String localName = thisElem.getLocalName(); - String nsURI = thisElem.getNamespaceURI(); - - // Ok, and then let's pop that element from the stack - mCurrElem = thisElem.getParent(); - // Need to return the instance to pool? - if (mPoolSize < MAX_POOL_SIZE) { - thisElem.addToPool(mOutputElemPool); - mOutputElemPool = thisElem; - ++mPoolSize; - } - - if (mCheckStructure) { - if (expName != null) { - // Let's only check the local name, for now... - if (!localName.equals(expName.getLocalPart())) { - /* Only gets called when trying to output an XMLEvent... in - * which case names can actually be compared - */ - reportNwfStructure("Mismatching close element local name, '"+localName+"'; expected '"+expName.getLocalPart()+"'."); - } - } - } - - /* Now, do we have an unfinished start element (created via - * writeStartElement() earlier)? - */ - if (mStartElementOpen) { - /* Can't/shouldn't call closeStartElement, but need to do same - * processing. Thus, this is almost identical to closeStartElement: - */ - if (mValidator != null) { - /* Note: return value is not of much use, since the - * element will be closed right away... - */ - mVldContent = mValidator.validateElementAndAttributes(); - } - mStartElementOpen = false; - try { - //If an EmptyElementHandler is provided use it to determine if allowEmpty is set - if (mEmptyElementHandler != null) { - allowEmpty = mEmptyElementHandler.allowEmptyElement(prefix, localName, nsURI, allowEmpty); - } - // We could write an empty element, implicitly? - if (allowEmpty) { - mWriter.writeStartTagEmptyEnd(); - if (mCurrElem.isRoot()) { - mState = STATE_EPILOG; - } - if (mValidator != null) { - mVldContent = mValidator.validateElementEnd(localName, nsURI, prefix); - } - return; - } - // Nah, need to close open elem, and then output close elem - mWriter.writeStartTagEnd(); - } catch (IOException ioe) { - throw new WstxIOException(ioe); - } - } - - try { - mWriter.writeEndTag(prefix, localName); - } catch (IOException ioe) { - throw new WstxIOException(ioe); - } - - if (mCurrElem.isRoot()) { - mState = STATE_EPILOG; - } - - // Ok, time to validate... - if (mValidator != null) { - mVldContent = mValidator.validateElementEnd(localName, nsURI, prefix); - } - } - - /* - //////////////////////////////////////////////////// - // More abstract methods for sub-classes to implement - //////////////////////////////////////////////////// - */ - - public abstract void doSetPrefix(String prefix, String uri) - throws XMLStreamException; - - public abstract void writeDefaultNamespace(String nsURI) - throws XMLStreamException; - - public abstract void writeNamespace(String prefix, String nsURI) - throws XMLStreamException; - - public abstract void writeStartElement(StartElement elem) - throws XMLStreamException; - - protected abstract void writeStartOrEmpty(String localName, String nsURI) - throws XMLStreamException; - - protected abstract void writeStartOrEmpty(String prefix, String localName, String nsURI) - throws XMLStreamException; -} diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/sw/BaseStreamWriter.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/sw/BaseStreamWriter.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/sw/BaseStreamWriter.java 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/sw/BaseStreamWriter.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,1746 +0,0 @@ -/* Woodstox XML processor - * - * Copyright (c) 2004- Tatu Saloranta, tatu.saloranta@iki.fi - * - * Licensed under the License specified in file LICENSE, included with - * the source code. - * You may not use this file except in compliance with the License. - * - * 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 com.ctc.wstx.sw; - -import java.io.IOException; -import java.io.Writer; -import java.text.MessageFormat; - -import javax.xml.namespace.NamespaceContext; -import javax.xml.namespace.QName; -import javax.xml.stream.Location; -import javax.xml.stream.XMLReporter; -import javax.xml.stream.XMLStreamException; -import javax.xml.stream.XMLStreamWriter; - -// unfortunate dependencies to StAX events: -import javax.xml.stream.events.Characters; -import javax.xml.stream.events.StartElement; - -import org.codehaus.stax2.DTDInfo; -import org.codehaus.stax2.XMLStreamLocation2; -import org.codehaus.stax2.XMLStreamReader2; -import org.codehaus.stax2.ri.Stax2WriterImpl; -import org.codehaus.stax2.validation.*; - -import com.ctc.wstx.api.WriterConfig; -import com.ctc.wstx.api.WstxInputProperties; -import com.ctc.wstx.api.WstxOutputProperties; -import com.ctc.wstx.cfg.ErrorConsts; -import com.ctc.wstx.cfg.OutputConfigFlags; -import com.ctc.wstx.cfg.XmlConsts; -import com.ctc.wstx.exc.*; -import com.ctc.wstx.io.WstxInputLocation; -import com.ctc.wstx.sr.StreamReaderImpl; -import com.ctc.wstx.sr.AttributeCollector; -import com.ctc.wstx.sr.InputElementStack; -import com.ctc.wstx.util.DataUtil; -import com.ctc.wstx.util.StringUtil; - -/** - * Base class for {@link XMLStreamWriter} implementations Woodstox has. - * Contains partial stream writer implementation, plus utility methods - * shared by concrete implementation classes. Main reason for such - * abstract base class is to allow other parts of Woodstox core to refer - * to any of stream writer implementations in general way. - */ -public abstract class BaseStreamWriter - extends Stax2WriterImpl - implements ValidationContext, OutputConfigFlags -{ - protected final static int STATE_PROLOG = 1; - protected final static int STATE_TREE = 2; - protected final static int STATE_EPILOG = 3; - - protected final static char CHAR_SPACE = ' '; - - /** - * This constant defines minimum length of a String, for which it - * is beneficial to do an intermediate copy (using String.getChars()), - * and iterate over intermediate array, instead of iterating using - * String.charAt(). Former is generally faster for longer Strings, but - * has some overhead for shorter Strings. Tests indicate that the - * threshold is somewhere between 8 and 16 characters, at least on - * x86 platform. - */ - protected final static int MIN_ARRAYCOPY = 12; - - protected final static int ATTR_MIN_ARRAYCOPY = 12; - - protected final static int DEFAULT_COPYBUFFER_LEN = 512; - - /* - /////////////////////////////////////////////////////////// - // Output objects - /////////////////////////////////////////////////////////// - */ - - /** - * Actual physical writer to output serialized XML content to - */ - protected final XmlWriter mWriter; - - /** - * Intermediate buffer into which characters of a String can be - * copied, in cases where such a copy followed by array access - * is faster than calling String.charAt() (which - * perhaps surprisingly is often case, and especially significant - * for longer buffers). - */ - protected char[] mCopyBuffer = null; - - /* - /////////////////////////////////////////////////////////// - // Per-factory configuration (options, features) - /////////////////////////////////////////////////////////// - */ - - protected final WriterConfig mConfig; - - // // // Specialized configuration flags, extracted from config flags: - - protected final boolean mCfgCDataAsText; - protected final boolean mCfgCopyDefaultAttrs; - protected final boolean mCfgAutomaticEmptyElems; - - // NOTE: can not be final, may be enabled when schema (etc) validation enabled - - protected boolean mCheckStructure; - protected boolean mCheckAttrs; - - /* - /////////////////////////////////////////////////////////// - // Per-writer configuration - /////////////////////////////////////////////////////////// - */ - - /** - * Encoding to use; may be passed from the factory (when - * a method that defines encoding is used), updated by - * a call to {@link #writeStartDocument}, or null if - * neither. Is passed to the escaping writer factory to - * allow escaping writers to do additional escaping if - * necessary (like encapsulating non-ascii chars in a doc - * encoded usig ascii). - */ - protected String mEncoding; - - /** - * Optional validator to use for validating output against - * one or more schemas, and/or for safe pretty-printing (indentation). - */ - protected XMLValidator mValidator = null; - - /** - * Since XML 1.1 has some differences to 1.0, we need to keep a flag - * to indicate if we were to output XML 1.1 document. - */ - protected boolean mXml11 = false; - - /** - * Custom validation problem handler, if any. - */ - protected ValidationProblemHandler mVldProbHandler = null; - - /* - //////////////////////////////////////////////////// - // State information - //////////////////////////////////////////////////// - */ - - protected int mState = STATE_PROLOG; - - /** - * Flag that is set to true first time something has been output. - * Generally needed to keep track of whether XML declaration - * (START_DOCUMENT) can be output or not. - */ - protected boolean mAnyOutput = false; - - /** - * Flag that is set during time that a start element is "open", ie. - * START_ELEMENT has been output (and possibly zero or more name - * space declarations and attributes), before other main-level - * constructs have been output. - */ - protected boolean mStartElementOpen = false; - - /** - * Flag that indicates that current element is an empty element (one - * that is explicitly defined as one, by calling a method -- NOT one - * that just happens to be empty). - * This is needed to know what to do when next non-ns/attr node - * is output; normally a new context is opened, but for empty - * elements not. - */ - protected boolean mEmptyElement = false; - - /** - * State value used with validation, to track types of content - * that is allowed at this point in output stream. Only used if - * validation is enabled: if so, value is determined via validation - * callbacks. - */ - protected int mVldContent = XMLValidator.CONTENT_ALLOW_ANY_TEXT; - - /** - * Value passed as the expected root element, when using the multiple - * argument {@link #writeDTD} method. Will be used in structurally - * validating mode (and in dtd-validating mode, since that automatically - * enables structural validation as well, to pre-filter well-formedness - * errors that validators might have trouble dealing with). - */ - protected String mDtdRootElem = null; - - protected boolean mReturnNullForDefaultNamespace; - - /* - //////////////////////////////////////////////////// - // Life-cycle - //////////////////////////////////////////////////// - */ - - protected BaseStreamWriter(XmlWriter xw, String enc, WriterConfig cfg) - { - mWriter = xw; - mEncoding = enc; - mConfig = cfg; - - int flags = cfg.getConfigFlags(); - - mCheckStructure = (flags & OutputConfigFlags.CFG_VALIDATE_STRUCTURE) != 0; - mCheckAttrs = (flags & OutputConfigFlags.CFG_VALIDATE_ATTR) != 0; - - mCfgAutomaticEmptyElems = (flags & OutputConfigFlags.CFG_AUTOMATIC_EMPTY_ELEMENTS) != 0; - mCfgCDataAsText = (flags & OutputConfigFlags.CFG_OUTPUT_CDATA_AS_TEXT) != 0; - mCfgCopyDefaultAttrs = (flags & OutputConfigFlags.CFG_COPY_DEFAULT_ATTRS) != 0; - - Object value = getProperty(WstxInputProperties.P_RETURN_NULL_FOR_DEFAULT_NAMESPACE); - mReturnNullForDefaultNamespace = (value instanceof Boolean) && ((Boolean) value).booleanValue(); - } - - /* - /////////////////////////////////////////////////////////// - // XMLStreamWriter API - /////////////////////////////////////////////////////////// - */ - - public void close() - throws XMLStreamException - { - /* 19-Jul-2004, TSa: Hmmh. Let's actually close all still open - * elements, starting with currently open start (-> empty) - * element, if one exists, and then closing scopes by adding - * matching end elements. - */ - _finishDocument(false); - } - - public void flush() - throws XMLStreamException - { - /* Note: there have been changes to exact scope of flushing - * (with Woodstox versions 2.x and 3.x); but the current - * one of just flushing the underlying OutputStream or Writer - * should be the interpretation compatible with the Stax specs. - */ - try { - mWriter.flush(); - } catch (IOException ie) { - throw new WstxIOException(ie); - } - } - - public abstract NamespaceContext getNamespaceContext(); - - public abstract String getPrefix(String uri); - - public Object getProperty(String name) - { - /* These properties just exist for interoperability with - * toolkits that were designed to work with Sun's parser (which - * introduced properties) - */ - if (name.equals(WstxOutputProperties.P_OUTPUT_UNDERLYING_STREAM)) { - return mWriter.getOutputStream(); - } - if (name.equals(WstxOutputProperties.P_OUTPUT_UNDERLYING_WRITER)) { - return mWriter.getWriter(); - } - return mConfig.getProperty(name); - } - - public abstract void setDefaultNamespace(String uri) - throws XMLStreamException; - - public abstract void setNamespaceContext(NamespaceContext context) - throws XMLStreamException; - - public abstract void setPrefix(String prefix, String uri) - throws XMLStreamException; - - public abstract void writeAttribute(String localName, String value) - throws XMLStreamException; - - public abstract void writeAttribute(String nsURI, String localName, - String value) - throws XMLStreamException; - - public abstract void writeAttribute(String prefix, String nsURI, - String localName, String value) - throws XMLStreamException; - - public void writeCData(String data) - throws XMLStreamException - { - /* 02-Dec-2004, TSa: Maybe the writer is to "re-direct" these - * writes as normal text? (sometimes useful to deal with broken - * XML parsers, for example) - */ - if (mCfgCDataAsText) { - writeCharacters(data); - return; - } - - mAnyOutput = true; - // Need to finish an open start element? - if (mStartElementOpen) { - closeStartElement(mEmptyElement); - } - verifyWriteCData(); - if (mVldContent == XMLValidator.CONTENT_ALLOW_VALIDATABLE_TEXT - && mValidator != null) { - /* Last arg is false, since we do not know if more text - * may be added with additional calls - */ - mValidator.validateText(data, false); - } - int ix; - try { - ix = mWriter.writeCData(data); - } catch (IOException ioe) { - throw new WstxIOException(ioe); - } - if (ix >= 0) { // unfixable problems? - reportNwfContent(ErrorConsts.WERR_CDATA_CONTENT, DataUtil.Integer(ix)); - } - } - - public void writeCharacters(char[] text, int start, int len) - throws XMLStreamException - { - mAnyOutput = true; - // Need to finish an open start element? - if (mStartElementOpen) { - closeStartElement(mEmptyElement); - } - - /* Not legal outside main element tree, except if it's all - * white space - */ - if (mCheckStructure) { - if (inPrologOrEpilog()) { - if (!StringUtil.isAllWhitespace(text, start, len)) { - reportNwfStructure(ErrorConsts.WERR_PROLOG_NONWS_TEXT); - } - } - } - // 08-Dec-2005, TSa: validator-based validation? - if (mVldContent <= XMLValidator.CONTENT_ALLOW_WS) { - if (mVldContent == XMLValidator.CONTENT_ALLOW_NONE) { // never ok - reportInvalidContent(CHARACTERS); - } else { // all-ws is ok... - if (!StringUtil.isAllWhitespace(text, start, len)) { - reportInvalidContent(CHARACTERS); - } - } - } else if (mVldContent == XMLValidator.CONTENT_ALLOW_VALIDATABLE_TEXT) { - if (mValidator != null) { - /* Last arg is false, since we do not know if more text - * may be added with additional calls - */ - mValidator.validateText(text, start, len, false); - } - } - - if (len > 0) { // minor optimization - try { - /* 21-Jun-2006, TSa: Fixing [WSTX-59]: no quoting can be done - * outside of element tree. - */ - if (inPrologOrEpilog()) { - mWriter.writeRaw(text, start, len); - } else { - mWriter.writeCharacters(text, start, len); - } - } catch (IOException ioe) { - throw new WstxIOException(ioe); - } - } - } - - public void writeCharacters(String text) - throws XMLStreamException - { - mAnyOutput = true; - // Need to finish an open start element? - if (mStartElementOpen) { - closeStartElement(mEmptyElement); - } - - // Need to validate structure? - if (mCheckStructure) { - // Not valid in prolog/epilog, except if it's all white space: - if (inPrologOrEpilog()) { - if (!StringUtil.isAllWhitespace(text)) { - reportNwfStructure(ErrorConsts.WERR_PROLOG_NONWS_TEXT); - } - } - } - - /* 08-Dec-2005, TSa: validator-based validation? - * Note: although it'd be good to check validity first, we - * do not know allowed textual content before actually writing - * pending start element (if any)... so can't call this earlier - */ - if (mVldContent <= XMLValidator.CONTENT_ALLOW_WS) { - if (mVldContent == XMLValidator.CONTENT_ALLOW_NONE) { // never ok - reportInvalidContent(CHARACTERS); - } else { // all-ws is ok... - if (!StringUtil.isAllWhitespace(text)) { - reportInvalidContent(CHARACTERS); - } - } - } else if (mVldContent == XMLValidator.CONTENT_ALLOW_VALIDATABLE_TEXT) { - if (mValidator != null) { - /* Last arg is false, since we do not know if more text - * may be added with additional calls - */ - mValidator.validateText(text, false); - } - } - - // Ok, let's just write it out - /* 21-Jun-2006, TSa: Fixing [WSTX-59]: no quoting can be done - * outside of element tree. - */ - if (inPrologOrEpilog()) { - try { - mWriter.writeRaw(text); - } catch (IOException ioe) { - throw new WstxIOException(ioe); - } - return; - } - - /* Now, would it pay off to make an intermediate copy? - * String.getChars (which uses System.arraycopy()) is - * very fast compared to access via String.charAt. - */ - int len = text.length(); - if (len >= MIN_ARRAYCOPY) { - char[] buf = getCopyBuffer(); - - int offset = 0; - while (len > 0) { - int thisLen = (len > buf.length) ? buf.length : len; - text.getChars(offset, offset+thisLen, buf, 0); - try { - mWriter.writeCharacters(buf, 0, thisLen); - } catch (IOException ioe) { - throw new WstxIOException(ioe); - } - offset += thisLen; - len -= thisLen; - } - } else { // nope, let's just access String using charAt(). - try { - mWriter.writeCharacters(text); - } catch (IOException ioe) { - throw new WstxIOException(ioe); - } - } - } - - public void writeComment(String data) - throws XMLStreamException - { - mAnyOutput = true; - // Need to finish an open start element? - if (mStartElementOpen) { - closeStartElement(mEmptyElement); - } - - // 08-Dec-2005, TSa: validator-based validation? - if (mVldContent == XMLValidator.CONTENT_ALLOW_NONE) { - reportInvalidContent(COMMENT); - } - - /* No structural validation needed per se, for comments; they are - * allowed anywhere in XML content. However, content may need to - * be checked (by XmlWriter) - */ - int ix; - try { - ix = mWriter.writeComment(data); - } catch (IOException ioe) { - throw new WstxIOException(ioe); - } - - if (ix >= 0) { - reportNwfContent(ErrorConsts.WERR_COMMENT_CONTENT, DataUtil.Integer(ix)); - } - } - - public abstract void writeDefaultNamespace(String nsURI) - throws XMLStreamException; - - public void writeDTD(String dtd) - throws XMLStreamException - { - verifyWriteDTD(); - mDtdRootElem = ""; // marker to verify only one is output - try { - mWriter.writeDTD(dtd); - } catch (IOException ioe) { - throw new WstxIOException(ioe); - } - - /* 20-Dec-2005, TSa: Should we try to decipher what was actually - * written, for validation? - */ - } - - public abstract void writeEmptyElement(String localName) - throws XMLStreamException; - - public abstract void writeEmptyElement(String nsURI, String localName) - throws XMLStreamException; - - public abstract void writeEmptyElement(String prefix, String localName, String nsURI) - throws XMLStreamException; - - public void writeEndDocument() throws XMLStreamException - { - _finishDocument(false); - } - - public abstract void writeEndElement() throws XMLStreamException; - - public void writeEntityRef(String name) - throws XMLStreamException - { - mAnyOutput = true; - // Need to finish an open start element? - if (mStartElementOpen) { - closeStartElement(mEmptyElement); - } - - // Structurally, need to check we are not in prolog/epilog. - if (mCheckStructure) { - if (inPrologOrEpilog()) { - reportNwfStructure("Trying to output an entity reference outside main element tree (in prolog or epilog)"); - } - } - // 08-Dec-2005, TSa: validator-based validation? - if (mVldContent == XMLValidator.CONTENT_ALLOW_NONE) { - /* May be char entity, general entity; whatever it is it's - * invalid! - */ - reportInvalidContent(ENTITY_REFERENCE); - } - - //if (mValidator != null) { - /* !!! 11-Dec-2005, TSa: Should be able to use DTD based validators - * to check if entity has been declared... - */ - //} - - try { - mWriter.writeEntityReference(name); - } catch (IOException ioe) { - throw new WstxIOException(ioe); - } - } - - public abstract void writeNamespace(String prefix, String nsURI) - throws XMLStreamException; - - public void writeProcessingInstruction(String target) - throws XMLStreamException - { - writeProcessingInstruction(target, null); - } - - public void writeProcessingInstruction(String target, String data) - throws XMLStreamException - { - mAnyOutput = true; - // Need to finish an open start element? - if (mStartElementOpen) { - closeStartElement(mEmptyElement); - } - - // Structurally, PIs are always ok (content might not be) - // 08-Dec-2005, TSa: validator-based validation? - if (mVldContent == XMLValidator.CONTENT_ALLOW_NONE) { - reportInvalidContent(PROCESSING_INSTRUCTION); - } - int ix; - try { - ix = mWriter.writePI(target, data); - } catch (IOException ioe) { - throw new WstxIOException(ioe); - } - if (ix >= 0) { - throw new XMLStreamException("Illegal input: processing instruction content has embedded '?>' in it (index "+ix+")"); - } - } - - public void writeStartDocument() - throws XMLStreamException - { - /* 03-Feb-2005, TSa: As per StAX 1.0 specs, version should - * be "1.0", and encoding "utf-8" (yes, lower case... it's - * wrong, but specs mandate it) - */ - /* 11-Jan-2006, TSa: Let's actually rather use whatever was passed - * in, if anything; only if none then default to something else. - * Plus, what the heck; let's use properly capitalized value - * too (and ignore faulty def in stax specs). - */ - if (mEncoding == null) { - mEncoding = WstxOutputProperties.DEFAULT_OUTPUT_ENCODING; - } - writeStartDocument(mEncoding, WstxOutputProperties.DEFAULT_XML_VERSION); - } - - public void writeStartDocument(String version) - throws XMLStreamException - { - writeStartDocument(mEncoding, version); - } - - public void writeStartDocument(String encoding, String version) - throws XMLStreamException - { - doWriteStartDocument(version, encoding, null); - } - - protected void doWriteStartDocument(String version, String encoding, - String standAlone) - throws XMLStreamException - { - /* Not legal to output XML declaration if there has been ANY - * output prior... that is, if we validate the structure. - */ - if (mCheckStructure) { - if (mAnyOutput) { - reportNwfStructure("Can not output XML declaration, after other output has already been done."); - } - } - - mAnyOutput = true; - - if (mConfig.willValidateContent()) { - // !!! 06-May-2004, TSa: Should validate encoding? - /*if (encoding != null) { - }*/ - if (version != null && version.length() > 0) { - if (!(version.equals(XmlConsts.XML_V_10_STR) - || version.equals(XmlConsts.XML_V_11_STR))) { - reportNwfContent("Illegal version argument ('"+version - +"'); should only use '"+XmlConsts.XML_V_10_STR - +"' or '"+XmlConsts.XML_V_11_STR+"'"); - } - } - } - - if (version == null || version.length() == 0) { - version = WstxOutputProperties.DEFAULT_XML_VERSION; - } - - /* 04-Feb-2006, TSa: Need to know if we are writing XML 1.1 - * document... - */ - mXml11 = XmlConsts.XML_V_11_STR.equals(version); - if (mXml11) { - mWriter.enableXml11(); - } - - if (encoding != null && encoding.length() > 0) { - /* 03-May-2005, TSa: But what about conflicting encoding? Let's - * only update encoding, if it wasn't set. - */ - if (mEncoding == null || mEncoding.length() == 0) { - mEncoding = encoding; - } - } - try { - mWriter.writeXmlDeclaration(version, encoding, standAlone); - } catch (IOException ioe) { - throw new WstxIOException(ioe); - } - } - - public abstract void writeStartElement(String localName) - throws XMLStreamException; - - public abstract void writeStartElement(String nsURI, String localName) - throws XMLStreamException; - - public abstract void writeStartElement(String prefix, String localName, - String nsURI) - throws XMLStreamException; - - /* - /////////////////////////////////////////////////////////// - // XMLStreamWriter2 methods (StAX2) - /////////////////////////////////////////////////////////// - */ - - /** - * Method that essentially copies event that the specified reader has - * just read. - * - * @param sr Stream reader to use for accessing event to copy - * @param preserveEventData If true, writer is not allowed to change - * the state of the reader (so that all the data associated with the - * current event has to be preserved); if false, writer is allowed - * to use methods that may cause some data to be discarded. Setting - * this to false may improve the performance, since it may allow - * full no-copy streaming of data, especially textual contents. - */ - public void copyEventFromReader(XMLStreamReader2 sr, boolean preserveEventData) - throws XMLStreamException - { - try { - switch (sr.getEventType()) { - case START_DOCUMENT: - { - String version = sr.getVersion(); - /* No real declaration? If so, we don't want to output - * anything, to replicate as closely as possible the - * source document - */ - if (version == null || version.length() == 0) { - ; // no output if no real input - } else { - if (sr.standaloneSet()) { - writeStartDocument(sr.getVersion(), - sr.getCharacterEncodingScheme(), - sr.isStandalone()); - } else { - writeStartDocument(sr.getCharacterEncodingScheme(), - sr.getVersion()); - } - } - } - return; - - case END_DOCUMENT: - writeEndDocument(); - return; - - // Element start/end events: - case START_ELEMENT: - if (sr instanceof StreamReaderImpl) { - StreamReaderImpl impl = (StreamReaderImpl) sr; - copyStartElement(impl.getInputElementStack(), impl.getAttributeCollector()); - } else { // otherwise impl from Stax ref. impl (Stax2WriterImpl) has to do: - super.copyStartElement(sr); - } - return; - - case END_ELEMENT: - writeEndElement(); - return; - - case SPACE: - { - mAnyOutput = true; - // Need to finish an open start element? - if (mStartElementOpen) { - closeStartElement(mEmptyElement); - } - /* No need to write as chars, should be pure space - * (caller should have verified); also, no escaping - * necessary. - */ - sr.getText(wrapAsRawWriter(), preserveEventData); - } - return; - - case CDATA: - - // First; is this to be changed to 'normal' text output? - if (!mCfgCDataAsText) { - mAnyOutput = true; - // Need to finish an open start element? - if (mStartElementOpen) { - closeStartElement(mEmptyElement); - } - - // Not legal outside main element tree: - if (mCheckStructure) { - if (inPrologOrEpilog()) { - reportNwfStructure(ErrorConsts.WERR_PROLOG_CDATA); - } - } - /* Note: no need to check content, since reader is assumed - * to have verified it to be valid XML. - */ - mWriter.writeCDataStart(); - sr.getText(wrapAsRawWriter(), preserveEventData); - mWriter.writeCDataEnd(); - return; - } - // fall down if it is to be converted... - - case CHARACTERS: - { - // Let's just assume content is fine... not 100% reliably - // true, but usually is (not true if input had a root - // element surrounding text, but omitted for output) - mAnyOutput = true; - // Need to finish an open start element? - if (mStartElementOpen) { - closeStartElement(mEmptyElement); - } - sr.getText(wrapAsTextWriter(), preserveEventData); - } - return; - - case COMMENT: - { - mAnyOutput = true; - if (mStartElementOpen) { - closeStartElement(mEmptyElement); - } - // No need to check for content (embedded '--'); reader - // is assumed to have verified it's ok (otherwise should - // have thrown an exception for non-well-formed XML) - mWriter.writeCommentStart(); - sr.getText(wrapAsRawWriter(), preserveEventData); - mWriter.writeCommentEnd(); - } - return; - - case PROCESSING_INSTRUCTION: - { - mWriter.writePIStart(sr.getPITarget(), true); - sr.getText(wrapAsRawWriter(), preserveEventData); - mWriter.writePIEnd(); - } - return; - - case DTD: - { - DTDInfo info = sr.getDTDInfo(); - if (info == null) { - // Hmmmh. It is legal for this to happen, for - // non-DTD-aware readers. But what is the right - // thing to do here? - throwOutputError("Current state DOCTYPE, but not DTDInfo Object returned -- reader doesn't support DTDs?"); - } - // Could optimize this a bit (stream the int. subset - // possible), but it's never going to occur more than - // once per document, so it's probably not much of a - // bottleneck, ever - writeDTD(info); - } - return; - - case ENTITY_REFERENCE: - writeEntityRef(sr.getLocalName()); - return; - - case ATTRIBUTE: - case NAMESPACE: - case ENTITY_DECLARATION: - case NOTATION_DECLARATION: - // Let's just fall back to throw the exception - } - } catch (IOException ioe) { - throw new WstxIOException(ioe); - } - - throw new XMLStreamException("Unrecognized event type (" - +sr.getEventType()+"); not sure how to copy"); - } - - /* - /////////////////////////////////////////////////////////// - // StAX2, output handling - /////////////////////////////////////////////////////////// - */ - - public void closeCompletely() - throws XMLStreamException - { - _finishDocument(true); - } - - /* - /////////////////////////////////////////////////////////// - // StAX2, config - /////////////////////////////////////////////////////////// - */ - - // NOTE: getProperty() defined in Stax 1.0 interface - - public boolean isPropertySupported(String name) { - // !!! TBI: not all these properties are really supported - return mConfig.isPropertySupported(name); - } - - /** - * @param name Name of the property to set - * @param value Value to set property to. - * - * @return True, if the specified property was succesfully - * set to specified value; false if its value was not changed - */ - public boolean setProperty(String name, Object value) - { - /* Note: can not call local method, since it'll return false for - * recognized but non-mutable properties - */ - return mConfig.setProperty(name, value); - } - - public XMLValidator validateAgainst(XMLValidationSchema schema) - throws XMLStreamException - { - XMLValidator vld = schema.createValidator(this); - - if (mValidator == null) { - /* Need to enable other validation modes? Structural validation - * should always be done when we have other validators as well, - * as well as attribute uniqueness checks. - */ - mCheckStructure = true; - mCheckAttrs = true; - mValidator = vld; - } else { - mValidator = new ValidatorPair(mValidator, vld); - } - return vld; - } - - public XMLValidator stopValidatingAgainst(XMLValidationSchema schema) - throws XMLStreamException - { - XMLValidator[] results = new XMLValidator[2]; - XMLValidator found = null; - if (ValidatorPair.removeValidator(mValidator, schema, results)) { // found - found = results[0]; - mValidator = results[1]; - found.validationCompleted(false); - if (mValidator == null) { - resetValidationFlags(); - } - } - return found; - } - - public XMLValidator stopValidatingAgainst(XMLValidator validator) - throws XMLStreamException - { - XMLValidator[] results = new XMLValidator[2]; - XMLValidator found = null; - if (ValidatorPair.removeValidator(mValidator, validator, results)) { // found - found = results[0]; - mValidator = results[1]; - found.validationCompleted(false); - if (mValidator == null) { - resetValidationFlags(); - } - } - return found; - } - - public ValidationProblemHandler setValidationProblemHandler(ValidationProblemHandler h) - { - ValidationProblemHandler oldH = mVldProbHandler; - mVldProbHandler = h; - return oldH; - } - - private void resetValidationFlags() - { - int flags = mConfig.getConfigFlags(); - mCheckStructure = (flags & CFG_VALIDATE_STRUCTURE) != 0; - mCheckAttrs = (flags & CFG_VALIDATE_ATTR) != 0; - } - - /* - /////////////////////////////////////////////////////////// - // StAX2, other accessors, mutators - /////////////////////////////////////////////////////////// - */ - - public XMLStreamLocation2 getLocation() - { - return new WstxInputLocation(null, // no parent - null, null, // pub/sys ids not yet known - mWriter.getAbsOffset(), - mWriter.getRow(), mWriter.getColumn()); - } - - public String getEncoding() { - return mEncoding; - } - - /* - /////////////////////////////////////////////////////////// - // StAX2, output methods - /////////////////////////////////////////////////////////// - */ - - public void writeCData(char[] cbuf, int start, int len) - throws XMLStreamException - { - /* 02-Dec-2004, TSa: Maybe the writer is to "re-direct" these - * writes as normal text? (sometimes useful to deal with broken - * XML parsers, for example) - */ - if (mCfgCDataAsText) { - writeCharacters(cbuf, start, len); - return; - } - - mAnyOutput = true; - // Need to finish an open start element? - if (mStartElementOpen) { - closeStartElement(mEmptyElement); - } - verifyWriteCData(); - if (mVldContent == XMLValidator.CONTENT_ALLOW_VALIDATABLE_TEXT - && mValidator != null) { - /* Last arg is false, since we do not know if more text - * may be added with additional calls - */ - mValidator.validateText(cbuf, start, len, false); - } - int ix; - try { - ix = mWriter.writeCData(cbuf, start, len); - } catch (IOException ioe) { - throw new WstxIOException(ioe); - } - if (ix >= 0) { // problems that could not to be fixed? - throwOutputError(ErrorConsts.WERR_CDATA_CONTENT, DataUtil.Integer(ix)); - } - } - - public void writeDTD(DTDInfo info) - throws XMLStreamException - { - writeDTD(info.getDTDRootName(), info.getDTDSystemId(), - info.getDTDPublicId(), info.getDTDInternalSubset()); - } - - public void writeDTD(String rootName, String systemId, String publicId, - String internalSubset) - throws XMLStreamException - { - verifyWriteDTD(); - mDtdRootElem = rootName; - try { - mWriter.writeDTD(rootName, systemId, publicId, internalSubset); - } catch (IOException ioe) { - throw new WstxIOException(ioe); - } - } - - public abstract void writeFullEndElement() throws XMLStreamException; - - public void writeStartDocument(String version, String encoding, - boolean standAlone) - throws XMLStreamException - { - doWriteStartDocument(version, encoding, standAlone ? "yes" : "no"); - } - - public void writeRaw(String text) - throws XMLStreamException - { - mAnyOutput = true; - if (mStartElementOpen) { - closeStartElement(mEmptyElement); - } - try { - mWriter.writeRaw(text, 0, text.length()); - } catch (IOException ioe) { - throw new WstxIOException(ioe); - } - } - - public void writeRaw(String text, int start, int offset) - throws XMLStreamException - { - mAnyOutput = true; - if (mStartElementOpen) { - closeStartElement(mEmptyElement); - } - try { - mWriter.writeRaw(text, start, offset); - } catch (IOException ioe) { - throw new WstxIOException(ioe); - } - } - - public void writeRaw(char[] text, int start, int offset) - throws XMLStreamException - { - mAnyOutput = true; - if (mStartElementOpen) { - closeStartElement(mEmptyElement); - } - try { - mWriter.writeRaw(text, start, offset); - } catch (IOException ioe) { - throw new WstxIOException(ioe); - } - } - - public void writeSpace(String text) - throws XMLStreamException - { - /* For now, let's just use writeRaw(): otherwise would need - * to add it to all backend writers: - */ - writeRaw(text); - } - - public void writeSpace(char[] text, int offset, int length) - throws XMLStreamException - { - // For now, let's just use writeRaw() (see above) - writeRaw(text, offset, length); - } - - /* - /////////////////////////////////////////////////////////// - // ValidationContext interface (StAX2, validation) - /////////////////////////////////////////////////////////// - */ - - public String getXmlVersion() { - return mXml11 ? XmlConsts.XML_V_11_STR : XmlConsts.XML_V_10_STR; - } - - public abstract QName getCurrentElementName(); - - public abstract String getNamespaceURI(String prefix); - - /** - * As of now, there is no way to specify the base URI. Could be improved - * in future, if xml:base is supported. - */ - public String getBaseUri() { - return null; - } - - public Location getValidationLocation() { - return getLocation(); - } - - public void reportProblem(XMLValidationProblem prob) - throws XMLStreamException - { - // Custom handler set? If so, it'll take care of it: - if (mVldProbHandler != null) { - mVldProbHandler.reportProblem(prob); - return; - } - - /* For now let's implement basic functionality: warnings get - * reported via XMLReporter, errors and fatal errors result in - * immediate exceptions. - */ - /* 27-May-2008, TSa: [WSTX-153] Above is incorrect: as per Stax - * javadocs for XMLReporter, both warnings and non-fatal errors - * (which includes all validation errors) should be reported via - * XMLReporter interface, and only fatals should cause an - * immediate stream exception (by-passing reporter) - */ - if (prob.getSeverity() > XMLValidationProblem.SEVERITY_ERROR) { - throw WstxValidationException.create(prob); - } - XMLReporter rep = mConfig.getProblemReporter(); - if (rep != null) { - doReportProblem(rep, prob); - } else { - /* If no reporter, regular non-fatal errors are to be reported - * as exceptions as well, for backwards compatibility - */ - if (prob.getSeverity() >= XMLValidationProblem.SEVERITY_ERROR) { - throw WstxValidationException.create(prob); - } - } - } - - /** - * Adding default attribute values does not usually make sense on - * output side, so the implementation is a NOP for now. - */ - public int addDefaultAttribute(String localName, String uri, String prefix, - String value) - { - // nothing to do, but to indicate we didn't add it... - return -1; - } - - // // // Notation/entity access: not (yet?) implemented - - public boolean isNotationDeclared(String name) { return false; } - - public boolean isUnparsedEntityDeclared(String name) { return false; } - - - // // // Attribute access: not yet implemented: - - /* !!! TODO: Implement attribute access (iff validate-attributes - * enabled? - */ - - public int getAttributeCount() { return 0; } - - public String getAttributeLocalName(int index) { return null; } - - public String getAttributeNamespace(int index) { return null; } - - public String getAttributePrefix(int index) { return null; } - - public String getAttributeValue(int index) { return null; } - - public String getAttributeValue(String nsURI, String localName) { - return null; - } - - public String getAttributeType(int index) { - return ""; - } - - public int findAttributeIndex(String nsURI, String localName) { - return -1; - } - - /* - /////////////////////////////////////////////////////////// - // Package methods (ie not part of public API) - /////////////////////////////////////////////////////////// - */ - - /** - * Method that can be called to get a wrapper instance that - * can be used to essentially call the writeRaw - * method via regular Writer interface. - */ - public final Writer wrapAsRawWriter() - { - return mWriter.wrapAsRawWriter(); - } - - /** - * Method that can be called to get a wrapper instance that - * can be used to essentially call the writeCharacters - * method via regular Writer interface. - */ - public final Writer wrapAsTextWriter() - { - return mWriter.wrapAsTextWriter(); - } - - /** - * Method that is used by output classes to determine whether we - * are in validating mode. - *

- * Note: current implementation of this method is not perfect; it - * may be possible it can return true even if we are only using a DTD - * to get some limited info, without validating? - */ - protected boolean isValidating() { - return (mValidator != null); - } - - /** - * Convenience method needed by {@link javax.xml.stream.XMLEventWriter} - * implementation, to use when - * writing a start element, and possibly its attributes and namespace - * declarations. - */ - public abstract void writeStartElement(StartElement elem) - throws XMLStreamException; - - /** - * Method called by {@link javax.xml.stream.XMLEventWriter} - * (instead of the version - * that takes no argument), so that we can verify it does match the - * start element if necessary. - */ - public abstract void writeEndElement(QName name) - throws XMLStreamException; - - /** - * Method called by {@link javax.xml.stream.XMLEventWriter} - * (instead of more generic - * text output methods), so that we can verify (if necessary) that - * this character output type is legal in this context. Specifically, - * it's not acceptable to add non-whitespace content outside root - * element (in prolog/epilog). - *

- * Note: cut'n pasted from the main writeCharacters; not - * good... but done to optimize white-space cases. - */ - public void writeCharacters(Characters ch) - throws XMLStreamException - { - // Need to finish an open start element? - if (mStartElementOpen) { - closeStartElement(mEmptyElement); - } - - /* Not legal outside main element tree, except if it's all - * white space - */ - if (mCheckStructure) { - if (inPrologOrEpilog()) { - if (!ch.isIgnorableWhiteSpace() && !ch.isWhiteSpace()) { - reportNwfStructure(ErrorConsts.WERR_PROLOG_NONWS_TEXT); - } - } - } - - if (mVldContent <= XMLValidator.CONTENT_ALLOW_WS) { - if (mVldContent == XMLValidator.CONTENT_ALLOW_NONE) { // never ok - reportInvalidContent(CHARACTERS); - } else { // all-ws is ok... - if (!ch.isIgnorableWhiteSpace() && !ch.isWhiteSpace()) { - reportInvalidContent(CHARACTERS); - } - } - } else if (mVldContent == XMLValidator.CONTENT_ALLOW_VALIDATABLE_TEXT) { - if (mValidator != null) { - /* Last arg is false, since we do not know if more text - * may be added with additional calls - */ - mValidator.validateText(ch.getData(), false); - } - } - - // Ok, let's just write it out: - try { - mWriter.writeCharacters(ch.getData()); - } catch (IOException ioe) { - throw new WstxIOException(ioe); - } - } - - /** - * Method called to close an open start element, when another - * main-level element (not namespace declaration or attribute) - * is being output; except for end element which is handled differently. - */ - protected abstract void closeStartElement(boolean emptyElem) - throws XMLStreamException; - - protected final boolean inPrologOrEpilog() { - return (mState != STATE_TREE); - } - - /** - * @param forceRealClose If true, will force calling of close() on the - * underlying physical result (stream, writer). If false, will let - * XmlWriter decide whether to call close(); will be done if auto-closing - * enabled, but not otherwise. - */ - private final void _finishDocument(boolean forceRealClose) - throws XMLStreamException - { - // Is tree still open? - if (mState != STATE_EPILOG) { - if (mCheckStructure && mState == STATE_PROLOG) { - reportNwfStructure("Trying to write END_DOCUMENT when document has no root (ie. trying to output empty document)."); - } - // 20-Jul-2004, TSa: Need to close the open sub-tree, if it exists... - // First, do we have an open start element? - if (mStartElementOpen) { - closeStartElement(mEmptyElement); - } - // Then, one by one, need to close open scopes: - /* 17-Nov-2008, TSa: that is, if we are allowed to do it - * (see [WSTX-165]) - */ - if (mState != STATE_EPILOG && mConfig.automaticEndElementsEnabled()) { - do { - writeEndElement(); - } while (mState != STATE_EPILOG); - } - } - - /* And finally, inform the underlying writer that it should flush - * and release its buffers, and close components it uses if any. - */ - char[] buf = mCopyBuffer; - if (buf != null) { - mCopyBuffer = null; - mConfig.freeMediumCBuffer(buf); - } - try { - mWriter.close(forceRealClose); - } catch (IOException ie) { - throw new WstxIOException(ie); - } - } - - /** - * Implementation-dependant method called to fully copy START_ELEMENT - * event that the passed-in stream reader points to - */ - public abstract void copyStartElement(InputElementStack elemStack, - AttributeCollector attrCollector) - throws IOException, XMLStreamException; - - /** - * Method called before writing a QName via Typed Access API. - * In namespace-repairing mode it should take appropriate actions - * to ensure that the given namespace URI is bound to a namespace - * and return whatever it maps to. In non-repairing work no additional - * work is to be done and methods - * - * @return Prefix to use when writing out given QName as an element - * or attribute value - */ - public abstract String validateQNamePrefix(QName name) - throws XMLStreamException; - - /* - /////////////////////////////////////////////////////////// - // Package methods, validation - /////////////////////////////////////////////////////////// - */ - - protected final void verifyWriteCData() - throws XMLStreamException - { - // Not legal outside main element tree: - if (mCheckStructure) { - if (inPrologOrEpilog()) { - reportNwfStructure(ErrorConsts.WERR_PROLOG_CDATA); - } - } - // 08-Dec-2005, TSa: validator-based validation? - if (mVldContent <= XMLValidator.CONTENT_ALLOW_WS) { - // there's no ignorable white space CDATA... - reportInvalidContent(CDATA); - } - } - - protected final void verifyWriteDTD() - throws XMLStreamException - { - // 20-Nov-2004, TSa: can check that we are in prolog - if (mCheckStructure) { - if (mState != STATE_PROLOG) { - throw new XMLStreamException("Can not write DOCTYPE declaration (DTD) when not in prolog any more (state "+mState+"; start element(s) written)"); - } - // 20-Dec-2005, TSa: and that we only output one... - if (mDtdRootElem != null) { - throw new XMLStreamException("Trying to write multiple DOCTYPE declarations"); - } - } - } - - protected void verifyRootElement(String localName, String prefix) - throws XMLStreamException - { - /* Note: this check is bit lame, due to DOCTYPE declaration (and DTD - * in general) being namespace-ignorant... - */ - if (isValidating()) { - /* 17-Mar-2006, TSa: Ideally, this should be a validity - * problem? - */ - if (mDtdRootElem != null && mDtdRootElem.length() > 0) { - String wrongElem = null; - - /* Ugh. It is possible that we just don't know the prefix -- - * in repairing mode it's assigned after this check. So for - * now, let's only verify the local name - */ - if (localName.equals(mDtdRootElem)) { - // good - } else { - int lnLen = localName.length(); - int oldLen = mDtdRootElem.length(); - - if (oldLen > lnLen - && mDtdRootElem.endsWith(localName) - && mDtdRootElem.charAt(oldLen - lnLen - 1) == ':') { - // good also - } else { - if (prefix == null) { // doesn't and won't have one - wrongElem = localName; - } else if (prefix.length() == 0) { // don't know what it'd be - wrongElem = "[unknown]:"+localName; - } else { - wrongElem = prefix + ":" + localName; - } - } - } - if (wrongElem != null) { - reportValidationProblem(ErrorConsts.ERR_VLD_WRONG_ROOT, wrongElem, mDtdRootElem); - } - } - } - mState = STATE_TREE; - } - - /* - /////////////////////////////////////////////////////////// - // Package methods, basic output problem reporting - /////////////////////////////////////////////////////////// - */ - - protected static void throwOutputError(String msg) - throws XMLStreamException - { - throw new XMLStreamException(msg); - } - - protected static void throwOutputError(String format, Object arg) - throws XMLStreamException - { - String msg = MessageFormat.format(format, new Object[] { arg }); - throwOutputError(msg); - } - - /** - * Method called when an illegal method (namespace-specific method - * on non-ns writer) is called by the application. - */ - protected static void reportIllegalMethod(String msg) - throws XMLStreamException - { - throwOutputError(msg); - } - - /** - * This is the method called when an output method call violates - * structural well-formedness checks - * and {@link WstxOutputProperties#P_OUTPUT_VALIDATE_STRUCTURE} is - * is enabled. - */ - protected static void reportNwfStructure(String msg) - throws XMLStreamException - { - throwOutputError(msg); - } - - protected static void reportNwfStructure(String msg, Object arg) - throws XMLStreamException - { - throwOutputError(msg, arg); - } - - /** - * This is the method called when an output method call violates - * content well-formedness checks - * and {@link WstxOutputProperties#P_OUTPUT_VALIDATE_CONTENT} is - * is enabled. - */ - protected static void reportNwfContent(String msg) - throws XMLStreamException - { - throwOutputError(msg); - } - - protected static void reportNwfContent(String msg, Object arg) - throws XMLStreamException - { - throwOutputError(msg, arg); - } - - /** - * This is the method called when an output method call violates - * attribute well-formedness checks (trying to output dup attrs) - * and {@link WstxOutputProperties#P_OUTPUT_VALIDATE_NAMES} is - * is enabled. - */ - protected static void reportNwfAttr(String msg) - throws XMLStreamException - { - throwOutputError(msg); - } - - protected static void reportNwfAttr(String msg, Object arg) - throws XMLStreamException - { - throwOutputError(msg, arg); - } - - protected static void throwFromIOE(IOException ioe) - throws XMLStreamException - { - throw new WstxIOException(ioe); - } - - protected static void reportIllegalArg(String msg) - throws IllegalArgumentException - { - throw new IllegalArgumentException(msg); - } - - /* - /////////////////////////////////////////////////////////// - // Package methods, output validation problem reporting - /////////////////////////////////////////////////////////// - */ - - protected void reportInvalidContent(int evtType) - throws XMLStreamException - { - switch (mVldContent) { - case XMLValidator.CONTENT_ALLOW_NONE: - reportValidationProblem(ErrorConsts.ERR_VLD_EMPTY, - getTopElementDesc(), - ErrorConsts.tokenTypeDesc(evtType)); - break; - case XMLValidator.CONTENT_ALLOW_WS: - reportValidationProblem(ErrorConsts.ERR_VLD_NON_MIXED, - getTopElementDesc()); - break; - case XMLValidator.CONTENT_ALLOW_VALIDATABLE_TEXT: - case XMLValidator.CONTENT_ALLOW_ANY_TEXT: - /* Not 100% sure if this should ever happen... depends on - * interpretation of 'any' content model? - */ - reportValidationProblem(ErrorConsts.ERR_VLD_ANY, - getTopElementDesc(), - ErrorConsts.tokenTypeDesc(evtType)); - break; - default: // should never occur: - reportValidationProblem("Internal error: trying to report invalid content for "+evtType); - } - } - - public void reportValidationProblem(String msg, Location loc, int severity) - throws XMLStreamException - { - reportProblem(new XMLValidationProblem(loc, msg, severity)); - } - - public void reportValidationProblem(String msg, int severity) - throws XMLStreamException - { - reportProblem(new XMLValidationProblem(getValidationLocation(), - msg, severity)); - } - - public void reportValidationProblem(String msg) - throws XMLStreamException - { - reportProblem(new XMLValidationProblem(getValidationLocation(), - msg, - XMLValidationProblem.SEVERITY_ERROR)); - } - - public void reportValidationProblem(Location loc, String msg) - throws XMLStreamException - { - reportProblem(new XMLValidationProblem(getValidationLocation(), msg)); - } - - public void reportValidationProblem(String format, Object arg) - throws XMLStreamException - { - String msg = MessageFormat.format(format, new Object[] { arg }); - reportProblem(new XMLValidationProblem(getValidationLocation(), - msg)); - } - - public void reportValidationProblem(String format, Object arg, Object arg2) - throws XMLStreamException - { - String msg = MessageFormat.format(format, new Object[] { arg, arg2 }); - reportProblem(new XMLValidationProblem(getValidationLocation(), msg)); - } - - protected void doReportProblem(XMLReporter rep, String probType, String msg, Location loc) - throws XMLStreamException - { - if (loc == null) { - loc = getLocation(); - } - doReportProblem(rep, new XMLValidationProblem(loc, msg, XMLValidationProblem.SEVERITY_ERROR, probType)); - } - - protected void doReportProblem(XMLReporter rep, XMLValidationProblem prob) - throws XMLStreamException - { - if (rep != null) { - Location loc = prob.getLocation(); - if (loc == null) { - loc = getLocation(); - prob.setLocation(loc); - } - // Backwards-compatibility fix: add non-null type, if missing: - if (prob.getType() == null) { - prob.setType(ErrorConsts.WT_VALIDATION); - } - // [WSTX-154]: was catching and dropping thrown exception: shouldn't. - rep.report(prob.getMessage(), prob.getType(), prob, loc); - } - } - - /** - * Method needed for error message generation - */ - protected abstract String getTopElementDesc(); - - /* - /////////////////////////////////////////////////////////// - // Package methods, other - /////////////////////////////////////////////////////////// - */ - - protected final char[] getCopyBuffer() - { - char[] buf = mCopyBuffer; - if (buf == null) { - mCopyBuffer = buf = mConfig.allocMediumCBuffer(DEFAULT_COPYBUFFER_LEN); - } - return buf; - } - - protected final char[] getCopyBuffer(int minLen) - { - char[] buf = mCopyBuffer; - if (buf == null || minLen > buf.length) { - mCopyBuffer = buf = mConfig.allocMediumCBuffer(Math.max(DEFAULT_COPYBUFFER_LEN, minLen)); - } - return buf; - } - - public String toString() - { - return "[StreamWriter: "+getClass()+", underlying outputter: " - +((mWriter == null) ? "NULL" : mWriter.toString()+"]"); - } -} diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/sw/BufferingXmlWriter.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/sw/BufferingXmlWriter.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/sw/BufferingXmlWriter.java 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/sw/BufferingXmlWriter.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,1666 +0,0 @@ -/* Woodstox XML processor - * - * Copyright (c) 2004- Tatu Saloranta, tatu.saloranta@iki.fi - * - * Licensed under the License specified in file LICENSE, included with - * the source code. - * You may not use this file except in compliance with the License. - * - * 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 com.ctc.wstx.sw; - -import java.io.*; - -import javax.xml.stream.XMLStreamConstants; -import javax.xml.stream.XMLStreamException; - -import org.codehaus.stax2.ri.typed.AsciiValueEncoder; -import org.codehaus.stax2.validation.XMLValidator; - -import com.ctc.wstx.api.WriterConfig; -import com.ctc.wstx.io.CharsetNames; -import com.ctc.wstx.io.CompletelyCloseable; - -/** - * Concrete implementation of {@link XmlWriter} that will dispatch writes - * to another writer (of type {@link java.io.Writer}, and will NOT handle - * encoding. It will, however, do basic buffering such that the underlying - * Writer need (and thus, should) not do buffering. - *

- * One design goal for this class is to avoid unnecessary buffering: since - * there will be another Writer doing the actual encoding, amount of - * buffering needed should still be limited. To this end, a threshold is - * used to define what's the threshold of writes that we do want to - * coalesce, ie. buffer. Writes bigger than this should in general proceed - * without buffering. - */ -public final class BufferingXmlWriter - extends XmlWriter - implements XMLStreamConstants -{ - /** - * Let's use a typical default to have a compromise between large - * enough chunks to output, and minimizing memory overhead. - * Compared to encoding writers, buffer size can be bit smaller - * since there's one more level of processing (at encoding), which - * may use bigger buffering. - */ - final static int DEFAULT_BUFFER_SIZE = 1000; - - /** - * Choosing threshold for 'small size' is a compromise between - * excessive buffering (high small size), and too many fragmented - * calls to the underlying writer (low small size). Let's just - * use about 1/4 of the full buffer size. - */ - final static int DEFAULT_SMALL_SIZE = 256; - - /** - * Highest valued character that may need to be encoded (minus charset - * encoding requirements) when writing attribute values. - */ - protected final static int HIGHEST_ENCODABLE_ATTR_CHAR = (int)'<'; - - /** - * Highest valued character that may need to be encoded (minus charset - * encoding requirements) when writing attribute values. - */ - protected final static int HIGHEST_ENCODABLE_TEXT_CHAR = (int)'>'; - - /* - //////////////////////////////////////////////// - // Output state, buffering - //////////////////////////////////////////////// - */ - - /** - * Actual Writer to use for outputting buffered data as appropriate. - */ - protected final Writer mOut; - - protected char[] mOutputBuffer; - - /** - * This is the threshold used to check what is considered a "small" - * write; small writes will be buffered until resulting size will - * be above the threshold. - */ - protected final int mSmallWriteSize; - - protected int mOutputPtr; - - protected int mOutputBufLen; - - /** - * Actual physical stream that the writer is using, if known. - * Not used for actual output, only needed so that calling - * application may (try to) figure out the original - * source. - */ - protected final OutputStream mUnderlyingStream; - - /* - //////////////////////////////////////////////// - // Encoding/escaping configuration - //////////////////////////////////////////////// - */ - - /** - * First Unicode character (one with lowest value) after (and including) - * which character entities have to be used. For - */ - private final int mEncHighChar; - - /** - * Character that is considered to be the enclosing quote character; - * for XML either single or double quote. - */ - final char mEncQuoteChar; - - /** - * Entity String to use for escaping the quote character. - */ - final String mEncQuoteEntity; - - /* - //////////////////////////////////////////////// - // Life-cycle - //////////////////////////////////////////////// - */ - - /** - * @param outs Underlying OutputStream that the writer - * (out) is using, if known. Needed to support - * (optional) access to the underlying stream - */ - public BufferingXmlWriter(Writer out, WriterConfig cfg, String enc, - boolean autoclose, - OutputStream outs, int bitsize) - throws IOException - { - super(cfg, enc, autoclose); - mOut = out; - mOutputBuffer = cfg.allocFullCBuffer(DEFAULT_BUFFER_SIZE); - mOutputBufLen = mOutputBuffer.length; - mSmallWriteSize = DEFAULT_SMALL_SIZE; - mOutputPtr = 0; - - mUnderlyingStream = outs; - - // Let's use double-quotes, as usual; alternative is apostrophe - mEncQuoteChar = '"'; - mEncQuoteEntity = """; - /* Note: let's actually exclude couple of illegal chars for - * unicode-based encoders. But we do not have to worry about - * surrogates quite here, fortunately. - */ - if (bitsize < 1) { - bitsize = guessEncodingBitSize(enc); - } - mEncHighChar = ((bitsize < 16) ? (1 << bitsize) : 0xFFFE); - } - - protected int getOutputPtr() { - return mOutputPtr; - } - - /* - //////////////////////////////////////////////// - // Raw access to underlying output objects - //////////////////////////////////////////////// - */ - - final protected OutputStream getOutputStream() - { - return mUnderlyingStream; - } - - final protected Writer getWriter() - { - return mOut; - } - - /* - //////////////////////////////////////////////// - // Low-level (pass-through) methods - //////////////////////////////////////////////// - */ - - public void close(boolean forceRealClose) - throws IOException - { - flush(); - mTextWriter = null; - mAttrValueWriter = null; - - // Buffers to free? - char[] buf = mOutputBuffer; - if (buf != null) { - mOutputBuffer = null; - mConfig.freeFullCBuffer(buf); - } - // Plus may need to close the actual writer - if (forceRealClose || mAutoCloseOutput) { - /* 14-Nov-2008, TSa: To resolve [WSTX-163], need to have a way - * to force UTF8Writer to close the underlying stream... - */ - if (mOut instanceof CompletelyCloseable) { - ((CompletelyCloseable)mOut).closeCompletely(); - } else { - mOut.close(); - } - } - } - - public final void flush() - throws IOException - { - flushBuffer(); - mOut.flush(); - } - - public void writeRaw(char[] cbuf, int offset, int len) - throws IOException - { - if (mOut == null) { - return; - } - - // First; is the new request small or not? If yes, needs to be buffered - if (len < mSmallWriteSize) { // yup - // Does it fit in with current buffer? If not, need to flush first - if ((mOutputPtr + len) > mOutputBufLen) { - flushBuffer(); - } - System.arraycopy(cbuf, offset, mOutputBuffer, mOutputPtr, len); - mOutputPtr += len; - return; - } - - // Ok, not a small request. But buffer may have existing content? - int ptr = mOutputPtr; - if (ptr > 0) { - // If it's a small chunk, need to fill enough before flushing - if (ptr < mSmallWriteSize) { - /* Also, if we are to copy any stuff, let's make sure - * that we either copy it all in one chunk, or copy - * enough for non-small chunk, flush, and output remaining - * non-small chink (former possible if chunk we were requested - * to output is only slightly over 'small' size) - */ - int needed = (mSmallWriteSize - ptr); - - // Just need minimal copy: - System.arraycopy(cbuf, offset, mOutputBuffer, ptr, needed); - mOutputPtr = ptr + needed; - len -= needed; - offset += needed; - } - flushBuffer(); - } - - // And then we'll just write whatever we have left: - mOut.write(cbuf, offset, len); - } - - /** - * Method called to output typed values (int, long, double, float etc) - * that are known not to contain any escapable characters, or anything - * else beyond 7-bit ascii range. - */ - public final void writeRawAscii(char[] cbuf, int offset, int len) - throws IOException - { - // Can't optimize any further with buffering writer, so: - writeRaw(cbuf, offset, len); - } - - public void writeRaw(String str) - throws IOException - { - if (mOut == null) { - return; - } - final int len = str.length(); - - // First; is the new request small or not? If yes, needs to be buffered - if (len < mSmallWriteSize) { // yup - // Does it fit in with current buffer? If not, need to flush first - if ((mOutputPtr + len) >= mOutputBufLen) { - flushBuffer(); - } - str.getChars(0, len, mOutputBuffer, mOutputPtr); - mOutputPtr += len; - return; - } - // Otherwise, let's just call the main method - writeRaw(str, 0, len); - } - - public void writeRaw(String str, int offset, int len) - throws IOException - { - if (mOut == null) { - return; - } - - // First; is the new request small or not? If yes, needs to be buffered - if (len < mSmallWriteSize) { // yup - // Does it fit in with current buffer? If not, need to flush first - if ((mOutputPtr + len) >= mOutputBufLen) { - flushBuffer(); - } - str.getChars(offset, offset+len, mOutputBuffer, mOutputPtr); - mOutputPtr += len; - return; - } - - // Ok, not a small request. But buffer may have existing content? - int ptr = mOutputPtr; - if (ptr > 0) { - // If it's a small chunk, need to fill enough before flushing - if (ptr < mSmallWriteSize) { - /* Also, if we are to copy any stuff, let's make sure - * that we either copy it all in one chunk, or copy - * enough for non-small chunk, flush, and output remaining - * non-small chunk (former possible if chunk we were requested - * to output is only slightly over 'small' size) - */ - int needed = (mSmallWriteSize - ptr); - - // Just need minimal copy: - str.getChars(offset, offset+needed, mOutputBuffer, ptr); - mOutputPtr = ptr + needed; - len -= needed; - offset += needed; - } - flushBuffer(); - } - - // And then we'll just write whatever we have left: - mOut.write(str, offset, len); - } - - /* - //////////////////////////////////////////////// - // "Trusted" low-level output methods - //////////////////////////////////////////////// - */ - - public final void writeCDataStart() - throws IOException - { - fastWriteRaw(""); - } - - public final void writeCommentStart() - throws IOException - { - fastWriteRaw(""); - } - - public final void writePIStart(String target, boolean addSpace) - throws IOException - { - fastWriteRaw('<', '?'); - fastWriteRaw(target); - if (addSpace) { - fastWriteRaw(' '); - } - } - - public final void writePIEnd() - throws IOException - { - fastWriteRaw('?', '>'); - } - - /* - //////////////////////////////////////////////// - // Higher-level output methods, text output - //////////////////////////////////////////////// - */ - - public int writeCData(String data) - throws IOException - { - if (mCheckContent) { - int ix = verifyCDataContent(data); - if (ix >= 0) { - if (!mFixContent) { // Can we fix it? - return ix; - } - // Yes we can! (...Bob the Builder...) - writeSegmentedCData(data, ix); - return -1; - } - } - fastWriteRaw(""); - return -1; - } - - public int writeCData(char[] cbuf, int offset, int len) - throws IOException - { - if (mCheckContent) { - int ix = verifyCDataContent(cbuf, offset, len); - if (ix >= 0) { - if (!mFixContent) { // Can we fix it? - return ix; - } - // Yes we can! (...Bob the Builder...) - writeSegmentedCData(cbuf, offset, len, ix); - return -1; - } - } - fastWriteRaw(""); - return -1; - } - - public void writeCharacters(String text) - throws IOException - { - if (mOut == null) { - return; - } - if (mTextWriter != null) { // custom escaping? - mTextWriter.write(text); - return; - } - int inPtr = 0; - final int len = text.length(); - int highChar = mEncHighChar; - - main_loop: - while (true) { - String ent = null; - - inner_loop: - while (true) { - if (inPtr >= len) { - break main_loop; - } - char c = text.charAt(inPtr++); - if (c <= HIGHEST_ENCODABLE_TEXT_CHAR) { - if (c <= 0x0020) { - if (c != ' ' && c != '\n' && c != '\t') { // fine as is - if (c == '\r') { - if (mEscapeCR) { - break inner_loop; - } - } else { - if (!mXml11 || c == 0) { - c = handleInvalidChar(c); // throws an error usually - } else { - break inner_loop; // need quoting - } - } - } - } else if (c == '<') { - ent = "<"; - break inner_loop; - } else if (c == '&') { - ent = "&"; - break inner_loop; - } else if (c == '>') { - // Let's be conservative; and if there's any - // change it might be part of "]]>" quote it - if (inPtr < 2 || text.charAt(inPtr-2) == ']') { - ent = ">"; - break inner_loop; - } - } - } else if (c >= highChar) { - break inner_loop; - } - if (mOutputPtr >= mOutputBufLen) { - flushBuffer(); - } - mOutputBuffer[mOutputPtr++] = c; - } - if (ent != null) { - writeRaw(ent); - } else { - writeAsEntity(text.charAt(inPtr-1)); - } - } - } - - public void writeCharacters(char[] cbuf, int offset, int len) - throws IOException - { - if (mOut == null) { - return; - } - - if (mTextWriter != null) { // custom escaping? - mTextWriter.write(cbuf, offset, len); - } else { // nope, default: - len += offset; - do { - int c = 0; - int highChar = mEncHighChar; - int start = offset; - String ent = null; - - for (; offset < len; ++offset) { - c = cbuf[offset]; - if (c <= HIGHEST_ENCODABLE_TEXT_CHAR) { - if (c == '<') { - ent = "<"; - break; - } else if (c == '&') { - ent = "&"; - break; - } else if (c == '>') { - /* Let's be conservative; and if there's any - * change it might be part of "]]>" quote it - */ - if ((offset == start) || cbuf[offset-1] == ']') { - ent = ">"; - break; - } - } else if (c < 0x0020) { - if (c == '\n' || c == '\t') { // fine as is - ; - } else if (c == '\r') { - if (mEscapeCR) { - break; - } - } else { - if (!mXml11 || c == 0) { - c = handleInvalidChar(c); - // Hmmh. This is very inefficient, but... - ent = String.valueOf((char) c); - } - break; // need quoting - } - } - } else if (c >= highChar) { - break; - } - // otherwise ok - } - int outLen = offset - start; - if (outLen > 0) { - writeRaw(cbuf, start, outLen); - } - if (ent != null) { - writeRaw(ent); - ent = null; - } else if (offset < len) { - writeAsEntity(c); - } - } while (++offset < len); - } - } - - /** - * Method that will try to output the content as specified. If - * the content passed in has embedded "--" in it, it will either - * add an intervening space between consequtive hyphens (if content - * fixing is enabled), or return the offset of the first hyphen in - * multi-hyphen sequence. - */ - public int writeComment(String data) - throws IOException - { - if (mCheckContent) { - int ix = verifyCommentContent(data); - if (ix >= 0) { - if (!mFixContent) { // Can we fix it? - return ix; - } - // Yes we can! (...Bob the Builder...) - writeSegmentedComment(data, ix); - return -1; - } - } - fastWriteRaw(""); - return -1; - } - - public void writeDTD(String data) - throws IOException - { - writeRaw(data); - } - - public void writeDTD(String rootName, String systemId, String publicId, - String internalSubset) - throws IOException, XMLStreamException - { - fastWriteRaw(" 0) { - fastWriteRaw(' ', '['); - fastWriteRaw(internalSubset); - fastWriteRaw(']'); - } - fastWriteRaw('>'); - } - - public void writeEntityReference(String name) - throws IOException, XMLStreamException - { - if (mCheckNames) { - verifyNameValidity(name, mNsAware); - } - fastWriteRaw('&'); - fastWriteRaw(name); - fastWriteRaw(';'); - } - - public void writeXmlDeclaration(String version, String encoding, String standalone) - throws IOException - { - fastWriteRaw(" 0) { - fastWriteRaw(" encoding='"); - fastWriteRaw(encoding); - fastWriteRaw('\''); - } - if (standalone != null) { - fastWriteRaw(" standalone='"); - fastWriteRaw(standalone); - fastWriteRaw('\''); - } - fastWriteRaw('?', '>'); - } - - public int writePI(String target, String data) - throws IOException, XMLStreamException - { - if (mCheckNames) { - // As per namespace specs, can not have colon(s) - verifyNameValidity(target, mNsAware); - } - fastWriteRaw('<', '?'); - fastWriteRaw(target); - if (data != null && data.length() > 0) { - if (mCheckContent) { - int ix = data.indexOf('?'); - if (ix >= 0) { - ix = data.indexOf("?>", ix); - if (ix >= 0) { - return ix; - } - } - } - fastWriteRaw(' '); - // Data may be longer, let's call regular writeRaw method - writeRaw(data); - } - fastWriteRaw('?', '>'); - return -1; - } - - /* - //////////////////////////////////////////////////// - // Write methods, elements - //////////////////////////////////////////////////// - */ - - public void writeStartTagStart(String localName) - throws IOException, XMLStreamException - { - if (mCheckNames) { - verifyNameValidity(localName, mNsAware); - } - - int ptr = mOutputPtr; - int extra = (mOutputBufLen - ptr) - (1 + localName.length()); - if (extra < 0) { // split on boundary, slower - fastWriteRaw('<'); - fastWriteRaw(localName); - } else { - char[] buf = mOutputBuffer; - buf[ptr++] = '<'; - int len = localName.length(); - localName.getChars(0, len, buf, ptr); - mOutputPtr = ptr+len; - } - } - - public void writeStartTagStart(String prefix, String localName) - throws IOException, XMLStreamException - { - if (prefix == null || prefix.length() == 0) { // shouldn't happen - writeStartTagStart(localName); - return; - } - - if (mCheckNames) { - verifyNameValidity(prefix, mNsAware); - verifyNameValidity(localName, mNsAware); - } - - int ptr = mOutputPtr; - int len = prefix.length(); - int extra = (mOutputBufLen - ptr) - (2 + localName.length() + len); - if (extra < 0) { // across buffer boundary, slow case - fastWriteRaw('<'); - fastWriteRaw(prefix); - fastWriteRaw(':'); - fastWriteRaw(localName); - } else { // fast case, all inlined - char[] buf = mOutputBuffer; - buf[ptr++] = '<'; - prefix.getChars(0, len, buf, ptr); - ptr += len; - buf[ptr++] = ':'; - len = localName.length(); - localName.getChars(0, len, buf, ptr); - mOutputPtr = ptr+len; - } - } - - public void writeStartTagEnd() - throws IOException - { - fastWriteRaw('>'); - } - - public void writeStartTagEmptyEnd() - throws IOException - { - int ptr = mOutputPtr; - if ((ptr + 3) >= mOutputBufLen) { - if (mOut == null) { - return; - } - flushBuffer(); - ptr = mOutputPtr; - } - char[] buf = mOutputBuffer; - if (mAddSpaceAfterEmptyElem) { - buf[ptr++] = ' '; - } - buf[ptr++] = '/'; - buf[ptr++] = '>'; - mOutputPtr = ptr; - } - - public void writeEndTag(String localName) - throws IOException - { - int ptr = mOutputPtr; - int extra = (mOutputBufLen - ptr) - (3 + localName.length()); - if (extra < 0) { - fastWriteRaw('<', '/'); - fastWriteRaw(localName); - fastWriteRaw('>'); - } else { - char[] buf = mOutputBuffer; - buf[ptr++] = '<'; - buf[ptr++] = '/'; - int len = localName.length(); - localName.getChars(0, len, buf, ptr); - ptr += len; - buf[ptr++] = '>'; - mOutputPtr = ptr; - } - } - - public void writeEndTag(String prefix, String localName) - throws IOException - { - if (prefix == null || prefix.length() == 0) { - writeEndTag(localName); - return; - } - int ptr = mOutputPtr; - int len = prefix.length(); - int extra = (mOutputBufLen - ptr) - (4 + localName.length() + len); - if (extra < 0) { - fastWriteRaw('<', '/'); - /* At this point, it is assumed caller knows that end tag - * matches with start tag, and that it (by extension) has been - * validated if and as necessary - */ - fastWriteRaw(prefix); - fastWriteRaw(':'); - fastWriteRaw(localName); - fastWriteRaw('>'); - } else { - char[] buf = mOutputBuffer; - buf[ptr++] = '<'; - buf[ptr++] = '/'; - prefix.getChars(0, len, buf, ptr); - ptr += len; - buf[ptr++] = ':'; - len = localName.length(); - localName.getChars(0, len, buf, ptr); - ptr += len; - buf[ptr++] = '>'; - mOutputPtr = ptr; - } - } - - /* - //////////////////////////////////////////////////// - // Write methods, attributes/ns - //////////////////////////////////////////////////// - */ - - public void writeAttribute(String localName, String value) - throws IOException, XMLStreamException - { - if (mOut == null) { - return; - } - if (mCheckNames) { - verifyNameValidity(localName, mNsAware); - } - int len = localName.length(); - if (((mOutputBufLen - mOutputPtr) - (3 + len)) < 0) { - fastWriteRaw(' '); - fastWriteRaw(localName); - fastWriteRaw('=', '"'); - } else { - int ptr = mOutputPtr; - char[] buf = mOutputBuffer; - buf[ptr++] = ' '; - localName.getChars(0, len, buf, ptr); - ptr += len; - buf[ptr++] = '='; - buf[ptr++] = '"'; - mOutputPtr = ptr; - } - - len = (value == null) ? 0 : value.length(); - if (len > 0) { - if (mAttrValueWriter != null) { // custom escaping? - mAttrValueWriter.write(value, 0, len); - } else { // nope, default - writeAttrValue(value, len); - } - } - fastWriteRaw('"'); - } - - public void writeAttribute(String localName, char[] value, int offset, int vlen) - throws IOException, XMLStreamException - { - if (mOut == null) { - return; - } - if (mCheckNames) { - verifyNameValidity(localName, mNsAware); - } - int len = localName.length(); - if (((mOutputBufLen - mOutputPtr) - (3 + len)) < 0) { - fastWriteRaw(' '); - fastWriteRaw(localName); - fastWriteRaw('=', '"'); - } else { - int ptr = mOutputPtr; - char[] buf = mOutputBuffer; - buf[ptr++] = ' '; - localName.getChars(0, len, buf, ptr); - ptr += len; - buf[ptr++] = '='; - buf[ptr++] = '"'; - mOutputPtr = ptr; - } - - if (vlen > 0) { - if (mAttrValueWriter != null) { // custom escaping? - mAttrValueWriter.write(value, offset, vlen); - } else { // nope, default - writeAttrValue(value, offset, vlen); - } - } - fastWriteRaw('"'); - } - - public void writeAttribute(String prefix, String localName, String value) - throws IOException, XMLStreamException - { - if (mOut == null) { - return; - } - if (mCheckNames) { - verifyNameValidity(prefix, mNsAware); - verifyNameValidity(localName, mNsAware); - } - int len = prefix.length(); - if (((mOutputBufLen - mOutputPtr) - (4 + localName.length() + len)) < 0) { - fastWriteRaw(' '); - if (len > 0) { - fastWriteRaw(prefix); - fastWriteRaw(':'); - } - fastWriteRaw(localName); - fastWriteRaw('=', '"'); - } else { - int ptr = mOutputPtr; - char[] buf = mOutputBuffer; - buf[ptr++] = ' '; - prefix.getChars(0, len, buf, ptr); - ptr += len; - buf[ptr++] = ':'; - len = localName.length(); - localName.getChars(0, len, buf, ptr); - ptr += len; - buf[ptr++] = '='; - buf[ptr++] = '"'; - mOutputPtr = ptr; - } - - len = (value == null) ? 0 : value.length(); - if (len > 0) { - if (mAttrValueWriter != null) { // custom escaping? - mAttrValueWriter.write(value, 0, len); - } else { // nope, default - writeAttrValue(value, len); - } - } - fastWriteRaw('"'); - } - - public void writeAttribute(String prefix, String localName, char[] value, int offset, int vlen) - throws IOException, XMLStreamException - { - if (mOut == null) { - return; - } - if (mCheckNames) { - verifyNameValidity(prefix, mNsAware); - verifyNameValidity(localName, mNsAware); - } - int len = prefix.length(); - if (((mOutputBufLen - mOutputPtr) - (4 + localName.length() + len)) < 0) { - fastWriteRaw(' '); - if (len > 0) { - fastWriteRaw(prefix); - fastWriteRaw(':'); - } - fastWriteRaw(localName); - fastWriteRaw('=', '"'); - } else { - int ptr = mOutputPtr; - char[] buf = mOutputBuffer; - buf[ptr++] = ' '; - prefix.getChars(0, len, buf, ptr); - ptr += len; - buf[ptr++] = ':'; - len = localName.length(); - localName.getChars(0, len, buf, ptr); - ptr += len; - buf[ptr++] = '='; - buf[ptr++] = '"'; - mOutputPtr = ptr; - } - if (vlen > 0) { - if (mAttrValueWriter != null) { // custom escaping? - mAttrValueWriter.write(value, offset, vlen); - } else { // nope, default - writeAttrValue(value, offset, vlen); - } - } - fastWriteRaw('"'); - } - - private final void writeAttrValue(String value, int len) - throws IOException - { - int inPtr = 0; - final char qchar = mEncQuoteChar; - int highChar = mEncHighChar; - - main_loop: - while (true) { // main_loop - String ent = null; - - inner_loop: - while (true) { - if (inPtr >= len) { - break main_loop; - } - char c = value.charAt(inPtr++); - if (c <= HIGHEST_ENCODABLE_ATTR_CHAR) { // special char? - if (c < 0x0020) { // tab, cr/lf need encoding too - if (c == '\r') { - if (mEscapeCR) { - break inner_loop; // quoting - } - } else if (c != '\n' && c != '\t' - && (!mXml11 || c == 0)) { - c = handleInvalidChar(c); - } else { - break inner_loop; // need quoting - } - } else if (c == qchar) { - ent = mEncQuoteEntity; - break inner_loop; - } else if (c == '<') { - ent = "<"; - break inner_loop; - } else if (c == '&') { - ent = "&"; - break inner_loop; - } - } else if (c >= highChar) { // out of range, have to escape - break inner_loop; - } - if (mOutputPtr >= mOutputBufLen) { - flushBuffer(); - } - mOutputBuffer[mOutputPtr++] = c; - } - if (ent != null) { - writeRaw(ent); - } else { - writeAsEntity(value.charAt(inPtr-1)); - } - } - } - - private final void writeAttrValue(char[] value, int offset, int len) - throws IOException - { - len += offset; - final char qchar = mEncQuoteChar; - int highChar = mEncHighChar; - - main_loop: - while (true) { // main_loop - String ent = null; - - inner_loop: - while (true) { - if (offset >= len) { - break main_loop; - } - char c = value[offset++]; - if (c <= HIGHEST_ENCODABLE_ATTR_CHAR) { // special char? - if (c < 0x0020) { // tab, cr/lf need encoding too - if (c == '\r') { - if (mEscapeCR) { - break inner_loop; // quoting - } - } else if (c != '\n' && c != '\t' - && (!mXml11 || c == 0)) { - c = handleInvalidChar(c); - } else { - break inner_loop; // need quoting - } - } else if (c == qchar) { - ent = mEncQuoteEntity; - break inner_loop; - } else if (c == '<') { - ent = "<"; - break inner_loop; - } else if (c == '&') { - ent = "&"; - break inner_loop; - } - } else if (c >= highChar) { // out of range, have to escape - break inner_loop; - } - if (mOutputPtr >= mOutputBufLen) { - flushBuffer(); - } - mOutputBuffer[mOutputPtr++] = c; - } - if (ent != null) { - writeRaw(ent); - } else { - writeAsEntity(value[offset-1]); - } - } - } - - /* - //////////////////////////////////////////////// - // Methods used by Typed Access API - //////////////////////////////////////////////// - */ - - public final void writeTypedElement(AsciiValueEncoder enc) - throws IOException - { - if (mOut == null) { - return; - } - - int free = mOutputBufLen - mOutputPtr; - if (enc.bufferNeedsFlush(free)) { - flush(); - } - while (true) { - mOutputPtr = enc.encodeMore(mOutputBuffer, mOutputPtr, mOutputBufLen); - // If no flushing needed, indicates that all data was encoded - if (enc.isCompleted()) { - break; - } - flush(); - } - } - - public final void writeTypedElement(AsciiValueEncoder enc, - XMLValidator validator, char[] copyBuffer) - throws IOException, XMLStreamException - { - if (mOut == null) { - return; - } - int free = mOutputBufLen - mOutputPtr; - if (enc.bufferNeedsFlush(free)) { - flush(); - } - int start = mOutputPtr; - while (true) { - mOutputPtr = enc.encodeMore(mOutputBuffer, mOutputPtr, mOutputBufLen); - // False -> can't be sure it's the whole remaining text - validator.validateText(mOutputBuffer, start, mOutputPtr, false); - if (enc.isCompleted()) { - break; - } - flush(); - start = mOutputPtr; - } - } - - public void writeTypedAttribute(String localName, AsciiValueEncoder enc) - throws IOException, XMLStreamException - { - if (mOut == null) { - return; - } - if (mCheckNames) { - verifyNameValidity(localName, mNsAware); - } - int len = localName.length(); - if ((mOutputPtr + 3 + len) > mOutputBufLen) { - fastWriteRaw(' '); - fastWriteRaw(localName); - fastWriteRaw('=', '"'); - } else { - int ptr = mOutputPtr; - char[] buf = mOutputBuffer; - buf[ptr++] = ' '; - localName.getChars(0, len, buf, ptr); - ptr += len; - buf[ptr++] = '='; - buf[ptr++] = '"'; - mOutputPtr = ptr; - } - - int free = mOutputBufLen - mOutputPtr; - if (enc.bufferNeedsFlush(free)) { - flush(); - } - while (true) { - mOutputPtr = enc.encodeMore(mOutputBuffer, mOutputPtr, mOutputBufLen); - if (enc.isCompleted()) { - break; - } - flush(); - } - fastWriteRaw('"'); - } - - public void writeTypedAttribute(String prefix, String localName, - AsciiValueEncoder enc) - throws IOException, XMLStreamException - { - if (mOut == null) { - return; - } - if (mCheckNames) { - verifyNameValidity(prefix, mNsAware); - verifyNameValidity(localName, mNsAware); - } - int plen = prefix.length(); - int llen = localName.length(); - - if ((mOutputPtr + 4 + plen + llen) > mOutputBufLen) { - writePrefixedName(prefix, localName); - fastWriteRaw('=', '"'); - } else { - int ptr = mOutputPtr; - char[] buf = mOutputBuffer; - buf[ptr++] = ' '; - if (plen > 0) { - prefix.getChars(0, plen, buf, ptr); - ptr += plen; - buf[ptr++] = ':'; - - } - localName.getChars(0, llen, buf, ptr); - ptr += llen; - buf[ptr++] = '='; - buf[ptr++] = '"'; - mOutputPtr = ptr; - } - - int free = mOutputBufLen - mOutputPtr; - if (enc.bufferNeedsFlush(free)) { - flush(); - } - while (true) { - mOutputPtr = enc.encodeMore(mOutputBuffer, mOutputPtr, mOutputBufLen); - if (enc.isCompleted()) { - break; - } - flush(); - } - - fastWriteRaw('"'); - } - - public void writeTypedAttribute(String prefix, String localName, String nsURI, - AsciiValueEncoder enc, - XMLValidator validator, char[] copyBuffer) - throws IOException, XMLStreamException - { - if (mOut == null) { - return; - } - if (prefix == null) { - prefix = ""; - } - if (nsURI == null) { - nsURI = ""; - } - int plen = prefix.length(); - if (mCheckNames) { - if (plen > 0) { - verifyNameValidity(prefix, mNsAware); - } - verifyNameValidity(localName, mNsAware); - } - if (((mOutputBufLen - mOutputPtr) - (4 + localName.length() + plen)) < 0) { - writePrefixedName(prefix, localName); - fastWriteRaw('=', '"'); - } else { - int ptr = mOutputPtr; - char[] buf = mOutputBuffer; - buf[ptr++] = ' '; - if (plen > 0) { - prefix.getChars(0, plen, buf, ptr); - ptr += plen; - buf[ptr++] = ':'; - - } - int llen = localName.length(); - localName.getChars(0, llen, buf, ptr); - ptr += llen; - buf[ptr++] = '='; - buf[ptr++] = '"'; - mOutputPtr = ptr; - } - - /* Tricky here is this: attributes to validate can not be - * split (validators expect complete values). So, if value - * won't fit as is, may need to aggregate using StringBuilder - */ - int free = mOutputBufLen - mOutputPtr; - if (enc.bufferNeedsFlush(free)) { - flush(); - } - int start = mOutputPtr; - - // First, let's see if one call is enough - mOutputPtr = enc.encodeMore(mOutputBuffer, mOutputPtr, mOutputBufLen); - if (enc.isCompleted()) { // yup - validator.validateAttribute(localName, nsURI, prefix, mOutputBuffer, start, mOutputPtr); - return; - } - - // If not, must combine first - StringBuffer sb = new StringBuffer(mOutputBuffer.length << 1); - sb.append(mOutputBuffer, start, mOutputPtr-start); - while (true) { - flush(); - start = mOutputPtr; - mOutputPtr = enc.encodeMore(mOutputBuffer, mOutputPtr, mOutputBufLen); - sb.append(mOutputBuffer, start, mOutputPtr-start); - // All done? - if (enc.isCompleted()) { - break; - } - } - fastWriteRaw('"'); - - // Then validate - String valueStr = sb.toString(); - validator.validateAttribute(localName, nsURI, prefix, valueStr); - } - - protected final void writePrefixedName(String prefix, String localName) - throws IOException - { - fastWriteRaw(' '); - if (prefix.length() > 0) { - fastWriteRaw(prefix); - fastWriteRaw(':'); - } - fastWriteRaw(localName); - } - - /* - //////////////////////////////////////////////////// - // Internal methods, buffering - //////////////////////////////////////////////////// - */ - - private final void flushBuffer() - throws IOException - { - if (mOutputPtr > 0 && mOutputBuffer != null) { - int ptr = mOutputPtr; - // Need to update location info, to keep it in sync - mLocPastChars += ptr; - mLocRowStartOffset -= ptr; - mOutputPtr = 0; - mOut.write(mOutputBuffer, 0, ptr); - } - } - - private final void fastWriteRaw(char c) - throws IOException - { - if (mOutputPtr >= mOutputBufLen) { - if (mOut == null) { - return; - } - flushBuffer(); - } - mOutputBuffer[mOutputPtr++] = c; - } - - private final void fastWriteRaw(char c1, char c2) - throws IOException - { - if ((mOutputPtr + 1) >= mOutputBufLen) { - if (mOut == null) { - return; - } - flushBuffer(); - } - mOutputBuffer[mOutputPtr++] = c1; - mOutputBuffer[mOutputPtr++] = c2; - } - - private final void fastWriteRaw(String str) - throws IOException - { - int len = str.length(); - int ptr = mOutputPtr; - if ((ptr + len) >= mOutputBufLen) { - if (mOut == null) { - return; - } - /* It's even possible that String is longer than the buffer (not - * likely, possible). If so, let's just call the full - * method: - */ - if (len > mOutputBufLen) { - writeRaw(str); - return; - } - flushBuffer(); - ptr = mOutputPtr; - } - str.getChars(0, len, mOutputBuffer, ptr); - mOutputPtr = ptr+len; - } - - /* - //////////////////////////////////////////////////// - // Internal methods, content verification/fixing - //////////////////////////////////////////////////// - */ - - /** - * @return Index at which a problem was found, if any; -1 if there's - * no problem. - */ - protected int verifyCDataContent(String content) - { - if (content != null && content.length() >= 3) { - int ix = content.indexOf(']'); - if (ix >= 0) { - return content.indexOf("]]>", ix); - } - } - return -1; - } - - protected int verifyCDataContent(char[] c, int start, int end) - { - if (c != null) { - start += 2; - /* Let's do simple optimization for search... - * (simple bayer-moore - like algorithm) - */ - while (start < end) { - char ch = c[start]; - if (ch == ']') { - ++start; // let's just move by one in this case - continue; - } - if (ch == '>') { // match? - if (c[start-1] == ']' - && c[start-2] == ']') { - return start-2; - } - } - start += 2; - } - } - return -1; - } - - protected int verifyCommentContent(String content) - { - int ix = content.indexOf('-'); - if (ix >= 0) { - /* actually, it's illegal to just end with '-' too, since - * that would cause invalid end marker '--->' - */ - if (ix < (content.length() - 1)) { - ix = content.indexOf("--", ix); - } - } - return ix; - } - - protected void writeSegmentedCData(String content, int index) - throws IOException - { - /* It's actually fairly easy, just split "]]>" into 2 pieces; - * for each ']]>'; first one containing "]]", second one ">" - * (as long as necessary) - */ - int start = 0; - while (index >= 0) { - fastWriteRaw(""); - start = index+2; - index = content.indexOf("]]>", start); - } - // Ok, then the last segment - fastWriteRaw(""); - } - - protected void writeSegmentedCData(char[] c, int start, int len, int index) - throws IOException - { - int end = start + len; - while (index >= 0) { - fastWriteRaw(""); - start = index+2; - index = verifyCDataContent(c, start, end); - } - // Ok, then the last segment - fastWriteRaw(""); - } - - protected void writeSegmentedComment(String content, int index) - throws IOException - { - int len = content.length(); - // First the special case (last char is hyphen): - if (index == (len-1)) { - fastWriteRaw(""); - return; - } - - /* Fixing comments is more difficult than that of CDATA segments'; - * this because CDATA can still contain embedded ']]'s, but - * comment neither allows '--' nor ending with '-->'; which means - * that it's impossible to just split segments. Instead we'll do - * something more intrusive, and embed single spaces between all - * '--' character pairs... it's intrusive, but comments are not - * supposed to contain any data, so that should be fine (plus - * at least result is valid, unlike contents as is) - */ - fastWriteRaw(""); - } - - /** - * Method used to figure out which part of the Unicode char set the - * encoding can natively support. Values returned are 7, 8 and 16, - * to indicate (respectively) "ascii", "ISO-Latin" and "native Unicode". - * These just best guesses, but should work ok for the most common - * encodings. - */ - public static int guessEncodingBitSize(String enc) - { - if (enc == null || enc.length() == 0) { // let's assume default is UTF-8... - return 16; - } - - // Let's see if we can find a normalized name, first: - enc = CharsetNames.normalize(enc); - - // Ok, first, do we have known ones; starting with most common: - if (enc == CharsetNames.CS_UTF8) { - return 16; // meaning up to 2^16 can be represented natively - } else if (enc == CharsetNames.CS_ISO_LATIN1) { - return 8; - } else if (enc == CharsetNames.CS_US_ASCII) { - return 7; - } else if (enc == CharsetNames.CS_UTF16 - || enc == CharsetNames.CS_UTF16BE - || enc == CharsetNames.CS_UTF16LE - || enc == CharsetNames.CS_UTF32BE - || enc == CharsetNames.CS_UTF32LE) { - return 16; - } - - /* Above and beyond well-recognized names, it might still be - * good to have more heuristics for as-of-yet unhandled cases... - * But, it's probably easier to only assume 8-bit clean (could - * even make it just 7, let's see how this works out) - */ - return 8; - } - - protected final void writeAsEntity(int c) - throws IOException - { - char[] buf = mOutputBuffer; - int ptr = mOutputPtr; - if ((ptr + 10) >= buf.length) { // &#x [up to 6 hex digits] ; - flushBuffer(); - ptr = mOutputPtr; - } - buf[ptr++] = '&'; - - // Can use more optimal notation for 8-bit ascii stuff: - if (c < 256) { - /* Also; although not really mandatory, let's also - * use pre-defined entities where possible. - */ - if (c == '&') { - buf[ptr++] = 'a'; - buf[ptr++] = 'm'; - buf[ptr++] = 'p'; - } else if (c == '<') { - buf[ptr++] = 'l'; - buf[ptr++] = 't'; - } else if (c == '>') { - buf[ptr++] = 'g'; - buf[ptr++] = 't'; - } else if (c == '\'') { - buf[ptr++] = 'a'; - buf[ptr++] = 'p'; - buf[ptr++] = 'o'; - buf[ptr++] = 's'; - } else if (c == '"') { - buf[ptr++] = 'q'; - buf[ptr++] = 'u'; - buf[ptr++] = 'o'; - buf[ptr++] = 't'; - } else { - buf[ptr++] = '#';; - buf[ptr++] = 'x';; - // Can use shortest quoting for tab, cr, lf: - if (c >= 16) { - int digit = (c >> 4); - buf[ptr++] = (char) ((digit < 10) ? ('0' + digit) : (('a' - 10) + digit)); - c &= 0xF; - } - buf[ptr++] = (char) ((c < 10) ? ('0' + c) : (('a' - 10) + c)); - } - } else { - buf[ptr++] = '#'; - buf[ptr++] = 'x'; - - // Ok, let's write the shortest possible sequence then: - int shift = 20; - int origPtr = ptr; - - do { - int digit = (c >> shift) & 0xF; - if (digit > 0 || (ptr != origPtr)) { - buf[ptr++] = (char) ((digit < 10) ? ('0' + digit) : (('a' - 10) + digit)); - } - shift -= 4; - } while (shift > 0); - c &= 0xF; - buf[ptr++] = (char) ((c < 10) ? ('0' + c) : (('a' - 10) + c)); - } - buf[ptr++] = ';'; - mOutputPtr = ptr; - } -} diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/sw/EncodingXmlWriter.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/sw/EncodingXmlWriter.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/sw/EncodingXmlWriter.java 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/sw/EncodingXmlWriter.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,934 +0,0 @@ -/* Woodstox XML processor - * - * Copyright (c) 2004- Tatu Saloranta, tatu.saloranta@iki.fi - * - * Licensed under the License specified in file LICENSE, included with - * the source code. - * You may not use this file except in compliance with the License. - * - * 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 com.ctc.wstx.sw; - -import java.io.*; -import javax.xml.stream.XMLStreamException; - -import org.codehaus.stax2.ri.typed.AsciiValueEncoder; -import org.codehaus.stax2.validation.XMLValidator; - -import com.ctc.wstx.api.WriterConfig; -import com.ctc.wstx.cfg.XmlConsts; - -/** - * Intermediate base class used when outputting to streams that use - * an encoding that is compatible with 7-bit single-byte Ascii encoding. - * That means it can be used for UTF-8, ISO-Latin1 and pure Ascii. - *

- * Implementation notes: - *

- * Parts of surrogate handling are implemented here in the base class: - * storage for the first part of a split surrogate (only possible when - * character content is output split in multiple calls) is within - * base class. Also, simple checks for unmatched surrogate pairs are - * in writeAscii method, since it is the most convenient - * place to catch cases where a text segment ends with an unmatched - * surrogate pair half. - */ -public abstract class EncodingXmlWriter - extends XmlWriter -{ - /** - * Let's use a typical default to have a compromise between large - * enough chunks to output, and minimizing memory overhead. - * 4k should be close enough to a physical page to work out - * acceptably, without causing excessive (if temporary) memory usage. - */ - final static int DEFAULT_BUFFER_SIZE = 4000; - - final static byte BYTE_SPACE = (byte) ' '; - final static byte BYTE_COLON = (byte) ':'; - final static byte BYTE_SEMICOLON = (byte) ';'; - final static byte BYTE_LBRACKET = (byte) '['; - final static byte BYTE_RBRACKET = (byte) ']'; - final static byte BYTE_QMARK = (byte) '?'; - final static byte BYTE_EQ = (byte) '='; - final static byte BYTE_SLASH = (byte) '/'; - final static byte BYTE_HASH = (byte) '#'; - final static byte BYTE_HYPHEN = (byte) '-'; - - final static byte BYTE_LT = (byte) '<'; - final static byte BYTE_GT = (byte) '>'; - final static byte BYTE_AMP = (byte) '&'; - final static byte BYTE_QUOT = (byte) '"'; - final static byte BYTE_APOS = (byte) '\''; - - final static byte BYTE_A = (byte) 'a'; - final static byte BYTE_G = (byte) 'g'; - final static byte BYTE_L = (byte) 'l'; - final static byte BYTE_M = (byte) 'm'; - final static byte BYTE_O = (byte) 'o'; - final static byte BYTE_P = (byte) 'p'; - final static byte BYTE_Q = (byte) 'q'; - final static byte BYTE_S = (byte) 's'; - final static byte BYTE_T = (byte) 't'; - final static byte BYTE_U = (byte) 'u'; - final static byte BYTE_X = (byte) 'x'; - - /* - //////////////////////////////////////////////// - // Output state, buffering - //////////////////////////////////////////////// - */ - - /** - * Actual output stream to use for outputting encoded content as - * bytes. - */ - private final OutputStream mOut; - - protected byte[] mOutputBuffer; - - protected int mOutputPtr; - - /** - * In case a split surrogate pair is output (which can only successfully - * occur with either writeRaw or - * writeCharacters), the first part is temporarily stored - * within this member variable. - */ - protected int mSurrogate = 0; - - /* - //////////////////////////////////////////////// - // - //////////////////////////////////////////////// - */ - - public EncodingXmlWriter(OutputStream out, WriterConfig cfg, String encoding, - boolean autoclose) - throws IOException - { - super(cfg, encoding, autoclose); - mOut = out; - mOutputBuffer = cfg.allocFullBBuffer(DEFAULT_BUFFER_SIZE); - mOutputPtr = 0; - } - - /** - * This method is needed by the super class, to calculate hard - * byte/char offsets. - */ - protected int getOutputPtr() { - return mOutputPtr; - } - - /* - //////////////////////////////////////////////// - // Partial API implementation - //////////////////////////////////////////////// - */ - - final protected OutputStream getOutputStream() - { - return mOut; - } - - final protected Writer getWriter() - { - // No writers are involved with these implementations... - return null; - } - - public void close(boolean forceRealClose) - throws IOException - { - flush(); - - // Buffers to free? - byte[] buf = mOutputBuffer; - if (buf != null) { - mOutputBuffer = null; - mConfig.freeFullBBuffer(buf); - } - // Plus may need to close the actual stream - if (forceRealClose || mAutoCloseOutput) { - /* 14-Nov-2008, TSa: Wrt [WSTX-163]; no need to - * check whether mOut implements CompletelyCloseable - * (unlike with BufferingXmlWriter) - */ - mOut.close(); - } - } - - public final void flush() - throws IOException - { - flushBuffer(); - mOut.flush(); - } - - public abstract void writeRaw(char[] cbuf, int offset, int len) - throws IOException; - - public abstract void writeRaw(String str, int offset, int len) - throws IOException; - - /* - ////////////////////////////////////////////////// - // "Trusted" low-level output methods (that do not - // need to verify validity of input) - ////////////////////////////////////////////////// - */ - - public final void writeCDataStart() - throws IOException - { - writeAscii(""); - } - - public final void writeCommentStart() - throws IOException - { - writeAscii(""); - } - - public final void writePIStart(String target, boolean addSpace) - throws IOException - { - writeAscii(BYTE_LT, BYTE_QMARK); - writeRaw(target); - if (addSpace) { - writeAscii(BYTE_SPACE); - } - } - - public final void writePIEnd() - throws IOException - { - writeAscii(BYTE_QMARK, BYTE_GT); - } - - /* - //////////////////////////////////////////////// - // Higher-level output methods, text output - //////////////////////////////////////////////// - */ - - public int writeCData(String data) - throws IOException - { - writeAscii("= 0) { - return ix; - } - writeAscii("]]>"); - return -1; - } - - public int writeCData(char[] cbuf, int offset, int len) - throws IOException - { - writeAscii("= 0) { - return ix; - } - writeAscii("]]>"); - return -1; - } - - public final void writeCharacters(String data) - throws IOException - { - // Note: may get second part of a surrogate - if (mTextWriter != null) { // custom escaping? - mTextWriter.write(data); - } else { // nope, default: - writeTextContent(data); - } - } - - public final void writeCharacters(char[] cbuf, int offset, int len) - throws IOException - { - // Note: may get second part of a surrogate - if (mTextWriter != null) { // custom escaping? - mTextWriter.write(cbuf, offset, len); - } else { // nope, default: - writeTextContent(cbuf, offset, len); - } - } - - /** - * Method that will try to output the content as specified. If - * the content passed in has embedded "--" in it, it will either - * add an intervening space between consequtive hyphens (if content - * fixing is enabled), or return the offset of the first hyphen in - * multi-hyphen sequence. - */ - public int writeComment(String data) - throws IOException - { - writeAscii(""); - return -1; - } - - public void writeDTD(String data) - throws IOException - { - if (mSurrogate != 0) { - throwUnpairedSurrogate(); - } - writeRaw(data, 0, data.length()); - } - - public void writeDTD(String rootName, String systemId, String publicId, - String internalSubset) - throws IOException, XMLStreamException - { - writeAscii(" 0) { - writeAscii(BYTE_SPACE, BYTE_LBRACKET); - writeRaw(internalSubset, 0, internalSubset.length()); - writeAscii(BYTE_RBRACKET); - } - writeAscii(BYTE_GT); - } - - public void writeEntityReference(String name) - throws IOException, XMLStreamException - { - if (mSurrogate != 0) { - throwUnpairedSurrogate(); - } - writeAscii(BYTE_AMP); - writeName(name); - writeAscii(BYTE_SEMICOLON); - } - - public void writeXmlDeclaration(String version, String encoding, String standalone) - throws IOException - { - writeAscii(" 0) { - writeAscii(" encoding='"); - // Should be ascii, but let's play it safe: - writeRaw(encoding, 0, encoding.length()); - writeAscii(BYTE_APOS); - } - if (standalone != null) { - writeAscii(" standalone='"); - writeAscii(standalone); - writeAscii(BYTE_APOS); - } - writeAscii(BYTE_QMARK, BYTE_GT); - } - - public int writePI(String target, String data) - throws IOException, XMLStreamException - { - writeAscii(BYTE_LT, BYTE_QMARK); - writeName(target); - if (data != null && data.length() > 0) { - writeAscii(BYTE_SPACE); - int ix = writePIData(data); - if (ix >= 0) { // embedded "?>"? - return ix; - } - } - writeAscii(BYTE_QMARK, BYTE_GT); - return -1; - } - - /* - //////////////////////////////////////////////////// - // Write methods, elements - //////////////////////////////////////////////////// - */ - - public void writeStartTagStart(String localName) - throws IOException, XMLStreamException - { - writeAscii(BYTE_LT); - writeName(localName); - } - - public void writeStartTagStart(String prefix, String localName) - throws IOException, XMLStreamException - { - if (prefix == null || prefix.length() == 0) { - writeStartTagStart(localName); - return; - } - writeAscii(BYTE_LT); - writeName(prefix); - writeAscii(BYTE_COLON); - writeName(localName); - } - - public void writeStartTagEnd() - throws IOException - { - writeAscii(BYTE_GT); - } - - public void writeStartTagEmptyEnd() - throws IOException - { - if (mAddSpaceAfterEmptyElem) { - writeAscii(" />"); - } else { - writeAscii(BYTE_SLASH, BYTE_GT); - } - } - - public void writeEndTag(String localName) - throws IOException - { - writeAscii(BYTE_LT, BYTE_SLASH); - /* At this point, it is assumed caller knows that end tag - * matches with start tag, and that it (by extension) has been - * validated if and as necessary - */ - writeNameUnchecked(localName); - writeAscii(BYTE_GT); - } - - public void writeEndTag(String prefix, String localName) - throws IOException - { - writeAscii(BYTE_LT, BYTE_SLASH); - /* At this point, it is assumed caller knows that end tag - * matches with start tag, and that it (by extension) has been - * validated if and as necessary - */ - if (prefix != null && prefix.length() > 0) { - writeNameUnchecked(prefix); - writeAscii(BYTE_COLON); - } - writeNameUnchecked(localName); - writeAscii(BYTE_GT); - } - - /* - //////////////////////////////////////////////////// - // Write methods, attributes/ns - //////////////////////////////////////////////////// - */ - - public void writeAttribute(String localName, String value) - throws IOException, XMLStreamException - { - writeAscii(BYTE_SPACE); - writeName(localName); - writeAscii(BYTE_EQ, BYTE_QUOT); - - int len = value.length(); - if (len > 0) { - if (mAttrValueWriter != null) { // custom escaping? - mAttrValueWriter.write(value, 0, len); - } else { // nope, default - writeAttrValue(value); - } - } - writeAscii(BYTE_QUOT); - } - - public void writeAttribute(String localName, char[] value, int offset, int len) - throws IOException, XMLStreamException - { - writeAscii(BYTE_SPACE); - writeName(localName); - writeAscii(BYTE_EQ, BYTE_QUOT); - - if (len > 0) { - if (mAttrValueWriter != null) { // custom escaping? - mAttrValueWriter.write(value, offset, len); - } else { // nope, default - writeAttrValue(value, offset, len); - } - } - writeAscii(BYTE_QUOT); - } - - public void writeAttribute(String prefix, String localName, String value) - throws IOException, XMLStreamException - { - writeAscii(BYTE_SPACE); - writeName(prefix); - writeAscii(BYTE_COLON); - writeName(localName); - writeAscii(BYTE_EQ, BYTE_QUOT); - - int len = value.length(); - if (len > 0) { - if (mAttrValueWriter != null) { // custom escaping? - mAttrValueWriter.write(value, 0, len); - } else { // nope, default - writeAttrValue(value); - } - } - writeAscii(BYTE_QUOT); - } - - public void writeAttribute(String prefix, String localName, char[] value, int offset, int len) - throws IOException, XMLStreamException - { - writeAscii(BYTE_SPACE); - writeName(prefix); - writeAscii(BYTE_COLON); - writeName(localName); - writeAscii(BYTE_EQ, BYTE_QUOT); - - if (len > 0) { - if (mAttrValueWriter != null) { // custom escaping? - mAttrValueWriter.write(value, offset, len); - } else { // nope, default - writeAttrValue(value, offset, len); - } - } - writeAscii(BYTE_QUOT); - } - - /* - //////////////////////////////////////////////// - // Methods used by Typed Access API - //////////////////////////////////////////////// - */ - - /** - * Non-validating version of typed write method - */ - public final void writeTypedElement(AsciiValueEncoder enc) - throws IOException - { - if (mSurrogate != 0) { - throwUnpairedSurrogate(); - } - if (enc.bufferNeedsFlush(mOutputBuffer.length - mOutputPtr)) { - flush(); - } - while (true) { - mOutputPtr = enc.encodeMore(mOutputBuffer, mOutputPtr, mOutputBuffer.length); - // If no flushing needed, indicates that all data was encoded - if (enc.isCompleted()) { - break; - } - flush(); - } - } - - /** - * Validating version of typed write method - */ - public final void writeTypedElement(AsciiValueEncoder enc, - XMLValidator validator, char[] copyBuffer) - throws IOException, XMLStreamException - { - if (mSurrogate != 0) { - throwUnpairedSurrogate(); - } - - /* Ok, this gets trickier: can't use efficient direct-to-bytes - * encoding since validator won't be able to use it. Instead - * have to use temporary copy buffer. - */ - final int copyBufferLen = copyBuffer.length; - - // Copy buffer should never be too small, no need to check up front - do { - int ptr = enc.encodeMore(copyBuffer, 0, copyBufferLen); - - // False -> can't be sure it's the whole remaining text - validator.validateText(copyBuffer, 0, ptr, false); - writeRawAscii(copyBuffer, 0, ptr); - } while (!enc.isCompleted()); - } - - public void writeTypedAttribute(String localName, AsciiValueEncoder enc) - throws IOException, XMLStreamException - { - writeAscii(BYTE_SPACE); - writeName(localName); - writeAscii(BYTE_EQ, BYTE_QUOT); - - if (enc.bufferNeedsFlush(mOutputBuffer.length - mOutputPtr)) { - flush(); - } - while (true) { - mOutputPtr = enc.encodeMore(mOutputBuffer, mOutputPtr, mOutputBuffer.length); - if (enc.isCompleted()) { - break; - } - flush(); - } - writeAscii(BYTE_QUOT); - } - - public void writeTypedAttribute(String prefix, String localName, - AsciiValueEncoder enc) - throws IOException, XMLStreamException - { - writeAscii(BYTE_SPACE); - writeName(prefix); - writeAscii(BYTE_COLON); - writeName(localName); - writeAscii(BYTE_EQ, BYTE_QUOT); - - if (enc.bufferNeedsFlush(mOutputBuffer.length - mOutputPtr)) { - flush(); - } - while (true) { - mOutputPtr = enc.encodeMore(mOutputBuffer, mOutputPtr, mOutputBuffer.length); - if (enc.isCompleted()) { - break; - } - flush(); - } - writeAscii(BYTE_QUOT); - } - - public void writeTypedAttribute(String prefix, String localName, String nsURI, - AsciiValueEncoder enc, - XMLValidator validator, char[] copyBuffer) - throws IOException, XMLStreamException - { - boolean hasPrefix = (prefix != null && prefix.length() > 0); - if (nsURI == null) { - nsURI = ""; - } - //validator.validateAttribute(localName, nsURI, (hasPrefix ? prefix: ""), buf, offset, len); - - writeAscii(BYTE_SPACE); - if (hasPrefix) { - writeName(prefix); - writeAscii(BYTE_COLON); - } - writeName(localName); - writeAscii(BYTE_EQ, BYTE_QUOT); - - /* Ok, this gets trickier: can't use efficient direct-to-bytes - * encoding since validator won't be able to use it. Instead - * have to use temporary copy buffer. - * In addition, attributes to validate can not be - * split (validators expect complete values). So, if value - * won't fit as is, may need to aggregate using StringBuilder - */ - final int copyBufferLen = copyBuffer.length; - - // First, let's see if one call is enough - int last = enc.encodeMore(copyBuffer, 0, copyBufferLen); - writeRawAscii(copyBuffer, 0, last); - if (enc.isCompleted()) { - validator.validateAttribute(localName, nsURI, prefix, copyBuffer, 0, last); - return; - } - - // If not, must combine first - StringBuffer sb = new StringBuffer(copyBufferLen << 1); - sb.append(copyBuffer, 0, last); - do { - last = enc.encodeMore(copyBuffer, 0, copyBufferLen); - writeRawAscii(copyBuffer, 0, last); - sb.append(copyBuffer, 0, last); - } while (!enc.isCompleted()); - - writeAscii(BYTE_QUOT); - - // Then validate - String valueStr = sb.toString(); - validator.validateAttribute(localName, nsURI, prefix, valueStr); - - return; - } - - /* - //////////////////////////////////////////////// - // Methods for sub-classes to use - //////////////////////////////////////////////// - */ - - protected final void flushBuffer() - throws IOException - { - if (mOutputPtr > 0 && mOutputBuffer != null) { - int ptr = mOutputPtr; - mOutputPtr = 0; - mOut.write(mOutputBuffer, 0, ptr); - } - } - - protected final void writeAscii(byte b) - throws IOException - { - if (mSurrogate != 0) { - throwUnpairedSurrogate(); - } - if (mOutputPtr >= mOutputBuffer.length) { - flushBuffer(); - } - mOutputBuffer[mOutputPtr++] = b; - } - - protected final void writeAscii(byte b1, byte b2) - throws IOException - { - if (mSurrogate != 0) { - throwUnpairedSurrogate(); - } - if ((mOutputPtr + 1) >= mOutputBuffer.length) { - flushBuffer(); - } - mOutputBuffer[mOutputPtr++] = b1; - mOutputBuffer[mOutputPtr++] = b2; - } - - protected final void writeAscii(String str) - throws IOException - { - if (mSurrogate != 0) { - throwUnpairedSurrogate(); - } - - int len = str.length(); - int ptr = mOutputPtr; - byte[] buf = mOutputBuffer; - if ((ptr + len) >= buf.length) { - /* It's even possible that String is longer than the buffer (not - * likely, possible). If so, let's just call the full - * method: - */ - if (len > buf.length) { - writeRaw(str, 0, len); - return; - } - flushBuffer(); - ptr = mOutputPtr; - } - mOutputPtr += len; - for (int i = 0; i < len; ++i) { - buf[ptr++] = (byte)str.charAt(i); - } - } - - public final void writeRawAscii(char[] buf, int offset, int len) - throws IOException - { - if (mSurrogate != 0) { - throwUnpairedSurrogate(); - } - int ptr = mOutputPtr; - byte[] dst = mOutputBuffer; - if ((ptr + len) >= dst.length) { - if (len > dst.length) { - writeRaw(buf, offset, len); - return; - } - flushBuffer(); - ptr = mOutputPtr; - } - mOutputPtr += len; - for (int i = 0; i < len; ++i) { - dst[ptr+i] = (byte)buf[offset+i]; - } - } - - /** - * Entity writing can be optimized quite nicely, since it only - * needs to output ascii characters. - * - * @return New value of mOutputPtr - */ - protected final int writeAsEntity(int c) - throws IOException - { - byte[] buf = mOutputBuffer; - int ptr = mOutputPtr; - if ((ptr + 10) >= buf.length) { // &#x [up to 6 hex digits] ; - flushBuffer(); - ptr = mOutputPtr; - } - buf[ptr++] = BYTE_AMP; - - // Can use more optimal notation for 8-bit ascii stuff: - if (c < 256) { - /* Also; although not really mandatory, let's also - * use pre-defined entities where possible. - */ - if (c == '&') { - buf[ptr++] = BYTE_A; - buf[ptr++] = BYTE_M; - buf[ptr++] = BYTE_P; - } else if (c == '<') { - buf[ptr++] = BYTE_L; - buf[ptr++] = BYTE_T; - } else if (c == '>') { - buf[ptr++] = BYTE_G; - buf[ptr++] = BYTE_T; - } else if (c == '\'') { - buf[ptr++] = BYTE_A; - buf[ptr++] = BYTE_P; - buf[ptr++] = BYTE_O; - buf[ptr++] = BYTE_S; - } else if (c == '"') { - buf[ptr++] = BYTE_Q; - buf[ptr++] = BYTE_U; - buf[ptr++] = BYTE_O; - buf[ptr++] = BYTE_T; - } else { - buf[ptr++] = BYTE_HASH; - buf[ptr++] = BYTE_X; - // Can use shortest quoting for tab, cr, lf: - if (c >= 16) { - int digit = (c >> 4); - buf[ptr++] = (byte) ((digit < 10) ? ('0' + digit) : (('a' - 10) + digit)); - c &= 0xF; - } - buf[ptr++] = (byte) ((c < 10) ? ('0' + c) : (('a' - 10) + c)); - } - } else { - buf[ptr++] = BYTE_HASH; - buf[ptr++] = BYTE_X; - - // Ok, let's write the shortest possible sequence then: - int shift = 20; - int origPtr = ptr; - - do { - int digit = (c >> shift) & 0xF; - if (digit > 0 || (ptr != origPtr)) { - buf[ptr++] = (byte) ((digit < 10) ? ('0' + digit) : (('a' - 10) + digit)); - } - shift -= 4; - } while (shift > 0); - c &= 0xF; - buf[ptr++] = (byte) ((c < 10) ? ('0' + c) : (('a' - 10) + c)); - } - buf[ptr++] = BYTE_SEMICOLON; - mOutputPtr = ptr; - return ptr; - } - - protected final void writeName(String name) - throws IOException, XMLStreamException - { - if (mCheckNames) { - verifyNameValidity(name, mNsAware); - } - // TODO: maybe we could reuse some previously encoded names? - writeRaw(name, 0, name.length()); - } - - protected final void writeNameUnchecked(String name) - throws IOException - { - writeRaw(name, 0, name.length()); - } - - protected final int calcSurrogate(int secondSurr) - throws IOException - { - // First, let's verify first surrogate is valid: - int firstSurr = mSurrogate; - mSurrogate = 0; - if (firstSurr < SURR1_FIRST || firstSurr > SURR1_LAST) { - throwUnpairedSurrogate(firstSurr); - } - - // Then that the second one is: - if ((secondSurr < SURR2_FIRST) || (secondSurr > SURR2_LAST)) { - throwUnpairedSurrogate(secondSurr); - } - int ch = 0x10000 + ((firstSurr - SURR1_FIRST) << 10) + (secondSurr - SURR2_FIRST); - if (ch > XmlConsts.MAX_UNICODE_CHAR) { - throw new IOException("Illegal surrogate character pair, resulting code 0x"+Integer.toHexString(ch)+" above legal XML character range"); - } - return ch; - } - - protected final void throwUnpairedSurrogate() - throws IOException - { - int surr = mSurrogate; - mSurrogate = 0; - throwUnpairedSurrogate(surr); - } - - protected final void throwUnpairedSurrogate(int code) - throws IOException -{ - // Let's flush to make debugging easier - flush(); - throw new IOException("Unpaired surrogate character (0x"+Integer.toHexString(code)+")"); -} - - /* - //////////////////////////////////////////////// - // Abstract methods for sub-classes to define - //////////////////////////////////////////////// - */ - - protected abstract void writeAttrValue(String data) - throws IOException; - - protected abstract void writeAttrValue(char[] value, int offset, int len) - throws IOException; - - protected abstract int writeCDataContent(String data) - throws IOException; - - protected abstract int writeCDataContent(char[] cbuf, int start, int len) - throws IOException; - - protected abstract int writeCommentContent(String data) - throws IOException; - - protected abstract int writePIData(String data) - throws IOException, XMLStreamException; - - protected abstract void writeTextContent(String data) - throws IOException; - - protected abstract void writeTextContent(char[] cbuf, int start, int len) - throws IOException; -} diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/sw/ISOLatin1XmlWriter.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/sw/ISOLatin1XmlWriter.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/sw/ISOLatin1XmlWriter.java 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/sw/ISOLatin1XmlWriter.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,791 +0,0 @@ -/* Woodstox XML processor - * - * Copyright (c) 2004- Tatu Saloranta, tatu.saloranta@iki.fi - * - * Licensed under the License specified in file LICENSE, included with - * the source code. - * You may not use this file except in compliance with the License. - * - * 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 com.ctc.wstx.sw; - -import java.io.*; - -import javax.xml.stream.XMLStreamException; - -import com.ctc.wstx.api.WriterConfig; -import com.ctc.wstx.io.CharsetNames; - -/** - * Concrete implementation of {@link EncodingXmlWriter} used when output - * is to be encoded using ISO-8859-1, aka ISO-Latin1 encoding. - *

- * Regarding surrogate pair handling: most of the checks are in the base - * class, and here we only need to worry about writeRaw - * methods. - */ -public final class ISOLatin1XmlWriter - extends EncodingXmlWriter -{ - public ISOLatin1XmlWriter(OutputStream out, WriterConfig cfg, boolean autoclose) - throws IOException - { - super(out, cfg, CharsetNames.CS_ISO_LATIN1, autoclose); - } - - public void writeRaw(char[] cbuf, int offset, int len) - throws IOException - { - if (mSurrogate != 0) { - throwUnpairedSurrogate(); - } - - int ptr = mOutputPtr; - while (len > 0) { - int max = mOutputBuffer.length - ptr; - if (max < 1) { // output buffer full? - mOutputPtr = ptr; - flushBuffer(); - ptr = 0; - max = mOutputBuffer.length; - } - // How much can we output? - if (max > len) { - max = len; - } - if (mCheckContent) { - for (int inEnd = offset + max; offset < inEnd; ++offset) { - int c = cbuf[offset]; - if (c < 32) { - if (c == '\n') { - // !!! TBI: line nr - } else if (c == '\r') { - // !!! TBI: line nr (and skipping \n that may follow) - } else if (c != '\t') { - mOutputPtr = ptr; - c = handleInvalidChar(c); - } - } else if (c > 0x7E) { - if (c > 0xFF) { - mOutputPtr = ptr; - handleInvalidLatinChar(c); - } else if (mXml11) { - if (c < 0x9F && c != 0x85) { - mOutputPtr = ptr; - c = handleInvalidChar(c); - } - } - } - mOutputBuffer[ptr++] = (byte) c; - } - } else { - for (int inEnd = offset + max; offset < inEnd; ++offset) { - mOutputBuffer[ptr++] = (byte) cbuf[offset]; - } - } - len -= max; - } - mOutputPtr = ptr; - } - - public void writeRaw(String str, int offset, int len) - throws IOException - { - if (mSurrogate != 0) { - throwUnpairedSurrogate(); - } - int ptr = mOutputPtr; - while (len > 0) { - int max = mOutputBuffer.length - ptr; - if (max < 1) { // output buffer full? - mOutputPtr = ptr; - flushBuffer(); - ptr = 0; - max = mOutputBuffer.length; - } - // How much can we output? - if (max > len) { - max = len; - } - if (mCheckContent) { - for (int inEnd = offset + max; offset < inEnd; ++offset) { - int c = str.charAt(offset); - if (c < 32) { - if (c == '\n') { - // !!! TBI: line nr - } else if (c == '\r') { - // !!! TBI: line nr (and skipping \n that may follow) - } else if (c != '\t') { - mOutputPtr = ptr; - c = handleInvalidChar(c); - } - } else if (c > 0x7E) { - if (c > 0xFF) { - mOutputPtr = ptr; - handleInvalidLatinChar(c); - } else if (mXml11) { - if (c < 0x9F && c != 0x85) { - mOutputPtr = ptr; - c = handleInvalidChar(c); - } - } - } - mOutputBuffer[ptr++] = (byte) c; - } - } else { - for (int inEnd = offset + max; offset < inEnd; ++offset) { - mOutputBuffer[ptr++] = (byte) str.charAt(offset); - } - } - len -= max; - } - mOutputPtr = ptr; - } - - protected void writeAttrValue(String data) - throws IOException - { - int offset = 0; - int len = data.length(); - int ptr = mOutputPtr; - - main_loop: - while (len > 0) { - int max = mOutputBuffer.length - ptr; - if (max < 1) { // output buffer full? - mOutputPtr = ptr; - flushBuffer(); - ptr = 0; - max = mOutputBuffer.length; - } - // Do we start with a surrogate? - if (mSurrogate != 0) { - int sec = data.charAt(offset++); - sec = calcSurrogate(sec); - mOutputPtr = ptr; - ptr = writeAsEntity(sec); - --len; - continue main_loop; - } - // How much can we output? - if (max > len) { - max = len; - } - inner_loop: - for (int inEnd = offset + max; offset < inEnd; ) { - int c = data.charAt(offset++); - if (c < 32) { - /* Need to quote all white space except for regular - * space chars, to preserve them (round-tripping) - */ - if (c == '\r') { - if (!mEscapeCR) { - mOutputBuffer[ptr++] = (byte) c; - continue; - } - } else if (c != '\n' && c != '\t') { - if (mCheckContent) { - if (!mXml11 || c == 0) { - c = handleInvalidChar(c); - mOutputBuffer[ptr++] = (byte) c; - continue; - } - } - } - // fall-through to char entity output - } else if (c < 0x7F) { - if (c != '<' && c != '&' && c != '"') { - mOutputBuffer[ptr++] = (byte) c; - continue; - } - // otherwise fall back on quoting - } else if (c > 0x9F && c <= 0xFF) { - mOutputBuffer[ptr++] = (byte) c; - continue; // [WSTX-88] - } else { - // Surrogate? - if (c >= SURR1_FIRST && c <= SURR2_LAST) { - mSurrogate = c; - // Last char needs special handling: - if (offset == inEnd) { - break inner_loop; - } - c = calcSurrogate(data.charAt(offset++)); - // Let's fall down to entity output - } - } - /* Has to be escaped as char entity; as such, also need - * to re-calc max. continguous data we can output - */ - mOutputPtr = ptr; - ptr = writeAsEntity(c); - len = data.length() - offset; - continue main_loop; - } - len -= max; - } - mOutputPtr = ptr; - } - - protected void writeAttrValue(char[] data, int offset, int len) - throws IOException - { - int ptr = mOutputPtr; - - main_loop: - while (len > 0) { - int max = mOutputBuffer.length - ptr; - if (max < 1) { // output buffer full? - mOutputPtr = ptr; - flushBuffer(); - ptr = 0; - max = mOutputBuffer.length; - } - // Do we start with a surrogate? - if (mSurrogate != 0) { - int sec = data[offset++]; - sec = calcSurrogate(sec); - mOutputPtr = ptr; - ptr = writeAsEntity(sec); - --len; - continue main_loop; - } - // How much can we output? - if (max > len) { - max = len; - } - inner_loop: - for (int inEnd = offset + max; offset < inEnd; ) { - int c = data[offset++]; - if (c < 32) { - /* Need to quote all white space except for regular - * space chars, to preserve them (round-tripping) - */ - if (c == '\r') { - if (!mEscapeCR) { - mOutputBuffer[ptr++] = (byte) c; - continue; - } - } else if (c != '\n' && c != '\t') { - if (mCheckContent) { - if (!mXml11 || c == 0) { - c = handleInvalidChar(c); - mOutputBuffer[ptr++] = (byte) c; - continue; - } - } - } - // fall-through to char entity output - } else if (c < 0x7F) { - if (c != '<' && c != '&' && c != '"') { - mOutputBuffer[ptr++] = (byte) c; - continue; - } - // otherwise fall back on quoting - } else if (c > 0x9F && c <= 0xFF) { - mOutputBuffer[ptr++] = (byte) c; - continue; // [WSTX-88] - } else { - // Surrogate? - if (c >= SURR1_FIRST && c <= SURR2_LAST) { - mSurrogate = c; - // Last char needs special handling: - if (offset == inEnd) { - break inner_loop; - } - c = calcSurrogate(data[offset++]); - // Let's fall down to entity output - } - } - /* Has to be escaped as char entity; as such, also need - * to re-calc max. contiguous data we can output - */ - mOutputPtr = ptr; - ptr = writeAsEntity(c); - max -= (inEnd - offset); // since we didn't loop completely - break inner_loop; - } - len -= max; - } - mOutputPtr = ptr; - } - - protected int writeCDataContent(String data) - throws IOException - { - // Note: mSurrogate can not be non-zero at this point, no need to check - - int offset = 0; - int len = data.length(); - if (!mCheckContent) { - writeRaw(data, offset, len); - return -1; - } - int ptr = mOutputPtr; - - main_loop: - while (len > 0) { - int max = mOutputBuffer.length - ptr; - if (max < 1) { // output buffer full? - mOutputPtr = ptr; - flushBuffer(); - ptr = 0; - max = mOutputBuffer.length; - } - // How much can we output? - if (max > len) { - max = len; - } - for (int inEnd = offset + max; offset < inEnd; ) { - int c = data.charAt(offset++); - if (c < 32) { - if (c == '\n') { - // !!! TBI: line nr - } else if (c == '\r') { - // !!! TBI: line nr (and skipping \n that may follow) - } else if (c != '\t') { - mOutputPtr = ptr; - c = handleInvalidChar(c); - } - } else if (c > 0x7E) { - if (c > 0xFF) { - mOutputPtr = ptr; - handleInvalidLatinChar(c); - } else if (mXml11) { - if (c < 0x9F && c != 0x85) { - mOutputPtr = ptr; - c = handleInvalidChar(c); - } - } - } else if (c == '>') { // embedded "]]>"? - if (offset > 2 && data.charAt(offset-2) == ']' - && data.charAt(offset-3) == ']') { - if (!mFixContent) { - return offset-3; - } - /* Relatively easy fix; just need to close this - * section, and open a new one... - */ - mOutputPtr = ptr; - writeCDataEnd(); - writeCDataStart(); - writeAscii(BYTE_GT); - ptr = mOutputPtr; - /* No guarantees there's as much free room in the - * output buffer, thus, need to restart loop: - */ - len = data.length() - offset; - continue main_loop; - } - } - mOutputBuffer[ptr++] = (byte) c; - } - len -= max; - } - mOutputPtr = ptr; - return -1; - } - - protected int writeCDataContent(char[] cbuf, int start, int len) - throws IOException - { - // Note: mSurrogate can not be non-zero at this point, no need to check - - if (!mCheckContent) { - writeRaw(cbuf, start, len); - return -1; - } - - int ptr = mOutputPtr; - int offset = start; - - while (len > 0) { - int max = mOutputBuffer.length - ptr; - if (max < 1) { // output buffer full? - mOutputPtr = ptr; - flushBuffer(); - ptr = 0; - max = mOutputBuffer.length; - } - // How much can we output? - if (max > len) { - max = len; - } - inner_loop: - for (int inEnd = offset + max; offset < inEnd; ) { - int c = cbuf[offset++]; - if (c < 32) { - if (c == '\n') { - // !!! TBI: line nr - } else if (c == '\r') { - // !!! TBI: line nr (and skipping \n that may follow) - } else if (c != '\t') { - mOutputPtr = ptr; - c = handleInvalidChar(c); - } - } else if (c > 0x7E) { - if (c > 0xFF) { - mOutputPtr = ptr; - handleInvalidLatinChar(c); - } else if (mXml11) { - if (c < 0x9F && c != 0x85) { - mOutputPtr = ptr; - c = handleInvalidChar(c); - } - } - } else if (c == '>') { // embedded "]]>"? - if (offset >= (start+3) && cbuf[offset-2] == ']' - && cbuf[offset-3] == ']') { - if (!mFixContent) { - return offset-3; - } - /* Relatively easy fix; just need to close this - * section, and open a new one... - */ - mOutputPtr = ptr; - writeCDataEnd(); - writeCDataStart(); - writeAscii(BYTE_GT); - ptr = mOutputPtr; - /* No guarantees there's as much free room in the - * output buffer, thus, need to restart loop: - */ - max -= (inEnd - offset); - break inner_loop; - } - } - mOutputBuffer[ptr++] = (byte) c; - } - len -= max; - } - mOutputPtr = ptr; - return -1; - } - - protected int writeCommentContent(String data) - throws IOException - { - // Note: mSurrogate can not be non-zero at this point, no need to check - - int offset = 0; - int len = data.length(); - if (!mCheckContent) { - writeRaw(data, offset, len); - return -1; - } - - int ptr = mOutputPtr; - - while (len > 0) { - int max = mOutputBuffer.length - ptr; - if (max < 1) { // output buffer full? - mOutputPtr = ptr; - flushBuffer(); - ptr = 0; - max = mOutputBuffer.length; - } - // How much can we output? - if (max > len) { - max = len; - } - inner_loop: - for (int inEnd = offset + max; offset < inEnd; ) { - int c = data.charAt(offset++); - if (c < 32) { - if (c == '\n') { - // !!! TBI: line nr - } else if (c == '\r') { - // !!! TBI: line nr (and skipping \n that may follow) - } else if (c != '\t') { - mOutputPtr = ptr; - c = handleInvalidChar(c); - } - } else if (c > 0x7E) { - if (c > 0xFF) { - mOutputPtr = ptr; - handleInvalidLatinChar(c); - } else if (mXml11) { - if (c < 0x9F && c != 0x85) { - mOutputPtr = ptr; - c = handleInvalidChar(c); - } - } - } else if (c == '-') { // embedded "--"? - if (offset > 1 && data.charAt(offset-2) == '-') { - if (!mFixContent) { - return offset-2; - } - /* Quite easy to fix: just add an extra space - * in front. There will be room for that char; - * but may need to take that the following '-' - * also fits. - */ - mOutputBuffer[ptr++] = ' '; - if (ptr >= mOutputBuffer.length) { // whops. need to flush - mOutputPtr = ptr; - flushBuffer(); - ptr = 0; - } - mOutputBuffer[ptr++] = BYTE_HYPHEN; - /* Also, since we did output an extra char, better - * restart the loop (since max calculation is now - * off) - */ - max -= (inEnd - offset); - break inner_loop; - } - } - mOutputBuffer[ptr++] = (byte) c; - } - len -= max; - } - mOutputPtr = ptr; - return -1; - } - - protected int writePIData(String data) - throws IOException, XMLStreamException - { - // Note: mSurrogate can not be non-zero at this point, no need to check - - int offset = 0; - int len = data.length(); - if (!mCheckContent) { - writeRaw(data, offset, len); - return -1; - } - - int ptr = mOutputPtr; - while (len > 0) { - int max = mOutputBuffer.length - ptr; - if (max < 1) { // output buffer full? - mOutputPtr = ptr; - flushBuffer(); - ptr = 0; - max = mOutputBuffer.length; - } - // How much can we output? - if (max > len) { - max = len; - } - for (int inEnd = offset + max; offset < inEnd; ++offset) { - int c = data.charAt(offset); - if (c < 32) { - if (c == '\n') { - // !!! TBI: line nr - } else if (c == '\r') { - // !!! TBI: line nr (and skipping \n that may follow) - } else if (c != '\t') { - mOutputPtr = ptr; - c = handleInvalidChar(c); - } - } else if (c > 0x7E) { - if (c > 0xFF) { - mOutputPtr = ptr; - handleInvalidLatinChar(c); - } else if (mXml11) { - if (c < 0x9F && c != 0x85) { - mOutputPtr = ptr; - c = handleInvalidChar(c); - } - } - } else if (c == '>') { // enclosed end marker ("?>")? - if (offset > 0 && data.charAt(offset-1) == '?') { - return offset-2; - } - } - mOutputBuffer[ptr++] = (byte) c; - } - len -= max; - } - mOutputPtr = ptr; - return -1; - } - - protected void writeTextContent(String data) - throws IOException - { - int offset = 0; - int len = data.length(); - - main_loop: - while (len > 0) { - int max = mOutputBuffer.length - mOutputPtr; - if (max < 1) { // output buffer full? - flushBuffer(); - max = mOutputBuffer.length; - } - // Do we start with a surrogate? - if (mSurrogate != 0) { - int sec = data.charAt(offset++); - sec = calcSurrogate(sec); - writeAsEntity(sec); - --len; - continue main_loop; - } - // How much can we output? - if (max > len) { - max = len; - } - inner_loop: - for (int inEnd = offset + max; offset < inEnd; ) { - int c = data.charAt(offset++); - if (c < 32) { - if (c == '\n' || c == '\t') { // TODO: line count - mOutputBuffer[mOutputPtr++] = (byte) c; - continue; - } else if (c == '\r') { - if (!mEscapeCR) { - mOutputBuffer[mOutputPtr++] = (byte) c; - continue; - } - } else if (!mXml11 || c == 0) { // ok in xml1.1, as entity - if (mCheckContent) { - c = handleInvalidChar(c); - mOutputBuffer[mOutputPtr++] = (byte) c; - continue; - } - // otherwise... well, I guess we can just escape it - } - // \r, or xml1.1 + other whitespace, need to escape - } else if (c < 0x7F) { - if (c != '<' && c != '&') { - if (c != '>' || (offset > 1 && data.charAt(offset-2) != ']')) { - mOutputBuffer[mOutputPtr++] = (byte) c; - continue; - } - } - // otherwise fall back on quoting - } else if (c > 0x9F && c <= 0xFF) { - mOutputBuffer[mOutputPtr++] = (byte) c; - continue; // [WSTX-88] - } else { - // Surrogate? - if (c >= SURR1_FIRST && c <= SURR2_LAST) { - mSurrogate = c; - // Last char needs special handling: - if (offset == inEnd) { - break inner_loop; - } - c = calcSurrogate(data.charAt(offset++)); - // Let's fall down to entity output - } - } - /* Has to be escaped as char entity; as such, also need - * to re-calc max. continguous data we can output - */ - writeAsEntity(c); - len = data.length() - offset; - continue main_loop; - } - len -= max; - } - } - - protected void writeTextContent(char[] cbuf, int offset, int len) - throws IOException - { - main_loop: - while (len > 0) { - int max = mOutputBuffer.length - mOutputPtr; - if (max < 1) { // output buffer full? - flushBuffer(); - max = mOutputBuffer.length; - } - // Do we start with a surrogate? - if (mSurrogate != 0) { - int sec = cbuf[offset++]; - sec = calcSurrogate(sec); - writeAsEntity(sec); - --len; - continue main_loop; - } - // How much can we output? - if (max > len) { - max = len; - } - inner_loop: - for (int inEnd = offset + max; offset < inEnd; ) { - int c = cbuf[offset++]; - if (c < 32) { - if (c == '\n' || c == '\t') { // TODO: line count - mOutputBuffer[mOutputPtr++] = (byte) c; - continue; - } else if (c == '\r') { - if (!mEscapeCR) { - mOutputBuffer[mOutputPtr++] = (byte) c; - continue; - } - } else if (!mXml11 || c == 0) { // ok in xml1.1, as entity - if (mCheckContent) { - c = handleInvalidChar(c); - mOutputBuffer[mOutputPtr++] = (byte) c; - continue; - } - // otherwise... well, I guess we can just escape it - } - // \r, or xml1.1 + other whitespace, need to escape - } else if (c < 0x7F) { - if (c !='<' && c != '&') { - /* Since we can be conservative, it doesn't matter - * if second check is not exact - */ - if (c != '>' || (offset > 1 && cbuf[offset-2] != ']')) { - mOutputBuffer[mOutputPtr++] = (byte) c; - continue; - } - } - // otherwise fall back on quoting - } else if (c > 0x9F && c <= 0xFF) { - mOutputBuffer[mOutputPtr++] = (byte) c; - continue; // [WSTX-88] - } else { - // Surrogate? - if (c >= SURR1_FIRST && c <= SURR2_LAST) { - mSurrogate = c; - // Last char needs special handling: - if (offset == inEnd) { - break inner_loop; - } - c = calcSurrogate(cbuf[offset++]); - // Let's fall down to entity output - } - } - /* Has to be escaped as char entity; as such, also need - * to re-calc max. continguous data we can output - */ - writeAsEntity(c); - max -= (inEnd - offset); - break inner_loop; - } - len -= max; - } - } - - /* - //////////////////////////////////////////////////// - // Internal methods - //////////////////////////////////////////////////// - */ - - protected void handleInvalidLatinChar(int c) - throws IOException - { - // First, let's flush any output we may have, to make debugging easier - flush(); - - /* 17-May-2006, TSa: Would really be useful if we could throw - * XMLStreamExceptions; esp. to indicate actual output location. - * However, this causes problem with methods that call us and - * can only throw IOExceptions (when invoked via Writer proxy). - * Need to figure out how to resolve this. - */ - throw new IOException("Invalid XML character (0x"+Integer.toHexString(c)+"); can only be output using character entity when using ISO-8859-1 encoding"); - } -} diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/sw/NonNsStreamWriter.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/sw/NonNsStreamWriter.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/sw/NonNsStreamWriter.java 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/sw/NonNsStreamWriter.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,553 +0,0 @@ -/* Woodstox XML processor - * - * Copyright (c) 2004- Tatu Saloranta, tatu.saloranta@iki.fi - * - * Licensed under the License specified in the file LICENSE which is - * included with the source code. - * You may not use this file except in compliance with the License. - * - * 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 com.ctc.wstx.sw; - -import java.io.IOException; -import java.util.*; - -import javax.xml.XMLConstants; -import javax.xml.namespace.NamespaceContext; -import javax.xml.namespace.QName; -import javax.xml.stream.XMLStreamWriter; -import javax.xml.stream.XMLStreamException; -import javax.xml.stream.events.Attribute; -import javax.xml.stream.events.StartElement; - -import org.codehaus.stax2.ri.typed.AsciiValueEncoder; - -import com.ctc.wstx.api.WriterConfig; -import com.ctc.wstx.cfg.ErrorConsts; -import com.ctc.wstx.cfg.XmlConsts; -import com.ctc.wstx.sr.AttributeCollector; -import com.ctc.wstx.sr.InputElementStack; -import com.ctc.wstx.util.EmptyNamespaceContext; -import com.ctc.wstx.util.StringVector; - -/** - * Implementation of {@link XMLStreamWriter} used when namespace support - * is not enabled. This means that only local names are used for elements - * and attributes; and if rudimentary namespace declarations need to be - * output, they are output using attribute writing methods. - */ -public class NonNsStreamWriter - extends TypedStreamWriter -{ - /* - //////////////////////////////////////////////////// - // State information - //////////////////////////////////////////////////// - */ - - /** - * Stack of currently open start elements; only local names - * are included. - */ - final StringVector mElements; - - /** - * Container for attribute names for current element; used only - * if uniqueness of attribute names is to be enforced. - *

- * TreeSet is used mostly because clearing it up is faster than - * clearing up HashSet, and the only access is done by - * adding entries and see if an value was already set. - */ - TreeSet mAttrNames; - - /* - //////////////////////////////////////////////////// - // Life-cycle (ctors) - //////////////////////////////////////////////////// - */ - - public NonNsStreamWriter(XmlWriter xw, String enc, WriterConfig cfg) - { - super(xw, enc, cfg); - mElements = new StringVector(32); - } - - /* - //////////////////////////////////////////////////// - // XMLStreamWriter API - //////////////////////////////////////////////////// - */ - - public NamespaceContext getNamespaceContext() { - return EmptyNamespaceContext.getInstance(); - } - - public String getPrefix(String uri) { - return null; - } - - public void setDefaultNamespace(String uri) - throws XMLStreamException - { - reportIllegalArg("Can not set default namespace for non-namespace writer."); - } - - public void setNamespaceContext(NamespaceContext context) - { - reportIllegalArg("Can not set NamespaceContext for non-namespace writer."); - } - - public void setPrefix(String prefix, String uri) - throws XMLStreamException - { - reportIllegalArg("Can not set namespace prefix for non-namespace writer."); - } - - public void writeAttribute(String localName, String value) - throws XMLStreamException - { - // No need to set mAnyOutput, nor close the element - if (!mStartElementOpen && mCheckStructure) { - reportNwfStructure(ErrorConsts.WERR_ATTR_NO_ELEM); - } - if (mCheckAttrs) { - /* 11-Dec-2005, TSa: Should use a more efficient Set/Map value - * for this in future. - */ - if (mAttrNames == null) { - mAttrNames = new TreeSet(); - } - if (!mAttrNames.add(localName)) { - reportNwfAttr("Trying to write attribute '"+localName+"' twice"); - } - } - if (mValidator != null) { - /* No need to get it normalized... even if validator does normalize - * it, we don't use that for anything - */ - mValidator.validateAttribute(localName, XmlConsts.ATTR_NO_NS_URI, XmlConsts.ATTR_NO_PREFIX, value); - } - - try { - mWriter.writeAttribute(localName, value); - } catch (IOException ioe) { - throwFromIOE(ioe); - } - } - - public void writeAttribute(String nsURI, String localName, String value) - throws XMLStreamException - { - writeAttribute(localName, value); - } - - public void writeAttribute(String prefix, String nsURI, - String localName, String value) - throws XMLStreamException - { - writeAttribute(localName, value); - } - - public void writeDefaultNamespace(String nsURI) - throws XMLStreamException - { - reportIllegalMethod("Can not call writeDefaultNamespace namespaces with non-namespace writer."); - } - - public void writeEmptyElement(String localName) - throws XMLStreamException - { - doWriteStartElement(localName); - mEmptyElement = true; - } - - public void writeEmptyElement(String nsURI, String localName) - throws XMLStreamException - { - writeEmptyElement(localName); - } - - public void writeEmptyElement(String prefix, String localName, String nsURI) - throws XMLStreamException - { - writeEmptyElement(localName); - } - - public void writeEndElement() - throws XMLStreamException - { - doWriteEndTag(null, mCfgAutomaticEmptyElems); - } - - public void writeNamespace(String prefix, String nsURI) - throws XMLStreamException - { - reportIllegalMethod("Can not set write namespaces with non-namespace writer."); - } - - public void writeStartElement(String localName) - throws XMLStreamException - { - doWriteStartElement(localName); - mEmptyElement = false; - } - - public void writeStartElement(String nsURI, String localName) - throws XMLStreamException - { - writeStartElement(localName); - } - - public void writeStartElement(String prefix, String localName, String nsURI) - throws XMLStreamException - { - writeStartElement(localName); - } - - /* - //////////////////////////////////////////////////// - // Remaining XMLStreamWriter2 methods (StAX2) - //////////////////////////////////////////////////// - */ - - /** - * Similar to {@link #writeEndElement}, but never allows implicit - * creation of empty elements. - */ - public void writeFullEndElement() - throws XMLStreamException - { - doWriteEndTag(null, false); - } - - /* - //////////////////////////////////////////////////// - // Remaining ValidationContext methods (StAX2) - //////////////////////////////////////////////////// - */ - - public QName getCurrentElementName() { - if (mElements.isEmpty()) { - return null; - } - return new QName(mElements.getLastString()); - } - - public String getNamespaceURI(String prefix) { - return null; - } - - /* - //////////////////////////////////////////////////// - // Package methods: - //////////////////////////////////////////////////// - */ - - public void writeStartElement(StartElement elem) - throws XMLStreamException - { - QName name = elem.getName(); - writeStartElement(name.getLocalPart()); - Iterator it = elem.getAttributes(); - while (it.hasNext()) { - Attribute attr = (Attribute) it.next(); - name = attr.getName(); - writeAttribute(name.getLocalPart(), attr.getValue()); - } - } - - /** - * Method called by {@link javax.xml.stream.XMLEventWriter} implementation - * (instead of the version - * that takes no argument), so that we can verify it does match the - * start element, if necessary - */ - public void writeEndElement(QName name) - throws XMLStreamException - { - doWriteEndTag(mCheckStructure ? name.getLocalPart() : null, - mCfgAutomaticEmptyElems); - } - - protected void writeTypedAttribute(String prefix, String nsURI, String localName, - AsciiValueEncoder enc) - throws XMLStreamException - { - // note: mostly copied from the other writeAttribute() method.. - if (!mStartElementOpen && mCheckStructure) { - reportNwfStructure(ErrorConsts.WERR_ATTR_NO_ELEM); - } - if (mCheckAttrs) { // doh. Not good, need to construct non-transient value... - if (mAttrNames == null) { - mAttrNames = new TreeSet(); - } - if (!mAttrNames.add(localName)) { - reportNwfAttr("Trying to write attribute '"+localName+"' twice"); - } - } - - try { - if (mValidator == null) { - mWriter.writeTypedAttribute(localName, enc); - } else { - mWriter.writeTypedAttribute(null, localName, null, enc, mValidator, getCopyBuffer()); - } - } catch (IOException ioe) { - throwFromIOE(ioe); - } - } - - /** - * Method called to close an open start element, when another - * main-level element (not namespace declaration or - * attribute) is being output; except for end element which is - * handled differently. - */ - protected void closeStartElement(boolean emptyElem) - throws XMLStreamException - { - mStartElementOpen = false; - if (mAttrNames != null) { - mAttrNames.clear(); - } - - try { - if (emptyElem) { - mWriter.writeStartTagEmptyEnd(); - } else { - mWriter.writeStartTagEnd(); - } - } catch (IOException ioe) { - throwFromIOE(ioe); - } - - if (mValidator != null) { - mVldContent = mValidator.validateElementAndAttributes(); - } - - // Need bit more special handling for empty elements... - if (emptyElem) { - String localName = mElements.removeLast(); - if (mElements.isEmpty()) { - mState = STATE_EPILOG; - } - if (mValidator != null) { - mVldContent = mValidator.validateElementEnd(localName, XmlConsts.ELEM_NO_NS_URI, XmlConsts.ELEM_NO_PREFIX); - } - } - } - - /** - * Element copier method implementation suitable to be used with - * non-namespace-aware writers. The only special thing here is that - * the copier can convert namespace declarations to equivalent - * attribute writes. - */ - public void copyStartElement(InputElementStack elemStack, - AttributeCollector attrCollector) - throws IOException, XMLStreamException - { - String ln = elemStack.getLocalName(); - boolean nsAware = elemStack.isNamespaceAware(); - - /* First, since we are not to output namespace stuff as is, - * we just need to copy the element: - */ - if (nsAware) { // but reader is ns-aware? Need to add prefix? - String prefix = elemStack.getPrefix(); - if (prefix != null && prefix.length() > 0) { // yup - ln = prefix + ":" + ln; - } - } - writeStartElement(ln); - - /* However, if there are any namespace declarations, we probably - * better output them just as 'normal' attributes: - */ - if (nsAware) { - int nsCount = elemStack.getCurrentNsCount(); - if (nsCount > 0) { - for (int i = 0; i < nsCount; ++i) { - String prefix = elemStack.getLocalNsPrefix(i); - if (prefix == null || prefix.length() == 0) { // default NS decl - prefix = XMLConstants.XML_NS_PREFIX; - } else { - prefix = "xmlns:"+prefix; - } - writeAttribute(prefix, elemStack.getLocalNsURI(i)); - } - } - } - - /* And then let's just output attributes, if any (whether to copy - * implicit, aka "default" attributes, is configurable) - */ - int attrCount = mCfgCopyDefaultAttrs ? - attrCollector.getCount() : - attrCollector.getSpecifiedCount(); - - if (attrCount > 0) { - for (int i = 0; i < attrCount; ++i) { - attrCollector.writeAttribute(i, mWriter); - } - } - } - - protected String getTopElementDesc() - { - return mElements.isEmpty() ? "#root" : mElements.getLastString(); - } - - public String validateQNamePrefix(QName name) - { - // Can either strip prefix out, or return as is - return name.getPrefix(); - } - - /* - //////////////////////////////////////////////////// - // Internal methods - //////////////////////////////////////////////////// - */ - - private void doWriteStartElement(String localName) - throws XMLStreamException - { - mAnyOutput = true; - // Need to finish an open start element? - if (mStartElementOpen) { - closeStartElement(mEmptyElement); - } else if (mState == STATE_PROLOG) { - // 20-Dec-2005, TSa: Does this match DOCTYPE declaration? - verifyRootElement(localName, null); - } else if (mState == STATE_EPILOG) { - if (mCheckStructure) { - reportNwfStructure(ErrorConsts.WERR_PROLOG_SECOND_ROOT, localName); - } - // Outputting fragment? Better reset to tree, then... - mState = STATE_TREE; - } - - /* Note: need not check for CONTENT_ALLOW_NONE here, since the - * validator should handle this particular case... - */ - /*if (mVldContent == XMLValidator.CONTENT_ALLOW_NONE) { // EMPTY content - reportInvalidContent(START_ELEMENT); - }*/ - if (mValidator != null) { - mValidator.validateElementStart(localName, XmlConsts.ELEM_NO_NS_URI, XmlConsts.ELEM_NO_PREFIX); - } - - mStartElementOpen = true; - mElements.addString(localName); - try { - mWriter.writeStartTagStart(localName); - } catch (IOException ioe) { - throwFromIOE(ioe); - } - } - - /** - *

- * Note: Caller has to do actual removal of the element from element - * stack, before calling this method. - * - * @param expName Name that the closing element should have; null - * if whatever is in stack should be used - * @param allowEmpty If true, is allowed to create the empty element - * if the closing element was truly empty; if false, has to write - * the full empty element no matter what - */ - private void doWriteEndTag(String expName, boolean allowEmpty) - throws XMLStreamException - { - /* First of all, do we need to close up an earlier empty element? - * (open start element that was not created via call to - * writeEmptyElement gets handled later on) - */ - if (mStartElementOpen && mEmptyElement) { - mEmptyElement = false; - // note: this method guarantees proper updates to validation - closeStartElement(true); - } - - // Better have something to close... (to figure out what to close) - if (mState != STATE_TREE) { - // Have to throw an exception always, don't know elem name - reportNwfStructure("No open start element, when trying to write end element"); - } - - /* Now, do we have an unfinished start element (created via - * writeStartElement() earlier)? - */ - String localName = mElements.removeLast(); - if (mCheckStructure) { - if (expName != null && !localName.equals(expName)) { - /* Only gets called when trying to output an XMLEvent... in - * which case names can actually be compared - */ - reportNwfStructure("Mismatching close element name, '"+localName+"'; expected '"+expName+"'."); - } - } - - /* Can't yet validate, since we have two paths; one for empty - * elements, another for non-empty... - */ - - // Got a half output start element to close? - if (mStartElementOpen) { - /* Can't/shouldn't call closeStartElement, but need to do same - * processing. Thus, this is almost identical to closeStartElement: - */ - if (mValidator != null) { - /* Note: return value is not of much use, since the - * element will be closed right away... - */ - mVldContent = mValidator.validateElementAndAttributes(); - } - mStartElementOpen = false; - if (mAttrNames != null) { - mAttrNames.clear(); - } - try { - // We could write an empty element, implicitly? - if (allowEmpty) { - mWriter.writeStartTagEmptyEnd(); - if (mElements.isEmpty()) { - mState = STATE_EPILOG; - } - if (mValidator != null) { - mVldContent = mValidator.validateElementEnd(localName, XmlConsts.ELEM_NO_NS_URI, XmlConsts.ELEM_NO_PREFIX); - } - return; - } - // Nah, need to close open elem, and then output close elem - mWriter.writeStartTagEnd(); - } catch (IOException ioe) { - throwFromIOE(ioe); - } - } - - try { - mWriter.writeEndTag(localName); - } catch (IOException ioe) { - throwFromIOE(ioe); - } - - if (mElements.isEmpty()) { - mState = STATE_EPILOG; - } - - // Ok, time to validate... - if (mValidator != null) { - mVldContent = mValidator.validateElementEnd(localName, XmlConsts.ELEM_NO_NS_URI, XmlConsts.ELEM_NO_PREFIX); - } - } -} diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/sw/OutputElementBase.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/sw/OutputElementBase.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/sw/OutputElementBase.java 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/sw/OutputElementBase.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,373 +0,0 @@ -/* Woodstox XML processor - * - * Copyright (c) 2005 Tatu Saloranta, tatu.saloranta@iki.fi - * - * Licensed under the License specified in file LICENSE, included with - * the source code. - * You may not use this file except in compliance with the License. - * - * 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 com.ctc.wstx.sw; - -import java.util.*; - -import javax.xml.XMLConstants; -import javax.xml.namespace.NamespaceContext; -import javax.xml.stream.XMLStreamException; - -import org.codehaus.stax2.ri.EmptyIterator; - -import com.ctc.wstx.util.BijectiveNsMap; - -/** - * Class that encapsulates information about a specific element in virtual - * output stack for namespace-aware writers. - * It provides support for URI-to-prefix mappings as well as namespace - * mapping generation. - *

- * One noteworthy feature of the class is that it is designed to allow - * "short-term recycling", ie. instances can be reused within context - * of a simple document output. While reuse/recycling of such lightweight - * object is often useless or even counter productive, here it may - * be worth using, due to simplicity of the scheme (basically using - * a very simple free-elements linked list). - */ -public abstract class OutputElementBase - implements NamespaceContext -{ - public final static int PREFIX_UNBOUND = 0; - public final static int PREFIX_OK = 1; - public final static int PREFIX_MISBOUND = 2; - - final static String sXmlNsPrefix = XMLConstants.XML_NS_PREFIX; - final static String sXmlNsURI = XMLConstants.XML_NS_URI; - - /* - //////////////////////////////////////////// - // Namespace binding/mapping information - //////////////////////////////////////////// - */ - - /** - * Namespace context end application may have supplied, and that - * (if given) should be used to augment explicitly defined bindings. - */ - protected NamespaceContext mRootNsContext; - - protected String mDefaultNsURI; - - /** - * Mapping of namespace prefixes to URIs and back. - */ - protected BijectiveNsMap mNsMapping; - - /** - * True, if {@link #mNsMapping} is a shared copy from the parent; - * false if a local copy was created (which happens when namespaces - * get bound etc). - */ - protected boolean mNsMapShared; - - /* - //////////////////////////////////////////// - // Life-cycle - //////////////////////////////////////////// - */ - - /** - * Constructor for the virtual root element - */ - protected OutputElementBase() - { - mNsMapping = null; - mNsMapShared = false; - mDefaultNsURI = ""; - mRootNsContext = null; - } - - protected OutputElementBase(OutputElementBase parent, BijectiveNsMap ns) - { - mNsMapping = ns; - mNsMapShared = (ns != null); - mDefaultNsURI = parent.mDefaultNsURI; - mRootNsContext = parent.mRootNsContext; - } - - /** - * Method called to reuse a pooled instance. - */ - protected void relink(OutputElementBase parent) - { - mNsMapping = parent.mNsMapping; - mNsMapShared = (mNsMapping != null); - mDefaultNsURI = parent.mDefaultNsURI; - mRootNsContext = parent.mRootNsContext; - } - - protected abstract void setRootNsContext(NamespaceContext ctxt); - - /* - //////////////////////////////////////////// - // Public API, accessors - //////////////////////////////////////////// - */ - - public abstract boolean isRoot(); - - /** - * @return String presentation of the fully-qualified name, in - * "prefix:localName" format (no URI). Useful for error and - * debugging messages. - */ - public abstract String getNameDesc(); - - public final String getDefaultNsUri() { - return mDefaultNsURI; - } - - /* - //////////////////////////////////////////// - // Public API, ns binding, checking - //////////////////////////////////////////// - */ - - /** - * Method similar to {@link #getPrefix}, but one that will not accept - * the default namespace, only an explicit one. Usually used when - * trying to find a prefix for attributes. - */ - public final String getExplicitPrefix(String uri) - { - if (mNsMapping != null) { - String prefix = mNsMapping.findPrefixByUri(uri); - if (prefix != null) { - return prefix; - } - } - if (mRootNsContext != null) { - String prefix = mRootNsContext.getPrefix(uri); - if (prefix != null) { - // Hmmh... still can't use the default NS: - if (prefix.length() > 0) { - return prefix; - } - // ... should we try to find an explicit one? - } - } - return null; - } - - /** - * Method that verifies that passed-in prefix indeed maps to the specified - * namespace URI; and depending on how it goes returns a status for - * caller. - * - * @param isElement If true, rules for the default NS are those of elements - * (ie. empty prefix can map to non-default namespace); if false, - * rules are those of attributes (only non-default prefix can map to - * a non-default namespace). - * - * @return PREFIX_OK, if passed-in prefix matches matched-in namespace URI - * in current scope; PREFIX_UNBOUND if it's not bound to anything, - * and PREFIX_MISBOUND if it's bound to another URI. - * - * @throws XMLStreamException True if default (no) prefix is allowed to - * match a non-default URI (elements); false if not (attributes) - */ - public final int isPrefixValid(String prefix, String nsURI, - boolean isElement) - throws XMLStreamException - { - // Hmmm.... caller shouldn't really pass null. - if (nsURI == null) { - nsURI = ""; - } - - /* First thing is to see if specified prefix is bound to a namespace; - * and if so, verify it matches with data passed in: - */ - - // Checking default namespace? - if (prefix == null || prefix.length() == 0) { - if (isElement) { - // It's fine for elements only if the URI actually matches: - if (nsURI == mDefaultNsURI || nsURI.equals(mDefaultNsURI)) { - return PREFIX_OK; - } - } else { - /* Attributes never use the default namespace: "no prefix" - * can only mean "no namespace" - */ - if (nsURI.length() == 0) { - return PREFIX_OK; - } - } - return PREFIX_MISBOUND; - } - - /* Need to handle 'xml' prefix and its associated - * URI; they are always declared by default - */ - if (prefix.equals(sXmlNsPrefix)) { - // Should we thoroughly verify its namespace matches...? - // 01-Apr-2005, TSa: Yes, let's always check this - if (!nsURI.equals(sXmlNsURI)) { - throwOutputError("Namespace prefix '"+sXmlNsPrefix - +"' can not be bound to non-default namespace ('"+nsURI+"'); has to be the default '" - +sXmlNsURI+"'"); - } - return PREFIX_OK; - } - - // Nope checking some other namespace - String act; - - if (mNsMapping != null) { - act = mNsMapping.findUriByPrefix(prefix); - } else { - act = null; - } - - if (act == null && mRootNsContext != null) { - act = mRootNsContext.getNamespaceURI(prefix); - } - - // Not (yet) bound... - if (act == null) { - return PREFIX_UNBOUND; - } - - return (act == nsURI || act.equals(nsURI)) ? - PREFIX_OK : PREFIX_MISBOUND; - } - - /* - //////////////////////////////////////////// - // Public API, mutators - //////////////////////////////////////////// - */ - - public abstract void setDefaultNsUri(String uri); - - public final String generateMapping(String prefixBase, String uri, int[] seqArr) - { - // This is mostly cut'n pasted from addPrefix()... - if (mNsMapping == null) { - // Didn't have a mapping yet? Need to create one... - mNsMapping = BijectiveNsMap.createEmpty(); - } else if (mNsMapShared) { - /* Was shared with parent(s)? Need to create a derivative, to - * allow for nesting/scoping of new prefix - */ - mNsMapping = mNsMapping.createChild(); - mNsMapShared = false; - } - return mNsMapping.addGeneratedMapping(prefixBase, mRootNsContext, - uri, seqArr); - } - - public final void addPrefix(String prefix, String uri) - { - if (mNsMapping == null) { - // Didn't have a mapping yet? Need to create one... - mNsMapping = BijectiveNsMap.createEmpty(); - } else if (mNsMapShared) { - /* Was shared with parent(s)? Need to create a derivative, to - * allow for nesting/scoping of new prefix - */ - mNsMapping = mNsMapping.createChild(); - mNsMapShared = false; - } - mNsMapping.addMapping(prefix, uri); - } - - /* - ////////////////////////////////////////////////// - // NamespaceContext implementation - ////////////////////////////////////////////////// - */ - - public final String getNamespaceURI(String prefix) - { - if (prefix.length() == 0) { //default NS - return mDefaultNsURI; - } - if (mNsMapping != null) { - String uri = mNsMapping.findUriByPrefix(prefix); - if (uri != null) { - return uri; - } - } - return (mRootNsContext != null) ? - mRootNsContext.getNamespaceURI(prefix) : null; - } - - public final String getPrefix(String uri) - { - if (mDefaultNsURI.equals(uri)) { - return ""; - } - if (mNsMapping != null) { - String prefix = mNsMapping.findPrefixByUri(uri); - if (prefix != null) { - return prefix; - } - } - return (mRootNsContext != null) ? - mRootNsContext.getPrefix(uri) : null; - } - - public final Iterator getPrefixes(String uri) - { - List l = null; - - if (mDefaultNsURI.equals(uri)) { - l = new ArrayList(); - l.add(""); - } - if (mNsMapping != null) { - l = mNsMapping.getPrefixesBoundToUri(uri, l); - } - // How about the root namespace context? (if any) - /* Note: it's quite difficult to properly resolve masking, when - * combining these things (not impossible, just tricky); for now - * let's do best effort without worrying about masking: - */ - if (mRootNsContext != null) { - Iterator it = mRootNsContext.getPrefixes(uri); - while (it.hasNext()) { - String prefix = (String) it.next(); - if (prefix.length() == 0) { // default NS already checked - continue; - } - // slow check... but what the heck - if (l == null) { - l = new ArrayList(); - } else if (l.contains(prefix)) { // double-defined... - continue; - } - l.add(prefix); - } - } - return (l == null) ? EmptyIterator.getInstance() : - l.iterator(); - } - - /* - //////////////////////////////////////////// - // Internal methods - //////////////////////////////////////////// - */ - - protected final void throwOutputError(String msg) - throws XMLStreamException - { - throw new XMLStreamException(msg); - } -} diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/sw/RepairingNsStreamWriter.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/sw/RepairingNsStreamWriter.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/sw/RepairingNsStreamWriter.java 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/sw/RepairingNsStreamWriter.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,646 +0,0 @@ -/* Woodstox XML processor - * - * Copyright (c) 2004- Tatu Saloranta, tatu.saloranta@iki.fi - * - * Licensed under the License specified in the file LICENSE, - * included with the source code. - * You may not use this file except in compliance with the License. - * - * Unless required by applicable law or agreed to in writing, softwar - * 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 com.ctc.wstx.sw; - -import java.io.IOException; -import java.util.HashMap; -import java.util.Iterator; -import java.util.Map; - -import javax.xml.namespace.QName; -import javax.xml.stream.XMLStreamWriter; -import javax.xml.stream.XMLStreamException; -import javax.xml.stream.events.Attribute; -import javax.xml.stream.events.StartElement; - -import org.codehaus.stax2.ri.typed.AsciiValueEncoder; - -import com.ctc.wstx.api.WriterConfig; -import com.ctc.wstx.cfg.ErrorConsts; -import com.ctc.wstx.sr.AttributeCollector; -import com.ctc.wstx.sr.InputElementStack; - -/** - * Namespace-aware implementation of {@link XMLStreamWriter}, that does - * namespace repairing, ie resolves possible conflicts between prefixes - * (add new bindings as necessary), as well as automatically creates - * namespace declarations as necessary. - */ -public final class RepairingNsStreamWriter - extends BaseNsStreamWriter -{ - /* - /////////////////////////////////////////////////////////// - // Configuration (options, features) - /////////////////////////////////////////////////////////// - */ - - // // // Additional specific config flags base class doesn't have - - protected final String mAutomaticNsPrefix; - - /* - /////////////////////////////////////////////////////////// - // Additional state - /////////////////////////////////////////////////////////// - */ - - /** - * Sequence number used for generating dynamic namespace prefixes. - * Array used as a wrapper to allow for easy sharing of the sequence - * number. - */ - protected int[] mAutoNsSeq = null; - - protected String mSuggestedDefNs = null; - - /** - * Map that contains URI-to-prefix entries that point out suggested - * prefixes for URIs. These are populated by calls to - * {@link #setPrefix}, and they are only used as hints for binding; - * if there are conflicts, repairing writer can just use some other - * prefix. - */ - protected HashMap mSuggestedPrefixes = null; - - /* - /////////////////////////////////////////////////////////// - // Life-cycle (ctors) - /////////////////////////////////////////////////////////// - */ - - public RepairingNsStreamWriter(XmlWriter xw, String enc, WriterConfig cfg) - { - super(xw, enc, cfg, true); - mAutomaticNsPrefix = cfg.getAutomaticNsPrefix(); - } - - /* - /////////////////////////////////////////////////////////// - // XMLStreamWriter API - /////////////////////////////////////////////////////////// - */ - - //public NamespaceContext getNamespaceContext() - //public void setNamespaceContext(NamespaceContext context) - //public String getPrefix(String uri) - //public void setPrefix(String prefix, String uri) - //public void setDefaultNamespace(String uri) - - //public void writeAttribute(String localName, String value) - - public void writeAttribute(String nsURI, String localName, String value) - throws XMLStreamException - { - // No need to set mAnyOutput, nor close the element - if (!mStartElementOpen) { - throwOutputError(ErrorConsts.WERR_ATTR_NO_ELEM); - } - doWriteAttr(localName, nsURI, - findOrCreateAttrPrefix(null, nsURI, mCurrElem), - value); - } - - public void writeAttribute(String prefix, String nsURI, - String localName, String value) - throws XMLStreamException - { - if (!mStartElementOpen) { - throwOutputError(ErrorConsts.WERR_ATTR_NO_ELEM); - } - - doWriteAttr(localName, nsURI, findOrCreateAttrPrefix(prefix, nsURI, mCurrElem), - value); - } - - public void writeDefaultNamespace(String nsURI) - throws XMLStreamException - { - /* 01-Sep-2006, TSa: The use case for calling this method is that - * of caller may wanting to 'suggest' that - * such a namespace should indeed be bound at this level. This - * may be necessary for canonicalization, or for minimizing number - * of binding declarations (all children need the ns, but root - * itself not). - */ - if (!mStartElementOpen) { - throwOutputError(ERR_NSDECL_WRONG_STATE); - } - /* ... We have one complication though: if the current element - * uses default namespace, can not change it (attributes don't - * matter -- they never use the default namespace, but either don't - * belong to a namespace, or belong to one using explicit prefix) - */ - String prefix = mCurrElem.getPrefix(); - if (prefix != null && prefix.length() > 0) { // ok, can change it - mCurrElem.setDefaultNsUri(nsURI); - doWriteDefaultNs(nsURI); - } - } - - //public void writeEmptyElement(String localName) throws XMLStreamException - - public void writeNamespace(String prefix, String nsURI) - throws XMLStreamException - { - /* (see discussion in 'writeDefaultNamespace()' for details on - * if and how this method may get called in repairing mode) - */ - if (prefix == null || prefix.length() == 0) { - writeDefaultNamespace(nsURI); - return; - } - if (!mStartElementOpen) { - throwOutputError(ERR_NSDECL_WRONG_STATE); - } - /* 01-Sep-2006, TSa: Let's only add the declaration if the prefix - * is as of yet unbound. If we have to re-bind things in future, - * so be it -- for now, this should suffice (and if we have to - * add re-binding, must verify that no attribute, nor element - * itself, is using overridden prefix) - */ - int value = mCurrElem.isPrefixValid(prefix, nsURI, true); - if (value == SimpleOutputElement.PREFIX_UNBOUND) { - mCurrElem.addPrefix(prefix, nsURI); - doWriteNamespace(prefix, nsURI); - } - } - - /* - /////////////////////////////////////////////////////////// - // Package methods: - /////////////////////////////////////////////////////////// - */ - - /** - * With repairing writer, this is only taken as a suggestion as to how - * the caller would prefer prefixes to be mapped. - */ - public void setDefaultNamespace(String uri) - throws XMLStreamException - { - mSuggestedDefNs = (uri == null || uri.length() == 0) ? null : uri; - } - - public void doSetPrefix(String prefix, String uri) - throws XMLStreamException - { - /* Ok; let's assume that passing in a null or empty String as - * the URI means that we don't want passed prefix to be preferred - * for any URI. - */ - if (uri == null || uri.length() == 0) { - if (mSuggestedPrefixes != null) { - for (Iterator it = mSuggestedPrefixes.entrySet().iterator(); - it.hasNext(); ) { - Map.Entry en = (Map.Entry) it.next(); - String thisP = (String) en.getValue(); - if (thisP.equals(prefix)) { - it.remove(); - } - } - } - } else { - if (mSuggestedPrefixes == null) { - mSuggestedPrefixes = new HashMap(16); - } - mSuggestedPrefixes.put(uri, prefix); - } - } - - public void writeStartElement(StartElement elem) - throws XMLStreamException - { - /* In repairing mode this is simple: let's just pass info - * we have, and things should work... a-may-zing! - */ - QName name = elem.getName(); - writeStartElement(name.getPrefix(), name.getLocalPart(), - name.getNamespaceURI()); - Iterator it = elem.getAttributes(); - while (it.hasNext()) { - Attribute attr = (Attribute) it.next(); - name = attr.getName(); - writeAttribute(name.getPrefix(), name.getNamespaceURI(), - name.getLocalPart(), attr.getValue()); - } - } - - //public void writeEndElement(QName name) throws XMLStreamException - - protected void writeTypedAttribute(String prefix, String nsURI, String localName, - AsciiValueEncoder enc) - throws XMLStreamException - { - super.writeTypedAttribute(findOrCreateAttrPrefix(prefix, nsURI, mCurrElem), - nsURI, localName, enc); - } - - protected void writeStartOrEmpty(String localName, String nsURI) - throws XMLStreamException - { - checkStartElement(localName, ""); - - // First, need to find prefix matching URI, if any: - String prefix = findElemPrefix(nsURI, mCurrElem); - /* Then need to create the element, since it'll have to - * contain the new namespace binding, if one needed - * (changed to resolve [WSTX-135] as reported by Y-J Choi, - * who also proposed the solution) - */ - if (mOutputElemPool != null) { - SimpleOutputElement newCurr = mOutputElemPool; - mOutputElemPool = newCurr.reuseAsChild(mCurrElem, prefix, localName, nsURI); - --mPoolSize; - mCurrElem = newCurr; - } else { - mCurrElem = mCurrElem.createChild(prefix, localName, nsURI); - } - - if (prefix != null) { // prefix ok, easy, no need to overwrite - if (mValidator != null) { - mValidator.validateElementStart(localName, nsURI, prefix); - } - doWriteStartTag(prefix, localName); - } else { // no prefix, more work - prefix = generateElemPrefix(null, nsURI, mCurrElem); - if (mValidator != null) { - mValidator.validateElementStart(localName, nsURI, prefix); - } - mCurrElem.setPrefix(prefix); - doWriteStartTag(prefix, localName); - if (prefix == null || prefix.length() == 0) { // def NS - mCurrElem.setDefaultNsUri(nsURI); - doWriteDefaultNs(nsURI); - } else { // explicit NS - mCurrElem.addPrefix(prefix, nsURI); - doWriteNamespace(prefix, nsURI); - } - } - } - - protected void writeStartOrEmpty(String suggPrefix, String localName, String nsURI) - throws XMLStreamException - { - checkStartElement(localName, suggPrefix); - - // In repairing mode, better ensure validity: - String actPrefix = validateElemPrefix(suggPrefix, nsURI, mCurrElem); - if (actPrefix != null) { // fine, an existing binding we can use: - if (mValidator != null) { - mValidator.validateElementStart(localName, nsURI, actPrefix); - } - if (mOutputElemPool != null) { - SimpleOutputElement newCurr = mOutputElemPool; - mOutputElemPool = newCurr.reuseAsChild(mCurrElem, actPrefix, localName, nsURI); - --mPoolSize; - mCurrElem = newCurr; - } else { - mCurrElem = mCurrElem.createChild(actPrefix, localName, nsURI); - } - doWriteStartTag(actPrefix, localName); - } else { // nah, need to create a new binding... - /* Need to ensure that we'll pass "" as prefix, not null, so - * that it is understood as "I want to use the default NS", not - * as "whatever prefix, I don't care" - */ - if (suggPrefix == null) { - suggPrefix = ""; - } - actPrefix = generateElemPrefix(suggPrefix, nsURI, mCurrElem); - if (mValidator != null) { - mValidator.validateElementStart(localName, nsURI, actPrefix); - } - if (mOutputElemPool != null) { - SimpleOutputElement newCurr = mOutputElemPool; - mOutputElemPool = newCurr.reuseAsChild(mCurrElem, actPrefix, localName, nsURI); - --mPoolSize; - mCurrElem = newCurr; - } else { - mCurrElem = mCurrElem.createChild(actPrefix, localName, nsURI); - } - mCurrElem.setPrefix(actPrefix); - doWriteStartTag(actPrefix, localName); - if (actPrefix == null || actPrefix.length() == 0) { // def NS - mCurrElem.setDefaultNsUri(nsURI); - doWriteDefaultNs(nsURI); - } else { // explicit NS - mCurrElem.addPrefix(actPrefix, nsURI); - doWriteNamespace(actPrefix, nsURI); - } - } - } - - /** - * Element copier method implementation suitable for use with - * namespace-aware writers in repairing mode. - * The trickiest thing is having to properly - * order calls to setPrefix, writeNamespace - * and writeStartElement; the order writers expect is - * bit different from the order in which element information is - * passed in. - */ - public final void copyStartElement(InputElementStack elemStack, AttributeCollector ac) - throws IOException, XMLStreamException - { - /* In case of repairing stream writer, we can actually just - * go ahead and first output the element: stream writer should - * be able to resolve namespace mapping for the element - * automatically, as necessary. - */ - String prefix = elemStack.getPrefix(); - String uri = elemStack.getNsURI(); - writeStartElement(prefix, elemStack.getLocalName(), uri); - - /* 04-Sep-2006, TSa: Although we could really just ignore all - * namespace declarations, some apps prefer (or even expect...) - * that ns bindings are preserved as much as possible. So, let's - * just try to output them as they are (could optimize and skip - * ones related to the start element [same prefix or URI], but - * for now let's not bother) - */ - int nsCount = elemStack.getCurrentNsCount(); - if (nsCount > 0) { // yup, got some... - for (int i = 0; i < nsCount; ++i) { - writeNamespace(elemStack.getLocalNsPrefix(i), elemStack.getLocalNsURI(i)); - } - } - - /* And then let's just output attributes, if any (whether to copy - * implicit, aka "default" attributes, is configurable) - */ - int attrCount = mCfgCopyDefaultAttrs ? ac.getCount() : ac.getSpecifiedCount(); - - /* Unlike in non-ns and simple-ns modes, we can not simply literally - * copy the attributes here. It is possible that some namespace - * prefixes have been remapped... so need to be bit more careful. - */ - if (attrCount > 0) { - for (int i = 0; i < attrCount; ++i) { - // First; need to make sure that the prefix-to-ns mapping - // attribute has is valid... and can not output anything - // before that's done (since remapping will output a namespace - // declaration!) - uri = ac.getURI(i); - prefix = ac.getPrefix(i); - - // With attributes, missing/empty prefix always means 'no - // namespace', can take a shortcut: - if (prefix == null || prefix.length() == 0) { - ; - } else { - // and otherwise we'll always have a prefix as attributes - // can not make use of the def. namespace... - prefix = findOrCreateAttrPrefix(prefix, uri, mCurrElem); - } - /* Hmmh. Since the prefix we use may be different from what - * collector has, we can not use pass-through method of - * the collector, but need to call XmlWriter directly: - */ - if (prefix == null || prefix.length() == 0) { - mWriter.writeAttribute(ac.getLocalName(i), ac.getValue(i)); - } else { - mWriter.writeAttribute(prefix, ac.getLocalName(i), ac.getValue(i)); - } - } - } - } - - public String validateQNamePrefix(QName name) - throws XMLStreamException - { - /* Gets bit more complicated: we need to ensure that given URI - * is properly bound... - */ - String uri = name.getNamespaceURI(); - String suggPrefix = name.getPrefix(); - String actPrefix = validateElemPrefix(suggPrefix, uri, mCurrElem); - if (actPrefix == null) { // no suitable prefix, must bind - /* Need to ensure that we'll pass "" as prefix, not null, so - * that it is understood as "I want to use the default NS", not - * as "whatever prefix, I don't care" - */ - if (suggPrefix == null) { - suggPrefix = ""; - } - actPrefix = generateElemPrefix(suggPrefix, uri, mCurrElem); - if (actPrefix == null || actPrefix.length() == 0) { // def NS - writeDefaultNamespace(uri); - } else { - writeNamespace(actPrefix, uri); - } - } - return actPrefix; - } - - /* - /////////////////////////////////////////////////////////// - // Internal methods - /////////////////////////////////////////////////////////// - */ - - /** - * Method called to find an existing prefix for the given namespace, - * if any exists in the scope. If one is found, it's returned (including - * "" for the current default namespace); if not, null is returned. - * - * @param nsURI URI of namespace for which we need a prefix - */ - protected final String findElemPrefix(String nsURI, SimpleOutputElement elem) - throws XMLStreamException - { - /* Special case: empty NS URI can only be bound to the empty - * prefix... - */ - if (nsURI == null || nsURI.length() == 0) { - String currDefNsURI = elem.getDefaultNsUri(); - if (currDefNsURI != null && currDefNsURI.length() > 0) { - // Nope; won't do... has to be re-bound, but not here: - return null; - } - return ""; - } - return mCurrElem.getPrefix(nsURI); - } - - /** - * Method called after {@link #findElemPrefix} has returned null, - * to create and bind a namespace mapping for specified namespace. - */ - protected final String generateElemPrefix(String suggPrefix, String nsURI, - SimpleOutputElement elem) - throws XMLStreamException - { - /* Ok... now, since we do not have an existing mapping, let's - * see if we have a preferred prefix to use. - */ - /* Except if we need the empty namespace... that can only be - * bound to the empty prefix: - */ - if (nsURI == null || nsURI.length() == 0) { - return ""; - } - - /* Ok; with elements this is easy: the preferred prefix can - * ALWAYS be used, since it can mask preceding bindings: - */ - if (suggPrefix == null) { - // caller wants this URI to map as the default namespace? - if (mSuggestedDefNs != null && mSuggestedDefNs.equals(nsURI)) { - suggPrefix = ""; - } else { - suggPrefix = (mSuggestedPrefixes == null) ? null: - (String) mSuggestedPrefixes.get(nsURI); - if (suggPrefix == null) { - /* 16-Oct-2005, TSa: We have 2 choices here, essentially; - * could make elements always try to override the def - * ns... or can just generate new one. Let's do latter - * for now. - */ - if (mAutoNsSeq == null) { - mAutoNsSeq = new int[1]; - mAutoNsSeq[0] = 1; - } - suggPrefix = elem.generateMapping(mAutomaticNsPrefix, nsURI, - mAutoNsSeq); - } - } - } - - // Ok; let's let the caller deal with bindings - return suggPrefix; - } - - /** - * Method called to somehow find a prefix for given namespace, to be - * used for a new start element; either use an existing one, or - * generate a new one. If a new mapping needs to be generated, - * it will also be automatically bound, and necessary namespace - * declaration output. - * - * @param suggPrefix Suggested prefix to bind, if any; may be null - * to indicate "no preference" - * @param nsURI URI of namespace for which we need a prefix - * @param elem Currently open start element, on which the attribute - * will be added. - */ - protected final String findOrCreateAttrPrefix(String suggPrefix, String nsURI, - SimpleOutputElement elem) - throws XMLStreamException - { - if (nsURI == null || nsURI.length() == 0) { - /* Attributes never use the default namespace; missing - * prefix always leads to the empty ns... so nothing - * special is needed here. - */ - return null; - } - // Maybe the suggested prefix is properly bound? - if (suggPrefix != null) { - int status = elem.isPrefixValid(suggPrefix, nsURI, false); - if (status == SimpleOutputElement.PREFIX_OK) { - return suggPrefix; - } - /* Otherwise, if the prefix is unbound, let's just bind - * it -- if caller specified a prefix, it probably prefers - * binding that prefix even if another prefix already existed? - * The remaining case (already bound to another URI) we don't - * want to touch, at least not yet: it may or not be safe - * to change binding, so let's just not try it. - */ - if (status == SimpleOutputElement.PREFIX_UNBOUND) { - elem.addPrefix(suggPrefix, nsURI); - doWriteNamespace(suggPrefix, nsURI); - return suggPrefix; - } - } - - // If not, perhaps there's another existing binding available? - String prefix = elem.getExplicitPrefix(nsURI); - if (prefix != null) { // already had a mapping for the URI... cool. - return prefix; - } - - /* Nope, need to create one. First, let's see if there's a - * preference... - */ - if (suggPrefix != null) { - prefix = suggPrefix; - } else if (mSuggestedPrefixes != null) { - prefix = (String) mSuggestedPrefixes.get(nsURI); - // note: def ns is never added to suggested prefix map - } - - if (prefix != null) { - /* Can not use default namespace for attributes. - * Also, re-binding is tricky for attributes; can't - * re-bind anything that's bound on this scope... or - * used in this scope. So, to simplify life, let's not - * re-bind anything for attributes. - */ - if (prefix.length() == 0 - || (elem.getNamespaceURI(prefix) != null)) { - prefix = null; - } - } - - if (prefix == null) { - if (mAutoNsSeq == null) { - mAutoNsSeq = new int[1]; - mAutoNsSeq[0] = 1; - } - prefix = mCurrElem.generateMapping(mAutomaticNsPrefix, nsURI, - mAutoNsSeq); - } - - // Ok; so far so good: let's now bind and output the namespace: - elem.addPrefix(prefix, nsURI); - doWriteNamespace(prefix, nsURI); - return prefix; - } - - private final String validateElemPrefix(String prefix, String nsURI, - SimpleOutputElement elem) - throws XMLStreamException - { - /* 06-Feb-2005, TSa: Special care needs to be taken for the - * "empty" (or missing) namespace: - * (see comments from findOrCreatePrefix()) - */ - if (nsURI == null || nsURI.length() == 0) { - String currURL = elem.getDefaultNsUri(); - if (currURL == null || currURL.length() == 0) { - // Ok, good: - return ""; - } - // Nope, needs to be re-bound: - return null; - } - - int status = elem.isPrefixValid(prefix, nsURI, true); - if (status == SimpleOutputElement.PREFIX_OK) { - return prefix; - } - - /* Hmmh... now here's bit of dilemma: that particular prefix is - * either not bound, or is masked... but it is possible some other - * prefix would be bound. Should we search for another one, or - * try to re-define suggested one? Let's do latter, for now; - * caller can then (try to) bind the preferred prefix: - */ - return null; - } -} diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/sw/SimpleNsStreamWriter.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/sw/SimpleNsStreamWriter.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/sw/SimpleNsStreamWriter.java 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/sw/SimpleNsStreamWriter.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,336 +0,0 @@ -/* Woodstox XML processor - * - * Copyright (c) 2004- Tatu Saloranta, tatu.saloranta@iki.fi - * - * Licensed under the License specified in the file LICENSE, - * included with the source code. - * You may not use this file except in compliance with the License. - * - * 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 com.ctc.wstx.sw; - -import java.io.IOException; -import java.util.Iterator; - -import javax.xml.XMLConstants; -import javax.xml.namespace.QName; -import javax.xml.stream.XMLStreamWriter; -import javax.xml.stream.XMLStreamException; -import javax.xml.stream.events.Attribute; -import javax.xml.stream.events.Namespace; -import javax.xml.stream.events.StartElement; - -import com.ctc.wstx.api.WriterConfig; -import com.ctc.wstx.cfg.ErrorConsts; -import com.ctc.wstx.sr.AttributeCollector; -import com.ctc.wstx.sr.InputElementStack; - -/** - * Namespace-aware implementation of {@link XMLStreamWriter}, that does - * not do namespace repairing, ie doesn't try to resolve possible - * conflicts between prefixes and namespace URIs, or automatically - * create namespace bindings. - */ -public class SimpleNsStreamWriter - extends BaseNsStreamWriter -{ - /* - //////////////////////////////////////////////////// - // Life-cycle (ctors) - //////////////////////////////////////////////////// - */ - - public SimpleNsStreamWriter(XmlWriter xw, String enc, WriterConfig cfg) - { - super(xw, enc, cfg, false); - } - - /* - //////////////////////////////////////////////////// - // XMLStreamWriter API - //////////////////////////////////////////////////// - */ - - //public NamespaceContext getNamespaceContext() - //public void setNamespaceContext(NamespaceContext context) - //public String getPrefix(String uri) - //public void setPrefix(String prefix, String uri) - - //public void writeAttribute(String localName, String value) - - public void writeAttribute(String nsURI, String localName, String value) - throws XMLStreamException - { - // No need to set mAnyOutput, nor close the element - if (!mStartElementOpen) { - throwOutputError(ErrorConsts.WERR_ATTR_NO_ELEM); - } - String prefix = mCurrElem.getExplicitPrefix(nsURI); - if (!mReturnNullForDefaultNamespace && prefix == null) { - throwOutputError("Unbound namespace URI '" + nsURI + "'"); - } - doWriteAttr(localName, nsURI, prefix, value); - } - - public void writeAttribute(String prefix, String nsURI, - String localName, String value) - throws XMLStreamException - { - if (!mStartElementOpen) { - throwOutputError(ErrorConsts.WERR_ATTR_NO_ELEM); - } - doWriteAttr(localName, nsURI, prefix, value); - } - - //public void writeEmptyElement(String localName) throws XMLStreamException - //public void writeEmptyElement(String nsURI, String localName) throws XMLStreamException - //public void writeEmptyElement(String prefix, String localName, String nsURI) throws XMLStreamException - - //public void writeEndElement() throws XMLStreamException - - public void writeDefaultNamespace(String nsURI) - throws XMLStreamException - { - if (!mStartElementOpen) { - throwOutputError(ERR_NSDECL_WRONG_STATE); - } - // 27-Mar-2007, TSa: Apparently TCK expects a binding to be added - setDefaultNamespace(nsURI); - doWriteDefaultNs(nsURI); - } - - public void writeNamespace(String prefix, String nsURI) - throws XMLStreamException - { - if (prefix == null || prefix.length() == 0 - || prefix.equals(XMLConstants.XMLNS_ATTRIBUTE)) { - writeDefaultNamespace(nsURI); - return; - } - - // No need to set mAnyOutput, and shouldn't close the element. - // But element needs to be open, obviously. - if (!mStartElementOpen) { - throwOutputError(ERR_NSDECL_WRONG_STATE); - } - /* 05-Feb-2005, TSa: Also, as per namespace specs; the 'empty' - * namespace URI can not be bound as a non-default namespace - * (ie. for any actual prefix) - */ - /* 04-Feb-2005, TSa: Namespaces 1.1 does allow this, though, - * so for xml 1.1 documents we need to allow it - */ - if (!mXml11) { - if (nsURI.length() == 0) { - throwOutputError(ErrorConsts.ERR_NS_EMPTY); - } - // 01-Apr-2005, TSa: Can we (and do we want to) verify NS consistency? - } - // 27-Mar-2007, TSa: Apparently TCK expects a binding to be added - setPrefix(prefix, nsURI); - doWriteNamespace(prefix, nsURI); - } - - /* - //////////////////////////////////////////////////// - // Package methods: - //////////////////////////////////////////////////// - */ - - public void setDefaultNamespace(String uri) - throws XMLStreamException - { - mCurrElem.setDefaultNsUri(uri); - } - - public void doSetPrefix(String prefix, String uri) - throws XMLStreamException - { - mCurrElem.addPrefix(prefix, uri); - } - - public void writeStartElement(StartElement elem) - throws XMLStreamException - { - QName name = elem.getName(); - Iterator it = elem.getNamespaces(); - - while (it.hasNext()) { - Namespace ns = (Namespace) it.next(); - // First need to 'declare' namespace: - String prefix = ns.getPrefix(); - if (prefix == null || prefix.length() == 0) { - setDefaultNamespace(ns.getNamespaceURI()); - } else { - setPrefix(prefix, ns.getNamespaceURI()); - } - } - - /* Outputting element itself is fairly easy. The main question - * is whether namespaces match. Let's use simple heuristics: - * if writer is to do automatic prefix matching, let's only - * pass explicit prefix (not default one); otherwise we'll - * pass all parameters as is. - */ - /* Quick check first though: if URI part of QName is null, it's - * assumed element will just use whatever is current default - * namespace.... - */ - String nsURI = name.getNamespaceURI(); - if (nsURI == null) { - writeStartElement(name.getLocalPart()); - } else { - String prefix = name.getPrefix(); - writeStartElement(prefix, name.getLocalPart(), nsURI); - } - - // And now we need to output namespaces (including default), if any: - it = elem.getNamespaces(); - while (it.hasNext()) { - Namespace ns = (Namespace) it.next(); - String prefix = ns.getPrefix(); - if (prefix == null || prefix.length() == 0) { - writeDefaultNamespace(ns.getNamespaceURI()); - } else { - writeNamespace(prefix, ns.getNamespaceURI()); - } - } - - - // And finally, need to output attributes as well: - - it = elem.getAttributes(); - while (it.hasNext()) { - Attribute attr = (Attribute) it.next(); - name = attr.getName(); - nsURI = name.getNamespaceURI(); - // In non-default/empty namespace? - if (nsURI != null && nsURI.length() > 0) { - writeAttribute(name.getPrefix(), nsURI, - name.getLocalPart(), attr.getValue()); - } else { - writeAttribute(name.getLocalPart(), attr.getValue()); - } - } - } - - //public void writeEndElement(QName name) throws XMLStreamException - - protected void writeStartOrEmpty(String localName, String nsURI) - throws XMLStreamException - { - // Need a prefix... - String prefix = mCurrElem.getPrefix(nsURI); - if (prefix == null) { - throw new XMLStreamException("Unbound namespace URI '"+nsURI+"'"); - } - checkStartElement(localName, prefix); - if (mValidator != null) { - mValidator.validateElementStart(localName, nsURI, prefix); - } - - if (mOutputElemPool != null) { - SimpleOutputElement newCurr = mOutputElemPool; - mOutputElemPool = newCurr.reuseAsChild(mCurrElem, prefix, localName, nsURI); - --mPoolSize; - mCurrElem = newCurr; - } else { - mCurrElem = mCurrElem.createChild(prefix, localName, nsURI); - } - doWriteStartTag(prefix, localName); - } - - protected void writeStartOrEmpty(String prefix, String localName, String nsURI) - throws XMLStreamException - { - checkStartElement(localName, prefix); - if (mValidator != null) { - mValidator.validateElementStart(localName, nsURI, prefix); - } - - if (mOutputElemPool != null) { - SimpleOutputElement newCurr = mOutputElemPool; - mOutputElemPool = newCurr.reuseAsChild(mCurrElem, prefix, localName, nsURI); - --mPoolSize; - mCurrElem = newCurr; - } else { - mCurrElem = mCurrElem.createChild(prefix, localName, nsURI); - } - doWriteStartTag(prefix, localName); - } - - /** - * Element copier method implementation suitable to be used with - * namespace-aware writers in non-repairing (explicit namespaces) mode. - * The trickiest thing is having to properly - * order calls to setPrefix, writeNamespace - * and writeStartElement; the order writers expect is - * bit different from the order in which element information is - * passed in. - */ - public final void copyStartElement(InputElementStack elemStack, - AttributeCollector attrCollector) - throws IOException, XMLStreamException - { - // Any namespace declarations/bindings? - int nsCount = elemStack.getCurrentNsCount(); - if (nsCount > 0) { // yup, got some... - /* First, need to (or at least, should?) add prefix bindings: - * (may not be 100% required, but probably a good thing to do, - * just so that app code has access to prefixes then) - */ - for (int i = 0; i < nsCount; ++i) { - String prefix = elemStack.getLocalNsPrefix(i); - String uri = elemStack.getLocalNsURI(i); - if (prefix == null || prefix.length() == 0) { // default NS - setDefaultNamespace(uri); - } else { - setPrefix(prefix, uri); - } - } - } - - writeStartElement(elemStack.getPrefix(), - elemStack.getLocalName(), - elemStack.getNsURI()); - - if (nsCount > 0) { - // And then output actual namespace declarations: - for (int i = 0; i < nsCount; ++i) { - String prefix = elemStack.getLocalNsPrefix(i); - String uri = elemStack.getLocalNsURI(i); - - if (prefix == null || prefix.length() == 0) { // default NS - writeDefaultNamespace(uri); - } else { - writeNamespace(prefix, uri); - } - } - } - - /* And then let's just output attributes, if any (whether to copy - * implicit, aka "default" attributes, is configurable) - */ - int attrCount = mCfgCopyDefaultAttrs ? - attrCollector.getCount() : - attrCollector.getSpecifiedCount(); - - if (attrCount > 0) { - for (int i = 0; i < attrCount; ++i) { - attrCollector.writeAttribute(i, mWriter); - } - } - } - - public String validateQNamePrefix(QName name) - { - // Good as is, let's not complicate things - return name.getPrefix(); - } -} diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/sw/SimpleOutputElement.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/sw/SimpleOutputElement.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/sw/SimpleOutputElement.java 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/sw/SimpleOutputElement.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,367 +0,0 @@ -/* Woodstox XML processor - * - * Copyright (c) 2005 Tatu Saloranta, tatu.saloranta@iki.fi - * - * Licensed under the License specified in file LICENSE, included with - * the source code. - * You may not use this file except in compliance with the License. - * - * 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 com.ctc.wstx.sw; - -import java.util.*; - -import javax.xml.namespace.NamespaceContext; -import javax.xml.namespace.QName; -import javax.xml.stream.XMLStreamException; - -import com.ctc.wstx.compat.QNameCreator; -import com.ctc.wstx.util.BijectiveNsMap; - -/** - * Class that encapsulates information about a specific element in virtual - * output stack for namespace-aware writers. - * It provides support for URI-to-prefix mappings as well as namespace - * mapping generation. - *

- * One noteworthy feature of the class is that it is designed to allow - * "short-term recycling", ie. instances can be reused within context - * of a simple document output. While reuse/recycling of such lightweight - * object is often useless or even counter productive, here it may - * be worth using, due to simplicity of the scheme (basically using - * a very simple free-elements linked list). - */ -public final class SimpleOutputElement - extends OutputElementBase -{ - /* - //////////////////////////////////////////// - // Information about element itself: - //////////////////////////////////////////// - */ - - /** - * Reference to the parent element, element enclosing this element. - * Null for root element. - * Non-final only to allow temporary pooling - * (on per-writer basis, to keep these short-lived). - */ - SimpleOutputElement mParent; - - /** - * Prefix that is used for the element. Can not be final, since sometimes - * it needs to be dynamically generated and bound after creating the - * element instance. - */ - String mPrefix; - - /** - * Local name of the element. - * Non-final only to allow reuse. - */ - String mLocalName; - - /** - * Namespace of the element, whatever {@link #mPrefix} maps to. - * Non-final only to allow reuse. - */ - String mURI; - - /* - //////////////////////////////////////////// - // Attribute information - //////////////////////////////////////////// - */ - - /** - * Map used to check for duplicate attribute declarations, if - * feature is enabled. - */ - protected HashSet mAttrSet = null; - - /* - //////////////////////////////////////////// - // Life-cycle - //////////////////////////////////////////// - */ - - /** - * Constructor for the virtual root element - */ - private SimpleOutputElement() - { - super(); - mParent = null; - mPrefix = null; - mLocalName = ""; - mURI = null; - } - - private SimpleOutputElement(SimpleOutputElement parent, - String prefix, String localName, String uri, - BijectiveNsMap ns) - { - super(parent, ns); - mParent = parent; - mPrefix = prefix; - mLocalName = localName; - mURI = uri; - } - - /** - * Method called to reuse a pooled instance. - * - * @return Chained pooled instance that should now be head of the - * reuse chain - */ - private void relink(SimpleOutputElement parent, - String prefix, String localName, String uri) - { - super.relink(parent); - mParent = parent; - mPrefix = prefix; - mLocalName = localName; - mURI = uri; - mNsMapping = parent.mNsMapping; - mNsMapShared = (mNsMapping != null); - mDefaultNsURI = parent.mDefaultNsURI; - mRootNsContext = parent.mRootNsContext; - } - - public static SimpleOutputElement createRoot() - { - return new SimpleOutputElement(); - } - - /** - * Simplest factory method, which gets called when a 1-argument - * element output method is called. It is, then, assumed to - * use the default namespce. - */ - protected SimpleOutputElement createChild(String localName) - { - /* At this point we can also discard attribute Map; it is assumed - * that when a child element has been opened, no more attributes - * can be output. - */ - mAttrSet = null; - return new SimpleOutputElement(this, null, localName, - mDefaultNsURI, mNsMapping); - } - - /** - * @return New head of the recycle pool - */ - protected SimpleOutputElement reuseAsChild(SimpleOutputElement parent, - String localName) - { - mAttrSet = null; - SimpleOutputElement poolHead = mParent; - relink(parent, null, localName, mDefaultNsURI); - return poolHead; - } - - protected SimpleOutputElement reuseAsChild(SimpleOutputElement parent, - String prefix, String localName, - String uri) - { - mAttrSet = null; - SimpleOutputElement poolHead = mParent; - relink(parent, prefix, localName, uri); - return poolHead; - } - - /** - * Full factory method, used for 'normal' namespace qualified output - * methods. - */ - protected SimpleOutputElement createChild(String prefix, String localName, - String uri) - { - /* At this point we can also discard attribute Map; it is assumed - * that when a child element has been opened, no more attributes - * can be output. - */ - mAttrSet = null; - return new SimpleOutputElement(this, prefix, localName, uri, mNsMapping); - } - - /** - * Method called to temporarily link this instance to a pool, to - * allow reusing of instances with the same reader. - */ - protected void addToPool(SimpleOutputElement poolHead) - { - mParent = poolHead; - } - - /* - //////////////////////////////////////////// - // Public API, accessors - //////////////////////////////////////////// - */ - - public SimpleOutputElement getParent() { - return mParent; - } - - public boolean isRoot() { - // (Virtual) Root element has no parent... - return (mParent == null); - } - - /** - * @return String presentation of the fully-qualified name, in - * "prefix:localName" format (no URI). Useful for error and - * debugging messages. - */ - public String getNameDesc() { - if (mPrefix != null && mPrefix.length() > 0) { - return mPrefix + ":" +mLocalName; - } - if (mLocalName != null && mLocalName.length() > 0) { - return mLocalName; - } - return "#error"; // unexpected case - } - - public String getPrefix() { - return mPrefix; - } - - public String getLocalName() { - return mLocalName; - } - - public String getNamespaceURI() { - return mURI; - } - - public QName getName() { - return QNameCreator.create(mURI, mLocalName, mPrefix); - } - - /* - //////////////////////////////////////////// - // Public API, ns binding, checking - //////////////////////////////////////////// - */ - - public void checkAttrWrite(String nsURI, String localName) - throws XMLStreamException - { - AttrName an = new AttrName(nsURI, localName); - if (mAttrSet == null) { - /* 13-Dec-2005, TSa: Should use a more efficient Set/Map value - * for this in future -- specifically one that could use - * ns/local-name pairs without intermediate objects - */ - mAttrSet = new HashSet(); - } - if (!mAttrSet.add(an)) { - throw new XMLStreamException("Duplicate attribute write for attribute '"+an+"'"); - } - } - - /* - //////////////////////////////////////////// - // Public API, mutators - //////////////////////////////////////////// - */ - - public void setPrefix(String prefix) { - mPrefix = prefix; - } - - public void setDefaultNsUri(String uri) { - mDefaultNsURI = uri; - } - - /** - * Note: this method can and will only be called before outputting - * the root element. - */ - protected final void setRootNsContext(NamespaceContext ctxt) - { - mRootNsContext = ctxt; - // Let's also figure out the default ns binding, if any: - String defURI = ctxt.getNamespaceURI(""); - if (defURI != null && defURI.length() > 0) { - mDefaultNsURI = defURI; - } - } - - /* - ////////////////////////////////////////////////// - // Helper classes: - ////////////////////////////////////////////////// - */ - - /** - * Simple key class used to represent two-piece (attribute) names; - * first part being optional (URI), and second non-optional (local name). - */ - final static class AttrName - implements Comparable - { - final String mNsURI; - final String mLocalName; - - /** - * Let's cache the hash code, since although hash calculation is - * fast, hash code is needed a lot as this is always used as a - * HashSet/TreeMap key. - */ - final int mHashCode; - - public AttrName(String nsURI, String localName) { - mNsURI = (nsURI == null) ? "" : nsURI; - mLocalName = localName; - mHashCode = mNsURI.hashCode() * 31 ^ mLocalName.hashCode(); - } - - public boolean equals(Object o) { - if (o == this) { - return true; - } - if (!(o instanceof AttrName)) { - return false; - } - AttrName other = (AttrName) o; - String otherLN = other.mLocalName; - // Local names are shorter, more varying: - if (otherLN != mLocalName && !otherLN.equals(mLocalName)) { - return false; - } - String otherURI = other.mNsURI; - return (otherURI == mNsURI || otherURI.equals(mNsURI)); - } - - public String toString() { - if (mNsURI.length() > 0) { - return "{"+mNsURI + "} " +mLocalName; - } - return mLocalName; - } - - public int hashCode() { - return mHashCode; - } - - public int compareTo(Object o) { - AttrName other = (AttrName) o; - // Let's first order by namespace: - int result = mNsURI.compareTo(other.mNsURI); - if (result == 0) { - result = mLocalName.compareTo(other.mLocalName); - } - return result; - } - } -} diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/sw/TypedStreamWriter.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/sw/TypedStreamWriter.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/sw/TypedStreamWriter.java 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/sw/TypedStreamWriter.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,330 +0,0 @@ -/* Woodstox XML processor - * - * Copyright (c) 2004- Tatu Saloranta, tatu.saloranta@iki.fi - * - * Licensed under the License specified in file LICENSE, included with - * the source code. - * You may not use this file except in compliance with the License. - * - * 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 com.ctc.wstx.sw; - -import java.io.IOException; -import java.math.BigDecimal; -import java.math.BigInteger; - -import javax.xml.namespace.QName; -import javax.xml.stream.XMLStreamException; - -import org.codehaus.stax2.typed.Base64Variant; -import org.codehaus.stax2.typed.Base64Variants; -import org.codehaus.stax2.ri.typed.AsciiValueEncoder; -import org.codehaus.stax2.ri.typed.ValueEncoderFactory; -import org.codehaus.stax2.validation.XMLValidator; - -import com.ctc.wstx.api.WriterConfig; -import com.ctc.wstx.cfg.ErrorConsts; -import com.ctc.wstx.exc.WstxIOException; - -/** - * Intermediate base class that implements Typed Access API (Stax2 v3) - * for all (repairing, non-repairing, non-namespace) native stream - * writer implementations. - */ -public abstract class TypedStreamWriter - extends BaseStreamWriter -{ - /** - * When outputting using Typed Access API, we will need - * encoders. If so, they will created by lazily-constructed - * factory - */ - protected ValueEncoderFactory mValueEncoderFactory; - - /* - //////////////////////////////////////////////////// - // Life-cycle - //////////////////////////////////////////////////// - */ - - protected TypedStreamWriter(XmlWriter xw, String enc, WriterConfig cfg) - { - super(xw, enc, cfg); - } - - protected final ValueEncoderFactory valueEncoderFactory() - { - if (mValueEncoderFactory == null) { - mValueEncoderFactory = new ValueEncoderFactory(); - } - return mValueEncoderFactory; - } - - /* - ///////////////////////////////////////////////// - // TypedXMLStreamWriter2 implementation - // (Typed Access API, Stax v3.0) - ///////////////////////////////////////////////// - */ - - // // // Typed element content write methods - - public void writeBoolean(boolean value) - throws XMLStreamException - { - writeTypedElement(valueEncoderFactory().getEncoder(value)); - } - - public void writeInt(int value) - throws XMLStreamException - { - writeTypedElement(valueEncoderFactory().getEncoder(value)); - } - - public void writeLong(long value) - throws XMLStreamException - { - writeTypedElement(valueEncoderFactory().getEncoder(value)); - } - - public void writeFloat(float value) - throws XMLStreamException - { - writeTypedElement(valueEncoderFactory().getEncoder(value)); - } - - public void writeDouble(double value) - throws XMLStreamException - { - writeTypedElement(valueEncoderFactory().getEncoder(value)); - - } - - public void writeInteger(BigInteger value) - throws XMLStreamException - { - /* No really efficient method exposed by JDK, keep it simple - * (esp. considering that length is actually not bound) - */ - writeTypedElement(valueEncoderFactory().getScalarEncoder(value.toString())); - } - - public void writeDecimal(BigDecimal value) - throws XMLStreamException - { - /* No really efficient method exposed by JDK, keep it simple - * (esp. considering that length is actually not bound) - */ - writeTypedElement(valueEncoderFactory().getScalarEncoder(value.toString())); - } - - public void writeQName(QName name) - throws XMLStreamException - { - /* Can't use AsciiValueEncoder, since QNames can contain - * non-ascii characters - */ - writeCharacters(serializeQName(name)); - } - - public final void writeIntArray(int[] value, int from, int length) - throws XMLStreamException - { - writeTypedElement(valueEncoderFactory().getEncoder(value, from, length)); - } - - public void writeLongArray(long[] value, int from, int length) - throws XMLStreamException - { - writeTypedElement(valueEncoderFactory().getEncoder(value, from, length)); - } - - public void writeFloatArray(float[] value, int from, int length) - throws XMLStreamException - { - writeTypedElement(valueEncoderFactory().getEncoder(value, from, length)); - } - - public void writeDoubleArray(double[] value, int from, int length) - throws XMLStreamException - { - writeTypedElement(valueEncoderFactory().getEncoder(value, from, length)); - } - - public void writeBinary(byte[] value, int from, int length) - throws XMLStreamException - { - Base64Variant v = Base64Variants.getDefaultVariant(); - writeTypedElement(valueEncoderFactory().getEncoder(v, value, from, length)); - } - - public void writeBinary(Base64Variant v, byte[] value, int from, int length) - throws XMLStreamException - { - writeTypedElement(valueEncoderFactory().getEncoder(v, value, from, length)); - } - - protected final void writeTypedElement(AsciiValueEncoder enc) - throws XMLStreamException - { - if (mStartElementOpen) { - closeStartElement(mEmptyElement); - } - // How about well-formedness? - if (mCheckStructure) { - if (inPrologOrEpilog()) { - reportNwfStructure(ErrorConsts.WERR_PROLOG_NONWS_TEXT); - } - } - // Or validity? - if (mVldContent <= XMLValidator.CONTENT_ALLOW_WS) { - reportInvalidContent(CHARACTERS); - } - - // So far so good: let's serialize - try { - XMLValidator vld = (mVldContent == XMLValidator.CONTENT_ALLOW_VALIDATABLE_TEXT) ? - mValidator : null; - if (vld == null) { - mWriter.writeTypedElement(enc); - } else { - mWriter.writeTypedElement(enc, vld, getCopyBuffer()); - } - } catch (IOException ioe) { - throw new WstxIOException(ioe); - } - } - - // // // Typed attribute value write methods - - public void writeBooleanAttribute(String prefix, String nsURI, String localName, boolean value) - throws XMLStreamException - { - writeTypedAttribute(prefix, nsURI, localName, - valueEncoderFactory().getEncoder(value)); - } - - public void writeIntAttribute(String prefix, String nsURI, String localName, int value) - throws XMLStreamException - { - writeTypedAttribute(prefix, nsURI, localName, - valueEncoderFactory().getEncoder(value)); - } - - public void writeLongAttribute(String prefix, String nsURI, String localName, long value) - throws XMLStreamException - { - writeTypedAttribute(prefix, nsURI, localName, - valueEncoderFactory().getEncoder(value)); - } - - public void writeFloatAttribute(String prefix, String nsURI, String localName, float value) - throws XMLStreamException - { - writeTypedAttribute(prefix, nsURI, localName, - valueEncoderFactory().getEncoder(value)); - } - - public void writeDoubleAttribute(String prefix, String nsURI, String localName, double value) - throws XMLStreamException - { - writeTypedAttribute(prefix, nsURI, localName, - valueEncoderFactory().getEncoder(value)); - } - - public void writeIntegerAttribute(String prefix, String nsURI, String localName, BigInteger value) - throws XMLStreamException - { - // not optimal, but has to do: - writeTypedAttribute(prefix, nsURI, localName, - valueEncoderFactory().getScalarEncoder(value.toString())); - } - - public void writeDecimalAttribute(String prefix, String nsURI, String localName, BigDecimal value) - throws XMLStreamException - { - // not optimal, but has to do: - writeTypedAttribute(prefix, nsURI, localName, - valueEncoderFactory().getScalarEncoder(value.toString())); - } - - public void writeQNameAttribute(String prefix, String nsURI, String localName, QName name) - throws XMLStreamException - { - /* Can't use AsciiValueEncoder, since QNames can contain - * non-ascii characters - */ - writeAttribute(prefix, nsURI, localName, serializeQName(name)); - } - - public void writeIntArrayAttribute(String prefix, String nsURI, String localName, int[] value) - throws XMLStreamException - { - writeTypedAttribute(prefix, nsURI, localName, - valueEncoderFactory().getEncoder(value, 0, value.length)); - } - - public void writeLongArrayAttribute(String prefix, String nsURI, String localName, long[] value) - throws XMLStreamException - { - writeTypedAttribute(prefix, nsURI, localName, - valueEncoderFactory().getEncoder(value, 0, value.length)); - } - - public void writeFloatArrayAttribute(String prefix, String nsURI, String localName, float[] value) - throws XMLStreamException - { - writeTypedAttribute(prefix, nsURI, localName, - valueEncoderFactory().getEncoder(value, 0, value.length)); - } - - public void writeDoubleArrayAttribute(String prefix, String nsURI, String localName, double[] value) - throws XMLStreamException - { - writeTypedAttribute(prefix, nsURI, localName, - valueEncoderFactory().getEncoder(value, 0, value.length)); - } - - public void writeBinaryAttribute(String prefix, String nsURI, String localName, byte[] value) - throws XMLStreamException - { - Base64Variant v = Base64Variants.getDefaultVariant(); - writeTypedAttribute(prefix, nsURI, localName, - valueEncoderFactory().getEncoder(v, value, 0, value.length)); - } - - public void writeBinaryAttribute(Base64Variant v, String prefix, String nsURI, String localName, byte[] value) - throws XMLStreamException - { - writeTypedAttribute(prefix, nsURI, localName, - valueEncoderFactory().getEncoder(v, value, 0, value.length)); - } - - /** - * Method that will write attribute with value that is known not to - * require additional escaping. - */ - protected abstract void writeTypedAttribute(String prefix, String nsURI, - String localName, - AsciiValueEncoder enc) - throws XMLStreamException; - - private String serializeQName(QName name) - throws XMLStreamException - { - String vp = validateQNamePrefix(name); - String local = name.getLocalPart(); - if (vp == null || vp.length() == 0) { - return local; - } - - // Not efficient... but should be ok - return vp + ":" + local; - } -} diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/sw/XmlWriter.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/sw/XmlWriter.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/sw/XmlWriter.java 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/sw/XmlWriter.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,625 +0,0 @@ -/* Woodstox XML processor - * - * Copyright (c) 2004- Tatu Saloranta, tatu.saloranta@iki.fi - * - * Licensed under the License specified in file LICENSE, included with - * the source code. - * You may not use this file except in compliance with the License. - * - * 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 com.ctc.wstx.sw; - -import java.io.IOException; -import java.io.OutputStream; -import java.io.Writer; -import java.text.MessageFormat; - -import javax.xml.stream.XMLStreamException; - -import org.codehaus.stax2.io.EscapingWriterFactory; -import org.codehaus.stax2.ri.typed.AsciiValueEncoder; -import org.codehaus.stax2.validation.XMLValidator; - -import com.ctc.wstx.api.InvalidCharHandler; -import com.ctc.wstx.api.WriterConfig; -import com.ctc.wstx.api.WstxOutputProperties; -import com.ctc.wstx.cfg.ErrorConsts; -import com.ctc.wstx.cfg.OutputConfigFlags; -import com.ctc.wstx.exc.WstxIOException; -import com.ctc.wstx.io.WstxInputData; - -/** - * This is the base class for actual physical xml outputters. These - * instances will only handle actual writing (possibly including - * encoding) of the serialized textual xml, and will in general - * not verify content being output. The exception are the - * character-by-character checks that are most efficiently done - * at encoding level (such as character escaping, and checks for - * illegal character combinations), which are handled at this - * level. - *

- * Note that implementations can have different operating modes: - * specifically, when dealing with illegal content (such as "--" - * in a comment, "?>" in processing instruction, or "]]>" within - * CDATA section), implementations can do one of 3 things: - *

    - *
  • Fix the problem, by splitting the section (which can be done - * for CDATA sections, and to some degree, comments) - *
  • - *
  • Stop outputting, and return an index to the illegal piece - * of data (if there is no easy way to fix the problem: for - * example, for processing instruction) - *
  • - *
  • Just output content even though it will not result in - * well-formed output. This should only be done if the calling - * application has specifically requested verifications to be - * disabled. - *
  • - *
- */ -public abstract class XmlWriter -{ - protected final static int SURR1_FIRST = 0xD800; - protected final static int SURR1_LAST = 0xDBFF; - protected final static int SURR2_FIRST = 0xDC00; - protected final static int SURR2_LAST = 0xDFFF; - - protected final static char DEFAULT_QUOTE_CHAR = '"'; - - protected final WriterConfig mConfig; - protected final String mEncoding; - - // // // Operating mode: base class needs to know whether - // // // namespaces are support (for entity/PI target validation) - - protected final boolean mNsAware; - - protected final boolean mCheckStructure; - protected final boolean mCheckContent; - protected final boolean mCheckNames; - protected final boolean mFixContent; - - /** - * Whether to escape CR (\r) character. - */ - final boolean mEscapeCR; - - /** - * Whether to add a space after empty element (before closing "/>") - * or not. - */ - final boolean mAddSpaceAfterEmptyElem; - - /** - * Flag that defines whether close() on this writer should call - * close on the underlying output object (stream, writer) - */ - protected final boolean mAutoCloseOutput; - - /** - * Optional escaping writer used for escaping characters like '<' - * '&' and '>' in textual content. - * Constructed if calling code has - * installed a special escaping writer factory for text content. - * Null if the default escaper is to be used. - */ - protected Writer mTextWriter; - - /** - * Optional escaping writer used for escaping characters like '"' - * '&' and '<' in attribute values. - * Constructed if calling code has - * installed a special escaping writer factory for text content. - * Null if the default escaper is to be used. - */ - protected Writer mAttrValueWriter; - - /** - * Indicates whether output is to be compliant; if false, is to be - * xml 1.0 compliant, if true, xml 1.1 compliant. - */ - protected boolean mXml11 = false; - - /** - * Lazy-constructed wrapper object, which will route all calls to - * Writer API, to matching writeRaw methods of this - * XmlWriter instance. - */ - protected XmlWriterWrapper mRawWrapper = null; - - /** - * Lazy-constructed wrapper object, which will route all calls to - * Writer API, to matching writeCharacters methods of this - * XmlWriter instance. - */ - protected XmlWriterWrapper mTextWrapper = null; - - /* - /////////////////////////////////////////////////////// - // Output location info - /////////////////////////////////////////////////////// - */ - - /** - * Number of characters output prior to currently buffered output - */ - protected int mLocPastChars = 0; - - protected int mLocRowNr = 1; - - /** - * Offset of the first character on this line. May be negative, if - * the offset was in a buffer that has been flushed out. - */ - protected int mLocRowStartOffset = 0; - - /* - /////////////////////////////////////////////////////// - // Life-cycle - /////////////////////////////////////////////////////// - */ - - protected XmlWriter(WriterConfig cfg, String encoding, boolean autoclose) - throws IOException - { - mConfig = cfg; - mEncoding = encoding; - mAutoCloseOutput = autoclose; - int flags = cfg.getConfigFlags(); - mNsAware = (flags & OutputConfigFlags.CFG_ENABLE_NS) != 0; - mCheckStructure = (flags & OutputConfigFlags.CFG_VALIDATE_STRUCTURE) != 0; - mCheckContent = (flags & OutputConfigFlags.CFG_VALIDATE_CONTENT) != 0; - mCheckNames = (flags & OutputConfigFlags.CFG_VALIDATE_NAMES) != 0; - mFixContent = (flags & OutputConfigFlags.CFG_FIX_CONTENT) != 0; - mEscapeCR = (flags & OutputConfigFlags.CFG_ESCAPE_CR) != 0; - mAddSpaceAfterEmptyElem = (flags & OutputConfigFlags.CFG_ADD_SPACE_AFTER_EMPTY_ELEM) != 0; - - // Has caller requested any custom text or attr value escaping? - - EscapingWriterFactory f = mConfig.getTextEscaperFactory(); - if (f == null) { - mTextWriter = null; - } else { - String enc = (mEncoding == null || mEncoding.length() == 0) ? - WstxOutputProperties.DEFAULT_OUTPUT_ENCODING : mEncoding; - mTextWriter = f.createEscapingWriterFor(wrapAsRawWriter(), enc); - } - - f = mConfig.getAttrValueEscaperFactory(); - if (f == null) { - mAttrValueWriter = null; - } else { - String enc = (mEncoding == null || mEncoding.length() == 0) ? - WstxOutputProperties.DEFAULT_OUTPUT_ENCODING : mEncoding; - mAttrValueWriter = f.createEscapingWriterFor(wrapAsRawWriter(), enc); - } - } - - /* - //////////////////////////////////////////////////// - // Extra configuration - //////////////////////////////////////////////////// - */ - - public void enableXml11() { - mXml11 = true; - } - - /* - //////////////////////////////////////////////////// - // Access to underlying physical output destinations - //////////////////////////////////////////////////// - */ - - /** - * @return Underlying OutputStream used for physical output, - * if the writer was constructed using one - */ - protected abstract OutputStream getOutputStream(); - - /** - * @return Underlying Writer used for physical output, - * if the writer was constructed with one, or one was - * created to be used with an OutputStream. - */ - protected abstract Writer getWriter(); - - /* - //////////////////////////////////////////////////// - // Basic methods for communicating with underlying - // stream or writer - //////////////////////////////////////////////////// - */ - - /** - * Method called to flush the buffer(s), and close the output - * sink (stream or writer) if enabled (auto-closing) or - * forced. - */ - public abstract void close(boolean forceRealClose) throws IOException; - - public abstract void flush() - throws IOException; - - public abstract void writeRaw(String str, int offset, int len) - throws IOException; - - public void writeRaw(String str) - throws IOException - { - writeRaw(str, 0, str.length()); - } - - public abstract void writeRaw(char[] cbuf, int offset, int len) - throws IOException; - - /** - * Like {@link #writeRaw}, but caller guarantees that the contents - * additionally are known to be in 7-bit ascii range. - */ - public abstract void writeRawAscii(char[] cbuf, int offset, int len) - throws IOException; - - /* - //////////////////////////////////////////////////// - // Raw, non-verifying write methods; used when - // directly copying trusted content - //////////////////////////////////////////////////// - */ - - public abstract void writeCDataStart() - throws IOException; - - public abstract void writeCDataEnd() - throws IOException; - - public abstract void writeCommentStart() - throws IOException; - - public abstract void writeCommentEnd() - throws IOException; - - public abstract void writePIStart(String target, boolean addSpace) - throws IOException; - - public abstract void writePIEnd() - throws IOException; - - /* - //////////////////////////////////////////////////// - // Write methods, textual: - //////////////////////////////////////////////////// - */ - - /** - * @param data Contents of the CDATA section to write out - - * @return offset of the (first) illegal content segment ("]]>") in - * passed content and not in repairing mode; or -1 if none or is - * repairing - */ - public abstract int writeCData(String data) - throws IOException, XMLStreamException; - - public abstract int writeCData(char[] cbuf, int offset, int len) - throws IOException, XMLStreamException; - - public abstract void writeCharacters(String data) - throws IOException; - - public abstract void writeCharacters(char[] cbuf, int offset, int len) - throws IOException; - - /* - //////////////////////////////////////////////////// - // Write methods, non-textual, non-elem/attr: - //////////////////////////////////////////////////// - */ - - /** - * Method that will try to output the content as specified. If - * the content passed in has embedded "--" in it, it will either - * add an intervening space between consequtive hyphens (if content - * fixing is enabled), or return the offset of the first hyphen in - * multi-hyphen sequence. - */ - public abstract int writeComment(String data) - throws IOException, XMLStreamException; - - /** - * Older "legacy" output method for outputting DOCTYPE declaration. - * Assumes that the passed-in String contains a complete DOCTYPE - * declaration properly quoted. - */ - public abstract void writeDTD(String data) - throws IOException, XMLStreamException; - - public abstract void writeDTD(String rootName, - String systemId, String publicId, - String internalSubset) - throws IOException, XMLStreamException; - - public abstract void writeEntityReference(String name) - throws IOException, XMLStreamException; - - public abstract int writePI(String target, String data) - throws IOException, XMLStreamException; - - public abstract void writeXmlDeclaration(String version, String enc, String standalone) - throws IOException; - - /* - //////////////////////////////////////////////////// - // Write methods, elements - //////////////////////////////////////////////////// - */ - - /** - *

- * Note: can throw XMLStreamException, if name checking is enabled, - * and name is invalid (name check has to be in this writer, not - * caller, since it depends not only on xml limitations, but also - * on encoding limitations) - */ - public abstract void writeStartTagStart(String localName) - throws IOException, XMLStreamException; - - /** - *

- * Note: can throw XMLStreamException, if name checking is enabled, - * and name is invalid (name check has to be in this writer, not - * caller, since it depends not only on xml limitations, but also - * on encoding limitations) - */ - public abstract void writeStartTagStart(String prefix, String localName) - throws IOException, XMLStreamException; - - public abstract void writeStartTagEnd() - throws IOException; - - public abstract void writeStartTagEmptyEnd() - throws IOException; - - public abstract void writeEndTag(String localName) - throws IOException; - - public abstract void writeEndTag(String prefix, String localName) - throws IOException; - - /* - //////////////////////////////////////////////////// - // Write methods, attributes/ns - //////////////////////////////////////////////////// - */ - - /** - *

- * Note: can throw XMLStreamException, if name checking is enabled, - * and name is invalid (name check has to be in this writer, not - * caller, since it depends not only on xml limitations, but also - * on encoding limitations) - */ - public abstract void writeAttribute(String localName, String value) - throws IOException, XMLStreamException; - - public abstract void writeAttribute(String localName, char[] value, int offset, int len) - throws IOException, XMLStreamException; - - /** - *

- * Note: can throw XMLStreamException, if name checking is enabled, - * and name is invalid (name check has to be in this writer, not - * caller, since it depends not only on xml limitations, but also - * on encoding limitations) - */ - public abstract void writeAttribute(String prefix, String localName, String value) - throws IOException, XMLStreamException; - - public abstract void writeAttribute(String prefix, String localName, char[] value, int offset, int len) - throws IOException, XMLStreamException; - - /* - //////////////////////////////////////////////////// - // Write methods, Typed Access API support - //////////////////////////////////////////////////// - */ - - /** - * Like {@link #writeRaw}, but caller guarantees that the contents - * additionally are known to be in 7-bit ascii range, and also - * passes an encoder object that will encode values only when - * being handed a buffer to append to. - * - * @param enc Encoder that will produce content - */ - public abstract void writeTypedElement(AsciiValueEncoder enc) - throws IOException; - - /** - * Like {@link #writeRaw}, but caller guarantees that the contents - * additionally are known to be in 7-bit ascii range, and also - * passes an encoder object that will encode values only when - * being handed a buffer to append to. - * - * @param enc Encoder that will produce content - * @param validator Validator to use for validating serialized textual - * content (can not be null) - * @param copyBuffer Temporary buffer that writer can use for temporary - * copies as necessary - */ - public abstract void writeTypedElement(AsciiValueEncoder enc, - XMLValidator validator, char[] copyBuffer) - throws IOException, XMLStreamException; - - /** - * Method similar to {@link #writeAttribute(String,String,char[],int,int)} - * but where is known not to require escaping. - * No validation needs to be performed. - */ - public abstract void writeTypedAttribute(String localName, AsciiValueEncoder enc) - throws IOException, XMLStreamException; - - /** - * Method similar to {@link #writeAttribute(String,String,char[],int,int)} - * but where is known not to require escaping. - * No validation needs to be performed. - */ - public abstract void writeTypedAttribute(String prefix, String localName, AsciiValueEncoder enc) - throws IOException, XMLStreamException; - - /** - * Method similar to {@link #writeAttribute(String,String,char[],int,int)} - * but where is known not to require escaping. - * Validation of the attribute value must be done by calling given - * validator appropriately. - */ - public abstract void writeTypedAttribute(String prefix, String localName, String nsURI, - AsciiValueEncoder enc, - XMLValidator validator, char[] copyBuffer) - throws IOException, XMLStreamException; - - /* - //////////////////////////////////////////////////// - // Location information - //////////////////////////////////////////////////// - */ - - protected abstract int getOutputPtr(); - - public int getRow() { - return mLocRowNr; - } - - public int getColumn() { - return (getOutputPtr() - mLocRowStartOffset) + 1; - } - - public int getAbsOffset() { - return mLocPastChars +getOutputPtr(); - } - - /* - //////////////////////////////////////////////////// - // Wrapper methods, semi-public - //////////////////////////////////////////////////// - */ - - /** - * Method that can be called to get a wrapper instance that - * can be used to essentially call the writeRaw - * method. - */ - public final Writer wrapAsRawWriter() - { - if (mRawWrapper == null) { - mRawWrapper = XmlWriterWrapper.wrapWriteRaw(this); - } - return mRawWrapper; - } - - public final Writer wrapAsTextWriter() - { - if (mTextWrapper == null) { - mTextWrapper = XmlWriterWrapper.wrapWriteCharacters(this); - } - return mTextWrapper; - } - - /* - //////////////////////////////////////////////////// - // Helper methods for sub-classes - //////////////////////////////////////////////////// - */ - - /** - * Method called to verify that the name is a legal XML name. - */ - public final void verifyNameValidity(String name, boolean checkNs) - throws XMLStreamException - { - /* No empty names... caller must have dealt with optional arguments - * prior to calling this method - */ - if (name == null || name.length() == 0) { - reportNwfName(ErrorConsts.WERR_NAME_EMPTY); - } - int illegalIx = WstxInputData.findIllegalNameChar(name, checkNs, mXml11); - if (illegalIx >= 0) { - if (illegalIx == 0) { - reportNwfName(ErrorConsts.WERR_NAME_ILLEGAL_FIRST_CHAR, - WstxInputData.getCharDesc(name.charAt(0))); - } - reportNwfName(ErrorConsts.WERR_NAME_ILLEGAL_CHAR, - WstxInputData.getCharDesc(name.charAt(illegalIx))); - } - } - - /** - * This is the method called when an output method call violates - * name well-formedness checks - * and {@link WstxOutputProperties#P_OUTPUT_VALIDATE_NAMES} is - * is enabled. - */ - protected void reportNwfName(String msg) - throws XMLStreamException - { - throwOutputError(msg); - } - - protected void reportNwfName(String msg, Object arg) - throws XMLStreamException - { - throwOutputError(msg, arg); - } - - protected void reportNwfContent(String msg) - throws XMLStreamException - { - throwOutputError(msg); - } - - protected void throwOutputError(String msg) - throws XMLStreamException - { - // First, let's flush any output we may have, to make debugging easier - try { - flush(); - } catch (IOException ioe) { - throw new WstxIOException(ioe); - } - - throw new XMLStreamException(msg); - } - - protected void throwOutputError(String format, Object arg) - throws XMLStreamException - { - String msg = MessageFormat.format(format, new Object[] { arg }); - throwOutputError(msg); - } - - /** - * Method called to handle invalid character in textual content requested - * to be output. Content may be part of textual events (CHARACTER, CDATA), - * attribute value, COMMENT content or PROCESSING_INSTRUCTION data. - * The default behavior is to just throw an exception, but this can - * be configured via property {@link WstxOutputProperties#P_OUTPUT_INVALID_CHAR_HANDLER}. - */ - protected char handleInvalidChar(int c) - throws IOException - { - // First, let's flush any output we may have, to make debugging easier - flush(); - InvalidCharHandler h = mConfig.getInvalidCharHandler(); - if (h == null) { - h = InvalidCharHandler.FailingHandler.getInstance(); - } - return h.convertInvalidChar(c); - } -} diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/sw/XmlWriterWrapper.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/sw/XmlWriterWrapper.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/sw/XmlWriterWrapper.java 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/sw/XmlWriterWrapper.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,172 +0,0 @@ -/* Woodstox XML processor - * - * Copyright (c) 2004- Tatu Saloranta, tatu.saloranta@iki.fi - * - * Licensed under the License specified in file LICENSE, included with - * the source code. - * You may not use this file except in compliance with the License. - * - * 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 com.ctc.wstx.sw; - -import java.io.*; - -/** - * This is a simple wrapper class, which decorates an {@link XmlWriter} - * to look like a Writer. This is necessary to implement a (legacy) - * character quoting system introduced for Woodstox 2.0, which relies - * on having a Writer to use for outputting. - */ -public abstract class XmlWriterWrapper - extends Writer -{ - protected final XmlWriter mWriter; - - private char[] mBuffer = null; - - public static XmlWriterWrapper wrapWriteRaw(XmlWriter xw) - { - return new RawWrapper(xw); - } - - public static XmlWriterWrapper wrapWriteCharacters(XmlWriter xw) - { - return new TextWrapper(xw); - } - - protected XmlWriterWrapper(XmlWriter writer) - { - mWriter = writer; - } - - public final void close() - throws IOException - { - mWriter.close(false); - } - - public final void flush() - throws IOException - { - mWriter.flush(); - } - - /* !!! 30-Nov-2006, TSa: Due to co-variance between Appendable and - * Writer, this would not compile with javac 1.5, in 1.4 mode - * (source and target set to "1.4". Not a huge deal, but since - * the base impl is just fine, no point in overriding it. - */ - /* - public final Writer append(char c) - throws IOException - { - if (mBuffer == null) { - mBuffer = new char[1]; - } - mBuffer[0] = (char) c; - write(mBuffer, 0, 1); - return this; - } - */ - - public final void write(char[] cbuf) - throws IOException - { - write(cbuf, 0, cbuf.length); - } - - public abstract void write(char[] cbuf, int off, int len) - throws IOException; - - public final void write(int c) - throws IOException - { - if (mBuffer == null) { - mBuffer = new char[1]; - } - mBuffer[0] = (char) c; - write(mBuffer, 0, 1); - } - - public abstract void write(String str) - throws IOException; - - public abstract void write(String str, int off, int len) - throws IOException; - - /* - ////////////////////////////////////////////////// - // Implementation classes - ////////////////////////////////////////////////// - */ - - /** - * This wrapper directs calls to writeRaw methods. Thus, - * it is a "vanilla" writer, and no escaping is done. - */ - private final static class RawWrapper - extends XmlWriterWrapper - { - protected RawWrapper(XmlWriter writer) - { - super(writer); - } - - public void write(char[] cbuf, int off, int len) - throws IOException - { - mWriter.writeRaw(cbuf, off, len); - } - - public void write(String str, int off, int len) - throws IOException - { - mWriter.writeRaw(str, off, len); - } - - public final void write(String str) - throws IOException - { - mWriter.writeRaw(str, 0, str.length()); - } - } - - /** - * This wrapper directs calls to writeCharacters methods. - * This means that text content escaping (and, possibly, validation) - * is done, using default or custom escaping code. - */ - private static class TextWrapper - extends XmlWriterWrapper - { - protected TextWrapper(XmlWriter writer) - { - super(writer); - } - - public void write(char[] cbuf, int off, int len) - throws IOException - { - mWriter.writeCharacters(cbuf, off, len); - } - - public void write(String str) - throws IOException - { - mWriter.writeCharacters(str); - } - - public void write(String str, int off, int len) - throws IOException - { - mWriter.writeCharacters(str.substring(off, off+len)); - } - } -} - diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/util/ArgUtil.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/util/ArgUtil.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/util/ArgUtil.java 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/util/ArgUtil.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,58 +0,0 @@ -package com.ctc.wstx.util; - -/** - * Simple static utility class that contains (static) utility methods useful - * when parsing non-typesafe arguments (String-only configuration, command - * line args). - */ -public final class ArgUtil -{ - private ArgUtil() { } - - public static boolean convertToBoolean(String prop, Object value) - { - if (value == null) { - return false; - } - if (value instanceof Boolean) { - return ((Boolean) value).booleanValue(); - } - if (value instanceof String) { - String str = (String) value; - if (str.equalsIgnoreCase("false")) { - return false; - } - if (str.equalsIgnoreCase("true")) { - return true; - } - throw new IllegalArgumentException("Invalid String value for property '"+prop+"': expected Boolean value."); - } - throw new IllegalArgumentException("Invalid value type ("+value.getClass()+") for property '"+prop+"': expected Boolean value."); - } - - public static int convertToInt(String prop, Object value, int minValue) - { - int i; - - if (value == null) { - i = 0; - } else if (value instanceof Number) { - i = ((Number) value).intValue(); - } else if (value instanceof String) { - try { - i = Integer.parseInt((String) value); - } catch (NumberFormatException nex) { - throw new IllegalArgumentException("Invalid String value for property '"+prop+"': expected a number (Integer)."); - } - } else { - throw new IllegalArgumentException("Invalid value type ("+value.getClass()+") for property '"+prop+"': expected Integer value."); - } - - if (i < minValue) { - throw new IllegalArgumentException("Invalid numeric value ("+i - +") for property '"+prop - +"': minimum is "+minValue+"."); - } - return i; - } -} diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/util/BaseNsContext.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/util/BaseNsContext.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/util/BaseNsContext.java 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/util/BaseNsContext.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,132 +0,0 @@ -/* Woodstox XML processor - * - * Copyright (c) 2004 Tatu Saloranta, tatu.saloranta@iki.fi - * - * Licensed under the License specified in file LICENSE, included with - * the source code. - * You may not use this file except in compliance with the License. - * - * 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 com.ctc.wstx.util; - -import java.io.IOException; -import java.io.Writer; -import java.util.Iterator; - -import javax.xml.XMLConstants; -import javax.xml.namespace.NamespaceContext; -import javax.xml.stream.XMLStreamException; -import javax.xml.stream.XMLStreamWriter; - -import org.codehaus.stax2.ri.SingletonIterator; - -import com.ctc.wstx.cfg.ErrorConsts; - -/** - * Abstract base class that defines extra features defined by most - * NamespaceContext implementations Wodstox uses. - */ -public abstract class BaseNsContext - implements NamespaceContext -{ - /** - * This is the URI returned for default namespace, when it hasn't - * been explicitly declared; could be either "" or null. - */ - protected final static String UNDECLARED_NS_URI = ""; - - /* - ///////////////////////////////////////////// - // NamespaceContext API - ///////////////////////////////////////////// - */ - - public final String getNamespaceURI(String prefix) - { - /* First the known offenders; invalid args, 2 predefined xml namespace - * prefixes - */ - if (prefix == null) { - throw new IllegalArgumentException(ErrorConsts.ERR_NULL_ARG); - } - if (prefix.length() > 0) { - if (prefix.equals(XMLConstants.XML_NS_PREFIX)) { - return XMLConstants.XML_NS_URI; - } - if (prefix.equals(XMLConstants.XMLNS_ATTRIBUTE)) { - return XMLConstants.XMLNS_ATTRIBUTE_NS_URI; - } - } - return doGetNamespaceURI(prefix); - } - - public final String getPrefix(String nsURI) - { - /* First the known offenders; invalid args, 2 predefined xml namespace - * prefixes - */ - if (nsURI == null || nsURI.length() == 0) { - throw new IllegalArgumentException("Illegal to pass null/empty prefix as argument."); - } - if (nsURI.equals(XMLConstants.XML_NS_URI)) { - return XMLConstants.XML_NS_PREFIX; - } - if (nsURI.equals(XMLConstants.XMLNS_ATTRIBUTE_NS_URI)) { - return XMLConstants.XMLNS_ATTRIBUTE; - } - return doGetPrefix(nsURI); - } - - public final Iterator getPrefixes(String nsURI) - { - /* First the known offenders; invalid args, 2 predefined xml namespace - * prefixes - */ - if (nsURI == null || nsURI.length() == 0) { - throw new IllegalArgumentException("Illegal to pass null/empty prefix as argument."); - } - if (nsURI.equals(XMLConstants.XML_NS_URI)) { - return new SingletonIterator(XMLConstants.XML_NS_PREFIX); - } - if (nsURI.equals(XMLConstants.XMLNS_ATTRIBUTE_NS_URI)) { - return new SingletonIterator(XMLConstants.XMLNS_ATTRIBUTE); - } - - return doGetPrefixes(nsURI); - } - - /* - ///////////////////////////////////////////// - // Extended API - ///////////////////////////////////////////// - */ - - public abstract Iterator getNamespaces(); - - /** - * Method called by the matching start element class to - * output all namespace declarations active in current namespace - * scope, if any. - */ - public abstract void outputNamespaceDeclarations(Writer w) throws IOException; - - public abstract void outputNamespaceDeclarations(XMLStreamWriter w) throws XMLStreamException; - - /* - ///////////////////////////////////////////////// - // Template methods sub-classes need to implement - ///////////////////////////////////////////////// - */ - - public abstract String doGetNamespaceURI(String prefix); - - public abstract String doGetPrefix(String nsURI); - - public abstract Iterator doGetPrefixes(String nsURI); -} diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/util/BijectiveNsMap.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/util/BijectiveNsMap.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/util/BijectiveNsMap.java 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/util/BijectiveNsMap.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,326 +0,0 @@ -/* Woodstox XML processor - * - * Copyright (c) 2005 Tatu Saloranta, tatu.saloranta@iki.fi - * - * Licensed under the License specified in file LICENSE, included with - * the source code. - * You may not use this file except in compliance with the License. - * - * 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 com.ctc.wstx.util; - -import java.util.*; - -import javax.xml.XMLConstants; -import javax.xml.namespace.NamespaceContext; - -import com.ctc.wstx.util.DataUtil; - -/** - * Helper class that implements "bijective map" (Map that allows use of values - * as keys and vice versa, bidirectional access), and is specifically - * used for storing namespace binding information. - * One thing worth noting is that Strings stored are NOT assumed to have - * been unified (interned) -- if they were, different implementation would - * be more optimal. - *

- * Currently only used by stream writers, but could be more generally useful - * too. - */ - -public final class BijectiveNsMap -{ - /* - /////////////////////////////////////////////// - // Constants - /////////////////////////////////////////////// - */ - - /** - * Let's plan for having up to 14 explicit namespace declarations (2 - * defaults, for 'xml' and 'xmlns', are pre-populated) - */ - final static int DEFAULT_ARRAY_SIZE = 2 * 16; - - /* - /////////////////////////////////////////////// - // Member vars - /////////////////////////////////////////////// - */ - - final int mScopeStart; - - /** - * Array that contains { prefix, ns-uri } pairs, up to (but not including) - * index {@link #mScopeEnd}. - */ - String[] mNsStrings; - - int mScopeEnd; - - /* - /////////////////////////////////////////////// - // Life-cycle - /////////////////////////////////////////////// - */ - - private BijectiveNsMap(int scopeStart, String[] strs) - { - mScopeStart = mScopeEnd = scopeStart; - mNsStrings = strs; - } - - public static BijectiveNsMap createEmpty() - { - String[] strs = new String[DEFAULT_ARRAY_SIZE]; - - strs[0] = XMLConstants.XML_NS_PREFIX; - strs[1] = XMLConstants.XML_NS_URI; - strs[2] = XMLConstants.XMLNS_ATTRIBUTE; - strs[3] = XMLConstants.XMLNS_ATTRIBUTE_NS_URI; - - /* Let's consider pre-defined ones to be 'out of scope', i.e. - * conceptually be part of (missing) parent's mappings. - */ - return new BijectiveNsMap(4, strs); - } - - public BijectiveNsMap createChild() { - return new BijectiveNsMap(mScopeEnd, mNsStrings); - } - - /* - /////////////////////////////////////////////// - // Public API, accessors - /////////////////////////////////////////////// - */ - - public String findUriByPrefix(String prefix) - { - /* This is quite simple: just need to locate the last mapping - * for the prefix, if any: - */ - String[] strs = mNsStrings; - int phash = prefix.hashCode(); - - for (int ix = mScopeEnd - 2; ix >= 0; ix -= 2) { - String thisP = strs[ix]; - if (thisP == prefix || - (thisP.hashCode() == phash && thisP.equals(prefix))) { - return strs[ix+1]; - } - } - return null; - } - - public String findPrefixByUri(String uri) - { - - /* Finding a valid binding for the given URI is trickier, since - * mappings can be masked by others... so, we need to first find - * most recent binding, from the freshest one, and then verify - * it's still unmasked; if not, continue with the first loop, - * and so on. - */ - - String[] strs = mNsStrings; - int uhash = uri.hashCode(); - - main_loop: - for (int ix = mScopeEnd - 1; ix > 0; ix -= 2) { - String thisU = strs[ix]; - if (thisU == uri || - (thisU.hashCode() == uhash && thisU.equals(uri))) { - // match, but has it been masked? - String prefix = strs[ix-1]; - /* only need to check, if it wasn't within current scope - * (no masking allowed within scopes) - */ - if (ix < mScopeStart) { - int phash = prefix.hashCode(); - for (int j = ix+1, end = mScopeEnd; j < end; j += 2) { - String thisP = strs[j]; - if (thisP == prefix || - (thisP.hashCode() == phash && thisP.equals(prefix))) { - // Masking... got to continue the main loop: - continue main_loop; - } - } - } - // Ok, unmasked one, can return - return prefix; - } - } - return null; - } - - public List getPrefixesBoundToUri(String uri, List l) - { - /* Same problems (masking) apply here, as well as with - * findPrefixByUri... - */ - String[] strs = mNsStrings; - int uhash = uri.hashCode(); - - main_loop: - for (int ix = mScopeEnd - 1; ix > 0; ix -= 2) { - String thisU = strs[ix]; - if (thisU == uri || - (thisU.hashCode() == uhash && thisU.equals(uri))) { - // match, but has it been masked? - String prefix = strs[ix-1]; - /* only need to check, if it wasn't within current scope - * (no masking allowed within scopes) - */ - if (ix < mScopeStart) { - int phash = prefix.hashCode(); - for (int j = ix+1, end = mScopeEnd; j < end; j += 2) { - String thisP = strs[j]; - if (thisP == prefix || - (thisP.hashCode() == phash && thisP.equals(prefix))) { - // Masking... got to continue the main loop: - continue main_loop; - } - } - } - // Ok, unmasked one, can add - if (l == null) { - l = new ArrayList(); - } - l.add(prefix); - } - } - return l; - } - - public int size() { - return (mScopeEnd >> 1); - } - - public int localSize() { - return ((mScopeEnd - mScopeStart) >> 1); - } - - /* - /////////////////////////////////////////////// - // Public API, mutators - /////////////////////////////////////////////// - */ - - /** - * Method to add a new prefix-to-URI mapping for the current scope. - * Note that it should NOT be used for the default namespace - * declaration - * - * @param prefix Prefix to bind - * @param uri URI to bind to the prefix - * - * @return If the prefix was already bound, the URI it was bound to: - * null if it's a new binding for the current scope. - */ - public String addMapping(String prefix, String uri) - { - String[] strs = mNsStrings; - int phash = prefix.hashCode(); - - for (int ix = mScopeStart, end = mScopeEnd; ix < end; ix += 2) { - String thisP = strs[ix]; - if (thisP == prefix || - (thisP.hashCode() == phash && thisP.equals(prefix))) { - // Overriding an existing mapping - String old = strs[ix+1]; - strs[ix+1] = uri; - return old; - } - } - // no previous binding, let's just add it at the end - if (mScopeEnd >= strs.length) { - // let's just double the array sizes... - strs = DataUtil.growArrayBy(strs, strs.length); - mNsStrings = strs; - } - strs[mScopeEnd++] = prefix; - strs[mScopeEnd++] = uri; - - return null; - } - - /** - * Method used to add a dynamic binding, and return the prefix - * used to bind the specified namespace URI. - */ - public String addGeneratedMapping(String prefixBase, NamespaceContext ctxt, - String uri, int[] seqArr) - { - String[] strs = mNsStrings; - int seqNr = seqArr[0]; - String prefix; - - main_loop: - while (true) { - /* We better intern the resulting prefix? Or not? - * TODO: maybe soft cache these for other docs? - */ - prefix = (prefixBase + seqNr).intern(); - ++seqNr; - - /* Ok, let's see if we have a mapping (masked or not) for - * the prefix. If we do, let's just not use it: we could - * of course mask it (unless it's in current scope), but - * it's easier to just get a "virgin" prefix... - */ - int phash = prefix.hashCode(); - - for (int ix = mScopeEnd - 2; ix >= 0; ix -= 2) { - String thisP = strs[ix]; - if (thisP == prefix || - (thisP.hashCode() == phash && thisP.equals(prefix))) { - continue main_loop; - } - } - /* So far so good... but do we have a root context that might - * have something too? - */ - - if (ctxt != null && ctxt.getNamespaceURI(prefix) != null) { - continue; - } - break; - } - seqArr[0] = seqNr; - - // Ok, good; then let's just add it in... - if (mScopeEnd >= strs.length) { - // let's just double the array sizes... - strs = DataUtil.growArrayBy(strs, strs.length); - mNsStrings = strs; - } - strs[mScopeEnd++] = prefix; - strs[mScopeEnd++] = uri; - - return prefix; - } - - /* - /////////////////////////////////////////////// - // Standard overridden methods - /////////////////////////////////////////////// - */ - - public String toString() { - return "["+getClass().toString()+"; "+size()+" entries; of which " - +localSize()+" local]"; - } - - /* - /////////////////////////////////////////////// - // Internal methods - /////////////////////////////////////////////// - */ -} diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/util/DataUtil.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/util/DataUtil.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/util/DataUtil.java 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/util/DataUtil.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,135 +0,0 @@ -package com.ctc.wstx.util; - -import java.lang.reflect.Array; -import java.util.*; - -public final class DataUtil -{ - final static char[] EMPTY_CHAR_ARRAY = new char[0]; - - /** - * If baseline requirement was JDK 1.5, we wouldn't need to - * cache Integer instances like this (since it has - * Integer.valueOf() which does it); but until then, we - * alas need our known canonicalization. - */ - final static Integer[] INTS = new Integer[100]; - static { - for (int i = 0; i < INTS.length; ++i) { - INTS[i] = new Integer(i); - } - } - - private DataUtil() { } - - /* - //////////////////////////////////////////////////////////// - // Pooling for immutable objects - //////////////////////////////////////////////////////////// - */ - - public static char[] getEmptyCharArray() { - return EMPTY_CHAR_ARRAY; - } - - public static Integer Integer(int i) - { - /* !!! 13-Sep-2008, TSa: JDK 1.5 can use Integer.valueOf(int) - * which does the same. When upgrading baseline, can get rid - * of this method. - */ - if (i < 0 || i >= INTS.length) { - return new Integer(i); - } - return INTS[i]; - } - - /* - //////////////////////////////////////////////////////////// - // Methods for common operations on std data structs - //////////////////////////////////////////////////////////// - */ - - /** - * Method that can be used to efficiently check if 2 collections - * share at least one common element. - * - * @return True if there is at least one element that's common - * to both Collections, ie. that is contained in both of them. - */ - public static boolean anyValuesInCommon(Collection c1, Collection c2) - { - // Let's always iterate over smaller collection: - if (c1.size() > c2.size()) { - Collection tmp = c1; - c1 = c2; - c2 = tmp; - } - Iterator it = c1.iterator(); - while (it.hasNext()) { - if (c2.contains(it.next())) { - return true; - } - } - return false; - } - - final static String NO_TYPE = "Illegal to pass null; can not determine component type"; - - public static Object growArrayBy50Pct(Object arr) - { - if (arr == null) { - throw new IllegalArgumentException(NO_TYPE); - } - Object old = arr; - int len = Array.getLength(arr); - arr = Array.newInstance(arr.getClass().getComponentType(), len + (len >> 1)); - System.arraycopy(old, 0, arr, 0, len); - return arr; - } - - /** - * Method similar to {@link #growArrayBy50Pct}, but it also ensures that - * the new size is at least as big as the specified minimum size. - */ - public static Object growArrayToAtLeast(Object arr, int minLen) - { - if (arr == null) { - throw new IllegalArgumentException(NO_TYPE); - } - Object old = arr; - int oldLen = Array.getLength(arr); - int newLen = oldLen + ((oldLen + 1) >> 1); - if (newLen < minLen) { - newLen = minLen; - } - arr = Array.newInstance(arr.getClass().getComponentType(), newLen); - System.arraycopy(old, 0, arr, 0, oldLen); - return arr; - } - - public static String[] growArrayBy(String[] arr, int more) - { - if (arr == null) { - return new String[more]; - } - String[] old = arr; - int len = arr.length; - arr = new String[len + more]; - System.arraycopy(old, 0, arr, 0, len); - return arr; - } - - public static int[] growArrayBy(int[] arr, int more) - { - if (arr == null) { - return new int[more]; - } - int[] old = arr; - int len = arr.length; - arr = new int[len + more]; - System.arraycopy(old, 0, arr, 0, len); - return arr; - } -} - diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/util/DefaultXmlSymbolTable.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/util/DefaultXmlSymbolTable.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/util/DefaultXmlSymbolTable.java 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/util/DefaultXmlSymbolTable.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,93 +0,0 @@ -package com.ctc.wstx.util; - -import com.ctc.wstx.util.SymbolTable; - -/** - * Factory class used for instantiating pre-populated XML symbol - * tables. Such tables already have basic String constants that - * XML standard defines. - */ -public final class DefaultXmlSymbolTable -{ - /** - * Root symbol table from which child instances are derived. - */ - final static SymbolTable sInstance; - - final static String mNsPrefixXml; - final static String mNsPrefixXmlns; - - /* Although theoretically there'd be no strict need to pre-populate - * the default table, if all access was done using suggested usage - * patterns (reuse input factories consistently, esp. for same types - * of documents), it is possible some developers just use each factory - * just once. As such, it does matter how tables are pre-populated. - * Thus, let's use limited sensible set of predefined prefixes and - * names. - */ - static { - /* 128 means it's ok without resize up to ~96 symbols; true that - * default symbols added will be interned. - */ - sInstance = new SymbolTable(true, 128); - - // Let's add default namespace binding prefixes - mNsPrefixXml = sInstance.findSymbol("xml"); - mNsPrefixXmlns = sInstance.findSymbol("xmlns"); - - /* No need to add keywords, as they are checked directly by - * Reader, without constructing Strings. - */ - - // Ok, any common prefixes? - - // or local names (element, attribute)? - sInstance.findSymbol("id"); - sInstance.findSymbol("name"); - - // XML Schema? - // prefixes: - sInstance.findSymbol("xsd"); - sInstance.findSymbol("xsi"); - // local names: - sInstance.findSymbol("type"); - - // How about some common prefixes and names for Soap? - // commonly used prefixes: - sInstance.findSymbol("soap"); - sInstance.findSymbol("SOAP-ENC"); - sInstance.findSymbol("SOAP-ENV"); - // local names: - sInstance.findSymbol("Body"); - sInstance.findSymbol("Envelope"); - } - - /* - /////////////////////////////////////////////////// - // Public API, factory method(s): - /////////////////////////////////////////////////// - */ - - /** - * Method that will return an instance of SymbolTable that has basic - * XML 1.0 constants pre-populated. - */ - public static SymbolTable getInstance() { - return sInstance.makeChild(); - } - - /* - /////////////////////////////////////////////////// - // Public API, efficient access to (shared) - // constants values: - /////////////////////////////////////////////////// - */ - - public static String getXmlSymbol() { - return mNsPrefixXml; - } - - public static String getXmlnsSymbol() { - return mNsPrefixXmlns; - } -} diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/util/ElementId.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/util/ElementId.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/util/ElementId.java 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/util/ElementId.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,162 +0,0 @@ -package com.ctc.wstx.util; - -import javax.xml.stream.Location; - -import com.ctc.wstx.cfg.ErrorConsts; - -/** - * Simple container Object used to store information about id attribute - * values, and references to such (as of yet undefined) values. - *

- * Instances can be in one of 2 modes: either in fully defined mode, - * in which case information refers to location where value was defined - * (ie. we had id as a value of ID type attribute); or in undefined mode, - * in which case information refers to the first reference. - *

- * Note: this class is designed to be used with {@link ElementIdMap}, - * and as a result has some information specifically needed by the - * map implementation (such as collision links). - */ -public final class ElementId -{ - /** - * Flag that indicates whether this Object presents a defined id - * value (value of an ID attribute) or just a reference to one. - */ - private boolean mDefined; - - /* - ///////////////////////////////////////////////// - // Information about id value or value reference, - // depending on mDefined flag - ///////////////////////////////////////////////// - */ - - /** - * Actual id value - */ - private final String mIdValue; - - /** - * Location of either definition (if {@link #mDefined} is true; or - * first reference (otherwise). Used when reporting errors; either - * a referenced id has not been defined, or there are multiple - * definitions of same id. - */ - private Location mLocation; - - /** - * Name of element for which this id refers. - */ - private PrefixedName mElemName; - - /** - * Name of the attribute that contains this id value (often "id", - * but need not be) - */ - private PrefixedName mAttrName; - - /* - //////////////////////////////////////////////////// - // Linking information, needed by the map to keep - // track of collided ids, as well as undefined ids - //////////////////////////////////////////////////// - */ - - private ElementId mNextUndefined; - - /** - * Pointer to the next element within collision chain. - */ - private ElementId mNextColl; - - /* - ///////////////////////////////////////////////// - // Life cycle - ///////////////////////////////////////////////// - */ - - ElementId(String id, Location loc, boolean defined, - PrefixedName elemName, PrefixedName attrName) - { - mIdValue = id; - mLocation = loc; - mDefined = defined; - mElemName = elemName; - mAttrName = attrName; - } - - protected void linkUndefined(ElementId undefined) - { - if (mNextUndefined != null) { - throw new IllegalStateException("ElementId '"+this+"' already had net undefined set ('"+mNextUndefined+"')"); - } - mNextUndefined = undefined; - } - - protected void setNextColliding(ElementId nextColl) - { - // May add/remove link, no point in checking - mNextColl = nextColl; - } - - /* - ///////////////////////////////////////////////// - // Public API - ///////////////////////////////////////////////// - */ - - public String getId() { return mIdValue; } - public Location getLocation() { return mLocation; } - public PrefixedName getElemName() { return mElemName; } - public PrefixedName getAttrName() { return mAttrName; } - - public boolean isDefined() { return mDefined; } - - public boolean idMatches(char[] buf, int start, int len) - { - if (mIdValue.length() != len) { - return false; - } - // Assumes it's always at least one char long - if (buf[start] != mIdValue.charAt(0)) { - return false; - } - int i = 1; - len += start; - while (++start < len) { - if (buf[start] != mIdValue.charAt(i)) { - return false; - } - ++i; - } - return true; - } - - public boolean idMatches(String idStr) - { - return mIdValue.equals(idStr); - } - - public ElementId nextUndefined() { return mNextUndefined; } - public ElementId nextColliding() { return mNextColl; } - - public void markDefined(Location defLoc) { - if (mDefined) { // sanity check - throw new IllegalStateException(ErrorConsts.ERR_INTERNAL); - } - mDefined = true; - mLocation = defLoc; - } - - /* - ///////////////////////////////////////////////// - // Other methods - ///////////////////////////////////////////////// - */ - - public String toString() { - return mIdValue; - } -} - diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/util/ElementIdMap.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/util/ElementIdMap.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/util/ElementIdMap.java 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/util/ElementIdMap.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,425 +0,0 @@ -/* Woodstox XML processor - * - * Copyright (c) 2004- Tatu Saloranta, tatu.saloranta@iki.fi - * - * Licensed under the License specified in the file LICENSE which is - * included with the source code. - * You may not use this file except in compliance with the License. - * - * 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 com.ctc.wstx.util; - -import javax.xml.stream.Location; - - -/** - * This class is a specialized type-safe linked hash map used for - * storing {@link ElementId} instances. {@link ElementId} instances - * represent both id definitions (values of element attributes that - * have type ID in DTD), and references (values of element attributes - * of type IDREF and IDREFS). These definitions and references are - * stored for the purpose of verifying - * that all referenced id values are defined, and that none are defined - * more than once. - *

- * Note: there are 2 somewhat distinct usage modes, by DTDValidator and - * by MSV-based validators. - * DTDs pass raw character arrays, whereas - * MSV-based validators operate on Strings. This is the main reason - * for 2 distinct sets of methods. - */ - -public final class ElementIdMap -{ - /** - * Default initial table size; set so that usually it need not - * be expanded. - */ - protected static final int DEFAULT_SIZE = 128; - - protected static final int MIN_SIZE = 16; - - /** - * Let's use 80% fill factor... - */ - protected static final int FILL_PCT = 80; - - /* - //////////////////////////////////////// - // Actual hash table structure - //////////////////////////////////////// - */ - - /** - * Actual hash table area - */ - protected ElementId[] mTable; - - /** - * Current size (number of entries); needed to know if and when - * rehash. - */ - protected int mSize; - - /** - * Limit that indicates maximum size this instance can hold before - * it needs to be expanded and rehashed. Calculated using fill - * factor passed in to constructor. - */ - protected int mSizeThreshold; - - /** - * Mask used to get index from hash values; equal to - * mBuckets.length - 1, when mBuckets.length is - * a power of two. - */ - protected int mIndexMask; - - /* - //////////////////////////////////////// - // Linked list info - //////////////////////////////////////// - */ - - protected ElementId mHead; - - protected ElementId mTail; - - /* - //////////////////////////////////////// - // Life-cycle: - //////////////////////////////////////// - */ - - public ElementIdMap() - { - this(DEFAULT_SIZE); - } - - /** - * This constructor is mainly used for testing, as it can be sized - * appropriately to test rehashing etc. - */ - public ElementIdMap(int initialSize) - { - int actual = MIN_SIZE; - while (actual < initialSize) { - actual += actual; - } - mTable = new ElementId[actual]; - // Mask is easy to calc for powers of two. - mIndexMask = actual - 1; - mSize = 0; - mSizeThreshold = (actual * FILL_PCT) / 100; - mHead = mTail = null; - } - - /* - //////////////////////////////////////////////////// - // Public API - //////////////////////////////////////////////////// - */ - - public ElementId getFirstUndefined() - { - /* Since the linked list is pruned to always start with - * the first (in doc order) undefined id, we can just - * return head: - */ - return mHead; - } - - /** - * Method called when a reference to id is encountered. If so, need - * to check if specified id entry (ref or definiton) exists; and if not, - * to add a reference marker. - */ - public ElementId addReferenced(char[] buffer, int start, int len, int hash, - Location loc, PrefixedName elemName, PrefixedName attrName) - { - int index = (hash & mIndexMask); - ElementId id = mTable[index]; - - while (id != null) { - if (id.idMatches(buffer, start, len)) { // found existing one - return id; - } - id = id.nextColliding(); - } - - // Not found, need to create a placeholder... - - // But first, do we need more room? - if (mSize >= mSizeThreshold) { - rehash(); - // Index changes, for the new entr: - index = (hash & mIndexMask); - } - ++mSize; - - // Ok, then, let's create the entry - String idStr = new String(buffer, start, len); - id = new ElementId(idStr, loc, false, elemName, attrName); - - // First, let's link it to Map; all ids have to be connected - id.setNextColliding(mTable[index]); - mTable[index] = id; - - // And then add the undefined entry at the end of list - if (mHead == null) { - mHead = mTail = id; - } else { - mTail.linkUndefined(id); - mTail = id; - } - return id; - } - - public ElementId addReferenced(String idStr, - Location loc, PrefixedName elemName, PrefixedName attrName) - { - int hash = calcHash(idStr); - int index = (hash & mIndexMask); - ElementId id = mTable[index]; - - while (id != null) { - if (id.idMatches(idStr)) { // found existing one - return id; - } - id = id.nextColliding(); - } - - // Not found, need to create a placeholder... - - // But first, do we need more room? - if (mSize >= mSizeThreshold) { - rehash(); - // Index changes, for the new entr: - index = (hash & mIndexMask); - } - ++mSize; - - // Ok, then, let's create the entry - id = new ElementId(idStr, loc, false, elemName, attrName); - - // First, let's link it to Map; all ids have to be connected - id.setNextColliding(mTable[index]); - mTable[index] = id; - - // And then add the undefined entry at the end of list - if (mHead == null) { - mHead = mTail = id; - } else { - mTail.linkUndefined(id); - mTail = id; - } - return id; - } - - /** - * Method called when an id definition is encountered. If so, need - * to check if specified id entry (ref or definiton) exists. If not, - * need to add the definition marker. If it does exist, need to - * 'upgrade it', if it was a reference marker; otherwise need to - * just return the old entry, and expect caller to check for dups - * and report the error. - */ - public ElementId addDefined(char[] buffer, int start, int len, int hash, - Location loc, PrefixedName elemName, PrefixedName attrName) - { - int index = (hash & mIndexMask); - ElementId id = mTable[index]; - - while (id != null) { - if (id.idMatches(buffer, start, len)) { - break; - } - id = id.nextColliding(); - } - - /* Not found, can just add it to the Map; no need to add to the - * linked list as it's not undefined - */ - if (id == null) { - // First, do we need more room? - if (mSize >= mSizeThreshold) { - rehash(); - index = (hash & mIndexMask); - } - ++mSize; - String idStr = new String(buffer, start, len); - id = new ElementId(idStr, loc, true, elemName, attrName); - id.setNextColliding(mTable[index]); - mTable[index] = id; - } else { - /* If already defined, nothing additional to do (we could - * signal an error here, though... for now, we'll let caller - * do that - */ - if (id.isDefined()) { - ; - } else { - /* Not defined, just need to upgrade, and possibly remove from - * the linked list. - */ - id.markDefined(loc); - - /* Ok; if it was the first undefined, need to unlink it, as - * well as potentially next items. - */ - if (id == mHead) { - do { - mHead = mHead.nextUndefined(); - } while (mHead != null && mHead.isDefined()); - - // Did we clear up all undefined ids? - if (mHead == null) { - mTail = null; - } - } - } - } - - return id; - } - - public ElementId addDefined(String idStr, - Location loc, PrefixedName elemName, PrefixedName attrName) - { - int hash = calcHash(idStr); - int index = (hash & mIndexMask); - ElementId id = mTable[index]; - - while (id != null) { - if (id.idMatches(idStr)) { - break; - } - id = id.nextColliding(); - } - - /* Not found, can just add it to the Map; no need to add to the - * linked list as it's not undefined - */ - if (id == null) { - if (mSize >= mSizeThreshold) { // need more room - rehash(); - index = (hash & mIndexMask); - } - ++mSize; - id = new ElementId(idStr, loc, true, elemName, attrName); - id.setNextColliding(mTable[index]); - mTable[index] = id; - } else { - /* If already defined, nothing additional to do (we could - * signal an error here, though... for now, we'll let caller - * do that - */ - if (id.isDefined()) { - ; - } else { - /* Not defined, just need to upgrade, and possibly remove from - * the linked list. - */ - id.markDefined(loc); - - /* Ok; if it was the first undefined, need to unlink it, as - * well as potentially next items. - */ - if (id == mHead) { - do { - mHead = mHead.nextUndefined(); - } while (mHead != null && mHead.isDefined()); - if (mHead == null) { // cleared up all undefined ids? - mTail = null; - } - } - } - } - - return id; - } - - /** - * Implementation of a hashing method for variable length - * Strings. Most of the time intention is that this calculation - * is done by caller during parsing, not here; however, sometimes - * it needs to be done for parsed "String" too. - *

- * Note: identical to {@link com.ctc.wstx.util.SymbolTable#calcHash}, - * although not required to be. - * - * @param len Length of String; has to be at least 1 (caller guarantees - * this pre-condition) - */ - public static int calcHash(char[] buffer, int start, int len) - { - int hash = (int) buffer[0]; - for (int i = 1; i < len; ++i) { - hash = (hash * 31) + (int) buffer[i]; - } - return hash; - } - - public static int calcHash(String key) - { - int hash = (int) key.charAt(0); - for (int i = 1, len = key.length(); i < len; ++i) { - hash = (hash * 31) + (int) key.charAt(i); - - } - return hash; - } - - /* - ////////////////////////////////////////////////////////// - // Internal methods - ////////////////////////////////////////////////////////// - */ - - /** - * Method called when size (number of entries) of symbol table grows - * so big that load factor is exceeded. Since size has to remain - * power of two, arrays will then always be doubled. Main work - * is really redistributing old entries into new String/Bucket - * entries. - */ - private void rehash() - { - int size = mTable.length; - /* Let's grow aggressively; this should minimize number of - * resizes, while adding to mem usage. But since these Maps - * are never long-lived (only during parsing and validation of - * a single doc), that shouldn't greatly matter. - */ - int newSize = (size << 2); - ElementId[] oldSyms = mTable; - mTable = new ElementId[newSize]; - - // Let's update index mask, threshold, now (needed for rehashing) - mIndexMask = newSize - 1; - mSizeThreshold <<= 2; - - int count = 0; // let's do sanity check - - for (int i = 0; i < size; ++i) { - for (ElementId id = oldSyms[i]; id != null; ) { - ++count; - int index = calcHash(id.getId()) & mIndexMask; - ElementId nextIn = id.nextColliding(); - id.setNextColliding(mTable[index]); - mTable[index] = id; - id = nextIn; - } - } - - if (count != mSize) { - ExceptionUtil.throwInternal("on rehash(): had "+mSize+" entries; now have "+count+"."); - } - } -} diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/util/EmptyNamespaceContext.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/util/EmptyNamespaceContext.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/util/EmptyNamespaceContext.java 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/util/EmptyNamespaceContext.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,71 +0,0 @@ -package com.ctc.wstx.util; - -import java.io.Writer; -import java.util.Iterator; - -import javax.xml.namespace.NamespaceContext; -import javax.xml.stream.XMLStreamWriter; - -import org.codehaus.stax2.ri.EmptyIterator; - -/** - * Dummy {@link NamespaceContext} (and {@link BaseNsContext}) - * implementation that is usually used in - * non-namespace-aware mode. - *

- * Note: differs from Stax2 reference implementation's version - * slightly, since it needs to support Woodstox specific extensions - * for efficient namespace declaration serialization. - */ -public final class EmptyNamespaceContext - extends BaseNsContext -{ - final static EmptyNamespaceContext sInstance = new EmptyNamespaceContext(); - - private EmptyNamespaceContext() { } - - public static EmptyNamespaceContext getInstance() { return sInstance; } - - /* - ///////////////////////////////////////////// - // Extended API - ///////////////////////////////////////////// - */ - - public Iterator getNamespaces() { - return EmptyIterator.getInstance(); - } - - /** - * Method called by the matching start element class to - * output all namespace declarations active in current namespace - * scope, if any. - */ - public void outputNamespaceDeclarations(Writer w) - { - ; // nothing to output - } - - public void outputNamespaceDeclarations(XMLStreamWriter w) - { - ; // nothing to output - } - - /* - ///////////////////////////////////////////////// - // Template methods sub-classes need to implement - ///////////////////////////////////////////////// - */ - - public String doGetNamespaceURI(String prefix) { - return null; - } - - public String doGetPrefix(String nsURI) { - return null; - } - - public Iterator doGetPrefixes(String nsURI) { - return EmptyIterator.getInstance(); - } -} diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/util/ExceptionUtil.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/util/ExceptionUtil.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/util/ExceptionUtil.java 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/util/ExceptionUtil.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,72 +0,0 @@ -package com.ctc.wstx.util; - -public final class ExceptionUtil -{ - private ExceptionUtil() { } - - /** - * Method that can be used to convert any Throwable to a RuntimeException; - * conversion is only done for checked exceptions. - */ - public static void throwRuntimeException(Throwable t) - { - // Unchecked? Can re-throw as is - throwIfUnchecked(t); - // Otherwise, let's just change its type: - RuntimeException rex = new RuntimeException("[was "+t.getClass()+"] "+t.getMessage()); - // And indicate the root cause - setInitCause(rex, t); - throw rex; - } - - public static void throwAsIllegalArgument(Throwable t) - { - // Unchecked? Can re-throw as is - throwIfUnchecked(t); - // Otherwise, let's just change its type: - IllegalArgumentException rex = new IllegalArgumentException("[was "+t.getClass()+"] "+t.getMessage()); - // And indicate the root cause - setInitCause(rex, t); - throw rex; - } - - public static void throwIfUnchecked(Throwable t) - { - // If it's not checked, let's throw it as is - if (t instanceof RuntimeException) { - throw (RuntimeException) t; - } - if (t instanceof Error) { - throw (Error) t; - } - } - - /** - * This method is just added for convenience, and only to be used for - * assertion style of exceptions. For errors that actually occur, method - * with the string arg should be called instead. - */ - public static void throwGenericInternal() - { - throwInternal(null); - } - - public static void throwInternal(String msg) - { - if (msg == null) { - msg = "[no description]"; - } - throw new RuntimeException("Internal error: "+msg); - } - - public static void setInitCause(Throwable newT, Throwable rootT) - { - /* [WSTX-110]: Better make sure we do not already have - * a chained exception... - */ - if (newT.getCause() == null) { - newT.initCause(rootT); - } - } -} - diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/util/InternCache.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/util/InternCache.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/util/InternCache.java 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/util/InternCache.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,72 +0,0 @@ -package com.ctc.wstx.util; - -import java.util.LinkedHashMap; -import java.util.Map; - -/** - * Singleton class that implements "fast intern" functionality, essentially - * adding a layer that caches Strings that have been previously intern()ed, - * but that probably shouldn't be added to symbol tables. - * This is usually used by improving intern()ing of things like namespace - * URIs. - *

- * Note: that this class extends {@link LinkedHashMap} is an implementation - * detail -- no code should ever directly call Map methods. - */ -public final class InternCache extends LinkedHashMap // -{ - private static final long serialVersionUID = 1L; - - /** - * Let's create cache big enough to usually have enough space for - * all entries... (assuming NS URIs only) - */ - private final static int DEFAULT_SIZE = 64; - - /** - * Let's limit to hash area size of 1024. - */ - private final static int MAX_SIZE = 660; - - private final static InternCache sInstance = new InternCache(); - - private InternCache() { - /* Let's also try to seriously minimize collisions... since - * collisions are likely to be more costly here, with longer - * Strings; so let's use 2/3 ratio (67%) instead of default - * (75%) - */ - super(DEFAULT_SIZE, 0.6666f, false); - } - - public static InternCache getInstance() { - return sInstance; - } - - public String intern(String input) - { - String result; - - /* Let's split sync block to help in edge cases like - * [WSTX-220] - */ - synchronized (this) { - result = (String) get(input); - } - if (result == null) { - result = input.intern(); - synchronized (this) { - put(result, result); - } - } - return result; - } - - // We will force maximum size here (for [WSTX-237]) - //@Override protected boolean removeEldestEntry(Map.Entry eldest) - protected boolean removeEldestEntry(Map.Entry eldest) - { - return size() > MAX_SIZE; - } -} - diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/util/package.html libwoodstox-java-5.1.0/src/java/com/ctc/wstx/util/package.html --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/util/package.html 2012-04-24 04:38:21.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/util/package.html 1970-01-01 00:00:00.000000000 +0000 @@ -1,7 +0,0 @@ - -Contains utility classes that are not directly Woodstox specific, but are -for now only used by Woodstox. -

-Note that some of more generic classes may eventually be moved to more -generic packages under com.ctc package. - diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/util/PrefixedName.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/util/PrefixedName.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/util/PrefixedName.java 2012-04-24 04:38:20.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/util/PrefixedName.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,185 +0,0 @@ -/* Woodstox XML processor - * - * Copyright (c) 2004 Tatu Saloranta, tatu.saloranta@iki.fi - * - * Licensed under the License specified in file LICENSE, included with - * the source code. - * You may not use this file except in compliance with the License. - * - * 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 com.ctc.wstx.util; - -import javax.xml.namespace.QName; - -/** - * Simple key Object to be used for storing/accessing of potentially namespace - * scoped element and attribute names. - *

- * One important note about usage is that two of the name components (prefix - * and local name) HAVE to have been interned some way, as all comparisons - * are done using identity comparison; whereas URI is NOT necessarily - * interned. - *

- * Note that the main reason this class is mutable -- unlike most key classes - * -- is that this allows reusing key objects for access, as long as the code - * using it knows ramifications of trying to modify a key that's used - * in a data structure. - *

- * Note, too, that the hash code is cached as this class is mostly used as - * a Map key, and hash code is used a lot. - */ -public final class PrefixedName - implements Comparable // to allow alphabetic ordering -{ - private String mPrefix, mLocalName; - - volatile int mHash = 0; - - /* - /////////////////////////////////////////////////// - // Life-cycle - /////////////////////////////////////////////////// - */ - - public PrefixedName(String prefix, String localName) - { - mLocalName = localName; - mPrefix = (prefix != null && prefix.length() == 0) ? - null : prefix; - } - - public PrefixedName reset(String prefix, String localName) - { - mLocalName = localName; - mPrefix = (prefix != null && prefix.length() == 0) ? - null : prefix; - mHash = 0; - return this; - } - - public static PrefixedName valueOf(QName n) - { - return new PrefixedName(n.getPrefix(), n.getLocalPart()); - } - - /* - /////////////////////////////////////////////////// - // Accessors: - /////////////////////////////////////////////////// - */ - - public String getPrefix() { return mPrefix; } - - public String getLocalName() { return mLocalName; } - - /** - * @return True, if this attribute name would result in a namespace - * binding (ie. it's "xmlns" or starts with "xmlns:"). - */ - public boolean isaNsDeclaration() - { - if (mPrefix == null) { - return mLocalName == "xmlns"; - } - return mPrefix == "xmlns"; - } - - /** - * Method used to check for xml reserved attribute names, like - * "xml:space" and "xml:id". - *

- * Note: it is assumed that the passed-in localName is also - * interned. - */ - public boolean isXmlReservedAttr(boolean nsAware, String localName) - { - if (nsAware) { - if ("xml" == mPrefix) { - return mLocalName == localName; - } - } else { - if (mLocalName.length() == (4 + localName.length())) { - return (mLocalName.startsWith("xml:") - && mLocalName.endsWith(localName)); - } - } - return false; - } - - /* - /////////////////////////////////////////////////// - // Overridden standard methods: - /////////////////////////////////////////////////// - */ - - public String toString() - { - if (mPrefix == null || mPrefix.length() == 0) { - return mLocalName; - } - StringBuffer sb = new StringBuffer(mPrefix.length() + 1 + mLocalName.length()); - sb.append(mPrefix); - sb.append(':'); - sb.append(mLocalName); - return sb.toString(); - } - - public boolean equals(Object o) - { - if (o == this) { - return true; - } - if (!(o instanceof PrefixedName)) { // also filters out nulls - return false; - } - PrefixedName other = (PrefixedName) o; - - if (mLocalName != other.mLocalName) { // assumes equality - return false; - } - return (mPrefix == other.mPrefix); - } - - public int hashCode() { - int hash = mHash; - - if (hash == 0) { - hash = mLocalName.hashCode(); - if (mPrefix != null) { - hash ^= mPrefix.hashCode(); - } - mHash = hash; - } - return hash; - } - - public int compareTo(Object o) - { - PrefixedName other = (PrefixedName) o; - - // First, by prefix, then by local name: - String op = other.mPrefix; - - // Missing prefix is ordered before existing prefix - if (op == null || op.length() == 0) { - if (mPrefix != null && mPrefix.length() > 0) { - return 1; - } - } else if (mPrefix == null || mPrefix.length() == 0) { - return -1; - } else { - int result = mPrefix.compareTo(op); - if (result != 0) { - return result; - } - } - - return mLocalName.compareTo(other.mLocalName); - } -} diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/util/SimpleCache.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/util/SimpleCache.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/util/SimpleCache.java 2012-04-24 04:38:21.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/util/SimpleCache.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,59 +0,0 @@ -package com.ctc.wstx.util; - -import java.util.*; - -/** - * Simple Map implementation usable for caches where contents do not - * expire, but where size needs to remain bounded. - *

- * Note: we probably should use weak references, or something similar - * to limit maximum memory usage. This could be implemented in many - * ways, perhaps by using two areas: first, smaller one, with strong - * refs, and secondary bigger one that uses soft references. - */ -public final class SimpleCache -{ - protected final LimitMap mItems; - - protected final int mMaxSize; - - public SimpleCache(int maxSize) - { - mItems = new LimitMap(maxSize); - mMaxSize = maxSize; - } - - public Object find(Object key) { - return mItems.get(key); - } - - public void add(Object key, Object value) - { - mItems.put(key, value); - } - - /* - /////////////////////////////////////////////////////////////////////// - // Helper classes - /////////////////////////////////////////////////////////////////////// - */ - - final static class LimitMap - extends LinkedHashMap - { - private static final long serialVersionUID = 1L; - - protected final int mMaxSize; - - public LimitMap(int size) - { - super(size, 0.8f, true); - // Let's not allow silly low values... - mMaxSize = size; - } - - public boolean removeEldestEntry(Map.Entry eldest) { - return (size() >= mMaxSize); - } - } -} diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/util/StringUtil.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/util/StringUtil.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/util/StringUtil.java 2012-04-24 04:38:21.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/util/StringUtil.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,339 +0,0 @@ -package com.ctc.wstx.util; - -import java.util.Collection; -import java.util.Iterator; - -public final class StringUtil -{ - final static char CHAR_SPACE = ' '; // 0x0020 - private final static char INT_SPACE = 0x0020; - - static String sLF = null; - - public static String getLF() - { - String lf = sLF; - if (lf == null) { - try { - lf = (String) System.getProperty("line.separator"); - sLF = (lf == null) ? "\n" : lf; - } catch (Throwable t) { - // Doh.... whatever; most likely SecurityException - sLF = lf = "\n"; - } - } - return lf; - } - - public static void appendLF(StringBuffer sb) { - sb.append(getLF()); - } - - public static String concatEntries(Collection coll, String sep, String lastSep) { - if (lastSep == null) { - lastSep = sep; - } - int len = coll.size(); - StringBuffer sb = new StringBuffer(16 + (len << 3)); - Iterator it = coll.iterator(); - int i = 0; - while (it.hasNext()) { - if (i == 0) { - ; - } else if (i == (len - 1)) { - sb.append(lastSep); - } else { - sb.append(sep); - } - ++i; - sb.append(it.next()); - } - return sb.toString(); - } - - /** - * Method that will check character array passed, and remove all - * "extra" spaces (leading and trailing space), and normalize - * other white space (more than one consequtive space character - * replaced with a single space). - *

- * NOTE: we only remove explicit space characters (char code 0x0020); - * the reason being that other white space must have come from - * non-normalizable sources, ie. via entity expansion, and is thus - * not to be normalized - * - * @param buf Buffer that contains the String to check - * @param origStart Offset of the first character of the text to check - * in the buffer - * @param origEnd Offset of the character following the last character - * of the text (as per usual Java API convention) - * - * @return Normalized String, if any white space was removed or - * normalized; null if no changes were necessary. - */ - public static String normalizeSpaces(char[] buf, int origStart, int origEnd) - { - --origEnd; - - int start = origStart; - int end = origEnd; - - // First let's trim start... - while (start <= end && buf[start] == CHAR_SPACE) { - ++start; - } - // Was it all empty? - if (start > end) { - return ""; - } - - /* Nope, need to trim from the end then (note: it's known that char - * at index 'start' is not a space, at this point) - */ - while (end > start && buf[end] == CHAR_SPACE) { - --end; - } - - /* Ok, may have changes or not: now need to normalize - * intermediate duplicate spaces. We also now that the - * first and last characters can not be spaces. - */ - int i = start+1; - - while (i < end) { - if (buf[i] == CHAR_SPACE) { - if (buf[i+1] == CHAR_SPACE) { - break; - } - // Nah; no hole for these 2 chars! - i += 2; - } else { - ++i; - } - } - - // Hit the end? - if (i >= end) { - // Any changes? - if (start == origStart && end == origEnd) { - return null; // none - } - return new String(buf, start, (end-start)+1); - } - - /* Nope, got a hole, need to constuct the damn thing. Shouldn't - * happen too often... so let's just use StringBuffer() - */ - StringBuffer sb = new StringBuffer(end-start); // can't be longer - sb.append(buf, start, i-start); // won't add the starting space - - while (i <= end) { - char c = buf[i++]; - if (c == CHAR_SPACE) { - sb.append(CHAR_SPACE); - // Need to skip dups - while (true) { - c = buf[i++]; - if (c != CHAR_SPACE) { - sb.append(c); - break; - } - } - } else { - sb.append(c); - } - } - - return sb.toString(); - } - - public static boolean isAllWhitespace(String str) - { - for (int i = 0, len = str.length(); i < len; ++i) { - if (str.charAt(i) > CHAR_SPACE) { - return false; - } - } - return true; - } - - public static boolean isAllWhitespace(char[] ch, int start, int len) - { - len += start; - for (; start < len; ++start) { - if (ch[start] > CHAR_SPACE) { - return false; - } - } - return true; - } - - /** - * Internal constant used to denote END-OF-STRING - */ - private final static int EOS = 0x10000; - - /** - * Method that implements a loose String compairon for encoding - * Strings. It will work like {@link String#equalsIgnoreCase}, - * except that it will also ignore all hyphen, underscore and - * space characters. - */ - public static boolean equalEncodings(String str1, String str2) - { - final int len1 = str1.length(); - final int len2 = str2.length(); - - // Need to loop completely over both Strings - for (int i1 = 0, i2 = 0; i1 < len1 || i2 < len2; ) { - int c1 = (i1 >= len1) ? EOS : str1.charAt(i1++); - int c2 = (i2 >= len2) ? EOS : str2.charAt(i2++); - - // Can first do a quick comparison (usually they are equal) - if (c1 == c2) { - continue; - } - - // if not equal, maybe there are WS/hyphen/underscores to skip - while (c1 <= INT_SPACE || c1 == '_' || c1 == '-') { - c1 = (i1 >= len1) ? EOS : str1.charAt(i1++); - } - while (c2 <= INT_SPACE || c2 == '_' || c2 == '-') { - c2 = (i2 >= len2) ? EOS : str2.charAt(i2++); - } - // Ok, how about case differences, then? - if (c1 != c2) { - // If one is EOF, can't match (one is substring of the other) - if (c1 == EOS || c2 == EOS) { - return false; - } - if (c1 < 127) { // ascii is easy... - if (c1 <= 'Z' && c1 >= 'A') { - c1 = c1 + ('a' - 'A'); - } - } else { - c1 = Character.toLowerCase((char)c1); - } - if (c2 < 127) { // ascii is easy... - if (c2 <= 'Z' && c2 >= 'A') { - c2 = c2 + ('a' - 'A'); - } - } else { - c2 = Character.toLowerCase((char)c2); - } - if (c1 != c2) { - return false; - } - } - } - - // If we got this far, we are ok as long as we got through it all - return true; - } - - public static boolean encodingStartsWith(String enc, String prefix) - { - int len1 = enc.length(); - int len2 = prefix.length(); - - int i1 = 0, i2 = 0; - - // Need to loop completely over both Strings - while (i1 < len1 || i2 < len2) { - int c1 = (i1 >= len1) ? EOS : enc.charAt(i1++); - int c2 = (i2 >= len2) ? EOS : prefix.charAt(i2++); - - // Can first do a quick comparison (usually they are equal) - if (c1 == c2) { - continue; - } - - // if not equal, maybe there are WS/hyphen/underscores to skip - while (c1 <= CHAR_SPACE || c1 == '_' || c1 == '-') { - c1 = (i1 >= len1) ? EOS : enc.charAt(i1++); - } - while (c2 <= CHAR_SPACE || c2 == '_' || c2 == '-') { - c2 = (i2 >= len2) ? EOS : prefix.charAt(i2++); - } - // Ok, how about case differences, then? - if (c1 != c2) { - if (c2 == EOS) { // Prefix done, good! - return true; - } - if (c1 == EOS) { // Encoding done, not good - return false; - } - if (Character.toLowerCase((char)c1) != Character.toLowerCase((char)c2)) { - return false; - } - } - } - - // Ok, prefix was exactly the same as encoding... that's fine - return true; - } - - /** - * Method that will remove all non-alphanumeric characters, and optionally - * upper-case included letters, from the given String. - */ - public static String trimEncoding(String str, boolean upperCase) - { - int i = 0; - int len = str.length(); - - // Let's first check if String is fine as is: - for (; i < len; ++i) { - char c = str.charAt(i); - if (c <= CHAR_SPACE || !Character.isLetterOrDigit(c)) { - break; - } - } - - if (i == len) { - return str; - } - - // Nope: have to trim it - StringBuffer sb = new StringBuffer(); - if (i > 0) { - sb.append(str.substring(0, i)); - } - for (; i < len; ++i) { - char c = str.charAt(i); - if (c > CHAR_SPACE && Character.isLetterOrDigit(c)) { - if (upperCase) { - c = Character.toUpperCase(c); - } - sb.append(c); - } - } - - return sb.toString(); - } - - public static boolean matches(String str, char[] cbuf, int offset, int len) - { - if (str.length() != len) { - return false; - } - for (int i = 0; i < len; ++i) { - if (str.charAt(i) != cbuf[offset+i]) { - return false; - } - } - return true; - } - - /** - *

- * Note that it is assumed that any "weird" white space - * (xml 1.1 LSEP and NEL) have been replaced by canonical - * alternatives (linefeed for element content, regular space - * for attributes) - */ - public final static boolean isSpace(char c) - { - return ((int) c) <= 0x0020; - } -} diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/util/StringVector.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/util/StringVector.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/util/StringVector.java 2012-04-24 04:38:21.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/util/StringVector.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,244 +0,0 @@ -package com.ctc.wstx.util; - -/** - * Data container similar {@link java.util.List} (from storage perspective), - * but that can be used in multiple ways. For some uses it acts more like - * type-safe String list/vector; for others as order associative list of - * String-to-String mappings. - */ -public final class StringVector -{ - private String[] mStrings; - - private int mSize; - - /* - /////////////////////////////////////////////////////// - // Life-cycle: - /////////////////////////////////////////////////////// - */ - - public StringVector(int initialCount) { - mStrings = new String[initialCount]; - } - - /* - /////////////////////////////////////////////////////// - // Basic accessors - /////////////////////////////////////////////////////// - */ - - public int size() { return mSize; } - - public boolean isEmpty() { return mSize == 0; } - - public String getString(int index) { - if (index < 0 || index >= mSize) { - throw new IllegalArgumentException("Index "+index+" out of valid range; current size: "+mSize+"."); - } - return mStrings[index]; - } - - public String getLastString() { - if (mSize < 1) { - throw new IllegalStateException("getLastString() called on empty StringVector."); - } - return mStrings[mSize-1]; - } - - public String[] getInternalArray() { - return mStrings; - } - - public String[] asArray() { - String[] strs = new String[mSize]; - System.arraycopy(mStrings, 0, strs, 0, mSize); - return strs; - } - - public boolean containsInterned(String value) { - String[] str = mStrings; - for (int i = 0, len = mSize; i < len; ++i) { - if (str[i] == value) { - return true; - } - } - return false; - } - - /* - /////////////////////////////////////////////////////// - // Mutators: - /////////////////////////////////////////////////////// - */ - - public void addString(String str) { - if (mSize == mStrings.length) { - String[] old = mStrings; - int oldSize = old.length; - mStrings = new String[oldSize + (oldSize << 1)]; - System.arraycopy(old, 0, mStrings, 0, oldSize); - } - mStrings[mSize++] = str; - } - - public void addStrings(String str1, String str2) { - if ((mSize + 2) > mStrings.length) { - String[] old = mStrings; - int oldSize = old.length; - mStrings = new String[oldSize + (oldSize << 1)]; - System.arraycopy(old, 0, mStrings, 0, oldSize); - } - mStrings[mSize] = str1; - mStrings[mSize+1] = str2; - mSize += 2; - } - - public void setString(int index, String str) { - mStrings[index] = str; - } - - public void clear(boolean removeRefs) { - if (removeRefs) { - for (int i = 0, len = mSize; i < len; ++i) { - mStrings[i] = null; - } - } - mSize = 0; - } - - public String removeLast() { - String result = mStrings[--mSize]; - mStrings[mSize] = null; - return result; - } - - public void removeLast(int count) { - while (--count >= 0) { - mStrings[--mSize] = null; - } - } - - /* - /////////////////////////////////////////////////////// - // Specialized "map accessors": - /////////////////////////////////////////////////////// - */ - - /** - * Specialized access method; treats vector as a Map, with 2 Strings - * per entry; first one being key, second value. Further, keys are - * assumed to be canonicalized with passed in key (ie. either intern()ed, - * or resolved from symbol table). - * Starting from the - * end (assuming even number of entries), tries to find an entry with - * matching key, and if so, returns value. - */ - public String findLastFromMap(String key) { - int index = mSize; - while ((index -= 2) >= 0) { - if (mStrings[index] == key) { - return mStrings[index+1]; - } - } - return null; - } - - public String findLastNonInterned(String key) - { - int index = mSize; - while ((index -= 2) >= 0) { - String curr = mStrings[index]; - if (curr == key || (curr != null && curr.equals(key))) { - return mStrings[index+1]; - } - } - return null; - } - - public int findLastIndexNonInterned(String key) { - int index = mSize; - while ((index -= 2) >= 0) { - String curr = mStrings[index]; - if (curr == key || (curr != null && curr.equals(key))) { - return index; - } - } - return -1; - } - - public String findLastByValueNonInterned(String value) { - for (int index = mSize-1; index > 0; index -= 2) { - String currVal = mStrings[index]; - if (currVal == value || (currVal != null && currVal.equals(value))) { - return mStrings[index-1]; - } - } - return null; - } - - public int findLastIndexByValueNonInterned(String value) { - for (int index = mSize-1; index > 0; index -= 2) { - String currVal = mStrings[index]; - if (currVal == value || (currVal != null && currVal.equals(value))) { - return index-1; - } - } - return -1; - } - - /* - // Not needed any more - public Iterator findAllByValueNonInterned(String value) { - String first = null; - ArrayList all = null; - for (int index = mSize-1; index > 0; index -= 2) { - String currVal = mStrings[index]; - if (currVal == value || (currVal != null && currVal.equals(value))) { - if (first == null) { - first = mStrings[index-1]; - } else { - if (all == null) { - all = new ArrayList(); - all.add(first); - } - all.add(mStrings[index-1]); - } - } - } - if (all != null) { - return all.iterator(); - } - if (first != null) { - return new SingletonIterator(first); - } - return EmptyIterator.getInstance(); - } - */ - - /* - /////////////////////////////////////////////////////// - // Other methods - /////////////////////////////////////////////////////// - */ - - public String toString() { - StringBuffer sb = new StringBuffer(mSize * 16); - sb.append("[(size = "); - sb.append(mSize); - sb.append(" ) "); - for (int i = 0; i < mSize; ++i) { - if (i > 0) { - sb.append(", "); - } - sb.append('"'); - sb.append(mStrings[i]); - sb.append('"'); - - sb.append(" == "); - sb.append(Integer.toHexString(System.identityHashCode(mStrings[i]))); - } - sb.append(']'); - return sb.toString(); - } -} diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/util/SymbolTable.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/util/SymbolTable.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/util/SymbolTable.java 2012-04-24 04:38:21.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/util/SymbolTable.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,731 +0,0 @@ -/* Woodstox XML processor - * - * Copyright (c) 2004- Tatu Saloranta, tatu.saloranta@iki.fi - * - * Licensed under the License specified in the file LICENSE which is - * included with the source code. - * You may not use this file except in compliance with the License. - * - * 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 com.ctc.wstx.util; - -/** - * This class is a kind of specialized type-safe Map, from char array to - * String value. Specialization means that in addition to type-safety - * and specific access patterns (key char array, Value optionally interned - * String; values added on access if necessary), and that instances are - * meant to be used concurrently, but by using well-defined mechanisms - * to obtain such concurrently usable instances. Main use for the class - * is to store symbol table information for things like compilers and - * parsers; especially when number of symbols (keywords) is limited. - *

- * For optimal performance, usage pattern should be one where matches - * should be very common (esp. after "warm-up"), and as with most hash-based - * maps/sets, that hash codes are uniformly distributed. Also, collisions - * are slightly more expensive than with HashMap or HashSet, since hash codes - * are not used in resolving collisions; that is, equals() comparison is - * done with all symbols in same bucket index.
- * Finally, rehashing is also more expensive, as hash codes are not - * stored; rehashing requires all entries' hash codes to be recalculated. - * Reason for not storing hash codes is reduced memory usage, hoping - * for better memory locality. - *

- * Usual usage pattern is to create a single "master" instance, and either - * use that instance in sequential fashion, or to create derived "child" - * instances, which after use, are asked to return possible symbol additions - * to master instance. In either case benefit is that symbol table gets - * initialized so that further uses are more efficient, as eventually all - * symbols needed will already be in symbol table. At that point no more - * Symbol String allocations are needed, nor changes to symbol table itself. - *

- * Note that while individual SymbolTable instances are NOT thread-safe - * (much like generic collection classes), concurrently used "child" - * instances can be freely used without synchronization. However, using - * master table concurrently with child instances can only be done if - * access to master instance is read-only (ie. no modifications done). - */ - -public class SymbolTable { - - /** - * Default initial table size; no need to make it miniscule, due - * to couple of things: first, overhead of array reallocation - * is significant, - * and second, overhead of rehashing is also non-negligible. - *

- * Let's use 128 as the default; it allows for up to 96 symbols, - * and uses about 512 bytes on 32-bit machines. - */ - protected static final int DEFAULT_TABLE_SIZE = 128; - - protected static final float DEFAULT_FILL_FACTOR = 0.75f; - - protected static final String EMPTY_STRING = ""; - - /* - //////////////////////////////////////// - // Configuration: - //////////////////////////////////////// - */ - - /** - * Flag that determines whether Strings to be added need to be - * interned before being added or not. Forcing intern()ing will add - * some overhead when adding new Strings, but may be beneficial if such - * Strings are generally used by other parts of system. Note that even - * without interning, all returned String instances are guaranteed - * to be comparable with equality (==) operator; it's just that such - * guarantees are not made for Strings other classes return. - */ - protected boolean mInternStrings; - - /* - //////////////////////////////////////// - // Actual symbol table data: - //////////////////////////////////////// - */ - - /** - * Primary matching symbols; it's expected most match occur from - * here. - */ - protected String[] mSymbols; - - /** - * Overflow buckets; if primary doesn't match, lookup is done - * from here. - *

- * Note: Number of buckets is half of number of symbol entries, on - * assumption there's less need for buckets. - */ - protected Bucket[] mBuckets; - - /** - * Current size (number of entries); needed to know if and when - * rehash. - */ - protected int mSize; - - /** - * Limit that indicates maximum size this instance can hold before - * it needs to be expanded and rehashed. Calculated using fill - * factor passed in to constructor. - */ - protected int mSizeThreshold; - - /** - * Mask used to get index from hash values; equal to - * mBuckets.length - 1, when mBuckets.length is - * a power of two. - */ - protected int mIndexMask; - - /* - //////////////////////////////////////// - // Information about concurrency - //////////////////////////////////////// - */ - - /** - * Version of this table instance; used when deriving new concurrently - * used versions from existing 'master' instance. - */ - protected int mThisVersion; - - /** - * Flag that indicates if any changes have been made to the data; - * used to both determine if bucket array needs to be copied when - * (first) change is made, and potentially if updated bucket list - * is to be resync'ed back to master instance. - */ - protected boolean mDirty; - - /* - //////////////////////////////////////// - // Life-cycle: - //////////////////////////////////////// - */ - - /** - * Method for constructing a master symbol table instance; this one - * will create master instance with default size, and with interning - * enabled. - */ - public SymbolTable() { - this(true); - } - - /** - * Method for constructing a master symbol table instance. - */ - public SymbolTable(boolean internStrings) { - this(internStrings, DEFAULT_TABLE_SIZE); - } - - /** - * Method for constructing a master symbol table instance. - */ - public SymbolTable(boolean internStrings, int initialSize) { - this(internStrings, initialSize, DEFAULT_FILL_FACTOR); - } - - /** - * Main method for constructing a master symbol table instance; will - * be called by other public constructors. - * - * @param internStrings Whether Strings to add are intern()ed or not - * @param initialSize Minimum initial size for bucket array; internally - * will always use a power of two equal to or bigger than this value. - * @param fillFactor Maximum fill factor allowed for bucket table; - * when more entries are added, table will be expanded. - */ - public SymbolTable(boolean internStrings, int initialSize, - float fillFactor) - { - mInternStrings = internStrings; - // Let's start versions from 1 - mThisVersion = 1; - // And we'll also set flags so no copying of buckets is needed: - mDirty = true; - - // No point in requesting funny initial sizes... - if (initialSize < 1) { - throw new IllegalArgumentException("Can not use negative/zero initial size: "+initialSize); - } - /* Initial size has to be a power of two. Also, let's not honour - * sizes that are ridiculously small... - */ - { - int currSize = 4; - while (currSize < initialSize) { - currSize += currSize; - } - initialSize = currSize; - } - - mSymbols = new String[initialSize]; - mBuckets = new Bucket[initialSize >> 1]; - // Mask is easy to calc for powers of two. - mIndexMask = initialSize - 1; - mSize = 0; - - // Sanity check for fill factor: - if (fillFactor < 0.01f) { - throw new IllegalArgumentException("Fill factor can not be lower than 0.01."); - } - if (fillFactor > 10.0f) { // just to catch stupid values, ie. useless from performance perspective - throw new IllegalArgumentException("Fill factor can not be higher than 10.0."); - } - mSizeThreshold = (int) (initialSize * fillFactor + 0.5); - } - - /** - * Internal constructor used when creating child instances. - */ - private SymbolTable(boolean internStrings, String[] symbols, - Bucket[] buckets, int size, int sizeThreshold, - int indexMask, int version) - { - mInternStrings = internStrings; - mSymbols = symbols; - mBuckets = buckets; - mSize = size; - mSizeThreshold = sizeThreshold; - mIndexMask = indexMask; - mThisVersion = version; - - // Need to make copies of arrays, if/when adding new entries - mDirty = false; - } - - /** - * "Factory" method; will create a new child instance of this symbol - * table. It will be a copy-on-write instance, ie. it will only use - * read-only copy of parent's data, but when changes are needed, a - * copy will be created. - *

- * Note: while this method is synchronized, it is generally not - * safe to both use makeChild/mergeChild, AND to use instance - * actively. Instead, a separate 'root' instance should be used - * on which only makeChild/mergeChild are called, but instance itself - * is not used as a symbol table. - */ - public synchronized SymbolTable makeChild() { - return new SymbolTable(mInternStrings, mSymbols, mBuckets, - mSize, mSizeThreshold, mIndexMask, - mThisVersion+1); - } - - /** - * Method that allows contents of child table to potentially be - * "merged in" with contents of this symbol table. - *

- * Note that caller has to make sure symbol table passed in is - * really a child or sibling of this symbol table. - */ - public synchronized void mergeChild(SymbolTable child) - { - // Let's do a basic sanity check first: - if (child.size() <= size()) { // nothing to add - return; - } - - // Okie dokie, let's get the data in! - mSymbols = child.mSymbols; - mBuckets = child.mBuckets; - mSize = child.mSize; - mSizeThreshold = child.mSizeThreshold; - mIndexMask = child.mIndexMask; - mThisVersion++; // to prevent other children from overriding - - // Dirty flag... well, let's just clear it, to force copying just - // in case. Shouldn't really matter, for master tables. - mDirty = false; - - /* However, we have to mark child as dirty, so that it will not - * be modifying arrays we "took over" (since child may have - * returned an updated table before it stopped fully using - * the SymbolTable: for example, it may still use it for - * parsing PI targets in epilog) - */ - child.mDirty = false; - } - - /* - //////////////////////////////////////////////////// - // Public API, configuration - //////////////////////////////////////////////////// - */ - - public void setInternStrings(boolean state) { - mInternStrings = state; - } - - /* - //////////////////////////////////////////////////// - // Public API, generic accessors: - //////////////////////////////////////////////////// - */ - - public int size() { return mSize; } - - public int version() { return mThisVersion; } - - public boolean isDirty() { return mDirty; } - - public boolean isDirectChildOf(SymbolTable t) - { - /* Actually, this doesn't really prove it is a child (would have to - * use sequence number, or identityHash to really prove it), but - * it's good enough if relationship is known to exist. - */ - /* (for real check, one would need to child/descendant stuff; or - * at least an identity hash... or maybe even just a _static_ global - * counter for instances... maybe that would actually be worth - * doing?) - */ - if (mThisVersion == (t.mThisVersion + 1)) { - return true; - } - return false; - } - - /* - //////////////////////////////////////////////////// - // Public API, accessing symbols: - //////////////////////////////////////////////////// - */ - - /** - * Main access method; will check if actual symbol String exists; - * if so, returns it; if not, will create, add and return it. - * - * @return The symbol matching String in input array - */ - /* - public String findSymbol(char[] buffer, int start, int len) - { - return findSymbol(buffer, start, len, calcHash(buffer, start, len)); - } - */ - - public String findSymbol(char[] buffer, int start, int len, int hash) - { - // Sanity check: - if (len < 1) { - return EMPTY_STRING; - } - - hash &= mIndexMask; - - String sym = mSymbols[hash]; - - // Optimal case; checking existing primary symbol for hash index: - if (sym != null) { - // Let's inline primary String equality checking: - if (sym.length() == len) { - int i = 0; - do { - if (sym.charAt(i) != buffer[start+i]) { - break; - } - } while (++i < len); - // Optimal case; primary match found - if (i == len) { - return sym; - } - } - // How about collision bucket? - Bucket b = mBuckets[hash >> 1]; - if (b != null) { - sym = b.find(buffer, start, len); - if (sym != null) { - return sym; - } - } - } - - // Need to expand? - if (mSize >= mSizeThreshold) { - rehash(); - /* Need to recalc hash; rare occurence (index mask has been - * recalculated as part of rehash) - */ - hash = calcHash(buffer, start, len) & mIndexMask; - } else if (!mDirty) { - // Or perhaps we need to do copy-on-write? - copyArrays(); - mDirty = true; - } - ++mSize; - - String newSymbol = new String(buffer, start, len); - if (mInternStrings) { - newSymbol = newSymbol.intern(); - } - // Ok; do we need to add primary entry, or a bucket? - if (mSymbols[hash] == null) { - mSymbols[hash] = newSymbol; - } else { - int bix = hash >> 1; - mBuckets[bix] = new Bucket(newSymbol, mBuckets[bix]); - } - - return newSymbol; - } - - /** - * Similar to {link #findSymbol}, but will not add passed in symbol - * if it is not in symbol table yet. - */ - public String findSymbolIfExists(char[] buffer, int start, int len, int hash) - { - // Sanity check: - if (len < 1) { - return EMPTY_STRING; - } - hash &= mIndexMask; - - String sym = mSymbols[hash]; - // Optimal case; checking existing primary symbol for hash index: - if (sym != null) { - // Let's inline primary String equality checking: - if (sym.length() == len) { - int i = 0; - do { - if (sym.charAt(i) != buffer[start+i]) { - break; - } - } while (++i < len); - // Optimal case; primary match found - if (i == len) { - return sym; - } - } - // How about collision bucket? - Bucket b = mBuckets[hash >> 1]; - if (b != null) { - sym = b.find(buffer, start, len); - if (sym != null) { - return sym; - } - } - } - return null; - } - - /** - * Similar to to {@link #findSymbol(char[],int,int,int)}; used to either - * do potentially cheap intern() (if table already has intern()ed version), - * or to pre-populate symbol table with known values. - */ - public String findSymbol(String str) - { - int len = str.length(); - // Sanity check: - if (len < 1) { - return EMPTY_STRING; - } - - int index = calcHash(str) & mIndexMask; - String sym = mSymbols[index]; - - // Optimal case; checking existing primary symbol for hash index: - if (sym != null) { - // Let's inline primary String equality checking: - if (sym.length() == len) { - int i = 0; - for (; i < len; ++i) { - if (sym.charAt(i) != str.charAt(i)) { - break; - } - } - // Optimal case; primary match found - if (i == len) { - return sym; - } - } - // How about collision bucket? - Bucket b = mBuckets[index >> 1]; - if (b != null) { - sym = b.find(str); - if (sym != null) { - return sym; - } - } - } - - // Need to expand? - if (mSize >= mSizeThreshold) { - rehash(); - /* Need to recalc hash; rare occurence (index mask has been - * recalculated as part of rehash) - */ - index = calcHash(str) & mIndexMask; - } else if (!mDirty) { - // Or perhaps we need to do copy-on-write? - copyArrays(); - mDirty = true; - } - ++mSize; - - if (mInternStrings) { - str = str.intern(); - } - // Ok; do we need to add primary entry, or a bucket? - if (mSymbols[index] == null) { - mSymbols[index] = str; - } else { - int bix = index >> 1; - mBuckets[bix] = new Bucket(str, mBuckets[bix]); - } - - return str; - } - - /** - * Implementation of a hashing method for variable length - * Strings. Most of the time intention is that this calculation - * is done by caller during parsing, not here; however, sometimes - * it needs to be done for parsed "String" too. - * - * @param len Length of String; has to be at least 1 (caller guarantees - * this pre-condition) - */ - public static int calcHash(char[] buffer, int start, int len) { - int hash = (int) buffer[0]; - for (int i = 1; i < len; ++i) { - hash = (hash * 31) + (int) buffer[i]; - } - return hash; - } - - public static int calcHash(String key) { - int hash = (int) key.charAt(0); - for (int i = 1, len = key.length(); i < len; ++i) { - hash = (hash * 31) + (int) key.charAt(i); - - } - return hash; - } - - /* - ////////////////////////////////////////////////////////// - // Internal methods - ////////////////////////////////////////////////////////// - */ - - /** - * Method called when copy-on-write is needed; generally when first - * change is made to a derived symbol table. - */ - private void copyArrays() { - String[] oldSyms = mSymbols; - int size = oldSyms.length; - mSymbols = new String[size]; - System.arraycopy(oldSyms, 0, mSymbols, 0, size); - Bucket[] oldBuckets = mBuckets; - size = oldBuckets.length; - mBuckets = new Bucket[size]; - System.arraycopy(oldBuckets, 0, mBuckets, 0, size); - } - - /** - * Method called when size (number of entries) of symbol table grows - * so big that load factor is exceeded. Since size has to remain - * power of two, arrays will then always be doubled. Main work - * is really redistributing old entries into new String/Bucket - * entries. - */ - private void rehash() - { - int size = mSymbols.length; - int newSize = size + size; - String[] oldSyms = mSymbols; - Bucket[] oldBuckets = mBuckets; - mSymbols = new String[newSize]; - mBuckets = new Bucket[newSize >> 1]; - // Let's update index mask, threshold, now (needed for rehashing) - mIndexMask = newSize - 1; - mSizeThreshold += mSizeThreshold; - - int count = 0; // let's do sanity check - - /* Need to do two loops, unfortunately, since spillover area is - * only half the size: - */ - for (int i = 0; i < size; ++i) { - String symbol = oldSyms[i]; - if (symbol != null) { - ++count; - int index = calcHash(symbol) & mIndexMask; - if (mSymbols[index] == null) { - mSymbols[index] = symbol; - } else { - int bix = index >> 1; - mBuckets[bix] = new Bucket(symbol, mBuckets[bix]); - } - } - } - - size >>= 1; - for (int i = 0; i < size; ++i) { - Bucket b = oldBuckets[i]; - while (b != null) { - ++count; - String symbol = b.getSymbol(); - int index = calcHash(symbol) & mIndexMask; - if (mSymbols[index] == null) { - mSymbols[index] = symbol; - } else { - int bix = index >> 1; - mBuckets[bix] = new Bucket(symbol, mBuckets[bix]); - } - b = b.getNext(); - } - } - - if (count != mSize) { - throw new IllegalStateException("Internal error on SymbolTable.rehash(): had "+mSize+" entries; now have "+count+"."); - } - } - - /* - ////////////////////////////////////////////////////////// - // Test/debug support: - ////////////////////////////////////////////////////////// - */ - - public double calcAvgSeek() { - int count = 0; - - for (int i = 0, len = mSymbols.length; i < len; ++i) { - if (mSymbols[i] != null) { - ++count; - } - } - - for (int i = 0, len = mBuckets.length; i < len; ++i) { - Bucket b = mBuckets[i]; - int cost = 2; - while (b != null) { - count += cost; - ++cost; - b = b.getNext(); - } - } - - return ((double) count) / ((double) mSize); - } - - /* - ////////////////////////////////////////////////////////// - // Bucket class - ////////////////////////////////////////////////////////// - */ - - /** - * This class is a symbol table entry. Each entry acts as a node - * in a linked list. - */ - static final class Bucket { - private final String mSymbol; - private final Bucket mNext; - - public Bucket(String symbol, Bucket next) { - mSymbol = symbol; - mNext = next; - } - - public String getSymbol() { return mSymbol; } - public Bucket getNext() { return mNext; } - - public String find(char[] buf, int start, int len) { - String sym = mSymbol; - Bucket b = mNext; - - while (true) { // Inlined equality comparison: - if (sym.length() == len) { - int i = 0; - do { - if (sym.charAt(i) != buf[start+i]) { - break; - } - } while (++i < len); - if (i == len) { - return sym; - } - } - if (b == null) { - break; - } - sym = b.getSymbol(); - b = b.getNext(); - } - return null; - } - - public String find(String str) { - String sym = mSymbol; - Bucket b = mNext; - - while (true) { - if (sym.equals(str)) { - return sym; - } - if (b == null) { - break; - } - sym = b.getSymbol(); - b = b.getNext(); - } - return null; - } - } -} diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/util/TextAccumulator.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/util/TextAccumulator.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/util/TextAccumulator.java 2012-04-24 04:38:21.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/util/TextAccumulator.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,75 +0,0 @@ -package com.ctc.wstx.util; - -/** - * Simple utility class used to efficiently accumulate and concatenate - * text passed in various forms - */ -public final class TextAccumulator -{ - private String mText = null; - - /* !!! JDK 1.5: when we can upgrade to Java 5, can convert - * to using StringBuilder instead. - */ - private StringBuffer mBuilder = null; - - public TextAccumulator() { } - - public boolean hasText() { - return (mBuilder != null) || (mText != null); - } - - public void addText(String text) - { - int len = text.length(); - if (len > 0) { - // Any prior text? - if (mText != null) { - mBuilder = new StringBuffer(mText.length() + len); - mBuilder.append(mText); - mText = null; - } - if (mBuilder != null) { - mBuilder.append(text); - } else { - mText = text; - } - } - } - - public void addText(char[] buf, int start, int end) - { - int len = end-start; - if (len > 0) { - // Any prior text? - if (mText != null) { - mBuilder = new StringBuffer(mText.length() + len); - mBuilder.append(mText); - mText = null; - } else if (mBuilder == null) { - /* more efficient to use a builder than a string; and although - * could use a char array, StringBuilder has the benefit of - * being able to share the array, eventually. - */ - mBuilder = new StringBuffer(len); - } - mBuilder.append(buf, start, end-start); - } - } - - public String getAndClear() - { - String result; - - if (mText != null) { - result = mText; - mText = null; - } else if (mBuilder != null) { - result = mBuilder.toString(); - mBuilder = null; - } else { - result = ""; - } - return result; - } -} diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/util/TextBuffer.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/util/TextBuffer.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/util/TextBuffer.java 2012-04-24 04:38:21.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/util/TextBuffer.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,1406 +0,0 @@ -package com.ctc.wstx.util; - -import java.io.*; -import java.util.ArrayList; -import javax.xml.stream.Location; -import javax.xml.stream.XMLStreamException; - -import org.xml.sax.ContentHandler; -import org.xml.sax.SAXException; -import org.xml.sax.ext.LexicalHandler; - -import org.codehaus.stax2.typed.Base64Variant; -import org.codehaus.stax2.typed.TypedArrayDecoder; -import org.codehaus.stax2.typed.TypedValueDecoder; -import org.codehaus.stax2.typed.TypedXMLStreamException; -import org.codehaus.stax2.validation.XMLValidator; - -import org.codehaus.stax2.ri.typed.CharArrayBase64Decoder; - -import com.ctc.wstx.api.ReaderConfig; -import com.ctc.wstx.dtd.DTDEventListener; -import com.ctc.wstx.sr.InputProblemReporter; -import com.ctc.wstx.util.StringUtil; - -/** - * TextBuffer is a class similar to {@link StringBuffer}, with - * following differences: - *

    - *
  • TextBuffer uses segments character arrays, to avoid having - * to do additional array copies when array is not big enough. This - * means that only reallocating that is necessary is done only once -- - * if and when caller - * wants to access contents in a linear array (char[], String). - *
  • - *
  • TextBuffer is not synchronized. - *
  • - *
- *

- * Over time more and more cruft has accumulated here, mostly to - * support efficient access to collected text. Since access is - * easiest to do efficiently using callbacks, this class now needs - * to known interfaces of SAX classes and validators. - *

- * Notes about usage: for debugging purposes, it's suggested to use - * {@link #toString} method, as opposed to - * {@link #contentsAsArray} or {@link #contentsAsString}. Internally - * resulting code paths may or may not be different, WRT caching. - * - * @author Tatu Saloranta - */ -public final class TextBuffer -{ - /* 23-Mar-2006, TSa: Memory buffer clearing is a significant overhead - * for small documents, no need to use huge buffer -- it will expand - * as necessary for larger docs, but commonly text segments just - * aren't that long. - */ - /** - * Size of the first text segment buffer to allocate; need not contain - * the biggest segment, since new ones will get allocated as needed. - * However, it's sensible to use something that often is big enough - * to contain segments. - */ - final static int DEF_INITIAL_BUFFER_SIZE = 500; // 1k - - /** - * We will also restrict maximum length of individual segments - * to allocate (not including cases where we must return a single - * segment). Value is somewhat arbitrary, let's use it so that - * memory used is no more than 1/2 megabytes. - */ - final static int MAX_SEGMENT_LENGTH = 256 * 1024; - - final static int INT_SPACE = 0x0020; - - // // // Configuration: - - private final ReaderConfig mConfig; - - // // // Shared read-only input buffer: - - /** - * Shared input buffer; stored here in case some input can be returned - * as is, without being copied to collector's own buffers. Note that - * this is read-only for this Objet. - */ - private char[] mInputBuffer; - - /** - * Character offset of first char in input buffer; -1 to indicate - * that input buffer currently does not contain any useful char data - */ - private int mInputStart; - - /** - * When using shared buffer, offset after the last character in - * shared buffer - */ - private int mInputLen; - - // // // Internal non-shared collector buffers: - - private boolean mHasSegments = false; - - /** - * List of segments prior to currently active segment. - */ - private ArrayList mSegments; - - - // // // Currently used segment; not (yet) contained in mSegments - - /** - * Amount of characters in segments in {@link mSegments} - */ - private int mSegmentSize; - - private char[] mCurrentSegment; - - /** - * Number of characters in currently active (last) segment - */ - private int mCurrentSize; - - // // // Temporary caching for Objects to return - - /** - * String that will be constructed when the whole contents are - * needed; will be temporarily stored in case asked for again. - */ - private String mResultString; - - private char[] mResultArray; - - // // // Canonical indentation objects (up to 32 spaces, 8 tabs) - - public final static int MAX_INDENT_SPACES = 32; - public final static int MAX_INDENT_TABS = 8; - - // Let's add one more space at the end, for safety... - private final static String sIndSpaces = - // 123456789012345678901234567890123 - "\n "; - private final static char[] sIndSpacesArray = sIndSpaces.toCharArray(); - private final static String[] sIndSpacesStrings = new String[sIndSpacesArray.length]; - - private final static String sIndTabs = - // 1 2 3 4 5 6 7 8 9 - "\n\t\t\t\t\t\t\t\t\t"; - private final static char[] sIndTabsArray = sIndTabs.toCharArray(); - private final static String[] sIndTabsStrings = new String[sIndTabsArray.length]; - - /* - ////////////////////////////////////////////// - // Life-cycle - ////////////////////////////////////////////// - */ - - private TextBuffer(ReaderConfig cfg) - { - mConfig = cfg; - } - - public static TextBuffer createRecyclableBuffer(ReaderConfig cfg) - { - return new TextBuffer(cfg); - } - - public static TextBuffer createTemporaryBuffer() - { - return new TextBuffer(null); - } - - /** - * Method called to indicate that the underlying buffers should now - * be recycled if they haven't yet been recycled. Although caller - * can still use this text buffer, it is not advisable to call this - * method if that is likely, since next time a buffer is needed, - * buffers need to reallocated. - * Note: calling this method automatically also clears contents - * of the buffer. - */ - public void recycle(boolean force) - { - if (mConfig != null && mCurrentSegment != null) { - if (force) { - /* If we are allowed to wipe out all existing data, it's - * quite easy; we'll just wipe out contents, and return - * biggest buffer: - */ - resetWithEmpty(); - } else { - /* But if there's non-shared data (ie. buffer is still - * in use), can't return it yet: - */ - if (mInputStart < 0 && (mSegmentSize + mCurrentSize) > 0) { - return; - } - // If no data (or only shared data), can continue - if (mSegments != null && mSegments.size() > 0) { - // No need to use anything from list, curr segment not null - mSegments.clear(); - mSegmentSize = 0; - } - } - - char[] buf = mCurrentSegment; - mCurrentSegment = null; - mConfig.freeMediumCBuffer(buf); - } - } - - /** - * Method called to clear out any content text buffer may have, and - * initializes buffer to use non-shared data. - */ - public void resetWithEmpty() - { - mInputBuffer = null; - mInputStart = -1; // indicates shared buffer not used - mInputLen = 0; - - mResultString = null; - mResultArray = null; - - // And then reset internal input buffers, if necessary: - if (mHasSegments) { - clearSegments(); - } - mCurrentSize = 0; - } - - /** - * Similar to {@link #resetWithEmpty}, but actively marks current - * text content to be empty string (whereas former method leaves - * content as undefined). - */ - public void resetWithEmptyString() - { - mInputBuffer = null; - mInputStart = -1; // indicates shared buffer not used - mInputLen = 0; - mResultString = ""; - mResultArray = null; - if (mHasSegments) { - clearSegments(); - } - mCurrentSize = 0; - } - - /** - * Method called to initialize the buffer with a shared copy of data; - * this means that buffer will just have pointers to actual data. It - * also means that if anything is to be appended to the buffer, it - * will first have to unshare it (make a local copy). - */ - public void resetWithShared(char[] buf, int start, int len) - { - // Let's first mark things we need about input buffer - mInputBuffer = buf; - mInputStart = start; - mInputLen = len; - - // Then clear intermediate values, if any: - mResultString = null; - mResultArray = null; - - // And then reset internal input buffers, if necessary: - if (mHasSegments) { - clearSegments(); - } - } - - public void resetWithCopy(char[] buf, int start, int len) - { - mInputBuffer = null; - mInputStart = -1; // indicates shared buffer not used - mInputLen = 0; - - mResultString = null; - mResultArray = null; - - // And then reset internal input buffers, if necessary: - if (mHasSegments) { - clearSegments(); - } else { - if (mCurrentSegment == null) { - mCurrentSegment = allocBuffer(len); - } - mCurrentSize = mSegmentSize = 0; - } - append(buf, start, len); - } - - /** - * Method called to make sure there is a non-shared segment to use, without - * appending any content yet. - */ - public void resetInitialized() - { - resetWithEmpty(); - if (mCurrentSegment == null) { - mCurrentSegment = allocBuffer(0); - } - } - - private final char[] allocBuffer(int needed) - { - int size = Math.max(needed, DEF_INITIAL_BUFFER_SIZE); - char[] buf = null; - if (mConfig != null) { - buf = mConfig.allocMediumCBuffer(size); - if (buf != null) { - return buf; - } - } - return new char[size]; - } - - private final void clearSegments() - { - mHasSegments = false; - /* Since the current segment should be the biggest one - * (as we allocate 50% bigger each time), let's retain it, - * and clear others - */ - mSegments.clear(); - mCurrentSize = mSegmentSize = 0; - } - - public void resetWithIndentation(int indCharCount, char indChar) - { - mInputStart = 0; - mInputLen = indCharCount+1; - String text; - if (indChar == '\t') { // tabs? - mInputBuffer = sIndTabsArray; - text = sIndTabsStrings[indCharCount]; - if (text == null) { - sIndTabsStrings[indCharCount] = text = sIndTabs.substring(0, mInputLen); - } - } else { // nope, spaces (should assert indChar?) - mInputBuffer = sIndSpacesArray; - text = sIndSpacesStrings[indCharCount]; - if (text == null) { - sIndSpacesStrings[indCharCount] = text = sIndSpaces.substring(0, mInputLen); - } - } - mResultString = text; - - /* Should not need the explicit non-shared array; no point in - * pre-populating it (can be changed if this is not true) - */ - mResultArray = null; - - // And then reset internal input buffers, if necessary: - if (mSegments != null && mSegments.size() > 0) { - mSegments.clear(); - mCurrentSize = mSegmentSize = 0; - } - } - - /* - ////////////////////////////////////////////// - // Accessors for implementing StAX interface: - ////////////////////////////////////////////// - */ - - /** - * @return Number of characters currently stored by this collector - */ - public int size() { - if (mInputStart >= 0) { // shared copy from input buf - return mInputLen; - } - // local segmented buffers - return mSegmentSize + mCurrentSize; - } - - public int getTextStart() - { - /* Only shared input buffer can have non-zero offset; buffer - * segments start at 0, and if we have to create a combo buffer, - * that too will start from beginning of the buffer - */ - return (mInputStart >= 0) ? mInputStart : 0; - } - - public char[] getTextBuffer() - { - // Are we just using shared input buffer? - if (mInputStart >= 0) { - return mInputBuffer; - } - // Nope; but does it fit in just one segment? - if (mSegments == null || mSegments.size() == 0) { - return mCurrentSegment; - } - // Nope, need to have/create a non-segmented array and return it - return contentsAsArray(); - } - - /* - ///////////////////////////////////////////////// - // Accessors for implementing StAX2 Typed access - ///////////////////////////////////////////////// - */ - - /** - * Generic pass-through method which call given decoder - * with accumulated data - */ - public void decode(TypedValueDecoder tvd) - throws IllegalArgumentException - { - char[] buf; - int start, end; - - if (mInputStart >= 0) { // shared buffer, common case - buf = mInputBuffer; - start = mInputStart; - end = start + mInputLen; - } else { - buf = getTextBuffer(); - start = 0; - end = mSegmentSize + mCurrentSize; - } - - // Need to trim first - while (true) { - if (start >= end) { - tvd.handleEmptyValue(); - return; - } - if (!StringUtil.isSpace(buf[start])) { - break; - } - ++start; - } - // Trailing space? - while (--end > start && StringUtil.isSpace(buf[end])) { } - tvd.decode(buf, start, end+1); - } - - /** - * Pass-through decode method called to find find the next token, - * decode it, and repeat the process as long as there are more - * tokens and the array decoder accepts more entries. - * All tokens processed will be "consumed", such that they will - * not be visible via buffer. - * - * @return Number of tokens decoded; 0 means that no (more) tokens - * were found from this buffer. - */ - public int decodeElements(TypedArrayDecoder tad, InputProblemReporter rep) - throws TypedXMLStreamException - { - int count = 0; - - /* First: for simplicity, we require a single flat buffer to - * decode from. Second: to be able to update start location - * (to keep track of what's available), we need to fake that - * we are using a shared buffer (since that has offset) - */ - if (mInputStart < 0) { - if (mHasSegments) { - mInputBuffer = buildResultArray(); - mInputLen = mInputBuffer.length; - // let's also clear segments since they are not needed any more - clearSegments(); - } else { - // just current buffer, easier to fake - mInputBuffer = mCurrentSegment; - mInputLen = mCurrentSize; - } - mInputStart = 0; - } - - // And then let's decode - int ptr = mInputStart; - final int end = ptr + mInputLen; - final char[] buf = mInputBuffer; - int start = ptr; - - try { - decode_loop: - while (ptr < end) { - // First, any space to skip? - while (buf[ptr] <= INT_SPACE) { - if (++ptr >= end) { - break decode_loop; - } - } - // Then let's figure out non-space char (token) - start = ptr; - ++ptr; - while (ptr < end && buf[ptr] > INT_SPACE) { - ++ptr; - } - ++count; - int tokenEnd = ptr; - ++ptr; // to skip trailing space (or, beyond end) - // And there we have it - if (tad.decodeValue(buf, start, tokenEnd)) { - break; - } - } - } catch (IllegalArgumentException iae) { - // Need to convert to a checked stream exception - - /* Hmmh. This is probably not an accurate location... but - * we can't do much better as content we have has been - * normalized already. - */ - Location loc = rep.getLocation(); - // -1 to move it back after being advanced earlier (to skip trailing space) - String lexical = new String(buf, start, (ptr-start-1)); - throw new TypedXMLStreamException(lexical, iae.getMessage(), loc, iae); - } finally { - mInputStart = ptr; - mInputLen = end-ptr; - } - return count; - } - - /** - * Method that needs to be called to configure given base64 decoder - * with textual contents collected by this buffer. - * - * @param dec Decoder that will need data - * @param firstChunk Whether this is the first segment fed or not; - * if it is, state needs to be fullt reset; if not, only partially. - */ - public void initBinaryChunks(Base64Variant v, CharArrayBase64Decoder dec, boolean firstChunk) - { - if (mInputStart < 0) { // non-shared - dec.init(v, firstChunk, mCurrentSegment, 0, mCurrentSize, mSegments); - } else { // shared - dec.init(v, firstChunk, mInputBuffer, mInputStart, mInputLen, null); - } - } - - /* - ////////////////////////////////////////////// - // Accessors: - ////////////////////////////////////////////// - */ - - public String contentsAsString() - { - if (mResultString == null) { - // Has array been requested? Can make a shortcut, if so: - if (mResultArray != null) { - mResultString = new String(mResultArray); - } else { - // Do we use shared array? - if (mInputStart >= 0) { - if (mInputLen < 1) { - return (mResultString = ""); - } - mResultString = new String(mInputBuffer, mInputStart, mInputLen); - } else { // nope... need to copy - // But first, let's see if we have just one buffer - int segLen = mSegmentSize; - int currLen = mCurrentSize; - - if (segLen == 0) { // yup - mResultString = (currLen == 0) ? "" : new String(mCurrentSegment, 0, currLen); - } else { // no, need to combine - StringBuffer sb = new StringBuffer(segLen + currLen); - // First stored segments - if (mSegments != null) { - for (int i = 0, len = mSegments.size(); i < len; ++i) { - char[] curr = (char[]) mSegments.get(i); - sb.append(curr, 0, curr.length); - } - } - // And finally, current segment: - sb.append(mCurrentSegment, 0, mCurrentSize); - mResultString = sb.toString(); - } - } - } - } - return mResultString; - } - - /** - * Similar to {@link #contentsAsString}, but constructs a StringBuffer - * for further appends. - * - * @param extraSpace Number of extra characters to preserve in StringBuffer - * beyond space immediately needed to hold the contents - */ - public StringBuffer contentsAsStringBuffer(int extraSpace) - { - if (mResultString != null) { - return new StringBuffer(mResultString); - } - if (mResultArray != null) { - StringBuffer sb = new StringBuffer(mResultArray.length + extraSpace); - sb.append(mResultArray, 0, mResultArray.length); - return sb; - } - if (mInputStart >= 0) { // shared array - if (mInputLen < 1) { - return new StringBuffer(); - } - StringBuffer sb = new StringBuffer(mInputLen + extraSpace); - sb.append(mInputBuffer, mInputStart, mInputLen); - return sb; - } - int segLen = mSegmentSize; - int currLen = mCurrentSize; - - StringBuffer sb = new StringBuffer(segLen + currLen + extraSpace); - // First stored segments - if (mSegments != null) { - for (int i = 0, len = mSegments.size(); i < len; ++i) { - char[] curr = (char[]) mSegments.get(i); - sb.append(curr, 0, curr.length); - } - } - // And finally, current segment: - sb.append(mCurrentSegment, 0, currLen); - return sb; - } - - public void contentsToStringBuffer(StringBuffer sb) - { - if (mResultString != null) { - sb.append(mResultString); - } else if (mResultArray != null) { - sb.append(mResultArray); - } else if (mInputStart >= 0) { // shared array - if (mInputLen > 0) { - sb.append(mInputBuffer, mInputStart, mInputLen); - } - } else { - // First stored segments - if (mSegments != null) { - for (int i = 0, len = mSegments.size(); i < len; ++i) { - char[] curr = (char[]) mSegments.get(i); - sb.append(curr, 0, curr.length); - } - } - // And finally, current segment: - sb.append(mCurrentSegment, 0, mCurrentSize); - } - } - - public char[] contentsAsArray() - { - char[] result = mResultArray; - if (result == null) { - mResultArray = result = buildResultArray(); - } - return result; - } - - public int contentsToArray(int srcStart, char[] dst, int dstStart, int len) { - // Easy to copy from shared buffer: - if (mInputStart >= 0) { - int amount = mInputLen - srcStart; - if (amount > len) { - amount = len; - } else if (amount < 0) { - amount = 0; - } - if (amount > 0) { - System.arraycopy(mInputBuffer, mInputStart+srcStart, - dst, dstStart, amount); - } - return amount; - } - - /* Could also check if we have array, but that'd only help with - * braindead clients that get full array first, then segments... - * which hopefully aren't that common - */ - // Copying from segmented array is bit more involved: - int totalAmount = 0; - if (mSegments != null) { - for (int i = 0, segc = mSegments.size(); i < segc; ++i) { - char[] segment = (char[]) mSegments.get(i); - int segLen = segment.length; - int amount = segLen - srcStart; - if (amount < 1) { // nothing from this segment? - srcStart -= segLen; - continue; - } - if (amount >= len) { // can get rest from this segment? - System.arraycopy(segment, srcStart, dst, dstStart, len); - return (totalAmount + len); - } - // Can get some from this segment, offset becomes zero: - System.arraycopy(segment, srcStart, dst, dstStart, amount); - totalAmount += amount; - dstStart += amount; - len -= amount; - srcStart = 0; - } - } - - // Need to copy anything from last segment? - if (len > 0) { - int maxAmount = mCurrentSize - srcStart; - if (len > maxAmount) { - len = maxAmount; - } - if (len > 0) { // should always be true - System.arraycopy(mCurrentSegment, srcStart, dst, dstStart, len); - totalAmount += len; - } - } - - return totalAmount; - } - - /** - * Method that will stream contents of this buffer into specified - * Writer. - */ - public int rawContentsTo(Writer w) - throws IOException - { - // Let's first see if we have created helper objects: - if (mResultArray != null) { - w.write(mResultArray); - return mResultArray.length; - } - if (mResultString != null) { - w.write(mResultString); - return mResultString.length(); - } - - // Do we use shared array? - if (mInputStart >= 0) { - if (mInputLen > 0) { - w.write(mInputBuffer, mInputStart, mInputLen); - } - return mInputLen; - } - // Nope, need to do full segmented output - int rlen = 0; - if (mSegments != null) { - for (int i = 0, len = mSegments.size(); i < len; ++i) { - char[] ch = (char[]) mSegments.get(i); - w.write(ch); - rlen += ch.length; - } - } - if (mCurrentSize > 0) { - w.write(mCurrentSegment, 0, mCurrentSize); - rlen += mCurrentSize; - } - return rlen; - } - - public Reader rawContentsViaReader() - throws IOException - { - // Let's first see if we have created helper objects: - if (mResultArray != null) { - return new CharArrayReader(mResultArray); - } - if (mResultString != null) { - return new StringReader(mResultString); - } - - // Do we use shared array? - if (mInputStart >= 0) { - if (mInputLen > 0) { - return new CharArrayReader(mInputBuffer, mInputStart, mInputLen); - } - return new StringReader(""); - } - // or maybe it's all in the current segment - if (mSegments == null || mSegments.size() == 0) { - return new CharArrayReader(mCurrentSegment, 0, mCurrentSize); - } - // Nope, need to do full segmented output - return new BufferReader(mSegments, mCurrentSegment, mCurrentSize); - } - - public boolean isAllWhitespace() - { - if (mInputStart >= 0) { // using single shared buffer? - char[] buf = mInputBuffer; - int i = mInputStart; - int last = i + mInputLen; - for (; i < last; ++i) { - if (buf[i] > INT_SPACE) { - return false; - } - } - return true; - } - - // Nope, need to do full segmented output - if (mSegments != null) { - for (int i = 0, len = mSegments.size(); i < len; ++i) { - char[] buf = (char[]) mSegments.get(i); - for (int j = 0, len2 = buf.length; j < len2; ++j) { - if (buf[j] > INT_SPACE) { - return false; - } - } - } - } - - char[] buf = mCurrentSegment; - for (int i = 0, len = mCurrentSize; i < len; ++i) { - if (buf[i] > INT_SPACE) { - return false; - } - } - return true; - } - - /** - * Method that can be used to check if the contents of the buffer end - * in specified String. - * - * @return True if the textual content buffer contains ends with the - * specified String; false otherwise - */ - public boolean endsWith(String str) - { - /* Let's just play this safe; should seldom if ever happen... - * and because of that, can be sub-optimal, performancewise, to - * alternatives. - */ - if (mInputStart >= 0) { - unshare(16); - } - - int segIndex = (mSegments == null) ? 0 : mSegments.size(); - int inIndex = str.length() - 1; - char[] buf = mCurrentSegment; - int bufIndex = mCurrentSize-1; - - while (inIndex >= 0) { - if (str.charAt(inIndex) != buf[bufIndex]) { - return false; - } - if (--inIndex == 0) { - break; - } - if (--bufIndex < 0) { - if (--segIndex < 0) { // no more data? - return false; - } - buf = (char[]) mSegments.get(segIndex); - bufIndex = buf.length-1; - } - } - - return true; - } - - /** - * Note: it is assumed that this method is not used often enough to - * be a bottleneck, or for long segments. Based on this, it is optimized - * for common simple cases where there is only one single character - * segment to use; fallback for other cases is to create such segment. - */ - public boolean equalsString(String str) - { - int expLen = str.length(); - - // First the easy check; if we have a shared buf: - if (mInputStart >= 0) { - if (mInputLen != expLen) { - return false; - } - for (int i = 0; i < expLen; ++i) { - if (str.charAt(i) != mInputBuffer[mInputStart+i]) { - return false; - } - } - return true; - } - - // Otherwise, segments: - if (expLen != size()) { - return false; - } - char[] seg; - if (mSegments == null || mSegments.size() == 0) { - // just one segment, still easy - seg = mCurrentSegment; - } else { - /* Ok; this is the sub-optimal case. Could obviously juggle through - * segments, but probably not worth the hassle, we seldom if ever - * get here... - */ - seg = contentsAsArray(); - } - - for (int i = 0; i < expLen; ++i) { - if (seg[i] != str.charAt(i)) { - return false; - } - } - return true; - } - - /* - ////////////////////////////////////////////// - // Access using SAX handlers: - ////////////////////////////////////////////// - */ - - public void fireSaxCharacterEvents(ContentHandler h) - throws SAXException - { - if (mResultArray != null) { // already have single array? - h.characters(mResultArray, 0, mResultArray.length); - } else if (mInputStart >= 0) { // sharing input buffer? - h.characters(mInputBuffer, mInputStart, mInputLen); - } else { - if (mSegments != null) { - for (int i = 0, len = mSegments.size(); i < len; ++i) { - char[] ch = (char[]) mSegments.get(i); - h.characters(ch, 0, ch.length); - } - } - if (mCurrentSize > 0) { - h.characters(mCurrentSegment, 0, mCurrentSize); - } - } - } - - public void fireSaxSpaceEvents(ContentHandler h) - throws SAXException - { - if (mResultArray != null) { // only happens for indentation - h.ignorableWhitespace(mResultArray, 0, mResultArray.length); - } else if (mInputStart >= 0) { // sharing input buffer? - h.ignorableWhitespace(mInputBuffer, mInputStart, mInputLen); - } else { - if (mSegments != null) { - for (int i = 0, len = mSegments.size(); i < len; ++i) { - char[] ch = (char[]) mSegments.get(i); - h.ignorableWhitespace(ch, 0, ch.length); - } - } - if (mCurrentSize > 0) { - h.ignorableWhitespace(mCurrentSegment, 0, mCurrentSize); - } - } - } - - public void fireSaxCommentEvent(LexicalHandler h) - throws SAXException - { - // Comment can not be split, so may need to combine the array - if (mResultArray != null) { // only happens for indentation - h.comment(mResultArray, 0, mResultArray.length); - } else if (mInputStart >= 0) { // sharing input buffer? - h.comment(mInputBuffer, mInputStart, mInputLen); - } else if (mSegments != null && mSegments.size() > 0) { - char[] ch = contentsAsArray(); - h.comment(ch, 0, ch.length); - } else { - h.comment(mCurrentSegment, 0, mCurrentSize); - } - } - - public void fireDtdCommentEvent(DTDEventListener l) - { - // Comment can not be split, so may need to combine the array - if (mResultArray != null) { // only happens for indentation - l.dtdComment(mResultArray, 0, mResultArray.length); - } else if (mInputStart >= 0) { // sharing input buffer? - l.dtdComment(mInputBuffer, mInputStart, mInputLen); - } else if (mSegments != null && mSegments.size() > 0) { - char[] ch = contentsAsArray(); - l.dtdComment(ch, 0, ch.length); - } else { - l.dtdComment(mCurrentSegment, 0, mCurrentSize); - } - } - - /* - ////////////////////////////////////////////// - // Support for validation - ////////////////////////////////////////////// - */ - - public void validateText(XMLValidator vld, boolean lastSegment) - throws XMLStreamException - { - // Shared buffer? Let's just pass that - if (mInputStart >= 0) { - vld.validateText(mInputBuffer, mInputStart, mInputStart + mInputLen, lastSegment); - } else { - /* Otherwise, can either create a combine buffer, or construct - * a String. While former could be more efficient, let's do latter - * for now since current validator implementations work better - * with Strings. - */ - vld.validateText(contentsAsString(), lastSegment); - } - } - - /* - ////////////////////////////////////////////// - // Public mutators: - ////////////////////////////////////////////// - */ - - /** - * Method called to make sure that buffer is not using shared input - * buffer; if it is, it will copy such contents to private buffer. - */ - public void ensureNotShared() { - if (mInputStart >= 0) { - unshare(16); - } - } - - public void append(char c) { - // Using shared buffer so far? - if (mInputStart >= 0) { - unshare(16); - } - mResultString = null; - mResultArray = null; - // Room in current segment? - char[] curr = mCurrentSegment; - if (mCurrentSize >= curr.length) { - expand(1); - curr = mCurrentSegment; - } - curr[mCurrentSize++] = c; - } - - public void append(char[] c, int start, int len) - { - // Can't append to shared buf (sanity check) - if (mInputStart >= 0) { - unshare(len); - } - mResultString = null; - mResultArray = null; - - // Room in current segment? - char[] curr = mCurrentSegment; - int max = curr.length - mCurrentSize; - - if (max >= len) { - System.arraycopy(c, start, curr, mCurrentSize, len); - mCurrentSize += len; - } else { - // No room for all, need to copy part(s): - if (max > 0) { - System.arraycopy(c, start, curr, mCurrentSize, max); - start += max; - len -= max; - } - /* And then allocate new segment; we are guaranteed to now - * have enough room in segment. - */ - expand(len); // note: curr != mCurrentSegment after this - System.arraycopy(c, start, mCurrentSegment, 0, len); - mCurrentSize = len; - } - } - - public void append(String str) - { - // Can't append to shared buf (sanity check) - int len = str.length(); - if (mInputStart >= 0) { - unshare(len); - } - mResultString = null; - mResultArray = null; - - // Room in current segment? - char[] curr = mCurrentSegment; - int max = curr.length - mCurrentSize; - if (max >= len) { - str.getChars(0, len, curr, mCurrentSize); - mCurrentSize += len; - } else { - // No room for all, need to copy part(s): - if (max > 0) { - str.getChars(0, max, curr, mCurrentSize); - len -= max; - } - /* And then allocate new segment; we are guaranteed to now - * have enough room in segment. - */ - expand(len); - str.getChars(max, max+len, mCurrentSegment, 0); - mCurrentSize = len; - } - } - - /* - ////////////////////////////////////////////// - // Raw access, for high-performance use: - ////////////////////////////////////////////// - */ - - public char[] getCurrentSegment() - { - /* Since the intention of the caller is to directly add stuff into - * buffers, we should NOT have anything in shared buffer... ie. may - * need to unshare contents. - */ - if (mInputStart >= 0) { - unshare(1); - } else { - char[] curr = mCurrentSegment; - if (curr == null) { - mCurrentSegment = allocBuffer(0); - } else if (mCurrentSize >= curr.length) { - // Plus, we better have room for at least one more char - expand(1); - } - } - return mCurrentSegment; - } - - public int getCurrentSegmentSize() { - return mCurrentSize; - } - - public void setCurrentLength(int len) { - mCurrentSize = len; - } - - public char[] finishCurrentSegment() - { - if (mSegments == null) { - mSegments = new ArrayList(); - } - mHasSegments = true; - mSegments.add(mCurrentSegment); - int oldLen = mCurrentSegment.length; - mSegmentSize += oldLen; - char[] curr = new char[calcNewSize(oldLen)]; - mCurrentSize = 0; - mCurrentSegment = curr; - return curr; - } - - /** - * Method used to determine size of the next segment to - * allocate to contain textual content. - */ - private int calcNewSize(int latestSize) - { - // Let's grow segments by 50%, when over 8k - int incr = (latestSize < 8000) ? latestSize : (latestSize >> 1); - int size = latestSize + incr; - // but let's not create too big chunks - return Math.min(size, MAX_SEGMENT_LENGTH); - } - - /* - ////////////////////////////////////////////// - // Standard methods: - ////////////////////////////////////////////// - */ - - /** - * Note: calling this method may not be as efficient as calling - * {@link #contentsAsString}, since it's not guaranteed that resulting - * String is cached. - */ - public String toString() { - return contentsAsString(); - } - - /* - ////////////////////////////////////////////// - // Internal methods: - ////////////////////////////////////////////// - */ - - /** - * Method called if/when we need to append content when we have been - * initialized to use shared buffer. - */ - public void unshare(int needExtra) - { - int len = mInputLen; - mInputLen = 0; - char[] inputBuf = mInputBuffer; - mInputBuffer = null; - int start = mInputStart; - mInputStart = -1; - - // Is buffer big enough, or do we need to reallocate? - int needed = len+needExtra; - if (mCurrentSegment == null || needed > mCurrentSegment.length) { - mCurrentSegment = allocBuffer(needed); - } - if (len > 0) { - System.arraycopy(inputBuf, start, mCurrentSegment, 0, len); - } - mSegmentSize = 0; - mCurrentSize = len; - } - - /** - * Method called when current segment is full, to allocate new - * segment. - * - * @param roomNeeded Number of characters that the resulting - * new buffer must have - */ - private void expand(int roomNeeded) - { - // First, let's move current segment to segment list: - if (mSegments == null) { - mSegments = new ArrayList(); - } - char[] curr = mCurrentSegment; - mHasSegments = true; - mSegments.add(curr); - int oldLen = curr.length; - mSegmentSize += oldLen; - int newSize = Math.max(roomNeeded, calcNewSize(oldLen)); - curr = new char[newSize]; - mCurrentSize = 0; - mCurrentSegment = curr; - } - - private char[] buildResultArray() - { - if (mResultString != null) { // Can take a shortcut... - return mResultString.toCharArray(); - } - char[] result; - - // Do we use shared array? - if (mInputStart >= 0) { - if (mInputLen < 1) { - return DataUtil.getEmptyCharArray(); - } - result = new char[mInputLen]; - System.arraycopy(mInputBuffer, mInputStart, result, 0, - mInputLen); - } else { // nope - int size = size(); - if (size < 1) { - return DataUtil.getEmptyCharArray(); - } - int offset = 0; - result = new char[size]; - if (mSegments != null) { - for (int i = 0, len = mSegments.size(); i < len; ++i) { - char[] curr = (char[]) mSegments.get(i); - int currLen = curr.length; - System.arraycopy(curr, 0, result, offset, currLen); - offset += currLen; - } - } - System.arraycopy(mCurrentSegment, 0, result, offset, mCurrentSize); - } - return result; - } - - private final static class BufferReader - extends Reader - { - ArrayList _Segments; - char[] _CurrentSegment; - final int _CurrentLength; - - int _SegmentIndex; - int _SegmentOffset; - int _CurrentOffset; - - public BufferReader(ArrayList segs, char[] currSeg, int currSegLen) - { - _Segments = segs; - _CurrentSegment = currSeg; - _CurrentLength = currSegLen; - - _SegmentIndex = 0; - _SegmentOffset = _CurrentOffset = 0; - } - - public void close() { - _Segments = null; - _CurrentSegment = null; - } - - public void mark(int x) - throws IOException - { - throw new IOException("mark() not supported"); - } - - public boolean markSupported() { - return false; - } - - public int read(char[] cbuf, int offset, int len) - { - if (len < 1) { - return 0; - } - - int origOffset = offset; - // First need to copy stuff from previous segments - while (_Segments != null) { - char[] curr = (char[]) _Segments.get(_SegmentIndex); - int max = curr.length - _SegmentOffset; - if (len <= max) { // this is enough - System.arraycopy(curr, _SegmentOffset, cbuf, offset, len); - _SegmentOffset += len; - offset += len; - return (offset - origOffset); - } - // Not enough, but helps... - if (max > 0) { - System.arraycopy(curr, _SegmentOffset, cbuf, offset, max); - offset += max; - } - if (++_SegmentIndex >= _Segments.size()) { // last one - _Segments = null; - } else { - _SegmentOffset = 0; - } - } - - // ok, anything to copy from the active segment? - if (len > 0 && _CurrentSegment != null) { - int max = _CurrentLength - _CurrentOffset; - if (len >= max) { // reading it all - len = max; - System.arraycopy(_CurrentSegment, _CurrentOffset, - cbuf, offset, len); - _CurrentSegment = null; - } else { - System.arraycopy(_CurrentSegment, _CurrentOffset, - cbuf, offset, len); - _CurrentOffset += len; - } - offset += len; - } - - return (origOffset == offset) ? -1 : (offset - origOffset); - } - - public boolean ready() { - return true; - } - - public void reset() - throws IOException - { - throw new IOException("reset() not supported"); - } - - public long skip(long amount) - { - /* Note: implementation is almost identical to that of read(); - * difference being that no data is copied. - */ - if (amount < 0) { - return 0L; - } - - long origAmount= amount; - - while (_Segments != null) { - char[] curr = (char[]) _Segments.get(_SegmentIndex); - int max = curr.length - _SegmentOffset; - if (max >= amount) { // this is enough - _SegmentOffset += (int) amount; - return origAmount; - } - // Not enough, but helps... - amount -= max; - if (++_SegmentIndex >= _Segments.size()) { // last one - _Segments = null; - } else { - _SegmentOffset = 0; - } - } - - // ok, anything left in the active segment? - if (amount > 0 && _CurrentSegment != null) { - int max = _CurrentLength - _CurrentOffset; - if (amount >= max) { // reading it all - amount -= max; - _CurrentSegment = null; - } else { - amount = 0L; - _CurrentOffset += (int) amount; - } - } - - return (amount == origAmount) ? -1L : (origAmount - amount); - } - } -} diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/util/TextBuilder.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/util/TextBuilder.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/util/TextBuilder.java 2012-04-24 04:38:21.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/util/TextBuilder.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,133 +0,0 @@ -package com.ctc.wstx.util; - -/** - * Class similar to {@link StringBuffer}, except that it can be used to - * construct multiple Strings, that will share same underlying character - * buffer. This is generally useful for closely related value Strings, - * such as attribute values of a single XML start element. - */ -public final class TextBuilder -{ - private final static int MIN_LEN = 60; - private final static int MAX_LEN = 120; - - private char[] mBuffer; - - private int mBufferLen; - - private String mResultString; - - /* - /////////////////////////////////////////////// - // Life-cycle: - /////////////////////////////////////////////// - */ - - public TextBuilder(int initialSize) - { - int charSize = (initialSize << 4); // multiply by 16 (-> def. 192 chars) - if (charSize < MIN_LEN) { - charSize = MIN_LEN; - } else if (charSize > MAX_LEN) { - charSize = MAX_LEN; - } - mBuffer = new char[charSize]; - } - - /** - * Method called before starting to (re)use the buffer, will discard - * any existing content, and start collecting new set of values. - */ - public void reset() { - mBufferLen = 0; - mResultString = null; - } - - /* - /////////////////////////////////////////////// - // Accesors: - /////////////////////////////////////////////// - */ - - public boolean isEmpty() { - return mBufferLen == 0; - } - - public String getAllValues() - { - if (mResultString == null) { - mResultString = new String(mBuffer, 0, mBufferLen); - } - return mResultString; - } - - /** - * Method that gives access to underlying character buffer - */ - public char[] getCharBuffer() { - return mBuffer; - } - - public int getCharSize() { - return mBufferLen; - } - - /* - /////////////////////////////////////////////// - // Mutators: - /////////////////////////////////////////////// - */ - - public void append(char c) { - if (mBuffer.length == mBufferLen) { - resize(1); - } - mBuffer[mBufferLen++] = c; - } - - public void append(char[] src, int start, int len) { - if (len > (mBuffer.length - mBufferLen)) { - resize(len); - } - System.arraycopy(src, start, mBuffer, mBufferLen, len); - mBufferLen += len; - } - - public void setBufferSize(int newSize) { - mBufferLen = newSize; - } - - public char[] bufferFull(int needSpaceFor) { - mBufferLen = mBuffer.length; - resize(1); - return mBuffer; - } - - /* - /////////////////////////////////////////////// - // Debugging: - /////////////////////////////////////////////// - */ - - public String toString() { - return new String(mBuffer, 0, mBufferLen); - } - - /* - /////////////////////////////////////////////// - // Internal methods: - /////////////////////////////////////////////// - */ - - private void resize(int needSpaceFor) { - char[] old = mBuffer; - int oldLen = old.length; - int addition = oldLen >> 1; // Grow by 50% - needSpaceFor -= (oldLen - mBufferLen); - if (addition < needSpaceFor) { - addition = needSpaceFor; - } - mBuffer = new char[oldLen+addition]; - System.arraycopy(old, 0, mBuffer, 0, mBufferLen); - } -} diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/util/URLUtil.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/util/URLUtil.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/util/URLUtil.java 2012-04-24 04:38:21.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/util/URLUtil.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,190 +0,0 @@ -package com.ctc.wstx.util; - -import java.io.*; -import java.net.URI; -import java.net.URL; -import java.net.URLDecoder; -import java.net.MalformedURLException; -import java.net.URISyntaxException; - -public final class URLUtil -{ - private URLUtil() { } - - /** - * Method that tries to figure out how to create valid URL from a system - * id, without additional contextual information. - * If we could use URIs this might be easier to do, but they are part - * of JDK 1.4, and preferably code should only require 1.2 (or maybe 1.3) - */ - public static URL urlFromSystemId(String sysId) - throws IOException - { - try { - /* Ok, does it look like a full URL? For one, you need a colon. Also, - * to reduce likelihood of collision with Windows paths, let's only - * accept it if there are 3 preceding other chars... - * Not sure if Mac might be a problem? (it uses ':' as file path - * separator, alas, at least prior to MacOS X) - */ - int ix = sysId.indexOf(':', 0); - /* Also, protocols are generally fairly short, usually 3 or 4 - * chars (http, ftp, urn); so let's put upper limit of 8 chars too - */ - if (ix >= 3 && ix <= 8) { - return new URL(sysId); - } - // Ok, let's just assume it's local file reference... - /* 24-May-2006, TSa: Amazingly, this single call does show in - * profiling, for small docs. The problem is that deep down it - * tries to check physical file system, to check if the File - * pointed to is a directory: and that is (relatively speaking) - * a very expensive call. Since in this particular case it - * should never be a dir (and/or doesn't matter), let's just - * implement conversion locally - */ - String absPath = new java.io.File(sysId).getAbsolutePath(); - // Need to convert colons/backslashes to regular slashes? - { - char sep = File.separatorChar; - if (sep != '/') { - absPath = absPath.replace(sep, '/'); - } - } - if (absPath.length() > 0 && absPath.charAt(0) != '/') { - absPath = "/" + absPath; - } - return new URL("file", "", absPath); - } catch (MalformedURLException e) { - throwIOException(e, sysId); - return null; // never gets here - } - } - - /** - * @since 4.1 - */ - public static URI uriFromSystemId(String sysId) throws IOException - { - // note: mostly a copy of matching method above, but with URI instead of URL - try { - int ix = sysId.indexOf(':', 0); - if (ix >= 3 && ix <= 8) { - return new URI(sysId); - } - String absPath = new java.io.File(sysId).getAbsolutePath(); - char sep = File.separatorChar; - if (sep != '/') { - absPath = absPath.replace(sep, '/'); - } - if (absPath.length() > 0 && absPath.charAt(0) != '/') { - absPath = "/" + absPath; - } - return new URI("file", absPath, null); - } catch (URISyntaxException e) { - throwIOException(e, sysId); - return null; // never gets here - } - } - - public static URL urlFromSystemId(String sysId, URL ctxt) throws IOException - { - if (ctxt == null) { - return urlFromSystemId(sysId); - } - try { - return new URL(ctxt, sysId); - } catch (MalformedURLException e) { - throwIOException(e, sysId); - return null; // never gets here - } - } - - /** - * Method that tries to create and return URL that denotes current - * working directory. Usually used to create a context, when one is - * not explicitly passed. - */ - public static URL urlFromCurrentDir() - throws java.net.MalformedURLException /* an IOException */ - { - /* This seems to work; independent of whether there happens to - * be such/file dir or not. - */ - return new File("a").getAbsoluteFile().getParentFile().toURL(); - } - - /** - * Method that tries to get a stream (ideally, optimal one) to read from - * the specified URL. - * Currently it just means creating a simple file input stream if the - * URL points to a (local) file, and otherwise relying on URL classes - * input stream creation method. - */ - public static InputStream inputStreamFromURL(URL url) - throws IOException - { - if ("file".equals(url.getProtocol())) { - /* As per [WSTX-82], can not do this if the path refers - * to a network drive on windows. This fixes the problem; - * might not be needed on all platforms (NFS?), but should not - * matter a lot: performance penalty of extra wrapping is more - * relevant when accessing local file system. - */ - String host = url.getHost(); - if (host == null || host.length() == 0) { - /* One more test: if there are quoted characters, need - * to decoded [WSTX-207]: - */ - String path = url.getPath(); - if (path.indexOf('%') >= 0) { - path = URLDecoder.decode(path, "UTF-8"); - } - return new FileInputStream(path); - } - } - return url.openStream(); - } - - /** - * Method that tries to get a stream (ideally, optimal one) to write to - * the resource specified by given URL. - * Currently it just means creating a simple file output stream if the - * URL points to a (local) file, and otherwise relying on URL classes - * input stream creation method. - */ - public static OutputStream outputStreamFromURL(URL url) - throws IOException - { - if ("file".equals(url.getProtocol())) { - /* As per [WSTX-82], can not do this if the path refers - * to a network drive on windows. - */ - String host = url.getHost(); - if (host == null || host.length() == 0) { - return new FileOutputStream(url.getPath()); - } - } - return url.openConnection().getOutputStream(); - } - - /* - /////////////////////////////////////////////////////////////////////// - // Private helper methods - /////////////////////////////////////////////////////////////////////// - */ - - /** - * Helper method that tries to fully convert strange URL-specific exception - * to more general IO exception. Also, to try to use JDK 1.4 feature without - * creating requirement, uses reflection to try to set the root cause, if - * we are running on JDK1.4 - */ - private static void throwIOException(Exception mex, String sysId) - throws IOException - { - IOException ie = new IOException("[resolving systemId '"+sysId+"']: "+mex.toString()); - ExceptionUtil.setInitCause(ie, mex); - throw ie; - } -} diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/util/WordResolver.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/util/WordResolver.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/util/WordResolver.java 2012-04-24 04:38:21.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/util/WordResolver.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,580 +0,0 @@ -package com.ctc.wstx.util; - -import java.util.*; - -/** - * A specialized Map/Symbol table - like data structure that can be used - * for both checking whether a word (passed in as a char array) exists - * in certain set of words AND getting that word as a String. - * It is reasonably efficient both time and speed-wise, at least for - * certain use cases; specifically, if there is no existing key to use, - * it is more efficient way to get to a shared copy of that String - * The general usage pattern is expected - * to be such that most checks are positive, ie. that the word indeed - * is contained in the structure. - *

- * Although this is an efficient data struct for specific set of usage - * patterns, one restriction is that the full set of words to include has to - * be known before constructing the instnace. Also, the size of the set is - * limited to total word content of about 20k characters. - *

- * TODO: Should document the internal data structure... - */ -public final class WordResolver -{ - /** - * Maximum number of words (Strings) an instance can contain - */ - public final static int MAX_WORDS = 0x2000; - - final static char CHAR_NULL = (char) 0; - - /** - * Offset added to numbers to mark 'negative' numbers. Asymmetric, - * since range of negative markers needed is smaller than positive - * numbers... - */ - final static int NEGATIVE_OFFSET = 0x10000 - MAX_WORDS; - - /** - * This is actually just a guess; but in general linear search should - * be faster for short sequences (definitely for 4 or less; maybe up - * to 8 or less?) - */ - final static int MIN_BINARY_SEARCH = 7; - - /** - * Compressed presentation of the word set. - */ - final char[] mData; - - /** - * Array of actual words returned resolved for matches. - */ - final String[] mWords; - - /* - //////////////////////////////////////////////// - // Life-cycle - //////////////////////////////////////////////// - */ - - private WordResolver(String[] words, char[] index) { - mWords = words; - mData = index; - } - - /** - * Tries to construct an instance given ordered set of words. - *

- * Note: currently maximum number of words that can be contained - * is limited to {@link #MAX_WORDS}; additionally, maximum length - * of all such words can not exceed roughly 28000 characters. - * - * @return WordResolver constructed for given set of words, if - * the word set size is not too big; null to indicate "too big" - * instance. - */ - public static WordResolver constructInstance(TreeSet wordSet) - { - if (wordSet.size() > MAX_WORDS) { - return null; - } - return new Builder(wordSet).construct(); - } - - /* - //////////////////////////////////////////////// - // Public API - //////////////////////////////////////////////// - */ - - /** - * @return Number of words contained - */ - public int size() { - return mWords.length; - } - - /* - public int indexSize() { - return mData.length; - } - */ - - /** - * @param str Character array that contains the word to find - * @param start Index of the first character of the word - * @param end Index following the last character of the word, - * so that end - start equals word length (similar - * to the way String.substring() has). - * - * @return (Shared) string instance of the word, if it exists in - * the word set; null if not. - */ - public String find(char[] str, final int start, final int end) - { - char[] data = mData; - - // 03-Jan-2006, TSa: Special case; one entry - if (data == null) { - return findFromOne(str, start, end); - } - - int ptr = 0; // pointer to compressed set data - int offset = start; - - while (true) { - // End of input String? Need to match the runt entry! - if (offset == end) { - if (data[ptr+1] == CHAR_NULL) { - return mWords[data[ptr+2] - NEGATIVE_OFFSET]; - } - return null; - } - - int count = data[ptr++]; - // Need to find the branch to follow, if any - char c = str[offset++]; - - inner_block: - do { // dummy loop, need to have break - // Linear or binary search? - if (count < MIN_BINARY_SEARCH) { - // always at least two branches; never less - if (data[ptr] == c) { - ptr = (int) data[ptr+1]; - break inner_block; - } - if (data[ptr+2] == c) { - ptr = (int) data[ptr+3]; - break inner_block; - } - int branchEnd = ptr + (count << 1); - // Starts from entry #3, if such exists - for (ptr += 4; ptr < branchEnd; ptr += 2) { - if (data[ptr] == c) { - ptr = (int) data[ptr+1]; - break inner_block; - } - } - return null; // No match! - } else { // Ok, binary search: - int low = 0; - int high = count-1; - int mid; - - while (low <= high) { - mid = (low + high) >> 1; - int ix = ptr + (mid << 1); - int diff = data[ix] - c; - if (diff > 0) { // char was 'higher', need to go down - high = mid-1; - } else if (diff < 0) { // lower, need to go up - low = mid+1; - } else { // match (so far) - ptr = (int) data[ix+1]; - break inner_block; - } - } - return null; // No match! - } - } while (false); - - // Ok; now, is it the end? - if (ptr >= NEGATIVE_OFFSET) { - String word = mWords[ptr - NEGATIVE_OFFSET]; - int expLen = (end - start); - if (word.length() != expLen) { - return null; - } - for (int i = offset - start; offset < end; ++i, ++offset) { - if (word.charAt(i) != str[offset]) { - return null; - } - } - return word; - } - } - // never gets here - } - - private String findFromOne(char[] str, final int start, final int end) - { - String word = mWords[0]; - int len = end-start; - if (word.length() != len) { - return null; - } - for (int i = 0; i < len; ++i) { - if (word.charAt(i) != str[start+i]) { - return null; - } - } - return word; - } - - /** - * @return (Shared) string instance of the word, if it exists in - * the word set; null if not. - */ - public String find(String str) - { - char[] data = mData; - - // 03-Jan-2006, TSa: Special case; one entry - if (data == null) { - String word = mWords[0]; - return word.equals(str) ? word : null; - } - - int ptr = 0; // pointer to compressed set data - int offset = 0; - int end = str.length(); - - while (true) { - // End of input String? Need to match the runt entry! - if (offset == end) { - if (data[ptr+1] == CHAR_NULL) { - return mWords[data[ptr+2] - NEGATIVE_OFFSET]; - } - return null; - } - - int count = data[ptr++]; - // Need to find the branch to follow, if any - char c = str.charAt(offset++); - - inner_block: - do { // dummy loop, need to have break - // Linear or binary search? - if (count < MIN_BINARY_SEARCH) { - // always at least two branches; never less - if (data[ptr] == c) { - ptr = (int) data[ptr+1]; - break inner_block; - } - if (data[ptr+2] == c) { - ptr = (int) data[ptr+3]; - break inner_block; - } - int branchEnd = ptr + (count << 1); - // Starts from entry #3, if such exists - for (ptr += 4; ptr < branchEnd; ptr += 2) { - if (data[ptr] == c) { - ptr = (int) data[ptr+1]; - break inner_block; - } - } - return null; // No match! - } else { // Ok, binary search: - int low = 0; - int high = count-1; - int mid; - - while (low <= high) { - mid = (low + high) >> 1; - int ix = ptr + (mid << 1); - int diff = data[ix] - c; - if (diff > 0) { // char was 'higher', need to go down - high = mid-1; - } else if (diff < 0) { // lower, need to go up - low = mid+1; - } else { // match (so far) - ptr = (int) data[ix+1]; - break inner_block; - } - } - return null; // No match! - } - } while (false); - - // Ok; now, is it the end? - if (ptr >= NEGATIVE_OFFSET) { - String word = mWords[ptr - NEGATIVE_OFFSET]; - if (word.length() != str.length()) { - return null; - } - for (; offset < end; ++offset) { - if (word.charAt(offset) != str.charAt(offset)) { - return null; - } - } - return word; - } - } - // never gets here - } - - /* - //////////////////////////////////////////////// - // Re-defined public methods - //////////////////////////////////////////////// - */ - - public String toString() - { - StringBuffer sb = new StringBuffer(16 + (mWords.length << 3)); - for (int i = 0, len = mWords.length; i < len; ++i) { - if (i > 0) { - sb.append(", "); - } - sb.append(mWords[i]); - } - return sb.toString(); - } - - /* - //////////////////////////////////////////////// - // Private methods - //////////////////////////////////////////////// - */ - - /* - //////////////////////////////////////////////// - // Helper classes - //////////////////////////////////////////////// - */ - - private final static class Builder - { - final String[] mWords; - - char[] mData; - - /** - * Number of characters currently used from mData - */ - int mSize; - - public Builder(TreeSet wordSet) - { - int wordCount = wordSet.size(); - - mWords = new String[wordCount]; - wordSet.toArray(mWords); - - /* 03-Jan-2006, TSa: Special case: just one entry; if so, - * let's leave char array null, and just have the String - * array with one entry. - */ - if (wordCount < 2) { - if (wordCount == 0) { - throw new IllegalArgumentException(); // not legal - } - mData = null; - } else { - /* Let's guess approximate size we should need, assuming - * average word length of 6 characters, overhead matching - * compression (ie. about 1-to-1 ratio overall) - */ - int size = wordCount * 6; - if (size < 256) { - size = 256; - } - mData = new char[size]; - } - } - - /** - * @return Raw character data that contains compressed structure - * of the word set - */ - public WordResolver construct() - { - char[] result; - - /* 03-Jan-2006, TSa: Special case: just one entry; if so, - * let's leave char array null, and just have the String - * array with one entry. - */ - if (mData == null) { - result = null; - } else { - constructBranch(0, 0, mWords.length); - - // Too big? - if (mSize > NEGATIVE_OFFSET) { - return null; - } - - result = new char[mSize]; - System.arraycopy(mData, 0, result, 0, mSize); - } - - return new WordResolver(mWords, result); - } - - /** - * Method that is called recursively to build the data - * representation for a branch, ie. part of word set tree - * that still has more than one ending - * - * @param charIndex Index of the character in words to consider - * for this round - * @param start Index of the first word to be processed - * @param end Index of the word after last word to be processed - * (so that number of words is end - start - 1 - */ - private void constructBranch(int charIndex, int start, int end) - { - // If more than one entry, need to divide into groups - - // First, need to add placeholder for branch count: - if (mSize >= mData.length) { - expand(1); - } - mData[mSize++] = 0; // placeholder! - /* structStart will point to second char of first entry - * (which will temporarily have entry count, eventually 'link' - * to continuation) - */ - int structStart = mSize + 1; - int groupCount = 0; - int groupStart = start; - String[] words = mWords; - boolean gotRunt; - - /* First thing we need to do is a special check for the - * first entry -- it may be "runt" word, one that has no - * more chars but also has a longer version ("id" vs. - * "identifier"). If so, it needs to be marked; this is done - * by adding a special entry before other entries (since such - * entry would always be ordered first alphabetically) - */ - if (words[groupStart].length() == charIndex) { // yup, got one: - if ((mSize + 2) > mData.length) { - expand(2); - } - /* First null marks the "missing" char (or, end-of-word); - * and then we need the index - */ - mData[mSize++] = CHAR_NULL; - mData[mSize++] = (char) (NEGATIVE_OFFSET + groupStart); - - // Ok, let's then ignore that entry - ++groupStart; - ++groupCount; - gotRunt = true; - } else { - gotRunt = false; - } - - // Ok, then, let's find the ('real') groupings: - while (groupStart < end) { - // Inner loop, let's find the group: - char c = words[groupStart].charAt(charIndex); - int j = groupStart+1; - while (j < end && words[j].charAt(charIndex) == c) { - ++j; - } - /* Ok, let's store the char in there, along with count; - * count will be needed in second, and will then get - * overwritten with actual data later on - */ - if ((mSize + 2) > mData.length) { - expand(2); - } - mData[mSize++] = c; - mData[mSize++] = (char) (j - groupStart); // entries in group - groupStart = j; - ++groupCount; - } - - /* Ok, groups found; need to loop through them, recursively - * calling branch and/or leaf methods - */ - // first let's output the header, ie. group count: - mData[structStart-2] = (char) groupCount; - groupStart = start; - - // Do we have the "runt" to skip? - if (gotRunt) { - structStart += 2; - ++groupStart; - } - - int structEnd = mSize; - ++charIndex; - for (; structStart < structEnd; structStart += 2) { - groupCount = (int) mData[structStart]; // no sign expansion, is ok - /* Ok, count gotten, can either create a branch (if more than - * one entry) or leaf (just one entry) - */ - if (groupCount == 1) { - mData[structStart] = (char) (NEGATIVE_OFFSET + groupStart); - } else { - mData[structStart] = (char) mSize; - constructBranch(charIndex, groupStart, - groupStart + groupCount); - } - groupStart += groupCount; - } - - // done! - } - - private char[] expand(int needSpace) - { - char[] old = mData; - int len = old.length; - int newSize = len + ((len < 4096) ? len : (len >> 1)); - - /* Let's verify we get enough; should always be true but - * better safe than sorry - */ - if (newSize < (mSize + needSpace)) { - newSize = mSize + needSpace + 64; - } - mData = new char[newSize]; - System.arraycopy(old, 0, mData, 0, len); - return mData; - } - } - - /* - //////////////////////////////////////////////////// - // Simple test driver, useful for debugging - // (uncomment if needed -- commented out so it won't - // affect coverage testing) - //////////////////////////////////////////////////// - */ - - /* - public static void main(String[] args) - { - if (args.length < 2) { - System.err.println("Usage: "+WordResolver.class+" word1 [word2] ... [wordN] keyword"); - System.exit(1); - } - String key = args[args.length-1]; - TreeSet words = new TreeSet(); - for (int i = 0; i < args.length-1; ++i) { - words.add(args[i]); - } - - WordResolver set = WordResolver.constructInstance(words); - -//outputData(set.mData); - - // Ok, and then the test! - char[] keyA = new char[key.length() + 4]; - key.getChars(0, key.length(), keyA, 2); - //System.out.println("Word '"+key+"' found via array search: "+WordResolver.find(data, keyA, 2, key.length() + 2)); - System.out.println("Word '"+key+"' found via array search: "+set.find(keyA, 2, key.length() + 2)); - } - - static void outputData(char[] data) - { - for (int i = 0; i < data.length; ++i) { - char c = data[i]; - System.out.print(Integer.toHexString(i)+" ["+Integer.toHexString(c)+"]"); - if (c > 32 && c <= 127) { // printable char (letter) - System.out.println(" -> '"+c+"'"); - } else { - System.out.println(); - } - } - } - */ -} diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/util/WordSet.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/util/WordSet.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/util/WordSet.java 2012-04-24 04:38:21.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/util/WordSet.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,476 +0,0 @@ -package com.ctc.wstx.util; - -import java.util.*; - -/** - * An efficient (both memory and time) implementation of a Set used to - * verify that a given - * word is contained within the set. The general usage pattern is expected - * to be such that most checks are positive, ie. that the word indeed - * is contained in the set. - *

- * Performance of the set is comparable to that of {@link java.util.TreeSet} - * for Strings, ie. 2-3x slower than {@link java.util.HashSet} when - * using pre-constructed Strings. This is generally result of algorithmic - * complexity of structures; Word and Tree sets are roughly logarithmic - * to the whole data, whereas Hash set is linear to the length of key. - * However: - *

    - *
  • WordSet can use char arrays as keys, without constructing Strings. - * In cases where there is no (need for) Strings, WordSet seems to be - * about twice as fast, even without considering additional GC caused - * by temporary String instances. - *
  • - *
  • WordSet is more compact in its memory presentation; if Strings are - * shared its size is comparable to optimally filled HashSet, and if - * no such Strings exists, its much more compact (relatively speaking) - *
  • - *
- *

- * Although this is an efficient set for specific set of usage patterns, - * one restriction is that the full set of words to include has to be - * known before constructing the set. Also, the size of the set is - * limited to total word content of about 20k characters; factory method - * does verify the limit and indicates if an instance can not be created. - */ -public final class WordSet -{ - final static char CHAR_NULL = (char) 0; - - /** - * Offset added to numbers to mark 'negative' numbers. Asymmetric, - * since range of negative markers needed is smaller than positive - * numbers... - */ - final static int NEGATIVE_OFFSET = 0xC000; - - /** - * This is actually just a guess; but in general linear search should - * be faster for short sequences (definitely for 4 or less; maybe up - * to 8 or less?) - */ - final static int MIN_BINARY_SEARCH = 7; - - /** - * Compressed presentation of the word set. - */ - final char[] mData; - - /* - //////////////////////////////////////////////// - // Life-cycle - //////////////////////////////////////////////// - */ - - private WordSet(char[] data) { - mData = data; - } - - public static WordSet constructSet(TreeSet wordSet) - { - return new WordSet(new Builder(wordSet).construct()); - } - - public static char[] constructRaw(TreeSet wordSet) - { - return new Builder(wordSet).construct(); - } - - /* - //////////////////////////////////////////////// - // Public API - //////////////////////////////////////////////// - */ - - public boolean contains(char[] buf, int start, int end) { - return contains(mData, buf, start, end); - } - - public static boolean contains(char[] data, char[] str, int start, int end) - { - int ptr = 0; // pointer to compressed set data - - main_loop: - do { - int left = end-start; - - // End of input String? Need to have the run entry: - if (left == 0) { - return (data[ptr+1] == CHAR_NULL); - } - - int count = data[ptr++]; - - // Nope, but do we have an end marker? - if (count >= NEGATIVE_OFFSET) { - // How many chars do we need to have left to match? - int expCount = count - NEGATIVE_OFFSET; - if (left != expCount) { - return false; - } - while (start < end) { - if (data[ptr] != str[start]) { - return false; - } - ++ptr; - ++start; - } - return true; - } - - // No, need to find the branch to follow, if any - char c = str[start++]; - - // Linear or binary search? - if (count < MIN_BINARY_SEARCH) { - // always at least two branches; never less - if (data[ptr] == c) { - ptr = (int) data[ptr+1]; - continue main_loop; - } - if (data[ptr+2] == c) { - ptr = (int) data[ptr+3]; - continue main_loop; - } - int branchEnd = ptr + (count << 1); - // Starts from entry #3, if such exists - for (ptr += 4; ptr < branchEnd; ptr += 2) { - if (data[ptr] == c) { - ptr = (int) data[ptr+1]; - continue main_loop; - } - } - return false; // No match! - } - - { // Ok, binary search: - int low = 0; - int high = count-1; - int mid; - - while (low <= high) { - mid = (low + high) >> 1; - int ix = ptr + (mid << 1); - int diff = data[ix] - c; - if (diff > 0) { // char was 'higher', need to go down - high = mid-1; - } else if (diff < 0) { // lower, need to go up - low = mid+1; - } else { // match - ptr = (int) data[ix+1]; - continue main_loop; - } - } - } - - // If we fall here, no match! - return false; - - } while (ptr != 0); - - // If we reached an end state, must match the length - return (start == end); - } - - public boolean contains(String str) { - return contains(mData, str); - } - - public static boolean contains(char[] data, String str) - { - // Let's use same vars as array-based code, to allow cut'n pasting - int ptr = 0; // pointer to compressed set data - int start = 0; - int end = str.length(); - - main_loop: - do { - int left = end-start; - - // End of input String? Need to have the run entry: - if (left == 0) { - return (data[ptr+1] == CHAR_NULL); - } - - int count = data[ptr++]; - - // Nope, but do we have an end marker? - if (count >= NEGATIVE_OFFSET) { - // How many chars do we need to have left to match? - int expCount = count - NEGATIVE_OFFSET; - if (left != expCount) { - return false; - } - while (start < end) { - if (data[ptr] != str.charAt(start)) { - return false; - } - ++ptr; - ++start; - } - return true; - } - - // No, need to find the branch to follow, if any - char c = str.charAt(start++); - - // Linear or binary search? - if (count < MIN_BINARY_SEARCH) { - // always at least two branches; never less - if (data[ptr] == c) { - ptr = (int) data[ptr+1]; - continue main_loop; - } - if (data[ptr+2] == c) { - ptr = (int) data[ptr+3]; - continue main_loop; - } - int branchEnd = ptr + (count << 1); - // Starts from entry #3, if such exists - for (ptr += 4; ptr < branchEnd; ptr += 2) { - if (data[ptr] == c) { - ptr = (int) data[ptr+1]; - continue main_loop; - } - } - return false; // No match! - } - - { // Ok, binary search: - int low = 0; - int high = count-1; - int mid; - - while (low <= high) { - mid = (low + high) >> 1; - int ix = ptr + (mid << 1); - int diff = data[ix] - c; - if (diff > 0) { // char was 'higher', need to go down - high = mid-1; - } else if (diff < 0) { // lower, need to go up - low = mid+1; - } else { // match - ptr = (int) data[ix+1]; - continue main_loop; - } - } - } - - // If we fall here, no match! - return false; - - } while (ptr != 0); - - // If we reached an end state, must match the length - return (start == end); - } - - /* - //////////////////////////////////////////////// - // Private methods - //////////////////////////////////////////////// - */ - - /* - //////////////////////////////////////////////// - // Helper classes - //////////////////////////////////////////////// - */ - - private final static class Builder - { - final String[] mWords; - - char[] mData; - - /** - * Number of characters currently used from mData - */ - int mSize; - - public Builder(TreeSet wordSet) { - int wordCount = wordSet.size(); - mWords = new String[wordCount]; - wordSet.toArray(mWords); - - /* Let's guess approximate size we should need, assuming - * average word length of 6 characters, and 100% overhead - * in structure: - */ - int size = wordCount * 12; - if (size < 256) { - size = 256; - } - mData = new char[size]; - } - - /** - * @return Raw character data that contains compressed structure - * of the word set - */ - public char[] construct() - { -// Uncomment if you need to debug array-out-of-bound probs -//try { - // Let's check degenerate case of 1 word: - if (mWords.length == 1) { - constructLeaf(0, 0); - } else { - constructBranch(0, 0, mWords.length); - } -//} catch (Throwable t) { System.err.println("Error: "+t); } - - char[] result = new char[mSize]; - System.arraycopy(mData, 0, result, 0, mSize); - return result; - } - - /** - * Method that is called recursively to build the data - * representation for a branch, ie. part of word set tree - * that still has more than one ending - * - * @param charIndex Index of the character in words to consider - * for this round - * @param start Index of the first word to be processed - * @param end Index of the word after last word to be processed - * (so that number of words is end - start - 1 - */ - private void constructBranch(int charIndex, int start, int end) - { - // If more than one entry, need to divide into groups - - // First, need to add placeholder for branch count: - if (mSize >= mData.length) { - expand(1); - } - mData[mSize++] = 0; // placeholder! - /* structStart will point to second char of first entry - * (which will temporarily have entry count, eventually 'link' - * to continuation) - */ - int structStart = mSize + 1; - int groupCount = 0; - int groupStart = start; - String[] words = mWords; - - /* First thing we need to do is a special check for the - * first entry -- it may be "runt" word, one that has no - * more chars but also has a longer version ("id" vs. - * "identifier"). If there is such a word, it'll always - * be first in alphabetic ordering: - */ - if (words[groupStart].length() == charIndex) { // yup, got one: - if ((mSize + 2) > mData.length) { - expand(2); - } - /* Nulls mark both imaginary branching null char and - * "missing link" to the rest - */ - mData[mSize++] = CHAR_NULL; - mData[mSize++] = CHAR_NULL; - - // Ok, let's then ignore that entry - ++groupStart; - ++groupCount; - } - - // Ok, then, let's find the ('real') groupings: - while (groupStart < end) { - // Inner loop, let's find the group: - char c = words[groupStart].charAt(charIndex); - int j = groupStart+1; - while (j < end && words[j].charAt(charIndex) == c) { - ++j; - } - /* Ok, let's store the char in there, along with count; - * count will be needed in second, and will then get - * overwritten with actual data later on - */ - if ((mSize + 2) > mData.length) { - expand(2); - } - mData[mSize++] = c; - mData[mSize++] = (char) (j - groupStart); // entries in group - groupStart = j; - ++groupCount; - } - - /* Ok, groups found; need to loop through them, recursively - * calling branch and/or leaf methods - */ - // first let's output the header, ie. group count: - mData[structStart-2] = (char) groupCount; - groupStart = start; - - // Do we have the "runt" to skip? - if (mData[structStart] == CHAR_NULL) { - structStart += 2; - ++groupStart; - } - - int structEnd = mSize; - ++charIndex; - for (; structStart < structEnd; structStart += 2) { - groupCount = (int) mData[structStart]; // no sign expansion, is ok - // Ok, count gotten, can now put the 'link' (pointer) in there - mData[structStart] = (char) mSize; - if (groupCount == 1) { - /* One optimization; if it'd lead to a single runt - * entry, we can just add 'null' link: - */ - String word = words[groupStart]; - if (word.length() == charIndex) { - mData[structStart] = CHAR_NULL; - } else { // otherwise, let's just create end state: - constructLeaf(charIndex, groupStart); - } - } else { - constructBranch(charIndex, groupStart, - groupStart + groupCount); - } - groupStart += groupCount; - } - - // done! - } - - /** - * Method called to add leaf entry to word set; basically - * "here is the rest of the only matching word" - */ - private void constructLeaf(int charIndex, int wordIndex) - { - String word = mWords[wordIndex]; - int len = word.length(); - char[] data = mData; - - // need room for 1 header char, rest of the word - if ((mSize + len + 1) >= data.length) { - data = expand(len+1); - } - - data[mSize++] = (char) (NEGATIVE_OFFSET + (len - charIndex)); - for (; charIndex < len; ++charIndex) { - data[mSize++] = word.charAt(charIndex); - } - } - - private char[] expand(int needSpace) - { - char[] old = mData; - int len = old.length; - int newSize = len + ((len < 4096) ? len : (len >> 1)); - - /* Let's verify we get enough; should always be true but - * better safe than sorry - */ - if (newSize < (mSize + needSpace)) { - newSize = mSize + needSpace + 64; - } - mData = new char[newSize]; - System.arraycopy(old, 0, mData, 0, len); - return mData; - } - } -} diff -Nru libwoodstox-java-4.1.3/src/java/com/ctc/wstx/util/XmlChars.java libwoodstox-java-5.1.0/src/java/com/ctc/wstx/util/XmlChars.java --- libwoodstox-java-4.1.3/src/java/com/ctc/wstx/util/XmlChars.java 2012-04-24 04:38:21.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/com/ctc/wstx/util/XmlChars.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,532 +0,0 @@ -package com.ctc.wstx.util; - -/** - * Simple utility class that encapsulates logic of determining validity - * of characters outside basic 7-bit range of Unicode, for XML 1.0 - */ -public final class XmlChars -{ - /* We don't need full 64k bits... (0x80 - 0x312C) / 32. But to - * simplify things, let's just include first 0x80 entries in there etc - */ - final static int SIZE = (0x3140 >> 5); // 32 bits per int - - final static int[] sXml10StartChars = new int[SIZE]; - static { - SETBITS(sXml10StartChars, 0xC0, 0xD6); - SETBITS(sXml10StartChars, 0xD8, 0xF6); - SETBITS(sXml10StartChars, 0xF8, 0xFF); - SETBITS(sXml10StartChars, 0x100, 0x131); - SETBITS(sXml10StartChars, 0x134, 0x13e); - SETBITS(sXml10StartChars, 0x141, 0x148); - SETBITS(sXml10StartChars, 0x14a, 0x17e); - SETBITS(sXml10StartChars, 0x180, 0x1c3); - SETBITS(sXml10StartChars, 0x1cd, 0x1f0); - SETBITS(sXml10StartChars, 0x1f4, 0x1f5); - SETBITS(sXml10StartChars, 0x1fa, 0x217); - SETBITS(sXml10StartChars, 0x250, 0x2a8); - SETBITS(sXml10StartChars, 0x2bb, 0x2c1); - SETBITS(sXml10StartChars, 0x386); - SETBITS(sXml10StartChars, 0x388, 0x38a); - SETBITS(sXml10StartChars, 0x38c); - SETBITS(sXml10StartChars, 0x38e, 0x3a1); - SETBITS(sXml10StartChars, 0x3a3, 0x3ce); - SETBITS(sXml10StartChars, 0x3d0, 0x3d6); - SETBITS(sXml10StartChars, 0x3da); - SETBITS(sXml10StartChars, 0x3dc); - SETBITS(sXml10StartChars, 0x3de); - SETBITS(sXml10StartChars, 0x3e0); - SETBITS(sXml10StartChars, 0x3e2, 0x3f3); - SETBITS(sXml10StartChars, 0x401, 0x40c); - SETBITS(sXml10StartChars, 0x40e, 0x44f); - SETBITS(sXml10StartChars, 0x451, 0x45c); - SETBITS(sXml10StartChars, 0x45e, 0x481); - SETBITS(sXml10StartChars, 0x490, 0x4c4); - SETBITS(sXml10StartChars, 0x4c7, 0x4c8); - SETBITS(sXml10StartChars, 0x4cb, 0x4cc); - SETBITS(sXml10StartChars, 0x4d0, 0x4eb); - SETBITS(sXml10StartChars, 0x4ee, 0x4f5); - SETBITS(sXml10StartChars, 0x4f8, 0x4f9); - - SETBITS(sXml10StartChars, 0x531, 0x556); - SETBITS(sXml10StartChars, 0x559); - SETBITS(sXml10StartChars, 0x561, 0x586); - SETBITS(sXml10StartChars, 0x5d0, 0x5ea); - SETBITS(sXml10StartChars, 0x5f0, 0x5f2); - SETBITS(sXml10StartChars, 0x621, 0x63a); - SETBITS(sXml10StartChars, 0x641, 0x64a); - SETBITS(sXml10StartChars, 0x671, 0x6b7); - SETBITS(sXml10StartChars, 0x6ba, 0x6be); - SETBITS(sXml10StartChars, 0x6c0, 0x6ce); - SETBITS(sXml10StartChars, 0x6d0, 0x6d3); - SETBITS(sXml10StartChars, 0x6d5); - - SETBITS(sXml10StartChars, 0x6e5, 0x6e6); - SETBITS(sXml10StartChars, 0x905, 0x939); - SETBITS(sXml10StartChars, 0x93d); - SETBITS(sXml10StartChars, 0x958, 0x961); - SETBITS(sXml10StartChars, 0x985, 0x98c); - SETBITS(sXml10StartChars, 0x98f, 0x990); - SETBITS(sXml10StartChars, 0x993, 0x9a8); - SETBITS(sXml10StartChars, 0x9aa, 0x9b0); - SETBITS(sXml10StartChars, 0x9b2); - SETBITS(sXml10StartChars, 0x9b6, 0x9b9); - SETBITS(sXml10StartChars, 0x9dc); - SETBITS(sXml10StartChars, 0x9dd); - SETBITS(sXml10StartChars, 0x9df, 0x9e1); - SETBITS(sXml10StartChars, 0x9f0); SETBITS(sXml10StartChars, 0x9f1); - SETBITS(sXml10StartChars, 0xA05, 0xA0A); - SETBITS(sXml10StartChars, 0xA0F); SETBITS(sXml10StartChars, 0xA10); - SETBITS(sXml10StartChars, 0xA13, 0xA28); - SETBITS(sXml10StartChars, 0xA2A, 0xA30); - SETBITS(sXml10StartChars, 0xA32); SETBITS(sXml10StartChars, 0xA33); - SETBITS(sXml10StartChars, 0xA35); SETBITS(sXml10StartChars, 0xA36); - SETBITS(sXml10StartChars, 0xA38); SETBITS(sXml10StartChars, 0xA39); - SETBITS(sXml10StartChars, 0xA59, 0xA5C); - SETBITS(sXml10StartChars, 0xA5E); - SETBITS(sXml10StartChars, 0xA72, 0xA74); - SETBITS(sXml10StartChars, 0xA85, 0xA8B); - SETBITS(sXml10StartChars, 0xA8D); - SETBITS(sXml10StartChars, 0xA8F, 0xA91); - SETBITS(sXml10StartChars, 0xA93, 0xAA8); - SETBITS(sXml10StartChars, 0xAAA, 0xAB0); - SETBITS(sXml10StartChars, 0xAB2, 0xAB3); - SETBITS(sXml10StartChars, 0xAB5, 0xAB9); - SETBITS(sXml10StartChars, 0xABD); - SETBITS(sXml10StartChars, 0xAE0); - SETBITS(sXml10StartChars, 0xB05, 0xB0C); - SETBITS(sXml10StartChars, 0xB0F); SETBITS(sXml10StartChars, 0xB10); - SETBITS(sXml10StartChars, 0xB13, 0xB28); - - SETBITS(sXml10StartChars, 0xB2A, 0xB30); - SETBITS(sXml10StartChars, 0xB32); SETBITS(sXml10StartChars, 0xB33); - SETBITS(sXml10StartChars, 0xB36, 0xB39); - SETBITS(sXml10StartChars, 0xB3D); - SETBITS(sXml10StartChars, 0xB5C); SETBITS(sXml10StartChars, 0xB5D); - SETBITS(sXml10StartChars, 0xB5F, 0xB61); - SETBITS(sXml10StartChars, 0xB85, 0xB8A); - SETBITS(sXml10StartChars, 0xB8E, 0xB90); - - SETBITS(sXml10StartChars, 0xB92, 0xB95); - SETBITS(sXml10StartChars, 0xB99, 0xB9A); - SETBITS(sXml10StartChars, 0xB9C); - SETBITS(sXml10StartChars, 0xB9E); SETBITS(sXml10StartChars, 0xB9F); - SETBITS(sXml10StartChars, 0xBA3); SETBITS(sXml10StartChars, 0xBA4); - SETBITS(sXml10StartChars, 0xBA8, 0xBAA); - SETBITS(sXml10StartChars, 0xBAE, 0xBB5); - SETBITS(sXml10StartChars, 0xBB7, 0xBB9); - SETBITS(sXml10StartChars, 0xC05, 0xC0C); - SETBITS(sXml10StartChars, 0xC0E, 0xC10); - - SETBITS(sXml10StartChars, 0xC12, 0xC28); - SETBITS(sXml10StartChars, 0xC2A, 0xC33); - SETBITS(sXml10StartChars, 0xC35, 0xC39); - SETBITS(sXml10StartChars, 0xC60); SETBITS(sXml10StartChars, 0xC61); - SETBITS(sXml10StartChars, 0xC85, 0xC8C); - SETBITS(sXml10StartChars, 0xC8E, 0xC90); - SETBITS(sXml10StartChars, 0xC92, 0xCA8); - SETBITS(sXml10StartChars, 0xCAA, 0xCB3); - SETBITS(sXml10StartChars, 0xCB5, 0xCB9); - SETBITS(sXml10StartChars, 0xCDE); - SETBITS(sXml10StartChars, 0xCE0); SETBITS(sXml10StartChars, 0xCE1); - SETBITS(sXml10StartChars, 0xD05, 0xD0C); - SETBITS(sXml10StartChars, 0xD0E, 0xD10); - SETBITS(sXml10StartChars, 0xD12, 0xD28); - SETBITS(sXml10StartChars, 0xD2A, 0xD39); - SETBITS(sXml10StartChars, 0xD60); SETBITS(sXml10StartChars, 0xD61); - SETBITS(sXml10StartChars, 0xE01, 0xE2E); - SETBITS(sXml10StartChars, 0xE30); - SETBITS(sXml10StartChars, 0xE32); SETBITS(sXml10StartChars, 0xE33); - SETBITS(sXml10StartChars, 0xE40, 0xE45); - SETBITS(sXml10StartChars, 0xE81); SETBITS(sXml10StartChars, 0xE82); - SETBITS(sXml10StartChars, 0xE84); - SETBITS(sXml10StartChars, 0xE87); SETBITS(sXml10StartChars, 0xE88); - SETBITS(sXml10StartChars, 0xE8A); SETBITS(sXml10StartChars, 0xE8D); - SETBITS(sXml10StartChars, 0xE94, 0xE97); - SETBITS(sXml10StartChars, 0xE99, 0xE9F); - SETBITS(sXml10StartChars, 0xEA1, 0xEA3); - SETBITS(sXml10StartChars, 0xEA5); SETBITS(sXml10StartChars, 0xEA7); - SETBITS(sXml10StartChars, 0xEAA); SETBITS(sXml10StartChars, 0xEAB); - SETBITS(sXml10StartChars, 0xEAD); SETBITS(sXml10StartChars, 0xEAE); - SETBITS(sXml10StartChars, 0xEB0); - SETBITS(sXml10StartChars, 0xEB2); SETBITS(sXml10StartChars, 0xEB3); - SETBITS(sXml10StartChars, 0xEBD); - - SETBITS(sXml10StartChars, 0xEC0, 0xEC4); - SETBITS(sXml10StartChars, 0xF40, 0xF47); - SETBITS(sXml10StartChars, 0xF49, 0xF69); - SETBITS(sXml10StartChars, 0x10a0, 0x10c5); - SETBITS(sXml10StartChars, 0x10d0, 0x10f6); - SETBITS(sXml10StartChars, 0x1100); - SETBITS(sXml10StartChars, 0x1102, 0x1103); - SETBITS(sXml10StartChars, 0x1105, 0x1107); - SETBITS(sXml10StartChars, 0x1109); - SETBITS(sXml10StartChars, 0x110b, 0x110c); - SETBITS(sXml10StartChars, 0x110e, 0x1112); - SETBITS(sXml10StartChars, 0x113c); - SETBITS(sXml10StartChars, 0x113e); - SETBITS(sXml10StartChars, 0x1140); - SETBITS(sXml10StartChars, 0x114c); - SETBITS(sXml10StartChars, 0x114e); - SETBITS(sXml10StartChars, 0x1150); - SETBITS(sXml10StartChars, 0x1154, 0x1155); - SETBITS(sXml10StartChars, 0x1159); - SETBITS(sXml10StartChars, 0x115f, 0x1161); - SETBITS(sXml10StartChars, 0x1163); - SETBITS(sXml10StartChars, 0x1165); - SETBITS(sXml10StartChars, 0x1167); - SETBITS(sXml10StartChars, 0x1169); - SETBITS(sXml10StartChars, 0x116d, 0x116e); - SETBITS(sXml10StartChars, 0x1172, 0x1173); - SETBITS(sXml10StartChars, 0x1175); - SETBITS(sXml10StartChars, 0x119e); - SETBITS(sXml10StartChars, 0x11a8); - SETBITS(sXml10StartChars, 0x11ab); - SETBITS(sXml10StartChars, 0x11ae, 0x11af); - SETBITS(sXml10StartChars, 0x11b7, 0x11b8); - SETBITS(sXml10StartChars, 0x11ba); - SETBITS(sXml10StartChars, 0x11bc, 0x11c2); - SETBITS(sXml10StartChars, 0x11eb); - SETBITS(sXml10StartChars, 0x11f0); - SETBITS(sXml10StartChars, 0x11f9); - SETBITS(sXml10StartChars, 0x1e00, 0x1e9b); - SETBITS(sXml10StartChars, 0x1ea0, 0x1ef9); - SETBITS(sXml10StartChars, 0x1f00, 0x1f15); - SETBITS(sXml10StartChars, 0x1f18, 0x1f1d); - SETBITS(sXml10StartChars, 0x1f20, 0x1f45); - SETBITS(sXml10StartChars, 0x1f48, 0x1f4d); - SETBITS(sXml10StartChars, 0x1f50, 0x1f57); - SETBITS(sXml10StartChars, 0x1f59); - SETBITS(sXml10StartChars, 0x1f5b); - SETBITS(sXml10StartChars, 0x1f5d); - SETBITS(sXml10StartChars, 0x1f5f, 0x1f7d); - SETBITS(sXml10StartChars, 0x1f80, 0x1fb4); - SETBITS(sXml10StartChars, 0x1fb6, 0x1fbc); - SETBITS(sXml10StartChars, 0x1fbe); - SETBITS(sXml10StartChars, 0x1fc2, 0x1fc4); - SETBITS(sXml10StartChars, 0x1fc6, 0x1fcc); - SETBITS(sXml10StartChars, 0x1fd0, 0x1fd3); - SETBITS(sXml10StartChars, 0x1fd6, 0x1fdb); - SETBITS(sXml10StartChars, 0x1fe0, 0x1fec); - SETBITS(sXml10StartChars, 0x1ff2, 0x1ff4); - SETBITS(sXml10StartChars, 0x1ff6, 0x1ffc); - SETBITS(sXml10StartChars, 0x2126); - SETBITS(sXml10StartChars, 0x212a, 0x212b); - SETBITS(sXml10StartChars, 0x212e); - SETBITS(sXml10StartChars, 0x2180, 0x2182); - SETBITS(sXml10StartChars, 0x3041, 0x3094); - SETBITS(sXml10StartChars, 0x30a1, 0x30fa); - SETBITS(sXml10StartChars, 0x3105, 0x312c); - // note: AC00 - D7A3 handled separately - - // [86] Ideographic (but note: > 0x312c handled separately) - SETBITS(sXml10StartChars, 0x3007); - SETBITS(sXml10StartChars, 0x3021, 0x3029); - } - - final static int[] sXml10Chars = new int[SIZE]; - static { - // Let's start with all valid start chars: - System.arraycopy(sXml10StartChars, 0, sXml10Chars, 0, SIZE); - - // [87] CombiningChar ::= - SETBITS(sXml10Chars, 0x300, 0x345); - SETBITS(sXml10Chars, 0x360, 0x361); - SETBITS(sXml10Chars, 0x483, 0x486); - SETBITS(sXml10Chars, 0x591, 0x5a1); - SETBITS(sXml10Chars, 0x5a3, 0x5b9); - SETBITS(sXml10Chars, 0x5bb, 0x5bd); - SETBITS(sXml10Chars, 0x5bf); - - SETBITS(sXml10Chars, 0x5c1, 0x5c2); - SETBITS(sXml10Chars, 0x5c4); - SETBITS(sXml10Chars, 0x64b, 0x652); - SETBITS(sXml10Chars, 0x670); - SETBITS(sXml10Chars, 0x6d6, 0x6dc); - SETBITS(sXml10Chars, 0x6dd, 0x6df); - SETBITS(sXml10Chars, 0x6e0, 0x6e4); - SETBITS(sXml10Chars, 0x6e7, 0x6e8); - SETBITS(sXml10Chars, 0x6ea, 0x6ed); - - SETBITS(sXml10Chars, 0x901, 0x903); - SETBITS(sXml10Chars, 0x93c); - SETBITS(sXml10Chars, 0x93e, 0x94c); - SETBITS(sXml10Chars, 0x94d); - SETBITS(sXml10Chars, 0x951, 0x954); - SETBITS(sXml10Chars, 0x962); SETBITS(sXml10Chars, 0x963); - SETBITS(sXml10Chars, 0x981, 0x983); - SETBITS(sXml10Chars, 0x9bc); - SETBITS(sXml10Chars, 0x9be); SETBITS(sXml10Chars, 0x9bf); - SETBITS(sXml10Chars, 0x9c0, 0x9c4); - SETBITS(sXml10Chars, 0x9c7); SETBITS(sXml10Chars, 0x9c8); - SETBITS(sXml10Chars, 0x9cb, 0x9cd); - SETBITS(sXml10Chars, 0x9d7); - SETBITS(sXml10Chars, 0x9e2); SETBITS(sXml10Chars, 0x9e3); - SETBITS(sXml10Chars, 0xA02); - SETBITS(sXml10Chars, 0xA3C); - SETBITS(sXml10Chars, 0xA3E); SETBITS(sXml10Chars, 0xA3F); - SETBITS(sXml10Chars, 0xA40, 0xA42); - SETBITS(sXml10Chars, 0xA47); SETBITS(sXml10Chars, 0xA48); - SETBITS(sXml10Chars, 0xA4B, 0xA4D); - SETBITS(sXml10Chars, 0xA70); SETBITS(sXml10Chars, 0xA71); - SETBITS(sXml10Chars, 0xA81, 0xA83); - SETBITS(sXml10Chars, 0xABC); - SETBITS(sXml10Chars, 0xABE, 0xAC5); - SETBITS(sXml10Chars, 0xAC7, 0xAC9); - SETBITS(sXml10Chars, 0xACB, 0xACD); - SETBITS(sXml10Chars, 0xB01, 0xB03); - SETBITS(sXml10Chars, 0xB3C); - SETBITS(sXml10Chars, 0xB3E, 0xB43); - SETBITS(sXml10Chars, 0xB47); SETBITS(sXml10Chars, 0xB48); - SETBITS(sXml10Chars, 0xB4B, 0xB4D); - SETBITS(sXml10Chars, 0xB56); SETBITS(sXml10Chars, 0xB57); - SETBITS(sXml10Chars, 0xB82); SETBITS(sXml10Chars, 0xB83); - SETBITS(sXml10Chars, 0xBBE, 0xBC2); - SETBITS(sXml10Chars, 0xBC6, 0xBC8); - SETBITS(sXml10Chars, 0xBCA, 0xBCD); - SETBITS(sXml10Chars, 0xBD7); - SETBITS(sXml10Chars, 0xC01, 0xC03); - SETBITS(sXml10Chars, 0xC3E, 0xC44); - SETBITS(sXml10Chars, 0xC46, 0xC48); - SETBITS(sXml10Chars, 0xC4A, 0xC4D); - SETBITS(sXml10Chars, 0xC55, 0xC56); - SETBITS(sXml10Chars, 0xC82, 0xC83); - SETBITS(sXml10Chars, 0xCBE, 0xCC4); - SETBITS(sXml10Chars, 0xCC6, 0xCC8); - SETBITS(sXml10Chars, 0xCCA, 0xCCD); - SETBITS(sXml10Chars, 0xCD5, 0xCD6); - SETBITS(sXml10Chars, 0xD02, 0xD03); - SETBITS(sXml10Chars, 0xD3E, 0xD43); - SETBITS(sXml10Chars, 0xD46, 0xD48); - SETBITS(sXml10Chars, 0xD4A, 0xD4D); - SETBITS(sXml10Chars, 0xD57); - SETBITS(sXml10Chars, 0xE31); - SETBITS(sXml10Chars, 0xE34, 0xE3A); - SETBITS(sXml10Chars, 0xE47, 0xE4E); - SETBITS(sXml10Chars, 0xEB1); - SETBITS(sXml10Chars, 0xEB4, 0xEB9); - SETBITS(sXml10Chars, 0xEBB, 0xEBC); - SETBITS(sXml10Chars, 0xEC8, 0xECD); - SETBITS(sXml10Chars, 0xF18, 0xF19); - SETBITS(sXml10Chars, 0xF35); SETBITS(sXml10Chars, 0xF37); - SETBITS(sXml10Chars, 0xF39); - SETBITS(sXml10Chars, 0xF3E); SETBITS(sXml10Chars, 0xF3F); - SETBITS(sXml10Chars, 0xF71, 0xF84); - SETBITS(sXml10Chars, 0xF86, 0xF8B); - SETBITS(sXml10Chars, 0xF90, 0xF95); - SETBITS(sXml10Chars, 0xF97); - SETBITS(sXml10Chars, 0xF99, 0xFAD); - SETBITS(sXml10Chars, 0xFB1, 0xFB7); - SETBITS(sXml10Chars, 0xFB9); - SETBITS(sXml10Chars, 0x20D0, 0x20DC); - SETBITS(sXml10Chars, 0x20E1); - SETBITS(sXml10Chars, 0x302A, 0x302F); - SETBITS(sXml10Chars, 0x3099); SETBITS(sXml10Chars, 0x309A); - // [88] Digit: - SETBITS(sXml10Chars, 0x660, 0x669); - SETBITS(sXml10Chars, 0x6f0, 0x6f9); - SETBITS(sXml10Chars, 0x966, 0x96f); - SETBITS(sXml10Chars, 0x9e6, 0x9ef); - SETBITS(sXml10Chars, 0xa66, 0xa6f); - SETBITS(sXml10Chars, 0xae6, 0xaef); - SETBITS(sXml10Chars, 0xb66, 0xb6f); - SETBITS(sXml10Chars, 0xbe7, 0xbef); - SETBITS(sXml10Chars, 0xc66, 0xc6f); - SETBITS(sXml10Chars, 0xce6, 0xcef); - SETBITS(sXml10Chars, 0xd66, 0xd6f); - SETBITS(sXml10Chars, 0xe50, 0xe59); - SETBITS(sXml10Chars, 0xed0, 0xed9); - SETBITS(sXml10Chars, 0xf20, 0xf29); - - // [89] Extender: - SETBITS(sXml10Chars, 0xb7); - SETBITS(sXml10Chars, 0x2d0); - SETBITS(sXml10Chars, 0x2d1); - SETBITS(sXml10Chars, 0x387); - SETBITS(sXml10Chars, 0x640); - SETBITS(sXml10Chars, 0xE46); - SETBITS(sXml10Chars, 0xEC6); - SETBITS(sXml10Chars, 0x3005); - SETBITS(sXml10Chars, 0x3031, 0x3035); - SETBITS(sXml10Chars, 0x309d, 0x309e); - SETBITS(sXml10Chars, 0x30fc, 0x30fe); - } - - private XmlChars() { } - - public final static boolean is10NameStartChar(char c) - { - // First, let's deal with outliers - if (c > 0x312C) { // Most valid chars are below this.. - if (c < 0xAC00) { - return (c >= 0x4E00 && c <= 0x9FA5); // valid ideograms - } - if (c <= 0xD7A3) { // 0xAC00 - 0xD7A3, valid base chars - return true; - } - /* As to surrogate pairs... let's do the bare minimum; - * 0xD800 - 0xDBFF (high surrogate) are ok; low surrogates - * can only follow high one - */ - return (c <= 0xDBFF && c >= 0xD800); - } - // but then we'll just need to use the table... - int ix = (int) c; - return (sXml10StartChars[ix >> 5] & (1 << (ix & 31))) != 0; - } - - public final static boolean is10NameChar(char c) - { - // First, let's deal with outliers - if (c > 0x312C) { // Most valid chars are below this.. - if (c < 0xAC00) { - return (c >= 0x4E00 && c <= 0x9FA5); // valid ideograms - } - if (c <= 0xD7A3) { // 0xAC00 - 0xD7A3, valid base chars - return true; - } - /* As to surrogate pairs... let's do the bare minimum; - * 0xD800 - 0xDFFF (high, low surrogate) are ok (need to - * check pairing in future) - */ - return (c >= 0xD800 && c <= 0xDFFF); - } - // but then we'll just need to use the table... - int ix = (int) c; - return (sXml10Chars[ix >> 5] & (1 << (ix & 31))) != 0; - } - - public final static boolean is11NameStartChar(char c) - { - // Others are checked block-by-block: - if (c <= 0x2FEF) { - if (c < 0x300) { - if (c < 0x00C0) { // 8-bit ctrl chars - return false; - } - // most of the rest are fine... - return (c != 0xD7 && c != 0xF7); - } - if (c >= 0x2C00) { - // 0x2C00 - 0x2FEF are ok - return true; - } - if (c < 0x370 || c > 0x218F) { - // 0x300 - 0x36F, 0x2190 - 0x2BFF invalid - return false; - } - if (c < 0x2000) { - // 0x370 - 0x37D, 0x37F - 0x1FFF are ok - return (c != 0x37E); - } - if (c >= 0x2070) { - // 0x2070 - 0x218F are ok - return (c <= 0x218F); - } - // And finally, 0x200C - 0x200D - return (c == 0x200C || c == 0x200D); - } - - // 0x3000 and above: - if (c >= 0x3001) { - /* Hmmh, let's allow high surrogates here, without checking - * that they are properly followed... crude basic support, - * I know, but allows valid combinations, just doesn't catch - * invalid ones - */ - if (c <= 0xDBFF) { // 0x3001 - 0xD7FF (chars), - // 0xD800 - 0xDBFF (high surrogate) are ok (unlike DC00-DFFF) - return true; - } - if (c >= 0xF900 && c <= 0xFFFD) { - /* Check above removes low surrogate (since one can not - * START an identifier), and byte-order markers.. - */ - return (c <= 0xFDCF || c >= 0xFDF0); - } - } - - return false; - } - - public final static boolean is11NameChar(char c) - { - // Others are checked block-by-block: - if (c <= 0x2FEF) { - if (c < 0x2000) { // only 8-bit ctrl chars and 0x37E to filter out - return (c >= 0x00C0 && c != 0x37E) || (c == 0xB7); - } - if (c >= 0x2C00) { - // 0x100 - 0x1FFF, 0x2C00 - 0x2FEF are ok - return true; - } - if (c < 0x200C || c > 0x218F) { - // 0x2000 - 0x200B, 0x2190 - 0x2BFF invalid - return false; - } - if (c >= 0x2070) { - // 0x2070 - 0x218F are ok - return true; - } - // And finally, 0x200C - 0x200D, 0x203F - 0x2040 are ok - return (c == 0x200C || c == 0x200D - || c == 0x203F || c == 0x2040); - } - - // 0x3000 and above: - if (c >= 0x3001) { - /* Hmmh, let's allow surrogate heres, without checking that - * they have proper ordering. For non-first name chars, both are - * ok, for valid names. Crude basic support, - * I know, but allows valid combinations, just doesn't catch - * invalid ones - */ - if (c <= 0xDFFF) { // 0x3001 - 0xD7FF (chars), - // 0xD800 - 0xDFFF (high, low surrogate) are ok: - return true; - } - if (c >= 0xF900 && c <= 0xFFFD) { - /* Check above removes other invalid chars (below valid - * range), and byte-order markers (0xFFFE, 0xFFFF). - */ - return (c <= 0xFDCF || c >= 0xFDF0); - } - } - - return false; - } - - private static void SETBITS(int[] array, int start, int end) - { - int bit1 = (start & 31); - int bit2 = (end & 31); - start >>= 5; - end >>= 5; - - /* Ok; this is not perfectly optimal, but should be good enough... - * we'll only do one-by-one at the ends. - */ - if (start == end) { - for (; bit1 <= bit2; ++bit1) { - array[start] |= (1 << bit1); - } - } else { - for (int bit = bit1; bit <= 31; ++bit) { - array[start] |= (1 << bit); - } - while (++start < end) { - array[start] = -1; - } - for (int bit = 0; bit <= bit2; ++bit) { - array[end] |= (1 << bit); - } - } - } - - private static void SETBITS(int[] array, int point) { - int ix = (point >> 5); - int bit = (point & 31); - - array[ix] |= (1 << bit); - } -} diff -Nru libwoodstox-java-4.1.3/src/java/org/codehaus/stax2/ri/package.html libwoodstox-java-5.1.0/src/java/org/codehaus/stax2/ri/package.html --- libwoodstox-java-4.1.3/src/java/org/codehaus/stax2/ri/package.html 2012-04-24 04:38:21.000000000 +0000 +++ libwoodstox-java-5.1.0/src/java/org/codehaus/stax2/ri/package.html 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ - -Package that contains a skeletal reference implementation of Stax2 API, -as well as some utility/helper classes that can be useful in building -one. - diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/api/CommonConfig.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/api/CommonConfig.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/api/CommonConfig.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/api/CommonConfig.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,282 @@ +package com.ctc.wstx.api; + +import java.util.*; + +import org.codehaus.stax2.XMLStreamProperties; + +import com.ctc.wstx.util.ArgUtil; + +/** + * Shared common base class for variour configuration container implementations + * for public factories Woodstox uses: implementations of + * {@link javax.xml.stream.XMLInputFactory}, + * {@link javax.xml.stream.XMLOutputFactory} and + * {@link org.codehaus.stax2.validation.XMLValidationSchemaFactory}. + * Implements basic settings for some shared settings, defined by the + * shared property interface {@link XMLStreamProperties}. + */ +abstract class CommonConfig + implements XMLStreamProperties +{ + /* + /////////////////////////////////////////////////////////////////////// + // Implementation info + /////////////////////////////////////////////////////////////////////// + */ + + protected final static String IMPL_NAME = "woodstox"; + + /* !!! TBI: get from props file or so? Or build as part of Ant + * build process? + */ + /** + * This is "major.minor" version used for purposes of determining + * the feature set. Patch level is not included, since those should + * not affect API or feature set. Using applications should be + * prepared to take additional levels, however, just not depend + * on those being available. + */ + protected final static String IMPL_VERSION = "5.0"; + + /* + /////////////////////////////////////////////////////////////////////// + // Internal constants + /////////////////////////////////////////////////////////////////////// + */ + + final static int CPROP_IMPL_NAME = 1; + final static int CPROP_IMPL_VERSION = 2; + + final static int CPROP_SUPPORTS_XML11 = 3; + final static int CPROP_SUPPORT_XMLID = 4; + + final static int CPROP_RETURN_NULL_FOR_DEFAULT_NAMESPACE = 5; + + /** + * Map to use for converting from String property ids to enumeration + * (ints). Used for faster dispatching. + */ + final static HashMap sStdProperties = new HashMap(16); + static { + // Basic information about the implementation: + sStdProperties.put(XMLStreamProperties.XSP_IMPLEMENTATION_NAME, CPROP_IMPL_NAME); + sStdProperties.put(XMLStreamProperties.XSP_IMPLEMENTATION_VERSION, CPROP_IMPL_VERSION); + + // XML version support: + sStdProperties.put(XMLStreamProperties.XSP_SUPPORTS_XML11, CPROP_SUPPORTS_XML11); + + // Xml:id support: + sStdProperties.put(XMLStreamProperties.XSP_SUPPORT_XMLID, CPROP_SUPPORT_XMLID); + + sStdProperties.put(WstxInputProperties.P_RETURN_NULL_FOR_DEFAULT_NAMESPACE, + CPROP_RETURN_NULL_FOR_DEFAULT_NAMESPACE); + + /* 23-Apr-2008, tatus: Additional interoperability property, + * one that Sun implementation uses. Can map to Stax2 + * property quite easily. + */ + sStdProperties.put("http://java.sun.com/xml/stream/properties/implementation-name", + CPROP_IMPL_NAME); + } + + /* + /////////////////////////////////////////////////////////////////////// + // Shared config + /////////////////////////////////////////////////////////////////////// + */ + + /** + * As per [WSTX-277], can specify whether prefix for the + * "default namespace" is return as null (true) or empty String (false) + */ + protected boolean mReturnNullForDefaultNamespace; + + /* + /////////////////////////////////////////////////////////////////////// + // Construction + /////////////////////////////////////////////////////////////////////// + */ + + /** + * Constructor used by sub-classes + * + * @param base Base instance to copy settings from, if any; null for + * 'root' configuration objects. + */ + protected CommonConfig(CommonConfig base) { + mReturnNullForDefaultNamespace = (base == null) + /* 27-Mar-2018, tatu: What the hell... why does it take it from System properties? + * I should have done better code review; Woodstox should not do that. + * System properties are evil for shared libraries, not to be used. + */ + ? Boolean.getBoolean(WstxInputProperties.P_RETURN_NULL_FOR_DEFAULT_NAMESPACE) + : base.mReturnNullForDefaultNamespace; + } + + /* + /////////////////////////////////////////////////////////////////////// + // Public API, generic StAX config methods + /////////////////////////////////////////////////////////////////////// + */ + + public Object getProperty(String propName) + { + /* Related to [WSTX-243]; would be nice to not to have to throw an + * exception; but Stax spec suggests that we do need to indicate + * unrecognized property by exception. + */ + int id = findPropertyId(propName); + if (id >= 0) { + return getProperty(id); + } + id = findStdPropertyId(propName); + if (id < 0) { + reportUnknownProperty(propName); + return null; + } + return getStdProperty(id); + } + + public boolean isPropertySupported(String propName) + { + return (findPropertyId(propName) >= 0) + || (findStdPropertyId(propName) >= 0); + } + + /** + * @return True, if the specified property was successfully + * set to specified value; false if its value was not changed + */ + public boolean setProperty(String propName, Object value) + { + int id = findPropertyId(propName); + if (id >= 0) { + return setProperty(propName, id, value); + } + id = findStdPropertyId(propName); + if (id < 0) { + reportUnknownProperty(propName); + return false; + } + return setStdProperty(propName, id, value); + } + + protected void reportUnknownProperty(String propName) + { + // see [WSTX-243] for discussion on whether to throw... + throw new IllegalArgumentException("Unrecognized property '"+propName+"'"); + } + + /* + /////////////////////////////////////////////////////////////////////// + // Additional methods used by Woodstox core + /////////////////////////////////////////////////////////////////////// + */ + + public final Object safeGetProperty(String propName) + { + int id = findPropertyId(propName); + if (id >= 0) { + return getProperty(id); + } + id = findStdPropertyId(propName); + if (id < 0) { + return null; + } + return getStdProperty(id); + } + + /** + * Method used to figure out the official implementation name + * for input/output/validation factories. + */ + public static String getImplName() { return IMPL_NAME; } + + /** + * Method used to figure out the official implementation version + * for input/output/validation factories. + */ + public static String getImplVersion() { return IMPL_VERSION; } + + /* + /////////////////////////////////////////////////////////////////////// + // Interface sub-classes have to implement / can override + /////////////////////////////////////////////////////////////////////// + */ + + /** + * @return Internal enumerated int matching the String name + * of the property, if one found: -1 to indicate no match + * was found. + */ + protected abstract int findPropertyId(String propName); + + public boolean doesSupportXml11() { + /* Woodstox does support xml 1.1 ... but sub-classes can + * override it if/as necessary (validator factories might not + * support it?) + */ + return true; + } + + public boolean doesSupportXmlId() { + /* Woodstox does support Xml:id ... but sub-classes can + * override it if/as necessary. + */ + return true; + } + + public boolean returnNullForDefaultNamespace() { + return mReturnNullForDefaultNamespace; + } + + protected abstract Object getProperty(int id); + + protected abstract boolean setProperty(String propName, int id, Object value); + + /* + /////////////////////////////////////////////////////////////////////// + // Internal methods + /////////////////////////////////////////////////////////////////////// + */ + + protected int findStdPropertyId(String propName) + { + Integer I = sStdProperties.get(propName); + return (I == null) ? -1 : I.intValue(); + } + + /** + * @param propName Name of standard property to set + * @param id Internal id matching the name + * @param value Value to set the standard property to + */ + protected boolean setStdProperty(String propName, int id, Object value) + { + // Only one settable property... + switch (id) { + case CPROP_RETURN_NULL_FOR_DEFAULT_NAMESPACE: + mReturnNullForDefaultNamespace = ArgUtil.convertToBoolean(propName, value); + return true; + } + return false; + } + + protected Object getStdProperty(int id) + { + switch (id) { + case CPROP_IMPL_NAME: + return IMPL_NAME; + case CPROP_IMPL_VERSION: + return IMPL_VERSION; + case CPROP_SUPPORTS_XML11: + return doesSupportXml11() ? Boolean.TRUE : Boolean.FALSE; + case CPROP_SUPPORT_XMLID: + return doesSupportXmlId() ? Boolean.TRUE : Boolean.FALSE; + case CPROP_RETURN_NULL_FOR_DEFAULT_NAMESPACE: + return returnNullForDefaultNamespace() ? Boolean.TRUE : Boolean.FALSE; + default: // sanity check, should never happen + throw new IllegalStateException("Internal error: no handler for property with internal id "+id+"."); + } + } +} diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/api/EmptyElementHandler.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/api/EmptyElementHandler.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/api/EmptyElementHandler.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/api/EmptyElementHandler.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,82 @@ +package com.ctc.wstx.api; + +import java.util.Set; +import java.util.TreeSet; + +/** + * Optional handler used to determine if a specific empty element (by name) should + * be allowed to use the self-closing syntax instead of having a separate end tag. + * + * @since 4.1 + */ +public interface EmptyElementHandler +{ + /** + * @param prefix The element's namespace prefix, null if not set + * @param localName The element's local name + * @param nsURI The elements's namespace URI, null if not set + * @param allowEmpty The allow empty setting specified by the caller. + * @return True if the empty element can be self-closing. False if a separate end tag should be written. + */ + public boolean allowEmptyElement(String prefix, String localName, String nsURI, boolean allowEmpty); + + /** + * Handler that uses a Set of Strings. If the local part of the element's QName is contained + * in the Set the element is allowed to be empty. + *

+ * Users of this class are encouraged to use a {@link TreeSet} with the {@link String#CASE_INSENSITIVE_ORDER} + * comparator if case-insensitive comparison is needed (like when dealing with HTML tags). + */ + public static class SetEmptyElementHandler + implements EmptyElementHandler + { + final protected Set mEmptyElements; + + public SetEmptyElementHandler(Set emptyElements) + { + mEmptyElements = emptyElements; + } + + @Override + public boolean allowEmptyElement(String prefix, String localName, String nsURI, boolean allowEmpty) + { + return mEmptyElements.contains(localName); + } + } + + /** + * HTML specific empty element handler. + * Extends the {@link SetEmptyElementHandler} and configures + * the HTML elements that must be self-closing according to the W3C: + * http://www.w3.org/TR/html4/index/elements.html + *

+ * Note that element name comparison is case-insensitive as required + * by HTML specification. + */ + public static class HtmlEmptyElementHandler + extends SetEmptyElementHandler + { + private final static HtmlEmptyElementHandler sInstance = new HtmlEmptyElementHandler(); + + public static HtmlEmptyElementHandler getInstance() { return sInstance; } + + protected HtmlEmptyElementHandler() + { + super(new TreeSet(String.CASE_INSENSITIVE_ORDER)); + mEmptyElements.add("area"); + mEmptyElements.add("base"); + mEmptyElements.add("basefont"); + mEmptyElements.add("br"); + mEmptyElements.add("col"); + mEmptyElements.add("frame"); + mEmptyElements.add("hr"); + mEmptyElements.add("input"); + mEmptyElements.add("img"); + mEmptyElements.add("isindex"); + mEmptyElements.add("link"); + mEmptyElements.add("meta"); + mEmptyElements.add("param"); + } + } +} + diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/api/InvalidCharHandler.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/api/InvalidCharHandler.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/api/InvalidCharHandler.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/api/InvalidCharHandler.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,91 @@ +package com.ctc.wstx.api; + +import java.io.IOException; + +/** + * Simple converter interface designed to be used with stream writer property + * {@link WstxOutputProperties#P_OUTPUT_INVALID_CHAR_HANDLER}. + * The idea is that it should be easy to have a way to convert invalid + * characters such as Ascii control characters into something that + * is legal to include in XML content. This only allows for simple + * char-by-char replacements, instead of something more advanced such + * as escaping. If escaping is needed, check out + * {@link org.codehaus.stax2.XMLOutputFactory2#P_TEXT_ESCAPER} instead. + *

+ * Note about exceptions: choice of only allowing throwing of + * {@link IOException}s is due to the way Woodstox stream writer + * backend works; XmlWriter can only throw IOExceptions. + */ +public interface InvalidCharHandler +{ + public char convertInvalidChar(int invalidChar) throws IOException; + + /** + * This handler implementation just throws an exception for + * all invalid characters encountered. It is the default handler + * used if nothing else has been specified. + */ + public static class FailingHandler + implements InvalidCharHandler + { + public final static int SURR1_FIRST = 0xD800; + public final static int SURR1_LAST = 0xDBFF; + public final static int SURR2_FIRST = 0xDC00; + public final static int SURR2_LAST = 0xDFFF; + + private final static FailingHandler sInstance = new FailingHandler(); + + protected FailingHandler() { } + + public static FailingHandler getInstance() { return sInstance; } + + @Override + public char convertInvalidChar(int c) throws IOException + { + /* 17-May-2006, TSa: Would really be useful if we could throw + * XMLStreamExceptions; esp. to indicate actual output location. + * However, this causes problem with methods that call us and + * can only throw IOExceptions (when invoked via Writer proxy). + * Need to figure out how to resolve this. + */ + if (c == 0) { + throw new IOException("Invalid null character in text to output"); + } + if (c < ' ' || (c >= 0x7F && c <= 0x9F)) { + String msg = "Invalid white space character (0x"+Integer.toHexString(c)+") in text to output (in xml 1.1, could output as a character entity)"; + throw new IOException(msg); + } + if (c > 0x10FFFF) { + throw new IOException("Illegal unicode character point (0x"+Integer.toHexString(c)+") to output; max is 0x10FFFF as per RFC 3629"); + } + /* Surrogate pair in non-quotable (not text or attribute value) + * content, and non-unicode encoding (ISO-8859-x, Ascii)? + */ + if (c >= SURR1_FIRST && c <= SURR2_LAST) { + throw new IOException("Illegal surrogate pair -- can only be output via character entities, which are not allowed in this content"); + } + throw new IOException("Invalid XML character (0x"+Integer.toHexString(c)+") in text to output"); + } + } + + /** + * Alternative to the default handler, this handler converts all invalid + * characters to the specified output character. That character will + * not be further verified or modified by the stream writer. + */ + public static class ReplacingHandler + implements InvalidCharHandler + { + final char mReplacementChar; + + public ReplacingHandler(char c) { + mReplacementChar = c; + } + + @Override + public char convertInvalidChar(int c) throws IOException { + return mReplacementChar; + } + } +} + diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/api/package.html libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/api/package.html --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/api/package.html 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/api/package.html 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,7 @@ + +Package that contains subset of Woodstox classes that are considered to be +its public API (in addition to regular Stax 1.0 -- javax.xml.stream.* -- and +Stax2 -- org.codehaus.stax2.*). This means that application code can rely +on these classes, and effort is made to keep them backwards compatible +between releases. + diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/api/ReaderConfig.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/api/ReaderConfig.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/api/ReaderConfig.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/api/ReaderConfig.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,1696 @@ +package com.ctc.wstx.api; + +import java.lang.ref.SoftReference; +import java.net.URL; +import java.util.*; + +import javax.xml.stream.*; + +import org.codehaus.stax2.XMLInputFactory2; // for property consts +import org.codehaus.stax2.XMLStreamProperties; // for property consts +import org.codehaus.stax2.validation.DTDValidationSchema; + +import com.ctc.wstx.api.WstxInputProperties; +import com.ctc.wstx.cfg.InputConfigFlags; +import com.ctc.wstx.dtd.DTDEventListener; +import com.ctc.wstx.ent.IntEntity; +import com.ctc.wstx.ent.EntityDecl; +import com.ctc.wstx.io.BufferRecycler; +import com.ctc.wstx.util.ArgUtil; +import com.ctc.wstx.util.DataUtil; +import com.ctc.wstx.util.SymbolTable; + +/** + * Simple configuration container class; passed by reader factory to reader + * instance created. + *

+ * In addition to its main task as a configuration container, this class + * also acts as a wrapper around simple buffer recycling functionality. + * The reason is that while conceptually this is a separate concern, + * there are enough commonalities with the life-cycle of this object to + * make this a very convenience place to add that functionality... + * (that is: conceptually this is not right, but from pragmatic viewpoint + * it just makes sense) + */ +public final class ReaderConfig + extends CommonConfig + implements InputConfigFlags +{ + // Default limit values + + public final static int DEFAULT_MAX_ATTRIBUTES_PER_ELEMENT = 1000; + public final static int DEFAULT_MAX_ATTRIBUTE_LENGTH = 65536 * 8; + + public final static int DEFAULT_MAX_ELEMENT_DEPTH = 1000; + + public final static int DEFAULT_MAX_ENTITY_DEPTH = 500; + public final static int DEFAULT_MAX_ENTITY_COUNT = 100 * 1000; + + /* + /////////////////////////////////////////////////////////////////////// + // Constants for reader properties: + /////////////////////////////////////////////////////////////////////// + */ + + // // First, standard StAX properties: + + // Simple flags: + final static int PROP_COALESCE_TEXT = 1; + final static int PROP_NAMESPACE_AWARE = 2; + final static int PROP_REPLACE_ENTITY_REFS = 3; + final static int PROP_SUPPORT_EXTERNAL_ENTITIES = 4; + final static int PROP_VALIDATE_AGAINST_DTD = 5; + final static int PROP_SUPPORT_DTD = 6; + + // Object type properties + public final static int PROP_EVENT_ALLOCATOR = 7; + final static int PROP_WARNING_REPORTER = 8; + final static int PROP_XML_RESOLVER = 9; + + // // Then StAX2 standard properties: + + // Simple flags: + final static int PROP_INTERN_NS_URIS = 20; + final static int PROP_INTERN_NAMES = 21; + final static int PROP_REPORT_CDATA = 22; + final static int PROP_REPORT_PROLOG_WS = 23; + final static int PROP_PRESERVE_LOCATION = 24; + final static int PROP_AUTO_CLOSE_INPUT = 25; + + // Enum / Object type properties: + final static int PROP_SUPPORT_XMLID = 26; // shared with WriterConfig + final static int PROP_DTD_OVERRIDE = 27; + + // // // Constants for additional Wstx properties: + + // Simple flags: + + /** + * Note: this entry was deprecated for 4.0 versions up until + * and including 4.0.7; was brought back for 4.0.8 (and will + * be retained for 4.1) + */ + final static int PROP_NORMALIZE_LFS = 40; + + /* This entry was deprecated for 3.2 and removed in 4.0 + * version. There are no plans to bring it back. + */ + //final static int PROP_NORMALIZE_ATTR_VALUES = 41; + + final static int PROP_CACHE_DTDS = 42; + final static int PROP_CACHE_DTDS_BY_PUBLIC_ID = 43; + final static int PROP_LAZY_PARSING = 44; + final static int PROP_SUPPORT_DTDPP = 45; + final static int PROP_TREAT_CHAR_REFS_AS_ENTS = 46; + + // Object type properties: + + final static int PROP_INPUT_BUFFER_LENGTH = 50; + //final static int PROP_TEXT_BUFFER_LENGTH = 51; + final static int PROP_MIN_TEXT_SEGMENT = 52; + final static int PROP_CUSTOM_INTERNAL_ENTITIES = 53; + final static int PROP_DTD_RESOLVER = 54; + final static int PROP_ENTITY_RESOLVER = 55; + final static int PROP_UNDECLARED_ENTITY_RESOLVER = 56; + final static int PROP_BASE_URL = 57; + final static int PROP_INPUT_PARSING_MODE = 58; + + // Size limitation to prevent various DOS attacks + final static int PROP_MAX_ATTRIBUTES_PER_ELEMENT = 60; + final static int PROP_MAX_CHILDREN_PER_ELEMENT = 61; + final static int PROP_MAX_ELEMENT_COUNT = 62; + final static int PROP_MAX_ELEMENT_DEPTH = 63; + final static int PROP_MAX_CHARACTERS = 64; + final static int PROP_MAX_ATTRIBUTE_SIZE = 65; + final static int PROP_MAX_TEXT_LENGTH = 66; + final static int PROP_MAX_ENTITY_COUNT = 67; + final static int PROP_MAX_ENTITY_DEPTH = 68; + + /* + //////////////////////////////////////////////// + // Limits for numeric properties + //////////////////////////////////////////////// + */ + + /** + * Need to set a minimum size, since there are some limitations to + * smallest consequtive block that can be used. + */ + final static int MIN_INPUT_BUFFER_LENGTH = 8; // 16 bytes + + /** + * Let's allow caching of just a dozen DTDs... shouldn't really + * matter, how many DTDs does one really use? + */ + final static int DTD_CACHE_SIZE_J2SE = 12; + + final static int DTD_CACHE_SIZE_J2ME = 5; + + /* + /////////////////////////////////////////////////////////////////////// + // Default values for custom properties: + /////////////////////////////////////////////////////////////////////// + */ + + /** + * By default, let's require minimum of 64 chars to be delivered + * as shortest partial (piece of) text (CDATA, text) segment; + * same for both J2ME subset and full readers. Prevents tiniest + * runts from getting passed + */ + final static int DEFAULT_SHORTEST_TEXT_SEGMENT = 64; + + /** + * Default config flags are converted from individual settings, + * to conform to StAX 1.0 specifications. + */ + final static int DEFAULT_FLAGS_FULL = + 0 + // First, default settings StAX specs dictate: + + | CFG_NAMESPACE_AWARE + // Coalescing to be disabled + //| CFG_COALESCE_TEXT + | CFG_REPLACE_ENTITY_REFS + | CFG_SUPPORT_EXTERNAL_ENTITIES + | CFG_SUPPORT_DTD + + // and then custom setting defaults: + + // and namespace URI interning + | CFG_INTERN_NAMES + | CFG_INTERN_NS_URIS + + // we will also accurately report CDATA, by default + | CFG_REPORT_CDATA + + /* 20-Jan-2006, TSa: As per discussions on stax-builders list + * (and input from xml experts), 4.0 will revert to "do not + * report SPACE events outside root element by default" + * settings. Conceptually this is what xml specification + * implies should be done: there is no content outside of + * the element tree, including any ignorable content, just + * processing instructions and comments. + */ + //| CFG_REPORT_PROLOG_WS + + /* but enable DTD caching (if they are handled): + * (... maybe J2ME subset shouldn't do it?) + */ + | CFG_CACHE_DTDS + /* 29-Mar-2006, TSa: But note, no caching by public-id, due + * to problems with cases where public-id/system-id were + * inconsistently used, leading to problems. + */ + + /* by default, let's also allow lazy parsing, since it tends + * to improve performance + */ + | CFG_LAZY_PARSING + + /* and also make Event objects preserve location info... + * can be turned off for maximum performance + */ + | CFG_PRESERVE_LOCATION + + // As per Stax 1.0 specs, we can not enable this by default: + //| CFG_AUTO_CLOSE_INPUT); + + /* Also, let's enable dtd++ support (shouldn't hurt with non-dtd++ + * dtds) + */ + + | CFG_SUPPORT_DTDPP + + /* + * Set this as a default, as this is required in xml; + */ + | CFG_NORMALIZE_LFS + + /* Regarding Xml:id, let's enabled typing by default, but not + * uniqueness validity checks: latter will be taken care of + * by DTD validation if enabled, otherwise needs to be explicitly + * enabled + */ + | CFG_XMLID_TYPING + // | CFG_XMLID_UNIQ_CHECKS + ; + + /** + * For now defaults for J2ME flags can be identical to 'full' set; + * differences are in buffer sizes. + */ + final static int DEFAULT_FLAGS_J2ME = DEFAULT_FLAGS_FULL; + + // // // + + /** + * Map to use for converting from String property ids to ints + * described above; useful to allow use of switch later on. + */ + final static HashMap sProperties = new HashMap(64); // we have about 40 entries + static { + // Standard ones; support for features + sProperties.put(XMLInputFactory.IS_COALESCING, PROP_COALESCE_TEXT); + sProperties.put(XMLInputFactory.IS_NAMESPACE_AWARE, + PROP_NAMESPACE_AWARE); + sProperties.put(XMLInputFactory.IS_REPLACING_ENTITY_REFERENCES, + PROP_REPLACE_ENTITY_REFS); + sProperties.put(XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES, + PROP_SUPPORT_EXTERNAL_ENTITIES); + sProperties.put(XMLInputFactory.IS_VALIDATING, + PROP_VALIDATE_AGAINST_DTD); + sProperties.put(XMLInputFactory.SUPPORT_DTD, + PROP_SUPPORT_DTD); + + // Standard ones; pluggable components + sProperties.put(XMLInputFactory.ALLOCATOR, + PROP_EVENT_ALLOCATOR); + sProperties.put(XMLInputFactory.REPORTER, + PROP_WARNING_REPORTER); + sProperties.put(XMLInputFactory.RESOLVER, + PROP_XML_RESOLVER); + + // StAX2-introduced flags: + sProperties.put(XMLInputFactory2.P_INTERN_NAMES, + PROP_INTERN_NAMES); + sProperties.put(XMLInputFactory2.P_INTERN_NS_URIS, + PROP_INTERN_NS_URIS); + sProperties.put(XMLInputFactory2.P_REPORT_CDATA, + PROP_REPORT_CDATA); + sProperties.put(XMLInputFactory2.P_REPORT_PROLOG_WHITESPACE, + PROP_REPORT_PROLOG_WS); + sProperties.put(XMLInputFactory2.P_PRESERVE_LOCATION, + PROP_PRESERVE_LOCATION); + sProperties.put(XMLInputFactory2.P_AUTO_CLOSE_INPUT, + PROP_AUTO_CLOSE_INPUT); + sProperties.put(XMLInputFactory2.XSP_SUPPORT_XMLID, + PROP_SUPPORT_XMLID); + sProperties.put(XMLInputFactory2.P_DTD_OVERRIDE, + PROP_DTD_OVERRIDE); + + // Non-standard ones, flags: + + sProperties.put(WstxInputProperties.P_CACHE_DTDS, PROP_CACHE_DTDS); + sProperties.put(WstxInputProperties.P_CACHE_DTDS_BY_PUBLIC_ID, + PROP_CACHE_DTDS_BY_PUBLIC_ID); + sProperties.put(XMLInputFactory2.P_LAZY_PARSING, PROP_LAZY_PARSING); + /* + sProperties.put(WstxInputProperties.P_SUPPORT_DTDPP, + PROP_SUPPORT_DTDPP)); + */ + sProperties.put(WstxInputProperties.P_TREAT_CHAR_REFS_AS_ENTS, + PROP_TREAT_CHAR_REFS_AS_ENTS); + sProperties.put(WstxInputProperties.P_NORMALIZE_LFS, PROP_NORMALIZE_LFS); + + + // Non-standard ones, non-flags: + + sProperties.put(WstxInputProperties.P_INPUT_BUFFER_LENGTH, + PROP_INPUT_BUFFER_LENGTH); + sProperties.put(WstxInputProperties.P_MIN_TEXT_SEGMENT, + PROP_MIN_TEXT_SEGMENT); + sProperties.put(WstxInputProperties.P_MAX_ATTRIBUTES_PER_ELEMENT, + PROP_MAX_ATTRIBUTES_PER_ELEMENT); + sProperties.put(WstxInputProperties.P_MAX_ATTRIBUTE_SIZE, + PROP_MAX_ATTRIBUTE_SIZE); + sProperties.put(WstxInputProperties.P_MAX_CHILDREN_PER_ELEMENT, + PROP_MAX_CHILDREN_PER_ELEMENT); + sProperties.put(WstxInputProperties.P_MAX_TEXT_LENGTH, + PROP_MAX_TEXT_LENGTH); + sProperties.put(WstxInputProperties.P_MAX_ELEMENT_COUNT, + PROP_MAX_ELEMENT_COUNT); + sProperties.put(WstxInputProperties.P_MAX_ELEMENT_DEPTH, + PROP_MAX_ELEMENT_DEPTH); + sProperties.put(WstxInputProperties.P_MAX_ENTITY_DEPTH, + PROP_MAX_ENTITY_DEPTH); + sProperties.put(WstxInputProperties.P_MAX_ENTITY_COUNT, + PROP_MAX_ENTITY_COUNT); + sProperties.put(WstxInputProperties.P_MAX_CHARACTERS, PROP_MAX_CHARACTERS); + + { + @SuppressWarnings("deprecation") + String key = WstxInputProperties.P_CUSTOM_INTERNAL_ENTITIES; + sProperties.put(key, Integer.valueOf(PROP_CUSTOM_INTERNAL_ENTITIES)); + } + sProperties.put(WstxInputProperties.P_DTD_RESOLVER, + PROP_DTD_RESOLVER); + sProperties.put(WstxInputProperties.P_ENTITY_RESOLVER, + PROP_ENTITY_RESOLVER); + sProperties.put(WstxInputProperties.P_UNDECLARED_ENTITY_RESOLVER, + PROP_UNDECLARED_ENTITY_RESOLVER); + sProperties.put(WstxInputProperties.P_BASE_URL, + PROP_BASE_URL); + sProperties.put(WstxInputProperties.P_INPUT_PARSING_MODE, + PROP_INPUT_PARSING_MODE); + } + + /* + /////////////////////////////////////////////////////////////////////// + // Current config state: + /////////////////////////////////////////////////////////////////////// + */ + + final protected boolean mIsJ2MESubset; + + final protected SymbolTable mSymbols; + + /** + * Bitset that contains state of on/off properties; initialized + * to defaults, but can be set/cleared. + */ + protected int mConfigFlags; + + /** + * Bitset that indicates explicit changes to {@link #mConfigFlags} + * through calls; empty bit means that the corresponding property + * has its default value, set bit that an explicit call has been + * made. + */ + protected int mConfigFlagMods; + + /** + * 13-Nov-2008, tatus: Need to be able to keep track of whether + * name-interning has been explicitly enabled/disable or not + * (not if it's whatever defaults we have) + */ + final static int PROP_INTERN_NAMES_EXPLICIT = 26; + final static int PROP_INTERN_NS_URIS_EXPLICIT = 27; + + protected int mInputBufferLen; + protected int mMinTextSegmentLen; + protected int mMaxAttributesPerElement = DEFAULT_MAX_ATTRIBUTES_PER_ELEMENT; + protected int mMaxAttributeSize = DEFAULT_MAX_ATTRIBUTE_LENGTH; + protected int mMaxChildrenPerElement = Integer.MAX_VALUE; + protected int mMaxElementDepth = DEFAULT_MAX_ELEMENT_DEPTH; + protected long mMaxElementCount = Long.MAX_VALUE; // unlimited + protected long mMaxCharacters = Long.MAX_VALUE; // unlimited + protected int mMaxTextLength = Integer.MAX_VALUE; // unlimited + + protected int mMaxEntityDepth = DEFAULT_MAX_ENTITY_DEPTH; + protected long mMaxEntityCount = DEFAULT_MAX_ENTITY_COUNT; + + /** + * Base URL to use as the resolution context for relative entity + * references + */ + protected URL mBaseURL; + + /** + * Parsing mode can be changed from the default xml compliant + * behavior to one of alternate modes (fragment processing, + * multiple document processing). + */ + protected WstxInputProperties.ParsingMode mParsingMode = + WstxInputProperties.PARSING_MODE_DOCUMENT; + + /** + * This boolean flag is set if the input document requires + * xml 1.1 (or above) compliant processing: default is xml 1.0 + * compliant. Note that unlike most other properties, this + * does not come from configuration settings, but from processed + * document itself. + */ + protected boolean mXml11 = false; + + /* + /////////////////////////////////////////////////////////////////////// + // Common configuration objects + /////////////////////////////////////////////////////////////////////// + */ + + XMLReporter mReporter; + + XMLResolver mDtdResolver = null; + XMLResolver mEntityResolver = null; + + /* + /////////////////////////////////////////////////////////////////////// + // More special(ized) configuration objects + /////////////////////////////////////////////////////////////////////// + */ + + //Map mCustomEntities; + //XMLResolver mUndeclaredEntityResolver; + //DTDEventListener mDTDEventListener; + + Object[] mSpecialProperties = null; + + private final static int SPEC_PROC_COUNT = 4; + + private final static int SP_IX_CUSTOM_ENTITIES = 0; + private final static int SP_IX_UNDECL_ENT_RESOLVER = 1; + private final static int SP_IX_DTD_EVENT_LISTENER = 2; + private final static int SP_IX_DTD_OVERRIDE = 3; + + /* + /////////////////////////////////////////////////////////////////////// + // Buffer recycling: + /////////////////////////////////////////////////////////////////////// + */ + + /** + * This ThreadLocal contains a {@link SoftRerefence} + * to a {@link BufferRecycler} used to provide a low-cost + * buffer recycling between Reader instances. + */ + final static ThreadLocal> mRecyclerRef = new ThreadLocal>(); + + /** + * This is the actually container of the recyclable buffers. It + * is obtained via ThreadLocal/SoftReference combination, if one + * exists, when Config instance is created. If one does not + * exist, it will created first time a buffer is returned. + */ + BufferRecycler mCurrRecycler = null; + + /* + /////////////////////////////////////////////////////////////////////// + // Life-cycle + /////////////////////////////////////////////////////////////////////// + */ + + private ReaderConfig(ReaderConfig base, + boolean j2meSubset, SymbolTable symbols, + int configFlags, int configFlagMods, + int inputBufLen, + int minTextSegmentLen) + { + super(base); + mIsJ2MESubset = j2meSubset; + mSymbols = symbols; + + mConfigFlags = configFlags; + mConfigFlagMods = configFlagMods; + + mInputBufferLen = inputBufLen; + mMinTextSegmentLen = minTextSegmentLen; + if (base != null) { + mMaxAttributesPerElement = base.mMaxAttributesPerElement; + mMaxAttributeSize = base.mMaxAttributeSize; + mMaxChildrenPerElement = base.mMaxChildrenPerElement; + mMaxElementCount = base.mMaxElementCount; + mMaxElementDepth = base.mMaxElementDepth; + mMaxCharacters = base.mMaxCharacters; + mMaxTextLength = base.mMaxTextLength; + mMaxEntityDepth = base.mMaxEntityDepth; + mMaxEntityCount = base.mMaxEntityCount; + } + + /* Ok, let's then see if we can find a buffer recycler. Since they + * are lazily constructed, and since GC may just flush them out + * on its whims, it's possible we might not find one. That's ok; + * we can reconstruct one if and when we are to return one or more + * buffers. + */ + SoftReference ref = mRecyclerRef.get(); + if (ref != null) { + mCurrRecycler = ref.get(); + } + } + + public static ReaderConfig createJ2MEDefaults() + { + /* For J2ME we'll use slightly smaller buffer sizes by + * default, on assumption lower memory usage is desireable: + */ + ReaderConfig rc = new ReaderConfig(null, + true, null, DEFAULT_FLAGS_J2ME, 0, + // 4k input buffer (2000 chars): + 2000, + DEFAULT_SHORTEST_TEXT_SEGMENT); + return rc; + } + + public static ReaderConfig createFullDefaults() + { + /* For full version, can use bit larger buffers to achieve better + * overall performance. + */ + ReaderConfig rc = new ReaderConfig(null, + false, null, DEFAULT_FLAGS_FULL, 0, + // 8k input buffer (4000 chars): + 4000, + DEFAULT_SHORTEST_TEXT_SEGMENT); + return rc; + } + + public ReaderConfig createNonShared(SymbolTable sym) + { + // should we throw an exception? + //if (sym == null) { } + ReaderConfig rc = new ReaderConfig(this, + mIsJ2MESubset, sym, + mConfigFlags, mConfigFlagMods, + mInputBufferLen, + mMinTextSegmentLen); + rc.mReporter = mReporter; + rc.mDtdResolver = mDtdResolver; + rc.mEntityResolver = mEntityResolver; + rc.mBaseURL = mBaseURL; + rc.mParsingMode = mParsingMode; + rc.mMaxAttributesPerElement = mMaxAttributesPerElement; + rc.mMaxAttributeSize = mMaxAttributeSize; + rc.mMaxChildrenPerElement = mMaxChildrenPerElement; + rc.mMaxElementCount = mMaxElementCount; + rc.mMaxCharacters = mMaxCharacters; + rc.mMaxTextLength = mMaxTextLength; + rc.mMaxElementDepth = mMaxElementDepth; + rc.mMaxEntityDepth = mMaxEntityDepth; + rc.mMaxEntityCount = mMaxEntityCount; + if (mSpecialProperties != null) { + int len = mSpecialProperties.length; + Object[] specProps = new Object[len]; + System.arraycopy(mSpecialProperties, 0, specProps, 0, len); + rc.mSpecialProperties = specProps; + } + return rc; + } + + /** + * Unlike name suggests there is also some limited state information + * associated with the config object. If these objects are reused, + * that state needs to be reset between reuses, to avoid carrying + * over incorrect state. + */ + public void resetState() + { + // Current, only xml 1.0 vs 1.1 state is stored here: + mXml11 = false; + } + + /* + /////////////////////////////////////////////////////////////////////// + // Implementation of abstract methods + /////////////////////////////////////////////////////////////////////// + */ + + @Override + protected int findPropertyId(String propName) + { + Integer I = sProperties.get(propName); + return (I == null) ? -1 : I.intValue(); + } + + /* + /////////////////////////////////////////////////////////////////////// + // Public API, accessors + /////////////////////////////////////////////////////////////////////// + */ + + // // // Accessors for immutable configuration: + + public SymbolTable getSymbols() { return mSymbols; } + + /** + * In future this property could/should be made configurable? + */ + + public int getDtdCacheSize() { + return mIsJ2MESubset ? DTD_CACHE_SIZE_J2ME : DTD_CACHE_SIZE_J2SE; + } + + // // // "Raw" accessors for on/off properties: + + public int getConfigFlags() { return mConfigFlags; } + + // // // Standard StAX on/off property accessors + + public boolean willCoalesceText() { + return _hasConfigFlag(CFG_COALESCE_TEXT); + } + + public boolean willSupportNamespaces() { + return _hasConfigFlag(CFG_NAMESPACE_AWARE); + } + + public boolean willReplaceEntityRefs() { + return _hasConfigFlag(CFG_REPLACE_ENTITY_REFS); + } + + public boolean willSupportExternalEntities() { + return _hasConfigFlag(CFG_SUPPORT_EXTERNAL_ENTITIES); + } + + public boolean willSupportDTDs() { + return _hasConfigFlag(CFG_SUPPORT_DTD); + } + + public boolean willValidateWithDTD() { + return _hasConfigFlag(CFG_VALIDATE_AGAINST_DTD); + } + + // // // Stax2 on/off property accessors + + public boolean willReportCData() { + return _hasConfigFlag(CFG_REPORT_CDATA); + } + + public boolean willParseLazily() { + return _hasConfigFlag(CFG_LAZY_PARSING); + } + + public boolean willInternNames() { + return _hasConfigFlag(CFG_INTERN_NAMES); + } + + public boolean willInternNsURIs() { + return _hasConfigFlag(CFG_INTERN_NS_URIS); + } + + public boolean willPreserveLocation() { + return _hasConfigFlag(CFG_PRESERVE_LOCATION); + } + + public boolean willAutoCloseInput() { + return _hasConfigFlag(CFG_AUTO_CLOSE_INPUT); + } + + // // // Woodstox on/off property accessors + + public boolean willReportPrologWhitespace() { + return _hasConfigFlag(CFG_REPORT_PROLOG_WS); + } + + public boolean willCacheDTDs() { + return _hasConfigFlag(CFG_CACHE_DTDS); + } + + public boolean willCacheDTDsByPublicId() { + return _hasConfigFlag(CFG_CACHE_DTDS_BY_PUBLIC_ID); + } + + public boolean willDoXmlIdTyping() { + return _hasConfigFlag(CFG_XMLID_TYPING); + } + + public boolean willDoXmlIdUniqChecks() { + return _hasConfigFlag(CFG_XMLID_UNIQ_CHECKS); + } + + public boolean willSupportDTDPP() { + return _hasConfigFlag(CFG_SUPPORT_DTDPP); + } + + public boolean willNormalizeLFs() { + return _hasConfigFlag(CFG_NORMALIZE_LFS); + } + + public boolean willTreatCharRefsAsEnts() { + return _hasConfigFlag(CFG_TREAT_CHAR_REFS_AS_ENTS); + } + + public int getInputBufferLength() { return mInputBufferLen; } + + public int getShortestReportedTextSegment() { return mMinTextSegmentLen; } + + public int getMaxAttributesPerElement() { return mMaxAttributesPerElement; } + public int getMaxAttributeSize() { return mMaxAttributeSize; } + public int getMaxChildrenPerElement() { return mMaxChildrenPerElement; } + + public int getMaxElementDepth() { return mMaxElementDepth; } + public long getMaxElementCount() { return mMaxElementCount; } + + public int getMaxEntityDepth() { return mMaxEntityDepth; } + public long getMaxEntityCount() { return mMaxEntityCount; } + + public long getMaxCharacters() { return mMaxCharacters; } + public long getMaxTextLength() { return mMaxTextLength; } + + public Map getCustomInternalEntities() + { + @SuppressWarnings("unchecked") + Map custEnt = (Map) _getSpecialProperty(SP_IX_CUSTOM_ENTITIES); + if (custEnt == null) { + return Collections.emptyMap(); + } + // Better be defensive and just return a copy... + int len = custEnt.size(); + HashMap m = new HashMap(len + (len >> 2), 0.81f); + for (Map.Entry me : custEnt.entrySet()) { + m.put(me.getKey(), me.getValue()); + } + return m; + } + + public EntityDecl findCustomInternalEntity(String id) + { + @SuppressWarnings("unchecked") + Map custEnt = (Map) _getSpecialProperty(SP_IX_CUSTOM_ENTITIES); + if (custEnt == null) { + return null; + } + return custEnt.get(id); + } + + public XMLReporter getXMLReporter() { return mReporter; } + + public XMLResolver getXMLResolver() { return mEntityResolver; } + + public XMLResolver getDtdResolver() { return mDtdResolver; } + public XMLResolver getEntityResolver() { return mEntityResolver; } + public XMLResolver getUndeclaredEntityResolver() { + return (XMLResolver) _getSpecialProperty(SP_IX_UNDECL_ENT_RESOLVER); + } + + public URL getBaseURL() { return mBaseURL; } + + public WstxInputProperties.ParsingMode getInputParsingMode() { + return mParsingMode; + } + + public boolean inputParsingModeDocuments() { + return mParsingMode == WstxInputProperties.PARSING_MODE_DOCUMENTS; + } + + public boolean inputParsingModeFragment() { + return mParsingMode == WstxInputProperties.PARSING_MODE_FRAGMENT; + } + + /** + * @return True if the input well-formedness and validation checks + * should be done according to xml 1.1 specification; false if + * xml 1.0 specification. + */ + public boolean isXml11() { + return mXml11; + } + + public DTDEventListener getDTDEventListener() { + return (DTDEventListener) _getSpecialProperty(SP_IX_DTD_EVENT_LISTENER); + } + + public DTDValidationSchema getDTDOverride() { + return (DTDValidationSchema) _getSpecialProperty(SP_IX_DTD_OVERRIDE); + } + + /** + * Special accessor to use to verify whether name interning has + * explicitly been enabled; true if call was been made to set + * it to true; false otherwise (default, or set to false) + */ + public boolean hasInternNamesBeenEnabled() { + return _hasExplicitConfigFlag(CFG_INTERN_NAMES); + } + + public boolean hasInternNsURIsBeenEnabled() { + return _hasExplicitConfigFlag(CFG_INTERN_NS_URIS); + } + + /* + /////////////////////////////////////////////////////////////////////// + // Simple mutators + /////////////////////////////////////////////////////////////////////// + */ + + public void setConfigFlag(int flag) { + mConfigFlags |= flag; + mConfigFlagMods |= flag; + } + + public void clearConfigFlag(int flag) { + mConfigFlags &= ~flag; + mConfigFlagMods |= flag; + } + + // // // Mutators for standard StAX properties + + public void doCoalesceText(boolean state) { + setConfigFlag(CFG_COALESCE_TEXT, state); + } + + public void doSupportNamespaces(boolean state) { + setConfigFlag(CFG_NAMESPACE_AWARE, state); + } + + public void doReplaceEntityRefs(boolean state) { + setConfigFlag(CFG_REPLACE_ENTITY_REFS, state); + } + + public void doSupportExternalEntities(boolean state) { + setConfigFlag(CFG_SUPPORT_EXTERNAL_ENTITIES, state); + } + + public void doSupportDTDs(boolean state) { + setConfigFlag(CFG_SUPPORT_DTD, state); + } + + public void doValidateWithDTD(boolean state) { + setConfigFlag(CFG_VALIDATE_AGAINST_DTD, state); + } + + // // // Mutators for Woodstox-specific properties + + public void doInternNames(boolean state) { + setConfigFlag(CFG_INTERN_NAMES, state); + } + + public void doInternNsURIs(boolean state) { + setConfigFlag(CFG_INTERN_NS_URIS, state); + } + + public void doReportPrologWhitespace(boolean state) { + setConfigFlag(CFG_REPORT_PROLOG_WS, state); + } + + public void doReportCData(boolean state) { + setConfigFlag(CFG_REPORT_CDATA, state); + } + + public void doCacheDTDs(boolean state) { + setConfigFlag(CFG_CACHE_DTDS, state); + } + + public void doCacheDTDsByPublicId(boolean state) { + setConfigFlag(CFG_CACHE_DTDS_BY_PUBLIC_ID, state); + } + + public void doParseLazily(boolean state) { + setConfigFlag(CFG_LAZY_PARSING, state); + } + + public void doXmlIdTyping(boolean state) { + setConfigFlag(CFG_XMLID_TYPING, state); + } + + public void doXmlIdUniqChecks(boolean state) { + setConfigFlag(CFG_XMLID_UNIQ_CHECKS, state); + } + + public void doPreserveLocation(boolean state) { + setConfigFlag(CFG_PRESERVE_LOCATION, state); + } + + public void doAutoCloseInput(boolean state) { + setConfigFlag(CFG_AUTO_CLOSE_INPUT, state); + } + + public void doSupportDTDPP(boolean state) { + setConfigFlag(CFG_SUPPORT_DTDPP, state); + } + + public void doTreatCharRefsAsEnts(final boolean state) { + setConfigFlag(CFG_TREAT_CHAR_REFS_AS_ENTS, state); + } + + public void doNormalizeLFs(final boolean state) { + setConfigFlag(CFG_NORMALIZE_LFS, state); + } + + public void setInputBufferLength(int value) + { + /* Let's enforce minimum here; necessary to allow longest + * consequtive text span to be available (xml decl, etc) + */ + if (value < MIN_INPUT_BUFFER_LENGTH) { + value = MIN_INPUT_BUFFER_LENGTH; + } + mInputBufferLen = value; + } + + public void setShortestReportedTextSegment(int value) { + mMinTextSegmentLen = value; + } + public void setMaxAttributesPerElement(int value) { + mMaxAttributesPerElement = value; + } + public void setMaxAttributeSize(int value) { + mMaxAttributeSize = value; + } + public void setMaxChildrenPerElement(int value) { + mMaxChildrenPerElement = value; + } + public void setMaxElementDepth(int value) { + mMaxElementDepth = value; + } + public void setMaxElementCount(long value) { + mMaxElementCount = value; + } + public void setMaxCharacters(long value) { + mMaxCharacters = value; + } + public void setMaxTextLength(int value) { + mMaxTextLength = value; + } + public void setMaxEntityDepth(int value) { + mMaxEntityDepth = value; + } + public void setMaxEntityCount(long value) { + mMaxEntityCount = value; + } + + public void setCustomInternalEntities(Map m) + { + Map entMap; + if (m == null || m.size() < 1) { + entMap = Collections.emptyMap(); + } else { + int len = m.size(); + entMap = new HashMap(len + (len >> 1), 0.75f); + for (Map.Entry me : m.entrySet()) { + Object val = me.getValue(); + char[] ch; + if (val == null) { + ch = DataUtil.getEmptyCharArray(); + } else if (val instanceof char[]) { + ch = (char[]) val; + } else { + // Probably String, but let's just ensure that + String str = val.toString(); + ch = str.toCharArray(); + } + String name = me.getKey(); + entMap.put(name, IntEntity.create(name, ch)); + } + } + _setSpecialProperty(SP_IX_CUSTOM_ENTITIES, entMap); + } + + public void setXMLReporter(XMLReporter r) { + mReporter = r; + } + + /** + * Note: for better granularity, you should call {@link #setEntityResolver} + * and {@link #setDtdResolver} instead. + */ + public void setXMLResolver(XMLResolver r) { + mEntityResolver = r; + mDtdResolver = r; + } + + public void setDtdResolver(XMLResolver r) { + mDtdResolver = r; + } + + public void setEntityResolver(XMLResolver r) { + mEntityResolver = r; + } + + public void setUndeclaredEntityResolver(XMLResolver r) { + _setSpecialProperty(SP_IX_UNDECL_ENT_RESOLVER, r); + } + + public void setBaseURL(URL baseURL) { mBaseURL = baseURL; } + + public void setInputParsingMode(WstxInputProperties.ParsingMode mode) { + mParsingMode = mode; + } + + /** + * Method called to enable or disable 1.1 compliant processing; if + * disabled, defaults to xml 1.0 compliant processing. + */ + public void enableXml11(boolean state) { + mXml11 = state; + } + + public void setDTDEventListener(DTDEventListener l) { + _setSpecialProperty(SP_IX_DTD_EVENT_LISTENER, l); + } + + public void setDTDOverride(DTDValidationSchema schema) { + _setSpecialProperty(SP_IX_DTD_OVERRIDE, schema); + } + + /* + /////////////////////////////////////////////////////////////////////// + // Profile mutators: + /////////////////////////////////////////////////////////////////////// + */ + + /** + * Method to call to make Reader created conform as closely to XML + * standard as possible, doing all checks and transformations mandated + * (linefeed conversions, attr value normalizations). + * See {@link XMLInputFactory2#configureForXmlConformance} for + * required settings for standard StAX/StAX properties. + *

+ * In addition to the standard settings, following Woodstox-specific + * settings are also done: + *

    + * None. + *
+ *

+ * Notes: Does NOT change 'performance' settings (buffer sizes, + * DTD caching, coalescing, interning, accurate location info). + */ + public void configureForXmlConformance() + { + // // StAX 1.0 settings + doSupportNamespaces(true); + doSupportDTDs(true); + doSupportExternalEntities(true); + doReplaceEntityRefs(true); + + // // Stax2 additional settings + + // Better enable full xml:id checks: + doXmlIdTyping(true); + doXmlIdUniqChecks(true); + + // Woodstox-specific ones: + } + + /** + * Method to call to make Reader created be as "convenient" to use + * as possible; ie try to avoid having to deal with some of things + * like segmented text chunks. This may incur some slight performance + * penalties, but should not affect XML conformance. + * See {@link XMLInputFactory2#configureForConvenience} for + * required settings for standard StAX/StAX properties. + *

+ * In addition to the standard settings, following Woodstox-specific + * settings are also done: + *

    + *
  • Disable XMLStreamFactory2.P_LAZY_PARSING (to allow for synchronous + * error notification by forcing full XML events to be completely + * parsed when reader's next() is called) + *
  • + *
+ */ + public void configureForConvenience() + { + // StAX (1.0) settings: + doCoalesceText(true); + doReplaceEntityRefs(true); + + // StAX2: + doReportCData(false); + doReportPrologWhitespace(false); + /* Also, knowing exact locations is nice esp. for error + * reporting purposes + */ + doPreserveLocation(true); + + // Woodstox-specific: + + /* Also, we can force errors to be reported in timely manner: + * (once again, at potential expense of performance) + */ + doParseLazily(false); + } + + /** + * Method to call to make the Reader created be as fast as possible reading + * documents, especially for long-running processes where caching is + * likely to help. + * + * See {@link XMLInputFactory2#configureForSpeed} for + * required settings for standard StAX/StAX properties. + *

+ * In addition to the standard settings, following Woodstox-specific + * settings are also done: + *

    + *
  • Enable P_CACHE_DTDS. + *
  • + *
  • Enable XMLStremaFactory2.P_LAZY_PARSING (can improve performance + * especially when skipping text segments) + *
  • + *
  • Disable Xml:id uniqueness checks (and leave typing as is) + *
  • + *
  • Set lowish value for P_MIN_TEXT_SEGMENT, to allow + * reader to optimize segment length it uses (and possibly avoids + * one copy operation in the process) + *
  • + *
  • Increase P_INPUT_BUFFER_LENGTH a bit from default, + * to allow for longer consequtive read operations; also reduces cases + * where partial text segments are on input buffer boundaries. + *
  • + *
+ */ + public void configureForSpeed() + { + // StAX (1.0): + doCoalesceText(false); + + // StAX2: + doPreserveLocation(false); + doReportPrologWhitespace(false); + //doInternNames(true); // this is a NOP + doInternNsURIs(true); + doXmlIdUniqChecks(false); + + // Woodstox-specific: + doCacheDTDs(true); + doParseLazily(true); + + /* If we let Reader decide sizes of text segments, it should be + * able to optimize it better, thus low min value. This value + * is only used in cases where text is at buffer boundary, or + * where entity prevents using consequtive chars from input buffer: + */ + setShortestReportedTextSegment(16); + setInputBufferLength(8000); // 16k input buffer + } + + /** + * Method to call to minimize the memory usage of the stream/event reader; + * both regarding Objects created, and the temporary memory usage during + * parsing. + * This generally incurs some performance penalties, due to using + * smaller input buffers. + *

+ * See {@link XMLInputFactory2#configureForLowMemUsage} for + * required settings for standard StAX/StAX properties. + *

+ * In addition to the standard settings, following Woodstox-specific + * settings are also done: + *

    + *
  • Disable P_CACHE_DTDS + *
  • + *
  • Enable P_PARSE_LAZILY + *
  • + *
  • Resets P_MIN_TEXT_SEGMENT to the (somewhat low) + * default value. + *
  • + *
  • Reduces P_INPUT_BUFFER_LENGTH a bit from the default + *
  • + *
+ */ + public void configureForLowMemUsage() + { + // StAX (1.0) + doCoalesceText(false); + + // StAX2: + + doPreserveLocation(false); // can reduce temporary mem usage + + // Woodstox-specific: + doCacheDTDs(false); + doParseLazily(true); // can reduce temporary mem usage + doXmlIdUniqChecks(false); // enabling would increase mem usage + setShortestReportedTextSegment(ReaderConfig.DEFAULT_SHORTEST_TEXT_SEGMENT); + setInputBufferLength(512); // 1k input buffer + // Text buffer need not be huge, as we do not coalesce + } + + /** + * Method to call to make Reader try to preserve as much of input + * formatting as possible, so that round-tripping would be as lossless + * as possible. + *

+ * See {@link XMLInputFactory2#configureForLowMemUsage} for + * required settings for standard StAX/StAX properties. + *

+ * In addition to the standard settings, following Woodstox-specific + * settings are also done: + *

    + *
  • Increases P_MIN_TEXT_SEGMENT to the maximum value so + * that all original text segment chunks are reported without + * segmentation (but without coalescing with adjacent CDATA segments) + *
  • + *
  • Sets P_TREAT_CHAR_REFS_AS_ENTS to true, so the all the + * original character references are reported with their position, + * original text, and the replacement text. + *
  • + *
+ */ + public void configureForRoundTripping() + { + // StAX (1.0) + doCoalesceText(false); + doReplaceEntityRefs(false); + + // StAX2: + doReportCData(true); + doReportPrologWhitespace(true); + + // Woodstox specific settings + doTreatCharRefsAsEnts(true); + doNormalizeLFs(false); + + // effectively prevents from reporting partial segments: + setShortestReportedTextSegment(Integer.MAX_VALUE); + } + + /* + /////////////////////////////////////////////////////////////////////// + // Buffer recycling: + /////////////////////////////////////////////////////////////////////// + */ + + public char[] allocSmallCBuffer(int minSize) + { + if (mCurrRecycler != null) { + char[] result = mCurrRecycler.getSmallCBuffer(minSize); + if (result != null) { + return result; + } + } + // Nope; no recycler, or it has no suitable buffers, let's create: + return new char[minSize]; + } + + public void freeSmallCBuffer(char[] buffer) + { + // Need to create (and assign) the buffer? + if (mCurrRecycler == null) { + mCurrRecycler = createRecycler(); + } + mCurrRecycler.returnSmallCBuffer(buffer); + } + + public char[] allocMediumCBuffer(int minSize) + { + if (mCurrRecycler != null) { + char[] result = mCurrRecycler.getMediumCBuffer(minSize); + if (result != null) { + return result; + } + } + return new char[minSize]; + } + + public void freeMediumCBuffer(char[] buffer) + { + if (mCurrRecycler == null) { + mCurrRecycler = createRecycler(); + } + mCurrRecycler.returnMediumCBuffer(buffer); + } + + public char[] allocFullCBuffer(int minSize) + { + if (mCurrRecycler != null) { + char[] result = mCurrRecycler.getFullCBuffer(minSize); + if (result != null) { + return result; + } + } + return new char[minSize]; + } + + public void freeFullCBuffer(char[] buffer) + { + // Need to create (and assign) the buffer? + if (mCurrRecycler == null) { + mCurrRecycler = createRecycler(); + } + mCurrRecycler.returnFullCBuffer(buffer); + } + + public byte[] allocFullBBuffer(int minSize) + { + if (mCurrRecycler != null) { + byte[] result = mCurrRecycler.getFullBBuffer(minSize); + if (result != null) { + return result; + } + } + return new byte[minSize]; + } + + public void freeFullBBuffer(byte[] buffer) + { + // Need to create (and assign) the buffer? + if (mCurrRecycler == null) { + mCurrRecycler = createRecycler(); + } + mCurrRecycler.returnFullBBuffer(buffer); + } + + private BufferRecycler createRecycler() + { + BufferRecycler recycler = new BufferRecycler(); + // No way to reuse/reset SoftReference, have to create new always: + mRecyclerRef.set(new SoftReference(recycler)); + return recycler; + } + + /* + /////////////////////////////////////////////////////////////////////// + // Internal methods: + /////////////////////////////////////////////////////////////////////// + */ + + private void setConfigFlag(int flag, boolean state) + { + if (state) { + mConfigFlags |= flag; + } else { + mConfigFlags &= ~flag; + } + mConfigFlagMods |= flag; + } + + @Override + public Object getProperty(int id) + { + switch (id) { + // First, standard Stax 1.0 properties: + + case PROP_COALESCE_TEXT: + return willCoalesceText() ? Boolean.TRUE : Boolean.FALSE; + case PROP_NAMESPACE_AWARE: + return willSupportNamespaces() ? Boolean.TRUE : Boolean.FALSE; + case PROP_REPLACE_ENTITY_REFS: + return willReplaceEntityRefs() ? Boolean.TRUE : Boolean.FALSE; + case PROP_SUPPORT_EXTERNAL_ENTITIES: + return willSupportExternalEntities() ? Boolean.TRUE : Boolean.FALSE; + + case PROP_VALIDATE_AGAINST_DTD: + return willValidateWithDTD() ? Boolean.TRUE : Boolean.FALSE; + case PROP_SUPPORT_DTD: + return willSupportDTDs() ? Boolean.TRUE : Boolean.FALSE; + case PROP_WARNING_REPORTER: + return getXMLReporter(); + case PROP_XML_RESOLVER: + return getXMLResolver(); + case PROP_EVENT_ALLOCATOR: + /* 25-Mar-2006, TSa: Not really supported here, so let's + * return null + */ + return null; + + // Then Stax2 properties: + + case PROP_REPORT_PROLOG_WS: + return willReportPrologWhitespace() ? Boolean.TRUE : Boolean.FALSE; + case PROP_REPORT_CDATA: + return willReportCData() ? Boolean.TRUE : Boolean.FALSE; + + case PROP_INTERN_NAMES: + return willInternNames() ? Boolean.TRUE : Boolean.FALSE; + case PROP_INTERN_NS_URIS: + return willInternNsURIs() ? Boolean.TRUE : Boolean.FALSE; + + case PROP_PRESERVE_LOCATION: + return willPreserveLocation() ? Boolean.TRUE : Boolean.FALSE; + case PROP_AUTO_CLOSE_INPUT: + return willAutoCloseInput() ? Boolean.TRUE : Boolean.FALSE; + + case PROP_DTD_OVERRIDE: + return getDTDOverride(); + + // // // Then Woodstox custom properties: + + // first, flags: + case PROP_CACHE_DTDS: + return willCacheDTDs() ? Boolean.TRUE : Boolean.FALSE; + case PROP_CACHE_DTDS_BY_PUBLIC_ID: + return willCacheDTDsByPublicId() ? Boolean.TRUE : Boolean.FALSE; + case PROP_LAZY_PARSING: + return willParseLazily() ? Boolean.TRUE : Boolean.FALSE; + case PROP_SUPPORT_XMLID: + { + if (!_hasConfigFlag(CFG_XMLID_TYPING)) { + return XMLStreamProperties.XSP_V_XMLID_NONE; + } + return _hasConfigFlag(CFG_XMLID_UNIQ_CHECKS) ? + XMLStreamProperties.XSP_V_XMLID_FULL : + XMLStreamProperties.XSP_V_XMLID_TYPING; + } + + case PROP_TREAT_CHAR_REFS_AS_ENTS: + return willTreatCharRefsAsEnts() ? Boolean.TRUE : Boolean.FALSE; + + case PROP_NORMALIZE_LFS: + return willNormalizeLFs() ? Boolean.TRUE : Boolean.FALSE; + + // then object values: + case PROP_INPUT_BUFFER_LENGTH: + return getInputBufferLength(); + case PROP_MAX_ATTRIBUTES_PER_ELEMENT: + return getMaxAttributesPerElement(); + case PROP_MAX_ATTRIBUTE_SIZE: + return getMaxAttributeSize(); + case PROP_MAX_CHILDREN_PER_ELEMENT: + return getMaxChildrenPerElement(); + case PROP_MAX_ELEMENT_DEPTH: + return getMaxElementDepth(); + case PROP_MAX_ELEMENT_COUNT: + return getMaxElementCount(); + case PROP_MAX_CHARACTERS: + return getMaxCharacters(); + case PROP_MAX_TEXT_LENGTH: + return getMaxTextLength(); + case PROP_MAX_ENTITY_DEPTH: + return getMaxEntityDepth(); + case PROP_MAX_ENTITY_COUNT: + return getMaxEntityCount(); + + case PROP_MIN_TEXT_SEGMENT: + return getShortestReportedTextSegment(); + case PROP_CUSTOM_INTERNAL_ENTITIES: + return getCustomInternalEntities(); + case PROP_DTD_RESOLVER: + return getDtdResolver(); + case PROP_ENTITY_RESOLVER: + return getEntityResolver(); + case PROP_UNDECLARED_ENTITY_RESOLVER: + return getUndeclaredEntityResolver(); + case PROP_BASE_URL: + return getBaseURL(); + case PROP_INPUT_PARSING_MODE: + return getInputParsingMode(); + + default: // sanity check, should never happen + throw new IllegalStateException("Internal error: no handler for property with internal id "+id+"."); + } + } + + @Override + public boolean setProperty(String propName, int id, Object value) + { + switch (id) { + // First, standard (Stax 1.0) properties: + + case PROP_COALESCE_TEXT: + doCoalesceText(ArgUtil.convertToBoolean(propName, value)); + break; + + case PROP_NAMESPACE_AWARE: + doSupportNamespaces(ArgUtil.convertToBoolean(propName, value)); + break; + + case PROP_REPLACE_ENTITY_REFS: + doReplaceEntityRefs(ArgUtil.convertToBoolean(propName, value)); + break; + + case PROP_SUPPORT_EXTERNAL_ENTITIES: + doSupportExternalEntities(ArgUtil.convertToBoolean(propName, value)); + break; + + case PROP_SUPPORT_DTD: + doSupportDTDs(ArgUtil.convertToBoolean(propName, value)); + break; + + // // // Then ones that can be dispatched: + + case PROP_VALIDATE_AGAINST_DTD: + doValidateWithDTD(ArgUtil.convertToBoolean(propName, value)); + break; + + case PROP_WARNING_REPORTER: + setXMLReporter((XMLReporter) value); + break; + + case PROP_XML_RESOLVER: + setXMLResolver((XMLResolver) value); + break; + + case PROP_EVENT_ALLOCATOR: + /* 25-Mar-2006, TSa: Not really supported here, so let's + * return false to let caller deal with it + */ + return false; + + // // // Then Stax2 properties, flags: + + case PROP_INTERN_NS_URIS: + doInternNsURIs(ArgUtil.convertToBoolean(propName, value)); + break; + + case PROP_INTERN_NAMES: + doInternNames(ArgUtil.convertToBoolean(propName, value)); + break; + + case PROP_REPORT_CDATA: + doReportCData(ArgUtil.convertToBoolean(propName, value)); + break; + + case PROP_REPORT_PROLOG_WS: + doReportPrologWhitespace(ArgUtil.convertToBoolean(propName, value)); + break; + + case PROP_PRESERVE_LOCATION: + doPreserveLocation(ArgUtil.convertToBoolean(propName, value)); + break; + + case PROP_AUTO_CLOSE_INPUT: + doAutoCloseInput(ArgUtil.convertToBoolean(propName, value)); + break; + + // // // Then Stax2 properties, enum/object types: + + case PROP_SUPPORT_XMLID: + { + boolean typing, uniq; + + if (XMLStreamProperties.XSP_V_XMLID_NONE.equals(value)) { + typing = uniq = false; + } else if (XMLStreamProperties.XSP_V_XMLID_TYPING.equals(value)) { + typing = true; + uniq = false; + } else if (XMLStreamProperties.XSP_V_XMLID_FULL.equals(value)) { + typing = uniq = true; + } else { + throw new IllegalArgumentException + ("Illegal argument ('"+value+"') to set property " ++XMLStreamProperties.XSP_SUPPORT_XMLID+" to: has to be one of '" ++XMLStreamProperties.XSP_V_XMLID_NONE+"', '"+XMLStreamProperties.XSP_V_XMLID_TYPING+"' or '"+XMLStreamProperties.XSP_V_XMLID_FULL+"'" + ); + } + setConfigFlag(CFG_XMLID_TYPING, typing); + setConfigFlag(CFG_XMLID_UNIQ_CHECKS, uniq); + } + break; + + case PROP_DTD_OVERRIDE: + setDTDOverride((DTDValidationSchema) value); + break; + + // // // And then Woodstox specific, flags + + case PROP_CACHE_DTDS: + doCacheDTDs(ArgUtil.convertToBoolean(propName, value)); + break; + + case PROP_CACHE_DTDS_BY_PUBLIC_ID: + doCacheDTDsByPublicId(ArgUtil.convertToBoolean(propName, value)); + break; + + case PROP_LAZY_PARSING: + doParseLazily(ArgUtil.convertToBoolean(propName, value)); + break; + + case PROP_TREAT_CHAR_REFS_AS_ENTS: + doTreatCharRefsAsEnts(ArgUtil.convertToBoolean(propName, value)); + break; + + case PROP_NORMALIZE_LFS: + doNormalizeLFs(ArgUtil.convertToBoolean(propName, value)); + break; + + // // // And then Woodstox specific, enum/object: + + case PROP_INPUT_BUFFER_LENGTH: + setInputBufferLength(ArgUtil.convertToInt(propName, value, 1)); + break; + + case PROP_MAX_ATTRIBUTES_PER_ELEMENT: + setMaxAttributesPerElement(ArgUtil.convertToInt(propName, value, 1)); + break; + case PROP_MAX_ATTRIBUTE_SIZE: + setMaxAttributeSize(ArgUtil.convertToInt(propName, value, 1)); + break; + case PROP_MAX_CHILDREN_PER_ELEMENT: + setMaxChildrenPerElement(ArgUtil.convertToInt(propName, value, 1)); + break; + case PROP_MAX_ELEMENT_DEPTH: + setMaxElementDepth(ArgUtil.convertToInt(propName, value, 1)); + break; + case PROP_MAX_ELEMENT_COUNT: + setMaxElementCount(ArgUtil.convertToLong(propName, value, 1)); + break; + case PROP_MAX_CHARACTERS: + setMaxCharacters(ArgUtil.convertToLong(propName, value, 1)); + break; + case PROP_MAX_TEXT_LENGTH: + setMaxTextLength(ArgUtil.convertToInt(propName, value, 1)); + break; + case PROP_MAX_ENTITY_DEPTH: + setMaxEntityDepth(ArgUtil.convertToInt(propName, value, 1)); + break; + case PROP_MAX_ENTITY_COUNT: + setMaxEntityCount(ArgUtil.convertToLong(propName, value, 1)); + break; + + case PROP_MIN_TEXT_SEGMENT: + setShortestReportedTextSegment(ArgUtil.convertToInt(propName, value, 1)); + break; + + case PROP_CUSTOM_INTERNAL_ENTITIES: + { + @SuppressWarnings("unchecked") + Map arg = (Map) value; + setCustomInternalEntities(arg); + } + break; + + case PROP_DTD_RESOLVER: + setDtdResolver((XMLResolver) value); + break; + + case PROP_ENTITY_RESOLVER: + setEntityResolver((XMLResolver) value); + break; + + case PROP_UNDECLARED_ENTITY_RESOLVER: + setUndeclaredEntityResolver((XMLResolver) value); + break; + + case PROP_BASE_URL: + /* 17-Nov-2008, TSa: Let's make it bit more versatile; if it's not + * a URL per se, let's assume it is something that we can convert + * to URL + */ + { + URL u; + if (value == null) { + u = null; + } else if (value instanceof URL) { + u = (URL) value; + } else { + try { + u = new URL(value.toString()); + } catch (Exception ioe) { // MalformedURLException actually... + throw new IllegalArgumentException(ioe.getMessage(), ioe); + } + } + setBaseURL(u); + } + break; + + case PROP_INPUT_PARSING_MODE: + setInputParsingMode((WstxInputProperties.ParsingMode) value); + break; + + default: // sanity check, should never happen + throw new IllegalStateException("Internal error: no handler for property with internal id "+id+"."); + } + + return true; + } + + protected boolean _hasConfigFlag(int flag) { + return (mConfigFlags & flag) != 0; + } + + /** + * Method similar to {@link #_hasConfigFlag}, but that will only + * return true if in addition to being set, flag has been explicitly + * modified (i.e. setProperty has been called to modify it) + */ + protected boolean _hasExplicitConfigFlag(int flag) { + return _hasConfigFlag(flag) && (mConfigFlagMods & flag) != 0; + } + + private final Object _getSpecialProperty(int ix) + { + if (mSpecialProperties == null) { + return null; + } + return mSpecialProperties[ix]; + } + + private final void _setSpecialProperty(int ix, Object value) + { + if (mSpecialProperties == null) { + mSpecialProperties = new Object[SPEC_PROC_COUNT]; + } + mSpecialProperties[ix] = value; + } +} diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/api/ValidatorConfig.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/api/ValidatorConfig.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/api/ValidatorConfig.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/api/ValidatorConfig.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,42 @@ +package com.ctc.wstx.api; + +public final class ValidatorConfig + extends CommonConfig +{ + /** + * For now, since there are no mutable properties, we can share + * a singleton instance. + */ + final static ValidatorConfig sInstance = new ValidatorConfig(null); + + private ValidatorConfig(ValidatorConfig base) { + super(base); + } + + public static ValidatorConfig createDefaults() + { + /* For now, since there are no mutable properties, we can share + * a singleton instance. + */ + return sInstance; + } + + @Override + protected int findPropertyId(String propName) { + // Nothing above and beyond default settings... + return -1; + } + + @Override + protected Object getProperty(int id) { + // nothing to get: + return null; + } + + @Override + protected boolean setProperty(String propName, int id, Object value) { + // nothing to set: + return false; + } +} + diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/api/WriterConfig.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/api/WriterConfig.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/api/WriterConfig.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/api/WriterConfig.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,900 @@ +package com.ctc.wstx.api; + +import java.lang.ref.SoftReference; +import java.util.HashMap; + +import javax.xml.stream.XMLOutputFactory; +import javax.xml.stream.XMLReporter; + +import org.codehaus.stax2.XMLOutputFactory2; +import org.codehaus.stax2.XMLStreamProperties; +import org.codehaus.stax2.io.EscapingWriterFactory; + +import com.ctc.wstx.cfg.OutputConfigFlags; +import com.ctc.wstx.io.BufferRecycler; +import com.ctc.wstx.util.ArgUtil; +import com.ctc.wstx.util.DataUtil; +// for property consts + +/** + * Simple configuration container class; passed by writer factory to writer + * instance created. + */ +public final class WriterConfig + extends CommonConfig + implements OutputConfigFlags +{ + // // // Constants for standard Stax properties: + + protected final static String DEFAULT_AUTOMATIC_NS_PREFIX = "wstxns"; + + // // // First, standard Stax writer properties + + final static int PROP_AUTOMATIC_NS = 1; // standard property ("repairing") + + // // // And then additional Stax2 properties: + + // General output settings + final static int PROP_AUTOMATIC_EMPTY_ELEMENTS = 2; + final static int PROP_AUTO_CLOSE_OUTPUT = 3; + // Namespace settings: + final static int PROP_ENABLE_NS = 4; + final static int PROP_AUTOMATIC_NS_PREFIX = 5; + // Escaping text content/attr values: + final static int PROP_TEXT_ESCAPER = 6; + final static int PROP_ATTR_VALUE_ESCAPER = 7; + // Problem checking/reporting options + final static int PROP_PROBLEM_REPORTER = 8; + + // // // And then custom Wstx properties: + + // Output settings: + final static int PROP_USE_DOUBLE_QUOTES_IN_XML_DECL = 10; + + final static int PROP_OUTPUT_CDATA_AS_TEXT = 11; + + final static int PROP_COPY_DEFAULT_ATTRS = 12; + + final static int PROP_ESCAPE_CR = 13; + + final static int PROP_ADD_SPACE_AFTER_EMPTY_ELEM = 14; + + final static int PROP_AUTOMATIC_END_ELEMENTS = 15; + + // Validation flags: + + final static int PROP_VALIDATE_STRUCTURE = 16; + final static int PROP_VALIDATE_CONTENT = 17; + final static int PROP_VALIDATE_ATTR = 18; + final static int PROP_VALIDATE_NAMES = 19; + final static int PROP_FIX_CONTENT = 20; + + // Other: + + final static int PROP_OUTPUT_INVALID_CHAR_HANDLER = 21; + final static int PROP_OUTPUT_EMPTY_ELEMENT_HANDLER = 22; + + // Per-writer instance information + + final static int PROP_UNDERLYING_STREAM = 30; + final static int PROP_UNDERLYING_WRITER = 31; + + // // // Default settings for additional properties: + + /* 18-May-2013, feature request WSTX-291 + */ + final static boolean DEFAULT_USE_DOUBLE_QUOTES_IN_XML_DECL = false; + + final static boolean DEFAULT_OUTPUT_CDATA_AS_TEXT = false; + final static boolean DEFAULT_COPY_DEFAULT_ATTRS = false; + + /* 26-Dec-2006, TSa: Since CRs have been auto-escaped so far, let's + * retain the defaults when adding new properties/features. + */ + final static boolean DEFAULT_ESCAPE_CR = true; + + /** + * 09-Aug-2007, TSa: Space has always been added after empty + * element (before closing "/>"), but now it is configurable. + * 31-Dec-2009, TSa: Intention was to leave it enabled for backwards + * compatibility: but due to a bug this was NOT the case... ugh. + */ + final static boolean DEFAULT_ADD_SPACE_AFTER_EMPTY_ELEM = false; + + /* How about validation? Let's turn them mostly off by default, since + * there are some performance hits when enabling them. + */ + + // Structural checks are easy, cheap and useful... + final static boolean DEFAULT_VALIDATE_STRUCTURE = true; + + /* 17-May-2006, TSa: Since content validation is now much cheaper + * (due to integrated transcoders) than it used to be, let's + * just enable content validation too. + */ + final static boolean DEFAULT_VALIDATE_CONTENT = true; + final static boolean DEFAULT_VALIDATE_ATTR = false; + final static boolean DEFAULT_VALIDATE_NAMES = false; + + // This only matters if content validation is enabled... + /** + * As per [WSTX-120], default was changed to false, + * from true (default prior to wstx 4.0) + */ + //final static boolean DEFAULT_FIX_CONTENT = true; + final static boolean DEFAULT_FIX_CONTENT = false; + + /** + * Default config flags are converted from individual settings, + * to conform to Stax 1.0 specifications. + */ + final static int DEFAULT_FLAGS_J2ME = + 0 + + // Stax 1.0 mandated: + + // namespace-awareness assumed; repairing disabled by default: + // | CFG_AUTOMATIC_NS + | CFG_ENABLE_NS + + // Usually it's good to allow writer to produce empty elems + // (note: default for woodstox 1.x was false) + | CFG_AUTOMATIC_EMPTY_ELEMENTS + + | (DEFAULT_USE_DOUBLE_QUOTES_IN_XML_DECL ? CFG_USE_DOUBLE_QUOTES_IN_XML_DECL : 0) + | (DEFAULT_OUTPUT_CDATA_AS_TEXT ? CFG_OUTPUT_CDATA_AS_TEXT : 0) + | (DEFAULT_COPY_DEFAULT_ATTRS ? CFG_COPY_DEFAULT_ATTRS : 0) + | (DEFAULT_ESCAPE_CR ? CFG_ESCAPE_CR : 0) + | (DEFAULT_ADD_SPACE_AFTER_EMPTY_ELEM ? CFG_ADD_SPACE_AFTER_EMPTY_ELEM : 0) + | CFG_AUTOMATIC_END_ELEMENTS + + | (DEFAULT_VALIDATE_STRUCTURE ? CFG_VALIDATE_STRUCTURE : 0) + | (DEFAULT_VALIDATE_CONTENT ? CFG_VALIDATE_CONTENT : 0) + | (DEFAULT_VALIDATE_ATTR ? CFG_VALIDATE_ATTR : 0) + | (DEFAULT_VALIDATE_NAMES ? CFG_VALIDATE_NAMES : 0) + | (DEFAULT_FIX_CONTENT ? CFG_FIX_CONTENT : 0) + + // As per Stax 1.0 specs, we can not enable this by default: + //| CFG_AUTO_CLOSE_INPUT); + ; + + /** + * For now, full instances start with same settings as J2ME subset + */ + final static int DEFAULT_FLAGS_FULL = DEFAULT_FLAGS_J2ME; + + // // // + + /** + * Map to use for converting from String property ids to ints + * described above; useful to allow use of switch later on. + */ + final static HashMap sProperties = new HashMap(8); + static { + // // Stax (1.0) standard ones: + sProperties.put(XMLOutputFactory.IS_REPAIRING_NAMESPACES, + DataUtil.Integer(PROP_AUTOMATIC_NS)); + + // // Stax2 standard ones: + + // Namespace support + sProperties.put(XMLStreamProperties.XSP_NAMESPACE_AWARE, + DataUtil.Integer(PROP_ENABLE_NS)); + + // Generic output + sProperties.put(XMLOutputFactory2.P_AUTOMATIC_EMPTY_ELEMENTS, + DataUtil.Integer(PROP_AUTOMATIC_EMPTY_ELEMENTS)); + sProperties.put(XMLOutputFactory2.P_AUTO_CLOSE_OUTPUT, + DataUtil.Integer(PROP_AUTO_CLOSE_OUTPUT)); + // Namespace support + sProperties.put(XMLOutputFactory2.P_AUTOMATIC_NS_PREFIX, + DataUtil.Integer(PROP_AUTOMATIC_NS_PREFIX)); + // Text/attr value escaping (customized escapers) + sProperties.put(XMLOutputFactory2.P_TEXT_ESCAPER, + DataUtil.Integer(PROP_TEXT_ESCAPER)); + sProperties.put(XMLOutputFactory2.P_ATTR_VALUE_ESCAPER, + DataUtil.Integer(PROP_ATTR_VALUE_ESCAPER)); + // Problem checking/reporting options + sProperties.put(XMLStreamProperties.XSP_PROBLEM_REPORTER, + DataUtil.Integer(PROP_PROBLEM_REPORTER)); + + // // Woodstox-specifics: + + // Output conversions + sProperties.put(WstxOutputProperties.P_USE_DOUBLE_QUOTES_IN_XML_DECL, + DataUtil.Integer(PROP_USE_DOUBLE_QUOTES_IN_XML_DECL)); + sProperties.put(WstxOutputProperties.P_OUTPUT_CDATA_AS_TEXT, + DataUtil.Integer(PROP_OUTPUT_CDATA_AS_TEXT)); + sProperties.put(WstxOutputProperties.P_COPY_DEFAULT_ATTRS, + DataUtil.Integer(PROP_COPY_DEFAULT_ATTRS)); + sProperties.put(WstxOutputProperties.P_OUTPUT_ESCAPE_CR, + DataUtil.Integer(PROP_ESCAPE_CR)); + sProperties.put(WstxOutputProperties.P_ADD_SPACE_AFTER_EMPTY_ELEM, + DataUtil.Integer(PROP_ADD_SPACE_AFTER_EMPTY_ELEM)); + sProperties.put(WstxOutputProperties.P_AUTOMATIC_END_ELEMENTS, + DataUtil.Integer(PROP_AUTOMATIC_END_ELEMENTS)); + sProperties.put(WstxOutputProperties.P_OUTPUT_INVALID_CHAR_HANDLER, + DataUtil.Integer(PROP_OUTPUT_INVALID_CHAR_HANDLER)); + sProperties.put(WstxOutputProperties.P_OUTPUT_EMPTY_ELEMENT_HANDLER, + DataUtil.Integer(PROP_OUTPUT_EMPTY_ELEMENT_HANDLER)); + + // Validation settings: + sProperties.put(WstxOutputProperties.P_OUTPUT_VALIDATE_STRUCTURE, + DataUtil.Integer(PROP_VALIDATE_STRUCTURE)); + sProperties.put(WstxOutputProperties.P_OUTPUT_VALIDATE_CONTENT, + DataUtil.Integer(PROP_VALIDATE_CONTENT)); + sProperties.put(WstxOutputProperties.P_OUTPUT_VALIDATE_ATTR, + DataUtil.Integer(PROP_VALIDATE_ATTR)); + sProperties.put(WstxOutputProperties.P_OUTPUT_VALIDATE_NAMES, + DataUtil.Integer(PROP_VALIDATE_NAMES)); + sProperties.put(WstxOutputProperties.P_OUTPUT_FIX_CONTENT, + DataUtil.Integer(PROP_FIX_CONTENT)); + + // Underlying stream/writer access + sProperties.put(WstxOutputProperties.P_OUTPUT_UNDERLYING_STREAM, + DataUtil.Integer(PROP_UNDERLYING_STREAM)); + sProperties.put(WstxOutputProperties.P_OUTPUT_UNDERLYING_STREAM, + DataUtil.Integer(PROP_UNDERLYING_STREAM)); + } + + /* + ////////////////////////////////////////////////////////// + // Current config state: + ////////////////////////////////////////////////////////// + */ + + final boolean mIsJ2MESubset; + + protected int mConfigFlags; + + /* + ////////////////////////////////////////////////////////// + // More special(ized) configuration objects + ////////////////////////////////////////////////////////// + */ + + //protected String mAutoNsPrefix; + //protected EscapingWriterFactory mTextEscaperFactory = null; + //protected EscapingWriterFactory mAttrValueEscaperFactory = null; + //protected XMLReporter mProblemReporter = null; + //protected InvalidCharHandler mInvalidCharHandler = null; + + Object[] mSpecialProperties = null; + + private final static int SPEC_PROC_COUNT = 6; + + private final static int SP_IX_AUTO_NS_PREFIX = 0; + private final static int SP_IX_TEXT_ESCAPER_FACTORY = 1; + private final static int SP_IX_ATTR_VALUE_ESCAPER_FACTORY = 2; + private final static int SP_IX_PROBLEM_REPORTER = 3; + private final static int SP_IX_INVALID_CHAR_HANDLER = 4; + private final static int SP_IX_EMPTY_ELEMENT_HANDLER = 5; + + /* + ////////////////////////////////////////////////////////// + // Buffer recycling: + ////////////////////////////////////////////////////////// + */ + + /** + * This ThreadLocal contains a {@link SoftRerefence} + * to a {@link BufferRecycler} used to provide a low-cost + * buffer recycling between Reader instances. + */ + final static ThreadLocal> mRecyclerRef = new ThreadLocal>(); + + /** + * This is the actually container of the recyclable buffers. It + * is obtained via ThreadLocal/SoftReference combination, if one + * exists, when Config instance is created. If one does not + * exists, it will created first time a buffer is returned. + */ + BufferRecycler mCurrRecycler = null; + + /* + ////////////////////////////////////////////////////////// + // Life-cycle: + ////////////////////////////////////////////////////////// + */ + + private WriterConfig(WriterConfig base, + boolean j2meSubset, int flags, Object[] specProps) + { + super(base); + mIsJ2MESubset = j2meSubset; + mConfigFlags = flags; + mSpecialProperties = specProps; + + /* Ok, let's then see if we can find a buffer recycler. Since they + * are lazily constructed, and since GC may just flush them out + * on its whims, it's possible we might not find one. That's ok; + * we can reconstruct one if and when we are to return one or more + * buffers. + */ + SoftReference ref = mRecyclerRef.get(); + if (ref != null) { + mCurrRecycler = ref.get(); + } + } + + public static WriterConfig createJ2MEDefaults() + { + return new WriterConfig(null, true, DEFAULT_FLAGS_J2ME, null); + } + + public static WriterConfig createFullDefaults() + { + return new WriterConfig(null, false, DEFAULT_FLAGS_FULL, null); + } + + public WriterConfig createNonShared() + { + Object[] specProps; + + if (mSpecialProperties != null) { + int len = mSpecialProperties.length; + specProps = new Object[len]; + System.arraycopy(mSpecialProperties, 0, specProps, 0, len); + } else { + specProps = null; + } + return new WriterConfig(this, mIsJ2MESubset, mConfigFlags, specProps); + } + + /* + ////////////////////////////////////////////////////////// + // Implementation of abstract methods + ////////////////////////////////////////////////////////// + */ + + @Override + protected int findPropertyId(String propName) + { + Integer I = sProperties.get(propName); + return (I == null) ? -1 : I.intValue(); + } + + /* + ////////////////////////////////////////////////////////// + // Public API + ////////////////////////////////////////////////////////// + */ + + @Override + public Object getProperty(int id) + { + switch (id) { + + // First, Stax 1.0 properties: + + case PROP_AUTOMATIC_NS: + return automaticNamespacesEnabled() ? Boolean.TRUE : Boolean.FALSE; + + // Then Stax2 properties: + + // First, properties common to input/output factories: + + case PROP_ENABLE_NS: + return willSupportNamespaces() ? Boolean.TRUE : Boolean.FALSE; + case PROP_PROBLEM_REPORTER: + return getProblemReporter(); + + // Then output-specific properties: + case PROP_AUTOMATIC_EMPTY_ELEMENTS: + return automaticEmptyElementsEnabled() ? Boolean.TRUE : Boolean.FALSE; + case PROP_AUTO_CLOSE_OUTPUT: + return willAutoCloseOutput() ? Boolean.TRUE : Boolean.FALSE; + case PROP_AUTOMATIC_NS_PREFIX: + return getAutomaticNsPrefix(); + case PROP_TEXT_ESCAPER: + return getTextEscaperFactory(); + case PROP_ATTR_VALUE_ESCAPER: + return getAttrValueEscaperFactory(); + + // // // Then Woodstox-specific properties: + + case PROP_USE_DOUBLE_QUOTES_IN_XML_DECL: + return willUseDoubleQuotesInXmlDecl() ? Boolean.TRUE : Boolean.FALSE; + case PROP_OUTPUT_CDATA_AS_TEXT: + return willOutputCDataAsText() ? Boolean.TRUE : Boolean.FALSE; + case PROP_COPY_DEFAULT_ATTRS: + return willCopyDefaultAttrs() ? Boolean.TRUE : Boolean.FALSE; + case PROP_ESCAPE_CR: + return willEscapeCr() ? Boolean.TRUE : Boolean.FALSE; + case PROP_ADD_SPACE_AFTER_EMPTY_ELEM: + return willAddSpaceAfterEmptyElem() ? Boolean.TRUE : Boolean.FALSE; + case PROP_AUTOMATIC_END_ELEMENTS: + return automaticEndElementsEnabled() ? Boolean.TRUE : Boolean.FALSE; + + case PROP_VALIDATE_STRUCTURE: + return willValidateStructure() ? Boolean.TRUE : Boolean.FALSE; + case PROP_VALIDATE_CONTENT: + return willValidateContent() ? Boolean.TRUE : Boolean.FALSE; + case PROP_VALIDATE_ATTR: + return willValidateAttributes() ? Boolean.TRUE : Boolean.FALSE; + case PROP_VALIDATE_NAMES: + return willValidateNames() ? Boolean.TRUE : Boolean.FALSE; + case PROP_FIX_CONTENT: + return willFixContent() ? Boolean.TRUE : Boolean.FALSE; + case PROP_OUTPUT_INVALID_CHAR_HANDLER: + return getInvalidCharHandler(); + case PROP_OUTPUT_EMPTY_ELEMENT_HANDLER: + return getEmptyElementHandler(); + + // And then per-instance properties: not valid via config object + case PROP_UNDERLYING_STREAM: + case PROP_UNDERLYING_WRITER: + throw new IllegalStateException("Can not access per-stream-writer properties via factory"); + } + + throw new IllegalStateException("Internal error: no handler for property with internal id "+id+"."); + } + + /** + * @return True, if the specified property was succesfully + * set to specified value; false if its value was not changed + */ + @Override + public boolean setProperty(String name, int id, Object value) + { + switch (id) { + // First, Stax 1.0 properties: + + case PROP_AUTOMATIC_NS: + enableAutomaticNamespaces(ArgUtil.convertToBoolean(name, value)); + break; + + // // // Then Stax2 ones: + + case PROP_ENABLE_NS: + doSupportNamespaces(ArgUtil.convertToBoolean(name, value)); + break; + case PROP_PROBLEM_REPORTER: + setProblemReporter((XMLReporter) value); + break; + + case PROP_AUTOMATIC_EMPTY_ELEMENTS: + enableAutomaticEmptyElements(ArgUtil.convertToBoolean(name, value)); + break; + + case PROP_AUTO_CLOSE_OUTPUT: + doAutoCloseOutput(ArgUtil.convertToBoolean(name, value)); + break; + + case PROP_AUTOMATIC_NS_PREFIX: + // value should be a String, but let's verify that: + setAutomaticNsPrefix(value.toString()); + break; + + case PROP_TEXT_ESCAPER: + setTextEscaperFactory((EscapingWriterFactory) value); + break; + + case PROP_ATTR_VALUE_ESCAPER: + setAttrValueEscaperFactory((EscapingWriterFactory) value); + break; + + // // // Then Woodstox-specific ones: + + case PROP_USE_DOUBLE_QUOTES_IN_XML_DECL: + doUseDoubleQuotesInXmlDecl(ArgUtil.convertToBoolean(name, value)); + break; + case PROP_OUTPUT_CDATA_AS_TEXT: + doOutputCDataAsText(ArgUtil.convertToBoolean(name, value)); + break; + case PROP_COPY_DEFAULT_ATTRS: + doCopyDefaultAttrs(ArgUtil.convertToBoolean(name, value)); + break; + case PROP_ESCAPE_CR: + doEscapeCr(ArgUtil.convertToBoolean(name, value)); + break; + case PROP_ADD_SPACE_AFTER_EMPTY_ELEM: + doAddSpaceAfterEmptyElem(ArgUtil.convertToBoolean(name, value)); + break; + case PROP_AUTOMATIC_END_ELEMENTS: + enableAutomaticEndElements(ArgUtil.convertToBoolean(name, value)); + break; + case PROP_VALIDATE_STRUCTURE: + doValidateStructure(ArgUtil.convertToBoolean(name, value)); + break; + case PROP_VALIDATE_CONTENT: + doValidateContent(ArgUtil.convertToBoolean(name, value)); + break; + case PROP_VALIDATE_ATTR: + doValidateAttributes(ArgUtil.convertToBoolean(name, value)); + break; + case PROP_VALIDATE_NAMES: + doValidateNames(ArgUtil.convertToBoolean(name, value)); + break; + case PROP_FIX_CONTENT: + doFixContent(ArgUtil.convertToBoolean(name, value)); + break; + case PROP_OUTPUT_INVALID_CHAR_HANDLER: + setInvalidCharHandler((InvalidCharHandler) value); + break; + case PROP_OUTPUT_EMPTY_ELEMENT_HANDLER: + setEmptyElementHandler((EmptyElementHandler) value); + break; + + case PROP_UNDERLYING_STREAM: + case PROP_UNDERLYING_WRITER: + throw new IllegalStateException("Can not modify per-stream-writer properties via factory"); + + default: + throw new IllegalStateException("Internal error: no handler for property with internal id "+id+"."); + } + + return true; + } + + /* + ////////////////////////////////////////////////////////// + // Extended Woodstox API, accessors/modifiers + ////////////////////////////////////////////////////////// + */ + + // // // "Raw" accessors for on/off properties: + + public int getConfigFlags() { return mConfigFlags; } + + + // // // Accessors, standard properties: + + public boolean automaticNamespacesEnabled() { + return hasConfigFlag(CFG_AUTOMATIC_NS); + } + + // // // Accessors, Woodstox properties: + + public boolean automaticEmptyElementsEnabled() { + return hasConfigFlag(CFG_AUTOMATIC_EMPTY_ELEMENTS); + } + + public boolean willAutoCloseOutput() { + return hasConfigFlag(CFG_AUTO_CLOSE_OUTPUT); + } + + public boolean willSupportNamespaces() { + return hasConfigFlag(CFG_ENABLE_NS); + } + + /** + * @since 4.2.2 + */ + public boolean willUseDoubleQuotesInXmlDecl() { + return hasConfigFlag(CFG_USE_DOUBLE_QUOTES_IN_XML_DECL); + } + + public boolean willOutputCDataAsText() { + return hasConfigFlag(CFG_OUTPUT_CDATA_AS_TEXT); + } + + public boolean willCopyDefaultAttrs() { + return hasConfigFlag(CFG_COPY_DEFAULT_ATTRS); + } + + public boolean willEscapeCr() { + return hasConfigFlag(CFG_ESCAPE_CR); + } + + public boolean willAddSpaceAfterEmptyElem() { + return hasConfigFlag(CFG_ADD_SPACE_AFTER_EMPTY_ELEM); + } + + public boolean automaticEndElementsEnabled() { + return hasConfigFlag(CFG_AUTOMATIC_END_ELEMENTS); + } + + public boolean willValidateStructure() { + return hasConfigFlag(CFG_VALIDATE_STRUCTURE); + } + + public boolean willValidateContent() { + return hasConfigFlag(CFG_VALIDATE_CONTENT); + } + + public boolean willValidateAttributes() { + return hasConfigFlag(CFG_VALIDATE_ATTR); + } + + public boolean willValidateNames() { + return hasConfigFlag(CFG_VALIDATE_NAMES); + } + + public boolean willFixContent() { + return hasConfigFlag(CFG_FIX_CONTENT); + } + + /** + * @return Prefix to use as the base for automatically generated + * namespace prefixes ("namespace prefix prefix", so to speak). + * Defaults to "wstxns". + */ + public String getAutomaticNsPrefix() { + String prefix = (String) getSpecialProperty(SP_IX_AUTO_NS_PREFIX); + if (prefix == null) { + prefix = DEFAULT_AUTOMATIC_NS_PREFIX; + } + return prefix; + } + + public EscapingWriterFactory getTextEscaperFactory() { + return (EscapingWriterFactory) getSpecialProperty(SP_IX_TEXT_ESCAPER_FACTORY); + } + + public EscapingWriterFactory getAttrValueEscaperFactory() { + return (EscapingWriterFactory) getSpecialProperty(SP_IX_ATTR_VALUE_ESCAPER_FACTORY); + } + + public XMLReporter getProblemReporter() { + return (XMLReporter) getSpecialProperty(SP_IX_PROBLEM_REPORTER); + } + + public InvalidCharHandler getInvalidCharHandler() { + return (InvalidCharHandler) getSpecialProperty(SP_IX_INVALID_CHAR_HANDLER); + } + + public EmptyElementHandler getEmptyElementHandler() { + return (EmptyElementHandler) getSpecialProperty(SP_IX_EMPTY_ELEMENT_HANDLER); + } + + // // // Mutators: + + // Standard properies: + + public void enableAutomaticNamespaces(boolean state) { + setConfigFlag(CFG_AUTOMATIC_NS, state); + } + + // Wstx properies: + + public void enableAutomaticEmptyElements(boolean state) { + setConfigFlag(CFG_AUTOMATIC_EMPTY_ELEMENTS, state); + } + + public void doAutoCloseOutput(boolean state) { + setConfigFlag(CFG_AUTO_CLOSE_OUTPUT, state); + } + + public void doSupportNamespaces(boolean state) { + setConfigFlag(CFG_ENABLE_NS, state); + } + + /** + * @since 4.2.2 + */ + public void doUseDoubleQuotesInXmlDecl(boolean state) { + setConfigFlag(CFG_USE_DOUBLE_QUOTES_IN_XML_DECL, state); + } + + public void doOutputCDataAsText(boolean state) { + setConfigFlag(CFG_OUTPUT_CDATA_AS_TEXT, state); + } + + public void doCopyDefaultAttrs(boolean state) { + setConfigFlag(CFG_COPY_DEFAULT_ATTRS, state); + } + + public void doEscapeCr(boolean state) { + setConfigFlag(CFG_ESCAPE_CR, state); + } + + public void doAddSpaceAfterEmptyElem(boolean state) { + setConfigFlag(CFG_ADD_SPACE_AFTER_EMPTY_ELEM, state); + } + + public void enableAutomaticEndElements(boolean state) { + setConfigFlag(CFG_AUTOMATIC_END_ELEMENTS, state); + } + + public void doValidateStructure(boolean state) { + setConfigFlag(CFG_VALIDATE_STRUCTURE, state); + } + + public void doValidateContent(boolean state) { + setConfigFlag(CFG_VALIDATE_CONTENT, state); + } + + public void doValidateAttributes(boolean state) { + setConfigFlag(CFG_VALIDATE_ATTR, state); + } + + public void doValidateNames(boolean state) { + setConfigFlag(CFG_VALIDATE_NAMES, state); + } + + public void doFixContent(boolean state) { + setConfigFlag(CFG_FIX_CONTENT, state); + } + + /** + * @param prefix Prefix to use as the base for automatically generated + * namespace prefixes ("namespace prefix prefix", so to speak). + */ + public void setAutomaticNsPrefix(String prefix) { + setSpecialProperty(SP_IX_AUTO_NS_PREFIX, prefix); + } + + public void setTextEscaperFactory(EscapingWriterFactory f) { + setSpecialProperty(SP_IX_TEXT_ESCAPER_FACTORY, f); + } + + public void setAttrValueEscaperFactory(EscapingWriterFactory f) { + setSpecialProperty(SP_IX_ATTR_VALUE_ESCAPER_FACTORY, f); + } + + public void setProblemReporter(XMLReporter rep) { + setSpecialProperty(SP_IX_PROBLEM_REPORTER, rep); + } + + public void setInvalidCharHandler(InvalidCharHandler h) { + setSpecialProperty(SP_IX_INVALID_CHAR_HANDLER, h); + } + + public void setEmptyElementHandler(EmptyElementHandler h) { + setSpecialProperty(SP_IX_EMPTY_ELEMENT_HANDLER, h); + } + + /* + ////////////////////////////////////////////////////////// + // Extended Woodstox API, profiles + ////////////////////////////////////////////////////////// + */ + + /** + * For Woodstox, this profile enables all basic well-formedness checks, + * including checking for name validity. + */ + public void configureForXmlConformance() + { + doValidateAttributes(true); + doValidateContent(true); + doValidateStructure(true); + doValidateNames(true); + } + + /** + * For Woodstox, this profile enables all basic well-formedness checks, + * including checking for name validity, and also enables all matching + * "fix-me" properties (currently only content-fixing property exists). + */ + public void configureForRobustness() + { + doValidateAttributes(true); + doValidateStructure(true); + doValidateNames(true); + + /* This the actual "meat": we do want to not only check if the + * content is ok, but also "fix" it if not, and if there's a way + * to fix it: + */ + doValidateContent(true); + doFixContent(true); + } + + /** + * For Woodstox, setting this profile disables most checks for validity; + * specifically anything that can have measurable performance impact. + * + */ + public void configureForSpeed() + { + doValidateAttributes(false); + doValidateContent(false); + doValidateNames(false); + + // Structural validation is cheap: can be left enabled (if already so) + //doValidateStructure(false); + } + + /* + ///////////////////////////////////////////////////// + // Buffer recycling: + ///////////////////////////////////////////////////// + */ + + /** + * Method called to allocate intermediate recyclable copy buffers + */ + public char[] allocMediumCBuffer(int minSize) + { + if (mCurrRecycler != null) { + char[] result = mCurrRecycler.getMediumCBuffer(minSize); + if (result != null) { + return result; + } + } + return new char[minSize]; + } + + public void freeMediumCBuffer(char[] buffer) + { + // Need to create (and assign) the buffer? + if (mCurrRecycler == null) { + mCurrRecycler = createRecycler(); + } + mCurrRecycler.returnMediumCBuffer(buffer); + } + + public char[] allocFullCBuffer(int minSize) + { + if (mCurrRecycler != null) { + char[] result = mCurrRecycler.getFullCBuffer(minSize); + if (result != null) { + return result; + } + } + return new char[minSize]; + } + + public void freeFullCBuffer(char[] buffer) + { + // Need to create (and assign) the buffer? + if (mCurrRecycler == null) { + mCurrRecycler = createRecycler(); + } + mCurrRecycler.returnFullCBuffer(buffer); + } + + public byte[] allocFullBBuffer(int minSize) + { + if (mCurrRecycler != null) { + byte[] result = mCurrRecycler.getFullBBuffer(minSize); + if (result != null) { + return result; + } + } + return new byte[minSize]; + } + + public void freeFullBBuffer(byte[] buffer) + { + // Need to create (and assign) the buffer? + if (mCurrRecycler == null) { + mCurrRecycler = createRecycler(); + } + mCurrRecycler.returnFullBBuffer(buffer); + } + + private BufferRecycler createRecycler() + { + BufferRecycler recycler = new BufferRecycler(); + // No way to reuse/reset SoftReference, have to create new always: + mRecyclerRef.set(new SoftReference(recycler)); + return recycler; + } + + /* + ////////////////////////////////////////////////////////// + // Internal methods + ////////////////////////////////////////////////////////// + */ + + private void setConfigFlag(int flag, boolean state) { + if (state) { + mConfigFlags |= flag; + } else { + mConfigFlags &= ~flag; + } + } + + private final boolean hasConfigFlag(int flag) { + return ((mConfigFlags & flag) == flag); + } + + private final Object getSpecialProperty(int ix) + { + if (mSpecialProperties == null) { + return null; + } + return mSpecialProperties[ix]; + } + + private final void setSpecialProperty(int ix, Object value) + { + if (mSpecialProperties == null) { + mSpecialProperties = new Object[SPEC_PROC_COUNT]; + } + mSpecialProperties[ix] = value; + } +} diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/api/WstxInputProperties.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/api/WstxInputProperties.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/api/WstxInputProperties.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/api/WstxInputProperties.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,336 @@ +package com.ctc.wstx.api; + +import javax.xml.stream.XMLResolver; + +import org.codehaus.stax2.XMLInputFactory2; + +/** + * Class that contains constant for property names used to configure + * cursor and event readers produced by Wstx implementation of + * {@link javax.xml.stream.XMLInputFactory}. + *

+ * TODO: + * + * - CHECK_CHAR_VALIDITY (separate for white spaces?) + * - CATALOG_RESOLVER? (or at least, ENABLE_CATALOGS) + */ +public final class WstxInputProperties +{ + /** + * Constants used when no DTD handling is done, and we do not know the + * 'real' type of an attribute. Seems like CDATA is the safe choice. + */ + public final static String UNKNOWN_ATTR_TYPE = "CDATA"; + + /* + /////////////////////////////////////////////////////////////////////// + // Simple on/off settings: + /////////////////////////////////////////////////////////////////////// + */ + + // // // Normalization: + + /** + * Feature that controls whether linefeeds are normalized into + * canonical linefeed as mandated by xml specification. + *

+ * Note that disabling this property (from its default enabled + * state) will result in non-conforming XML processing. It may + * be useful for use cases where changes to input content should + * be minimized. + *

+ * Note: this property was initially removed from Woodstox 4.0, + * but was reintroduced in 4.0.8 due to user request. + */ + public final static String P_NORMALIZE_LFS = "com.ctc.wstx.normalizeLFs"; + + //public final static String P_NORMALIZE_ATTR_VALUES = "com.ctc.wstx.normalizeAttrValues"; + + // // // XML character validation: + + /** + * Whether readers will verify that characters in text content are fully + * valid XML characters (not just Unicode). If true, will check + * that they are valid (including white space); if false, will not + * check. + *

+ * Note that this property will NOT have effect on all encoding problems, + * specifically: + *

    + *
  • UTF-8 decoder will still report invalid UTF-8 byte sequences (and same + * for other character encodings). + *
  • + *
  • XML Name character rules follow separate validation which will not be affected + *
  • + *
+ *

+ * Turning this option off may improve parsing performance; leaving + * it on guarantees compatibility with XML 1.0 specs regarding character + * validity rules. + */ + public final static String P_VALIDATE_TEXT_CHARS = "com.ctc.wstx.validateTextChars"; + + // // // Caching: + + /** + * Whether readers will try to cache parsed external DTD subsets or not. + */ + + public final static String P_CACHE_DTDS = "com.ctc.wstx.cacheDTDs"; + + /** + * Whether reader is to cache DTDs (when caching enabled) based on public id + * or not: if not, system id will be primarily used. Although theoretically + * public IDs should be unique, and should be good caching keys, sometimes + * broken documents use 'wrong' public IDs, and such by default caching keys + * are based on system id only. + */ + public final static String P_CACHE_DTDS_BY_PUBLIC_ID = "com.ctc.wstx.cacheDTDsByPublicId"; + + + // // // Enabling/disabling lazy/incomplete parsing + + /** + * Whether stream readers are allowed to do lazy parsing, meaning + * to parse minimal part of the event when + * {@link javax.xml.stream.XMLStreamReader#next} is called, and only parse the rest + * as needed (or skip remainder of no extra information is needed). + * Alternative to lazy parsing is called "eager parsing", and is + * what most xml parsers use by default. + *

+ * Enabling lazy parsing can improve performance for tasks where + * number of textual events are skipped. The downside is that + * not all well-formedness problems are reported when + * {@link javax.xml.stream.XMLStreamReader#next} is called, but only when the + * rest of event are read or skipped. + *

+ * Default value for Woodstox is such that lazy parsing is + * enabled. + * + * @deprecated As of Woodstox 4.0 use + * {@link XMLInputFactory2#P_LAZY_PARSING} instead (from + * Stax2 extension API, v3.0) + */ + @Deprecated + public final static String P_LAZY_PARSING = XMLInputFactory2.P_LAZY_PARSING; + + // // // API behavior (for backwards compatibility) + + /** + * This read-only property indicates whether null is returned for default name space prefix; + * Boolean.TRUE indicates it does, Boolean.FALSE that it does not. + *

+ * Default value for 4.1 is 'false'; this will most likely change for 5.0 since + * Stax API actually specifies null to be used. + * + * @since 4.1.2 + */ + public final static String P_RETURN_NULL_FOR_DEFAULT_NAMESPACE = "com.ctc.wstx.returnNullForDefaultNamespace"; + + // // // Enabling/disabling support for dtd++ + + /** + * Whether the Reader will recognized DTD++ extensions when parsing + * DTD subsets. + *

+ * Note: not implemented by Woodstox. + * + * @deprecated Never implement, let's phase this out (deprecated in 4.2) + */ + @Deprecated + public final static String P_SUPPORT_DTDPP = "com.ctc.wstx.supportDTDPP"; + + /** + * Whether the Reader will treat character references as entities while parsing + * XML documents. + */ + public static final String P_TREAT_CHAR_REFS_AS_ENTS = "com.ctc.wstx.treatCharRefsAsEnts"; + + // // // Enabling alternate mode for parsing XML fragments instead + // // // of full documents + + // Automatic W3C Schema support? + /* + * Whether W3C Schema hint attributes are recognized within document, + * and used to locate Schema to use for validation. + */ + //public final static String P_AUTOMATIC_W3C_SCHEMA = 0x00100000; + + /* + /////////////////////////////////////////////////////////////////////// + // More complex settings + /////////////////////////////////////////////////////////////////////// + */ + + // // // Buffer sizes; + + /** + * Size of input buffer (in chars), to use for reading XML content + * from input stream/reader. + */ + public final static String P_INPUT_BUFFER_LENGTH = "com.ctc.wstx.inputBufferLength"; + + // // // Constraints on sizes of text segments parsed: + + + /** + * Property to specify shortest non-complete text segment (part of + * CDATA section or text content) that parser is allowed to return, + * if not required to coalesce text. + */ + public final static String P_MIN_TEXT_SEGMENT = "com.ctc.wstx.minTextSegment"; + + // // // Other size constraints (4.2+) + + /** + * Maximum number of attributes allowed for single XML element. + * @since 4.2 + */ + public final static String P_MAX_ATTRIBUTES_PER_ELEMENT = "com.ctc.wstx.maxAttributesPerElement"; + + /** + * Maximum length of of individual attribute values (in characters) + * @since 4.2 + */ + public final static String P_MAX_ATTRIBUTE_SIZE = "com.ctc.wstx.maxAttributeSize"; + + /** + * Maximum number of child elements for any given element. + * @since 4.2 + */ + public final static String P_MAX_CHILDREN_PER_ELEMENT = "com.ctc.wstx.maxChildrenPerElement"; + + /** + * Maximum number of all elements in a single document. + * @since 4.2 + */ + public final static String P_MAX_ELEMENT_COUNT = "com.ctc.wstx.maxElementCount"; + + /** + * Maximum level of nesting of XML elements, starting with root element. + * @since 4.2 + */ + public final static String P_MAX_ELEMENT_DEPTH = "com.ctc.wstx.maxElementDepth"; + + /** + * Maximum length of input document, in characters. + * @since 4.2 + */ + public final static String P_MAX_CHARACTERS = "com.ctc.wstx.maxCharacters"; + + /** + * Maximum length of individual text (cdata) segments in input, in characters. + * @since 4.2 + */ + public final static String P_MAX_TEXT_LENGTH = "com.ctc.wstx.maxTextLength"; + + // and more size constraints (4.3+) + + /** + * Maximum number of total (general parsed) entity expansions within input. + * + * @since 4.3 + */ + public final static String P_MAX_ENTITY_COUNT = "com.ctc.wstx.maxEntityCount"; + + /** + * Maximum depth of nested (general parsed) entity expansions. + * + * @since 4.3 + */ + public final static String P_MAX_ENTITY_DEPTH = "com.ctc.wstx.maxEntityDepth"; + + // // // Entity handling + + /** + * Property of type {@link java.util.Map}, that defines explicit set of + * internal (generic) entities that will define of override any entities + * defined in internal or external subsets; except for the 5 pre-defined + * entities (lt, gt, amp, apos, quot). Can be used to explicitly define + * entites that would normally come from a DTD. + *

+ * @deprecated This feature may be removed from future versions of + * Woodstox, since the same functionality can be achieved by using + * custom entity resolvers. + */ + @Deprecated + public final static String P_CUSTOM_INTERNAL_ENTITIES = "com.ctc.wstx.customInternalEntities"; + + /** + * Property of type {@link XMLResolver}, that + * will allow overriding of default DTD and external parameter entity + * resolution. + */ + public final static String P_DTD_RESOLVER = "com.ctc.wstx.dtdResolver"; + + /** + * Property of type {@link XMLResolver}, that + * will allow overriding of default external general entity + * resolution. Note that using this property overrides settings done + * using {@link javax.xml.stream.XMLInputFactory#RESOLVER} (and vice versa). + */ + public final static String P_ENTITY_RESOLVER = "com.ctc.wstx.entityResolver"; + + /** + * Property of type {@link XMLResolver}, that + * will allow graceful handling of references to undeclared (general) + * entities. + */ + public final static String P_UNDECLARED_ENTITY_RESOLVER = "com.ctc.wstx.undeclaredEntityResolver"; + + /** + * Property of type {@link java.net.URL}, that will allow specifying + * context URL to use when resolving relative references, for the + * main-level entities (external DTD subset, references from the internal + * DTD subset). + */ + public final static String P_BASE_URL = "com.ctc.wstx.baseURL"; + + // // // Alternate parsing modes + + /** + * Three-valued property (one of + * {@link #PARSING_MODE_DOCUMENT}, + * {@link #PARSING_MODE_FRAGMENT} or + * {@link #PARSING_MODE_DOCUMENTS}; default being the document mode) + * that can be used to handle "non-standard" XML content. The default + * mode (PARSING_MODE_DOCUMENT) allows parsing of only + * well-formed XML documents, but the other two modes allow more lenient + * parsing. Fragment mode allows parsing of XML content that does not + * have a single root element (can have zero or more), nor can have + * XML or DOCTYPE declarations: this may be useful if parsing a subset + * of a full XML document. Multi-document + * (PARSING_MODE_DOCUMENTS) mode on the other hand allows + * parsing of a stream that contains multiple consequtive well-formed + * documents, with possibly multiple XML and DOCTYPE declarations. + *

+ * The main difference from the API perspective is that in first two + * modes, START_DOCUMENT and END_DOCUMENT are used as usual (as the first + * and last events returned), whereas the multi-document mode can return + * multiple pairs of these events: although it is still true that the + * first event (one cursor points to when reader is instantiated or + * returned by the event reader), there may be intervening pairs that + * signal boundary between two adjacent enclosed documents. + */ + public final static String P_INPUT_PARSING_MODE = "com.ctc.wstx.fragmentMode"; + + // // // DTD defaulting, overriding + + /* + /////////////////////////////////////////////////////////////////////// + // Helper classes, values enumerations + /////////////////////////////////////////////////////////////////////// + */ + + public final static ParsingMode PARSING_MODE_DOCUMENT = new ParsingMode(); + public final static ParsingMode PARSING_MODE_FRAGMENT = new ParsingMode(); + public final static ParsingMode PARSING_MODE_DOCUMENTS = new ParsingMode(); + + /** + * Inner class used for creating type-safe enumerations (prior to JDK 1.5). + */ + public final static class ParsingMode + { + ParsingMode() { } + } +} diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/api/WstxOutputProperties.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/api/WstxOutputProperties.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/api/WstxOutputProperties.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/api/WstxOutputProperties.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,186 @@ +package com.ctc.wstx.api; + +/** + * Class that contains constant for property names used to configure + * cursor and event writers produced by Wstx implementation of + * {@link javax.xml.stream.XMLOutputFactory}. + *

+ */ +public final class WstxOutputProperties +{ + /** + * Default xml version number output, if none was specified by + * application. Version 1.0 is used + * to try to maximize compatibility (some older parsers + * may barf on 1.1 and later...) + */ + public final static String DEFAULT_XML_VERSION = "1.0"; + + /** + * If no encoding is passed, we should just default to what xml + * in general expects (and can determine), UTF-8. + *

+ * Note: you can check out bug entry [WSTX-18] for more details + */ + public final static String DEFAULT_OUTPUT_ENCODING = "UTF-8"; + + // // // Output options, simple on/off settings: + + /** + * Whether writer should use double quotes in the XML declaration. + * The default is to use single quotes. + * + * @since 4.2.2 + */ + public final static String P_USE_DOUBLE_QUOTES_IN_XML_DECL = "com.ctc.wstx.useDoubleQuotesInXmlDecl"; + + /** + * Whether writer should just automatically convert all calls that + * would normally produce CDATA to produce (quoted) text. + */ + public final static String P_OUTPUT_CDATA_AS_TEXT = "com.ctc.wstx.outputCDataAsText"; + + /** + * Whether writer should copy attributes that were initially expanded + * using default settings ("implicit" attributes) or not. + */ + public final static String P_COPY_DEFAULT_ATTRS = "com.ctc.wstx.copyDefaultAttrs"; + + /** + * Whether writer is to add a single white space before closing "/>" + * of the empty element or not. It is sometimes useful to add to + * increase compatibility with HTML browsers, or to increase + * readability. + *

+ * The default value is 'false', up to Woodstox 4.x. + *

+ * NOTE: JavaDocs for versions 4.0.0 - 4.0.7 incorrectly state that + * default is 'true': this is NOT the case. + *

+ * Note: added to resolve Jira entry + * WSTX-125. + */ + public final static String P_ADD_SPACE_AFTER_EMPTY_ELEM = "com.ctc.wstx.addSpaceAfterEmptyElem"; + + /** + * Whether stream writer is to automatically add end elements that are + * needed to properly close the output tree, when the stream is closed + * (either explicitly by a call to close or + * closeCompletely, or implicitly by a call + * to writeEndDocument. + *

+ * The default value is 'true' as of Woodstox 4.x. + * Prior to 4.0, this feature was always enabled and there was no + * way to disable it) + * + * @since 3.2.8 + */ + public final static String P_AUTOMATIC_END_ELEMENTS = "com.ctc.wstx.automaticEndElements"; + + // // // Validation options: + + /** + * Whether output classes should do basic verification that the output + * structure is well-formed (start and end elements match); that + * there is one and only one root, and that there is no textual content + * in prolog/epilog. If false, won't do any checking regarding structure. + */ + public final static String P_OUTPUT_VALIDATE_STRUCTURE = "com.ctc.wstx.outputValidateStructure"; + + /** + * Whether output classes should do basic verification that the textual + * content output as part of nodes should be checked for validity, + * if there's a possibility of invalid content. Nodes that include + * such constraints are: comment/'--', cdata/']]>', + * proc. instr/'?>'. + */ + public final static String P_OUTPUT_VALIDATE_CONTENT = "com.ctc.wstx.outputValidateContent"; + + /** + * Whether output classes should check uniqueness of attribute names, + * to prevent accidental output of duplicate attributes. + */ + public final static String P_OUTPUT_VALIDATE_ATTR = "com.ctc.wstx.outputValidateAttr"; + + /** + * Whether output classes should check validity of names, ie that they + * only contain legal XML identifier characters. + */ + public final static String P_OUTPUT_VALIDATE_NAMES = "com.ctc.wstx.outputValidateNames"; + + /** + * Property that further modifies handling of invalid content so + * that if {@link #P_OUTPUT_VALIDATE_CONTENT} is enabled, instead of + * reporting an error, writer will try to fix the problem. + * Invalid content in this context refers to comment + * content with "--", CDATA with "]]>" and proc. instr data with "?>". + * This can + * be done for some content (CDATA, possibly comment), by splitting + * content into separate + * segments; but not for others (proc. instr, since that might + * change the semantics in unintended ways). + */ + public final static String P_OUTPUT_FIX_CONTENT = "com.ctc.wstx.outputFixContent"; + + /** + * Property that determines whether Carriage Return (\r) characters are + * to be escaped when output or not. If enabled, all instances of + * of character \r are escaped using a character entity (where possible, + * that is, within CHARACTERS events, and attribute values). Otherwise + * they are output as is. The main reason to enable this property is + * to ensure that carriage returns are preserved as is through parsing, + * since otherwise they will be converted to canonical xml linefeeds + * (\n), when occuring along or as part of \r\n pair. + */ + public final static String P_OUTPUT_ESCAPE_CR = "com.ctc.wstx.outputEscapeCr"; + + /** + * Property that defines a {@link InvalidCharHandler} used to determine + * what to do with a Java character that app tries to output but which + * is not a valid xml character. Alternatives are converting it to + * another character or throw an exception: default implementations + * exist for both behaviors. + */ + public final static String P_OUTPUT_INVALID_CHAR_HANDLER = "com.ctc.wstx.outputInvalidCharHandler"; + + /** + * Property that defines an {@link EmptyElementHandler} used to determine + * if the end tag for an empty element should be written or not. + * + * If specified {@link org.codehaus.stax2.XMLOutputFactory2#P_AUTOMATIC_EMPTY_ELEMENTS} is ignored. + */ + public final static String P_OUTPUT_EMPTY_ELEMENT_HANDLER = "com.ctc.wstx.outputEmptyElementHandler"; + + // // // Per-instance access to underlying output objects + + /** + * Property that can be used to find out the underlying + * {@link java.io.OutputStream} that an + * {@link javax.xml.stream.XMLStreamWriter} instance is using, + * if known (not known if constructed with a {@link java.io.Writer}, + * or other non-stream destination). Null is returned, if not + * known. + *

+ * Note: in general it is dangerous to operate on returned stream + * (if any), due to buffering stream writer can do. As such, caller + * has to take care to know what he is doing, including properly + * flushing output. + */ + public final static String P_OUTPUT_UNDERLYING_STREAM = "com.ctc.wstx.outputUnderlyingStream"; + + /** + * Property that can be used to find out the underlying + * {@link java.io.Writer} that an + * {@link javax.xml.stream.XMLStreamWriter} instance is using, + * if known (may not be known if constructed with a {@link java.io.OutputStream}, + * or other non-Writer destination). Null is returned, if not + * known. Note that the Writer may be an internal wrapper over + * an output stream. + *

+ * Note: in general it is dangerous to operate on returned Writer + * (if any), due to buffering stream writer can do. As such, caller + * has to take care to know what he is doing, including properly + * flushing output. + */ + public final static String P_OUTPUT_UNDERLYING_WRITER = "com.ctc.wstx.outputUnderlyingWriter"; +} diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/cfg/ErrorConsts.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/cfg/ErrorConsts.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/cfg/ErrorConsts.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/cfg/ErrorConsts.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,193 @@ +package com.ctc.wstx.cfg; + +import javax.xml.XMLConstants; +import javax.xml.stream.XMLStreamConstants; + +/** + * "Static" class that contains error message constants. Note that the + * error message constants are NOT made final; reason is that doing so + * would make compiler inline them in other classes. Doing so would increase + * class size (although not mem usage -- Strings do get interned), with + * minimal performance impact. + */ +public class ErrorConsts + implements XMLStreamConstants +{ + // // // Types of warnings we issue via XMLReporter + + public static String WT_ENT_DECL = "entity declaration"; + public static String WT_ELEM_DECL = "element declaration"; + public static String WT_ATTR_DECL = "attribute declaration"; + public static String WT_XML_DECL = "xml declaration"; + public static String WT_DT_DECL = "doctype declaration"; + public static String WT_NS_DECL = "namespace declaration"; + + /** + * This is the generic type for warnings based on XMLValidationProblem + * objects. + */ + public static String WT_VALIDATION = "schema validation"; + + // // And then warning strings + + public static String W_UNDEFINED_ELEM = "Undefined element \"{0}\"; referred to by attribute(s)"; + public static String W_MIXED_ENCODINGS = "Inconsistent text encoding; declared as \"{0}\" in xml declaration, application had passed \"{1}\""; + public static String W_MISSING_DTD = "Missing DOCTYPE declaration in validating mode; can not validate elements or attributes"; + public static String W_DTD_DUP_ATTR = "Attribute \"{0}\" (for element <{1}>) declared multiple times"; + public static String W_DTD_ATTR_REDECL = "Attribute \"{0}\" already declared for element <{1}>; ignoring re-declaration"; + + // // // Generic errors: + + public static String ERR_INTERNAL = "Internal error"; + public static String ERR_NULL_ARG = "Illegal to pass null as argument"; + public static String ERR_UNKNOWN_FEATURE = "Unrecognized feature \"{0}\""; + + // // // Wrong reader state: + + public static String ERR_STATE_NOT_STELEM = "Current event not START_ELEMENT"; + public static String ERR_STATE_NOT_ELEM = "Current event not START_ELEMENT or END_ELEMENT"; + public static String ERR_STATE_NOT_PI = "Current event not PROCESSING_INSTRUCTION"; + public static String ERR_STATE_NOT_ELEM_OR_TEXT = "Current event ({0}) not START_ELEMENT, END_ELEMENT, CHARACTERS or CDATA"; + + // // // XML declaration related problems + + public static String ERR_XML_10_VS_11 = "XML 1.0 document can not refer to XML 1.1 parsed external entities"; + + // // // Structural problems, prolog/epilog: + + public static String ERR_DTD_IN_EPILOG = "Can not have DOCTYPE declaration in epilog"; + public static String ERR_DTD_DUP = "Duplicate DOCTYPE declaration"; + public static String ERR_CDATA_IN_EPILOG = " (CDATA not allowed in prolog/epilog)"; + + // // // Illegal input: + + public static String ERR_HYPHENS_IN_COMMENT = "String '--' not allowed in comment (missing '>'?)"; + public static String ERR_BRACKET_IN_TEXT = "String ']]>' not allowed in textual content, except as the end marker of CDATA section"; + + // // // Generic parsing errors: + + public static String ERR_UNEXP_KEYWORD = "Unexpected keyword \"{0}\"; expected \"{1}\""; + + public static String ERR_WF_PI_MISSING_TARGET = "Missing processing instruction target"; + public static String ERR_WF_PI_XML_TARGET = "Illegal processing instruction target (\"{0}\"); 'xml' (case insensitive) is reserved by the specs."; + public static String ERR_WF_PI_XML_MISSING_SPACE = "excepted either space or \"?>\" after PI target"; + + // // // Entity problems: + + public static String ERR_WF_ENTITY_EXT_DECLARED = "Entity \"{0}\" declared externally, but referenced from a document declared 'standalone=\"yes\"'"; + + public static String ERR_WF_GE_UNDECLARED = "Undeclared general entity \"{0}\""; + + public static String ERR_WF_GE_UNDECLARED_SA = "Undeclared general entity \"{0}\" (document in stand-alone mode; perhaps declared externally?)"; + + // // // Namespace problems: + + public static String ERR_NS_UNDECLARED = "Undeclared namespace prefix \"{0}\""; + public static String ERR_NS_UNDECLARED_FOR_ATTR = "Undeclared namespace prefix \"{0}\" (for attribute \"{1}\")"; + + public static String ERR_NS_REDECL_XML = "Trying to redeclare prefix 'xml' from its default URI '" + +XMLConstants.XML_NS_URI + +"' to \"{0}\""; + + public static String ERR_NS_REDECL_XMLNS = "Trying to declare prefix 'xmlns' (illegal as per NS 1.1 #4)"; + + public static String ERR_NS_REDECL_XML_URI = "Trying to bind URI '" + +XMLConstants.XML_NS_URI+" to prefix \"{0}\" (can only bind to 'xml')"; + + public static String ERR_NS_REDECL_XMLNS_URI = "Trying to bind URI '" + +XMLConstants.XMLNS_ATTRIBUTE_NS_URI+" to prefix \"{0}\" (can not be explicitly bound)"; + + public static String ERR_NS_EMPTY = +"Non-default namespace can not map to empty URI (as per Namespace 1.0 # 2) in XML 1.0 documents"; + + + // // // DTD-specific: + + public static String ERR_DTD_MAINLEVEL_KEYWORD = "; expected a keyword (ATTLIST, ELEMENT, ENTITY, NOTATION), comment, or conditional section"; + + public static String ERR_DTD_ATTR_TYPE = "; expected one of type (CDATA, ID, IDREF, IDREFS, ENTITY, ENTITIES NOTATION, NMTOKEN or NMTOKENS)"; + + public static String ERR_DTD_DEFAULT_TYPE = "; expected #REQUIRED, #IMPLIED or #FIXED"; + + public static String ERR_DTD_ELEM_REDEFD = + "Trying to redefine element \"{0}\" (originally defined at {1})"; + public static String ERR_DTD_NOTATION_REDEFD = + "Trying to redefine notation \"{0}\" (originally defined at {1})"; + + public static String ERR_DTD_UNDECLARED_ENTITY = + "Undeclared {0} entity \"{1}\""; + + public static String ERR_DTD_XML_SPACE = "Attribute xml:space has to be defined of type enumerated, and have 1 or 2 values, 'default' and/or 'preserve'"; + + public static String ERR_DTD_XML_ID = "Attribute xml:id has to have attribute type of ID, as per Xml:id specification"; + + + // // // DTD-validation: + + public static String ERR_VLD_UNKNOWN_ELEM = "Undefined element <{0}> encountered"; + + public static String ERR_VLD_EMPTY = "Element <{0}> has EMPTY content specification; can not contain {1}"; + public static String ERR_VLD_NON_MIXED = "Element <{0}> has non-mixed content specification; can not contain non-white space text, or any CDATA sections"; + public static String ERR_VLD_ANY = "Element <{0}> has ANY content specification; can not contain {1}"; + public static String ERR_VLD_UNKNOWN_ATTR = "Element <{0}> has no attribute \"{1}\""; + public static String ERR_VLD_WRONG_ROOT = "Unexpected root element <{0}>; expected <{0}> as per DOCTYPE declaration"; + + // // // Output problems: + + public static String WERR_PROLOG_CDATA = + "Trying to output a CDATA block outside main element tree (in prolog or epilog)"; + public static String WERR_PROLOG_NONWS_TEXT = + "Trying to output non-whitespace characters outside main element tree (in prolog or epilog)"; + public static String WERR_PROLOG_SECOND_ROOT = + "Trying to output second root, <{0}>"; + + public static String WERR_CDATA_CONTENT = + "Illegal input: CDATA block has embedded ']]>' in it (index {0})"; + public static String WERR_COMMENT_CONTENT = + "Illegal input: comment content has embedded '--' in it (index {0})"; + + public static String WERR_ATTR_NO_ELEM = + "Trying to write an attribute when there is no open start element."; + + public static String WERR_NAME_EMPTY = "Illegal to pass empty name"; + + public static String WERR_NAME_ILLEGAL_FIRST_CHAR = "Illegal first name character {0}"; + public static String WERR_NAME_ILLEGAL_CHAR = "Illegal name character {0}"; + + /* + //////////////////////////////////////////////////// + // Utility methods + //////////////////////////////////////////////////// + */ + + public static String tokenTypeDesc(int type) + { + switch (type) { + case START_ELEMENT: + return "START_ELEMENT"; + case END_ELEMENT: + return "END_ELEMENT"; + case START_DOCUMENT: + return "START_DOCUMENT"; + case END_DOCUMENT: + return "END_DOCUMENT"; + + case CHARACTERS: + return "CHARACTERS"; + case CDATA: + return "CDATA"; + case SPACE: + return "SPACE"; + + case COMMENT: + return "COMMENT"; + case PROCESSING_INSTRUCTION: + return "PROCESSING_INSTRUCTION"; + case DTD: + return "DTD"; + case ENTITY_REFERENCE: + return "ENTITY_REFERENCE"; + } + return "["+type+"]"; + } +} diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/cfg/InputConfigFlags.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/cfg/InputConfigFlags.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/cfg/InputConfigFlags.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/cfg/InputConfigFlags.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,204 @@ +package com.ctc.wstx.cfg; + +/** + * Constant interface that contains configuration flag used by parser + * and parser factory, as well as some other input constants. + */ +public interface InputConfigFlags +{ + /* + ////////////////////////////////////////////////////// + // Flags for standard StAX features: + ////////////////////////////////////////////////////// + */ + + // // // Namespace handling: + + /** + * If true, parser will handle namespaces according to XML specs; if + * false, will only pass them as part of element/attribute name value + * information. + */ + final static int CFG_NAMESPACE_AWARE = 0x0001; + + + // // // Text normalization + + + /// Flag that indicates iterator should coalesce all text segments. + final static int CFG_COALESCE_TEXT = 0x0002; + + + // // // Entity handling + + /** + * Flag that enables automatic replacement of internal entities + */ + final static int CFG_REPLACE_ENTITY_REFS = 0x0004; + + /** + * Flag that enables support for expanding external entities. Woodstox + * pretty much ignores the setting, since effectively it is irrelevant, + * as {@link #CFG_REPLACE_ENTITY_REFS} and {@link #CFG_SUPPORT_DTD} + * both need to be enabled for external entities to be supported. + */ + final static int CFG_SUPPORT_EXTERNAL_ENTITIES = 0x0008; + + // // // DTD handling + + /** + * Whether DTD handling is enabled or disabled; disabling means both + * internal and external subsets will just be skipped unprocessed. + */ + final static int CFG_SUPPORT_DTD = 0x0010; + + /** + * Not yet (fully) supported; added as the placeholder + */ + final static int CFG_VALIDATE_AGAINST_DTD = 0x0020; + + // // Note: can add 2 more 'standard' flags here... + + /* + ////////////////////////////////////////////////////// + // Flags for StAX2 features + ////////////////////////////////////////////////////// + */ + + /** + * If true, parser will report (ignorable) white space events in prolog + * and epilog; if false, it will silently ignore them. + */ + final static int CFG_REPORT_PROLOG_WS = 0x0100; + + // // // Type conversions: + + + /** + * If true, parser will accurately report CDATA event as such (unless + * coalescing); otherwise will always report them as CHARACTERS + * independent of coalescing settings. + */ + final static int CFG_REPORT_CDATA = 0x0200; + + // // // String interning: + + /** + * If true, will guarantee that all names (attribute/element local names + * have been intern()ed. If false, this is not guaranteed although + * implementation may still choose to do it. + */ + final static int CFG_INTERN_NAMES = 0x0400; + + /** + * It true, will call intern() on all namespace URIs parsed; otherwise + * will just use 'regular' Strings created from parsed contents. Interning + * makes namespace-based access faster, but has initial overhead of + * intern() call. + */ + final static int CFG_INTERN_NS_URIS = 0x0800; + + // // // Lazy/incomplete parsing + + /** + * Property that determines whether Event objects created will + * contain (accurate) {@link javax.xml.stream.Location} information or not. If not, + * Location may be null or a fixed location (beginning of main + * XML file). + *

+ * Note, however, that the underlying parser will still keep track + * of location information for error reporting purposes; it's only + * Event objects that are affected. + */ + final static int CFG_PRESERVE_LOCATION = 0x1000; + + // // // Input source handling + + /** + * Property that enables/disables stream reader to close the underlying + * input source, either when it is asked to (.close() is called), or + * when it doesn't need it any more (reaching EOF, hitting an + * unrecoverable exception). + * As per Stax 1.0 specification, automatic closing is NOT enabled by + * default; except if the caller has no access to the target (i.e. + * when factory created it) + */ + final static int CFG_AUTO_CLOSE_INPUT = 0x2000; + + /* + ////////////////////////////////////////////////////// + // Flags for Woodstox-specific features + ////////////////////////////////////////////////////// + */ + + // // // Content normalization + + // 20-Jan-2007, TSa: These properties removed from 4.0, deprecated: + final static int CFG_NORMALIZE_LFS = 0x4000; + //final static int CFG_NORMALIZE_ATTR_VALUES = 0x8000; + + // // // Caching + + /** + * If true, input factory is allowed cache parsed external DTD subsets, + * potentially speeding up things for which DTDs are needed for: entity + * substitution, attribute defaulting, and of course DTD-based validation. + */ + final static int CFG_CACHE_DTDS = 0x00010000; + + /** + * If true, key used for matching DTD subsets can be the public id, + * if false, only system id can be used. + */ + final static int CFG_CACHE_DTDS_BY_PUBLIC_ID = 0x00020000; + + // // // Lazy/incomplete parsing + + /** + * If true, input factory can defer parsing of nodes until data is + * actually needed; if false, it has to read all the data in right + * away when next type is requested. Setting it to true is good for + * performance, in the cases where some of the nodes (like comments, + * processing instructions, or whole subtrees) are ignored. Otherwise + * setting will not make much of a difference. Downside is that error + * reporting is also done 'lazily'; not right away when getting the next + * even type but when either accessing data, or skipping it. + */ + final static int CFG_LAZY_PARSING = 0x00040000; + + // // // Validation support + + // DTD++ support + + /** + * If true, DTD-parser will recognize DTD++ features, and the validator + * will also use any such information found from DTD when DTD validation + * is enabled. + */ + final static int CFG_SUPPORT_DTDPP = 0x00080000; + + // Automatic W3C Schema support? + //final static int CFG_AUTOMATIC_W3C_SCHEMA = 0x00100000; + + // // // Xml:id support + + /** + * If true, xml:id attribute type assignment and matching checks will + * be done as per Xml:id specification. Needs to be enabled for xml:id + * uniqueness checks to function properly + */ + final static int CFG_XMLID_TYPING = 0x00200000; + + /** + * If true, xml:id attribute uniqueness constraints are enforced, even + * if not validating against DTD otherwise. + */ + final static int CFG_XMLID_UNIQ_CHECKS = 0x00400000; + + /** + * If true, the XML parser will treat character references as entities. + * + */ + final static int CFG_TREAT_CHAR_REFS_AS_ENTS = 0x00800000; +} + diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/cfg/OutputConfigFlags.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/cfg/OutputConfigFlags.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/cfg/OutputConfigFlags.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/cfg/OutputConfigFlags.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,112 @@ +package com.ctc.wstx.cfg; + +/** + * Constant interface that contains configuration flag used by output + * classes internally, for presenting on/off configuration options. + */ +public interface OutputConfigFlags +{ + /** + * Flag that indicates whether writer is namespace-aware or not; if not, + * only local part is ever used. + */ + final static int CFG_ENABLE_NS = 0x0001; + + /// Flag that indicates that output class should auto-generate namespace prefixes as necessary. + final static int CFG_AUTOMATIC_NS = 0x0002; + + /// Flag that indicates we can output 'automatic' empty elements. + final static int CFG_AUTOMATIC_EMPTY_ELEMENTS = 0x0004; + + /** + * Whether writer should just automatically convert all calls that + * would normally produce CDATA to produce (quoted) text. + */ + final static int CFG_OUTPUT_CDATA_AS_TEXT = 0x0008; + + /** + * Flag that indicates whether attributes expanded from default attribute + * values should be copied to output, when using copy methods. + */ + final static int CFG_COPY_DEFAULT_ATTRS = 0x0010; + + /** + * Flag that indicates whether CR (\r, ascii 13) characters occuring + * in text (CHARACTERS) and attribute values should be escaped using + * character entities or not. Escaping is needed to enable seamless + * round-tripping (preserving CR characters). + */ + final static int CFG_ESCAPE_CR = 0x0020; + + /** + * Flag that indicates + * whether writer is to add a single white space before closing "/>" + * of the empty element or not. It is sometimes useful to add to + * increase compatibility with HTML browsers, or to increase + * readability. + */ + final static int CFG_ADD_SPACE_AFTER_EMPTY_ELEM = 0x0040; + + /** + * Flag that indicates we can output 'automatic' empty elements; + * end elements needed to close the logical output tree when + * stream writer is closed (by closing it explicitly, or by writing + * end-document event) + * + * @since 3.2.8 + */ + final static int CFG_AUTOMATIC_END_ELEMENTS = 0x0080; + + /// Flag that indicates we should check validity of output XML structure. + final static int CFG_VALIDATE_STRUCTURE = 0x0100; + + /** + * Flag that indicates we should check validity of textual content of + * nodes that have constraints. + *

+ * Specifically: comments can not have '--', CDATA sections can not + * have ']]>' and processing instruction can not have '?<' character + * combinations in content passed in. + */ + final static int CFG_VALIDATE_CONTENT = 0x0200; + + /** + * Flag that indicates we should check validity of names (element and + * attribute names and prefixes; processing instruction names), that they + * contain only legal identifier characters. + */ + final static int CFG_VALIDATE_NAMES = 0x0400; + + /** + * Flag that indicates we should check uniqueness of attribute names, + * to prevent accidental output of duplicate attributes. + */ + final static int CFG_VALIDATE_ATTR = 0x0800; + + /** + * Flag that will enable writer that checks for validity of content + * to try to fix the problem, by splitting output segments as + * necessary. If disabled, validation will throw an exception; and + * without validation no problem is noticed by writer (but instead + * invalid output is created). + */ + final static int CFG_FIX_CONTENT = 0x1000; + + /** + * Property that enables/disables stream write to close the underlying + * output target, either when it is asked to (.close() is called), or + * when it doesn't need it any more (reaching EOF, hitting an + * unrecoverable exception). + * As per Stax 1.0 specification, automatic closing is NOT enabled by + * default; except if the caller has no access to the target (i.e. + * when factory created it) + */ + final static int CFG_AUTO_CLOSE_OUTPUT = 0x2000; + + /** + * Property that indicates if singe quotes or double quotes should be + * used in the XML declaration. + * The default is to use single quotes. + */ + final static int CFG_USE_DOUBLE_QUOTES_IN_XML_DECL = 0x4000; +} diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/cfg/package.html libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/cfg/package.html --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/cfg/package.html 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/cfg/package.html 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,3 @@ + +Package that contains internal configuration settings for Woodstox. + diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/cfg/ParsingErrorMsgs.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/cfg/ParsingErrorMsgs.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/cfg/ParsingErrorMsgs.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/cfg/ParsingErrorMsgs.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,26 @@ +package com.ctc.wstx.cfg; + +public interface ParsingErrorMsgs +{ + // // // EOF problems: + + final static String SUFFIX_IN_ATTR_VALUE = " in attribute value"; + final static String SUFFIX_IN_DEF_ATTR_VALUE = " in attribute default value"; + final static String SUFFIX_IN_CDATA = " in CDATA section"; + final static String SUFFIX_IN_CLOSE_ELEMENT = " in end tag"; + final static String SUFFIX_IN_COMMENT = " in comment"; + final static String SUFFIX_IN_DTD = " in DOCTYPE declaration"; + final static String SUFFIX_IN_DTD_EXTERNAL = " in external DTD subset"; + final static String SUFFIX_IN_DTD_INTERNAL = " in internal DTD subset"; + final static String SUFFIX_IN_DOC = " in main document content"; + final static String SUFFIX_IN_ELEMENT = " in start tag"; + final static String SUFFIX_IN_ENTITY_REF = " in entity reference"; + final static String SUFFIX_IN_EPILOG = " in epilog"; + final static String SUFFIX_IN_NAME = " in name token"; + final static String SUFFIX_IN_PROC_INSTR = " in processing instruction"; + final static String SUFFIX_IN_PROLOG = " in prolog"; + final static String SUFFIX_IN_TEXT = " in document text content"; + final static String SUFFIX_IN_XML_DECL = " in xml declaration"; + + final static String SUFFIX_EOF_EXP_NAME = "; expected an identifier"; +} diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/cfg/XmlConsts.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/cfg/XmlConsts.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/cfg/XmlConsts.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/cfg/XmlConsts.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,66 @@ +package com.ctc.wstx.cfg; + +/** + * Simple constant container interface, shared by input and output + * sides. + */ +public interface XmlConsts +{ + // // // Constants for XML declaration + + public final static String XML_DECL_KW_ENCODING = "encoding"; + public final static String XML_DECL_KW_VERSION = "version"; + public final static String XML_DECL_KW_STANDALONE = "standalone"; + + public final static String XML_V_10_STR = "1.0"; + public final static String XML_V_11_STR = "1.1"; + + /** + * This constants refers to cases where the version has not been + * declared explicitly; and needs to be considered to be 1.0. + */ + public final static int XML_V_UNKNOWN = 0x0000; + + public final static int XML_V_10 = 0x0100; + public final static int XML_V_11 = 0x0110; + + public final static String XML_SA_YES = "yes"; + public final static String XML_SA_NO = "no"; + + // // // Stax specs mandates some settings: but since exact + // // // definitions have been re-interpreted a few times, + // // // let's isolate them in a single place + + /* 13-Mar-2008, TSa: As per latest reading of Stax specs, + * all of these are expected to be "", not null. + */ + + public final static String ELEM_NO_NS_URI = ""; + + public final static String ATTR_NO_NS_URI = ""; + + public final static String ELEM_NO_PREFIX = ""; + + public final static String ATTR_NO_PREFIX = ""; + + /** + * Top-most namespace URI assigned for root element, if not specifically + * defined (default namespace unbound). + *

+ * As per Stax specs, related clarifying discussion on + * the mailing list, and especially JDK 1.6 definitions + * in {@link javax.xml.XMLConstants} constants, empty String + * should be used instead of null. + */ + public final static String DEFAULT_NAMESPACE_URI = ELEM_NO_NS_URI; + + // // // Well, these are not strictly xml constants, but for + // // // now can live here + + /** + * This constant defines the highest Unicode character allowed + * in XML content. + */ + final static int MAX_UNICODE_CHAR = 0x10FFFF; + +} diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/compat/package.html libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/compat/package.html --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/compat/package.html 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/compat/package.html 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,7 @@ + +Package that contains classes that allow abstracting out the details of +JDK platform version being used. Currently classes are used to implement +"graceful degradation" of functionality, when certain JDK classes are only +fully implemented as part of JDKs later than the minimum version +Woodstox needs for running (for Woodstox versions up to 3.x it was JDK 1.2, for 4.x JDK 1.4). + diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/compat/QNameCreator.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/compat/QNameCreator.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/compat/QNameCreator.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/compat/QNameCreator.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,70 @@ +package com.ctc.wstx.compat; + +import java.util.logging.Logger; + +import javax.xml.namespace.QName; + +/** + * Helper class used to solve [WSTX-174]: some older AppServers were + * shipped with incompatible version of QName class, which is missing + * the 3 argument constructor. To address this, we'll use bit of + * ClassLoader hacker to gracefully (?) downgrade to using 2 arg + * alternatives if necessary. + *

+ * Note: choice of java.util.logging logging is only based on the + * fact that it is guaranteed to be present (we have JDK 1.4 baseline + * requirement) so that we do not add external dependencies. + * It is not a recommendation for using JUL per se; most users would + * do well to just use slf4j or log4j directly instead. + * + * @author Tatu Saloranta + * + * @since 3.2.8 + */ +public final class QNameCreator +{ + /** + * Creator object that creates QNames using proper 3-arg constructor. + * If dynamic class loading fails + */ + private final static Helper _helper; + static { + Helper h = null; + try { + // Not sure where it'll fail, constructor or create... + Helper h0 = new Helper(); + /*QName n =*/ h0.create("elem", "http://dummy", "ns"); + h = h0; + } catch (Throwable t) { + String msg = "Could not construct QNameCreator.Helper; assume 3-arg QName constructor not available and use 2-arg method instead. Problem: "+t.getMessage(); + try { + Logger.getLogger("com.ctc.wstx.compat.QNameCreator").warning(msg); + } catch (Throwable t2) { // just in case JUL craps out... + System.err.println("ERROR: failed to log error using Logger (problem "+t.getMessage()+"), original problem: "+msg); + } + } + _helper = h; + } + + public static QName create(String uri, String localName, String prefix) + { + if (_helper == null) { // can't use 3-arg constructor; but 2-arg will be there + return new QName(uri, localName); + } + return _helper.create(uri, localName, prefix); + } + + /** + * Helper class used to encapsulate calls to the missing method. + */ + private final static class Helper + { + public Helper() { } + + public QName create(String localName, String nsURI, String prefix) + { + return new QName(localName, nsURI, prefix); + } + } +} + diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/dom/DOMOutputElement.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/dom/DOMOutputElement.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/dom/DOMOutputElement.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/dom/DOMOutputElement.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,216 @@ +package com.ctc.wstx.dom; + +import javax.xml.namespace.NamespaceContext; + +import org.w3c.dom.Element; +import org.w3c.dom.Node; + +import com.ctc.wstx.sw.OutputElementBase; +import com.ctc.wstx.util.BijectiveNsMap; + +/** + * Context object that holds information about an open element + * (one for which START_ELEMENT has been sent, but no END_ELEMENT) + */ +public final class DOMOutputElement + extends OutputElementBase +{ + /** + * Reference to the parent element, element enclosing this element. + * Null for root element. + * Non-final to allow temporary pooling + * (on per-writer basis, to keep these short-lived). + */ + private DOMOutputElement mParent; + + /** + * DOM node that is the root under which content is written, in case + * where there is no parent (mParent == null). If mParent is not null, + * this will be null. + * Value is of type + * {@link Document}, {@link DocumentFragment} or {@link Element} + */ + private final Node mRootNode; + + /** + * Actual DOM element for which this element object acts as a proxy. + */ + private Element mElement; + + private boolean mDefaultNsSet; + + /** + * Constructor for the virtual root element + */ + private DOMOutputElement(Node rootNode) + { + super(); + mRootNode = rootNode; + mParent = null; + mElement = null; + mNsMapping = null; + mNsMapShared = false; + mDefaultNsURI = ""; + mRootNsContext = null; + mDefaultNsSet = false; + } + + private DOMOutputElement(DOMOutputElement parent, Element element, BijectiveNsMap ns) + { + super(parent, ns); + mRootNode = null; + mParent = parent; + mElement = element; + mNsMapping = ns; + mNsMapShared = (ns != null); + mDefaultNsURI = parent.mDefaultNsURI; + mRootNsContext = parent.mRootNsContext; + mDefaultNsSet = false; + } + + /** + * Method called to reuse a pooled instance. + * + * @returns Chained pooled instance that should now be head of the + * reuse chain + */ + private void relink(DOMOutputElement parent, Element element) + { + super.relink(parent); + mParent = parent; + mElement = element; + parent.appendNode(element); + mDefaultNsSet = false; + } + + public static DOMOutputElement createRoot(Node rootNode) + { + return new DOMOutputElement(rootNode); + } + + /** + * Simplest factory method, which gets called when a 1-argument + * element output method is called. It is, then, assumed to + * use the default namespace. + * Will both create the child element and attach it to parent element, + * or lacking own owner document. + */ + protected DOMOutputElement createAndAttachChild(Element element) + { + if (mRootNode != null) { + mRootNode.appendChild(element); + } else { + mElement.appendChild(element); + } + return createChild(element); + } + + protected DOMOutputElement createChild(Element element) + { + return new DOMOutputElement(this, element, mNsMapping); + } + + /** + * @return New head of the recycle pool + */ + protected DOMOutputElement reuseAsChild(DOMOutputElement parent, Element element) + { + DOMOutputElement poolHead = mParent; + relink(parent, element); + return poolHead; + } + + /** + * Method called to temporarily link this instance to a pool, to + * allow reusing of instances with the same reader. + */ + protected void addToPool(DOMOutputElement poolHead) + { + mParent = poolHead; + } + + /* + /////////////////////////////////////////////////////////////////////// + // Public API, accessors + /////////////////////////////////////////////////////////////////////// + */ + + public DOMOutputElement getParent() { + return mParent; + } + + @Override + public boolean isRoot() { + // (Virtual) Root element has no parent... + return (mParent == null); + } + + /** + * @return String presentation of the fully-qualified name, in + * "prefix:localName" format (no URI). Useful for error and + * debugging messages. + */ + @Override + public String getNameDesc() { + if(mElement != null) { + return mElement.getLocalName(); + } + return "#error"; // unexpected case + } + + /* + /////////////////////////////////////////////////////////////////////// + // Public API, mutators + /////////////////////////////////////////////////////////////////////// + */ + + @Override + public void setDefaultNsUri(String uri) { + mDefaultNsURI = uri; + mDefaultNsSet = true; + } + + @Override + protected void setRootNsContext(NamespaceContext ctxt) + { + mRootNsContext = ctxt; + /* Let's also see if we have an active default ns mapping: + * (provided it hasn't yet explicitly been set for this element) + */ + if (!mDefaultNsSet) { + String defURI = ctxt.getNamespaceURI(""); + if (defURI != null && defURI.length() > 0) { + mDefaultNsURI = defURI; + } + } + } + + /* + /////////////////////////////////////////////////////////////////////// + // Public API, DOM manipulation + /////////////////////////////////////////////////////////////////////// + */ + + protected void appendNode(Node n) + { + if (mRootNode != null) { + mRootNode.appendChild(n); + } else { + mElement.appendChild(n); + } + } + + protected void addAttribute(String pname, String value) + { + mElement.setAttribute(pname, value); + } + + protected void addAttribute(String uri, String qname, String value) + { + mElement.setAttributeNS(uri, qname, value); + } + + public void appendChild(Node n) { + mElement.appendChild(n); + } +} diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/dom/WstxDOMWrappingReader.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/dom/WstxDOMWrappingReader.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/dom/WstxDOMWrappingReader.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/dom/WstxDOMWrappingReader.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,92 @@ +package com.ctc.wstx.dom; + +import java.util.Collections; + +import javax.xml.stream.*; +import javax.xml.transform.dom.DOMSource; + +import org.codehaus.stax2.ri.dom.DOMWrappingReader; + +import com.ctc.wstx.api.ReaderConfig; +import com.ctc.wstx.exc.WstxParsingException; + +public class WstxDOMWrappingReader + extends DOMWrappingReader +{ + protected final ReaderConfig mConfig; + + /* + /////////////////////////////////////////////////// + // Life-cycle + /////////////////////////////////////////////////// + */ + + protected WstxDOMWrappingReader(DOMSource src, ReaderConfig cfg) + throws XMLStreamException + { + super(src, cfg.willSupportNamespaces(), cfg.willCoalesceText()); + mConfig = cfg; + // [WSTX-162]: allow enabling/disabling name/ns intern()ing + if (cfg.hasInternNamesBeenEnabled()) { + setInternNames(true); + } + if (cfg.hasInternNsURIsBeenEnabled()) { + setInternNsURIs(true); + } + } + + public static WstxDOMWrappingReader createFrom(DOMSource src, ReaderConfig cfg) + throws XMLStreamException + { + return new WstxDOMWrappingReader(src, cfg); + } + + /* + /////////////////////////////////////////////////// + // Defined/Overridden config methods + /////////////////////////////////////////////////// + */ + + @Override + public boolean isPropertySupported(String name) { + // !!! TBI: not all these properties are really supported + return mConfig.isPropertySupported(name); + } + + @Override + public Object getProperty(String name) + { + if (name.equals("javax.xml.stream.entities")) { + // !!! TBI + return Collections.EMPTY_LIST; + } + if (name.equals("javax.xml.stream.notations")) { + // !!! TBI + return Collections.EMPTY_LIST; + } + return mConfig.getProperty(name); + } + + @Override + public boolean setProperty(String name, Object value) + { + // Basic config accessor works just fine... + return mConfig.setProperty(name, value); + } + + /* + /////////////////////////////////////////////////// + // Defined/Overridden error reporting + /////////////////////////////////////////////////// + */ + + @Override + protected void throwStreamException(String msg, Location loc) + throws XMLStreamException + { + if (loc == null) { + throw new WstxParsingException(msg); + } + throw new WstxParsingException(msg, loc); + } +} diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/dom/WstxDOMWrappingWriter.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/dom/WstxDOMWrappingWriter.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/dom/WstxDOMWrappingWriter.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/dom/WstxDOMWrappingWriter.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,761 @@ +package com.ctc.wstx.dom; + +import java.util.*; + +import javax.xml.XMLConstants; +import javax.xml.namespace.*; +import javax.xml.stream.*; +import javax.xml.transform.dom.DOMResult; + +import org.w3c.dom.*; + +import org.codehaus.stax2.ri.EmptyNamespaceContext; +import org.codehaus.stax2.ri.dom.DOMWrappingWriter; + +import com.ctc.wstx.api.WriterConfig; +import com.ctc.wstx.cfg.ErrorConsts; +import com.ctc.wstx.sw.OutputElementBase; + +/* TODO: + * + * - validator interface implementation + */ + +/** + * This is an adapter class that allows building a DOM tree using + * {@link XMLStreamWriter} interface. + *

+ * Note that the implementation is only to be used for use with + * javax.xml.transform.dom.DOMResult. + *

+ * Some notes regarding missing/incomplete functionality: + *

    + *
  • Validation functionality not implemented + *
  • + *
+ * + * @author Tatu Saloranta + * @author Dan Diephouse + */ +public class WstxDOMWrappingWriter + extends DOMWrappingWriter +{ + /* + /////////////////////////////////////////////////////////// + // Constants + /////////////////////////////////////////////////////////// + */ + + final protected static String ERR_NSDECL_WRONG_STATE = + "Trying to write a namespace declaration when there is no open start element."; + + /* + /////////////////////////////////////////////////////////// + // Configuration + /////////////////////////////////////////////////////////// + */ + + protected final WriterConfig mConfig; + + /* + /////////////////////////////////////////////////////////// + // State + /////////////////////////////////////////////////////////// + */ + + /** + * This element is the current context element, under which + * all other nodes are added, until matching end element + * is output. Null outside of the main element tree. + *

+ * Note: explicit empty element (written using + * writeEmptyElement) will never become + * current element. + */ + protected DOMOutputElement mCurrElem; + + /** + * This element is non-null right after a call to + * either writeStartElement and + * writeEmptyElement, and can be used to + * add attributes and namespace declarations. + *

+ * Note: while this is often the same as {@link #mCurrElem}, + * it's not always. Specifically, an empty element (written + * explicitly using writeEmptyElement) will + * become open element but NOT current element. Conversely, + * regular elements will remain current element when + * non elements are written (text, comments, PI), but + * not the open element. + */ + protected DOMOutputElement mOpenElement; + + /** + * for NsRepairing mode + */ + protected int[] mAutoNsSeq; + protected String mSuggestedDefNs = null; + protected String mAutomaticNsPrefix; + + /** + * Map that contains URI-to-prefix entries that point out suggested + * prefixes for URIs. These are populated by calls to + * {@link #setPrefix}, and they are only used as hints for binding; + * if there are conflicts, repairing writer can just use some other + * prefix. + */ + HashMap mSuggestedPrefixes = null; + + /* + /////////////////////////////////////////////////////////// + // Life-cycle + /////////////////////////////////////////////////////////// + */ + + private WstxDOMWrappingWriter(WriterConfig cfg, Node treeRoot) + throws XMLStreamException + { + super(treeRoot, cfg.willSupportNamespaces(), cfg.automaticNamespacesEnabled()); + mConfig = cfg; + mAutoNsSeq = null; + mAutomaticNsPrefix = mNsRepairing ? mConfig.getAutomaticNsPrefix() : null; + + /* Ok; we need a document node; or an element node; or a document + * fragment node. + */ + switch (treeRoot.getNodeType()) { + case Node.DOCUMENT_NODE: + case Node.DOCUMENT_FRAGMENT_NODE: + // both are ok, but no current element + mCurrElem = DOMOutputElement.createRoot(treeRoot); + mOpenElement = null; + break; + + case Node.ELEMENT_NODE: // can make sub-tree... ok + { + // still need a virtual root node as parent + DOMOutputElement root = DOMOutputElement.createRoot(treeRoot); + Element elem = (Element) treeRoot; + mOpenElement = mCurrElem = root.createChild(elem); + } + break; + + default: // other Nodes not usable + throw new XMLStreamException("Can not create an XMLStreamWriter for a DOM node of type "+treeRoot.getClass()); + } + } + + public static WstxDOMWrappingWriter createFrom(WriterConfig cfg, DOMResult dst) + throws XMLStreamException + { + Node rootNode = dst.getNode(); + return new WstxDOMWrappingWriter(cfg, rootNode); + } + + /* + /////////////////////////////////////////////////////////// + // XMLStreamWriter API (Stax 1.0) + /////////////////////////////////////////////////////////// + */ + + //public void close() { } + //public void flush() { } + + @Override + public NamespaceContext getNamespaceContext() + { + if (!mNsAware) { + return EmptyNamespaceContext.getInstance(); + } + return mCurrElem; + } + + @Override + public String getPrefix(String uri) + { + if (!mNsAware) { + return null; + } + if (mNsContext != null) { + String prefix = mNsContext.getPrefix(uri); + if (prefix != null) { + return prefix; + } + } + return mCurrElem.getPrefix(uri); + } + + @Override + public Object getProperty(String name) { + return mConfig.getProperty(name); + } + + @Override + public void setDefaultNamespace(String uri) { + mSuggestedDefNs = (uri == null || uri.length() == 0) ? null : uri; + } + + //public void setNamespaceContext(NamespaceContext context) + + @Override + public void setPrefix(String prefix, String uri) + throws XMLStreamException + { + if (prefix == null) { + throw new NullPointerException("Can not pass null 'prefix' value"); + } + // Are we actually trying to set the default namespace? + if (prefix.length() == 0) { + setDefaultNamespace(uri); + return; + } + if (uri == null) { + throw new NullPointerException("Can not pass null 'uri' value"); + } + + /* Let's verify that xml/xmlns are never (mis)declared; as + * mandated by XML NS specification + */ + { + if (prefix.equals("xml")) { + if (!uri.equals(XMLConstants.XML_NS_URI)) { + throwOutputError(ErrorConsts.ERR_NS_REDECL_XML, uri); + } + } else if (prefix.equals("xmlns")) { // prefix "xmlns" + if (!uri.equals(XMLConstants.XMLNS_ATTRIBUTE_NS_URI)) { + throwOutputError(ErrorConsts.ERR_NS_REDECL_XMLNS, uri); + } + // At any rate; we are NOT to output it + return; + } else { + // Neither of prefixes.. but how about URIs? + if (uri.equals(XMLConstants.XML_NS_URI)) { + throwOutputError(ErrorConsts.ERR_NS_REDECL_XML_URI, prefix); + } else if (uri.equals(XMLConstants.XMLNS_ATTRIBUTE_NS_URI)) { + throwOutputError(ErrorConsts.ERR_NS_REDECL_XMLNS_URI, prefix); + } + } + } + + if (mSuggestedPrefixes == null) { + mSuggestedPrefixes = new HashMap(16); + } + mSuggestedPrefixes.put(uri, prefix); + + } + + @Override + public void writeAttribute(String localName, String value) + throws XMLStreamException + { + outputAttribute(null, null, localName, value); + } + + @Override + public void writeAttribute(String nsURI, String localName, String value) + throws XMLStreamException + { + outputAttribute(nsURI, null, localName, value); + } + + @Override + public void writeAttribute(String prefix, String nsURI, String localName, String value) + throws XMLStreamException + { + outputAttribute(nsURI, prefix, localName, value); + } + + //public void writeCData(String data) + //public void writeCharacters(char[] text, int start, int len) + //public void writeCharacters(String text) + //public void writeComment(String data) + + @Override + public void writeDefaultNamespace(String nsURI) + { + if (mOpenElement == null) { + throw new IllegalStateException("No currently open START_ELEMENT, cannot write attribute"); + } + setDefaultNamespace(nsURI); + mOpenElement.addAttribute(XMLConstants.XMLNS_ATTRIBUTE_NS_URI, "xmlns", nsURI); + } + + //public void writeDTD(String dtd) + + @Override + public void writeEmptyElement(String localName) + throws XMLStreamException + { + writeEmptyElement(null, localName); + } + + @Override + public void writeEmptyElement(String nsURI, String localName) + throws XMLStreamException + { + // First things first: must + + /* Note: can not just call writeStartElement(), since this + * element will only become the open elem, but not a parent elem + */ + createStartElem(nsURI, null, localName, true); + } + + @Override + public void writeEmptyElement(String prefix, String localName, String nsURI) + throws XMLStreamException + { + if (prefix == null) { // passing null would mean "dont care", if repairing + prefix = ""; + } + createStartElem(nsURI, prefix, localName, true); + } + + @Override + public void writeEndDocument() + { + mCurrElem = mOpenElement = null; + } + + @Override + public void writeEndElement() + { + // Simple, just need to traverse up... if we can + if (mCurrElem == null || mCurrElem.isRoot()) { + throw new IllegalStateException("No open start element to close"); + } + mOpenElement = null; // just in case it was open + mCurrElem = mCurrElem.getParent(); + } + + //public void writeEntityRef(String name) + + @Override + public void writeNamespace(String prefix, String nsURI) throws XMLStreamException + { + if (prefix == null || prefix.length() == 0) { + writeDefaultNamespace(nsURI); + return; + } + if (!mNsAware) { + throwOutputError("Can not write namespaces with non-namespace writer."); + } + outputAttribute(XMLConstants.XMLNS_ATTRIBUTE_NS_URI, "xmlns", prefix, nsURI); + mCurrElem.addPrefix(prefix, nsURI); + } + + //public void writeProcessingInstruction(String target) + //public void writeProcessingInstruction(String target, String data) + + //public void writeStartDocument() + //public void writeStartDocument(String version) + //public void writeStartDocument(String encoding, String version) + + @Override + public void writeStartElement(String localName) + throws XMLStreamException + { + writeStartElement(null, localName); + } + + @Override + public void writeStartElement(String nsURI, String localName) + throws XMLStreamException + { + createStartElem(nsURI, null, localName, false); + } + + @Override + public void writeStartElement(String prefix, String localName, String nsURI) + throws XMLStreamException + { + createStartElem(nsURI, prefix, localName, false); + } + + /* + /////////////////////////////////////////////////////////// + // XMLStreamWriter2 API (Stax2 v3.0): + // additional accessors + /////////////////////////////////////////////////////////// + */ + + //public XMLStreamLocation2 getLocation() + //public String getEncoding() + + @Override + public boolean isPropertySupported(String name) + { + // !!! TBI: not all these properties are really supported + return mConfig.isPropertySupported(name); + } + + @Override + public boolean setProperty(String name, Object value) + { + /* Note: can not call local method, since it'll return false for + * recognized but non-mutable properties + */ + return mConfig.setProperty(name, value); + } + + /* + /////////////////////////////////////////////////////////// + // XMLStreamWriter2 API (Stax2 v2.0): + // extended write methods + /////////////////////////////////////////////////////////// + */ + + //public void writeCData(char[] text, int start, int len) + + @Override + public void writeDTD(String rootName, String systemId, String publicId, + String internalSubset) + throws XMLStreamException + { + /* Alas: although we can create a DocumentType object, there + * doesn't seem to be a way to attach it in DOM-2! + */ + if (mCurrElem != null) { + throw new IllegalStateException("Operation only allowed to the document before adding root element"); + } + reportUnsupported("writeDTD()"); + } + + //public void writeFullEndElement() throws XMLStreamException + + //public void writeSpace(char[] text, int start, int len) + //public void writeSpace(String text) + + + //public void writeStartDocument(String version, String encoding, boolean standAlone) + + /* + /////////////////////////////////////////////////////////// + // XMLStreamWriter2 API (Stax2 v2.0): validation + /////////////////////////////////////////////////////////// + */ + + //public XMLValidator validateAgainst(XMLValidationSchema schema) + //public XMLValidator stopValidatingAgainst(XMLValidationSchema schema) + //public XMLValidator stopValidatingAgainst(XMLValidator validator) + //public ValidationProblemHandler setValidationProblemHandler(ValidationProblemHandler h) + + /* + /////////////////////////////////////////////////////////// + // Impls of abstract methods from base class + /////////////////////////////////////////////////////////// + */ + + @Override + protected void appendLeaf(Node n) + throws IllegalStateException + { + mCurrElem.appendNode(n); + mOpenElement = null; + } + + /* + /////////////////////////////////////////////////////////// + // Internal methods + /////////////////////////////////////////////////////////// + */ + + /* Note: copied from regular RepairingNsStreamWriter#writeStartOrEmpty + * (and its non-repairing counterpart). + */ + + /** + * Method called by all start element write methods. + * + * @param nsURI Namespace URI to use: null and empty String denote 'no namespace' + */ + protected void createStartElem(String nsURI, String prefix, String localName, boolean isEmpty) + throws XMLStreamException + { + DOMOutputElement elem; + + if (!mNsAware) { + if(nsURI != null && nsURI.length() > 0) { + throwOutputError("Can not specify non-empty uri/prefix in non-namespace mode"); + } + elem = mCurrElem.createAndAttachChild(mDocument.createElement(localName)); + } else { + if (mNsRepairing) { + String actPrefix = validateElemPrefix(prefix, nsURI, mCurrElem); + if (actPrefix != null) { // fine, an existing binding we can use: + if (actPrefix.length() != 0) { + elem = mCurrElem.createAndAttachChild(mDocument.createElementNS(nsURI, actPrefix+":"+localName)); + } else { + elem = mCurrElem.createAndAttachChild(mDocument.createElementNS(nsURI, localName)); + } + } else { // nah, need to create a new binding... + /* Need to ensure that we'll pass "" as prefix, not null, + * so it is understood as "I want to use the default NS", + * not as "whatever prefix, I don't care" + */ + if (prefix == null) { + prefix = ""; + } + actPrefix = generateElemPrefix(prefix, nsURI, mCurrElem); + boolean hasPrefix = (actPrefix.length() != 0); + if (hasPrefix) { + localName = actPrefix + ":" + localName; + } + elem = mCurrElem.createAndAttachChild(mDocument.createElementNS(nsURI, localName)); + /* Hmmh. writeNamespace method requires open element + * to be defined. So we'll need to set it first + * (will be set again at a later point -- would be + * good to refactor this method into separate + * sub-classes or so) + */ + mOpenElement = elem; + // Need to add new ns declaration as well + if (hasPrefix) { + writeNamespace(actPrefix, nsURI); + elem.addPrefix(actPrefix, nsURI); + } else { + writeDefaultNamespace(nsURI); + elem.setDefaultNsUri(nsURI); + } + } + } else { + /* Non-repairing; if non-null prefix (including "" to + * indicate "no prefix") passed, use as is, otherwise + * try to locate the prefix if got namespace. + */ + if (prefix == null && nsURI != null && nsURI.length() > 0) { + prefix = (mSuggestedPrefixes == null) ? null : mSuggestedPrefixes.get(nsURI); + if (prefix == null) { + throwOutputError("Can not find prefix for namespace \""+nsURI+"\""); + } + } + if (prefix != null && prefix.length() != 0) { + localName = prefix + ":" +localName; + } + elem = mCurrElem.createAndAttachChild(mDocument.createElementNS(nsURI, localName)); + } + } + /* Got the element; need to make it the open element, and + * if it's not an (explicit) empty element, current element as well + */ + mOpenElement = elem; + if (!isEmpty) { + mCurrElem = elem; + } + } + + protected void outputAttribute(String nsURI, String prefix, String localName, String value) + throws XMLStreamException + { + if (mOpenElement == null) { + throw new IllegalStateException("No currently open START_ELEMENT, cannot write attribute"); + } + + if (mNsAware) { + if (mNsRepairing) { + prefix = findOrCreateAttrPrefix(prefix, nsURI, mOpenElement); + } + if (prefix != null && prefix.length() > 0) { + localName = prefix + ":" + localName; + } + mOpenElement.addAttribute(nsURI, localName, value); + } else { // non-ns, simple + if (prefix != null && prefix.length() > 0) { + localName = prefix + ":" + localName; + } + mOpenElement.addAttribute(localName, value); + } + } + + private final String validateElemPrefix(String prefix, String nsURI, + DOMOutputElement elem) + throws XMLStreamException + { + /* 06-Feb-2005, TSa: Special care needs to be taken for the + * "empty" (or missing) namespace: + * (see comments from findOrCreatePrefix()) + */ + if (nsURI == null || nsURI.length() == 0) { + String currURL = elem.getDefaultNsUri(); + if (currURL == null || currURL.length() == 0) { + // Ok, good: + return ""; + } + // Nope, needs to be re-bound: + return null; + } + + int status = elem.isPrefixValid(prefix, nsURI, true); + if (status == DOMOutputElement.PREFIX_OK) { + return prefix; + } + return null; + } + + /* + /////////////////////////////////////////////////////////// + // Internal methods + /////////////////////////////////////////////////////////// + */ + + /** + * Method called to find an existing prefix for the given namespace, + * if any exists in the scope. If one is found, it's returned (including + * "" for the current default namespace); if not, null is returned. + * + * @param nsURI URI of namespace for which we need a prefix + */ + protected final String findElemPrefix(String nsURI, DOMOutputElement elem) + throws XMLStreamException + { + /* Special case: empty NS URI can only be bound to the empty + * prefix... + */ + if (nsURI == null || nsURI.length() == 0) { + String currDefNsURI = elem.getDefaultNsUri(); + if (currDefNsURI != null && currDefNsURI.length() > 0) { + // Nope; won't do... has to be re-bound, but not here: + return null; + } + return ""; + } + return mCurrElem.getPrefix(nsURI); + } + + + /** + * Method called after {@link #findElemPrefix} has returned null, + * to create and bind a namespace mapping for specified namespace. + */ + protected final String generateElemPrefix(String suggPrefix, String nsURI, + DOMOutputElement elem) + throws XMLStreamException + { + /* Ok... now, since we do not have an existing mapping, let's + * see if we have a preferred prefix to use. + */ + /* Except if we need the empty namespace... that can only be + * bound to the empty prefix: + */ + if (nsURI == null || nsURI.length() == 0) { + return ""; + } + + /* Ok; with elements this is easy: the preferred prefix can + * ALWAYS be used, since it can mask preceding bindings: + */ + if (suggPrefix == null) { + // caller wants this URI to map as the default namespace? + if (mSuggestedDefNs != null && mSuggestedDefNs.equals(nsURI)) { + suggPrefix = ""; + } else { + suggPrefix = (mSuggestedPrefixes == null) ? null: mSuggestedPrefixes.get(nsURI); + if (suggPrefix == null) { + /* 16-Oct-2005, TSa: We have 2 choices here, essentially; + * could make elements always try to override the def + * ns... or can just generate new one. Let's do latter + * for now. + */ + if (mAutoNsSeq == null) { + mAutoNsSeq = new int[1]; + mAutoNsSeq[0] = 1; + } + suggPrefix = elem.generateMapping(mAutomaticNsPrefix, nsURI, + mAutoNsSeq); + } + } + } + + // Ok; let's let the caller deal with bindings + return suggPrefix; + } + + + /** + * Method called to somehow find a prefix for given namespace, to be + * used for a new start element; either use an existing one, or + * generate a new one. If a new mapping needs to be generated, + * it will also be automatically bound, and necessary namespace + * declaration output. + * + * @param suggPrefix Suggested prefix to bind, if any; may be null + * to indicate "no preference" + * @param nsURI URI of namespace for which we need a prefix + * @param elem Currently open start element, on which the attribute + * will be added. + */ + protected final String findOrCreateAttrPrefix(String suggPrefix, String nsURI, + DOMOutputElement elem) + throws XMLStreamException + { + if (nsURI == null || nsURI.length() == 0) { + /* Attributes never use the default namespace; missing + * prefix always leads to the empty ns... so nothing + * special is needed here. + */ + return null; + } + // Maybe the suggested prefix is properly bound? + if (suggPrefix != null) { + int status = elem.isPrefixValid(suggPrefix, nsURI, false); + if (status == OutputElementBase.PREFIX_OK) { + return suggPrefix; + } + /* Otherwise, if the prefix is unbound, let's just bind + * it -- if caller specified a prefix, it probably prefers + * binding that prefix even if another prefix already existed? + * The remaining case (already bound to another URI) we don't + * want to touch, at least not yet: it may or not be safe + * to change binding, so let's just not try it. + */ + if (status == OutputElementBase.PREFIX_UNBOUND) { + elem.addPrefix(suggPrefix, nsURI); + writeNamespace(suggPrefix, nsURI); + return suggPrefix; + } + } + + // If not, perhaps there's another existing binding available? + String prefix = elem.getExplicitPrefix(nsURI); + if (prefix != null) { // already had a mapping for the URI... cool. + return prefix; + } + + /* Nope, need to create one. First, let's see if there's a + * preference... + */ + if (suggPrefix != null) { + prefix = suggPrefix; + } else if (mSuggestedPrefixes != null) { + prefix = mSuggestedPrefixes.get(nsURI); + // note: def ns is never added to suggested prefix map + } + + if (prefix != null) { + /* Can not use default namespace for attributes. + * Also, re-binding is tricky for attributes; can't + * re-bind anything that's bound on this scope... or + * used in this scope. So, to simplify life, let's not + * re-bind anything for attributes. + */ + if (prefix.length() == 0 + || (elem.getNamespaceURI(prefix) != null)) { + prefix = null; + } + } + + if (prefix == null) { + if (mAutoNsSeq == null) { + mAutoNsSeq = new int[1]; + mAutoNsSeq[0] = 1; + } + prefix = mCurrElem.generateMapping(mAutomaticNsPrefix, nsURI, + mAutoNsSeq); + } + + // Ok; so far so good: let's now bind and output the namespace: + elem.addPrefix(prefix, nsURI); + writeNamespace(prefix, nsURI); + return prefix; + } +} diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/dtd/ChoiceContentSpec.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/dtd/ChoiceContentSpec.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/dtd/ChoiceContentSpec.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/dtd/ChoiceContentSpec.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,246 @@ +package com.ctc.wstx.dtd; + +import java.util.*; + +import com.ctc.wstx.util.ExceptionUtil; +import com.ctc.wstx.util.PrefixedName; + +/** + * Content specification that defines content model that has + * multiple alternative elements; including mixed content model. + */ +public class ChoiceContentSpec + extends ContentSpec +{ + final boolean mNsAware; + + /** + * Whether this is a mixed content model; mostly affects String + * representation + */ + final boolean mHasMixed; + + final ContentSpec[] mContentSpecs; + + /* + /////////////////////////////////////////////////// + // Life-cycle + /////////////////////////////////////////////////// + */ + + private ChoiceContentSpec(boolean nsAware, char arity, boolean mixed, + ContentSpec[] specs) + { + super(arity); + mNsAware = nsAware; + mHasMixed = mixed; + mContentSpecs = specs; + } + + private ChoiceContentSpec(boolean nsAware, char arity, boolean mixed, Collection specs) + { + super(arity); + mNsAware = nsAware; + mHasMixed = mixed; + mContentSpecs = new ContentSpec[specs.size()]; + specs.toArray(mContentSpecs); + } + + public static ChoiceContentSpec constructChoice(boolean nsAware, char arity, + Collection specs) + { + return new ChoiceContentSpec(nsAware, arity, false, specs); + } + + public static ChoiceContentSpec constructMixed(boolean nsAware, Collection specs) + { + return new ChoiceContentSpec(nsAware, '*', true, specs); + } + + /* + /////////////////////////////////////////////////// + // Public API + /////////////////////////////////////////////////// + */ + + @Override + public StructValidator getSimpleValidator() + { + /* Can we create a simple validator? Yes, if the sub-specs are + * all simple (leaves == element tokens with no arity modifier); + * this is always true for mixed. + */ + ContentSpec[] specs = mContentSpecs; + int len = specs.length; + int i; + + if (mHasMixed) { + i = len; + } else { + i = 0; + for (; i < len; ++i) { + if (!specs[i].isLeaf()) { + break; + } + } + } + + if (i == len) { // all leaves, kewl + PrefixedNameSet keyset = namesetFromSpecs(mNsAware, specs); + return new Validator(mArity, keyset); + } + + // Nah, need a DFA... + return null; + } + + @Override + public ModelNode rewrite() + { + // First, need to convert sub-specs: + ContentSpec[] specs = mContentSpecs; + int len = specs.length; + ModelNode[] models = new ModelNode[len]; + for (int i = 0; i < len; ++i) { + models[i] = specs[i].rewrite(); + } + ChoiceModel model = new ChoiceModel(models); + + // and then resolve arity modifiers, if necessary: + if (mArity == '*') { + return new StarModel(model); + } + if (mArity == '?') { + return new OptionalModel(model); + } + if (mArity == '+') { + return new ConcatModel(model, + new StarModel(model.cloneModel())); + } + return model; + } + + @Override + public String toString() + { + StringBuilder sb = new StringBuilder(); + + if (mHasMixed) { + sb.append("(#PCDATA | "); + } else { + sb.append('('); + } + for (int i = 0; i < mContentSpecs.length; ++i) { + if (i > 0) { + sb.append(" | "); + } + sb.append(mContentSpecs[i].toString()); + } + sb.append(')'); + + if (mArity != ' ') { + sb.append(mArity); + } + return sb.toString(); + } + + /* + /////////////////////////////////////////////////// + // Internal methods + /////////////////////////////////////////////////// + */ + + /* + /////////////////////////////////////////////////// + // Package methods + /////////////////////////////////////////////////// + */ + + protected static PrefixedNameSet namesetFromSpecs(boolean nsAware, ContentSpec[] specs) + { + int len = specs.length; + PrefixedName[] nameArray = new PrefixedName[len]; + for (int i = 0; i < len; ++i) { + nameArray[i] = ((TokenContentSpec)specs[i]).getName(); + } + + if (len < 5) { // 4 or fewer elements -> small + return new SmallPrefixedNameSet(nsAware, nameArray); + } + return new LargePrefixedNameSet(nsAware, nameArray); + } + + /* + /////////////////////////////////////////////////// + // Validator class that can be used for simple + // choices (including mixed content) + /////////////////////////////////////////////////// + */ + + final static class Validator + extends StructValidator + { + final char mArity; + final PrefixedNameSet mNames; + + int mCount = 0; + + public Validator(char arity, PrefixedNameSet names) + { + mArity = arity; + mNames = names; + } + + /** + * Rules for reuse are simple: if we can have any number of + * repetitions, we can just use a shared root instance. Although + * its count variable will get updated this doesn't really + * matter as it won't be used. Otherwise a new instance has to + * be created always, to keep track of instance counts. + */ + @Override + public StructValidator newInstance() { + return (mArity == '*') ? this : new Validator(mArity, mNames); + } + + @Override + public String tryToValidate(PrefixedName elemName) + { + if (!mNames.contains(elemName)) { + if (mNames.hasMultiple()) { + return "Expected one of ("+mNames.toString(" | ")+")"; + } + return "Expected <"+mNames.toString("")+">"; + } + if (++mCount > 1 && (mArity == '?' || mArity == ' ')) { + if (mNames.hasMultiple()) { + return "Expected $END (already had one of [" + +mNames.toString(" | ")+"]"; + } + return "Expected $END (already had one <" + +mNames.toString("")+">]"; + } + return null; + } + + @Override + public String fullyValid() + { + switch (mArity) { + case '*': + case '?': + return null; + case '+': // need at least one (and multiples checked earlier) + case ' ': + if (mCount > 0) { + return null; + } + return "Expected "+(mArity == '+' ? "at least" : "") + +" one of elements ("+mNames+")"; + } + // should never happen: + ExceptionUtil.throwGenericInternal(); + return null; + } + } +} diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/dtd/ChoiceModel.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/dtd/ChoiceModel.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/dtd/ChoiceModel.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/dtd/ChoiceModel.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,117 @@ +package com.ctc.wstx.dtd; + +import java.util.*; + +/** + * Model class that encapsulates set of sub-models, of which one (and only + * one) needs to be matched. + */ +public class ChoiceModel + extends ModelNode +{ + final ModelNode[] mSubModels; + + boolean mNullable = false; + + BitSet mFirstPos, mLastPos; + + /* + /////////////////////////////////////////////////// + // Life-cycle + /////////////////////////////////////////////////// + */ + + protected ChoiceModel(ModelNode[] subModels) + { + super(); + mSubModels = subModels; + boolean nullable = false; + for (int i = 0, len = subModels.length; i < len; ++i) { + if (subModels[i].isNullable()) { + nullable = true; + break; + } + } + mNullable = nullable; + } + + /* + /////////////////////////////////////////////////// + // Public API + /////////////////////////////////////////////////// + */ + + @Override + public String toString() + { + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < mSubModels.length; ++i) { + if (i > 0) { + sb.append(" | "); + } + sb.append(mSubModels[i].toString()); + } + sb.append(')'); + return sb.toString(); + } + + /** + * Method that has to create a deep copy of the model, without + * sharing any of existing Objects. + */ + @Override + public ModelNode cloneModel() + { + int len = mSubModels.length; + ModelNode[] newModels = new ModelNode[len]; + for (int i = 0; i < len; ++i) { + newModels[i] = mSubModels[i].cloneModel(); + } + return new ChoiceModel(newModels); + } + + @Override + public boolean isNullable() { + return mNullable; + } + + @Override + public void indexTokens(List tokens) + { + // First, let's ask sub-models to calc their settings + for (int i = 0, len = mSubModels.length; i < len; ++i) { + mSubModels[i].indexTokens(tokens); + } + } + + @Override + public void addFirstPos(BitSet firstPos) { + if (mFirstPos == null) { + mFirstPos = new BitSet(); + for (int i = 0, len = mSubModels.length; i < len; ++i) { + mSubModels[i].addFirstPos(mFirstPos); + } + } + firstPos.or(mFirstPos); + } + + @Override + public void addLastPos(BitSet lastPos) { + if (mLastPos == null) { + mLastPos = new BitSet(); + for (int i = 0, len = mSubModels.length; i < len; ++i) { + mSubModels[i].addLastPos(mLastPos); + } + } + lastPos.or(mLastPos); + } + + @Override + public void calcFollowPos(BitSet[] followPosSets) + { + // need to let child models do their stuff: + for (int i = 0, len = mSubModels.length; i < len; ++i) { + mSubModels[i].calcFollowPos(followPosSets); + } + } +} diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/dtd/ConcatModel.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/dtd/ConcatModel.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/dtd/ConcatModel.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/dtd/ConcatModel.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,119 @@ +package com.ctc.wstx.dtd; + +import java.util.*; + +/** + * Model class that represents sequence of 2 sub-models, needed to be + * matched in the order. + */ +public class ConcatModel + extends ModelNode +{ + ModelNode mLeftModel; + ModelNode mRightModel; + + final boolean mNullable; + + BitSet mFirstPos, mLastPos; + + /* + /////////////////////////////////////////////////// + // Life-cycle + /////////////////////////////////////////////////// + */ + + public ConcatModel(ModelNode left, ModelNode right) + { + super(); + mLeftModel = left; + mRightModel = right; + mNullable = mLeftModel.isNullable() && mRightModel.isNullable(); + } + + /* + /////////////////////////////////////////////////// + // Public API + /////////////////////////////////////////////////// + */ + + /** + * Method that has to create a deep copy of the model, without + * sharing any of existing Objects. + */ + @Override + public ModelNode cloneModel() { + return new ConcatModel(mLeftModel.cloneModel(), mRightModel.cloneModel()); + } + + @Override + public boolean isNullable() { + return mNullable; + } + + @Override + public void indexTokens(List tokens) + { + mLeftModel.indexTokens(tokens); + mRightModel.indexTokens(tokens); + } + + @Override + public void addFirstPos(BitSet pos) { + if (mFirstPos == null) { + mFirstPos = new BitSet(); + mLeftModel.addFirstPos(mFirstPos); + if (mLeftModel.isNullable()) { + mRightModel.addFirstPos(mFirstPos); + } + } + pos.or(mFirstPos); + } + + @Override + public void addLastPos(BitSet pos) { + if (mLastPos == null) { + mLastPos = new BitSet(); + mRightModel.addLastPos(mLastPos); + if (mRightModel.isNullable()) { + mLeftModel.addLastPos(mLastPos); + } + } + pos.or(mLastPos); + } + + @Override + public void calcFollowPos(BitSet[] followPosSets) + { + // Let's let sub-models do what they need to do + mLeftModel.calcFollowPos(followPosSets); + mRightModel.calcFollowPos(followPosSets); + + /* And then we can calculate follower sets between left and + * right sub models; so that left model's last position entries + * have right model's first position entries included + */ + BitSet foll = new BitSet(); + mRightModel.addFirstPos(foll); + + BitSet toAddTo = new BitSet(); + mLeftModel.addLastPos(toAddTo); + + int ix = 0; // need to/can skip the null entry (index 0) + while ((ix = toAddTo.nextSetBit(ix+1)) >= 0) { + // Ok; so token at this index needs to have follow positions added... + followPosSets[ix].or(foll); + } + } + + @Override + public String toString() + { + StringBuilder sb = new StringBuilder(); + sb.append('('); + sb.append(mLeftModel.toString()); + sb.append(", "); + sb.append(mRightModel.toString()); + sb.append(')'); + return sb.toString(); + } +} diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/dtd/ContentSpec.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/dtd/ContentSpec.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/dtd/ContentSpec.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/dtd/ContentSpec.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,68 @@ +/* Woodstox XML processor + * + * Copyright (c) 2004 Tatu Saloranta, tatu.saloranta@iki.fi + * + * Licensed under the License specified in the file LICENSE which is + * included with the source code. + * You may not use this file except in compliance with the License. + * + * 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 com.ctc.wstx.dtd; + +/** + * Abstract base class for classes that contain parts of a content + * specification of an element defined in DTD. They are created + * by {@link FullDTDReader} when parsing an DTD subset, and they + * will be used for constructing actual validators for the element + * content. + */ +public abstract class ContentSpec +{ + protected char mArity; + + /* + /////////////////////////////////////////////////// + // Life-cycle + /////////////////////////////////////////////////// + */ + + public ContentSpec(char arity) { + mArity = arity; + } + + /* + /////////////////////////////////////////////////// + // Public API + /////////////////////////////////////////////////// + */ + + public final char getArity() { return mArity; } + + public final void setArity(char c) { mArity = c; } + + public boolean isLeaf() { return false; } + + /** + * Method called by input element stack to get validator for + * this content specification, if this specification is simple + * enough not to need full DFA-based validator. + * + * @return Simple content model validator, if one can be directly + * constructed, or null to indicate that a DFA needs to be + * created. + */ + public abstract StructValidator getSimpleValidator(); + + /** + * Method called as the first part of DFA construction, if necessary; + * will usually create simpler {@link ModelNode} instances that will + * match definition this instance contains. + */ + public abstract ModelNode rewrite(); +} diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/dtd/DefaultAttrValue.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/dtd/DefaultAttrValue.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/dtd/DefaultAttrValue.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/dtd/DefaultAttrValue.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,218 @@ +/* Woodstox XML processor + * + * Copyright (c) 2004- Tatu Saloranta, tatu.saloranta@iki.fi + * + * Licensed under the License specified in the file LICENSE which is + * included with the source code. + * You may not use this file except in compliance with the License. + * + * 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 com.ctc.wstx.dtd; + +import java.text.MessageFormat; + +import javax.xml.stream.Location; +import javax.xml.stream.XMLStreamException; + +import org.codehaus.stax2.validation.ValidationContext; +import org.codehaus.stax2.validation.XMLValidationProblem; +import org.codehaus.stax2.validation.XMLValidator; + +import com.ctc.wstx.cfg.ErrorConsts; + +/** + * Simple container class used to contain information about the default + * value for an attribute. Although for most use cases a simple String + * would suffice, there are cases where additional information is needed + * (especially status of 'broken' default values, which only need to be + * reported should the default value be needed). + */ +public final class DefaultAttrValue +{ + /* + //////////////////////////////////////////////////// + // Constants + //////////////////////////////////////////////////// + */ + + // // // Default value types + + public final static int DEF_DEFAULT = 1; + public final static int DEF_IMPLIED = 2; + public final static int DEF_REQUIRED = 3; + public final static int DEF_FIXED = 4; + + /* + //////////////////////////////////////////////////// + // Singleton instances + //////////////////////////////////////////////////// + */ + + final static DefaultAttrValue sImplied = new DefaultAttrValue(DEF_IMPLIED); + + final static DefaultAttrValue sRequired = new DefaultAttrValue(DEF_REQUIRED); + + /* + //////////////////////////////////////////////////// + // State + //////////////////////////////////////////////////// + */ + + final int mDefValueType; + + /** + * Actual expanded textual content of the default attribute value; + * normalized if appropriate in this mode. + * Note that all entities have been expanded: if a GE/PE was undefined, + * and no fatal errors were reported (non-validating mode), the + * references were just silently removed, and matching entries added + * to mUndeclaredEntity + */ + private String mValue = null; + + /** + * For now, let's only keep track of the first undeclared entity: + * can be extended if necessary. + */ + private UndeclaredEntity mUndeclaredEntity = null; + + /* + //////////////////////////////////////////////////// + // Life-cycle (creation, configuration) + //////////////////////////////////////////////////// + */ + + private DefaultAttrValue(int defValueType) + { + mDefValueType = defValueType; + } + + public static DefaultAttrValue constructImplied() { return sImplied; } + public static DefaultAttrValue constructRequired() { return sRequired; } + + public static DefaultAttrValue constructFixed() { + return new DefaultAttrValue(DEF_FIXED); + } + + public static DefaultAttrValue constructOptional() { + return new DefaultAttrValue(DEF_DEFAULT); + } + + public void setValue(String v) { + mValue = v; + } + + public void addUndeclaredPE(String name, Location loc) + { + addUndeclaredEntity(name, loc, true); + } + + public void addUndeclaredGE(String name, Location loc) + { + addUndeclaredEntity(name, loc, false); + } + + public void reportUndeclared(ValidationContext ctxt, XMLValidator dtd) + throws XMLStreamException + { + mUndeclaredEntity.reportUndeclared(ctxt, dtd); + } + + /* + //////////////////////////////////////////////////// + // Accessors: + //////////////////////////////////////////////////// + */ + + public boolean hasUndeclaredEntities() { + return (mUndeclaredEntity != null); + } + + public String getValue() { + return mValue; + } + + /** + * @return Expanded default value String, if there were no problems + * (no undeclared entities), or null to indicate there were problems. + * In latter case, caller is to figure out exact type of the problem + * and report this appropriately to the application. + */ + public String getValueIfOk() + { + return (mUndeclaredEntity == null) ? mValue : null; + } + + public boolean isRequired() { + return (this == sRequired); + } + + public boolean isFixed() { + return (mDefValueType == DEF_FIXED); + } + + public boolean hasDefaultValue() { + return (mDefValueType == DEF_DEFAULT) + || (mDefValueType == DEF_FIXED); + } + + /** + * Method used by the element to figure out if attribute needs "special" + * checking; basically if it's required, and/or has a default value. + * In both cases missing the attribute has specific consequences, either + * exception or addition of a default value. + */ + public boolean isSpecial() { + // Only non-special if #IMPLIED + return (this != sImplied); + } + + /* + //////////////////////////////////////////////////// + // Internal methods + //////////////////////////////////////////////////// + */ + + private void addUndeclaredEntity(String name, Location loc, boolean isPe) + { + if (mUndeclaredEntity == null) { + mUndeclaredEntity = new UndeclaredEntity(name, loc, isPe); + } + } + + /* + //////////////////////////////////////////////////// + // Helper class(es): + //////////////////////////////////////////////////// + */ + + final static class UndeclaredEntity + { + final String mName; + final boolean mIsPe; + final Location mLocation; + + UndeclaredEntity(String name, Location loc, boolean isPe) + { + mName = name; + mIsPe = isPe; + mLocation = loc; + } + + public void reportUndeclared(ValidationContext ctxt, XMLValidator dtd) + throws XMLStreamException + { + String msg = MessageFormat.format(ErrorConsts.ERR_DTD_UNDECLARED_ENTITY, new Object[] { (mIsPe ? "parsed" : "general"), mName }); + XMLValidationProblem prob = new XMLValidationProblem + (mLocation, msg, XMLValidationProblem.SEVERITY_FATAL); + prob.setReporter(dtd); + ctxt.reportProblem(prob); + } + } +} diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/dtd/DFAState.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/dtd/DFAState.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/dtd/DFAState.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/dtd/DFAState.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,204 @@ +/* Woodstox XML processor + * + * Copyright (c) 2004 Tatu Saloranta, tatu.saloranta@iki.fi + * + * Licensed under the License specified in the file LICENSE which is + * included with the source code. + * You may not use this file except in compliance with the License. + * + * 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 com.ctc.wstx.dtd; + +import java.util.*; + +import com.ctc.wstx.util.PrefixedName; + +/** + * Class that represents a state in DFA used for validating complex + * DTD content models. + */ +public final class DFAState +{ + final int mIndex; + final boolean mAccepting; + + BitSet mTokenSet; + + HashMap mNext = new HashMap(); + + /* + /////////////////////////////////////////////// + // Life-cycle: + /////////////////////////////////////////////// + */ + + public DFAState(int index, BitSet tokenSet) + { + mIndex = index; + // If we have a transition to state 0, it is an accepting state... + mAccepting = tokenSet.get(0); + mTokenSet = tokenSet; + } + + public static DFAState constructDFA(ContentSpec rootSpec) + { + // Let's first create the real model tree: + ModelNode modelRoot = rootSpec.rewrite(); + + /* Then we need to add the dummy end token, and concat node + * to contain it: + */ + TokenModel eofToken = TokenModel.getNullToken(); + ConcatModel dummyRoot = new ConcatModel(modelRoot, eofToken); + + /* then need to allocate index numbers for tokens + * (which will also calculate nullability) + */ + ArrayList tokens = new ArrayList(); + tokens.add(eofToken); // has to be added first, explicitly + dummyRoot.indexTokens(tokens); + + /* And then we can request calculation of follow pos; this will + * also recursively calculate first/last pos as needed: + */ + int flen = tokens.size(); + BitSet[] followPos = new BitSet[flen]; + PrefixedName[] tokenNames = new PrefixedName[flen]; + for (int i = 0; i < flen; ++i) { + followPos[i] = new BitSet(flen); + tokenNames[i] = tokens.get(i).getName(); + } + dummyRoot.calcFollowPos(followPos); + + /* And then we can calculate DFA stuff. First step is to get + * firstpos set for the root node, for creating the first + * state: + */ + BitSet initial = new BitSet(flen); + dummyRoot.addFirstPos(initial); + DFAState firstState = new DFAState(0, initial); + ArrayList stateList = new ArrayList(); + stateList.add(firstState); + HashMap stateMap = new HashMap(); + stateMap.put(initial, firstState); + + int i = 0; + while (i < stateList.size()) { + DFAState curr = stateList.get(i++); + curr.calcNext(tokenNames, followPos, stateList, stateMap); + } + + // DEBUG: + /* + for (i = 0; i < stateList.size(); ++i) { + //System.out.println(stateList.get(i)); + } + */ + + // And there we have it! + return firstState; + } + + /* + /////////////////////////////////////////////// + // Public API, accessors: + /////////////////////////////////////////////// + */ + + public boolean isAcceptingState() { + return mAccepting; + } + + public int getIndex() { + return mIndex; + } + + public DFAState findNext(PrefixedName elemName) { + return mNext.get(elemName); + } + + public TreeSet getNextNames() { + // Let's order them alphabetically + TreeSet names = new TreeSet(); + for (PrefixedName n : mNext.keySet()) { + names.add(n); + } + return names; + } + + public void calcNext(PrefixedName[] tokenNames, BitSet[] tokenFPs, + List stateList, Map stateMap) + { + /* Need to loop over all included tokens, and find groups + * of said tokens + */ + int first = -1; + + /* Need to clone; can not modify in place, since the BitSet + * is also used as the key... + */ + BitSet tokenSet = (BitSet) mTokenSet.clone(); + // No need to keep the reference to it, though: + mTokenSet = null; + + while ((first = tokenSet.nextSetBit(first+1)) >= 0) { + PrefixedName tokenName = tokenNames[first]; + + /* Special case; the dummy end token has null as name; + * we can skip that one: + */ + if (tokenName == null) { + continue; + } + + BitSet nextGroup = (BitSet) tokenFPs[first].clone(); + int second = first; + + while ((second = tokenSet.nextSetBit(second+1)) > 0) { + if (tokenNames[second] == tokenName) { + // Let's clear it, too, so we won't match it again: + tokenSet.clear(second); + nextGroup.or(tokenFPs[second]); + } + } + + // Ok; is it a new group? + DFAState next = stateMap.get(nextGroup); + if (next == null) { // yup! + next = new DFAState(stateList.size(), nextGroup); + stateList.add(next); + stateMap.put(nextGroup, next); + } + mNext.put(tokenName, next); + } + } + + /* + /////////////////////////////////////////////// + // Other methods + /////////////////////////////////////////////// + */ + + @Override + public String toString() + { + StringBuilder sb = new StringBuilder(); + sb.append("State #"+mIndex+":\n"); + sb.append(" Accepting: "+mAccepting); + sb.append("\n Next states:\n"); + for (Map.Entry en : mNext.entrySet()) { + sb.append(en.getKey()); + sb.append(" -> "); + DFAState next = en.getValue(); + sb.append(next.getIndex()); + sb.append("\n"); + } + return sb.toString(); + } +} diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/dtd/DFAValidator.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/dtd/DFAValidator.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/dtd/DFAValidator.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/dtd/DFAValidator.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,80 @@ +/* Woodstox XML processor + * + * Copyright (c) 2004 Tatu Saloranta, tatu.saloranta@iki.fi + * + * Licensed under the License specified in the file LICENSE which is + * included with the source code. + * You may not use this file except in compliance with the License. + * + * 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 com.ctc.wstx.dtd; + +import java.util.*; + +import com.ctc.wstx.util.PrefixedName; +import com.ctc.wstx.util.StringUtil; + +/** + * Validator class that is based on a DFA constructed from DTD content + * specification. + */ +public final class DFAValidator + extends StructValidator +{ + /** + * For root validator instance, the start state of DFA; for other + * instances, current state. + */ + DFAState mState; + + public DFAValidator(DFAState initialState) { + mState = initialState; + } + + @Override + public StructValidator newInstance() { + return new DFAValidator(mState); + } + + @Override + public String tryToValidate(PrefixedName elemName) + { + // Do we have a follow state with that key? + DFAState next = mState.findNext(elemName); + + if (next == null) { + // Nope; let's show what we'd have expected instead... + TreeSet names = mState.getNextNames(); + if (names.size() == 0) { // expected end tag? + return "Expected $END"; + } + + // Either end tag, or another tag? + if (mState.isAcceptingState()) { + return "Expected <"+StringUtil.concatEntries(names, ">, <", null)+"> or $END"; + } + return "Expected <"+StringUtil.concatEntries(names, + ">, <", "> or <")+">"; + } + + mState = next; + return null; + } + + @Override + public String fullyValid() + { + if (mState.isAcceptingState()) { + return null; + } + TreeSet names = mState.getNextNames(); + return "Expected <"+StringUtil.concatEntries(names, + ">, <", "> or <")+">"; + } +} diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/dtd/DTDAttribute.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/dtd/DTDAttribute.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/dtd/DTDAttribute.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/dtd/DTDAttribute.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,511 @@ +/* Woodstox XML processor + * + * Copyright (c) 2004- Tatu Saloranta, tatu.saloranta@iki.fi + * + * Licensed under the License specified in the file LICENSE which is + * included with the source code. + * You may not use this file except in compliance with the License. + * + * 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 com.ctc.wstx.dtd; + +import java.util.Map; + +import javax.xml.stream.XMLStreamException; + +import org.codehaus.stax2.validation.ValidationContext; +import org.codehaus.stax2.validation.XMLValidator; + +import com.ctc.wstx.ent.EntityDecl; +import com.ctc.wstx.io.WstxInputData; +import com.ctc.wstx.sr.InputProblemReporter; +import com.ctc.wstx.util.PrefixedName; +import com.ctc.wstx.util.StringUtil; +import com.ctc.wstx.util.WordResolver; + +/** + * Base class for objects that contain attribute definitions from DTD. + * Sub-classes exists for specific typed attributes (enumeration-valued, + * non-CDATA ones); base class itself is used for attributes of type + * CDATA. + */ +public abstract class DTDAttribute +{ + final static char CHAR_SPACE = (char) 0x0020; + + /* + /////////////////////////////////////////////////// + // Type constants + /////////////////////////////////////////////////// + */ + + // // // Value types + + public final static int TYPE_CDATA = 0; // default... + public final static int TYPE_ENUMERATED = 1; + + public final static int TYPE_ID = 2; + public final static int TYPE_IDREF = 3; + public final static int TYPE_IDREFS = 4; + + public final static int TYPE_ENTITY = 5; + public final static int TYPE_ENTITIES = 6; + + public final static int TYPE_NOTATION = 7; + public final static int TYPE_NMTOKEN = 8; + public final static int TYPE_NMTOKENS = 9; + + /** + * Array that has String constants matching above mentioned + * value types + */ + final static String[] sTypes = new String[] { + "CDATA", + /* 05-Feb-2006, TSa: Hmmh. Apparently SAX specs indicate that + * enumerated type should be listed as "NMTOKEN"... but most + * SAX parsers use ENUMERATED, plus this way application can + * distinguish real NMTOKEN from enumerated type. + */ + /* 26-Nov-2006, TSa: Either way, we can change type to SAX + * compatible within SAX classes, not here. + */ + //"NMTOKEN" + "ENUMERATED", + "ID", + "IDREF", + "IDREFS", + "ENTITY", + "ENTITIES", + "NOTATION", + "NMTOKEN", + "NMTOKENS", + }; + + /* + /////////////////////////////////////////////////// + // Information about the attribute itself + /////////////////////////////////////////////////// + */ + + protected final PrefixedName mName; + + /** + * Index number amongst "special" attributes (required ones, attributes + * that have default values), if attribute is one: -1 if not. + */ + protected final int mSpecialIndex; + + protected final DefaultAttrValue mDefValue; + + protected final boolean mCfgNsAware; + protected final boolean mCfgXml11; + + /* + /////////////////////////////////////////////////// + // Life-cycle + /////////////////////////////////////////////////// + */ + + public DTDAttribute(PrefixedName name, DefaultAttrValue defValue, int specIndex, + boolean nsAware, boolean xml11) + { + mName = name; + mDefValue = defValue; + mSpecialIndex = specIndex; + mCfgNsAware = nsAware; + mCfgXml11 = xml11; + } + + public abstract DTDAttribute cloneWith(int specIndex); + + /* + /////////////////////////////////////////////////// + // Public API, accessors + /////////////////////////////////////////////////// + */ + + public final PrefixedName getName() { return mName; } + + @Override + public final String toString() { + return mName.toString(); + } + + public final String getDefaultValue(ValidationContext ctxt, XMLValidator dtd) + throws XMLStreamException + { + String val = mDefValue.getValueIfOk(); + if (val == null) { + mDefValue.reportUndeclared(ctxt, dtd); + /* should never get here, but just to be safe, let's use + * the 'raw' value (one that does not have undeclared entities + * included, most likely) + */ + val = mDefValue.getValue(); + } + return val; + } + + public final int getSpecialIndex() { + return mSpecialIndex; + } + + public final boolean needsValidation() { + return (getValueType() != TYPE_CDATA); + } + + public final boolean isFixed() { + return mDefValue.isFixed(); + } + + public final boolean isRequired() { + return mDefValue.isRequired(); + } + + /** + * Method used by the element to figure out if attribute needs "special" + * checking; basically if it's required, and/or has a default value. + * In both cases missing the attribute has specific consequences, either + * exception or addition of a default value. + */ + public final boolean isSpecial() { + return mDefValue.isSpecial(); + } + + public final boolean hasDefaultValue() { + return mDefValue.hasDefaultValue(); + } + + /** + * Returns the value type of this attribute as an enumerated int + * to match type (CDATA, ...) + *

+ * Note: + */ + public int getValueType() { + return TYPE_CDATA; + } + + public String getValueTypeString() + { + return sTypes[getValueType()]; + } + + public boolean typeIsId() { + return false; + } + + public boolean typeIsNotation() { + return false; + } + + /* + /////////////////////////////////////////////////// + // Public API, validation + /////////////////////////////////////////////////// + */ + + public abstract String validate(DTDValidatorBase v, char[] cbuf, int start, int end, boolean normalize) + throws XMLStreamException; + + /** + *

+ * Note: the default implementation is not optimized, as it does + * a potentially unnecessary copy of the contents. It is expected that + * this method is seldom called (Woodstox never directly calls it; it + * only gets called for chained validators when one validator normalizes + * the value, and then following validators are passed a String, not + * char array) + */ + public String validate(DTDValidatorBase v, String value, boolean normalize) + throws XMLStreamException + { + int len = value.length(); + /* Temporary buffer has to come from the validator itself, since + * attribute objects are stateless and shared... + */ + char[] cbuf = v.getTempAttrValueBuffer(value.length()); + if (len > 0) { + value.getChars(0, len, cbuf, 0); + } + return validate(v, cbuf, 0, len, normalize); + } + + /** + * Method called by the {@link DTDValidator} + * to ask attribute to verify that the default it has (if any) is + * valid for such type. + */ + public abstract void validateDefault(InputProblemReporter rep, boolean normalize) + throws XMLStreamException; + + /** + * Method called when no validation is to be done, but value is still + * to be normalized as much as it can. What this usually means is that + * all regular space (parser earlier on converts other white space to + * spaces, except for specific character entities; and these special + * cases are NOT to be normalized). + *

+ * The only exception is that CDATA will not do any normalization. But + * for now, let's implement basic functionality that CDTA instance will + * override + * + * @param v Validator that invoked normalization + * + * @return Normalized value as a String, if any changes were done; + * null if input was normalized + */ + public String normalize(DTDValidatorBase v, char[] cbuf, int start, int end) + { + return StringUtil.normalizeSpaces(cbuf, start, end); + } + + /** + * Method called to do initial normalization of the default attribute + * value, without trying to verify its validity. Thus, it's + * called independent of whether we are fully validating the document. + */ + public void normalizeDefault() + { + String val = mDefValue.getValue(); + if (val.length() > 0) { + char[] cbuf = val.toCharArray(); + String str = StringUtil.normalizeSpaces(cbuf, 0, cbuf.length); + if (str != null) { + mDefValue.setValue(str); + } + } + } + + /* + /////////////////////////////////////////////////// + // Package methods, validation helper methods + /////////////////////////////////////////////////// + */ + + protected String validateDefaultName(InputProblemReporter rep, boolean normalize) + throws XMLStreamException + { + String origDefValue = mDefValue.getValue(); + String defValue = origDefValue.trim(); + + if (defValue.length() == 0) { + reportValidationProblem(rep, "Invalid default value '"+defValue + +"'; empty String is not a valid name"); + } + + // Ok, needs to be a valid XML name: + int illegalIx = WstxInputData.findIllegalNameChar(defValue, mCfgNsAware, mCfgXml11); + if (illegalIx >= 0) { + if (illegalIx == 0) { + reportValidationProblem(rep, "Invalid default value '"+defValue+"'; character " + +WstxInputData.getCharDesc(defValue.charAt(0)) + +") not valid first character of a name"); + } else { + reportValidationProblem(rep, "Invalid default value '"+defValue+"'; character #"+illegalIx+" (" + +WstxInputData.getCharDesc(defValue.charAt(illegalIx)) + +") not valid name character"); + } + } + + // Ok, cool it's ok... + return normalize ? defValue : origDefValue; + } + + protected String validateDefaultNames(InputProblemReporter rep, boolean normalize) + throws XMLStreamException + { + String defValue = mDefValue.getValue().trim(); + int len = defValue.length(); + + // Then code similar to actual value validation: + StringBuilder sb = null; + int count = 0; + int start = 0; + + main_loop: + while (start < len) { + char c = defValue.charAt(start); + + // Ok, any white space to skip? + while (true) { + if (!WstxInputData.isSpaceChar(c)) { + break; + } + if (++start >= len) { + break main_loop; + } + c = defValue.charAt(start); + } + + // Then need to find the token itself: + int i = start+1; + + for (; i < len; ++i) { + if (WstxInputData.isSpaceChar(defValue.charAt(i))) { + break; + } + } + String token = defValue.substring(start, i); + int illegalIx = WstxInputData.findIllegalNameChar(token, mCfgNsAware, mCfgXml11); + if (illegalIx >= 0) { + if (illegalIx == 0) { + reportValidationProblem(rep, "Invalid default value '"+defValue + +"'; character " + +WstxInputData.getCharDesc(defValue.charAt(start)) + +") not valid first character of a name token"); + } else { + reportValidationProblem(rep, "Invalid default value '"+defValue + +"'; character " + +WstxInputData.getCharDesc(c) + +") not a valid name character"); + } + } + ++count; + if (normalize) { + if (sb == null) { + sb = new StringBuilder(i - start + 32); + } else { + sb.append(' '); + } + sb.append(token); + } + start = i+1; + } + + if (count == 0) { + reportValidationProblem(rep, "Invalid default value '"+defValue + +"'; empty String is not a valid name value"); + } + + return normalize ? sb.toString() : defValue; + } + + protected String validateDefaultNmToken(InputProblemReporter rep, boolean normalize) + throws XMLStreamException + { + String origDefValue = mDefValue.getValue(); + String defValue = origDefValue.trim(); + + if (defValue.length() == 0) { + reportValidationProblem(rep, "Invalid default value '"+defValue+"'; empty String is not a valid NMTOKEN"); + } + int illegalIx = WstxInputData.findIllegalNmtokenChar(defValue, mCfgNsAware, mCfgXml11); + if (illegalIx >= 0) { + reportValidationProblem(rep, "Invalid default value '"+defValue + +"'; character #"+illegalIx+" (" + +WstxInputData.getCharDesc(defValue.charAt(illegalIx)) + +") not valid NMTOKEN character"); + } + // Ok, cool it's ok... + return normalize ? defValue : origDefValue; + } + + /** + * Method called by validation/normalization code for enumeration-valued + * attributes, to trim + * specified attribute value (full normalization not needed -- called + * for values that CAN NOT have spaces inside; such values can not + * be legal), and then check whether it is included + * in set of words (tokens) passed in. If actual value was included, + * will return the normalized word (as well as store shared String + * locally); otherwise will return null. + */ + public String validateEnumValue(char[] cbuf, int start, int end, + boolean normalize, + WordResolver res) + { + /* Better NOT to build temporary Strings quite yet; can resolve + * matches via resolver more efficiently. + */ + // Note: at this point, should only have real spaces... + if (normalize) { + while (start < end && cbuf[start] <= CHAR_SPACE) { + ++start; + } + while (--end > start && cbuf[end] <= CHAR_SPACE) { + ; + } + ++end; // so it'll point to the first char (or beyond end of buffer) + } + + // Empty String is never legal for enums: + if (start >= end) { + return null; + } + return res.find(cbuf, start, end); + } + + protected EntityDecl findEntityDecl(DTDValidatorBase v, + char[] ch, int start, int len /*, int hash*/) + throws XMLStreamException + { + Map entMap = v.getEntityMap(); + /* !!! 13-Nov-2005, TSa: If this was to become a bottle-neck, we + * could use/share a symbol table. Or at least reuse Strings... + */ + String id = new String(ch, start, len); + EntityDecl ent = entMap.get(id); + + if (ent == null) { + reportValidationProblem(v, "Referenced entity '"+id+"' not defined"); + } else if (ent.isParsed()) { + reportValidationProblem(v, "Referenced entity '"+id+"' is not an unparsed entity"); + } + return ent; + } + + /* Too bad this method can not be combined with previous segment -- + * the reason is that DTDValidator does not implement + * InputProblemReporter... + */ + + protected void checkEntity(InputProblemReporter rep, String id, EntityDecl ent) + throws XMLStreamException + { + if (ent == null) { + rep.reportValidationProblem("Referenced entity '"+id+"' not defined"); + } else if (ent.isParsed()) { + rep.reportValidationProblem("Referenced entity '"+id+"' is not an unparsed entity"); + } + } + + /* + /////////////////////////////////////////////////// + // Package methods, error reporting + /////////////////////////////////////////////////// + */ + + protected String reportInvalidChar(DTDValidatorBase v, char c, String msg) + throws XMLStreamException + { + reportValidationProblem(v, "Invalid character "+WstxInputData.getCharDesc(c)+": "+msg); + return null; + } + + protected String reportValidationProblem(DTDValidatorBase v, String msg) + throws XMLStreamException + { + v.reportValidationProblem("Attribute '"+mName+"': "+msg); + return null; + } + + /** + * Method called during parsing of DTD schema, to report a problem. + * Note that unlike during actual validation, we have no option of + * just gracefully listing problems and ignoring them; an exception + * is always thrown. + */ + protected String reportValidationProblem(InputProblemReporter rep, String msg) + throws XMLStreamException + { + rep.reportValidationProblem("Attribute definition '"+mName+"': "+msg); + return null; + } +} diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/dtd/DTDCdataAttr.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/dtd/DTDCdataAttr.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/dtd/DTDCdataAttr.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/dtd/DTDCdataAttr.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,61 @@ +package com.ctc.wstx.dtd; + +import org.codehaus.stax2.validation.XMLValidationException; + +import com.ctc.wstx.sr.InputProblemReporter; +import com.ctc.wstx.util.PrefixedName; + +/** + * Simple {@link DTDAttribute} sub-class used for plain vanilla CDATA + * valued attributes. Although base class implements most of the methods, + * it's better designwise to keep that base class abstract and have + * separate CDATA type as well. + */ +public final class DTDCdataAttr + extends DTDAttribute +{ + public DTDCdataAttr(PrefixedName name, DefaultAttrValue defValue, int specIndex, + boolean nsAware, boolean xml11) + { + super(name, defValue, specIndex, nsAware, xml11); + } + + @Override + public DTDAttribute cloneWith(int specIndex) { + return new DTDCdataAttr(mName, mDefValue, specIndex, mCfgNsAware, mCfgXml11); + } + + /* + /////////////////////////////////////////////////// + // Public API, validation + /////////////////////////////////////////////////// + */ + + @Override + public String validate(DTDValidatorBase v, char[] cbuf, int start, int end, boolean normalize) + throws XMLValidationException + { + // Nothing to do for pure CDATA attributes... + return null; + } + + @Override + public void validateDefault(InputProblemReporter rep, boolean normalize) + throws javax.xml.stream.XMLStreamException + { + // Nothing to do for CDATA; all values are fine + } + + @Override + public String normalize(DTDValidatorBase v, char[] cbuf, int start, int end) + { + // Nothing to do for pure CDATA attributes... + return null; + } + + @Override + public void normalizeDefault() + { + // Nothing to do for pure CDATA attributes... + } +} diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/dtd/DTDElement.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/dtd/DTDElement.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/dtd/DTDElement.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/dtd/DTDElement.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,577 @@ +/* Woodstox XML processor + * + * Copyright (c) 2004- Tatu Saloranta, tatu.saloranta@iki.fi + * + * Licensed under the License specified in the file LICENSE which is + * included with the source code. + * You may not use this file except in compliance with the License. + * + * 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 com.ctc.wstx.dtd; + +import java.util.*; + +import javax.xml.stream.Location; +import javax.xml.stream.XMLStreamException; + +import org.codehaus.stax2.validation.XMLValidator; + +import com.ctc.wstx.api.ReaderConfig; +import com.ctc.wstx.cfg.ErrorConsts; +import com.ctc.wstx.sr.InputProblemReporter; +import com.ctc.wstx.util.ExceptionUtil; +import com.ctc.wstx.util.PrefixedName; +import com.ctc.wstx.util.WordResolver; + +/** + * Class that contains element definitions from DTD. + *

+ * Notes about thread-safety: this class is not thread-safe, since it does + * not have to be, in general case. That is, the only instances that can + * be shared are external subset instances, and those are used in read-only + * manner (with the exception of temporary arrays constructed on-demand). + */ +public final class DTDElement +{ + + /* + /////////////////////////////////////////////////// + // Information about the element itself + /////////////////////////////////////////////////// + */ + + final PrefixedName mName; + + /** + * Location of the (real) definition of the element; may be null for + * placeholder elements created to hold ATTLIST definitions + */ + final Location mLocation; + + /** + * Base validator object for validating content model of this element; + * may be null for some simple content models (ANY, EMPTY). + */ + StructValidator mValidator; + + int mAllowedContent; + + /** + * True if the DTD was parsed (and is to be used) in namespace-aware + * mode. + * Affects (name) validation amongst other things. + */ + final boolean mNsAware; + + /** + * True if the DTD was parsed in xml1.1 compliant mode (referenced to + * from an xml 1.1 document). + * Affects (name) validation amongst other things. + */ + final boolean mXml11; + + /* + /////////////////////////////////////////////////// + // Attribute info + /////////////////////////////////////////////////// + */ + + HashMap mAttrMap = null; + + /** + * Ordered list of attributes that have 'special' properties (attribute + * is required, has a default value [regular or fixed]); these attributes + * have to be specifically checked after actual values have been resolved. + */ + ArrayList mSpecAttrList = null; + + boolean mAnyFixed = false; + + /** + * Flag set to true if there are any attributes that have either + * basic default value, or #FIXED default value. + */ + boolean mAnyDefaults = false; + + /** + * Flag that is set to true if there is at least one attribute that + * has type that requires normalization and/or validation; that is, + * is of some other type than CDATA. + */ + boolean mValidateAttrs = false; + + /** + * Id attribute instance, if one already declared for this element; + * can only have up to one such attribute per element. + */ + DTDAttribute mIdAttr; + + /** + * Notation attribute instance, if one already declared for this element; + * can only have up to one such attribute per element. + */ + DTDAttribute mNotationAttr; + + // // // !! If you add new attributes, make sure they get copied + // // // in #define() method !! + + /* + /////////////////////////////////////////////////// + // Namespace declaration defaulting... + /////////////////////////////////////////////////// + */ + + /** + * Set of namespace declarations with default values, if any + * (regular ns pseudo-attr declarations are just ignored) + */ + HashMap mNsDefaults = null; + + /* + /////////////////////////////////////////////////// + // Life-cycle + /////////////////////////////////////////////////// + */ + + private DTDElement(Location loc, PrefixedName name, + StructValidator val, int allowedContent, + boolean nsAware, boolean xml11) + { + mName = name; + mLocation = loc; + mValidator = val; + mAllowedContent = allowedContent; + mNsAware = nsAware; + mXml11 = xml11; + } + + /** + * Method called to create an actual element definition, matching + * an ELEMENT directive in a DTD subset. + */ + public static DTDElement createDefined(ReaderConfig cfg, Location loc, PrefixedName name, + StructValidator val, int allowedContent) + { + if (allowedContent == XMLValidator.CONTENT_ALLOW_UNDEFINED) { // sanity check + ExceptionUtil.throwInternal("trying to use XMLValidator.CONTENT_ALLOW_UNDEFINED via createDefined()"); + } + return new DTDElement(loc, name, val, allowedContent, + cfg.willSupportNamespaces(), cfg.isXml11()); + } + + /** + * Method called to create a "placeholder" element definition, needed to + * contain attribute definitions. + */ + public static DTDElement createPlaceholder(ReaderConfig cfg, Location loc, PrefixedName name) + { + return new DTDElement(loc, name, null, XMLValidator.CONTENT_ALLOW_UNDEFINED, + cfg.willSupportNamespaces(), cfg.isXml11()); + } + + /** + * Method called on placeholder element, to create a real instance that + * has all attribute definitions placeholder had (it'll always have at + * least one -- otherwise no placeholder was needed). + */ + public DTDElement define(Location loc, StructValidator val, + int allowedContent) + { + verifyUndefined(); + if (allowedContent == XMLValidator.CONTENT_ALLOW_UNDEFINED) { // sanity check + ExceptionUtil.throwInternal("trying to use CONTENT_ALLOW_UNDEFINED via define()"); + } + + DTDElement elem = new DTDElement(loc, mName, val, allowedContent, + mNsAware, mXml11); + + // Ok, need to copy state collected so far: + elem.mAttrMap = mAttrMap; + elem.mSpecAttrList = mSpecAttrList; + elem.mAnyFixed = mAnyFixed; + elem.mValidateAttrs = mValidateAttrs; + elem.mAnyDefaults = mAnyDefaults; + elem.mIdAttr = mIdAttr; + elem.mNotationAttr = mNotationAttr; + elem.mNsDefaults = mNsDefaults; + + return elem; + } + + /** + * Method called to "upgrade" a placeholder using a defined element, + * including adding attributes. + */ + public void defineFrom(InputProblemReporter rep, DTDElement definedElem, + boolean fullyValidate) + throws XMLStreamException + { + if (fullyValidate) { + verifyUndefined(); + } + mValidator = definedElem.mValidator; + mAllowedContent = definedElem.mAllowedContent; + mergeMissingAttributesFrom(rep, definedElem, fullyValidate); + } + + private void verifyUndefined() + { + if (mAllowedContent != XMLValidator.CONTENT_ALLOW_UNDEFINED) { // sanity check + ExceptionUtil.throwInternal("redefining defined element spec"); + } + } + + /** + * Method called by DTD parser when it has read information about + * an attribute that belong to this element + * + * @return Newly created attribute Object if the attribute definition was + * added (hadn't been declared yet); null if it's a duplicate, in which + * case original definition sticks. + */ + public DTDAttribute addAttribute(InputProblemReporter rep, + PrefixedName attrName, int valueType, + DefaultAttrValue defValue, WordResolver enumValues, + boolean fullyValidate) + throws XMLStreamException + { + HashMap m = mAttrMap; + if (m == null) { + mAttrMap = m = new HashMap(); + } + + List specList = defValue.isSpecial() ? getSpecialList() : null; + + DTDAttribute attr; + int specIndex = (specList == null) ? -1 : specList.size(); + + switch (valueType) { + case DTDAttribute.TYPE_CDATA: + attr = new DTDCdataAttr(attrName, defValue, specIndex, mNsAware, mXml11); + break; + + case DTDAttribute.TYPE_ENUMERATED: + attr = new DTDEnumAttr(attrName, defValue, specIndex, mNsAware, mXml11, enumValues); + break; + + case DTDAttribute.TYPE_ID: + /* note: although ID attributes are not to have default value, + * this is 'only' a validity constraint, and in dtd-aware-but- + * not-validating mode it is apparently 'legal' to add default + * values. Bleech. + */ + attr = new DTDIdAttr(attrName, defValue, specIndex, mNsAware, mXml11); + break; + + case DTDAttribute.TYPE_IDREF: + attr = new DTDIdRefAttr(attrName, defValue, specIndex, mNsAware, mXml11); + break; + + case DTDAttribute.TYPE_IDREFS: + attr = new DTDIdRefsAttr(attrName, defValue, specIndex, mNsAware, mXml11); + break; + + case DTDAttribute.TYPE_ENTITY: + attr = new DTDEntityAttr(attrName, defValue, specIndex, mNsAware, mXml11); + break; + + case DTDAttribute.TYPE_ENTITIES: + attr = new DTDEntitiesAttr(attrName, defValue, specIndex, mNsAware, mXml11); + break; + + case DTDAttribute.TYPE_NOTATION: + attr = new DTDNotationAttr(attrName, defValue, specIndex, mNsAware, mXml11, enumValues); + break; + + case DTDAttribute.TYPE_NMTOKEN: + attr = new DTDNmTokenAttr(attrName, defValue, specIndex, mNsAware, mXml11); + break; + + case DTDAttribute.TYPE_NMTOKENS: + attr = new DTDNmTokensAttr(attrName, defValue, specIndex, mNsAware, mXml11); + break; + + default: + // 18-Jan-2006, TSa: should never get here... + ExceptionUtil.throwGenericInternal(); + attr = null; // unreachable, but compiler wants it + } + + DTDAttribute old = doAddAttribute(m, rep, attr, specList, fullyValidate); + return (old == null) ? attr : null; + } + + /** + * Method called to add a definition of a namespace-declaration + * pseudo-attribute with a default value. + * + * @param rep Reporter to use to report non-fatal problems + * @param fullyValidate Whether this is being invoked for actual DTD validation, + * or just the "typing non-validator" + * + * @return Attribute that acts as the placeholder, if the declaration + * was added; null to indicate it + * was a dup (there was an earlier declaration) + */ + public DTDAttribute addNsDefault + (InputProblemReporter rep, PrefixedName attrName, int valueType, + DefaultAttrValue defValue, boolean fullyValidate) + throws XMLStreamException + { + /* Let's simplify handling a bit: although theoretically all + * combinations of value can be used, let's really only differentiate + * between CDATA and 'other' (for which let's use NMTOKEN) + */ + DTDAttribute nsAttr; + + switch (valueType) { + case DTDAttribute.TYPE_CDATA: + nsAttr = new DTDCdataAttr(attrName, defValue, -1, mNsAware, mXml11); + break; + default: // something else, default to NMTOKEN then + nsAttr = new DTDNmTokenAttr(attrName, defValue, -1, mNsAware, mXml11); + break; + } + + // Ok. So which prefix are we to bind? Need to access by prefix... + String prefix = attrName.getPrefix(); + if (prefix == null || prefix.length() == 0) { // defult NS -> "" + prefix = ""; + } else { // non-default, use the local name + prefix = attrName.getLocalName(); + } + + if (mNsDefaults == null) { + mNsDefaults = new HashMap(); + } else { + if (mNsDefaults.containsKey(prefix)) { + return null; + } + } + mNsDefaults.put(prefix, nsAttr); + return nsAttr; + } + + public void mergeMissingAttributesFrom(InputProblemReporter rep, DTDElement other, + boolean fullyValidate) + throws XMLStreamException + { + Map otherMap = other.getAttributes(); + HashMap m = mAttrMap; + if (m == null) { + mAttrMap = m = new HashMap(); + } + + //boolean anyAdded = false; + + if (otherMap != null && otherMap.size() > 0) { + for (Map.Entry me : otherMap.entrySet()) { + PrefixedName key = me.getKey(); + // Should only add if no such attribute exists... + if (!m.containsKey(key)) { + // can only use as is, if it's not a special attr + DTDAttribute newAttr = me.getValue(); + List specList; + // otherwise need to clone + if (newAttr.isSpecial()) { + specList = getSpecialList(); + newAttr = newAttr.cloneWith(specList.size()); + } else { + specList = null; + } + doAddAttribute(m, rep, newAttr, specList, fullyValidate); + } + } + } + + HashMap otherNs = other.mNsDefaults; + if (otherNs != null) { + if (mNsDefaults == null) { + mNsDefaults = new HashMap(); + } + for (Map.Entry en : otherNs.entrySet()) { + String prefix = en.getKey(); + // Should only add if no such attribute exists... + if (!mNsDefaults.containsKey(prefix)) { + mNsDefaults.put(prefix, en.getValue()); + } + } + } + } + + /** + * @return Earlier declaration of the attribute, if any; null if + * this was a new attribute + */ + private DTDAttribute doAddAttribute(Map attrMap, InputProblemReporter rep, + DTDAttribute attr, List specList, + boolean fullyValidate) + throws XMLStreamException + { + PrefixedName attrName = attr.getName(); + + // Maybe we already have it? If so, need to ignore + DTDAttribute old = attrMap.get(attrName); + if (old != null) { + rep.reportProblem(null, ErrorConsts.WT_ATTR_DECL, ErrorConsts.W_DTD_DUP_ATTR, + attrName, mName); + return old; + } + + switch (attr.getValueType()) { + case DTDAttribute.TYPE_ID: + // Only one such attribute per element (Specs, 1.0#3.3.1) + if (fullyValidate && mIdAttr != null) { + rep.throwParseError("Invalid id attribute \"{0}\" for element <{1}>: already had id attribute \""+mIdAttr.getName()+"\"", attrName, mName); + } + mIdAttr = attr; + break; + + case DTDAttribute.TYPE_NOTATION: + // Only one such attribute per element (Specs, 1.0#3.3.1) + if (fullyValidate && mNotationAttr != null) { + rep.throwParseError("Invalid notation attribute '"+attrName+"' for element <"+mName+">: already had notation attribute '"+mNotationAttr.getName()+"'"); + } + mNotationAttr = attr; + break; + } + + attrMap.put(attrName, attr); + if (specList != null) { + specList.add(attr); + } + if (!mAnyFixed) { + mAnyFixed = attr.isFixed(); + } + if (!mValidateAttrs) { + mValidateAttrs = attr.needsValidation(); + } + if (!mAnyDefaults) { + mAnyDefaults = attr.hasDefaultValue(); + } + + return null; + } + + /* + /////////////////////////////////////////////////// + // Public API, accessors: + /////////////////////////////////////////////////// + */ + + public PrefixedName getName() { return mName; } + + @Override + public String toString() { + return mName.toString(); + } + + public String getDisplayName() { + return mName.toString(); + } + + public Location getLocation() { return mLocation; } + + public boolean isDefined() { + return (mAllowedContent != XMLValidator.CONTENT_ALLOW_UNDEFINED); + } + + /** + * @return Constant that identifies what kind of nodes are in general + * allowed inside this element. + */ + public int getAllowedContent() { + return mAllowedContent; + } + + /** + * Specialized accessor used by non-validating but typing 'validator': + * essentially, used to figure out whether #PCDATA is allowed or not; + * and based on that, return one of 2 allowable text values (only + * space, or anything). This is the relevant subset in non-validating + * modes, needed to properly type resulting character events. + */ + public int getAllowedContentIfSpace() + { + int vld = mAllowedContent; + return (vld <= XMLValidator.CONTENT_ALLOW_WS) ? + XMLValidator.CONTENT_ALLOW_WS_NONSTRICT : + XMLValidator.CONTENT_ALLOW_ANY_TEXT; + } + + public HashMap getAttributes() { + return mAttrMap; + } + + public int getSpecialCount() { + return (mSpecAttrList == null) ? 0 : mSpecAttrList.size(); + } + + public List getSpecialAttrs() { + return mSpecAttrList; + } + + /** + * @return True if at least one of the attributes has type other than + * CDATA; false if not + */ + public boolean attrsNeedValidation() { + return mValidateAttrs; + } + + public boolean hasFixedAttrs() { + return mAnyFixed; + } + + public boolean hasAttrDefaultValues() { + return mAnyDefaults; + } + + public DTDAttribute getIdAttribute() { + return mIdAttr; + } + + public DTDAttribute getNotationAttribute() { + return mNotationAttr; + } + + public boolean hasNsDefaults() { + return (mNsDefaults != null); + } + + /* + /////////////////////////////////////////////////// + // Public API, factory methods: + /////////////////////////////////////////////////// + */ + + public StructValidator getValidator() + { + return (mValidator == null) ? null : mValidator.newInstance(); + } + + protected HashMap getNsDefaults() { + return mNsDefaults; + } + + /* + /////////////////////////////////////////////////// + // Internal methods + /////////////////////////////////////////////////// + */ + + private List getSpecialList() + { + ArrayList l = mSpecAttrList; + if (l == null) { + mSpecAttrList = l = new ArrayList(); + } + return l; + } +} diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/dtd/DTDEntitiesAttr.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/dtd/DTDEntitiesAttr.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/dtd/DTDEntitiesAttr.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/dtd/DTDEntitiesAttr.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,178 @@ +package com.ctc.wstx.dtd; + +import java.util.StringTokenizer; + +import javax.xml.stream.XMLStreamException; + +import com.ctc.wstx.ent.EntityDecl; +import com.ctc.wstx.io.WstxInputData; +import com.ctc.wstx.sr.InputProblemReporter; +import com.ctc.wstx.util.PrefixedName; + +/** + * Specific attribute class for attributes that contain (unique) + * identifiers. + */ +public final class DTDEntitiesAttr + extends DTDAttribute +{ + /* + /////////////////////////////////////////////////// + // Life-cycle + /////////////////////////////////////////////////// + */ + + /** + * Main constructor. Note that id attributes can never have + * default values. + */ + public DTDEntitiesAttr(PrefixedName name, DefaultAttrValue defValue, int specIndex, + boolean nsAware, boolean xml11) + + { + super(name, defValue, specIndex, nsAware, xml11); + } + + @Override + public DTDAttribute cloneWith(int specIndex) { + return new DTDEntitiesAttr(mName, mDefValue, specIndex, mCfgNsAware, mCfgXml11); + } + + /* + /////////////////////////////////////////////////// + // Public API + /////////////////////////////////////////////////// + */ + + @Override + public int getValueType() { + return TYPE_ENTITIES; + } + + /* + /////////////////////////////////////////////////// + // Public API, validation + /////////////////////////////////////////////////// + */ + + /** + * Method called by the {@link DTDValidatorBase} + * to let the attribute do necessary normalization and/or validation + * for the value. + * + */ + @Override + public String validate(DTDValidatorBase v, char[] cbuf, int start, int end, boolean normalize) + throws XMLStreamException + { + /* Let's skip leading/trailing white space, even if we are not + * to normalize visible attribute value. This allows for better + * round-trip handling (no changes for physical value caller + * gets), but still allows succesful validation. + */ + while (start < end && WstxInputData.isSpaceChar(cbuf[start])) { + ++start; + } + + // Empty value? + if (start >= end) { + return reportValidationProblem(v, "Empty ENTITIES value"); + } + --end; // so that it now points to the last char + while (end > start && WstxInputData.isSpaceChar(cbuf[end])) { + --end; + } + + // Ok; now start points to first, last to last char (both inclusive) + String idStr = null; + StringBuilder sb = null; + + while (start <= end) { + // Ok, need to check char validity, and also calc hash code: + char c = cbuf[start]; + if (!WstxInputData.isNameStartChar(c, mCfgNsAware, mCfgXml11)) { + return reportInvalidChar(v, c, "not valid as the first ENTITIES character"); + } + int i = start+1; + for (; i <= end; ++i) { + c = cbuf[i]; + if (WstxInputData.isSpaceChar(c)) { + break; + } + if (!WstxInputData.isNameChar(c, mCfgNsAware, mCfgXml11)) { + return reportInvalidChar(v, c, "not valid as an ENTITIES character"); + } + } + + EntityDecl ent = findEntityDecl(v, cbuf, start, (i - start)); + // only returns if entity was found... + + // Can skip the trailing space char (if there was one) + start = i+1; + + /* When normalizing, we can possibly share id String, or + * alternatively, compose normalized String if multiple + */ + if (normalize) { + if (idStr == null) { // first idref + idStr = ent.getName(); + } else { + if (sb == null) { + sb = new StringBuilder(idStr); + } + idStr = ent.getName(); + sb.append(' '); + sb.append(idStr); + } + } + + // Ok, any white space to skip? + while (start <= end && WstxInputData.isSpaceChar(cbuf[start])) { + ++start; + } + } + + if (normalize) { + if (sb != null) { + idStr = sb.toString(); + } + return idStr; + } + + return null; + } + + /** + * Method called by the validator object + * to ask attribute to verify that the default it has (if any) is + * valid for such type. + */ + @Override + public void validateDefault(InputProblemReporter rep, boolean normalize) + throws XMLStreamException + { + String normStr = validateDefaultNames(rep, true); + if (normalize) { + mDefValue.setValue(normStr); + } + + // Ok, but were they declared? + + /* Performance really shouldn't be critical here (only called when + * parsing DTDs, which get cached) -- let's just + * tokenize using standard StringTokenizer + */ + StringTokenizer st = new StringTokenizer(normStr); + /* !!! 03-Dec-2004, TSa: This is rather ugly -- need to know we + * actually really get a DTD reader, and DTD reader needs + * to expose a special method... but it gets things done. + */ + MinimalDTDReader dtdr = (MinimalDTDReader) rep; + while (st.hasMoreTokens()) { + String str = st.nextToken(); + EntityDecl ent = dtdr.findEntity(str); + // Needs to exists, and be an unparsed entity... + checkEntity(rep, normStr, ent); + } + } +} diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/dtd/DTDEntityAttr.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/dtd/DTDEntityAttr.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/dtd/DTDEntityAttr.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/dtd/DTDEntityAttr.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,118 @@ +package com.ctc.wstx.dtd; + +import javax.xml.stream.XMLStreamException; + +import com.ctc.wstx.ent.EntityDecl; +import com.ctc.wstx.io.WstxInputData; +import com.ctc.wstx.sr.InputProblemReporter; +import com.ctc.wstx.util.PrefixedName; + +/** + * Specific attribute class for attributes that contain (unique) + * identifiers. + */ +public final class DTDEntityAttr + extends DTDAttribute +{ + /* + /////////////////////////////////////////////////// + // Life-cycle + /////////////////////////////////////////////////// + */ + + /** + * Main constructor. Note that id attributes can never have + * default values. + */ + public DTDEntityAttr(PrefixedName name, DefaultAttrValue defValue, int specIndex, + boolean nsAware, boolean xml11) + { + super(name, defValue, specIndex, nsAware, xml11); + } + + @Override + public DTDAttribute cloneWith(int specIndex) { + return new DTDEntityAttr(mName, mDefValue, specIndex, mCfgNsAware, mCfgXml11); + } + + /* + /////////////////////////////////////////////////// + // Public API + /////////////////////////////////////////////////// + */ + + @Override + public int getValueType() { + return TYPE_ENTITY; + } + + /* + /////////////////////////////////////////////////// + // Public API, validation + /////////////////////////////////////////////////// + */ + + /** + * Method called by the {@link DTDValidatorBase} + * to let the attribute do necessary normalization and/or validation + * for the value. + */ + @Override + public String validate(DTDValidatorBase v, char[] cbuf, int start, int end, boolean normalize) + throws XMLStreamException + { + while (start < end && WstxInputData.isSpaceChar(cbuf[start])) { + ++start; + } + + // Empty value? + if (start >= end) { + return reportValidationProblem(v, "Empty ENTITY value"); + } + --end; // so that it now points to the last char + while (end > start && WstxInputData.isSpaceChar(cbuf[end])) { + --end; + } + + // Ok, need to check char validity, and also calc hash code: + char c = cbuf[start]; + if (!WstxInputData.isNameStartChar(c, mCfgNsAware, mCfgXml11) && c != ':') { + return reportInvalidChar(v, c, "not valid as the first ID character"); + } + for (int i = start+1; i <= end; ++i) { + c = cbuf[i]; + if (!WstxInputData.isNameChar(c, mCfgNsAware, mCfgXml11)) { + return reportInvalidChar(v, c, "not valid as an ID character"); + } + } + + EntityDecl ent = findEntityDecl(v, cbuf, start, (end - start + 1)); + // only returns if it succeeded... + + return normalize ? ent.getName() : null; + } + + /** + * Method called by the validator object + * to ask attribute to verify that the default it has (if any) is + * valid for such type. + */ + @Override + public void validateDefault(InputProblemReporter rep, boolean normalize) + throws XMLStreamException + { + String normStr = validateDefaultName(rep, normalize); + if (normalize) { + mDefValue.setValue(normStr); + } + + // Ok, but was it declared? + + /* 03-Dec-2004, TSa: This is rather ugly -- need to know we + * actually really get a DTD reader, and DTD reader needs + * to expose a special method... but it gets things done. + */ + EntityDecl ent = ((MinimalDTDReader) rep).findEntity(normStr); + checkEntity(rep, normStr, ent); + } +} diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/dtd/DTDEnumAttr.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/dtd/DTDEnumAttr.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/dtd/DTDEnumAttr.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/dtd/DTDEnumAttr.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,97 @@ +package com.ctc.wstx.dtd; + +import javax.xml.stream.XMLStreamException; + +import com.ctc.wstx.sr.InputProblemReporter; +import com.ctc.wstx.util.PrefixedName; +import com.ctc.wstx.util.WordResolver; + +/** + * Specific attribute class for attributes that have enumerated values. + */ +public final class DTDEnumAttr + extends DTDAttribute +{ + final WordResolver mEnumValues; + + /* + /////////////////////////////////////////////////// + // Life-cycle + /////////////////////////////////////////////////// + */ + + public DTDEnumAttr(PrefixedName name, DefaultAttrValue defValue, + int specIndex, boolean nsAware, boolean xml11, + WordResolver enumValues) + { + super(name, defValue, specIndex, nsAware, xml11); + mEnumValues = enumValues; + } + + @Override + public DTDAttribute cloneWith(int specIndex) + { + return new DTDEnumAttr(mName, mDefValue, specIndex, mCfgNsAware, + mCfgXml11, mEnumValues); + } + + /* + /////////////////////////////////////////////////// + // Public API + /////////////////////////////////////////////////// + */ + + @Override + public int getValueType() { + return TYPE_ENUMERATED; + } + + /* + /////////////////////////////////////////////////// + // Public API, validation + /////////////////////////////////////////////////// + */ + + /** + * Method called by the validator + * to let the attribute do necessary normalization and/or validation + * for the value. + */ + @Override + public String validate(DTDValidatorBase v, char[] cbuf, int start, int end, boolean normalize) + throws XMLStreamException + { + String ok = validateEnumValue(cbuf, start, end, normalize, mEnumValues); + if (ok == null) { + String val = new String(cbuf, start, (end-start)); + return reportValidationProblem(v, "Invalid enumerated value '"+val+"': has to be one of (" + +mEnumValues+")"); + } + return ok; + } + + /** + * Method called by the validator + * to ask attribute to verify that the default it has (if any) is + * valid for such type. + */ + @Override + public void validateDefault(InputProblemReporter rep, boolean normalize) + throws XMLStreamException + { + String def = validateDefaultNmToken(rep, normalize); + + // And then that it's one of listed values: + String shared = mEnumValues.find(def); + if (shared == null) { + reportValidationProblem(rep, "Invalid default value '"+def+"': has to be one of (" + +mEnumValues+")"); + return; + } + + // Ok, cool it's ok... + if (normalize) { + mDefValue.setValue(shared); + } + } +} diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/dtd/DTDEventListener.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/dtd/DTDEventListener.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/dtd/DTDEventListener.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/dtd/DTDEventListener.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,51 @@ +/* Woodstox XML processor + * + * Copyright (c) 2004- Tatu Saloranta, tatu.saloranta@iki.fi + * + * Licensed under the License specified in file LICENSE, included with + * the source code. + * You may not use this file except in compliance with the License. + * + * 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 com.ctc.wstx.dtd; + +import java.net.URL; + +import javax.xml.stream.XMLStreamException; + +public interface DTDEventListener +{ + // Configuration + + /** + * @return True, if there is a listener interested in getting comment + * events within DTD subset (since that's optional) + */ + public boolean dtdReportComments(); + + // Basic content events + + public void dtdProcessingInstruction(String target, String data); + public void dtdComment(char[] data, int offset, int len); + public void dtdSkippedEntity(String name); + + // DTD declarations that must be exposed + public void dtdNotationDecl(String name, String publicId, String systemId, URL baseURL) + throws XMLStreamException; + + public void dtdUnparsedEntityDecl(String name, String publicId, String systemId, String notationName, URL baseURL) + throws XMLStreamException; + + // DTD declarations that can be exposed + + public void attributeDecl(String eName, String aName, String type, String mode, String value); + public void dtdElementDecl(String name, String model); + public void dtdExternalEntityDecl(String name, String publicId, String systemId); + public void dtdInternalEntityDecl(String name, String value); +} diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/dtd/DTDIdAttr.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/dtd/DTDIdAttr.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/dtd/DTDIdAttr.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/dtd/DTDIdAttr.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,136 @@ +package com.ctc.wstx.dtd; + +import javax.xml.stream.Location; +import javax.xml.stream.XMLStreamException; + +import com.ctc.wstx.cfg.ErrorConsts; +import com.ctc.wstx.io.WstxInputData; +import com.ctc.wstx.sr.InputProblemReporter; +import com.ctc.wstx.util.ElementId; +import com.ctc.wstx.util.ElementIdMap; +import com.ctc.wstx.util.PrefixedName; + +/** + * Specific attribute class for attributes that contain (unique) + * identifiers. + */ +public final class DTDIdAttr + extends DTDAttribute +{ + /* + /////////////////////////////////////////////////// + // Life-cycle + /////////////////////////////////////////////////// + */ + + /** + * Main constructor. Note that id attributes can never have + * default values. + *

+ * note: although ID attributes are not to have default value, + * this is 'only' a validity constraint, and in dtd-aware-but- + * not-validating mode it is apparently 'legal' to add default + * values. + */ + public DTDIdAttr(PrefixedName name, DefaultAttrValue defValue, int specIndex, + boolean nsAware, boolean xml11) + { + super(name, defValue, specIndex, nsAware, xml11); + } + + @Override + public DTDAttribute cloneWith(int specIndex) { + return new DTDIdAttr(mName, mDefValue, specIndex, mCfgNsAware, mCfgXml11); + } + + /* + /////////////////////////////////////////////////// + // Public API + /////////////////////////////////////////////////// + */ + + @Override + public int getValueType() { + return TYPE_ID; + } + + @Override + public boolean typeIsId() { + return true; + } + + /* + /////////////////////////////////////////////////// + // Public API, validation + /////////////////////////////////////////////////// + */ + + /** + * Method called by the validator + * to let the attribute do necessary normalization and/or validation + * for the value. + */ + @SuppressWarnings("cast") + @Override + public String validate(DTDValidatorBase v, char[] cbuf, int start, int end, boolean normalize) + throws XMLStreamException + { + // Let's trim leading white space first... + while (start < end && WstxInputData.isSpaceChar(cbuf[start])) { + ++start; + } + + // No id? + if (start >= end) { + return reportValidationProblem(v, "Empty ID value"); + } + --end; // so that it now points to the last char + while (end > start && WstxInputData.isSpaceChar(cbuf[end])) { + --end; + } + + // Ok, need to check char validity, and also calc hash code: + char c = cbuf[start]; + if (!WstxInputData.isNameStartChar(c, mCfgNsAware, mCfgXml11)) { + return reportInvalidChar(v, c, "not valid as the first ID character"); + } + int hash = (int) c; + for (int i = start+1; i <= end; ++i) { + c = cbuf[i]; + if (!WstxInputData.isNameChar(c, mCfgNsAware, mCfgXml11)) { + return reportInvalidChar(v, c, "not valid as an ID character"); + } + hash = (hash * 31) + (int) c; + } + + // Either way, we do need to validate characters, and calculate hash + ElementIdMap m = v.getIdMap(); + PrefixedName elemName = v.getElemName(); + Location loc = v.getLocation(); + ElementId id = m.addDefined(cbuf, start, (end - start + 1), hash, + loc, elemName, mName); + + // We can detect dups by checking if Location is the one we passed: + if (id.getLocation() != loc) { + return reportValidationProblem(v, "Duplicate id '"+id.getId()+"', first declared at " + +id.getLocation()); + } + + if (normalize) { + return id.getId(); + } + return null; + } + + /** + * Method called by the validator + * to ask attribute to verify that the default it has (if any) is + * valid for such type. + */ + @Override + public void validateDefault(InputProblemReporter rep, boolean normalize) + { + // Should never get called + throw new IllegalStateException(ErrorConsts.ERR_INTERNAL); + } +} diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/dtd/DTDId.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/dtd/DTDId.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/dtd/DTDId.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/dtd/DTDId.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,142 @@ +/* Woodstox XML processor + * + * Copyright (c) 2004- Tatu Saloranta, tatu.saloranta@iki.fi + * + * Licensed under the License specified in the file LICENSE which is + * included with the source code. + * You may not use this file except in compliance with the License. + * + * 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 com.ctc.wstx.dtd; + +import java.net.URI; + +/** + * Simple key object class, used for accessing (external) DTDs when stored for + * caching. Main idea is that the primary id of a DTD (public or system id; + * latter normalized if possible) + * has to match, as well as couple of on/off settings for parsing (namespace + * support, text normalization). + * Latter restriction is needed since although DTDs do not deal + * with (or understand) namespaces, some parsing is done to be able to validate + * namespace aware/non-aware documents, and handling differs between the two. + * As to primary key part, public id is used if one was defined; if so, + * comparison is String equality. If not, then system id is compared: system + * id has to be expressed as URL if so. + */ +public final class DTDId +{ + protected final String mPublicId; + + protected final URI mSystemId; + + protected final int mConfigFlags; + + protected final boolean mXml11; + + protected int mHashCode = 0; + + /* + /////////////////////////////////////////////////////////////////////// + // Life-cycle: + /////////////////////////////////////////////////////////////////////// + */ + + private DTDId(String publicId, URI systemId, int configFlags, boolean xml11) + { + mPublicId = publicId; + mSystemId = systemId; + mConfigFlags = configFlags; + mXml11 = xml11; + } + + public static DTDId constructFromPublicId(String publicId, int configFlags, + boolean xml11) + { + if (publicId == null || publicId.length() == 0) { + throw new IllegalArgumentException("Empty/null public id."); + } + return new DTDId(publicId, null, configFlags, xml11); + } + + public static DTDId constructFromSystemId(URI systemId, int configFlags, + boolean xml11) + { + if (systemId == null) { + throw new IllegalArgumentException("Null system id."); + } + return new DTDId(null, systemId, configFlags, xml11); + } + + public static DTDId construct(String publicId, URI systemId, int configFlags, boolean xml11) + { + if (publicId != null && publicId.length() > 0) { + return new DTDId(publicId, null, configFlags, xml11); + } + if (systemId == null) { + throw new IllegalArgumentException("Illegal arguments; both public and system id null/empty."); + } + return new DTDId(null, systemId, configFlags, xml11); + } + + /* + /////////////////////////////////////////////////////////////////////// + // Overridden standard methods + /////////////////////////////////////////////////////////////////////// + */ + + @Override + public int hashCode() { + int hash = mHashCode; + if (hash == 0) { + hash = mConfigFlags; + if (mPublicId != null) { + hash ^= mPublicId.hashCode(); + } else { + hash ^= mSystemId.hashCode(); + } + if (mXml11) { + hash ^= 1; + } + mHashCode = hash; + } + return hash; + } + + @Override + public String toString() { + StringBuffer sb = new StringBuffer(60); + sb.append("Public-id: "); + sb.append(mPublicId); + sb.append(", system-id: "); + sb.append(mSystemId); + sb.append(" [config flags: 0x"); + sb.append(Integer.toHexString(mConfigFlags)); + sb.append("], xml11: "); + sb.append(mXml11); + return sb.toString(); + } + + @Override + public boolean equals(Object o) + { + if (o == this) return true; + if (o == null || o.getClass() != getClass()) return false; + DTDId other = (DTDId) o; + if (other.mConfigFlags != mConfigFlags + || other.mXml11 != mXml11) { + return false; + } + if (mPublicId != null) { + String op = other.mPublicId; + return (op != null) && op.equals(mPublicId); + } + return mSystemId.equals(other.mSystemId); + } +} diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/dtd/DTDIdRefAttr.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/dtd/DTDIdRefAttr.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/dtd/DTDIdRefAttr.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/dtd/DTDIdRefAttr.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,120 @@ +package com.ctc.wstx.dtd; + +import javax.xml.stream.Location; +import javax.xml.stream.XMLStreamException; + +import com.ctc.wstx.io.WstxInputData; +import com.ctc.wstx.sr.InputProblemReporter; +import com.ctc.wstx.util.ElementId; +import com.ctc.wstx.util.ElementIdMap; +import com.ctc.wstx.util.PrefixedName; + +/** + * Attribute class for attributes that contain references + * to elements that have matching identifier specified. + */ +public final class DTDIdRefAttr + extends DTDAttribute +{ + /* + /////////////////////////////////////////////////// + // Life-cycle + /////////////////////////////////////////////////// + */ + + /** + * Main constructor. + */ + public DTDIdRefAttr(PrefixedName name, DefaultAttrValue defValue, int specIndex, + boolean nsAware, boolean xml11) + { + super(name, defValue, specIndex, nsAware, xml11); + } + + @Override + public DTDAttribute cloneWith(int specIndex) { + return new DTDIdRefAttr(mName, mDefValue, specIndex, mCfgNsAware, mCfgXml11); + } + + /* + /////////////////////////////////////////////////// + // Public API + /////////////////////////////////////////////////// + */ + + @Override + public int getValueType() { + return TYPE_IDREF; + } + + /* + /////////////////////////////////////////////////// + // Public API, validation + /////////////////////////////////////////////////// + */ + + /** + * Method called by the validator + * to let the attribute do necessary normalization and/or validation + * for the value. + */ + @SuppressWarnings("cast") + @Override + public String validate(DTDValidatorBase v, char[] cbuf, int start, int end, boolean normalize) + throws XMLStreamException + { + /* Let's skip leading/trailing white space, even if we are not + * to normalize visible attribute value. This allows for better + * round-trip handling, but still allow validation. + */ + while (start < end && WstxInputData.isSpaceChar(cbuf[start])) { + ++start; + } + + if (start >= end) { // empty (all white space) value? + return reportValidationProblem(v, "Empty IDREF value"); + } + + --end; // so that it now points to the last char + while (end > start && WstxInputData.isSpaceChar(cbuf[end])) { + --end; + } + + // Ok, need to check char validity, and also calc hash code: + char c = cbuf[start]; + if (!WstxInputData.isNameStartChar(c, mCfgNsAware, mCfgXml11)) { + return reportInvalidChar(v, c, "not valid as the first IDREF character"); + } + int hash = (int) c; + for (int i = start+1; i <= end; ++i) { + c = cbuf[i]; + if (!WstxInputData.isNameChar(c, mCfgNsAware, mCfgXml11)) { + return reportInvalidChar(v, c, "not valid as an IDREF character"); + } + hash = (hash * 31) + (int) c; + } + + // Ok, let's check and update id ref list... + ElementIdMap m = v.getIdMap(); + Location loc = v.getLocation(); + ElementId id = m.addReferenced(cbuf, start, (end - start + 1), hash, + loc, v.getElemName(), mName); + // and that's all; no more checks needed here + return normalize ? id.getId() : null; + } + + /** + * Method called by the validator + * to ask attribute to verify that the default it has (if any) is + * valid for such type. + */ + @Override + public void validateDefault(InputProblemReporter rep, boolean normalize) + throws XMLStreamException + { + String def = validateDefaultName(rep, normalize); + if (normalize) { + mDefValue.setValue(def); + } + } +} diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/dtd/DTDIdRefsAttr.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/dtd/DTDIdRefsAttr.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/dtd/DTDIdRefsAttr.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/dtd/DTDIdRefsAttr.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,162 @@ +package com.ctc.wstx.dtd; + +import javax.xml.stream.Location; +import javax.xml.stream.XMLStreamException; + +import com.ctc.wstx.io.WstxInputData; +import com.ctc.wstx.sr.InputProblemReporter; +import com.ctc.wstx.util.ElementId; +import com.ctc.wstx.util.ElementIdMap; +import com.ctc.wstx.util.PrefixedName; + +/** + * Attribute class for attributes that contain multiple references + * to elements that have matching identifier specified. + */ +public final class DTDIdRefsAttr + extends DTDAttribute +{ + /* + /////////////////////////////////////////////////// + // Life-cycle + /////////////////////////////////////////////////// + */ + + /** + * Main constructor. + */ + public DTDIdRefsAttr(PrefixedName name, DefaultAttrValue defValue, int specIndex, + boolean nsAware, boolean xml11) + { + super(name, defValue, specIndex, nsAware, xml11); + } + + @Override + public DTDAttribute cloneWith(int specIndex) { + return new DTDIdRefsAttr(mName, mDefValue, specIndex, mCfgNsAware, mCfgXml11); + } + + /* + /////////////////////////////////////////////////// + // Public API + /////////////////////////////////////////////////// + */ + + @Override + public int getValueType() { + return TYPE_IDREFS; + } + + /* + /////////////////////////////////////////////////// + // Public API, validation + /////////////////////////////////////////////////// + */ + + @SuppressWarnings("cast") + @Override + public String validate(DTDValidatorBase v, char[] cbuf, int start, int end, boolean normalize) + throws XMLStreamException + { + /* Let's skip leading/trailing white space, even if we are not + * to normalize visible attribute value. This allows for better + * round-trip handling (no changes for physical value caller + * gets), but still allows succesful validation. + */ + while (start < end && WstxInputData.isSpaceChar(cbuf[start])) { + ++start; + } + + // No id? + if (start >= end) { + return reportValidationProblem(v, "Empty IDREFS value"); + } + + --end; // so that it now points to the last char + // We now the first char is not a space by now... + while (end > start && WstxInputData.isSpaceChar(cbuf[end])) { + --end; + } + + // Ok; now start points to first, end to last char (both inclusive) + ElementIdMap m = v.getIdMap(); + Location loc = v.getLocation(); + + String idStr = null; + StringBuilder sb = null; + while (start <= end) { + // Ok, need to check char validity, and also calc hash code: + char c = cbuf[start]; + if (!WstxInputData.isNameStartChar(c, mCfgNsAware, mCfgXml11)) { + return reportInvalidChar(v, c, "not valid as the first IDREFS character"); + } + int hash = (int) c; + int i = start+1; + for (; i <= end; ++i) { + c = cbuf[i]; + if (WstxInputData.isSpaceChar(c)) { + break; + } + if (!WstxInputData.isNameChar(c, mCfgNsAware, mCfgXml11)) { + return reportInvalidChar(v, c, "not valid as an IDREFS character"); + } + hash = (hash * 31) + (int) c; + } + + // Ok, got the next id ref... + ElementId id = m.addReferenced(cbuf, start, i - start, hash, + loc, v.getElemName(), mName); + + // Can skip the trailing space char (if there was one) + start = i+1; + + /* When normalizing, we can possibly share id String, or + * alternatively, compose normalized String if multiple + */ + if (normalize) { + if (idStr == null) { // first idref + idStr = id.getId(); + } else { + if (sb == null) { + sb = new StringBuilder(idStr); + } + idStr = id.getId(); + sb.append(' '); + sb.append(idStr); + } + } + + // Ok, any white space to skip? + while (start <= end && WstxInputData.isSpaceChar(cbuf[start])) { + ++start; + } + } + + if (normalize) { + if (sb != null) { + idStr = sb.toString(); + } + return idStr; + } + + return null; + } + + /** + * Method called by the validator + * to ask attribute to verify that the default it has (if any) is + * valid for such type. + *

+ * It's unlikely there will be default values... but just in case, + * let's implement it properly. + */ + @Override + public void validateDefault(InputProblemReporter rep, boolean normalize) + throws XMLStreamException + { + String def = validateDefaultNames(rep, normalize); + if (normalize) { + mDefValue.setValue(def); + } + } +} diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/dtd/DTDNmTokenAttr.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/dtd/DTDNmTokenAttr.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/dtd/DTDNmTokenAttr.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/dtd/DTDNmTokenAttr.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,112 @@ +package com.ctc.wstx.dtd; + +import javax.xml.stream.XMLStreamException; + +import com.ctc.wstx.io.WstxInputData; +import com.ctc.wstx.sr.InputProblemReporter; +import com.ctc.wstx.util.PrefixedName; + +/** + * Specific attribute class for attributes that contain (unique) + * identifiers. + */ +public final class DTDNmTokenAttr + extends DTDAttribute +{ + /* + /////////////////////////////////////////////////// + // Life-cycle + /////////////////////////////////////////////////// + */ + + /** + * Main constructor. + */ + public DTDNmTokenAttr(PrefixedName name, DefaultAttrValue defValue, int specIndex, + boolean nsAware, boolean xml11) + { + super(name, defValue, specIndex, nsAware, xml11); + } + + @Override + public DTDAttribute cloneWith(int specIndex) + { + return new DTDNmTokenAttr(mName, mDefValue, specIndex, mCfgNsAware, mCfgXml11); + } + + /* + /////////////////////////////////////////////////// + // Public API + /////////////////////////////////////////////////// + */ + + @Override + public int getValueType() { + return TYPE_NMTOKEN; + } + + /* + /////////////////////////////////////////////////// + // Public API, validation + /////////////////////////////////////////////////// + */ + + /** + * Method called by the validator + * to let the attribute do necessary normalization and/or validation + * for the value. + */ + @Override + public String validate(DTDValidatorBase v, char[] cbuf, int start, int end, boolean normalize) + throws XMLStreamException + { + int origLen = end-start; + + // Let's trim leading white space first... + while (start < end && WstxInputData.isSpaceChar(cbuf[start])) { + ++start; + } + + // Empty value? + if (start >= end) { + return reportValidationProblem(v, "Empty NMTOKEN value"); + } + + --end; // so that it now points to the last char + while (end > start && WstxInputData.isSpaceChar(cbuf[end])) { + --end; + } + + // Ok, need to check char validity + for (int i = start; i <= end; ++i) { + char c = cbuf[i]; + if (!WstxInputData.isNameChar(c, mCfgNsAware, mCfgXml11)) { + return reportInvalidChar(v, c, "not valid NMTOKEN character"); + } + } + + if (normalize) { + // Let's only create the String if we trimmed something + int len = (end - start)+1; + if (len != origLen) { + return new String(cbuf, start, len); + } + } + return null; + } + + /** + * Method called by the validator + * to ask attribute to verify that the default it has (if any) is + * valid for such type. + */ + @Override + public void validateDefault(InputProblemReporter rep, boolean normalize) + throws XMLStreamException + { + String def = validateDefaultNmToken(rep, normalize); + if (normalize) { + mDefValue.setValue(def); + } + } +} diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/dtd/DTDNmTokensAttr.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/dtd/DTDNmTokensAttr.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/dtd/DTDNmTokensAttr.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/dtd/DTDNmTokensAttr.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,208 @@ +package com.ctc.wstx.dtd; + +import javax.xml.stream.XMLStreamException; + +import com.ctc.wstx.io.WstxInputData; +import com.ctc.wstx.sr.InputProblemReporter; +import com.ctc.wstx.util.PrefixedName; + +/** + * Specific attribute class for attributes that contain (unique) + * identifiers. + */ +public final class DTDNmTokensAttr + extends DTDAttribute +{ + /* + /////////////////////////////////////////////////// + // Life-cycle + /////////////////////////////////////////////////// + */ + + /** + * Main constructor. + */ + public DTDNmTokensAttr(PrefixedName name, DefaultAttrValue defValue, int specIndex, + boolean nsAware, boolean xml11) + { + super(name, defValue, specIndex, nsAware, xml11); + } + + @Override + public DTDAttribute cloneWith(int specIndex) { + return new DTDNmTokensAttr(mName, mDefValue, specIndex, mCfgNsAware, mCfgXml11); + } + + /* + /////////////////////////////////////////////////// + // Public API + /////////////////////////////////////////////////// + */ + + @Override + public int getValueType() { + return TYPE_NMTOKENS; + } + + /* + /////////////////////////////////////////////////// + // Public API, validation + /////////////////////////////////////////////////// + */ + + /** + * Method called by the validator + * to let the attribute do necessary normalization and/or validation + * for the value. + */ + @Override + public String validate(DTDValidatorBase v, char[] cbuf, int start, int end, boolean normalize) + throws XMLStreamException + { + //int origStart = start; + + /* First things first; let's ensure value is not empty (all + * white space)... + */ + while (start < end && WstxInputData.isSpaceChar(cbuf[start])) { + ++start; + } + // Empty value? + if (start >= end) { + return reportValidationProblem(v, "Empty NMTOKENS value"); + } + + /* Then, let's have separate handling for normalizing and + * non-normalizing case, since latter is trivially easy case: + */ + if (!normalize) { + for (; start < end; ++start) { + char c = cbuf[start]; + if (!WstxInputData.isSpaceChar(c) + && !WstxInputData.isNameChar(c, mCfgNsAware, mCfgXml11)) { + return reportInvalidChar(v, c, "not valid as NMTOKENS character"); + } + } + return null; // ok, all good + } + + //boolean trimmed = (origStart != start); + //origStart = start; + + --end; // so that it now points to the last char + // Wouldn't absolutely have to trim trailing... but is easy to do + while (end > start && WstxInputData.isSpaceChar(cbuf[end])) { + --end; + //trimmed = true; + } + + /* Ok, now, need to check we only have valid chars, and maybe + * also coalesce multiple spaces, if any. + */ + StringBuilder sb = null; + + while (start <= end) { + int i = start; + for (; i <= end; ++i) { + char c = cbuf[i]; + if (WstxInputData.isSpaceChar(c)) { + break; + } + if (!WstxInputData.isNameChar(c, mCfgNsAware, mCfgXml11)) { + return reportInvalidChar(v, c, "not valid as an NMTOKENS character"); + } + } + + if (sb == null) { + sb = new StringBuilder(end - start + 1); + } else { + sb.append(' '); + } + sb.append(cbuf, start, (i - start)); + + start = i + 1; + // Ok, any white space to skip? + while (start <= end && WstxInputData.isSpaceChar(cbuf[start])) { + ++start; + } + } + + /* 27-Nov-2005, TSa: Could actually optimize trimming, and often + * avoid using StringBuilder... but let's only do it if it turns + * out dealing with NMTOKENS normalization shows up on profiling... + */ + return sb.toString(); + } + + /** + * Method called by the validator + * to ask attribute to verify that the default it has (if any) is + * valid for such type. + */ + @Override + public void validateDefault(InputProblemReporter rep, boolean normalize) + throws XMLStreamException + { + String defValue = mDefValue.getValue(); + int len = defValue.length(); + + // Then code similar to actual value validation: + StringBuilder sb = null; + int count = 0; + int start = 0; + + main_loop: + while (start < len) { + char c = defValue.charAt(start); + + // Ok, any white space to skip? + while (true) { + if (!WstxInputData.isSpaceChar(c)) { + break; + } + if (++start >= len) { + break main_loop; + } + c = defValue.charAt(start); + } + + int i = start+1; + + do { + if (++i >= len) { + break; + } + c = defValue.charAt(i); + } while (!WstxInputData.isSpaceChar(c)); + ++count; + String token = defValue.substring(start, i); + int illegalIx = WstxInputData.findIllegalNmtokenChar(token, mCfgNsAware, mCfgXml11); + if (illegalIx >= 0) { + reportValidationProblem(rep, "Invalid default value '"+defValue + +"'; character #"+illegalIx+" (" + +WstxInputData.getCharDesc(defValue.charAt(illegalIx)) + +") not a valid NMTOKENS character"); + } + + if (normalize) { + if (sb == null) { + sb = new StringBuilder(i - start + 32); + } else { + sb.append(' '); + } + sb.append(token); + } + start = i+1; + } + + if (count == 0) { + reportValidationProblem(rep, "Invalid default value '"+defValue + +"'; empty String is not a valid NMTOKENS value"); + return; + } + + if (normalize) { + mDefValue.setValue(sb.toString()); + } + } +} diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/dtd/DTDNotationAttr.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/dtd/DTDNotationAttr.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/dtd/DTDNotationAttr.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/dtd/DTDNotationAttr.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,105 @@ +package com.ctc.wstx.dtd; + +import javax.xml.stream.XMLStreamException; + +import com.ctc.wstx.sr.InputProblemReporter; +import com.ctc.wstx.util.PrefixedName; +import com.ctc.wstx.util.WordResolver; + +/** + * Specific attribute class for attributes that are of NOTATION type, + * and also contain enumerated set of legal values. + */ +public final class DTDNotationAttr + extends DTDAttribute +{ + final WordResolver mEnumValues; + + /* + /////////////////////////////////////////////////// + // Life-cycle + /////////////////////////////////////////////////// + */ + + public DTDNotationAttr(PrefixedName name, DefaultAttrValue defValue, + int specIndex, boolean nsAware, boolean xml11, + WordResolver enumValues) + { + super(name, defValue, specIndex, nsAware, xml11); + mEnumValues = enumValues; + } + + @Override + public DTDAttribute cloneWith(int specIndex) + { + return new DTDNotationAttr(mName, mDefValue, specIndex, + mCfgNsAware, mCfgXml11, mEnumValues); + } + + /* + /////////////////////////////////////////////////// + // Public API + /////////////////////////////////////////////////// + */ + + @Override + public int getValueType() { + return TYPE_NOTATION; + } + + @Override + public boolean typeIsNotation() { + return true; + } + + /* + /////////////////////////////////////////////////// + // Public API, validation + /////////////////////////////////////////////////// + */ + + /** + * Method called by the validator + * to let the attribute do necessary normalization and/or validation + * for the value. + *

+ * Note: identical to the implementation in {@link DTDEnumAttr} + */ + @Override + public String validate(DTDValidatorBase v, char[] cbuf, int start, int end, boolean normalize) + throws XMLStreamException + { + String ok = validateEnumValue(cbuf, start, end, normalize, mEnumValues); + if (ok == null) { + String val = new String(cbuf, start, (end-start)); + return reportValidationProblem(v, "Invalid notation value '"+val+"': has to be one of (" + +mEnumValues+")"); + } + return ok; + } + + /** + * Method called by the validator + * to ask attribute to verify that the default it has (if any) is + * valid for such type. + */ + @Override + public void validateDefault(InputProblemReporter rep, boolean normalize) + throws XMLStreamException + { + // First, basic checks that it's a valid non-empty name: + String def = validateDefaultName(rep, normalize); + + // And then that it's one of listed values: + String shared = mEnumValues.find(def); + if (shared == null) { + reportValidationProblem(rep, "Invalid default value '"+def+"': has to be one of (" + +mEnumValues+")"); + } + + // Ok, cool it's ok... + if (normalize) { + mDefValue.setValue(shared); + } + } +} diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/dtd/DTDSchemaFactory.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/dtd/DTDSchemaFactory.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/dtd/DTDSchemaFactory.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/dtd/DTDSchemaFactory.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,204 @@ +/* Woodstox XML processor + * + * Copyright (c) 2004- Tatu Saloranta, tatu.saloranta@iki.fi + * + * Licensed under the License specified in the file LICENSE which is + * included with the source code. + * You may not use this file except in compliance with the License. + * + * 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 com.ctc.wstx.dtd; + +import java.io.*; +import java.net.URL; + +import javax.xml.stream.*; + +import org.codehaus.stax2.validation.*; + +import com.ctc.wstx.api.ReaderConfig; +import com.ctc.wstx.api.ValidatorConfig; +import com.ctc.wstx.cfg.XmlConsts; +import com.ctc.wstx.exc.WstxIOException; +import com.ctc.wstx.io.*; +import com.ctc.wstx.util.DefaultXmlSymbolTable; +import com.ctc.wstx.util.SymbolTable; +import com.ctc.wstx.util.URLUtil; + +/** + * Factory for creating DTD validator schema objects (shareable stateless + * "blueprints" for creating actual validators). + *

+ * Due to close coupling of XML and DTD, some of the functionality + * implemented (like that of reading internal subsets embedded in XML + * documents) is only accessible by core Woodstox. The externally + * accessible + */ +public class DTDSchemaFactory + extends XMLValidationSchemaFactory +{ + /* + ///////////////////////////////////////////////////// + // Objects shared by actual parsers + ///////////////////////////////////////////////////// + */ + + /** + * 'Root' symbol table, used for creating actual symbol table instances, + * but never as is. + */ + final static SymbolTable mRootSymbols = DefaultXmlSymbolTable.getInstance(); + static { + mRootSymbols.setInternStrings(true); + } + + /** + * Current configurations for this factory + */ + protected final ValidatorConfig mSchemaConfig; + + /** + * This configuration object is used (instead of a more specific one) + * since the actual DTD reader uses such configuration object. + */ + protected final ReaderConfig mReaderConfig; + + public DTDSchemaFactory() + { + super(XMLValidationSchema.SCHEMA_ID_DTD); + mReaderConfig = ReaderConfig.createFullDefaults(); + mSchemaConfig = ValidatorConfig.createDefaults(); + } + + /* + //////////////////////////////////////////////////////////// + // Stax2, Configuration methods + //////////////////////////////////////////////////////////// + */ + + @Override + public boolean isPropertySupported(String propName) { + return mSchemaConfig.isPropertySupported(propName); + } + + @Override + public boolean setProperty(String propName, Object value) { + return mSchemaConfig.setProperty(propName, value); + } + + @Override + public Object getProperty(String propName) { + return mSchemaConfig.getProperty(propName); + } + + /* + //////////////////////////////////////////////////////////// + // Stax2, Factory methods + //////////////////////////////////////////////////////////// + */ + + @Override + public XMLValidationSchema createSchema(InputStream in, String encoding, + String publicId, String systemId) + throws XMLStreamException + { + ReaderConfig rcfg = createPrivateReaderConfig(); + return doCreateSchema(rcfg, StreamBootstrapper.getInstance + (publicId, SystemId.construct(systemId), in), publicId, systemId, null); + } + + @Override + public XMLValidationSchema createSchema(Reader r, + String publicId, String systemId) + throws XMLStreamException + { + ReaderConfig rcfg = createPrivateReaderConfig(); + return doCreateSchema(rcfg, ReaderBootstrapper.getInstance + (publicId, SystemId.construct(systemId), r, null), publicId, systemId, null); + } + + @SuppressWarnings("resource") + @Override + public XMLValidationSchema createSchema(URL url) + throws XMLStreamException + { + ReaderConfig rcfg = createPrivateReaderConfig(); + try { + InputStream in = URLUtil.inputStreamFromURL(url); + return doCreateSchema(rcfg, StreamBootstrapper.getInstance + (null, null, in), + null, url.toExternalForm(), url); + } catch (IOException ioe) { + throw new WstxIOException(ioe); + } + } + + @SuppressWarnings("resource") + @Override + public XMLValidationSchema createSchema(File f) + throws XMLStreamException + { + ReaderConfig rcfg = createPrivateReaderConfig(); + try { + URL url = URLUtil.toURL(f); + return doCreateSchema(rcfg, StreamBootstrapper.getInstance + (null, null, new FileInputStream(f)), + null, url.toExternalForm(), url); + } catch (IOException ioe) { + throw new WstxIOException(ioe); + } + } + + /* + //////////////////////////////////////////////////////////// + // Internal methods + //////////////////////////////////////////////////////////// + */ + + /** + * The main validator construction method, called by all externally + * visible methods. + */ + @SuppressWarnings("resource") + protected XMLValidationSchema doCreateSchema + (ReaderConfig rcfg, InputBootstrapper bs, String publicId, String systemIdStr, URL ctxt) + throws XMLStreamException + { + try { + Reader r = bs.bootstrapInput(rcfg, false, XmlConsts.XML_V_UNKNOWN); + if (bs.declaredXml11()) { + rcfg.enableXml11(true); + } + if (ctxt == null) { // this is just needed as context for param entity expansion + ctxt = URLUtil.urlFromCurrentDir(); + } + /* Note: need to pass unknown for 'xmlVersion' here (as well as + * above for bootstrapping), since this is assumed to be the main + * level parsed document and no xml version compatibility checks + * should be done. + */ + SystemId systemId = SystemId.construct(systemIdStr, ctxt); + WstxInputSource src = InputSourceFactory.constructEntitySource + (rcfg, null, null, bs, publicId, systemId, XmlConsts.XML_V_UNKNOWN, r); + + /* true -> yes, fully construct for validation + * (does not mean it has to be used for validation, but required + * if it is to be used for that purpose) + */ + return FullDTDReader.readExternalSubset(src, rcfg, /*int.subset*/null, true, bs.getDeclaredVersion()); + } catch (IOException ioe) { + throw new WstxIOException(ioe); + } + } + + private ReaderConfig createPrivateReaderConfig() + { + return mReaderConfig.createNonShared(mRootSymbols.makeChild()); + } +} diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/dtd/DTDSubsetImpl.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/dtd/DTDSubsetImpl.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/dtd/DTDSubsetImpl.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/dtd/DTDSubsetImpl.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,531 @@ +/* Woodstox XML processor + * + * Copyright (c) 2004- Tatu Saloranta, tatu.saloranta@iki.fi + * + * Licensed under the License specified in file LICENSE, included with + * the source code. + * You may not use this file except in compliance with the License. + * + * 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 com.ctc.wstx.dtd; + +import java.text.MessageFormat; +import java.util.*; + +import javax.xml.stream.Location; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.events.NotationDeclaration; + +import org.codehaus.stax2.validation.*; + +import com.ctc.wstx.cfg.ErrorConsts; +import com.ctc.wstx.ent.EntityDecl; +import com.ctc.wstx.exc.WstxParsingException; +import com.ctc.wstx.sr.InputProblemReporter; +import com.ctc.wstx.util.DataUtil; +import com.ctc.wstx.util.PrefixedName; + +/** + * The default implementation of {@link DTDSubset} + */ +public final class DTDSubsetImpl + extends DTDSubset +{ + /** + * Whether this subset is cachable. Only those external + * subsets that do not refer to PEs defined by internal subsets (or + * GEs via default attribute value expansion) are cachable. + */ + final boolean mIsCachable; + + /** + * Whether this subset has full validation information; and + * consequently whether it will do actual validation, or just allow + * access to type information, notations, entities, and add default + * attribute values. + */ + final boolean mFullyValidating; + + /** + * Flag that indicates whether any of the elements declarared + * has any attribute default values for namespace pseudo-attributes. + */ + final boolean mHasNsDefaults; + + /* + ////////////////////////////////////////////////////// + // Entity information + ////////////////////////////////////////////////////// + */ + + /** + * Map (name-to-EntityDecl) of general entity declarations (internal, + * external) for this DTD subset. + */ + final HashMap mGeneralEntities; + + /** + * Lazily instantiated List that contains all notations from + * {@link #mGeneralEntities} (preferably in their declaration order; depends + * on whether platform, ie. JDK version, has insertion-ordered + * Maps available), used by DTD event Objects. + */ + volatile transient List mGeneralEntityList = null; + + /** + * Set of names of general entities references by this subset. Note that + * only those GEs that are referenced by default attribute value + * definitions count, since GEs in text content are only expanded + * when reading documents, but attribute default values are expanded + * when reading DTD subset itself. + *

+ * Needed + * for determinining if external subset materially depends on definitions + * from internal subset; if so, such subset is not cachable. + * This also + * means that information is not stored for non-cachable instance. + */ + final Set mRefdGEs; + + // // // Parameter entity info: + + /** + * Map (name-to-WEntityDeclaration) that contains all parameter entities + * defined by this subset. May be empty if such information will not be + * needed for use; for example, external subset's definitions are needed, + * nor are combined DTD set's. + */ + final HashMap mDefinedPEs; + + /** + * Set of names of parameter entities references by this subset. Needed + * when determinining if external subset materially depends on definitions + * from internal subset, which is needed to know when caching external + * subsets. + *

+ * Needed + * for determinining if external subset materially depends on definitions + * from internal subset; if so, such subset is not cachable. + * This also + * means that information is not stored for non-cachable instance. + */ + final Set mRefdPEs; + + /* + ////////////////////////////////////////////////////// + // Notation definitions: + ////////////////////////////////////////////////////// + */ + + /** + * Map (name-to-NotationDecl) that this subset has defined. + */ + final HashMap mNotations; + + /** + * Lazily instantiated List that contains all notations from + * {@link #mNotations} (preferably in their declaration order; depends + * on whether platform, ie. JDK version, has insertion-ordered + * Maps available), used by DTD event Objects. + */ + transient List mNotationList = null; + + + /* + ////////////////////////////////////////////////////// + // Element definitions: + ////////////////////////////////////////////////////// + */ + + final HashMap mElements; + + /* + ////////////////////////////////////////////////////// + // Life-cycle + ////////////////////////////////////////////////////// + */ + + private DTDSubsetImpl(boolean cachable, + HashMap genEnt, Set refdGEs, + HashMap paramEnt, Set peRefs, + HashMap notations, HashMap elements, + boolean fullyValidating) + { + mIsCachable = cachable; + mGeneralEntities = genEnt; + mRefdGEs = refdGEs; + mDefinedPEs = paramEnt; + mRefdPEs = peRefs; + mNotations = notations; + mElements = elements; + mFullyValidating = fullyValidating; + + boolean anyNsDefs = false; + if (elements != null) { + for (DTDElement elem : elements.values()) { + if (elem.hasNsDefaults()) { + anyNsDefs = true; + break; + } + } + } + mHasNsDefaults = anyNsDefs; + } + + public static DTDSubsetImpl constructInstance(boolean cachable, + HashMap genEnt, Set refdGEs, + HashMap paramEnt, Set refdPEs, + HashMap notations, + HashMap elements, + boolean fullyValidating) + { + return new DTDSubsetImpl(cachable, genEnt, refdGEs, + paramEnt, refdPEs, + notations, elements, + fullyValidating); + } + + /** + * Method that will combine definitions from internal and external subsets, + * producing a single DTD set. + */ + @Override + public DTDSubset combineWithExternalSubset(InputProblemReporter rep, DTDSubset extSubset) + throws XMLStreamException + { + /* First let's see if we can just reuse GE Map used by int or ext + * subset; (if only one has contents), or if not, combine them. + */ + HashMap ge1 = getGeneralEntityMap(); + HashMap ge2 = extSubset.getGeneralEntityMap(); + if (ge1 == null || ge1.isEmpty()) { + ge1 = ge2; + } else { + if (ge2 != null && !ge2.isEmpty()) { + /* Internal subset Objects are never shared or reused (and by + * extension, neither are objects they contain), so we can just + * modify GE map if necessary + */ + combineMaps(ge1, ge2); + } + } + + // Ok, then, let's combine notations similarly + HashMap n1 = getNotationMap(); + HashMap n2 = extSubset.getNotationMap(); + if (n1 == null || n1.isEmpty()) { + n1 = n2; + } else { + if (n2 != null && !n2.isEmpty()) { + /* First; let's make sure there are no colliding notation + * definitions: it's an error to try to redefine notations. + */ + checkNotations(n1, n2); + + /* Internal subset Objects are never shared or reused (and by + * extension, neither are objects they contain), so we can just + * modify notation map if necessary + */ + combineMaps(n1, n2); + } + } + + + // And finally elements, rather similarly: + HashMap e1 = getElementMap(); + HashMap e2 = extSubset.getElementMap(); + if (e1 == null || e1.isEmpty()) { + e1 = e2; + } else { + if (e2 != null && !e2.isEmpty()) { + /* Internal subset Objects are never shared or reused (and by + * extension, neither are objects they contain), so we can just + * modify element map if necessary + */ + combineElements(rep, e1, e2); + } + } + + /* Combos are not cachable, and because of that, there's no point + * in storing any PE info either. + */ + return constructInstance(false, ge1, null, null, null, n1, e1, + mFullyValidating); + } + + /* + ////////////////////////////////////////////////////// + // XMLValidationSchema implementation + ////////////////////////////////////////////////////// + */ + + @Override + public XMLValidator createValidator(ValidationContext ctxt) + throws XMLStreamException + { + if (mFullyValidating) { + return new DTDValidator(this, ctxt, mHasNsDefaults, + getElementMap(), getGeneralEntityMap()); + } + return new DTDTypingNonValidator(this, ctxt, mHasNsDefaults, + getElementMap(), getGeneralEntityMap()); + + } + + /* + ////////////////////////////////////////////////////// + // DTDValidationSchema implementation + ////////////////////////////////////////////////////// + */ + + @Override + public int getEntityCount() { + return (mGeneralEntities == null) ? 0 : mGeneralEntities.size(); + } + + @Override + public int getNotationCount() { + return (mNotations == null) ? 0 : mNotations.size(); + } + + /* + ////////////////////////////////////////////////////// + // Woodstox-specific public API + ////////////////////////////////////////////////////// + */ + + @Override + public boolean isCachable() { + return mIsCachable; + } + + @Override + public HashMap getGeneralEntityMap() { + return mGeneralEntities; + } + + @Override + public List getGeneralEntityList() + { + List l = mGeneralEntityList; + if (l == null) { + if (mGeneralEntities == null || mGeneralEntities.size() == 0) { + l = Collections.emptyList(); + } else { + l = Collections.unmodifiableList(new ArrayList(mGeneralEntities.values())); + } + mGeneralEntityList = l; + } + + return l; + } + + @Override + public HashMap getParameterEntityMap() { + return mDefinedPEs; + } + + @Override + public HashMap getNotationMap() { + return mNotations; + } + + @Override + public synchronized List getNotationList() + { + List l = mNotationList; + if (l == null) { + if (mNotations == null || mNotations.size() == 0) { + l = Collections.emptyList(); + } else { + l = Collections.unmodifiableList(new ArrayList(mNotations.values())); + } + mNotationList = l; + } + + return l; + } + + @Override + public HashMap getElementMap() { + return mElements; + } + + /** + * Method used in determining whether cached external subset instance + * can be used with specified internal subset. If ext. subset references + * any parameter/general entities int subset (re-)defines, it can not; + * otherwise it can be used. + * + * @return True if this (external) subset refers to a parameter entity + * defined in passed-in internal subset. + */ + @Override + public boolean isReusableWith(DTDSubset intSubset) + { + Set refdPEs = mRefdPEs; + + if (refdPEs != null && refdPEs.size() > 0) { + HashMap intPEs = intSubset.getParameterEntityMap(); + if (intPEs != null && intPEs.size() > 0) { + if (DataUtil.anyValuesInCommon(refdPEs, intPEs.keySet())) { + return false; + } + } + } + Set refdGEs = mRefdGEs; + + if (refdGEs != null && refdGEs.size() > 0) { + HashMap intGEs = intSubset.getGeneralEntityMap(); + if (intGEs != null && intGEs.size() > 0) { + if (DataUtil.anyValuesInCommon(refdGEs, intGEs.keySet())) { + return false; + } + } + } + return true; // yep, no dependencies overridden + } + + /* + ////////////////////////////////////////////////////// + // Overridden default methods: + ////////////////////////////////////////////////////// + */ + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("[DTDSubset: "); + int count = getEntityCount(); + sb.append(count); + sb.append(" general entities"); + sb.append(']'); + return sb.toString(); + } + + /* + ////////////////////////////////////////////////////// + // Convenience methods used by other classes + ////////////////////////////////////////////////////// + */ + + public static void throwNotationException(NotationDeclaration oldDecl, NotationDeclaration newDecl) + throws XMLStreamException + { + throw new WstxParsingException + (MessageFormat.format(ErrorConsts.ERR_DTD_NOTATION_REDEFD, + new Object[] { + newDecl.getName(), + oldDecl.getLocation().toString()}), + newDecl.getLocation()); + } + + public static void throwElementException(DTDElement oldElem, Location loc) + throws XMLStreamException + { + throw new WstxParsingException + (MessageFormat.format(ErrorConsts.ERR_DTD_ELEM_REDEFD, + new Object[] { + oldElem.getDisplayName(), + oldElem.getLocation().toString() }), + loc); + } + + /* + ////////////////////////////////////////////////////// + // Internal methods + ////////////////////////////////////////////////////// + */ + + /** + *

+ * Note: The first Map argument WILL be modified; second one + * not. Caller needs to ensure this is acceptable. + */ + private static void combineMaps(Map m1, Map m2) + { + for (Map.Entry me : m2.entrySet()) { + K key = me.getKey(); + /* Int. subset has precedence, but let's guess most of + * the time there are no collisions: + */ + V old = m1.put(key, me.getValue()); + // Oops, got value! Let's put it back + if (old != null) { + m1.put(key, old); + } + } + } + + /** + * Method that will try to merge in elements defined in the external + * subset, into internal subset; it will also check for redeclarations + * when doing this, as it's invalid to redeclare elements. Care has to + * be taken to only check actual redeclarations: placeholders should + * not cause problems. + */ + private void combineElements(InputProblemReporter rep, HashMap intElems, HashMap extElems) + throws XMLStreamException + { + for (Map.Entry me : extElems.entrySet()) { + PrefixedName key = me.getKey(); + DTDElement extElem = me.getValue(); + DTDElement intElem = intElems.get(key); + + // If there was no old value, can just merge new one in and continue + if (intElem == null) { + intElems.put(key, extElem); + continue; + } + + // Which one is defined (if either)? + if (extElem.isDefined()) { // one from the ext subset + if (intElem.isDefined()) { // but both can't be; that's an error + throwElementException(intElem, extElem.getLocation()); + } else { + /* Note: can/should not modify the external element (by + * for example adding attributes); external element may + * be cached and shared... so, need to do the reverse, + * define the one from internal subset. + */ + intElem.defineFrom(rep, extElem, mFullyValidating); + } + } else { + if (!intElem.isDefined()) { + /* ??? Should we warn about neither of them being really + * declared? + */ + rep.reportProblem(intElem.getLocation(), + ErrorConsts.WT_ENT_DECL, + ErrorConsts.W_UNDEFINED_ELEM, + extElem.getDisplayName(), null); + + } else { + intElem.mergeMissingAttributesFrom(rep, extElem, mFullyValidating); + } + } + } + } + + private static void checkNotations(HashMap fromInt, HashMap fromExt) + throws XMLStreamException + { + /* Since it's external subset that would try to redefine things + * defined in internal subset, let's traverse definitions in + * the ext. subset first (even though that may not be the fastest + * way), so that we have a chance of catching the first problem + * (As long as Maps iterate in insertion order). + */ + for (Map.Entry en : fromExt.entrySet()) { + if (fromInt.containsKey(en.getKey())) { + throwNotationException(fromInt.get(en.getKey()), en.getValue()); + } + } + } +} diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/dtd/DTDSubset.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/dtd/DTDSubset.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/dtd/DTDSubset.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/dtd/DTDSubset.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,122 @@ +/* Woodstox XML processor + * + * Copyright (c) 2004- Tatu Saloranta, tatu.saloranta@iki.fi + * + * Licensed under the License specified in the file LICENSE which is + * included with the source code. + * You may not use this file except in compliance with the License. + * + * 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 com.ctc.wstx.dtd; + +import java.util.*; + +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.events.NotationDeclaration; + +import org.codehaus.stax2.validation.*; + +import com.ctc.wstx.ent.EntityDecl; +import com.ctc.wstx.sr.InputProblemReporter; +import com.ctc.wstx.util.PrefixedName; + +/** + * This is the abstract base class that implements the standard Stax2 + * validation schema base class ({@link XMLValidationSchema}, as well + * as specifies extended Woodstox-specific interface for accessing + * DTD-specific things like entity expansions and notation properties. + *

+ * API is separated from its implementation to reduce coupling; for example, + * it is possible to have DTD subset implementations that do not implement + * validation logics, just entity expansion. + */ +public abstract class DTDSubset + implements DTDValidationSchema +{ + /* + ////////////////////////////////////////////////////// + // Life-cycle + ////////////////////////////////////////////////////// + */ + + protected DTDSubset() { } + + /** + * Method that will combine definitions from this internal subset with + * definitions from passed-in external subset, producing a new combined + * DTDSubset instance. + */ + public abstract DTDSubset combineWithExternalSubset(InputProblemReporter rep, + DTDSubset extSubset) + throws XMLStreamException; + + /* + ////////////////////////////////////////////////////// + // XMLValidationSchema implementation + ////////////////////////////////////////////////////// + */ + + @Override + public abstract XMLValidator createValidator(ValidationContext ctxt) + throws XMLStreamException; + + @Override + public String getSchemaType() { + return XMLValidationSchema.SCHEMA_ID_DTD; + } + + /* + ////////////////////////////////////////////////////// + // And extended DTDValidationSchema + ////////////////////////////////////////////////////// + */ + + @Override + public abstract int getEntityCount(); + + @Override + public abstract int getNotationCount(); + + /* + ////////////////////////////////////////////////////// + // Woodstox-specific API, caching support + ////////////////////////////////////////////////////// + */ + + public abstract boolean isCachable(); + + /** + * Method used in determining whether cached external subset instance + * can be used with specified internal subset. If ext. subset references + * any parameter entities int subset (re-)defines, it can not; otherwise + * it can be used. + * + * @return True if this (external) subset refers to a parameter entity + * defined in passed-in internal subset. + */ + public abstract boolean isReusableWith(DTDSubset intSubset); + + /* + ////////////////////////////////////////////////////// + // Woodstox-specific API, entity/notation handling + ////////////////////////////////////////////////////// + */ + + public abstract HashMap getGeneralEntityMap(); + + public abstract List getGeneralEntityList(); + + public abstract HashMap getParameterEntityMap(); + + public abstract HashMap getNotationMap(); + + public abstract List getNotationList(); + + public abstract HashMap getElementMap(); +} diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/dtd/DTDTypingNonValidator.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/dtd/DTDTypingNonValidator.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/dtd/DTDTypingNonValidator.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/dtd/DTDTypingNonValidator.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,326 @@ +/* Woodstox XML processor + * + * Copyright (c) 2004- Tatu Saloranta, tatu.saloranta@iki.fi + * + * Licensed under the License specified in file LICENSE, included with + * the source code. + * You may not use this file except in compliance with the License. + * + * 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 com.ctc.wstx.dtd; + +import java.util.*; + +import javax.xml.stream.XMLStreamException; + +import org.codehaus.stax2.validation.*; + +import com.ctc.wstx.ent.EntityDecl; +import com.ctc.wstx.util.DataUtil; +import com.ctc.wstx.util.ElementIdMap; +import com.ctc.wstx.util.ExceptionUtil; +import com.ctc.wstx.util.PrefixedName; + +/** + * This class is a "non-validating validator"; a validator-like object + * that handles DTD-based non-validation functionality: determining type + * information and default values. This instance does NOT implement any + * actual DTD-validation, and is to be used in DTD-aware non-validating + * mode. + */ +public class DTDTypingNonValidator + extends DTDValidatorBase +{ + /* + /////////////////////////////////////////// + // Element def/spec/validator stack, state + /////////////////////////////////////////// + */ + + /** + * Flag that indicates if current element has any attributes that + * have default values. + */ + protected boolean mHasAttrDefaults = false; + + /** + * Bitset used for keeping track of defaulted attributes for which values + * have been found. Only non-null when current element does have such + * attributes + */ + protected BitSet mCurrDefaultAttrs = null; + + /** + * Flag that indicates whether any of the attributes is potentially + * normalizable, and we are in attribute-normalizing mode. + */ + protected boolean mHasNormalizableAttrs = false; + + /* + /////////////////////////////////////// + // Temporary helper objects + /////////////////////////////////////// + */ + + /** + * Reusable lazily instantiated BitSet; needed to keep track of + * 'missing' attributes with default values (normal default, #FIXED). + */ + BitSet mTmpDefaultAttrs; + + /* + /////////////////////////////////////////// + // Life-cycle + /////////////////////////////////////////// + */ + + public DTDTypingNonValidator(DTDSubset schema, ValidationContext ctxt, boolean hasNsDefaults, + Map elemSpecs, Map genEntities) + { + super(schema, ctxt, hasNsDefaults, elemSpecs, genEntities); + } + + /** + * @return False, since this is not a real validator + */ + @Override + public final boolean reallyValidating() { return false; } + + /* + /////////////////////////////////////// + // Configuration + /////////////////////////////////////// + */ + + /** + * This 'validator' will not normalize any attributes, + * so let's implement this as no-op. + */ + @Override + public void setAttrValueNormalization(boolean state) { + // nop + } + + /* + /////////////////////////////////////// + // XMLValidator implementation + /////////////////////////////////////// + */ + + //public XMLValidationSchema getSchema() + + @Override + public void validateElementStart(String localName, String uri, String prefix) + throws XMLStreamException + { + // Ok, can we find the element definition? + mTmpKey.reset(prefix, localName); + DTDElement elem = mElemSpecs.get(mTmpKey); + // whether it's found or not, let's add a stack frame: + int elemCount = mElemCount++; + if (elemCount >= mElems.length) { + mElems = (DTDElement[]) DataUtil.growArrayBy50Pct(mElems); + } + + mElems[elemCount] = mCurrElem = elem; + mAttrCount = 0; + mIdAttrIndex = -2; // -2 as a "don't know yet" marker + + /* but if not found, can not obtain any type information. Not + * a validation problem though, since we are doing none... + * Oh, also, unlike with real validation, not having actual element + * information is ok; can still have attributes! + */ + if (elem == null) { // || !elem.isDefined()) + mCurrAttrDefs = NO_ATTRS; + mHasAttrDefaults = false; + mCurrDefaultAttrs = null; + mHasNormalizableAttrs = false; + return; + } + + // If element found, does it have any attributes? + mCurrAttrDefs = elem.getAttributes(); + if (mCurrAttrDefs == null) { + mCurrAttrDefs = NO_ATTRS; + mHasAttrDefaults = false; + mCurrDefaultAttrs = null; + mHasNormalizableAttrs = false; + return; + } + + // Any normalization needed? + mHasNormalizableAttrs = mNormAttrs || elem.attrsNeedValidation(); + + // Any default values? + mHasAttrDefaults = elem.hasAttrDefaultValues(); + if (mHasAttrDefaults) { + /* Special count also contains ones with #REQUIRED value, but + * that's a minor sub-optimality... + */ + int specCount = elem.getSpecialCount(); + BitSet bs = mTmpDefaultAttrs; + if (bs == null) { + mTmpDefaultAttrs = bs = new BitSet(specCount); + } else { + bs.clear(); + } + mCurrDefaultAttrs = bs; + } else { + mCurrDefaultAttrs = null; + } + } + + @Override + public String validateAttribute(String localName, String uri, + String prefix, String value) + throws XMLStreamException + { + /* no need to do any validation; however, need to do following: + * + * (a) Figure out type info, if any (to get data type, id index etc); + * if yes, do: + * (1) If attribute has default value, note down it's not needed due + * to explicit definition + * (2) If attribute is normalizable, normalize it without validation + */ + DTDAttribute attr = mCurrAttrDefs.get(mTmpKey.reset(prefix, localName)); + int index = mAttrCount++; + if (index >= mAttrSpecs.length) { + mAttrSpecs = (DTDAttribute[]) DataUtil.growArrayBy50Pct(mAttrSpecs); + } + mAttrSpecs[index] = attr; + + /* Although undeclared attribute would be a validation error, + * we don't care here... just need to skip it + */ + if (attr != null) { + if (mHasAttrDefaults) { + /* Once again, let's use more generic 'special' index, + * even though it also includes #REQUIRED values + */ + int specIndex = attr.getSpecialIndex(); + if (specIndex >= 0) { + mCurrDefaultAttrs.set(specIndex); + } + } + if (mHasNormalizableAttrs) { + // !!! TBI + } + } + return null; // fine as is + } + + @Override + public String validateAttribute(String localName, String uri, + String prefix, + char[] valueChars, int valueStart, + int valueEnd) + throws XMLStreamException + { + // note: cut'n pasted from above... + DTDAttribute attr = mCurrAttrDefs.get(mTmpKey.reset(prefix, localName)); + int index = mAttrCount++; + if (index >= mAttrSpecs.length) { + mAttrSpecs = (DTDAttribute[]) DataUtil.growArrayBy50Pct(mAttrSpecs); + } + mAttrSpecs[index] = attr; + if (attr != null) { + if (mHasAttrDefaults) { + int specIndex = attr.getSpecialIndex(); + if (specIndex >= 0) { + mCurrDefaultAttrs.set(specIndex); + } + } + if (mHasNormalizableAttrs) { // may get normalized, after all + return attr.normalize(this, valueChars, valueStart, valueEnd); + } + } + return null; // fine as is + } + + @Override + public int validateElementAndAttributes() + throws XMLStreamException + { + /* Ok; since we are not really validating, we just need to add possible + * attribute default values, and return "anything goes" + * as the allowable content: + */ + DTDElement elem = mCurrElem; + if (mHasAttrDefaults) { + BitSet specBits = mCurrDefaultAttrs; + int specCount = elem.getSpecialCount(); + int ix = specBits.nextClearBit(0); + while (ix < specCount) { // something amiss! + List specAttrs = elem.getSpecialAttrs(); + DTDAttribute attr = specAttrs.get(ix); + if (attr.hasDefaultValue()) { // no default for #REQUIRED... + doAddDefaultValue(attr); + } + ix = specBits.nextClearBit(ix+1); + } + } + /* However: we should indicate cases where PCDATA is not supposed + * to occur -- although it won't be considered an error, when not + * validating, info is needed to determine type of SPACE instead + * of CHARACTERS. Other validation types are not to be returned, + * however, since caller doesn't know how to deal with such + * cases. + */ + return (elem == null) ? XMLValidator.CONTENT_ALLOW_ANY_TEXT : + elem.getAllowedContentIfSpace(); + } + + @Override + public int validateElementEnd(String localName, String uri, String prefix) + throws XMLStreamException + { + /* Since we are not really validating, only need to maintain + * the element stack, and return "anything goes" as allowable content: + */ + int ix = --mElemCount; + mElems[ix] = null; + if (ix < 1) { + return XMLValidator.CONTENT_ALLOW_ANY_TEXT; + } + DTDElement elem = mElems[ix-1]; + return (elem == null) ? XMLValidator.CONTENT_ALLOW_ANY_TEXT : + mElems[ix-1].getAllowedContentIfSpace(); + } + + // base class implements these ok: + //public void validateText(String text, boolean lastTextSegment) + //public void validateText(char[] cbuf, int textStart, int textEnd, boolean lastTextSegment) + + @Override + public void validationCompleted(boolean eod) + //throws XMLStreamException + { + // fine, great, nothing to do... + } + + /* + /////////////////////////////////////// + // Package methods, accessors + /////////////////////////////////////// + */ + + @Override + protected ElementIdMap getIdMap() + { + /* should never be called; for now let's throw an exception, if it + * turns out it does get called can/should return an empty immutable + * map or something + */ + ExceptionUtil.throwGenericInternal(); + return null; // never gets here + } + +} diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/dtd/DTDValidatorBase.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/dtd/DTDValidatorBase.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/dtd/DTDValidatorBase.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/dtd/DTDValidatorBase.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,549 @@ +/* Woodstox XML processor + * + * Copyright (c) 2004- Tatu Saloranta, tatu.saloranta@iki.fi + * + * Licensed under the License specified in file LICENSE, included with + * the source code. + * You may not use this file except in compliance with the License. + * + * 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 com.ctc.wstx.dtd; + +import java.text.MessageFormat; +import java.util.*; + +import javax.xml.stream.Location; +import javax.xml.stream.XMLStreamException; + +import org.codehaus.stax2.validation.*; + +import com.ctc.wstx.api.WstxInputProperties; +import com.ctc.wstx.ent.EntityDecl; +import com.ctc.wstx.sr.NsDefaultProvider; +import com.ctc.wstx.sr.InputElementStack; +import com.ctc.wstx.util.DataUtil; +import com.ctc.wstx.util.ElementIdMap; +import com.ctc.wstx.util.ExceptionUtil; +import com.ctc.wstx.util.PrefixedName; + +/** + * Shared abstract base class for Woodstox implementations + * of {@link XMLValidator} for DTD validation. + * Since there are 2 sub-types -- full actual DTD validator, and a dummy + * one that only adds type information and default values, with no actual + * validation -- common functionality was refactored into this base + * class. + */ +public abstract class DTDValidatorBase + extends XMLValidator + implements NsDefaultProvider // for namespace attr defaults +{ + protected final static HashMap NO_ATTRS = new HashMap(); + + /* + ///////////////////////////////////////////////////// + // Constants + ///////////////////////////////////////////////////// + */ + + /** + * Estimated maximum depth of typical documents; used to allocate + * the array for element stack + */ + final static int DEFAULT_STACK_SIZE = 16; + + /** + * Estimated maximum number of attributes for a single element + */ + final static int EXP_MAX_ATTRS = 16; + + /** + * Let's actually just reuse a local Map... + */ + protected final static HashMap EMPTY_MAP = new HashMap(); + + /* + /////////////////////////////////////// + // Configuration + /////////////////////////////////////// + */ + + /** + * Flag that indicates whether any of the elements declared has default + * attribute values for namespace declaration pseudo-attributes. + */ + final boolean mHasNsDefaults; + + /** + * DTD schema ({@link DTDSubsetImpl}) object that created this validator + * instance. + */ + final DTDSubset mSchema; + + /** + * Validation context (owner) for this validator. Needed for adding + * default attribute values, for example. + */ + final ValidationContext mContext; + + /** + * Map that contains element specifications from DTD; null if no + * DOCTYPE declaration found. + */ + final Map mElemSpecs; + + /** + * General entities defined in DTD subsets; needed for validating + * ENTITY/ENTITIES attributes. + */ + final Map mGeneralEntities; + + /** + * Flag that indicates whether parser wants the attribute values + * to be normalized (according to XML specs) or not (which may be + * more efficient, although not compliant with the specs) + */ + protected boolean mNormAttrs; + + /* + /////////////////////////////////////////// + // Element def/spec/validator stack, state + /////////////////////////////////////////// + */ + + /** + * This is the element that is currently being validated; valid + * during + * validateElementStart, + * validateAttribute, + * validateElementAndAttributes calls. + */ + protected DTDElement mCurrElem = null; + + /** + * Stack of element definitions matching the current active element stack. + * Instances are elements definitions read from DTD. + */ + protected DTDElement[] mElems = null; + + /** + * Number of elements in {@link #mElems}. + */ + protected int mElemCount = 0; + + /** + * Attribute definitions for attributes the current element may have + */ + protected HashMap mCurrAttrDefs = null; + + /** + * List of attribute declarations/specifications, one for each + * attribute of the current element, for which there is a matching + * value (either explicitly defined, or assigned via defaulting). + */ + protected DTDAttribute[] mAttrSpecs = new DTDAttribute[EXP_MAX_ATTRS]; + + /** + * Number of attribute specification Objects in + * {@link #mAttrSpecs}; needed to store in case type information + * is requested later on. + */ + protected int mAttrCount = 0; + + /** + * Index of the attribute of type ID, within current element's + * attribute list. Track of this is kept separate from other + * attribute since id attributes often need to be used for resolving + * cross-references. + */ + protected int mIdAttrIndex = -1; + + /* + /////////////////////////////////////// + // Temporary helper objects + /////////////////////////////////////// + */ + + protected final transient PrefixedName mTmpKey = new PrefixedName(null, null); + + /** + * Temporary buffer attribute instances can share for validation + * purposes + */ + char[] mTmpAttrValueBuffer = null; + + /* + /////////////////////////////////////// + // Life-cycle + /////////////////////////////////////// + */ + + public DTDValidatorBase(DTDSubset schema, ValidationContext ctxt, boolean hasNsDefaults, + Map elemSpecs, Map genEntities) + { + mSchema = schema; + mContext = ctxt; + mHasNsDefaults = hasNsDefaults; + if (elemSpecs == null || elemSpecs.size() == 0) { + mElemSpecs = Collections.emptyMap(); + } else { + mElemSpecs = elemSpecs; + } + mGeneralEntities = genEntities; + // By default, let's assume attrs are to be normalized (fully xml compliant) + mNormAttrs = true; + mElems = new DTDElement[DEFAULT_STACK_SIZE]; + } + + /* + /////////////////////////////////////// + // Configuration + /////////////////////////////////////// + */ + + /** + * Method that allows enabling/disabling attribute value normalization. + * In general, readers by default enable normalization (to be fully xml + * compliant), + * whereas writers do not (since there is usually little to gain, if + * anything -- it is even possible value may be written before validation + * is called in some cases) + */ + public void setAttrValueNormalization(boolean state) { + mNormAttrs = state; + } + + /** + * @return True for validator object that actually do validate + * content; false for objects that only use DTD type information. + */ + public abstract boolean reallyValidating(); + + /* + /////////////////////////////////////// + // XMLValidator implementation + /////////////////////////////////////// + */ + + @Override + public final XMLValidationSchema getSchema() { + return mSchema; + } + + /** + * Method called to update information about the newly encountered (start) + * element. At this point namespace information has been resolved, but + * no DTD validation has been done. Validator is to do these validations, + * including checking for attribute value (and existence) compatibility. + */ + @Override + public abstract void validateElementStart(String localName, String uri, String prefix) + throws XMLStreamException; + + @Override + public abstract String validateAttribute(String localName, String uri, + String prefix, String value) + throws XMLStreamException; + + @Override + public abstract String validateAttribute(String localName, String uri, + String prefix, + char[] valueChars, int valueStart, + int valueEnd) + throws XMLStreamException; + + @Override + public abstract int validateElementAndAttributes() + throws XMLStreamException; + + /** + * @return Validation state that should be effective for the parent + * element state + */ + @Override + public abstract int validateElementEnd(String localName, String uri, String prefix) + throws XMLStreamException; + + @Override + public void validateText(String text, boolean lastTextSegment) + throws XMLStreamException + { + /* This method is a NOP, since basic DTD has no mechanism for + * validating textual content. + */ + } + + @Override + public void validateText(char[] cbuf, int textStart, int textEnd, + boolean lastTextSegment) + throws XMLStreamException + { + /* This method is a NOP, since basic DTD has no mechanism for + * validating textual content. + */ + } + + @Override + public abstract void validationCompleted(boolean eod) + throws XMLStreamException; + + /* + /////////////////////////////////////// + // Attribute info access + /////////////////////////////////////// + */ + + // // // Access to type info + + @Override + public String getAttributeType(int index) + { + DTDAttribute attr = mAttrSpecs[index]; + return (attr == null) ? WstxInputProperties.UNKNOWN_ATTR_TYPE : + attr.getValueTypeString(); + } + + /** + * Method for finding out the index of the attribute (collected using + * the attribute collector; having DTD-derived info in same order) + * that is of type ID. DTD explicitly specifies that at most one + * attribute can have this type for any element. + * + * @return Index of the attribute with type ID, in the current + * element, if one exists: -1 otherwise + */ + @Override + public int getIdAttrIndex() + { + // Let's figure out the index only when needed + int ix = mIdAttrIndex; + if (ix == -2) { + ix = -1; + if (mCurrElem != null) { + DTDAttribute idAttr = mCurrElem.getIdAttribute(); + if (idAttr != null) { + DTDAttribute[] attrs = mAttrSpecs; + for (int i = 0, len = attrs.length; i < len; ++i) { + if (attrs[i] == idAttr) { + ix = i; + break; + } + } + } + } + mIdAttrIndex = ix; + } + return ix; + } + + /** + * Method for finding out the index of the attribute (collected using + * the attribute collector; having DTD-derived info in same order) + * that is of type NOTATION. DTD explicitly specifies that at most one + * attribute can have this type for any element. + * + * @return Index of the attribute with type NOTATION, in the current + * element, if one exists: -1 otherwise + */ + @Override + public int getNotationAttrIndex() + { + /* If necessary, we could find this index when resolving the + * element, could avoid linear search. But who knows how often + * it's really needed... + */ + for (int i = 0, len = mAttrCount; i < len; ++i) { + if (mAttrSpecs[i].typeIsNotation()) { + return i; + } + } + return -1; + } + + /* + ///////////////////////////////////////////////////// + // NsDefaultProvider interface + ///////////////////////////////////////////////////// + */ + + /** + * Calling this method before {@link #checkNsDefaults} is necessary + * to pass information regarding the current element; although + * it will become available later on (via normal XMLValidator interface), + * that's too late (after namespace binding and resolving). + */ + @Override + public boolean mayHaveNsDefaults(String elemPrefix, String elemLN) + { + mTmpKey.reset(elemPrefix, elemLN); + DTDElement elem = mElemSpecs.get(mTmpKey); + mCurrElem = elem; + return (elem != null) && elem.hasNsDefaults(); + } + + @Override + public void checkNsDefaults(InputElementStack nsStack) + throws XMLStreamException + { + // We only get called if mCurrElem != null, and has defaults + HashMap m = mCurrElem.getNsDefaults(); + if (m != null) { + for (Map.Entry me : m.entrySet()) { + String prefix = me.getKey(); + if (!nsStack.isPrefixLocallyDeclared(prefix)) { + DTDAttribute attr = me.getValue(); + String uri = attr.getDefaultValue(mContext, this); + nsStack.addNsBinding(prefix, uri); + } + } + } + } + + /* + /////////////////////////////////////// + // Package methods, accessors + /////////////////////////////////////// + */ + + /** + * Name of current element on the top of the element stack. + */ + PrefixedName getElemName() { + DTDElement elem = mElems[mElemCount-1]; + return elem.getName(); + } + + Location getLocation() { + return mContext.getValidationLocation(); + } + + protected abstract ElementIdMap getIdMap(); + + Map getEntityMap() { + return mGeneralEntities; + } + + char[] getTempAttrValueBuffer(int neededLength) + { + if (mTmpAttrValueBuffer == null + || mTmpAttrValueBuffer.length < neededLength) { + int size = (neededLength < 100) ? 100 : neededLength; + mTmpAttrValueBuffer = new char[size]; + } + return mTmpAttrValueBuffer; + } + + public boolean hasNsDefaults() { + return mHasNsDefaults; + } + + /* + /////////////////////////////////////// + // Package methods, error handling + /////////////////////////////////////// + */ + + /** + * Method called to report validity problems; depending on mode, will + * either throw an exception, or add a problem notification to the + * list of problems. + */ + void reportValidationProblem(String msg) + throws XMLStreamException + { + doReportValidationProblem(msg, null); + } + + void reportValidationProblem(String msg, Location loc) + throws XMLStreamException + { + doReportValidationProblem(msg, loc); + } + + void reportValidationProblem(String format, Object arg) + throws XMLStreamException + { + doReportValidationProblem(MessageFormat.format(format, new Object[] { arg }), + null); + } + + void reportValidationProblem(String format, Object arg1, Object arg2) + throws XMLStreamException + { + doReportValidationProblem(MessageFormat.format(format, new Object[] { arg1, arg2 }), + null); + } + + /* + /////////////////////////////////////// + // Private/sub-class methods + /////////////////////////////////////// + */ + + protected void doReportValidationProblem(String msg, Location loc) + throws XMLStreamException + { + if (loc == null) { + loc = getLocation(); + } + XMLValidationProblem prob = new XMLValidationProblem(loc, msg, XMLValidationProblem.SEVERITY_ERROR); + prob.setReporter(this); + mContext.reportProblem(prob); + } + + protected void doAddDefaultValue(DTDAttribute attr) + throws XMLStreamException + { + /* If we get here, we should have a non-null (possibly empty) default + * value: + */ + String def = attr.getDefaultValue(mContext, this); + if (def == null) { + ExceptionUtil.throwInternal("null default attribute value"); + } + PrefixedName an = attr.getName(); + // Ok, do we need to find the URI? + String prefix = an.getPrefix(); + String uri = ""; + if (prefix != null && prefix.length() > 0) { + uri = mContext.getNamespaceURI(prefix); + // Can not map to empty NS! + if (uri == null || uri.length() == 0) { + /* Hmmh. This is a weird case where we do have to + * throw a validity exception; even though it really + * is more a ns-well-formedness error... + */ + reportValidationProblem("Unbound namespace prefix \"{0}\" for default attribute \"{1}\"", prefix, attr); + // May continue if we don't throw errors, just collect them to a list + uri = ""; + } + } + int defIx = mContext.addDefaultAttribute(an.getLocalName(), uri, prefix, def); + if (defIx < 0) { + /* 13-Dec-2005, Tatus: Hmmh. For readers this is an error + * condition, but writers may just indicate they are not + * interested in defaults. So let's let context report + * problem(s) if it has any regarding the request. + */ + // nop + } else { + while (defIx >= mAttrSpecs.length) { + mAttrSpecs = (DTDAttribute[]) DataUtil.growArrayBy50Pct(mAttrSpecs); + } + /* Any intervening empty slots? (can happen if other + * validators add default attributes...) + */ + while (mAttrCount < defIx) { + mAttrSpecs[mAttrCount++] = null; + } + mAttrSpecs[defIx] = attr; + mAttrCount = defIx+1; + } + } +} diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/dtd/DTDValidator.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/dtd/DTDValidator.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/dtd/DTDValidator.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/dtd/DTDValidator.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,415 @@ +/* Woodstox XML processor + * + * Copyright (c) 2004- Tatu Saloranta, tatu.saloranta@iki.fi + * + * Licensed under the License specified in file LICENSE, included with + * the source code. + * You may not use this file except in compliance with the License. + * + * 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 com.ctc.wstx.dtd; + +import java.util.*; + +import javax.xml.stream.XMLStreamException; + +import org.codehaus.stax2.validation.*; + +import com.ctc.wstx.cfg.ErrorConsts; +import com.ctc.wstx.ent.EntityDecl; +import com.ctc.wstx.util.DataUtil; +import com.ctc.wstx.util.ElementId; +import com.ctc.wstx.util.ElementIdMap; +import com.ctc.wstx.util.PrefixedName; +import com.ctc.wstx.util.StringUtil; + +/** + * Woodstox implementation of {@link XMLValidator}; the class that + * handles DTD-based validation. + */ +public class DTDValidator + extends DTDValidatorBase +{ + /* + /////////////////////////////////////// + // Configuration + /////////////////////////////////////// + */ + + /** + * Determines if identical problems (definition of the same element, + * for example) should cause multiple error notifications or not: + * if true, will get one error per instance, if false, only the first + * one will get reported. + */ + protected boolean mReportDuplicateErrors = false; + + /* + /////////////////////////////////////// + // Id/idref state + /////////////////////////////////////// + */ + + /** + * Information about declared and referenced element ids (unique + * ids that attributes may defined, as defined by DTD) + */ + protected ElementIdMap mIdMap = null; + + /* + /////////////////////////////////////////// + // Element def/spec/validator stack, state + /////////////////////////////////////////// + */ + + /** + * Stack of validators for open elements + */ + protected StructValidator[] mValidators = null; + + /** + * Bitset used for keeping track of required and defaulted attributes + * for which values have been found. + */ + protected BitSet mCurrSpecialAttrs = null; + + boolean mCurrHasAnyFixed = false; + + /* + /////////////////////////////////////// + // Temporary helper objects + /////////////////////////////////////// + */ + + /** + * Reusable lazily instantiated BitSet; needed to keep track of + * missing 'special' attributes (required ones, ones with default + * values) + */ + BitSet mTmpSpecialAttrs; + + /* + /////////////////////////////////////// + // Life-cycle + /////////////////////////////////////// + */ + + public DTDValidator(DTDSubset schema, ValidationContext ctxt, boolean hasNsDefaults, + Map elemSpecs, Map genEntities) + { + super(schema, ctxt, hasNsDefaults, elemSpecs, genEntities); + mValidators = new StructValidator[DEFAULT_STACK_SIZE]; + } + + @Override + public final boolean reallyValidating() { return true; } + + /* + /////////////////////////////////////// + // XMLValidator implementation + /////////////////////////////////////// + */ + + //public XMLValidationSchema getSchema(); + + /** + * Method called to update information about the newly encountered (start) + * element. At this point namespace information has been resolved, but + * no DTD validation has been done. Validator is to do these validations, + * including checking for attribute value (and existence) compatibility. + */ + @Override + public void validateElementStart(String localName, String uri, String prefix) + throws XMLStreamException + { + /* Ok, need to find the element definition; if not found (or + * only implicitly defined), need to throw the exception. + */ + mTmpKey.reset(prefix, localName); + + DTDElement elem = mElemSpecs.get(mTmpKey); + + /* Let's add the entry in (even if it's a null); this is necessary + * to keep things in-sync if allowing graceful handling of validity + * errors + */ + int elemCount = mElemCount++; + if (elemCount >= mElems.length) { + mElems = (DTDElement[]) DataUtil.growArrayBy50Pct(mElems); + mValidators = (StructValidator[]) DataUtil.growArrayBy50Pct(mValidators); + } + mElems[elemCount] = mCurrElem = elem; + if (elem == null || !elem.isDefined()) { + reportValidationProblem(ErrorConsts.ERR_VLD_UNKNOWN_ELEM, mTmpKey.toString()); + } + + // Is this element legal under the parent element? + StructValidator pv = (elemCount > 0) ? mValidators[elemCount-1] : null; + + if (pv != null && elem != null) { + String msg = pv.tryToValidate(elem.getName()); + if (msg != null) { + int ix = msg.indexOf("$END"); + String pname = mElems[elemCount-1].toString(); + if (ix >= 0) { + msg = msg.substring(0, ix) + "" + +msg.substring(ix+4); + } + reportValidationProblem("Validation error, encountered element <" + +elem.getName()+"> as a child of <" + +pname+">: "+msg); + } + } + + mAttrCount = 0; + mIdAttrIndex = -2; // -2 as a "don't know yet" marker + + // Ok, need to get the child validator, then: + if (elem == null) { + mValidators[elemCount] = null; + mCurrAttrDefs = NO_ATTRS; + mCurrHasAnyFixed = false; + mCurrSpecialAttrs = null; + } else { + mValidators[elemCount] = elem.getValidator(); + mCurrAttrDefs = elem.getAttributes(); + if (mCurrAttrDefs == null) { + mCurrAttrDefs = NO_ATTRS; + } + mCurrHasAnyFixed = elem.hasFixedAttrs(); + int specCount = elem.getSpecialCount(); + if (specCount == 0) { + mCurrSpecialAttrs = null; + } else { + BitSet bs = mTmpSpecialAttrs; + if (bs == null) { + mTmpSpecialAttrs = bs = new BitSet(specCount); + } else { + bs.clear(); + } + mCurrSpecialAttrs = bs; + } + } + } + + @Override + public String validateAttribute(String localName, String uri, + String prefix, String value) + throws XMLStreamException + { + DTDAttribute attr = mCurrAttrDefs.get(mTmpKey.reset(prefix, localName)); + if (attr == null) { + // Only report error if not already recovering from an error: + if (mCurrElem != null) { + reportValidationProblem(ErrorConsts.ERR_VLD_UNKNOWN_ATTR, + mCurrElem.toString(), mTmpKey.toString()); + } + /* [WSTX-190] NPE if we continued (after reported didn't + * throw an exception); nothing more to do, let's leave + */ + return value; + } + int index = mAttrCount++; + if (index >= mAttrSpecs.length) { + mAttrSpecs = (DTDAttribute[]) DataUtil.growArrayBy50Pct(mAttrSpecs); + } + mAttrSpecs[index] = attr; + if (mCurrSpecialAttrs != null) { // Need to mark that we got it + int specIndex = attr.getSpecialIndex(); + if (specIndex >= 0) { + mCurrSpecialAttrs.set(specIndex); + } + } + String result = attr.validate(this, value, mNormAttrs); + if (mCurrHasAnyFixed && attr.isFixed()) { + String act = (result == null) ? value : result; + String exp = attr.getDefaultValue(mContext, this); + if (!act.equals(exp)) { + reportValidationProblem("Value of attribute \""+attr+"\" (element <"+mCurrElem+">) not \""+exp+"\" as expected, but \""+act+"\""); + } + } + return result; + } + + @Override + public String validateAttribute(String localName, String uri, + String prefix, + char[] valueChars, int valueStart, + int valueEnd) + throws XMLStreamException + { + DTDAttribute attr = mCurrAttrDefs.get(mTmpKey.reset(prefix, localName)); + if (attr == null) { + // Only report error if not already covering from an error: + if (mCurrElem != null) { + reportValidationProblem(ErrorConsts.ERR_VLD_UNKNOWN_ATTR, + mCurrElem.toString(), mTmpKey.toString()); + } + /* [WSTX-190] NPE if we continued (after reported didn't + * throw an exception); nothing more to do, let's leave + */ + return new String(valueChars, valueStart, valueEnd); + } + int index = mAttrCount++; + if (index >= mAttrSpecs.length) { + mAttrSpecs = (DTDAttribute[]) DataUtil.growArrayBy50Pct(mAttrSpecs); + } + mAttrSpecs[index] = attr; + if (mCurrSpecialAttrs != null) { // Need to mark that we got it + int specIndex = attr.getSpecialIndex(); + if (specIndex >= 0) { + mCurrSpecialAttrs.set(specIndex); + } + } + String result = attr.validate(this, valueChars, valueStart, valueEnd, mNormAttrs); + if (mCurrHasAnyFixed && attr.isFixed()) { + String exp = attr.getDefaultValue(mContext, this); + boolean match; + if (result == null) { + match = StringUtil.matches(exp, valueChars, valueStart, valueEnd - valueStart); + } else { + match = exp.equals(result); + } + if (!match) { + String act = (result == null) ? + new String(valueChars, valueStart, valueEnd) : result; + reportValidationProblem("Value of #FIXED attribute \""+attr+"\" (element <"+mCurrElem+">) not \""+exp+"\" as expected, but \""+act+"\""); + } + } + return result; + } + + @Override + public int validateElementAndAttributes() + throws XMLStreamException + { + // Ok: are we fine with the attributes? + DTDElement elem = mCurrElem; + if (elem == null) { // had an error, most likely no such element defined... + // need to just return, nothing to do here + return XMLValidator.CONTENT_ALLOW_ANY_TEXT; + } + + // Any special attributes missing? + if (mCurrSpecialAttrs != null) { + BitSet specBits = mCurrSpecialAttrs; + int specCount = elem.getSpecialCount(); + int ix = specBits.nextClearBit(0); + while (ix < specCount) { // something amiss! + List specAttrs = elem.getSpecialAttrs(); + DTDAttribute attr = specAttrs.get(ix); + + /* [WSTX-155]: Problems if reportValidationProblem returns + * ok (which happens if a reporter handles it). So what + * to do with missing required value? First thought is + * to just leave it as is. + */ + if (attr.isRequired()) { + reportValidationProblem("Required attribute \"{0}\" missing from element <{1}>", attr, elem); + } else { + doAddDefaultValue(attr); + } + ix = specBits.nextClearBit(ix+1); + } + } + + return elem.getAllowedContent(); + } + + /** + * @return Validation state that should be effective for the parent + * element state + */ + @Override + public int validateElementEnd(String localName, String uri, String prefix) + throws XMLStreamException + { + // First, let's remove the top: + int ix = mElemCount-1; + /* [WSTX-200]: need to avoid problems when doing sub-tree + * validation... + */ + if (ix < 0) { + return XMLValidator.CONTENT_ALLOW_WS; + } + mElemCount = ix; + + DTDElement closingElem = mElems[ix]; + mElems[ix] = null; + StructValidator v = mValidators[ix]; + mValidators[ix] = null; + + // Validation? + if (v != null) { + String msg = v.fullyValid(); + if (msg != null) { + reportValidationProblem("Validation error, element : "+msg); + } + } + + // Then let's get info from parent, if any + if (ix < 1) { // root element closing.. + // doesn't really matter; epilog/prolog differently handled: + return XMLValidator.CONTENT_ALLOW_WS; + } + return mElems[ix-1].getAllowedContent(); + } + + //public void validateText(String text, boolean lastTextSegment) ; + //public void validateText(char[] cbuf, int textStart, int textEnd, boolean lastTextSegment) ; + + @Override + public void validationCompleted(boolean eod) throws XMLStreamException + { + /* Need to now ensure that all IDREF/IDREFS references + * point to defined ID attributes + */ + checkIdRefs(); + } + + /* + /////////////////////////////////////// + // Package methods, accessors + /////////////////////////////////////// + */ + + @Override + protected ElementIdMap getIdMap() { + if (mIdMap == null) { + mIdMap = new ElementIdMap(); + } + return mIdMap; + } + + /* + /////////////////////////////////////// + // Internal methods + /////////////////////////////////////// + */ + + protected void checkIdRefs() + throws XMLStreamException + { + /* 02-Oct-2004, TSa: Now we can also check that all id references + * pointed to ids that actually are defined + */ + if (mIdMap != null) { + ElementId ref = mIdMap.getFirstUndefined(); + if (ref != null) { // problem! + reportValidationProblem("Undefined id '"+ref.getId() + +"': referenced from element <" + +ref.getElemName()+">, attribute '" + +ref.getAttrName()+"'", + ref.getLocation()); + } + } + } + +} diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/dtd/DTDWriter.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/dtd/DTDWriter.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/dtd/DTDWriter.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/dtd/DTDWriter.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,164 @@ +package com.ctc.wstx.dtd; + +import java.io.IOException; +import java.io.Writer; + +import javax.xml.stream.XMLStreamException; + +import com.ctc.wstx.exc.WstxIOException; + +/** + * Simple utility class used by {@link DTDReader} when writing out + * flattened external DTD subset file. Writing functionality encapsulated + * here since it's specific to one mode of operation (flattening). + *

+ * Note, too, that underlying {@link IOException}s are generally wrapped + * as {@link XMLStreamException}s. This is needed to reduce amount of + * work caller has to do for wrapping. It will still be possible to + * unwrap these exceptions further up the call stack if need be. + */ +final class DTDWriter +{ + /* + ////////////////////////////////////////////////// + // Configuration + ////////////////////////////////////////////////// + */ + + final Writer mWriter; + + final boolean mIncludeComments; + + final boolean mIncludeConditionals; + + final boolean mIncludePEs; + + /* + ////////////////////////////////////////////////// + // Output status + ////////////////////////////////////////////////// + */ + + /** + * Counter that indicates whether flattened output should be written to + * (non-null) mWriter; values above zero indicate output is enabled, + * zero and below that output is disabled. + * Only enabled if mWriter is not + * null; will be temporarily disabled during processing of content + * that is not to be included (PE reference; or comments / conditional + * sections if comment/cs output is suppressed) + */ + int mIsFlattening = 0; + + /** + * Pointer to first character in the current input buffer that + * has not yet been written to flatten writer. + */ + int mFlattenStart = 0; + + /* + ////////////////////////////////////////////////// + // Life-cycle + ////////////////////////////////////////////////// + */ + + public DTDWriter(Writer out, boolean inclComments, boolean inclCond, + boolean inclPEs) + { + mWriter = out; + mIncludeComments = inclComments; + mIncludeConditionals = inclCond; + mIncludePEs = inclPEs; + + mIsFlattening = 1; // starts enabled + } + + /* + ////////////////////////////////////////////////// + // Public API, accessors, state change + ////////////////////////////////////////////////// + */ + + public boolean includeComments() { + return mIncludeComments; + } + + public boolean includeConditionals() { + return mIncludeConditionals; + } + + public boolean includeParamEntities() { + return mIncludePEs; + } + + public void disableOutput() + { + --mIsFlattening; + } + + public void enableOutput(int newStart) + { + ++mIsFlattening; + mFlattenStart = newStart; + } + + public void setFlattenStart(int ptr) { + mFlattenStart = ptr; + } + + public int getFlattenStart() { + return mFlattenStart; + } + + /* + ////////////////////////////////////////////////// + // Public API, output methods: + ////////////////////////////////////////////////// + */ + + public void flush(char[] buf, int upUntil) + throws XMLStreamException + { + if (mFlattenStart < upUntil) { + if (mIsFlattening > 0) { + try { + mWriter.write(buf, mFlattenStart, upUntil - mFlattenStart); + } catch (IOException ioe) { + throw new WstxIOException(ioe); + } + } + mFlattenStart = upUntil; + } + } + + /** + * Method called when explicit output has to be done for flatten output: + * this is usually done when there's need to do speculative checks + * before it's known if some chars are output (when suppressing comments + * or conditional sections) + */ + public void output(String output) + throws XMLStreamException + { + if (mIsFlattening > 0) { + try { + mWriter.write(output); + } catch (IOException ioe) { + throw new WstxIOException(ioe); + } + } + } + + public void output(char c) + throws XMLStreamException + { + if (mIsFlattening > 0) { + try { + mWriter.write(c); + } catch (IOException ioe) { + throw new WstxIOException(ioe); + } + } + } +} + diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/dtd/EmptyValidator.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/dtd/EmptyValidator.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/dtd/EmptyValidator.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/dtd/EmptyValidator.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,49 @@ +package com.ctc.wstx.dtd; + +import com.ctc.wstx.util.PrefixedName; + +/** + * Simple content model validator that accepts no elements, ever; this + * is true for pure #PCDATA content model as well as EMPTY content model. + * Can be used as a singleton, since all info needed for diagnostics + * is passed via methods. + */ +public class EmptyValidator + extends StructValidator +{ + final static EmptyValidator sPcdataInstance = new EmptyValidator("No elements allowed in pure #PCDATA content model"); + + final static EmptyValidator sEmptyInstance = new EmptyValidator("No elements allowed in EMPTY content model"); + + final String mErrorMsg; + + private EmptyValidator(String errorMsg) { + mErrorMsg = errorMsg; + } + + public static EmptyValidator getPcdataInstance() { return sPcdataInstance; } + public static EmptyValidator getEmptyInstance() { return sPcdataInstance; } + + /** + * Simple; can always (re)use instance itself; no state information + * is kept. + */ + @Override + public StructValidator newInstance() { + return this; + } + + @Override + public String tryToValidate(PrefixedName elemName) { + return mErrorMsg; + } + + /** + * If we ever get as far as element closing, things are all good; + * can just return null. + */ + @Override + public String fullyValid() { + return null; + } +} diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/dtd/FullDTDReader.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/dtd/FullDTDReader.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/dtd/FullDTDReader.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/dtd/FullDTDReader.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,3520 @@ +/* Woodstox XML processor + * + * Copyright (c) 2004- Tatu Saloranta, tatu.saloranta@iki.fi + * + * Licensed under the License specified in file LICENSE, included with + * the source code. + * You may not use this file except in compliance with the License. + * + * 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 com.ctc.wstx.dtd; + +import java.io.IOException; +import java.io.Writer; +import java.net.URL; +import java.text.MessageFormat; +import java.util.*; + +import javax.xml.stream.Location; +import javax.xml.stream.XMLReporter; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.events.NotationDeclaration; + +import org.codehaus.stax2.validation.XMLValidationProblem; +import org.codehaus.stax2.validation.XMLValidator; + +import com.ctc.wstx.api.ReaderConfig; +import com.ctc.wstx.cfg.ErrorConsts; +import com.ctc.wstx.cfg.XmlConsts; +import com.ctc.wstx.ent.*; +import com.ctc.wstx.evt.WNotationDeclaration; +import com.ctc.wstx.exc.WstxIOException; +import com.ctc.wstx.io.WstxInputData; +import com.ctc.wstx.io.WstxInputSource; +import com.ctc.wstx.util.*; + +/** + * Reader that reads in DTD information from internal or external subset. + *

+ * There are 2 main modes for DTDReader, depending on whether it is parsing + * internal or external subset. Parsing of internal subset is somewhat + * simpler, since no dependency checking is needed. For external subset, + * handling of parameter entities is bit more complicated, as care has to + * be taken to distinguish between using PEs defined in int. subset, and + * ones defined in ext. subset itself. This determines cachability of + * external subsets. + *

+ * Reader also implements simple stand-alone functionality for flattening + * DTD files (expanding all references to their eventual textual form); + * this is sometimes useful when optimizing modularized DTDs + * (which are more maintainable) into single monolithic DTDs (which in + * general can be more performant). + * + * @author Tatu Saloranta + */ +public class FullDTDReader + extends MinimalDTDReader +{ + /** + * Flag that can be changed to enable or disable interning of shared + * names; shared names are used for enumerated values to reduce + * memory usage. + */ + final static boolean INTERN_SHARED_NAMES = false; + + // // // Entity expansion types: + + final static Boolean ENTITY_EXP_GE = Boolean.FALSE; + + final static Boolean ENTITY_EXP_PE = Boolean.TRUE; + + /* + /////////////////////////////////////////////////////////// + // Configuration + /////////////////////////////////////////////////////////// + */ + + final int mConfigFlags; + + // Extracted wstx-specific settings: + + final boolean mCfgSupportDTDPP; + + /** + * This flag indicates whether we should build a validating 'real' + * validator (true, the usual case), + * or a simpler pseudo-validator that can do all non-validation tasks + * that are based on DTD info (entity expansion, notation references, + * default attribute values). Latter is used in non-validating mode. + *

+ */ + final boolean mCfgFullyValidating; + + /* + /////////////////////////////////////////////////////////// + // Entity handling, parameter entities (PEs) + /////////////////////////////////////////////////////////// + */ + + /** + * Set of parameter entities defined so far in the currently parsed + * subset. Note: the first definition sticks, entities can not be + * redefined. + *

+ * Keys are entity name Strings; values are instances of EntityDecl + */ + HashMap mParamEntities; + + /** + * Set of parameter entities already defined for the subset being + * parsed; namely, PEs defined in the internal subset passed when + * parsing matching external subset. Null when parsing internal + * subset. + */ + final HashMap mPredefdPEs; + + /** + * Set of parameter entities (ids) that have been referenced by this + * DTD; only maintained for external subsets, and only as long as + * no pre-defined PE has been referenced. + */ + Set mRefdPEs; + + /* + /////////////////////////////////////////////////////////// + // Entity handling, general entities (GEs) + /////////////////////////////////////////////////////////// + */ + + /** + * Set of generic entities defined so far in this subset. + * As with parameter entities, the first definition sticks. + *

+ * Keys are entity name Strings; values are instances of EntityDecl + *

+ * Note: this Map only contains entities declared and defined in the + * subset being parsed; no previously defined values are passed. + */ + HashMap mGeneralEntities; + + /** + * Set of general entities already defined for the subset being + * parsed; namely, PEs defined in the internal subset passed when + * parsing matching external subset. Null when parsing internal + * subset. Such entities are only needed directly for one purpose; + * to be expanded when reading attribute default value definitions. + */ + final HashMap mPredefdGEs; + + /** + * Set of general entities (ids) that have been referenced by this + * DTD; only maintained for external subsets, and only as long as + * no pre-defined GEs have been referenced. + */ + Set mRefdGEs; + + /* + /////////////////////////////////////////////////////////// + // Entity handling, both PEs and GEs + /////////////////////////////////////////////////////////// + */ + + /** + * Flag used to keep track of whether current (external) subset + * has referenced at least one PE that was pre-defined. + */ + boolean mUsesPredefdEntities = false; + + /* + /////////////////////////////////////////////////////////// + // Notation settings + /////////////////////////////////////////////////////////// + */ + + /** + * Set of notations defined so far. Since it's illegal to (try to) + * redefine notations, there's no specific precedence. + *

+ * Keys are entity name Strings; values are instances of + * NotationDecl objects + */ + HashMap mNotations; + + /** + * Notations already parsed before current subset; that is, + * notations from the internal subset if we are currently + * parsing matching external subset. + */ + final HashMap mPredefdNotations; + + /** + * Flag used to keep track of whether current (external) subset + * has referenced at least one notation that was defined in internal + * subset. If so, can not cache the external subset + */ + boolean mUsesPredefdNotations = false; + + /** + * Finally, we need to keep track of Notation references that were + * made prior to declaration. This is needed to ensure that all + * references can be properly resolved. + */ + HashMap mNotationForwardRefs; + + /* + /////////////////////////////////////////////////////////// + // Element specifications + /////////////////////////////////////////////////////////// + */ + + /** + * Map used to shared PrefixedName instances, to reduce memory usage + * of (qualified) element and attribute names + */ + HashMap mSharedNames = null; + + /** + * Contains definition of elements and matching content specifications. + * Also contains temporary placeholders for elements that are indirectly + * "created" by ATTLIST declarations that precede actual declaration + * for the ELEMENT referred to. + */ + LinkedHashMap mElements; + + /** + * Map used for sharing legal enumeration values; used since oftentimes + * same enumeration values are used with multiple attributes + */ + HashMap mSharedEnumValues = null; + + /* + /////////////////////////////////////////////////////////// + // Entity expansion state + /////////////////////////////////////////////////////////// + */ + + /** + * This is the attribute default value that is currently being parsed. + * Needs to be a global member due to the way entity expansion failures + * are reported: problems need to be attached to this object, even + * thought the default value itself will not be passed through. + */ + DefaultAttrValue mCurrAttrDefault = null; + + /** + * Flag that indicates if the currently expanding (or last expanded) + * entity is a Parameter Entity or General Entity. + */ + boolean mExpandingPE = false; + + /** + * Text buffer used for constructing expansion value of the internal + * entities, and for default attribute values. + * Lazily constructed when needed, reused. + */ + TextBuffer mValueBuffer = null; + + /* + /////////////////////////////////////////////////////////// + // Reader state + /////////////////////////////////////////////////////////// + */ + + /** + * Nesting count for conditionally included sections; 0 means that + * we are not inside such a section. Note that condition ignore is + * handled separately. + */ + int mIncludeCount = 0; + + /** + * This flag is used to catch uses of PEs in the internal subset + * within declarations (full declarations are ok, but not other types) + */ + boolean mCheckForbiddenPEs = false; + + /** + * Keyword of the declaration being currently parsed (if any). Can be + * used for error reporting purposes. + */ + String mCurrDeclaration; + + /* + /////////////////////////////////////////////////////////// + // DTD++ support information + /////////////////////////////////////////////////////////// + */ + + /** + * Flag that indicates if any DTD++ features have been encountered + * (in DTD++-supporting mode). + */ + boolean mAnyDTDppFeatures = false; + + /** + * Currently active default namespace URI. + */ + String mDefaultNsURI = ""; + + /** + * Prefix-to-NsURI mappings for this DTD, if any: lazily + * constructed when needed + */ + HashMap mNamespaces = null; + + /* + /////////////////////////////////////////////////////////// + // Additional support for creating expanded output + // of processed DTD. + /////////////////////////////////////////////////////////// + */ + + DTDWriter mFlattenWriter = null; + + /* + /////////////////////////////////////////////////////////// + // Support for SAX API impl: + /////////////////////////////////////////////////////////// + */ + + final DTDEventListener mEventListener; + + transient TextBuffer mTextBuffer = null; + + /* + /////////////////////////////////////////////////////////// + // Life-cycle + /////////////////////////////////////////////////////////// + */ + + /** + * Constructor used for reading/skipping internal subset. + */ + private FullDTDReader(WstxInputSource input, ReaderConfig cfg, + boolean constructFully, int xmlVersion) + { + this(input, cfg, false, null, constructFully, xmlVersion); + } + + /** + * Constructor used for reading external subset. + */ + private FullDTDReader(WstxInputSource input, ReaderConfig cfg, + DTDSubset intSubset, + boolean constructFully, int xmlVersion) + { + this(input, cfg, true, intSubset, constructFully, xmlVersion); + + // Let's make sure line/col offsets are correct... + input.initInputLocation(this, mCurrDepth, 0); + } + + /** + * Common initialization part of int/ext subset constructors. + */ + private FullDTDReader(WstxInputSource input, ReaderConfig cfg, + boolean isExt, DTDSubset intSubset, + boolean constructFully, int xmlVersion) + { + super(input, cfg, isExt); + /* What matters here is what the main xml doc had; that determines + * xml conformance level to use. + */ + mDocXmlVersion = xmlVersion; + mXml11 = cfg.isXml11(); + int cfgFlags = cfg.getConfigFlags(); + mConfigFlags = cfgFlags; + mCfgSupportDTDPP = (cfgFlags & CFG_SUPPORT_DTDPP) != 0; + mCfgFullyValidating = constructFully; + + mUsesPredefdEntities = false; + mParamEntities = null; + mRefdPEs = null; + mRefdGEs = null; + mGeneralEntities = null; + + // Did we get any existing parameter entities? + HashMap pes = (intSubset == null) ? + null : intSubset.getParameterEntityMap(); + if (pes == null || pes.isEmpty()) { + mPredefdPEs = null; + } else { + mPredefdPEs = pes; + } + + // How about general entities (needed only for attr. def. values) + HashMap ges = (intSubset == null) ? + null : intSubset.getGeneralEntityMap(); + if (ges == null || ges.isEmpty()) { + mPredefdGEs = null; + } else { + mPredefdGEs = ges; + } + + // And finally, notations + HashMap not = (intSubset == null) ? + null : intSubset.getNotationMap(); + if (not == null || not.isEmpty()) { + mPredefdNotations = null; + } else { + mPredefdNotations = not; + } + mEventListener = mConfig.getDTDEventListener(); + } + + /** + * Method called to read in the internal subset definition. + */ + public static DTDSubset readInternalSubset(WstxInputData srcData, + WstxInputSource input, + ReaderConfig cfg, + boolean constructFully, + int xmlVersion) + throws XMLStreamException + { + FullDTDReader r = new FullDTDReader(input, cfg, constructFully, xmlVersion); + // Need to read using the same low-level reader interface: + r.copyBufferStateFrom(srcData); + DTDSubset ss; + + try { + ss = r.parseDTD(); + } finally { + /* And then need to restore changes back to owner (line nrs etc); + * effectively means that we'll stop reading external DTD subset, + * if so. + */ + srcData.copyBufferStateFrom(r); + } + return ss; + } + + /** + * Method called to read in the external subset definition. + */ + public static DTDSubset readExternalSubset + (WstxInputSource src, ReaderConfig cfg, DTDSubset intSubset, + boolean constructFully, int xmlVersion) + throws XMLStreamException + { + FullDTDReader r = new FullDTDReader(src, cfg, intSubset, constructFully, xmlVersion); + return r.parseDTD(); + } + + /** + * Method that will parse, process and output contents of an external + * DTD subset. It will do processing similar to + * {@link #readExternalSubset}, but additionally will copy its processed + * ("flattened") input to specified writer. + * + * @param src Input source used to read the main external subset + * @param flattenWriter Writer to output processed DTD content to + * @param inclComments If true, will pass comments to the writer; if false, + * will strip comments out + * @param inclConditionals If true, will include conditional block markers, + * as well as intervening content; if false, will strip out both markers + * and ignorable sections. + * @param inclPEs If true, will output parameter entity declarations; if + * false will parse and use them, but not output. + */ + public static DTDSubset flattenExternalSubset(WstxInputSource src, Writer flattenWriter, + boolean inclComments, boolean inclConditionals, + boolean inclPEs) + throws IOException, XMLStreamException + { + ReaderConfig cfg = ReaderConfig.createFullDefaults(); + // Need to create a non-shared copy to populate symbol table field + cfg = cfg.createNonShared(new SymbolTable()); + + /* Let's assume xml 1.0... can be taken as an arg later on, if we + * truly care. + */ + FullDTDReader r = new FullDTDReader(src, cfg, null, true, XmlConsts.XML_V_UNKNOWN); + r.setFlattenWriter(flattenWriter, inclComments, inclConditionals, + inclPEs); + DTDSubset ss = r.parseDTD(); + r.flushFlattenWriter(); + flattenWriter.flush(); + return ss; + } + + private TextBuffer getTextBuffer() + { + if (mTextBuffer == null) { + mTextBuffer = TextBuffer.createTemporaryBuffer(); + mTextBuffer.resetInitialized(); + } else { + mTextBuffer.resetWithEmpty(); + } + return mTextBuffer; + } + + /* + /////////////////////////////////////////////////////////// + // Configuration + /////////////////////////////////////////////////////////// + */ + + /** + * Method that will set specified Writer as the 'flattening writer'; + * writer used to output flattened version of DTD read in. This is + * similar to running a C-preprocessor on C-sources, except that + * defining writer will not prevent normal parsing of DTD itself. + */ + public void setFlattenWriter(Writer w, boolean inclComments, + boolean inclConditionals, boolean inclPEs) + { + mFlattenWriter = new DTDWriter(w, inclComments, inclConditionals, + inclPEs); + } + + private void flushFlattenWriter() throws XMLStreamException { + mFlattenWriter.flush(mInputBuffer, mInputPtr); + } + + /* + /////////////////////////////////////////////////////////// + // Internal API + /////////////////////////////////////////////////////////// + */ + + /** + * Method that may need to be called by attribute default value + * validation code, during parsing.... + *

+ * Note: see base class for some additional remarks about this + * method. + */ + @Override + public EntityDecl findEntity(String entName) + { + if (mPredefdGEs != null) { + EntityDecl decl = mPredefdGEs.get(entName); + if (decl != null) { + return decl; + } + } + return mGeneralEntities.get(entName); + } + + /* + /////////////////////////////////////////////////////////// + // Main-level parsing methods + /////////////////////////////////////////////////////////// + */ + + protected DTDSubset parseDTD() + throws XMLStreamException + { + while (true) { + mCheckForbiddenPEs = false; // PEs are ok at this point + int i = getNextAfterWS(); + if (i < 0) { + if (mIsExternal) { // ok for external DTDs + break; + } + // Error for internal subset + throwUnexpectedEOF(SUFFIX_IN_DTD_INTERNAL); + } + if (i == '%') { // parameter entity + expandPE(); + continue; + } + + /* First, let's keep track of start of the directive; needed for + * entity and notation declaration events. + */ + mTokenInputTotal = mCurrInputProcessed + mInputPtr; + mTokenInputRow = mCurrInputRow; + mTokenInputCol = mInputPtr - mCurrInputRowStart; + + if (i == '<') { + // PEs not allowed within declarations, in the internal subset proper + mCheckForbiddenPEs = !mIsExternal && (mInput == mRootInput); + if (mFlattenWriter == null) { + parseDirective(); + } else { + parseDirectiveFlattened(); + } + continue; + } + + if (i == ']') { + if (mIncludeCount == 0 && !mIsExternal) { // End of internal subset + break; + } + if (mIncludeCount > 0) { // active INCLUDE block(s) open? + boolean suppress = (mFlattenWriter != null) && !mFlattenWriter.includeConditionals(); + + if (suppress) { + mFlattenWriter.flush(mInputBuffer, mInputPtr-1); + mFlattenWriter.disableOutput(); + } + + try { + // ]]> needs to be a token, can not come from PE: + char c = dtdNextFromCurr(); + if (c == ']') { + c = dtdNextFromCurr(); + if (c == '>') { + // Ok, fine, conditional include section ended. + --mIncludeCount; + continue; + } + } + throwDTDUnexpectedChar(c, "; expected ']]>' to close conditional include section"); + } finally { + if (suppress) { + mFlattenWriter.enableOutput(mInputPtr); + } + } + } + // otherwise will fall through, and give an error + } + + if (mIsExternal) { + throwDTDUnexpectedChar(i, "; expected a '<' to start a directive"); + } + throwDTDUnexpectedChar(i, "; expected a '<' to start a directive, or \"]>\" to end internal subset"); + } + + /* 05-Feb-2006, TSa: Not allowed to have unclosed INCLUDE/IGNORE + * blocks... + */ + if (mIncludeCount > 0) { // active INCLUDE block(s) open? + String suffix = (mIncludeCount == 1) ? "an INCLUDE block" : (""+mIncludeCount+" INCLUDE blocks"); + throwUnexpectedEOF(getErrorMsg()+"; expected closing marker for "+suffix); + } + + /* First check: have all notation references been resolved? + * (related to [WSTX-121]) + */ + if (mNotationForwardRefs != null && mNotationForwardRefs.size() > 0) { + _reportUndefinedNotationRefs(); + } + + // Ok; time to construct and return DTD data object. + DTDSubset ss; + + // There are more settings for ext. subsets: + if (mIsExternal) { + /* External subsets are cachable if they did not refer to any + * PEs or GEs defined in internal subset passed in (if any), + * nor to any notations. + * We don't care about PEs it defined itself, but need to pass + * in Set of PEs it refers to, to check if cached copy can be + * used with different int. subsets. + * We need not worry about notations referred, since they are + * not allowed to be re-defined. + */ + boolean cachable = !mUsesPredefdEntities && !mUsesPredefdNotations; + ss = DTDSubsetImpl.constructInstance(cachable, + mGeneralEntities, mRefdGEs, + null, mRefdPEs, + mNotations, mElements, + mCfgFullyValidating); + } else { + /* Internal subsets are not cachable (no unique way to refer + * to unique internal subsets), and there can be no references + * to pre-defined PEs, as none were passed. + */ + ss = DTDSubsetImpl.constructInstance(false, mGeneralEntities, null, + mParamEntities, null, + mNotations, mElements, + mCfgFullyValidating); + } + return ss; + } + + protected void parseDirective() + throws XMLStreamException + { + /* Hmmh. Don't think PEs are allowed to contain starting + * '!' (or '?')... and it has to come from the same + * input source too (no splits) + */ + char c = dtdNextFromCurr(); + if (c == '?') { // xml decl? + readPI(); + return; + } + if (c != '!') { // nothing valid + throwDTDUnexpectedChar(c, "; expected '!' to start a directive"); + } + + /* ignore/include, comment, or directive; we are still getting + * token from same section though + */ + c = dtdNextFromCurr(); + if (c == '-') { // plain comment + c = dtdNextFromCurr(); + if (c != '-') { + throwDTDUnexpectedChar(c, "; expected '-' for a comment"); + } + if (mEventListener != null && mEventListener.dtdReportComments()) { + readComment(mEventListener); + } else { + skipComment(); + } + } else if (c == '[') { + checkInclusion(); + } else if (c >= 'A' && c <= 'Z') { + handleDeclaration(c); + } else { + throwDTDUnexpectedChar(c, ErrorConsts.ERR_DTD_MAINLEVEL_KEYWORD); + } + } + + /** + * Method similar to {@link #parseDirective}, but one that takes care + * to properly output dtd contents via {@link com.ctc.wstx.dtd.DTDWriter} + * as necessary. + * Separated to simplify both methods; otherwise would end up with + * 'if (... flatten...) ... else ...' spaghetti code. + */ + protected void parseDirectiveFlattened() + throws XMLStreamException + { + /* First, need to flush any flattened output there may be, at + * this point (except for opening lt char): and then need to + * temporarily disable more output until we know the type and + * whether it should be output or not: + */ + mFlattenWriter.flush(mInputBuffer, mInputPtr-1); + mFlattenWriter.disableOutput(); + + /* Let's determine type here, and call appropriate skip/parse + * methods. + */ + char c = dtdNextFromCurr(); + if (c == '?') { // xml decl? + mFlattenWriter.enableOutput(mInputPtr); + mFlattenWriter.output("= 'A' && c <= 'Z') { + mFlattenWriter.enableOutput(mInputPtr); + mFlattenWriter.output(" 0) { + if (mFlattenWriter != null) { + mFlattenWriter.setFlattenStart(mInputPtr); + } + return true; + } + input.close(); + } catch (IOException ioe) { + throw constructFromIOE(ioe); + } + if (input == mRootInput) { + return false; + } + WstxInputSource parent = input.getParent(); + if (parent == null) { // sanity check! + throwNullParent(input); + } + /* 13-Feb-2006, TSa: Ok, do we violate a proper nesting constraints + * with this input block closure? + */ + if (mCurrDepth != input.getScopeId()) { + handleIncompleteEntityProblem(input); + } + + mInput = input = parent; + input.restoreContext(this); + if (mFlattenWriter != null) { + mFlattenWriter.setFlattenStart(mInputPtr); + } + mInputTopDepth = input.getScopeId(); + /* 21-Feb-2006, TSa: Since linefeed normalization needs to be + * suppressed for internal entity expansion, we may need to + * change the state... + */ + if (!mNormalizeLFs) { + mNormalizeLFs = !input.fromInternalEntity(); + } + // Maybe there are leftovers from that input in buffer now? + } while (mInputPtr >= mInputEnd); + + return true; + } + + @Override + protected boolean loadMoreFromCurrent() throws XMLStreamException + { + // Any flattened not-yet-output input to flush? + if (mFlattenWriter != null) { + mFlattenWriter.flush(mInputBuffer, mInputEnd); + } + + // Need to update offsets properly + mCurrInputProcessed += mInputEnd; + mCurrInputRowStart -= mInputEnd; + try { + int count = mInput.readInto(this); + if (count > 0) { + if (mFlattenWriter != null) { + mFlattenWriter.setFlattenStart(mInputPtr); + } + return true; + } + } catch (IOException ie) { + throwFromIOE(ie); + } + return false; + } + + @Override + protected boolean ensureInput(int minAmount) throws XMLStreamException + { + int currAmount = mInputEnd - mInputPtr; + if (currAmount >= minAmount) { + return true; + } + // Any flattened not-yet-output input to flush? + if (mFlattenWriter != null) { + mFlattenWriter.flush(mInputBuffer, mInputEnd); + } + try { + if (mInput.readMore(this, minAmount)) { + if (mFlattenWriter != null) { + //mFlattenWriter.setFlattenStart(mInputPtr); + mFlattenWriter.setFlattenStart(currAmount); + } + return true; + } + } catch (IOException ie) { + throwFromIOE(ie); + } + return false; + } + + /* + /////////////////////////////////////////////////////////// + // Internal methods, input access: + /////////////////////////////////////////////////////////// + */ + + private void loadMoreScoped(WstxInputSource currScope, + String entityName, Location loc) + throws XMLStreamException + { + boolean check = (mInput == currScope); + loadMore(getErrorMsg()); + // Did we get out of the scope? + if (check && (mInput != currScope)) { + _reportWFCViolation("Unterminated entity value for entity '" + +entityName+"' (definition started at " + +loc+")"); + } + } + + /** + * @return Next character from the current input block, if any left; + * NULL if end of block (entity expansion) + */ + private char dtdNextIfAvailable() + throws XMLStreamException + { + char c; + if (mInputPtr < mInputEnd) { + c = mInputBuffer[mInputPtr++]; + } else { + int i = peekNext(); + if (i < 0) { + return CHAR_NULL; + } + ++mInputPtr; + c = (char) i; + } + if (c == CHAR_NULL) { + throwNullChar(); + } + return c; + } + + /** + * Method that will get next character, and either return it as is (for + * normal chars), or expand parameter entity that starts with next + * character (which has to be '%'). + */ + private char getNextExpanded() + throws XMLStreamException + { + while (true) { + char c = (mInputPtr < mInputEnd) ? + mInputBuffer[mInputPtr++] : getNextChar(getErrorMsg()); + if (c != '%') { + return c; + } + expandPE(); + } + } + + private char skipDtdWs(boolean handlePEs) + throws XMLStreamException + { + while (true) { + char c = (mInputPtr < mInputEnd) + ? mInputBuffer[mInputPtr++] : getNextChar(getErrorMsg()); + if (c > CHAR_SPACE) { + if (c == '%' && handlePEs) { + expandPE(); + continue; + } + return c; + } + if (c == '\n' || c == '\r') { + skipCRLF(c); + } else if (c != CHAR_SPACE && c != '\t') { + throwInvalidSpace(c); + } + } + } + + /** + * Note: Apparently a parameter entity expansion does also count + * as white space (that is, PEs outside of quoted text are considered + * to be separated by white spaces on both sides). Fortunately this + * can be handled by 2 little hacks: both a start of a PE, and an + * end of input block (== end of PE expansion) count as succesful + * spaces. + * + * @return Character following the obligatory boundary (white space + * or PE start/end) + */ + private char skipObligatoryDtdWs() + throws XMLStreamException + { + /* Ok; since we need at least one space, or a PE, or end of input + * block, let's do this unique check first... + */ + int i = peekNext(); + char c; + + if (i == -1) { // just means 'local' EOF (since peek only checks current) + c = getNextChar(getErrorMsg()); + // Non-space, non PE is ok, due to end-of-block... + if (c > CHAR_SPACE && c != '%') { + return c; + } + } else { + c = mInputBuffer[mInputPtr++]; // was peek, need to read + if (c > CHAR_SPACE && c != '%') { + throwDTDUnexpectedChar(c, "; expected a separating white space"); + } + } + + // Ok, got it, now can loop... + while (true) { + if (c == '%') { + expandPE(); + } else if (c > CHAR_SPACE) { + break; + } else { + if (c == '\n' || c == '\r') { + skipCRLF(c); + } else if (c != CHAR_SPACE && c != '\t') { + throwInvalidSpace(c); + } + } + /* Now we got one space (or end of input block) -- no need to + * restrict get next on current block (in case PE ends); happens + * with xmltest/valid/not-sa/003.xml, for eaxmple. + */ + c = (mInputPtr < mInputEnd) + ? mInputBuffer[mInputPtr++] : getNextChar(getErrorMsg()); + } + return c; + } + + /** + * Method called to handle expansion of parameter entities. When called, + * '%' character has been encountered as a reference indicator, and + * now we should get parameter entity name. + */ + private void expandPE() + throws XMLStreamException + { + String id; + char c; + + if (mCheckForbiddenPEs) { + /* Ok; we hit a PE where we should not have (within the internal + * dtd subset proper, within a declaration). This is a WF error. + */ + throwForbiddenPE(); + } + + // 01-Jul-2004, TSa: When flattening, need to flush previous output + if (mFlattenWriter != null) { + // Flush up to but not including ampersand... + mFlattenWriter.flush(mInputBuffer, mInputPtr-1); + mFlattenWriter.disableOutput(); + c = (mInputPtr < mInputEnd) ? + mInputBuffer[mInputPtr++] : dtdNextFromCurr(); + id = readDTDName(c); + try { + c = (mInputPtr < mInputEnd) ? + mInputBuffer[mInputPtr++] : dtdNextFromCurr(); + } finally { + // will ignore name and colon (or whatever was parsed) + mFlattenWriter.enableOutput(mInputPtr); + } + } else { + c = (mInputPtr < mInputEnd) ? + mInputBuffer[mInputPtr++] : dtdNextFromCurr(); + id = readDTDName(c); + c = (mInputPtr < mInputEnd) ? + mInputBuffer[mInputPtr++] : dtdNextFromCurr(); + } + + // Should now get semicolon... + if (c != ';') { + throwDTDUnexpectedChar(c, "; expected ';' to end parameter entity name"); + } + mExpandingPE = true; + expandEntity(id, true, ENTITY_EXP_PE); + } + + /* + /////////////////////////////////////////////////////////// + // Internal methods, low-level parsing: + /////////////////////////////////////////////////////////// + */ + + /** + * Method called to verify whether input has specified keyword; if it + * has, returns null and points to char after the keyword; if not, + * returns whatever constitutes a keyword matched, for error + * reporting purposes. + */ + protected String checkDTDKeyword(String exp) + throws XMLStreamException + { + int i = 0; + int len = exp.length(); + char c = ' '; + + for (; i < len; ++i) { + if (mInputPtr < mInputEnd) { + c = mInputBuffer[mInputPtr++]; + } else { + c = dtdNextIfAvailable(); + if (c == CHAR_NULL) { // end of block, fine + return exp.substring(0, i); + } + } + if (c != exp.charAt(i)) { + break; + } + } + + if (i == len) { + // Got a match? Cool... except if identifier still continues... + c = dtdNextIfAvailable(); + if (c == CHAR_NULL) { // EOB, fine + return null; + } + if (!isNameChar(c)) { + --mInputPtr; // to push it back + return null; + } + } + StringBuilder sb = new StringBuilder(exp.substring(0, i)); + sb.append(c); + while (true) { + c = dtdNextIfAvailable(); + if (c == CHAR_NULL) { // EOB, fine + break; + } + if (!isNameChar(c) && c != ':') { + --mInputPtr; // to push it back + break; + } + sb.append(c); + } + return sb.toString(); + } + + /** + * Method called usually to indicate an error condition; will read rest + * of specified keyword (including characters that can be part of XML + * identifiers), append that to passed prefix (which is optional), and + * return resulting String. + * + * @param prefix Part of keyword already read in. + */ + protected String readDTDKeyword(String prefix) + throws XMLStreamException + { + StringBuilder sb = new StringBuilder(prefix); + + while (true) { + char c; + if (mInputPtr < mInputEnd) { + c = mInputBuffer[mInputPtr++]; + } else { + // Don't want to cross block boundary + c = dtdNextIfAvailable(); + if (c == CHAR_NULL) { + break; // end-of-block + } + } + if (!isNameChar(c) && c != ':') { + --mInputPtr; + break; + } + sb.append(c); + } + return sb.toString(); + } + + /** + * @return True, if input contains 'PUBLIC' keyword; false if it + * contains 'SYSTEM'; otherwise throws an exception. + */ + private boolean checkPublicSystemKeyword(char c) + throws XMLStreamException + { + String errId; + + if (c == 'P') { + errId = checkDTDKeyword("UBLIC"); + if (errId == null) { + return true; + } + errId = "P" + errId; + } else if (c == 'S') { + errId = checkDTDKeyword("YSTEM"); + if (errId == null) { + return false; + } + errId = "S" + errId; + } else { + if (!isNameStartChar(c)) { + throwDTDUnexpectedChar(c, "; expected 'PUBLIC' or 'SYSTEM' keyword"); + } + errId = readDTDKeyword(String.valueOf(c)); + } + + _reportWFCViolation("Unrecognized keyword '"+errId+"'; expected 'PUBLIC' or 'SYSTEM'"); + return false; // never gets here + } + + private String readDTDName(char c) + throws XMLStreamException + { + // Let's just check this before trying to parse the id... + if (!isNameStartChar(c)) { + throwDTDUnexpectedChar(c, "; expected an identifier"); + } + return parseFullName(c); + } + + private String readDTDLocalName(char c, boolean checkChar) + throws XMLStreamException + { + /* Let's just check this first, to get better error msg + * (parseLocalName() will double-check it too) + */ + if (checkChar && !isNameStartChar(c)) { + throwDTDUnexpectedChar(c, "; expected an identifier"); + } + return parseLocalName(c); + } + + /** + * Similar to {@link #readDTDName}, except that the rules are bit looser, + * ie. there are no additional restrictions for the first char + */ + private String readDTDNmtoken(char c) + throws XMLStreamException + { + char[] outBuf = getNameBuffer(64); + int outLen = outBuf.length; + int outPtr = 0; + + while (true) { + /* Note: colon not included in name char array, since it has + * special meaning WRT QNames, need to add into account here: + */ + if (!isNameChar(c) && c != ':') { + // Need to get at least one char + if (outPtr == 0) { + throwDTDUnexpectedChar(c, "; expected a NMTOKEN character to start a NMTOKEN"); + } + --mInputPtr; + break; + } + if (outPtr >= outLen) { + outBuf = expandBy50Pct(outBuf); + outLen = outBuf.length; + } + outBuf[outPtr++] = c; + if (mInputPtr < mInputEnd) { + c = mInputBuffer[mInputPtr++]; + } else { + c = dtdNextIfAvailable(); + if (c == CHAR_NULL) { // end-of-block + break; + } + } + } + + /* Nmtokens need not be canonicalized; they will be processed + * as necessary later on: + */ + return new String(outBuf, 0, outPtr); + } + + /** + * Method that will read an element or attribute name from DTD; depending + * on namespace mode, it can have prefix as well. + *

+ * Note: returned {@link PrefixedName} instances are canonicalized so that + * all instances read during parsing of a single DTD subset so that + * identity comparison can be used instead of calling equals() + * method (but only within a single subset!). This also reduces memory + * usage to some extent. + */ + private PrefixedName readDTDQName(char firstChar) + throws XMLStreamException + { + String prefix, localName; + + if (!mCfgNsEnabled) { + prefix = null; + localName = parseFullName(firstChar); + } else { + localName = parseLocalName(firstChar); + /* Hmmh. This is tricky; should only read from the current + * scope, but it is ok to hit end-of-block if it was a PE + * expansion... + */ + char c = dtdNextIfAvailable(); + if (c == CHAR_NULL) { // end-of-block + // ok, that's it... + prefix = null; + } else { + if (c == ':') { // Ok, got namespace and local name + prefix = localName; + c = dtdNextFromCurr(); + localName = parseLocalName(c); + } else { + prefix = null; + --mInputPtr; + } + } + } + + return findSharedName(prefix, localName); + } + + private char readArity() + throws XMLStreamException + { + char c = (mInputPtr < mInputEnd) ? + mInputBuffer[mInputPtr++] : getNextChar(getErrorMsg()); + if (c == '?' || c == '*' || c == '+') { + return c; + } + // Hmmh, not recognized, let's put it back: + --mInputPtr; + + // Default is 'just one' + return ' '; + } + + /** + * Method that reads and pre-processes replacement text for an internal + * entity (parameter or generic). + */ + private char[] parseEntityValue(String id, Location loc, char quoteChar) + throws XMLStreamException + { + /* 25-Jun-2004, TSa: Let's first mark current input source as the + * scope, so we can both make sure it ends in this input + * context (file), and that embedded single/double quotes + * in potentially expanded entities do not end the value + * definition (as per XML 1.0/3, 4.4.5) + */ + WstxInputSource currScope = mInput; + + /* 18-Jul-2004, TSa: Also, let's see if parameter entities are + * allowed; they are only legal outside of main internal subset + * (ie. main XML input) file (or to be precise; they are legal + * in the int. subset only as complete declarations) + */ + //boolean allowPEs = mIsExternal || (mInput != mRootInput); + + TextBuffer tb = mValueBuffer; + if (tb == null) { + tb = TextBuffer.createTemporaryBuffer(); + } + tb.resetInitialized(); + + char[] outBuf = tb.getCurrentSegment(); + int outPtr = tb.getCurrentSegmentSize(); + + while (true) { + if (mInputPtr >= mInputEnd) { + loadMoreScoped(currScope, id, loc); + } + char c = mInputBuffer[mInputPtr++]; + + // Let's get most normal chars 'skipped' first + if (c >= CHAR_FIRST_PURE_TEXT) { + ; + } else if (c == quoteChar) { + // Only end if we are in correct scope: + if (mInput == currScope) { + break; + } + } else if (c == '&') { // char entity that needs to be replaced? + /* 06-Sep-2004, TSa: We can NOT expand pre-defined entities, as + * XML specs consider them 'real' (non-char) entities. + * And expanding them would cause problems with entities + * that have such entities. + */ + int d = resolveCharOnlyEntity(false); + // Did we get a real char entity? + if (d != 0) { + if (d <= 0xFFFF) { + c = (char) d; + } else { + // Need more room? + if (outPtr >= outBuf.length) { + outBuf = tb.finishCurrentSegment(); + outPtr = 0; + } + d -= 0x10000; + outBuf[outPtr++] = (char) ((d >> 10) + 0xD800);; + c = (char) ((d & 0x3FF) + 0xDC00); + } + } else { + /* 11-Feb-2006, TSa: Even so, must verify that the + * entity reference is well-formed. + */ + boolean first = true; + while (true) { + if (outPtr >= outBuf.length) { // need more room? + outBuf = tb.finishCurrentSegment(); + outPtr = 0; + } + outBuf[outPtr++] = c; // starting with '&' + if (mInputPtr >= mInputEnd) { + loadMoreScoped(currScope, id, loc); + } + c = mInputBuffer[mInputPtr++]; + if (c == ';') { + break; + } + if (first) { + first = false; + if (isNameStartChar(c)) { + continue; + } + } else { + if (isNameChar(c)) { + continue; + } + } + if (c == ':' && !mCfgNsEnabled) { + continue; // fine in non-ns mode + } + if (first) { // missing name + throwDTDUnexpectedChar(c, "; expected entity name after '&'"); + } + throwDTDUnexpectedChar(c, "; expected semi-colon after entity name"); + } + // we can just fall through to let semicolon be added + } + // Either '&' itself, or expanded char entity + } else if (c == '%') { // param entity? + expandPE(); + // Need to loop over, no char available yet + continue; + } else if (c < CHAR_SPACE) { + if (c == '\n') { + markLF(); + } else if (c == '\r') { + if (skipCRLF(c)) { + if (!mNormalizeLFs) { + // Special handling, to output 2 chars at a time: + if (outPtr >= outBuf.length) { // need more room? + outBuf = tb.finishCurrentSegment(); + outPtr = 0; + } + outBuf[outPtr++] = c; + } + c = '\n'; + } else { + if (mNormalizeLFs) { // Mac LF + c = '\n'; + } + } + } else if (c != '\t') { + throwInvalidSpace(c); + } + } + + // Need more room? + if (outPtr >= outBuf.length) { + outBuf = tb.finishCurrentSegment(); + outPtr = 0; + } + // Ok, let's add char to output: + outBuf[outPtr++] = c; + } + tb.setCurrentLength(outPtr); + + // Ok, now need the closing '>': + char c = skipDtdWs(true); + if (c != '>') { + throwDTDUnexpectedChar(c, "; expected closing '>' after ENTITY declaration"); + } + char[] result = tb.contentsAsArray(); + mValueBuffer = tb; // recycle, if needed later on + + return result; + } + + /** + * This method is similar to {@link #parseEntityValue} in some ways, + * but has some notable differences, due to the way XML specs define + * differences. Main differences are that parameter entities are not + * allowed (or rather, recognized as entities), and that general + * entities need to be verified, but NOT expanded right away. + * Whether forward references are allowed or not is an open question + * right now. + */ + private void parseAttrDefaultValue(DefaultAttrValue defVal, char quoteChar, PrefixedName attrName, + Location loc, boolean gotFixed) + throws XMLStreamException + { + if (quoteChar != '"' && quoteChar != '\'') { // caller doesn't test it + String msg = "; expected a single or double quote to enclose the default value"; + if (!gotFixed) { + msg += ", or one of keywords (#REQUIRED, #IMPLIED, #FIXED)"; + } + msg += " (for attribute '"+attrName+"')"; + throwDTDUnexpectedChar(quoteChar, msg); + } + + /* Let's mark the current input source as the scope, so we can both + * make sure it ends in this input context (DTD subset), and that + * embedded single/double quotes in potentially expanded entities do + * not end the value definition (as per XML 1.0/3, 4.4.5) + */ + WstxInputSource currScope = mInput; + + TextBuffer tb = mValueBuffer; + if (tb == null) { + tb = TextBuffer.createTemporaryBuffer(); + } + tb.resetInitialized(); + + int outPtr = 0; + char[] outBuf = tb.getCurrentSegment(); + int outLen = outBuf.length; + + /* One more note: this is mostly cut'n pasted from stream reader's + * parseNormalizedAttrValue... + */ + main_loop: + + while (true) { + if (mInputPtr >= mInputEnd) { + boolean check = (mInput == currScope); + loadMore(getErrorMsg()); + // Did we get out of the scope? + if (check && (mInput != currScope)) { + _reportWFCViolation("Unterminated attribute default value for attribute '" + +attrName+"' (definition started at " + +loc+")"); + } + } + char c = mInputBuffer[mInputPtr++]; + + // Let's do a quick for most attribute content chars: + if (c < CHAR_FIRST_PURE_TEXT) { + if (c <= CHAR_SPACE) { + if (c == '\n') { + markLF(); + } else if (c == '\r') { + c = getNextChar(SUFFIX_IN_DEF_ATTR_VALUE); + if (c != '\n') { // nope, not 2-char lf (Mac?) + --mInputPtr; + c = mNormalizeLFs ? '\n' : '\r'; + } else { + // Fine if we are to normalize lfs + /* !!! 20-Jan-2007, TSa: Hmmh. Not sure if and + * how to preserve: for now, let's assume there's + * no need. + */ + /* + if (!mNormalizeLFs) { + if (outPtr >= outLen) { // need more room? + outBuf = tb.finishCurrentSegment(); + outPtr = 0; + outLen = outBuf.length; + } + outBuf[outPtr++] = '\r'; + // c is fine to continue + } + */ + } + markLF(); + } else if (c != CHAR_SPACE && c != '\t') { + throwInvalidSpace(c); + } + c = CHAR_SPACE; + } else if (c == quoteChar) { + /* It is possible to get these via expanded entities; + * need to make sure this is the same input level as + * the one that had starting quote + */ + if (mInput == currScope) { + break; + } + } else if (c == '&') { // an entity of some sort... + /* Will need to expand char entities and pre-defd + * int. entities (amp, lt, apos, gt): first method + * is just more optimized than the second + */ + int d; + if (inputInBuffer() >= 3) { + d = resolveSimpleEntity(true); + } else { + d = resolveCharOnlyEntity(true); + } + // Only get null if it's a 'real' general entity... + if (d == 0) { + c = getNextChar(SUFFIX_IN_ENTITY_REF); + String id = parseEntityName(c); + try { + mCurrAttrDefault = defVal; + mExpandingPE = false; + expandEntity(id, false, ENTITY_EXP_GE); + } finally { + mCurrAttrDefault = null; + } + // Ok, should have updated the input source by now + continue main_loop; + } + + if (c <= 0xFFFF) { + + } else{ + if (d <= 0xFFFF) { + c = (char) d; + } else { + // Need more room? + if (outPtr >= outBuf.length) { + outBuf = tb.finishCurrentSegment(); + outPtr = 0; + } + d -= 0x10000; + outBuf[outPtr++] = (char) ((d >> 10) + 0xD800);; + c = (char) ((d & 0x3FF) + 0xDC00); + } + } + } else if (c == '<') { + throwDTDUnexpectedChar(c, SUFFIX_IN_DEF_ATTR_VALUE); + } + } // if (c < CHAR_FIRST_PURE_TEXT) + + // Ok, let's just add char in, whatever it was + if (outPtr >= outLen) { // need more room? + outBuf = tb.finishCurrentSegment(); + outPtr = 0; + outLen = outBuf.length; + } + outBuf[outPtr++] = c; + } + + tb.setCurrentLength(outPtr); + defVal.setValue(tb.contentsAsString()); + mValueBuffer = tb; + } + + /** + * Method similar to {@link #skipPI}, but one that does basic + * well-formedness checks. + */ + protected void readPI() + throws XMLStreamException + { + String target = parseFullName(); + if (target.length() == 0) { + _reportWFCViolation(ErrorConsts.ERR_WF_PI_MISSING_TARGET); + } + if (target.equalsIgnoreCase("xml")) { + _reportWFCViolation(ErrorConsts.ERR_WF_PI_XML_TARGET, target); + } + + char c = dtdNextFromCurr(); + // Ok, need a space between target and data nonetheless + if (!isSpaceChar(c)) { // except if it ends right away + if (c != '?' || dtdNextFromCurr() != '>') { + throwUnexpectedChar(c, ErrorConsts.ERR_WF_PI_XML_MISSING_SPACE); + } + if (mEventListener != null) { + mEventListener.dtdProcessingInstruction(target, ""); + } + } else if (mEventListener == null) { + /* Otherwise, not that much to check since we don't care about + * the contents. + */ + while (true) { + c = (mInputPtr < mInputEnd) + ? mInputBuffer[mInputPtr++] : dtdNextFromCurr(); + if (c == '?') { + do { + c = (mInputPtr < mInputEnd) + ? mInputBuffer[mInputPtr++] : dtdNextFromCurr(); + } while (c == '?'); + if (c == '>') { + break; + } + } + if (c < CHAR_SPACE) { + if (c == '\n' || c == '\r') { + skipCRLF(c); + } else if (c != '\t') { + throwInvalidSpace(c); + } + } + } + } else { + // 24-Nov-2006, TSa: Actually, someone does care... + // First, need to skip extra space (if any) + while (c <= CHAR_SPACE) { + if (c == '\n' || c == '\r') { + skipCRLF(c); + } else if (c != '\t' && c != ' ') { + throwInvalidSpace(c); + } + c = (mInputPtr < mInputEnd) + ? mInputBuffer[mInputPtr++] : dtdNextFromCurr(); + } + + TextBuffer tb = getTextBuffer(); + char[] outBuf = tb.getCurrentSegment(); + int outPtr = 0; + + while (true) { + if (c == '?') { + while (true) { + c = (mInputPtr < mInputEnd) + ? mInputBuffer[mInputPtr++] : dtdNextFromCurr(); + if (c != '?') { + break; + } + if (outPtr >= outBuf.length) { + outBuf = tb.finishCurrentSegment(); + outPtr = 0; + } + outBuf[outPtr++] = c; + } + if (c == '>') { + break; + } + // Need to push back char that follows '?', output '?' + --mInputPtr; + c = '?'; + } else if (c < CHAR_SPACE) { + if (c == '\n' || c == '\r') { + skipCRLF(c); + c = '\n'; + } else if (c != '\t') { + throwInvalidSpace(c); + } + } + // Need more room? + if (outPtr >= outBuf.length) { + outBuf = tb.finishCurrentSegment(); + outPtr = 0; + } + // Ok, let's add char to output: + outBuf[outPtr++] = c; + c = (mInputPtr < mInputEnd) + ? mInputBuffer[mInputPtr++] : dtdNextFromCurr(); + } + tb.setCurrentLength(outPtr); + String data = tb.contentsAsString(); + mEventListener.dtdProcessingInstruction(target, data); + } + } + + /** + * Method similar to {@link #skipComment}, but that has to collect + * contents, to be reported for a SAX handler. + */ + protected void readComment(DTDEventListener l) + throws XMLStreamException + { + TextBuffer tb = getTextBuffer(); + char[] outBuf = tb.getCurrentSegment(); + int outPtr = 0; + + while (true) { + char c = (mInputPtr < mInputEnd) + ? mInputBuffer[mInputPtr++] : dtdNextFromCurr(); + if (c < CHAR_SPACE) { + if (c == '\n' || c == '\r') { + skipCRLF(c); + c = '\n'; + } else if (c != '\t') { + throwInvalidSpace(c); + } + } else if (c == '-') { + c = dtdNextFromCurr(); + if (c == '-') { // Ok, has to be end marker then: + // Either get '>' or error: + c = dtdNextFromCurr(); + if (c != '>') { + throwParseError(ErrorConsts.ERR_HYPHENS_IN_COMMENT); + } + break; + } + c = '-'; + --mInputPtr; // need to push back the second char read + } + // Need more room? + if (outPtr >= outBuf.length) { + outBuf = tb.finishCurrentSegment(); + outPtr = 0; + } + // Ok, let's add char to output: + outBuf[outPtr++] = c; + } + tb.setCurrentLength(outPtr); + tb.fireDtdCommentEvent(l); + } + + /* + /////////////////////////////////////////////////////////// + // Internal methods, conditional blocks: + /////////////////////////////////////////////////////////// + */ + + private void checkInclusion() + throws XMLStreamException + { + String keyword; + + // INCLUDE/IGNORE not allowed in internal subset... + /* 18-Jul-2004, TSa: Except if it's in an expanded parsed external + * entity... + */ + if (!mIsExternal && mInput == mRootInput) { + _reportWFCViolation("Internal DTD subset can not use (INCLUDE/IGNORE) directives (except via external entities)"); + } + + char c = skipDtdWs(true); + if (c != 'I') { + // let's obtain the keyword for error reporting purposes: + keyword = readDTDKeyword(String.valueOf(c)); + } else { + c = dtdNextFromCurr(); + if (c == 'G') { + keyword = checkDTDKeyword("NORE"); + if (keyword == null) { + handleIgnored(); + return; + } + keyword = "IG"+keyword; + } else if (c == 'N') { + keyword = checkDTDKeyword("CLUDE"); + if (keyword == null) { + handleIncluded(); + return; + } + keyword = "IN"+keyword; + } else { + --mInputPtr; + keyword = readDTDKeyword("I"); + } + } + + // If we get here, it was an error... + _reportWFCViolation("Unrecognized directive '"+keyword+"'; expected either 'IGNORE' or 'INCLUDE'"); + } + + private void handleIncluded() + throws XMLStreamException + { + char c = skipDtdWs(false); + if (c != '[') { + throwDTDUnexpectedChar(c, "; expected '[' to follow 'INCLUDE' directive"); + } + ++mIncludeCount; + } + + private void handleIgnored() + throws XMLStreamException + { + char c = skipDtdWs(false); + int count = 1; // Nesting of IGNORE/INCLUDE sections we have to match + + if (c != '[') { + throwDTDUnexpectedChar(c, "; expected '[' to follow 'IGNORE' directive"); + } + + /* Ok; now, let's just skip until we get the closing ']]>' + */ + String errorMsg = getErrorMsg(); + while (true) { + c = (mInputPtr < mInputEnd) + ? mInputBuffer[mInputPtr++] : getNextChar(errorMsg); + if (c < CHAR_SPACE) { + if (c == '\n' || c == '\r') { + skipCRLF(c); + } else if (c != '\t') { + throwInvalidSpace(c); + } + } else if (c == ']') { // closing? + if (getNextChar(errorMsg) == ']' + && getNextChar(errorMsg) == '>') { + if (--count < 1) { // done! + return; + } + // nested ignores, let's just continue + } else { + --mInputPtr; // need to push one char back, may be '<' + } + } else if (c == '<') { + if (getNextChar(errorMsg) == '!' + && getNextChar(errorMsg) == '[') { + // Further nesting, sweet + ++count; + } else { + --mInputPtr; // need to push one char back, may be '<' + } + } + } + } + + /* + /////////////////////////////////////////////////////////// + // Internal methods, validation, exceptions + /////////////////////////////////////////////////////////// + */ + + private void _reportUndefinedNotationRefs() + throws XMLStreamException + { + int count = mNotationForwardRefs.size(); + + String id = mNotationForwardRefs.keySet().iterator().next(); + String msg = ""+count+" referenced notation"+((count == 1) ? "":"s")+" undefined: first one '"+id+"'"; + _reportVCViolation(msg); + } + + private void _reportBadDirective(String dir) + throws XMLStreamException + { + String msg = "Unrecognized DTD directive ''; expected ATTLIST, ELEMENT, ENTITY or NOTATION"; + if (mCfgSupportDTDPP) { + msg += " (or, for DTD++, TARGETNS)"; + } + _reportWFCViolation(msg); + } + + private void _reportVCViolation(String msg) + throws XMLStreamException + { + /* 01-Sep-2006, TSa: Not 100% sure what's the right way to do it -- + * they are errors (non-fatal, but not warnings), but the way + * base class handles things, we probably better 'downgrade' + * them to warnings in non-validating mode. + */ + if (mCfgFullyValidating) { + reportValidationProblem(msg, XMLValidationProblem.SEVERITY_ERROR); + } else { + reportValidationProblem(msg, XMLValidationProblem.SEVERITY_WARNING); + } + } + + private void _reportWFCViolation(String msg) + throws XMLStreamException + { + throwParseError(msg); + } + + private void _reportWFCViolation(String format, Object arg) + throws XMLStreamException + { + throwParseError(format, arg, null); + } + + private void throwDTDElemError(String msg, Object elem) + throws XMLStreamException + { + _reportWFCViolation(elemDesc(elem) + ": " + msg); + } + + private void throwDTDAttrError(String msg, DTDElement elem, PrefixedName attrName) + throws XMLStreamException + { + _reportWFCViolation(attrDesc(elem, attrName) + ": " + msg); + } + + private void throwDTDUnexpectedChar(int i, String extraMsg) + throws XMLStreamException + { + if (extraMsg == null) { + throwUnexpectedChar(i, getErrorMsg()); + } + throwUnexpectedChar(i, getErrorMsg()+extraMsg); + } + + private void throwForbiddenPE() + throws XMLStreamException + { + _reportWFCViolation("Can not have parameter entities in the internal subset, except for defining complete declarations (XML 1.0, #2.8, WFC 'PEs In Internal Subset')"); + } + + private String elemDesc(Object elem) { + return "Element <"+elem+">)"; + } + + private String attrDesc(Object elem, PrefixedName attrName) { + return "Attribute '"+attrName+"' (of element <"+elem+">)"; + } + + private String entityDesc(WstxInputSource input) { + return "Entity &"+input.getEntityId()+";"; + } + + /* + /////////////////////////////////////////////////////////// + // Internal methods, main-level declaration parsing + /////////////////////////////////////////////////////////// + */ + + /** + *

+ * Note: c is known to be a letter (from 'A' to 'Z') at this poit. + */ + private void handleDeclaration(char c) + throws XMLStreamException + { + String keyw = null; + + /* We need to ensure that PEs do not span declaration boundaries + * (similar to element nesting wrt. GE expansion for xml content). + * This VC is defined in xml 1.0, section 2.8 as + * "VC: Proper Declaration/PE Nesting" + */ + /* We have binary depths within DTDs, for now: since the declaration + * just started, we should now have 1 as the depth: + */ + mCurrDepth = 1; + + try { + do { // dummy loop, for break + if (c == 'A') { // ATTLIST? + keyw = checkDTDKeyword("TTLIST"); + if (keyw == null) { + mCurrDeclaration = "ATTLIST"; + handleAttlistDecl(); + break; + } + keyw = "A" + keyw; + } else if (c == 'E') { // ENTITY, ELEMENT? + c = dtdNextFromCurr(); + if (c == 'N') { + keyw = checkDTDKeyword("TITY"); + if (keyw == null) { + mCurrDeclaration = "ENTITY"; + handleEntityDecl(false); + break; + } + keyw = "EN" + keyw; + } else if (c == 'L') { + keyw = checkDTDKeyword("EMENT"); + if (keyw == null) { + mCurrDeclaration = "ELEMENT"; + handleElementDecl(); + break; + } + keyw = "EL" + keyw; + } else { + keyw = readDTDKeyword("E"+c); + } + } else if (c == 'N') { // NOTATION? + keyw = checkDTDKeyword("OTATION"); + if (keyw == null) { + mCurrDeclaration = "NOTATION"; + handleNotationDecl(); + break; + } + keyw = "N" + keyw; + } else if (c == 'T' && mCfgSupportDTDPP) { // (dtd++ only) TARGETNS? + keyw = checkDTDKeyword("ARGETNS"); + if (keyw == null) { + mCurrDeclaration = "TARGETNS"; + handleTargetNsDecl(); + break; + } + keyw = "T" + keyw; + } else { + keyw = readDTDKeyword(String.valueOf(c)); + } + // If we got this far, we got a problem... + _reportBadDirective(keyw); + } while (false); + /* Ok: now, the current input can not have been started + * within the scope... so: + */ + if (mInput.getScopeId() > 0) { + handleGreedyEntityProblem(mInput); + } + + } finally { + // Either way, declaration has ended now... + mCurrDepth = 0; + mCurrDeclaration = null; + } + } + + /** + * Specialized method that handles potentially suppressable entity + * declaration. Specifically: at this point it is known that first + * letter is 'E', that we are outputting flattened DTD info, + * and that parameter entity declarations are to be suppressed. + * Furthermore, flatten output is still being disabled, and needs + * to be enabled by the method at some point. + */ + private void handleSuppressedDeclaration() + throws XMLStreamException + { + String keyw; + char c = dtdNextFromCurr(); + + if (c == 'N') { + keyw = checkDTDKeyword("TITY"); + if (keyw == null) { + handleEntityDecl(true); + return; + } + keyw = "EN" + keyw; + mFlattenWriter.enableOutput(mInputPtr); // error condition... + } else { + mFlattenWriter.enableOutput(mInputPtr); + mFlattenWriter.output(" m = getElementMap(); + DTDElement elem = m.get(elemName); + + if (elem == null) { // ok, need a placeholder + // Let's add ATTLIST location as the temporary location too + elem = DTDElement.createPlaceholder(mConfig, loc, elemName); + m.put(elemName, elem); + } + + // Ok, need to loop to get all attribute defs: + int index = 0; + + while (true) { + /* White space is optional, if we get the closing '>' char; + * otherwise it's obligatory. + */ + c = getNextExpanded(); + if (isSpaceChar(c)) { + // Let's push it back in case it's LF, to be handled properly + --mInputPtr; + c = skipDtdWs(true); + + /* 26-Jan-2006, TSa: actually there are edge cases where + * we may get the attribute name right away (esp. + * with PEs...); so let's defer possible error for + * later on. Should not allow missing spaces between + * attribute declarations... ? + */ + /* + } else if (c != '>') { + throwDTDUnexpectedChar(c, "; excepted either '>' closing ATTLIST declaration, or a white space character separating individual attribute declarations"); + */ + } + if (c == '>') { + break; + } + handleAttrDecl(elem, c, index, loc); + ++index; + } + } + + private void handleElementDecl() + throws XMLStreamException + { + char c = skipObligatoryDtdWs(); + final PrefixedName elemName = readDTDQName(c); + + /* Ok, event needs to know its exact starting point (opening '<' + * char), let's get that info now (note: data has been preserved + * earlier) + */ + Location loc = getStartLocation(); + + // Ok; name got, need some white space next + c = skipObligatoryDtdWs(); + + /* Then the content spec: either a special case (ANY, EMPTY), or + * a parenthesis group for 'real' content spec + */ + StructValidator val = null; + int vldContent = XMLValidator.CONTENT_ALLOW_ANY_TEXT; + + if (c == '(') { // real content model + c = skipDtdWs(true); + if (c == '#') { + val = readMixedSpec(elemName, mCfgFullyValidating); + vldContent = XMLValidator.CONTENT_ALLOW_ANY_TEXT; // checked against DTD + } else { + --mInputPtr; // let's push it back... + ContentSpec spec = readContentSpec(elemName, true, mCfgFullyValidating); + val = spec.getSimpleValidator(); + if (val == null) { + val = new DFAValidator(DFAState.constructDFA(spec)); + } + vldContent = XMLValidator.CONTENT_ALLOW_WS; // checked against DTD + } + } else if (isNameStartChar(c)) { + do { // dummy loop to allow break: + String keyw = null; + if (c == 'A') { + keyw = checkDTDKeyword("NY"); + if (keyw == null) { + vldContent = XMLValidator.CONTENT_ALLOW_ANY_TEXT; // no DTD checks + break; + } + keyw = "A"+keyw; + } else if (c == 'E') { + keyw = checkDTDKeyword("MPTY"); + if (keyw == null) { + val = EmptyValidator.getPcdataInstance(); + vldContent = XMLValidator.CONTENT_ALLOW_NONE; // needed to prevent non-elements too + break; + } + keyw = "E"+keyw; + } else { + --mInputPtr; + keyw = readDTDKeyword(String.valueOf(c)); + } + _reportWFCViolation("Unrecognized DTD content spec keyword '" + +keyw+"' (for element <"+elemName+">); expected ANY or EMPTY"); + } while (false); + } else { + throwDTDUnexpectedChar(c, ": excepted '(' to start content specification for element <"+elemName+">"); + } + + // Ok, still need the trailing gt-char to close the declaration: + c = skipDtdWs(true); + if (c != '>') { + throwDTDUnexpectedChar(c, "; expected '>' to finish the element declaration for <"+elemName+">"); + } + + LinkedHashMap m = getElementMap(); + DTDElement oldElem = m.get(elemName); + // Ok to have it if it's not 'really' declared + + if (oldElem != null) { + if (oldElem.isDefined()) { // oops, a problem! + /* 03-Feb-2006, TSa: Hmmh. Apparently all other XML parsers + * consider it's ok in non-validating mode. All right. + */ + if (mCfgFullyValidating) { + DTDSubsetImpl.throwElementException(oldElem, loc); + } else { + // let's just ignore re-definition if not validating + return; + } + } + + /* 09-Sep-2004, TSa: Need to transfer existing attribute + * definitions, however... + */ + oldElem = oldElem.define(loc, val, vldContent); + } else { + // Sweet, let's then add the definition: + oldElem = DTDElement.createDefined(mConfig, loc, elemName, val, vldContent); + } + m.put(elemName, oldElem); + } + + /** + * This method is tricky to implement, since it can contain parameter + * entities in multiple combinations... and yet declare one as well. + * + * @param suppressPEDecl If true, will need to take of enabling/disabling + * of flattened output. + */ + private void handleEntityDecl(boolean suppressPEDecl) + throws XMLStreamException + { + /* Hmmh. It seems that PE reference are actually accepted + * even here... which makes distinguishing definition from + * reference bit challenging. + */ + char c = dtdNextFromCurr(); + boolean gotSeparator = false; + boolean isParam = false; + + while (true) { + if (c == '%') { // reference? + // note: end-of-block acceptable, same as space + char d = dtdNextIfAvailable(); + if (d == CHAR_NULL || isSpaceChar(d)) { // ok, PE declaration + isParam = true; + if (d == '\n' || c == '\r') { + skipCRLF(d); + } + break; + } + // Reference? + if (!isNameStartChar(d)) { + throwDTDUnexpectedChar(d, "; expected a space (for PE declaration) or PE reference name"); + } + --mInputPtr; // need to push the first char back, then + gotSeparator = true; + expandPE(); + // need the next char, from the new scope... or if it gets closed, this one + c = dtdNextChar(); + } else if (!isSpaceChar(c)) { // non-PE entity? + break; + } else { + gotSeparator = true; + c = dtdNextFromCurr(); + } + } + + if (!gotSeparator) { + throwDTDUnexpectedChar(c, "; expected a space separating ENTITY keyword and entity name"); + } + + /* Ok; fair enough: now must have either '%', or a name start + * character: + */ + if (isParam) { + /* PE definition: at this point we already know that there must + * have been a space... just need to skip the rest, if any. + * Also, can still get a PE to expand (name of a PE to define + * from a PE reference) + */ + c = skipDtdWs(true); + } + + if (suppressPEDecl) { // only if mFlattenWriter != null + if (!isParam) { + mFlattenWriter.enableOutput(mInputPtr); + mFlattenWriter.output(" m; + if (isParam) { + m = mParamEntities; + if (m == null) { + mParamEntities = m = new HashMap(); + } + } else { + m = mGeneralEntities; + if (m == null) { + /* Let's try to get insert-ordered Map, to be able to + * report redefinition problems when validating subset + * compatibility + */ + mGeneralEntities = m = new LinkedHashMap(); + } + } + + // First definition sticks... + Object old; + if (m.size() > 0 && (old = m.get(id)) != null) { + // Application may want to know about the problem... + XMLReporter rep = mConfig.getXMLReporter(); + if (rep != null) { + EntityDecl oldED = (EntityDecl) old; + String str = " entity '"+id+"' defined more than once: first declaration at " + + oldED.getLocation(); + if (isParam) { + str = "Parameter" + str; + } else { + str = "General" + str; + } + _reportWarning(rep, ErrorConsts.WT_ENT_DECL, str, evtLoc); + } + } else { + m.put(id, ent); + } + + // And finally, let's notify listener, if we have one... + if (mEventListener != null) { + if (ent.isParsed()) { // Parsed GE or PE + } else { // unparsed GE + final URL src; + try { + src = mInput.getSource(); + } catch (IOException e) { + throw new WstxIOException(e); + } + mEventListener.dtdUnparsedEntityDecl(id, ent.getPublicId(), ent.getSystemId(), ent.getNotationName(), src); + } + } + } + + /** + * Method called to handle declaration. + */ + private void handleNotationDecl() + throws XMLStreamException + { + char c = skipObligatoryDtdWs(); + String id = readDTDName(c); + + c = skipObligatoryDtdWs(); + boolean isPublic = checkPublicSystemKeyword(c); + + String pubId, sysId; + + c = skipObligatoryDtdWs(); + + // Ok, now we can parse the reference; first public id if needed: + if (isPublic) { + if (c != '"' && c != '\'') { + throwDTDUnexpectedChar(c, "; expected a quote to start the public identifier"); + } + pubId = parsePublicId(c, getErrorMsg()); + c = skipDtdWs(true); + } else { + pubId = null; + } + + /* And then we may need the system id; one NOTATION oddity, if + * there's public id, system one is optional. + */ + if (c == '"' || c == '\'') { + sysId = parseSystemId(c, mNormalizeLFs, getErrorMsg()); + c = skipDtdWs(true); + } else { + if (!isPublic) { + throwDTDUnexpectedChar(c, "; expected a quote to start the system identifier"); + } + sysId = null; + } + + // And then we should get the closing '>' + if (c != '>') { + throwDTDUnexpectedChar(c, "; expected closing '>' after NOTATION declaration"); + } + URL baseURL; + try { + baseURL = mInput.getSource(); + } catch (IOException e) { + throw new WstxIOException(e); + } + + // Any external listeners? + if (mEventListener != null) { + mEventListener.dtdNotationDecl(id, pubId, sysId, baseURL); + } + + /* Ok, event needs to know its exact starting point (opening '<' + * char), let's get that info now (note: data has been preserved + * earlier) + */ + Location evtLoc = getStartLocation(); + NotationDeclaration nd = new WNotationDeclaration(evtLoc, id, pubId, sysId, baseURL); + + // Any definitions from the internal subset? + if (mPredefdNotations != null) { + NotationDeclaration oldDecl = mPredefdNotations.get(id); + if (oldDecl != null) { // oops, a problem! + DTDSubsetImpl.throwNotationException(oldDecl, nd); + } + } + + HashMap m = mNotations; + if (m == null) { + /* Let's try to get insert-ordered Map, to be able to + * report redefinition problems in proper order when validating + * subset compatibility + */ + mNotations = m = new LinkedHashMap(); + } else { + NotationDeclaration oldDecl = m.get(id); + if (oldDecl != null) { // oops, a problem! + DTDSubsetImpl.throwNotationException(oldDecl, nd); + } + } + // Does this resolve a dangling reference? + if (mNotationForwardRefs != null) { + mNotationForwardRefs.remove(id); + } + m.put(id, nd); + } + + /** + * Method called to handle declaration (the only + * new declaration type for DTD++) + *

+ * Note: only valid for DTD++, in 'plain DTD' mode shouldn't get + * called. + */ + private void handleTargetNsDecl() + throws XMLStreamException + { + mAnyDTDppFeatures = true; + + char c = skipObligatoryDtdWs(); + String name; + + // Explicit namespace name? + if (isNameStartChar(c)) { + name = readDTDLocalName(c, false); + c = skipObligatoryDtdWs(); + } else { // no, default namespace (or error) + name = null; + } + + // Either way, should now get a quote: + if (c != '"' && c != '\'') { + if (c == '>') { // slightly more accurate error + _reportWFCViolation("Missing namespace URI for TARGETNS directive"); + } + throwDTDUnexpectedChar(c, "; expected a single or double quote to enclose the namespace URI"); + } + + /* !!! 07-Nov-2004, TSa: what's the exact value we should get + * here? Ns declarations can have any attr value... + */ + String uri = parseSystemId(c, false, "in namespace URI"); + + // Do we need to normalize the URI? + if ((mConfigFlags & CFG_INTERN_NS_URIS) != 0) { + uri = InternCache.getInstance().intern(uri); + } + + // Ok, and then the closing '>': + c = skipDtdWs(true); + if (c != '>') { + throwDTDUnexpectedChar(c, "; expected '>' to end TARGETNS directive"); + } + + if (name == null) { // default NS URI + mDefaultNsURI = uri; + } else { + if (mNamespaces == null) { + mNamespaces = new HashMap(); + } + mNamespaces.put(name, uri); + } + } + + /* + /////////////////////////////////////////////////////////// + // Internal methods, secondary decl parsing methods + /////////////////////////////////////////////////////////// + */ + + /** + * @param elem Element that contains this attribute + * @param c First character of what should be the attribute name + * @param index Sequential index number of this attribute as children + * of the element; used for creating bit masks later on. + * @param loc Location of the element name in attribute list declaration + */ + private void handleAttrDecl(DTDElement elem, char c, int index, + Location loc) + throws XMLStreamException + { + // First attribute name + PrefixedName attrName = readDTDQName(c); + + // then type: + c = skipObligatoryDtdWs(); + + int type = 0; + WordResolver enumValues = null; + + if (c == '(') { // enumerated type + enumValues = parseEnumerated(elem, attrName, false); + type = DTDAttribute.TYPE_ENUMERATED; + } else { + String typeStr = readDTDName(c); + + dummy: + do { // dummy loop + switch (typeStr.charAt(0)) { + case 'C': // CDATA + if (typeStr == "CDATA") { + type = DTDAttribute.TYPE_CDATA; + break dummy; + } + break; + case 'I': // ID, IDREF, IDREFS + if (typeStr == "ID") { + type = DTDAttribute.TYPE_ID; + break dummy; + } else if (typeStr == "IDREF") { + type = DTDAttribute.TYPE_IDREF; + break dummy; + } else if (typeStr == "IDREFS") { + type = DTDAttribute.TYPE_IDREFS; + break dummy; + } + break; + case 'E': // ENTITY, ENTITIES + if (typeStr == "ENTITY") { + type = DTDAttribute.TYPE_ENTITY; + break dummy; + } else if (typeStr == "ENTITIES") { + type = DTDAttribute.TYPE_ENTITIES; + break dummy; + } + break; + case 'N': // NOTATION, NMTOKEN, NMTOKENS + if (typeStr == "NOTATION") { + type = DTDAttribute.TYPE_NOTATION; + /* Special case; is followed by a list of + * enumerated ids... + */ + c = skipObligatoryDtdWs(); + if (c != '(') { + throwDTDUnexpectedChar(c, "Excepted '(' to start the list of NOTATION ids"); + } + enumValues = parseEnumerated(elem, attrName, true); + break dummy; + } else if (typeStr == "NMTOKEN") { + type = DTDAttribute.TYPE_NMTOKEN; + break dummy; + } else if (typeStr == "NMTOKENS") { + type = DTDAttribute.TYPE_NMTOKENS; + break dummy; + } + break; + } + + // Problem: + throwDTDAttrError("Unrecognized attribute type '"+typeStr+"'" + +ErrorConsts.ERR_DTD_ATTR_TYPE, + elem, attrName); + } while (false); + } + DefaultAttrValue defVal; + + // Ok, and how about the default declaration? + c = skipObligatoryDtdWs(); + if (c == '#') { + String defTypeStr = readDTDName(getNextExpanded()); + if (defTypeStr == "REQUIRED") { + defVal = DefaultAttrValue.constructRequired(); + } else if (defTypeStr == "IMPLIED") { + defVal = DefaultAttrValue.constructImplied(); + } else if (defTypeStr == "FIXED") { + defVal = DefaultAttrValue.constructFixed(); + c = skipObligatoryDtdWs(); + parseAttrDefaultValue(defVal, c, attrName, loc, true); + } else { + throwDTDAttrError("Unrecognized attribute default value directive #"+defTypeStr + +ErrorConsts.ERR_DTD_DEFAULT_TYPE, + elem, attrName); + defVal = null; // never gets here... + } + } else { + defVal = DefaultAttrValue.constructOptional(); + parseAttrDefaultValue(defVal, c, attrName, loc, false); + } + + /* There are some checks that can/need to be done now, such as: + * + * - [#3.3.1/VC: ID Attribute default] def. value type can not + * be #FIXED + */ + if (type == DTDAttribute.TYPE_ID && defVal.hasDefaultValue()) { + // Just a VC, not WFC... so: + if (mCfgFullyValidating) { + throwDTDAttrError("has type ID; can not have a default (or #FIXED) value (XML 1.0/#3.3.1)", + elem, attrName); + } + } else { // not an ID... shouldn't be xml:id, then + if (mConfig.willDoXmlIdTyping()) { + if (attrName.isXmlReservedAttr(mCfgNsEnabled, "id")) { + // 26-Sep-2006, TSa: For [WSTX-22], need to verify 'xml:id' + checkXmlIdAttr(type); + } + } + } + + /* 01-Sep-2006, TSa: To address [WSTX-23], we should verify declaration + * of 'xml:space' attribute + */ + if (attrName.isXmlReservedAttr(mCfgNsEnabled, "space")) { + checkXmlSpaceAttr(type, enumValues); + } + + DTDAttribute attr; + + /* 17-Feb-2006, TSa: Ok. So some (legacy?) DTDs do declare namespace + * declarations too... sometimes including default values. + */ + if (mCfgNsEnabled && attrName.isaNsDeclaration()) { // only check in ns mode + /* Ok: just declaring them is unnecessary, and can be safely + * ignored. It's only the default values that matter (and yes, + * let's not worry about #REQUIRED for now) + */ + if (!defVal.hasDefaultValue()) { + return; + } + // But defaulting... Hmmh. + attr = elem.addNsDefault(this, attrName, type, + defVal, mCfgFullyValidating); + } else { + attr = elem.addAttribute(this, attrName, type, + defVal, enumValues, + mCfgFullyValidating); + } + + // getting null means this is a dup... + if (attr == null) { + // anyone interested in knowing about possible problem? + XMLReporter rep = mConfig.getXMLReporter(); + if (rep != null) { + String msg = MessageFormat.format(ErrorConsts.W_DTD_ATTR_REDECL, new Object[] { attrName, elem }); + _reportWarning(rep, ErrorConsts.WT_ATTR_DECL, msg, loc); + } + } else { + if (defVal.hasDefaultValue()) { + // always normalize + attr.normalizeDefault(); + // but only validate in validating mode: + if (mCfgFullyValidating) { + attr.validateDefault(this, true); + } + } + } + } + + /** + * Parsing method that reads a list of one or more space-separated + * tokens (nmtoken or name, depending on 'isNotation' argument) + */ + private WordResolver parseEnumerated(DTDElement elem, PrefixedName attrName, + boolean isNotation) + throws XMLStreamException + { + /* Need to use tree set to be able to construct the data + * structs we need later on... + */ + TreeSet set = new TreeSet(); + + char c = skipDtdWs(true); + if (c == ')') { // just to give more meaningful error msgs + throwDTDUnexpectedChar(c, " (empty list; missing identifier(s))?"); + } + + HashMap sharedEnums; + + if (isNotation) { + sharedEnums = null; + } else { + sharedEnums = mSharedEnumValues; + if (sharedEnums == null && !isNotation) { + mSharedEnumValues = sharedEnums = new HashMap(); + } + } + + String id = isNotation ? readNotationEntry(c, attrName, elem.getLocation()) + : readEnumEntry(c, sharedEnums); + set.add(id); + + while (true) { + c = skipDtdWs(true); + if (c == ')') { + break; + } + if (c != '|') { + throwDTDUnexpectedChar(c, "; missing '|' separator?"); + } + c = skipDtdWs(true); + id = isNotation ? readNotationEntry(c, attrName, elem.getLocation()) + : readEnumEntry(c, sharedEnums); + if (!set.add(id)) { + /* 03-Feb-2006, TSa: Hmmh. Apparently all other XML parsers + * consider it's ok in non-validating mode. All right. + */ + if (mCfgFullyValidating) { + throwDTDAttrError("Duplicate enumeration value '"+id+"'", + elem, attrName); + } + } + } + + // Ok, let's construct the minimal data struct, then: + return WordResolver.constructInstance(set); + } + + /** + * Method called to read a notation reference entry; done both for + * attributes of type NOTATION, and for external unparsed entities + * that refer to a notation. In both cases, notation referenced + * needs to have been defined earlier; but only if we are building + * a fully validating DTD subset object (there is the alternative + * of a minimal DTD in DTD-aware mode, which does no validation + * but allows attribute defaulting and normalization, as well as + * access to entity and notation declarations). + * + * @param attrName Name of attribute in declaration that refers to this entity + * + * @param refLoc Starting location of the DTD component that contains + * the reference + */ + private String readNotationEntry(char c, PrefixedName attrName, Location refLoc) + throws XMLStreamException + { + String id = readDTDName(c); + + /* Need to check whether we have a reference to a "pre-defined" + * notation: pre-defined here means that it was defined in the + * internal subset (prior to this parsing which then would external + * subset). This is needed to know if the subset can be cached or + * not. + */ + if (mPredefdNotations != null) { + NotationDeclaration decl = mPredefdNotations.get(id); + if (decl != null) { + mUsesPredefdNotations = true; + return decl.getName(); + } + } + + NotationDeclaration decl = (mNotations == null) ? null :mNotations.get(id); + if (decl == null) { + // In validating mode, this may be a problem (otherwise not) + if (mCfgFullyValidating) { + if (mNotationForwardRefs == null) { + mNotationForwardRefs = new LinkedHashMap(); + } + mNotationForwardRefs.put(id, refLoc); + } + return id; + } + return decl.getName(); + } + + private String readEnumEntry(char c, HashMap sharedEnums) + throws XMLStreamException + { + String id = readDTDNmtoken(c); + + /* Let's make sure it's shared for this DTD subset; saves memory + * both for DTDs and resulting docs. Could also intern Strings? + */ + String sid = sharedEnums.get(id); + if (sid == null) { + sid = id; + if (INTERN_SHARED_NAMES) { + /* 19-Nov-2004, TSa: Let's not use intern cache here... + * shouldn't be performance critical (DTDs themselves + * cached), and would add more entries to cache. + */ + sid = sid.intern(); + } + sharedEnums.put(sid, sid); + } + return sid; + } + + + /** + * Method called to parse what seems like a mixed content specification. + * + * @param construct If true, will build full object for validating content + * within mixed content model; if false, will just parse and discard + * information (done in non-validating DTD-supporting mode) + */ + private StructValidator readMixedSpec(PrefixedName elemName, boolean construct) + throws XMLStreamException + { + String keyw = checkDTDKeyword("PCDATA"); + if (keyw != null) { + _reportWFCViolation("Unrecognized directive #"+keyw+"'; expected #PCDATA (or element name)"); + } + + HashMap m = new LinkedHashMap(); + while (true) { + char c = skipDtdWs(true); + if (c == ')') { + break; + } + if (c == '|') { + c = skipDtdWs(true); + } else if (c == ',') { + throwDTDUnexpectedChar(c, " (sequences not allowed within mixed content)"); + } else if (c == '(') { + throwDTDUnexpectedChar(c, " (sub-content specs not allowed within mixed content)"); + } else { + throwDTDUnexpectedChar(c, "; expected either '|' to separate elements, or ')' to close the list"); + } + PrefixedName n = readDTDQName(c); + Object old = m.put(n, TokenContentSpec.construct(' ', n)); + if (old != null) { + /* 03-Feb-2006, TSa: Hmmh. Apparently all other XML parsers + * consider it's ok in non-validating mode. All right. + */ + if (mCfgFullyValidating) { + throwDTDElemError("duplicate child element <"+n+"> in mixed content model", + elemName); + } + } + } + + /* One more check: can have a trailing asterisk; in fact, have + * to have one if there were any elements. + */ + char c = (mInputPtr < mInputEnd) ? + mInputBuffer[mInputPtr++] : getNextChar(getErrorMsg()); + if (c != '*') { + if (m.size() > 0) { + _reportWFCViolation("Missing trailing '*' after a non-empty mixed content specification"); + } + --mInputPtr; // need to push it back + } + if (!construct) { // no one cares? + return null; + } + + /* Without elements, it's considered "pure" PCDATA, which can use a + * specific 'empty' validator: + */ + if (m.isEmpty()) { + return EmptyValidator.getPcdataInstance(); + } + ContentSpec spec = ChoiceContentSpec.constructMixed(mCfgNsEnabled, m.values()); + StructValidator val = spec.getSimpleValidator(); + if (val == null) { + DFAState dfa = DFAState.constructDFA(spec); + val = new DFAValidator(dfa); + } + return val; + } + + /** + * @param mainLevel Whether this is the main-level content specification or nested + */ + private ContentSpec readContentSpec(PrefixedName elemName, boolean mainLevel, + boolean construct) + throws XMLStreamException + { + ArrayList subSpecs = new ArrayList(); + boolean isChoice = false; // default to sequence + boolean choiceSet = false; + + while (true) { + char c = skipDtdWs(true); + if (c == ')') { + // Need to have had at least one entry... + if (subSpecs.isEmpty()) { + _reportWFCViolation("Empty content specification for '"+elemName+"' (need at least one entry)"); + } + break; + } + if (c == '|' || c == ',') { // choice/seq indicator + boolean newChoice = (c == '|'); + if (!choiceSet) { + isChoice = newChoice; + choiceSet = true; + } else { + if (isChoice != newChoice) { + _reportWFCViolation("Can not mix content spec separators ('|' and ','); need to use parenthesis groups"); + } + } + c = skipDtdWs(true); + } else { + // Need separator between subspecs... + if (!subSpecs.isEmpty()) { + throwDTDUnexpectedChar(c, " (missing separator '|' or ','?)"); + } + } + if (c == '(') { + ContentSpec cs = readContentSpec(elemName, false, construct); + subSpecs.add(cs); + continue; + } + + // Just to get better error messages: + if (c == '|' || c == ',') { + throwDTDUnexpectedChar(c, " (missing element name?)"); + } + PrefixedName thisName = readDTDQName(c); + + /* Now... it's also legal to directly tag arity marker to a + * single element name, too... + */ + char arity = readArity(); + ContentSpec cs = construct ? + TokenContentSpec.construct(arity, thisName) + : TokenContentSpec.getDummySpec(); + subSpecs.add(cs); + } + + char arity = readArity(); + + /* Not really interested in constructing anything? Let's just + * return the dummy placeholder. + */ + if (!construct) { + return TokenContentSpec.getDummySpec(); + } + + // Just one entry? Can just return it as is, combining arities + if (subSpecs.size() == 1) { + ContentSpec cs = subSpecs.get(0); + char otherArity = cs.getArity(); + if (arity != otherArity) { + cs.setArity(combineArities(arity, otherArity)); + } + return cs; + } + + if (isChoice) { + return ChoiceContentSpec.constructChoice(mCfgNsEnabled, arity, subSpecs); + } + return SeqContentSpec.construct(mCfgNsEnabled, arity, subSpecs); + } + + private static char combineArities(char arity1, char arity2) + { + if (arity1 == arity2) { + return arity1; + } + + // no modifier doesn't matter: + if (arity1 == ' ') { + return arity2; + } + if (arity2 == ' ') { + return arity1; + } + // Asterisk is most liberal, supercedes others: + if (arity1 == '*' || arity2 == '*') { + return '*'; + } + + /* Ok, can only have '+' and '?'; which combine to + * '*' + */ + return '*'; + } + + /** + * Method that handles rest of external entity declaration, after + * it's been figured out entity is not internal (does not continue + * with a quote). + * + * @param inputSource Input source for the start of the declaration. + * Needed for resolving relative system references, if any. + * @param isParam True if this a parameter entity declaration; false + * if general entity declaration + * @param evtLoc Location where entity declaration directive started; + * needed when construction event Objects for declarations. + */ + private EntityDecl handleExternalEntityDecl(WstxInputSource inputSource, + boolean isParam, String id, + char c, Location evtLoc) + throws XMLStreamException + { + boolean isPublic = checkPublicSystemKeyword(c); + + String pubId = null; + + // Ok, now we can parse the reference; first public id if needed: + if (isPublic) { + c = skipObligatoryDtdWs(); + if (c != '"' && c != '\'') { + throwDTDUnexpectedChar(c, "; expected a quote to start the public identifier"); + } + pubId = parsePublicId(c, getErrorMsg()); + /* 30-Sep-2005, TSa: SGML has public ids that miss the system + * id. Although not legal with XML DTDs, let's give bit more + * meaningful error in those cases... + */ + c = getNextExpanded(); + if (c <= CHAR_SPACE) { // good + c = skipDtdWs(true); + } else { // not good... + // Let's just push it back and generate normal error then: + if (c != '>') { // this is handled below though + --mInputPtr; + c = skipObligatoryDtdWs(); + } + } + + /* But here let's deal with one case that we are familiar with: + * SGML does NOT require system id after public one... + */ + if (c == '>') { + _reportWFCViolation("Unexpected end of ENTITY declaration (expected a system id after public id): trying to use an SGML DTD instead of XML one?"); + } + } else { + // Just need some white space here + c = skipObligatoryDtdWs(); + } + if (c != '"' && c != '\'') { + throwDTDUnexpectedChar(c, "; expected a quote to start the system identifier"); + } + String sysId = parseSystemId(c, mNormalizeLFs, getErrorMsg()); + + // Ok; how about notation? + String notationId = null; + + /* Ok; PEs are simpler, as they always are parsed (see production + * #72 in xml 1.0 specs) + */ + if (isParam) { + c = skipDtdWs(true); + } else { + /* GEs can be unparsed, too, so it's bit more complicated; + * if we get '>', don't need space; otherwise need separating + * space (or PE boundary). Thus, need bit more code. + */ + int i = peekNext(); + if (i == '>') { // good + c = '>'; + ++mInputPtr; + } else if (i < 0) { // local EOF, ok + c = skipDtdWs(true); + } else if (i == '%') { + c = getNextExpanded(); + } else { + ++mInputPtr; + c = (char) i; + if (!isSpaceChar(c)) { + throwDTDUnexpectedChar(c, "; expected a separating space or closing '>'"); + } + c = skipDtdWs(true); + } + + if (c != '>') { + if (!isNameStartChar(c)) { + throwDTDUnexpectedChar(c, "; expected either NDATA keyword, or closing '>'"); + } + String keyw = checkDTDKeyword("DATA"); + if (keyw != null) { + _reportWFCViolation("Unrecognized keyword '"+keyw+"'; expected NOTATION (or closing '>')"); + } + c = skipObligatoryDtdWs(); + notationId = readNotationEntry(c, null, evtLoc); + c = skipDtdWs(true); + } + } + + // Ok, better have '>' now: + if (c != '>') { + throwDTDUnexpectedChar(c, "; expected closing '>'"); + } + + URL ctxt; + try { + ctxt = inputSource.getSource(); + } catch (IOException e) { + throw new WstxIOException(e); + } + if (notationId == null) { // parsed entity: + return new ParsedExtEntity(evtLoc, id, ctxt, pubId, sysId); + } + return new UnparsedExtEntity(evtLoc, id, ctxt, pubId, sysId, notationId); + } + + /* + /////////////////////////////////////////////////////////// + // Data struct access + /////////////////////////////////////////////////////////// + */ + + private LinkedHashMap getElementMap() { + LinkedHashMap m = mElements; + if (m == null) { + /* Let's try to get insert-ordered Map, to be able to + * report redefinition problems in proper order when validating + * subset compatibility + */ + mElements = m = new LinkedHashMap(); + } + return m; + } + + final PrefixedName mAccessKey = new PrefixedName(null, null); + + /** + * Method used to 'intern()' qualified names; main benefit is reduced + * memory usage as the name objects are shared. May also slightly + * speed up Map access, as more often identity comparisons catch + * matches. + *

+ * Note: it is assumed at this point that access is only from a single + * thread, and non-recursive -- generally valid assumption as readers are + * not shared. Restriction is needed since the method is not re-entrant: + * it uses mAccessKey during the method call. + */ + private PrefixedName findSharedName(String prefix, String localName) + { + HashMap m = mSharedNames; + + if (mSharedNames == null) { + mSharedNames = m = new HashMap(); + } else { + // Maybe we already have a shared instance... ? + PrefixedName key = mAccessKey; + key.reset(prefix, localName); + key = m.get(key); + if (key != null) { // gotcha + return key; + } + } + + // Not found; let's create, cache and return it: + PrefixedName result = new PrefixedName(prefix, localName); + m.put(result, result); + return result; + } + + /* + /////////////////////////////////////////////////////////// + // Implementations of abstract methods from StreamScanner + /////////////////////////////////////////////////////////// + */ + + /** + * @param arg If Boolean.TRUE, we are expanding a general entity + * + */ + @Override + protected EntityDecl findEntity(String id, Object arg) + { + // Expand a Parameter Entity? + if (arg == ENTITY_EXP_PE) { // for attribute default + EntityDecl ed = (mPredefdPEs == null) ? null : mPredefdPEs.get(id); + if (ed != null) { // Entity from int. subset... + mUsesPredefdEntities = true; + /* No need to further keep track of internal references, + * since this subset can not be cached, so let's just free + * up Map if it has been created + */ + mRefdPEs = null; + } else if (mParamEntities != null) { + ed = mParamEntities.get(id); + if (ed != null) { + if (!mUsesPredefdEntities) { + // Let's also mark down the fact we referenced the entity: + Set used = mRefdPEs; + if (used == null) { + mRefdPEs = used = new HashSet(); + } + used.add(id); + } + } + } + return ed; + } + + // Nope, General Entity (within attribute default value)? + if (arg == ENTITY_EXP_GE) { + /* This is only complicated for external subsets, since + * they may 'inherit' entity definitions from preceding + * internal subset... + */ + EntityDecl ed = (mPredefdGEs == null) ? null : mPredefdGEs.get(id); + if (ed != null) { + mUsesPredefdEntities = true; + /* No need to further keep track of references, + * as this means this subset is not cachable... + * so let's just free up Map if it has been created + */ + mRefdGEs = null; + } else if (mGeneralEntities != null) { + ed = mGeneralEntities.get(id); + if (ed != null) { + // Ok, just need to mark reference, if we still care: + if (!mUsesPredefdEntities) { + // Let's also mark down the fact we referenced the entity: + if (mRefdGEs == null) { + mRefdGEs = new HashSet(); + } + mRefdGEs.add(id); + } + } + } + return ed; + } + + throw new IllegalStateException(ErrorConsts.ERR_INTERNAL); + } + + /** + * Undeclared parameter entity is a VC, not WFC... + */ + @Override + protected void handleUndeclaredEntity(String id) + throws XMLStreamException + { + _reportVCViolation("Undeclared parameter entity '"+id+"'."); + if (mCurrAttrDefault != null) { + Location loc = getLastCharLocation(); + if (mExpandingPE) { + mCurrAttrDefault.addUndeclaredPE(id, loc); + } else { + mCurrAttrDefault.addUndeclaredGE(id, loc); + } + } + if (mEventListener != null) { + // GEs only matter when expanding... + if (mExpandingPE) { + mEventListener.dtdSkippedEntity("%"+id); + } + } + } + + /** + * Handling of PE matching problems is actually intricate; one type + * will be a WFC ("PE Between Declarations", which refers to PEs that + * start from outside declarations), and another just a VC + * ("Proper Declaration/PE Nesting", when PE is contained within + * declaration) + */ + @Override + protected void handleIncompleteEntityProblem(WstxInputSource closing) + throws XMLStreamException + { + // Did it start outside of declaration? + if (closing.getScopeId() == 0) { // yup + // and being WFC, need not be validating + _reportWFCViolation(entityDesc(closing) + ": " + +"Incomplete PE: has to fully contain a declaration (as per xml 1.0.3, section 2.8, WFC 'PE Between Declarations')"); + } else { + // whereas the other one is only sent in validating mode.. + if (mCfgFullyValidating) { + _reportVCViolation(entityDesc(closing) + ": " + +"Incomplete PE: has to be fully contained in a declaration (as per xml 1.0.3, section 2.8, VC 'Proper Declaration/PE Nesting')"); + } + } + } + + protected void handleGreedyEntityProblem(WstxInputSource input) + throws XMLStreamException + { + // Here it can only be of VC kind... + if (mCfgFullyValidating) { // since it's a VC, not WFC + _reportWFCViolation(entityDesc(input) + ": " + + "Unbalanced PE: has to be fully contained in a declaration (as per xml 1.0.3, section 2.8, VC 'Proper Declaration/PE Nesting')"); + } + } + + /* + /////////////////////////////////////////////////////////// + // Additional validity checking + /////////////////////////////////////////////////////////// + */ + + protected void checkXmlSpaceAttr(int type, WordResolver enumValues) + throws XMLStreamException + { + boolean ok = (type == DTDAttribute.TYPE_ENUMERATED); + if (ok) { + switch (enumValues.size()) { + case 1: + ok = (enumValues.find("preserve") != null) + || (enumValues.find("default") != null); + break; + case 2: + ok = (enumValues.find("preserve") != null) + && (enumValues.find("default") != null); + break; + default: + ok = false; + } + } + + if (!ok) { + _reportVCViolation(ErrorConsts.ERR_DTD_XML_SPACE); + } + } + + protected void checkXmlIdAttr(int type) + throws XMLStreamException + { + if (type != DTDAttribute.TYPE_ID) { + _reportVCViolation(ErrorConsts.ERR_DTD_XML_ID); + } + } + + /* + /////////////////////////////////////////////////////////// + // Error handling + /////////////////////////////////////////////////////////// + */ + + private void _reportWarning(XMLReporter rep, String probType, String msg, + Location loc) + throws XMLStreamException + { + if (rep != null) { + /* Note: since the problem occurs at DTD (schema) parsing, + * not during validation, can not set reporter. + */ + XMLValidationProblem prob = new XMLValidationProblem + (loc, msg, XMLValidationProblem.SEVERITY_WARNING, probType); + rep.report(msg, probType, prob, loc); + } + } +} diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/dtd/LargePrefixedNameSet.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/dtd/LargePrefixedNameSet.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/dtd/LargePrefixedNameSet.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/dtd/LargePrefixedNameSet.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,189 @@ +package com.ctc.wstx.dtd; + +import java.util.Iterator; +import java.util.TreeSet; + +import com.ctc.wstx.util.PrefixedName; + +/** + * Implementation of {@link PrefixedNameSet} suitable for storing large number + * of entries; basically anything above trivially small sets (4 or less). + *

+ * Notes about usage: + *

    + *
  • All Strings contained in {@link PrefixedName} instances are assumed + * interned, so that equality comparison can be done (both for values + * stored and keys used) + *
  • + *
  • It is assumed that sets are never empty, ie. always contain at + * least one entry. + *
  • + *
  • It is assumed that caller has ensured that there are no duplicates + * in the set -- this data structure does no further validation. + *
  • + *
+ */ +public final class LargePrefixedNameSet + extends PrefixedNameSet +{ + /** + * Let's not bother creating tiny hash areas; should seldom be a problem + * as smaller sets are usually created using different impl. class. + */ + final static int MIN_HASH_AREA = 8; + + final boolean mNsAware; + + /** + * Primary hash area in which NameKeys are added. Sized to be the smallest + * power of two bigger than number of entries; but at least 4 (it doesn't + * make sense to create smaller arrays) + */ + final PrefixedName[] mNames; + + /** + * Secondary (spill) area, in which keys whose hash values collide + * with primary ones are added. Number of buckets is 1/4 of number + * of primary entries, + */ + final Bucket[] mBuckets; + + public LargePrefixedNameSet(boolean nsAware, PrefixedName[] names) + { + mNsAware = nsAware; + int len = names.length; + + // Let's find the size first... let's except 1/8 slack (88% fill rate) + int minSize = len + ((len + 7) >> 3); + // Let's not create hash areas smaller than certain limit + int tableSize = MIN_HASH_AREA; + + while (tableSize < minSize) { + tableSize += tableSize; + } + + mNames = new PrefixedName[tableSize]; + // and 1/4 of that for spill area... but let's do that lazily + + Bucket[] buckets = null; + int mask = (tableSize - 1); + + for (int i = 0; i < len; ++i) { + PrefixedName nk = names[i]; + int ix = (nk.hashCode() & mask); + if (mNames[ix] == null) { // no collision + mNames[ix] = nk; + } else { // collision, need to add a bucket + ix >>= 2; + + Bucket old; + if (buckets == null) { + buckets = new Bucket[tableSize >> 2]; + old = null; + } else { + old = buckets[ix]; + } + buckets[ix] = new Bucket(nk, old); + } + } + + mBuckets = buckets; + } + + @Override + public boolean hasMultiple() { return true; } + + /** + * @return True if the set contains specified name; false if not. + */ + @Override + public boolean contains(PrefixedName name) + { + PrefixedName[] hashArea = mNames; + int index = name.hashCode() & (hashArea.length - 1); + PrefixedName res = hashArea[index]; + + if (res != null && res.equals(name)) { + return true; + } + + Bucket[] buckets = mBuckets; + if (buckets != null) { + for (Bucket bucket = buckets[index >> 2]; bucket != null; + bucket = bucket.getNext()) { + res = bucket.getName(); + if (res.equals(name)) { + return true; + } + } + } + return false; + } + + /** + * Method called by debug/error handling code, to get a list of + * all names contained. + */ + @Override + public void appendNames(StringBuilder sb, String sep) + { + // Let's first get the alphabetized list of all names from main hash + TreeSet ts = new TreeSet(); + for (int i = 0; i < mNames.length; ++i) { + PrefixedName name = mNames[i]; + if (name != null) { + ts.add(name); + } + } + + // then spill area + if (mBuckets != null) { + for (int i = 0; i < (mNames.length >> 2); ++i) { + Bucket b = mBuckets[i]; + while (b != null) { + ts.add(b.getName()); + b = b.getNext(); + } + } + } + + // And then append them: + Iterator it = ts.iterator(); + boolean first = true; + while (it.hasNext()) { + if (first) { + first = false; + } else { + sb.append(sep); + } + sb.append(it.next().toString()); + } + } + + /* + /////////////////////////////////////////////////////////// + // Helper class(es) + /////////////////////////////////////////////////////////// + */ + + private final static class Bucket + { + final PrefixedName mName; + + final Bucket mNext; + + public Bucket(PrefixedName name, Bucket next) { + mName = name; + mNext = next; + } + + public PrefixedName getName() { return mName; } + public Bucket getNext() { return mNext; } + + /* + public boolean contains(PrefixedName n) { + return mName.equals(n); + } + */ + } +} diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/dtd/MinimalDTDReader.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/dtd/MinimalDTDReader.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/dtd/MinimalDTDReader.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/dtd/MinimalDTDReader.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,413 @@ +/* Woodstox XML processor + * + * Copyright (c) 2004- Tatu Saloranta, tatu.saloranta@iki.fi + * + * Licensed under the License specified in file LICENSE, included with + * the source code. + * You may not use this file except in compliance with the License. + * + * 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 com.ctc.wstx.dtd; + +import javax.xml.stream.Location; +import javax.xml.stream.XMLStreamException; + +import com.ctc.wstx.api.ReaderConfig; +import com.ctc.wstx.ent.EntityDecl; +import com.ctc.wstx.io.WstxInputData; +import com.ctc.wstx.io.WstxInputSource; +import com.ctc.wstx.sr.StreamScanner; + +/** + * Minimal DTD reader implementation that only knows how to skip + * internal DTD subsets. + */ +public class MinimalDTDReader + extends StreamScanner +{ + /* + ////////////////////////////////////////////////// + // Configuration + ////////////////////////////////////////////////// + */ + + /** + * True, when reading external subset, false when reading internal + * subset. + */ + final boolean mIsExternal; + + /* + ////////////////////////////////////////////////// + // Life-cycle + ////////////////////////////////////////////////// + */ + + /** + * Constructor used for reading/skipping internal subset. + */ + private MinimalDTDReader(WstxInputSource input, ReaderConfig cfg) + { + this(input, cfg, false); + } + + /** + * Common initialization part of int/ext subset constructors. + */ + protected MinimalDTDReader(WstxInputSource input, ReaderConfig cfg, + boolean isExt) + { + super(input, cfg, cfg.getDtdResolver()); + mIsExternal = isExt; + /* And let's force expansion (matters mostly/only for undefined + * entities) + */ + mCfgReplaceEntities = true; + } + + /** + * Method that just skims + * through structure of internal subset, but without doing any sort + * of validation, or parsing of contents. Method may still throw an + * exception, if skipping causes EOF or there's an I/O problem. + * + * @param srcData Link back to the input buffer shared with the owning + * stream reader. + */ + public static void skipInternalSubset(WstxInputData srcData, WstxInputSource input, + ReaderConfig cfg) + throws XMLStreamException + { + MinimalDTDReader r = new MinimalDTDReader(input, cfg); + // Need to read from same source as the master (owning stream reader) + r.copyBufferStateFrom(srcData); + try { + r.skipInternalSubset(); + } finally { + /* And then need to restore changes back to srcData (line nrs etc); + * effectively means that we'll stop reading internal DTD subset, + * if so. + */ + srcData.copyBufferStateFrom(r); + } + } + + /* + ////////////////////////////////////////////////// + // Abstract methods from StreamScanner + ////////////////////////////////////////////////// + */ + + /** + * What DTD reader returns doesn't really matter, so let's just return + * perceived start location (different from what stream readers actually + * do) + */ + @Override + public final Location getLocation() { + return getStartLocation(); + } + + @Override + protected EntityDecl findEntity(String id, Object arg) { + throwIllegalCall(); + return null; // never gets here but javac needs it + } + + /** + * This is a VC, not WFC, nothing to do when skipping through + * DTD in non-supporting mode. + */ + @Override + protected void handleUndeclaredEntity(String id) + throws XMLStreamException + { + // nothing to do... + } + + /** + * Since improper entity/PE nesting is VC, not WFC, let's not + * react to this failure at all when only skipping the DTD subset. + */ + @Override + protected void handleIncompleteEntityProblem(WstxInputSource closing) + throws XMLStreamException + { + // nothing to do... + } + + protected char handleExpandedSurrogate(char first, char second) + { + // should we throw an exception? + return first; + } + + /* + ////////////////////////////////////////////////// + // Internal API + ////////////////////////////////////////////////// + */ + + /** + * Method that may need to be called by attribute default value + * validation code, during parsing.... + *

+ * 03-Dec-2004, TSa: This is not particularly elegant: should be + * able to pass the information some other way. But for now it + * works and is necessary. + */ + public EntityDecl findEntity(String entName) { + return null; + } + + /* + ////////////////////////////////////////////////// + // Main-level skipping method(s) + ////////////////////////////////////////////////// + */ + + /** + * Method that will skip through internal DTD subset, without doing + * any parsing, except for trying to match end of subset properly. + */ + protected void skipInternalSubset() + throws XMLStreamException + { + while (true) { + int i = getNextAfterWS(); + if (i < 0) { + // Error for internal subset + throwUnexpectedEOF(SUFFIX_IN_DTD_INTERNAL); + } + if (i == '%') { // parameter entity + skipPE(); + continue; + } + if (i == '<') { + /* Let's determine type here, and call appropriate skip + * methods. + */ + char c = getNextSkippingPEs(); + if (c == '?') { // xml decl? + /* Not sure if PIs are really allowed in DTDs, but let's + * just allow them until proven otherwise. XML declaration + * is legal in the beginning, anyhow + */ + skipPI(); + } else if (c == '!') { // ignore/include, comment, declaration? + c = getNextSkippingPEs(); + if (c == '[') { + /* Shouldn't really get these, as they are not allowed + * in the internal subset? So let's just leave it + * as is, and see what happens. :-) + */ + ; + } else if (c == '-') { // plain comment + skipComment(); + } else if (c >= 'A' && c <= 'Z') { + skipDeclaration(c); + } else { + /* Hmmh, let's not care too much; but we need to try + * to match the closing gt-char nonetheless? + */ + skipDeclaration(c); + } + } else { + /* Shouldn't fail (since we are to completely ignore + * subset); let's just push it back and continue. + */ + --mInputPtr; + } + continue; + } + + if (i == ']') { + // Int. subset has no conditional sections, has to be the end... + /* 18-Jul-2004, TSa: Let's just make sure it happened + * in the main input source, not at external entity... + */ + if (mInput != mRootInput) { + throwParseError("Encountered int. subset end marker ']]>' in an expanded entity; has to be at main level."); + } + // End of internal subset + break; + } + throwUnexpectedChar(i, SUFFIX_IN_DTD_INTERNAL+"; expected a '<' to start a directive, or \"]>\" to end internal subset."); + } + } + + /* + ////////////////////////////////////////////////// + // Internal methods, input access: + ////////////////////////////////////////////////// + */ + + protected char dtdNextFromCurr() + throws XMLStreamException + { + return (mInputPtr < mInputEnd) ? + mInputBuffer[mInputPtr++] : getNextCharFromCurrent(getErrorMsg()); + } + + protected char dtdNextChar() + throws XMLStreamException + { + return (mInputPtr < mInputEnd) ? + mInputBuffer[mInputPtr++] : getNextChar(getErrorMsg()); + } + + protected char getNextSkippingPEs() + throws XMLStreamException + { + while (true) { + char c = (mInputPtr < mInputEnd) ? + mInputBuffer[mInputPtr++] : getNextChar(getErrorMsg()); + if (c != '%') { + return c; + } + skipPE(); + } + } + + /* + ////////////////////////////////////////////////// + // Internal methods, skipping: + ////////////////////////////////////////////////// + */ + + private void skipPE() + throws XMLStreamException + { + skipDTDName(); + /* Should now get semicolon... let's try to find and skip it; but + * if none found, let's not throw an exception -- we are just skipping + * internal subset here. + */ + char c = (mInputPtr < mInputEnd) ? + mInputBuffer[mInputPtr++] : dtdNextFromCurr(); + if (c != ';') { + --mInputPtr; + } + } + + protected void skipComment() + throws XMLStreamException + { + skipCommentContent(); + // Now, we may be getting end mark; first need second marker char:. + char c = (mInputPtr < mInputEnd) + ? mInputBuffer[mInputPtr++] : dtdNextFromCurr(); + if (c != '>') { + throwParseError("String '--' not allowed in comment (missing '>'?)"); + } + } + + protected void skipCommentContent() + throws XMLStreamException + { + while (true) { + char c = (mInputPtr < mInputEnd) ? + mInputBuffer[mInputPtr++] : dtdNextFromCurr(); + if (c == '-') { + c = (mInputPtr < mInputEnd) ? + mInputBuffer[mInputPtr++] : dtdNextFromCurr(); + if (c == '-') { + return; + } + } else if (c == '\n' || c == '\r') { + skipCRLF(c); + } + } + } + + protected void skipPI() + throws XMLStreamException + { + while (true) { + char c = (mInputPtr < mInputEnd) + ? mInputBuffer[mInputPtr++] : dtdNextFromCurr(); + if (c == '?') { + do { + c = (mInputPtr < mInputEnd) + ? mInputBuffer[mInputPtr++] : dtdNextFromCurr(); + } while (c == '?'); + if (c == '>') { + break; + } + } + if (c == '\n' || c == '\r') { + skipCRLF(c); + } + } + } + + private void skipDeclaration(char c) + throws XMLStreamException + { + while (c != '>') { + c = (mInputPtr < mInputEnd) + ? mInputBuffer[mInputPtr++] : dtdNextFromCurr(); + if (c == '\n' || c == '\r') { + skipCRLF(c); + /* No need for specific handling for PE refs; they just have + * identifier that'll get properly skipped. + */ + /* 17-Jul-2004, TSa: But we do need to properly handle literals; + * it is possible to add '>' char in entity expansion values. + */ + } else if (c == '\'' || c == '"') { + skipLiteral(c); + } + } + } + + private void skipLiteral(char quoteChar) + throws XMLStreamException + { + while (true) { + char c = (mInputPtr < mInputEnd) + ? mInputBuffer[mInputPtr++] : dtdNextFromCurr(); + if (c == '\n' || c == '\r') { + skipCRLF(c); + } else if (c == quoteChar) { + break; + } + /* No need for specific handling for PE refs, should be ignored + * just ok (plus they need to properly nested in any case) + */ + } + } + + private void skipDTDName() + throws XMLStreamException + { + /*int len =*/ skipFullName(getNextChar(getErrorMsg())); + /* Should we give an error about missing name? For now, + * let's just exit. + */ + } + + /* + ////////////////////////////////////////////////// + // Internal methods, error handling: + ////////////////////////////////////////////////// + */ + + protected String getErrorMsg() { + return mIsExternal ? SUFFIX_IN_DTD_EXTERNAL : SUFFIX_IN_DTD_INTERNAL; + } + + + protected void throwIllegalCall() + throws Error + { + throw new IllegalStateException("Internal error: this method should never be called"); + } +} + diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/dtd/ModelNode.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/dtd/ModelNode.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/dtd/ModelNode.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/dtd/ModelNode.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,35 @@ +package com.ctc.wstx.dtd; + +import java.util.BitSet; +import java.util.List; + +/** + * Abstract base class for classes constructed from {@link ContentSpec} + * objects, when they get rewritten (when their {@link ContentSpec#rewrite} + * gets called). These nodes are then used for constructing complete DFA + * states for validation. + */ +public abstract class ModelNode +{ + /* + /////////////////////////////////////////////////// + // Methods needed for DFA construction + /////////////////////////////////////////////////// + */ + + /** + * Method that has to create a deep copy of the model, without + * sharing any of existing Objects. + */ + public abstract ModelNode cloneModel(); + + public abstract boolean isNullable(); + + public abstract void indexTokens(List tokens); + + public abstract void addFirstPos(BitSet firstPos); + + public abstract void addLastPos(BitSet firstPos); + + public abstract void calcFollowPos(BitSet[] followPosSets); +} diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/dtd/OptionalModel.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/dtd/OptionalModel.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/dtd/OptionalModel.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/dtd/OptionalModel.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,72 @@ +package com.ctc.wstx.dtd; + +import java.util.*; + +/** + * Content specification class that represents an optional specification. + * Optional specifications are generally a result of '?' arity marker, + * and are created when {@link ContentSpec#rewrite} is called + * on a specification with '?' arity modifier. + */ +public class OptionalModel + extends ModelNode +{ + ModelNode mModel; + + /* + /////////////////////////////////////////////////// + // Life-cycle + /////////////////////////////////////////////////// + */ + + public OptionalModel(ModelNode model) { + mModel = model; + } + + /* + /////////////////////////////////////////////////// + // Public API + /////////////////////////////////////////////////// + */ + + /** + * Method that has to create a deep copy of the model, without + * sharing any of existing Objects. + */ + @Override + public ModelNode cloneModel() { + return new OptionalModel(mModel.cloneModel()); + } + + @Override + public boolean isNullable() { + return true; + } + + @Override + public void indexTokens(List tokens) { + mModel.indexTokens(tokens); + } + + @Override + public void addFirstPos(BitSet pos) { + mModel.addFirstPos(pos); + } + + @Override + public void addLastPos(BitSet pos) { + mModel.addLastPos(pos); + } + + @Override + public void calcFollowPos(BitSet[] followPosSets) + { + // Let's let sub-model do its stuff + mModel.calcFollowPos(followPosSets); + } + + @Override + public String toString() { + return mModel + "[?]"; + } +} diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/dtd/package.html libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/dtd/package.html --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/dtd/package.html 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/dtd/package.html 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,3 @@ + +Package that contains Woodstox classes that implement DTD handling. + diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/dtd/PrefixedNameSet.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/dtd/PrefixedNameSet.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/dtd/PrefixedNameSet.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/dtd/PrefixedNameSet.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,47 @@ +/* Woodstox XML processor + * + * Copyright (c) 2004 Tatu Saloranta, tatu.saloranta@iki.fi + * + * Licensed under the License specified in file LICENSE, included with + * the source code. + * You may not use this file except in compliance with the License. + * + * 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 com.ctc.wstx.dtd; + +import com.ctc.wstx.util.PrefixedName; + +public abstract class PrefixedNameSet +{ + protected PrefixedNameSet() { } + + /** + * @return True if set contains more than one entry; false if not + * (empty or has one) + */ + public abstract boolean hasMultiple(); + + /** + * @return True if the set contains specified name; false if not. + */ + public abstract boolean contains(PrefixedName name); + + public abstract void appendNames(StringBuilder sb, String sep); + + @Override + public final String toString() { + return toString(", "); + } + + public final String toString(String sep) { + StringBuilder sb = new StringBuilder(); + appendNames(sb, sep); + return sb.toString(); + } +} diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/dtd/SeqContentSpec.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/dtd/SeqContentSpec.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/dtd/SeqContentSpec.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/dtd/SeqContentSpec.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,239 @@ +package com.ctc.wstx.dtd; + +import java.util.*; + +import com.ctc.wstx.util.PrefixedName; + +/** + * Content specification that defines model that has sequence of one or more + * elements that have to come in the specified order. + */ +public class SeqContentSpec + extends ContentSpec +{ + final boolean mNsAware; + + final ContentSpec[] mContentSpecs; + + /* + /////////////////////////////////////////////////// + // Life-cycle + /////////////////////////////////////////////////// + */ + + public SeqContentSpec(boolean nsAware, char arity, ContentSpec[] subSpecs) + { + super(arity); + mNsAware = nsAware; + mContentSpecs = subSpecs; + } + + public static SeqContentSpec construct(boolean nsAware, char arity, Collection subSpecs) + { + ContentSpec[] specs = new ContentSpec[subSpecs.size()]; + subSpecs.toArray(specs); + return new SeqContentSpec(nsAware, arity, specs); + } + + /* + /////////////////////////////////////////////////// + // Public API + /////////////////////////////////////////////////// + */ + + @Override + public StructValidator getSimpleValidator() + { + /* Can we create a simple validator? Yes, if the sub-specs are + * all simple (leaves == element tokens with no arity modifier) + */ + ContentSpec[] specs = mContentSpecs; + int i = 0; + int len = specs.length; + + for (; i < len; ++i) { + if (!specs[i].isLeaf()) { + break; + } + } + + if (i == len) { // all leaves, kewl + PrefixedName[] set = new PrefixedName[len]; + for (i = 0; i < len; ++i) { + TokenContentSpec ss = (TokenContentSpec) specs[i]; + set[i] = ss.getName(); + } + return new Validator(mArity, set); + } + + // Nope, need a DFA: + return null; + } + + @Override + public ModelNode rewrite() + { + /* First, need to create a tree of sub-models, consisting of + * binary concat nodes (as opposed to n-ary list). Can do that + * recursively (note that we'll always have at least 2 child + * nodes!) + */ + ModelNode model = rewrite(mContentSpecs, 0, mContentSpecs.length); + + // and then resolve arity modifiers, if necessary: + if (mArity == '*') { + return new StarModel(model); + } + if (mArity == '?') { + return new OptionalModel(model); + } + if (mArity == '+') { + return new ConcatModel(model, + new StarModel(model.cloneModel())); + } + return model; + } + + private ModelNode rewrite(ContentSpec[] specs, int first, int last) + { + // 3 or less, can convert and create; 4 or more, need to recurse: + int count = last - first; + if (count > 3) { + int mid = (last + first + 1) >> 1; + return new ConcatModel(rewrite(specs, first, mid), + rewrite(specs, mid, last)); + } + ConcatModel model = new ConcatModel(specs[first].rewrite(), + specs[first+1].rewrite()); + if (count == 3) { + model = new ConcatModel(model, specs[first+2].rewrite()); + } + return model; + } + + @Override + public String toString() + { + StringBuilder sb = new StringBuilder(); + sb.append('('); + + for (int i = 0; i < mContentSpecs.length; ++i) { + if (i > 0) { + sb.append(", "); + } + sb.append(mContentSpecs[i].toString()); + } + sb.append(')'); + + if (mArity != ' ') { + sb.append(mArity); + } + return sb.toString(); + } + + /* + /////////////////////////////////////////////////// + // Validator class that can be used for simple + // choices (including mixed content) + /////////////////////////////////////////////////// + */ + + /** + * Simple validator that can be used if all components of a sequence + * are leaf nodes, ie. elements with no explicit arity modifiers. + */ + final static class Validator + extends StructValidator + { + final char mArity; + final PrefixedName[] mNames; + + /** + * Number of full repetitions done over the sequence + */ + int mRounds = 0; + + /** + * Expected next element in the sequence + */ + int mStep = 0; + + public Validator(char arity, PrefixedName[] names) + { + mArity = arity; + mNames = names; + } + + + /** + * Sequence content specification is always stateful; can not + * use a shared instance... so let's create new instance: + */ + @Override + public StructValidator newInstance() { + return new Validator(mArity, mNames); + } + + @Override + public String tryToValidate(PrefixedName elemName) + { + // First; have we already done that max. 1 sequence? + if (mStep == 0 && mRounds == 1) { + if (mArity == '?' || mArity == ' ') { + return "was not expecting any more elements in the sequence (" + +concatNames(mNames)+")"; + } + } + + PrefixedName next = mNames[mStep]; + if (!elemName.equals(next)) { + return expElem(mStep); + } + if (++mStep == mNames.length) { + ++mRounds; + mStep = 0; + } + return null; + } + + @Override + public String fullyValid() + { + if (mStep != 0) { + return expElem(mStep)+"; got end element"; + } + + switch (mArity) { + case '*': + case '?': + return null; + case '+': // need at least one (and multiples checked earlier) + case ' ': + if (mRounds > 0) { + return null; + } + return "Expected sequence ("+concatNames(mNames)+"); got end element"; + } + // should never happen: + throw new IllegalStateException("Internal error"); + } + + private String expElem(int step) + { + return "expected element <"+mNames[step]+"> in sequence (" + +concatNames(mNames)+")"; + } + + final static String concatNames(PrefixedName[] names) + { + StringBuilder sb = new StringBuilder(); + for (int i = 0, len = names.length; i < len; ++i) { + if (i > 0) { + sb.append(", "); + } + sb.append(names[i].toString()); + } + return sb.toString(); + } + } +} diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/dtd/SmallPrefixedNameSet.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/dtd/SmallPrefixedNameSet.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/dtd/SmallPrefixedNameSet.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/dtd/SmallPrefixedNameSet.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,104 @@ +package com.ctc.wstx.dtd; + +import com.ctc.wstx.util.PrefixedName; + +/** + * PrefixedNameSet implementation suitable for storing small set of PrefixedName + * values (generally 8 or less). Uses linear search, and is thus the + * most compact presentation for a set + *

+ * Notes about usage: + *

    + *
  • All Strings contained in {@link PrefixedName} instances are assumed + * interned, so that equality comparison can be done (both for values + * stored and keys used) + *
  • + *
  • It is assumed that sets are never empty, ie. always contain at + * least one entry. + *
  • + *
  • It is assumed that caller has ensured that there are no duplicates + * in the set -- this data structure does no further validation. + *
  • + *
+ */ +public final class SmallPrefixedNameSet + extends PrefixedNameSet +{ + final boolean mNsAware; + + final String[] mStrings; + + public SmallPrefixedNameSet(boolean nsAware, PrefixedName[] names) + { + mNsAware = nsAware; + int len = names.length; + if (len == 0) { // sanity check + throw new IllegalStateException("Trying to construct empty PrefixedNameSet"); + } + mStrings = new String[nsAware ? (len+len) : len]; + for (int out = 0, in = 0; in < len; ++in) { + PrefixedName nk = names[in]; + if (nsAware) { + mStrings[out++] = nk.getPrefix(); + } + mStrings[out++] = nk.getLocalName(); + } + } + + @Override + public boolean hasMultiple() { + return mStrings.length > 1; + } + + /** + * @return True if the set contains specified name; false if not. + */ + @Override + public boolean contains(PrefixedName name) + { + int len = mStrings.length; + String ln = name.getLocalName(); + String[] strs = mStrings; + + if (mNsAware) { + String prefix = name.getPrefix(); + if (strs[1] == ln && strs[0] == prefix) { + return true; + } + for (int i = 2; i < len; i += 2) { + if (strs[i+1] == ln && strs[i] == prefix) { + return true; + } + } + } else { + if (strs[0] == ln) { + return true; + } + for (int i = 1; i < len; ++i) { + if (strs[i] == ln) { + return true; + } + } + } + + return false; + } + + @Override + public void appendNames(StringBuilder sb, String sep) + { + for (int i = 0; i < mStrings.length; ) { + if (i > 0) { + sb.append(sep); + } + if (mNsAware) { + String prefix = mStrings[i++]; + if (prefix != null) { + sb.append(prefix); + sb.append(':'); + } + } + sb.append(mStrings[i++]); + } + } +} diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/dtd/StarModel.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/dtd/StarModel.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/dtd/StarModel.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/dtd/StarModel.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,90 @@ +package com.ctc.wstx.dtd; + +import java.util.*; + +/** + * Model class that represents any number of repetitions of its submodel + * (including no repetitions). + */ +public class StarModel + extends ModelNode +{ + ModelNode mModel; + + /* + /////////////////////////////////////////////////// + // Life-cycle + /////////////////////////////////////////////////// + */ + + public StarModel(ModelNode model) { + super(); + mModel = model; + } + + /* + /////////////////////////////////////////////////// + // Public API + /////////////////////////////////////////////////// + */ + + /** + * Method that has to create a deep copy of the model, without + * sharing any of existing Objects. + */ + @Override + public ModelNode cloneModel() { + return new StarModel(mModel.cloneModel()); + } + + @Override + public boolean isNullable() { + return true; + } + + @Override + public void indexTokens(List tokens) { + mModel.indexTokens(tokens); + } + + @Override + public void addFirstPos(BitSet pos) { + mModel.addFirstPos(pos); + } + + @Override + public void addLastPos(BitSet pos) { + mModel.addLastPos(pos); + } + + @Override + public void calcFollowPos(BitSet[] followPosSets) + { + // First, let's let sub-model do its stuff + mModel.calcFollowPos(followPosSets); + + /* And then add the closure for the model (since sub-model + * can 'follow itself' as many times as it needs to) + */ + + BitSet foll = new BitSet(); + mModel.addFirstPos(foll); + + BitSet toAddTo = new BitSet(); + mModel.addLastPos(toAddTo); + + int ix = 0; // need to/can skip the null entry (index 0) + while ((ix = toAddTo.nextSetBit(ix+1)) >= 0) { + /* Ok; so token at this index needs to have follow positions + * added... + */ + followPosSets[ix].or(foll); + } + } + + @Override + public String toString() { + return mModel.toString() + "*"; + } +} + diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/dtd/StructValidator.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/dtd/StructValidator.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/dtd/StructValidator.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/dtd/StructValidator.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,51 @@ +/* Woodstox XML processor + * + * Copyright (c) 2004 Tatu Saloranta, tatu.saloranta@iki.fi + * + * Licensed under the License specified in the file LICENSE which is + * included with the source code. + * You may not use this file except in compliance with the License. + * + * 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 com.ctc.wstx.dtd; + +import com.ctc.wstx.util.PrefixedName; + +/** + * Base class for validator Objects used to validate tree structure of an + * XML-document against DTD. + */ +public abstract class StructValidator +{ + /** + * Method that should be called to get the actual usable validator + * instance, from the 'template' validator. + */ + public abstract StructValidator newInstance(); + + /** + * Method called when a new (start) element is encountered within the + * scope of parent element this validator monitors. + * + * @return Null if element is valid in its current position; error + * message if not. + */ + public abstract String tryToValidate(PrefixedName elemName); + + /** + * Method called when the end element of the scope this validator + * validates is encountered. It should make sure that the content + * model is valid, and if not, to construct an error message. + * + * @return Null if the content model for the element is valid; error + * message if not. + */ + public abstract String fullyValid(); +} + diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/dtd/TokenContentSpec.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/dtd/TokenContentSpec.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/dtd/TokenContentSpec.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/dtd/TokenContentSpec.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,145 @@ +package com.ctc.wstx.dtd; + +import com.ctc.wstx.cfg.ErrorConsts; +import com.ctc.wstx.util.PrefixedName; + +/** + * Content specification that defines content model consisting of just + * one allowed element. In addition to the allowed element, spec can have + * optional arity ("*", "+", "?") marker. + */ +public class TokenContentSpec + extends ContentSpec +{ + final static TokenContentSpec sDummy = new TokenContentSpec + (' ', new PrefixedName("*", "*")); + + final PrefixedName mElemName; + + /* + /////////////////////////////////////////////////// + // Life-cycle + /////////////////////////////////////////////////// + */ + + public TokenContentSpec(char arity, PrefixedName elemName) + { + super(arity); + mElemName = elemName; + } + + public static TokenContentSpec construct(char arity, PrefixedName elemName) + { + return new TokenContentSpec(arity, elemName); + } + + public static TokenContentSpec getDummySpec() { + return sDummy; + } + + /* + /////////////////////////////////////////////////// + // Public API + /////////////////////////////////////////////////// + */ + + @Override + public boolean isLeaf() { + return mArity == ' '; + } + + public PrefixedName getName() { + return mElemName; + } + + @Override + public StructValidator getSimpleValidator() { + return new Validator(mArity, mElemName); + } + + @Override + public ModelNode rewrite() { + TokenModel model = new TokenModel(mElemName); + if (mArity == '*') { + return new StarModel(model); + } + if (mArity == '?') { + return new OptionalModel(model); + } + if (mArity == '+') { + return new ConcatModel(model, + new StarModel(new TokenModel(mElemName))); + } + return model; + } + + @Override + public String toString() { + return (mArity == ' ') ? mElemName.toString() + : (mElemName.toString() + mArity); + } + + /* + /////////////////////////////////////////////////// + // Validator class: + /////////////////////////////////////////////////// + */ + + final static class Validator + extends StructValidator + { + final char mArity; + final PrefixedName mElemName; + + int mCount = 0; + + public Validator(char arity, PrefixedName elemName) + { + mArity = arity; + mElemName = elemName; + } + + /** + * Rules for reuse are simple: if we can have any number of + * repetitions, we can just use a shared root instance. Although + * its count variable will get updated this doesn't really + * matter as it won't be used. Otherwise a new instance has to + * be created always, to keep track of instance counts. + */ + @Override + public StructValidator newInstance() { + return (mArity == '*') ? this : new Validator(mArity, mElemName); + } + + @Override + public String tryToValidate(PrefixedName elemName) + { + if (!elemName.equals(mElemName)) { + return "Expected element <"+mElemName+">"; + } + if (++mCount > 1 && (mArity == '?' || mArity == ' ')) { + return "More than one instance of element <"+mElemName+">"; + } + return null; + } + + @Override + public String fullyValid() + { + switch (mArity) { + case '*': + case '?': + return null; + case '+': // need at least one (and multiples checked earlier) + case ' ': + if (mCount > 0) { + return null; + } + return "Expected "+(mArity == '+' ? "at least one" : "") + +" element <"+mElemName+">"; + } + // should never happen: + throw new IllegalStateException(ErrorConsts.ERR_INTERNAL); + } + } +} diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/dtd/TokenModel.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/dtd/TokenModel.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/dtd/TokenModel.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/dtd/TokenModel.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,97 @@ +package com.ctc.wstx.dtd; + +import java.util.BitSet; +import java.util.List; + +import com.ctc.wstx.util.PrefixedName; + +/** + * Model class that encapsulates a single (obligatory) token instance. + */ +public final class TokenModel + extends ModelNode +{ + final static TokenModel NULL_TOKEN = new TokenModel(null); + static { // null token needs to have 0 as its index... + NULL_TOKEN.mTokenIndex = 0; + } + + final PrefixedName mElemName; + + int mTokenIndex = -1; // to catch errors... + + /* + /////////////////////////////////////////////////// + // Life-cycle + /////////////////////////////////////////////////// + */ + + public TokenModel(PrefixedName elemName) { + mElemName = elemName; + } + + public static TokenModel getNullToken() { + return NULL_TOKEN; + } + + /* + /////////////////////////////////////////////////// + // Public API + /////////////////////////////////////////////////// + */ + + public PrefixedName getName() { return mElemName; } + + /** + * Method that has to create a deep copy of the model, without + * sharing any of existing Objects. + */ + @Override + public ModelNode cloneModel() { + return new TokenModel(mElemName); + } + + @Override + public boolean isNullable() { + return false; + } + + @Override + public void indexTokens(List tokens) + { + /* Doh. This is not clean... but need to make sure the null + * token never gets reindexed or explicitly added: + */ + if (this != NULL_TOKEN) { + int index = tokens.size(); + mTokenIndex = index; + tokens.add(this); + } + } + + @Override + public void addFirstPos(BitSet firstPos) { + firstPos.set(mTokenIndex); + } + + @Override + public void addLastPos(BitSet lastPos) { + lastPos.set(mTokenIndex); + } + + @Override + public void calcFollowPos(BitSet[] followPosSets) { + // nothing to do, for tokens... + } + + @Override + public String toString() { + return (mElemName == null) ? "[null]" : mElemName.toString(); + } + + /* + /////////////////////////////////////////////////// + // Internal methods + /////////////////////////////////////////////////// + */ +} diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/ent/EntityDecl.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/ent/EntityDecl.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/ent/EntityDecl.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/ent/EntityDecl.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,145 @@ +/* Woodstox XML processor + * + * Copyright (c) 2004 Tatu Saloranta, tatu.saloranta@iki.fi + * + * Licensed under the License specified in file LICENSE, included with + * the source code. + * You may not use this file except in compliance with the License. + * + * 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 com.ctc.wstx.ent; + +import java.io.IOException; +import java.io.Writer; +import java.net.URL; + +import javax.xml.stream.Location; +import javax.xml.stream.XMLResolver; +import javax.xml.stream.XMLStreamException; + +import com.ctc.wstx.api.ReaderConfig; +import com.ctc.wstx.evt.WEntityDeclaration; +import com.ctc.wstx.io.WstxInputSource; + +/** + * Abstract base class for various entity declarations DTD reader + * has parsed from DTD subsets. + */ +public abstract class EntityDecl + extends WEntityDeclaration +{ + /** + * Name/id of the entity used to reference it. + */ + final String mName; + + /** + * Context that is to be used to resolve references encountered from + * expanded contents of this entity. + */ + final URL mContext; + + /** + * Flag that can be set to indicate that the declaration was in the + * external DTD subset. Default is false. + */ + protected boolean mDeclaredExternally = false; + + public EntityDecl(Location loc, String name, URL ctxt) + { + super(loc); + mName = name; + mContext = ctxt; + } + + public void markAsExternallyDeclared() { + mDeclaredExternally = true; + } + + @Override + public final String getBaseURI() { + return mContext.toExternalForm(); + } + + @Override + public final String getName() { + return mName; + } + + // 27-Mar-2018, tatu: Implemented by `BaseEventImpl` so... + /* + @Override + public final Location getLocation() { + return getLocation(); + } + */ + + @Override + public abstract String getNotationName(); + + @Override + public abstract String getPublicId(); + + @Override + public abstract String getReplacementText(); + + public abstract int getReplacementText(Writer w) + throws IOException; + + @Override + public abstract String getSystemId(); + + /** + * @return True, if the declaration occured in the external DTD + * subset; false if not (internal subset, custom declaration) + */ + public boolean wasDeclaredExternally() { + return mDeclaredExternally; + } + + /* + //////////////////////////////////////////////////////////// + // Implementation of abstract base methods + //////////////////////////////////////////////////////////// + */ + + @Override + public abstract void writeEnc(Writer w) throws IOException; + + /* + //////////////////////////////////////////////////////////// + // Extended API for Wstx core + //////////////////////////////////////////////////////////// + */ + + // // // Access to data + + public abstract char[] getReplacementChars(); + + public final int getReplacementTextLength() { + String str = getReplacementText(); + return (str == null) ? 0 : str.length(); + } + + // // // Type information + + public abstract boolean isExternal(); + + public abstract boolean isParsed(); + + // // // Factory methods + + /** + * Method called to create the new input source through which expansion + * value of the entity can be read. + */ + public abstract WstxInputSource expand(WstxInputSource parent, + XMLResolver res, ReaderConfig cfg, int xmlVersion) + throws IOException, XMLStreamException; +} diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/ent/ExtEntity.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/ent/ExtEntity.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/ent/ExtEntity.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/ent/ExtEntity.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,89 @@ +package com.ctc.wstx.ent; + +import com.ctc.wstx.api.ReaderConfig; + +import java.io.IOException; +import java.io.Writer; +import java.net.URL; + +import javax.xml.stream.Location; +import javax.xml.stream.XMLResolver; +import javax.xml.stream.XMLStreamException; + +import com.ctc.wstx.io.WstxInputSource; + +public abstract class ExtEntity + extends EntityDecl +{ + final String mPublicId; + final String mSystemId; + + public ExtEntity(Location loc, String name, URL ctxt, + String pubId, String sysId) + { + super(loc, name, ctxt); + mPublicId = pubId; + mSystemId = sysId; + } + + @Override + public abstract String getNotationName(); + + @Override + public String getPublicId() { + return mPublicId; + } + + @Override + public String getReplacementText() { + return null; + } + + @Override + public int getReplacementText(Writer w) + //throws IOException + { + return 0; + } + + @Override + public String getSystemId() { + return mSystemId; + } + + /* + /////////////////////////////////////////// + // Implementation of abstract base methods + /////////////////////////////////////////// + */ + + @Override + public abstract void writeEnc(Writer w) throws IOException; + + /* + /////////////////////////////////////////// + // Extended API for Wstx core + /////////////////////////////////////////// + */ + + // // // Access to data + + @Override + public char[] getReplacementChars() { + return null; + } + + // // // Type information + + @Override + public boolean isExternal() { return true; } + + @Override + public abstract boolean isParsed(); + + @Override + public abstract WstxInputSource expand(WstxInputSource parent, + XMLResolver res, ReaderConfig cfg, + int xmlVersion) + throws IOException, XMLStreamException; +} diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/ent/IntEntity.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/ent/IntEntity.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/ent/IntEntity.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/ent/IntEntity.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,143 @@ +package com.ctc.wstx.ent; + +import java.io.IOException; +import java.io.Writer; +import java.net.URL; + +import javax.xml.stream.Location; +import javax.xml.stream.XMLResolver; + +import com.ctc.wstx.api.ReaderConfig; +import com.ctc.wstx.io.InputSourceFactory; +import com.ctc.wstx.io.TextEscaper; +import com.ctc.wstx.io.WstxInputLocation; +import com.ctc.wstx.io.WstxInputSource; + +public class IntEntity + extends EntityDecl +{ + /** + * Location where entity content definition started; + * points to the starting/opening quote for internal + * entities. + */ + protected final Location mContentLocation; + + /** + * Replacement text of the entity; full array contents. + */ + final char[] mRepl; + + String mReplText = null; + + public IntEntity(Location loc, String name, URL ctxt, + char[] repl, Location defLoc) + { + super(loc, name, ctxt); + mRepl = repl; + mContentLocation = defLoc; + } + + public static IntEntity create(String id, String repl) + { + return create(id, repl.toCharArray()); + } + + public static IntEntity create(String id, char[] val) + { + WstxInputLocation loc = WstxInputLocation.getEmptyLocation(); + return new IntEntity(loc, id, null, val, loc); + } + + @Override + public String getNotationName() { + return null; + } + + @Override + public String getPublicId() { + return null; + } + + @Override + public String getReplacementText() + { + String repl = mReplText; + if (repl == null) { + repl = (mRepl.length == 0) ? "" : new String(mRepl); + mReplText = repl; + } + return mReplText; + } + + @Override + public int getReplacementText(Writer w) throws IOException + { + w.write(mRepl); + return mRepl.length; + } + + @Override + public String getSystemId() { + return null; + } + + /* + /////////////////////////////////////////// + // Implementation of abstract base methods + /////////////////////////////////////////// + */ + + @Override + public void writeEnc(Writer w) throws IOException + { + w.write(""); + } + + /* + /////////////////////////////////////////// + // Extended API for Wstx core + /////////////////////////////////////////// + */ + + // // // Access to data + + /** + * Gives raw access to replacement text data... + *

+ * Note: this is not really safe, as caller can modify the array, but + * since this method is thought to provide fast access, let's avoid making + * copy here. + */ + @Override + public char[] getReplacementChars() { + return mRepl; + } + + // // // Type information + + @Override + public boolean isExternal() { return false; } + + @Override + public boolean isParsed() { return true; } + + @Override + public WstxInputSource expand(WstxInputSource parent, + XMLResolver res, ReaderConfig cfg, + int xmlVersion) + { + /* 26-Dec-2006, TSa: Better leave source as null, since internal + * entity declaration context should never be used: when expanding, + * reference context is to be used. + */ + return InputSourceFactory.constructCharArraySource + //(parent, mName, mRepl, 0, mRepl.length, mContentLocation, getSource()); + (parent, mName, mRepl, 0, mRepl.length, mContentLocation, null); + } +} + diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/ent/package.html libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/ent/package.html --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/ent/package.html 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/ent/package.html 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,5 @@ + +Package contains internal entity object implementations, which are used +by stream reader classes, but parsed by dtd functionality. They are also +used for constructing entity events, + diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/ent/ParsedExtEntity.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/ent/ParsedExtEntity.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/ent/ParsedExtEntity.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/ent/ParsedExtEntity.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,80 @@ +package com.ctc.wstx.ent; + +import java.io.IOException; +import java.io.Writer; +import java.net.URL; + +import javax.xml.stream.Location; +import javax.xml.stream.XMLResolver; +import javax.xml.stream.XMLStreamException; + +import com.ctc.wstx.api.ReaderConfig; +import com.ctc.wstx.cfg.XmlConsts; +import com.ctc.wstx.io.DefaultInputResolver; +import com.ctc.wstx.io.WstxInputSource; + +public class ParsedExtEntity + extends ExtEntity +{ + public ParsedExtEntity(Location loc, String name, URL ctxt, + String pubId, String sysId) + { + super(loc, name, ctxt, pubId, sysId); + } + + @Override + public String getNotationName() { + return null; + } + + /* + /////////////////////////////////////////// + // Implementation of abstract base methods + /////////////////////////////////////////// + */ + + @Override + public void writeEnc(Writer w) throws IOException + { + w.write(""); + } + + /* + /////////////////////////////////////////// + // Extended API for Wstx core + /////////////////////////////////////////// + */ + + // // // Type information + + @Override + public boolean isParsed() { return true; } + + @Override + public WstxInputSource expand(WstxInputSource parent, + XMLResolver res, ReaderConfig cfg, + int xmlVersion) + throws IOException, XMLStreamException + { + /* 05-Feb-2006, TSa: If xmlVersion not explicitly known, it defaults + * to 1.0 + */ + if (xmlVersion == XmlConsts.XML_V_UNKNOWN) { + xmlVersion = XmlConsts.XML_V_10; + } + return DefaultInputResolver.resolveEntity + (parent, mContext, mName, getPublicId(), getSystemId(), res, cfg, xmlVersion); + } +} diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/ent/UnparsedExtEntity.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/ent/UnparsedExtEntity.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/ent/UnparsedExtEntity.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/ent/UnparsedExtEntity.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,75 @@ +package com.ctc.wstx.ent; + +import java.io.IOException; +import java.io.Writer; +import java.net.URL; + +import javax.xml.stream.Location; +import javax.xml.stream.XMLResolver; + +import com.ctc.wstx.api.ReaderConfig; +import com.ctc.wstx.io.WstxInputSource; + +public class UnparsedExtEntity + extends ExtEntity +{ + final String mNotationId; + + public UnparsedExtEntity(Location loc, String name, URL ctxt, + String pubId, String sysId, + String notationId) + { + super(loc, name, ctxt, pubId, sysId); + mNotationId = notationId; + } + + @Override + public String getNotationName() { + return mNotationId; + } + + /* + /////////////////////////////////////////// + // Implementation of abstract base methods + /////////////////////////////////////////// + */ + + @Override + public void writeEnc(Writer w) throws IOException + { + w.write("'); + } + + /* + /////////////////////////////////////////// + // Extended API for Wstx core + /////////////////////////////////////////// + */ + + // // // Type information + + @Override + public boolean isParsed() { return false; } + + @Override + public WstxInputSource expand(WstxInputSource parent, + XMLResolver res, ReaderConfig cfg, int xmlVersion) + { + // Should never get called, actually... + throw new IllegalStateException("Internal error: createInputSource() called for unparsed (external) entity."); + } +} diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/evt/BaseStartElement.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/evt/BaseStartElement.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/evt/BaseStartElement.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/evt/BaseStartElement.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,197 @@ +/* Woodstox XML processor + * + * Copyright (c) 2004 Tatu Saloranta, tatu.saloranta@iki.fi + * + * Licensed under the License specified in file LICENSE, included with + * the source code. + * You may not use this file except in compliance with the License. + * + * 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 com.ctc.wstx.evt; + +import java.io.IOException; +import java.io.Writer; +import java.util.Iterator; + +import javax.xml.namespace.NamespaceContext; +import javax.xml.namespace.QName; +import javax.xml.stream.*; +import javax.xml.stream.events.Attribute; +import javax.xml.stream.events.Namespace; +import javax.xml.stream.events.StartElement; + +import org.codehaus.stax2.XMLStreamWriter2; +import org.codehaus.stax2.ri.evt.BaseEventImpl; + +import com.ctc.wstx.exc.WstxIOException; +import com.ctc.wstx.util.BaseNsContext; +import com.ctc.wstx.util.DataUtil; + +/** + * Shared base class of {@link StartElement} implementations Wstx uses. + */ +abstract class BaseStartElement + extends BaseEventImpl + implements StartElement +{ + protected final QName mName; + + protected final BaseNsContext mNsCtxt; + + /* + ///////////////////////////////////////////// + // Life cycle + ///////////////////////////////////////////// + */ + + protected BaseStartElement(Location loc, QName name, BaseNsContext nsCtxt) + { + super(loc); + mName = name; + mNsCtxt = nsCtxt; + } + + /* + ///////////////////////////////////////////// + // StartElement API + ///////////////////////////////////////////// + */ + + @Override + public abstract Attribute getAttributeByName(QName name); + + @Override + public abstract Iterator getAttributes(); + + @Override + public final QName getName() { + return mName; + } + + @Override + public Iterator getNamespaces() + { + if (mNsCtxt == null) { + return DataUtil.emptyIterator(); + } + /* !!! 28-Sep-2004: Should refactor, since now it's up to ns context + * to construct namespace events... which adds unnecessary + * up-dependency from stream level to event objects. + */ + return mNsCtxt.getNamespaces(); + } + + @Override + public NamespaceContext getNamespaceContext() { + return mNsCtxt; + } + + @Override + public String getNamespaceURI(String prefix) { + return (mNsCtxt == null) ? null : mNsCtxt.getNamespaceURI(prefix); + } + + /* + ///////////////////////////////////////////////////// + // Implementation of abstract base methods, overrides + ///////////////////////////////////////////////////// + */ + + @Override + public StartElement asStartElement() { // overriden to save a cast + return this; + } + + @Override + public int getEventType() { + return START_ELEMENT; + } + + @Override + public boolean isStartElement() { + return true; + } + + @Override + public void writeAsEncodedUnicode(Writer w) + throws XMLStreamException + { + try { + w.write('<'); + String prefix = mName.getPrefix(); + if (prefix != null && prefix.length() > 0) { + w.write(prefix); + w.write(':'); + } + w.write(mName.getLocalPart()); + + // Base class can output namespaces and attributes: + outputNsAndAttr(w); + + w.write('>'); + } catch (IOException ie) { + throw new WstxIOException(ie); + } + } + + @Override + public void writeUsing(XMLStreamWriter2 w) throws XMLStreamException + { + QName n = mName; + w.writeStartElement(n.getPrefix(), n.getLocalPart(), + n.getNamespaceURI()); + outputNsAndAttr(w); + } + + protected abstract void outputNsAndAttr(Writer w) throws IOException; + + protected abstract void outputNsAndAttr(XMLStreamWriter w) throws XMLStreamException; + + /* + /////////////////////////////////////////// + // Standard method implementation + // + // note: copied from Stax2 RI's StartElementEventImpl + /////////////////////////////////////////// + */ + + @Override + public boolean equals(Object o) + { + if (o == this) return true; + if (o == null) return false; + + if (!(o instanceof StartElement)) return false; + + StartElement other = (StartElement) o; + + // First things first: names must match + if (mName.equals(other.getName())) { + /* Rest is much trickier. I guess the easiest way is to + * just blindly iterate through ns decls and attributes. + * The main issue is whether ordering should matter; it will, + * if just iterating. Would need to sort to get canonical + * comparison. + */ + if (iteratedEquals(getNamespaces(), other.getNamespaces())) { + return iteratedEquals(getAttributes(), other.getAttributes()); + } + } + return false; + } + + @Override + public int hashCode() + { + int hash = mName.hashCode(); + hash = addHash(getNamespaces(), hash); + hash = addHash(getAttributes(), hash); + return hash; + } +} diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/evt/CompactStartElement.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/evt/CompactStartElement.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/evt/CompactStartElement.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/evt/CompactStartElement.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,163 @@ +package com.ctc.wstx.evt; + +import java.io.IOException; +import java.io.Writer; +import java.util.ArrayList; +import java.util.Iterator; + +import javax.xml.namespace.QName; +import javax.xml.stream.*; +import javax.xml.stream.events.Attribute; +import javax.xml.stream.events.StartElement; + +import org.codehaus.stax2.ri.evt.AttributeEventImpl; + +import com.ctc.wstx.io.TextEscaper; +import com.ctc.wstx.sr.ElemAttrs; +import com.ctc.wstx.util.BaseNsContext; +import com.ctc.wstx.util.DataUtil; + +/** + * Wstx {@link StartElement} implementation used when directly creating + * events from a stream reader. + */ +public class CompactStartElement + extends BaseStartElement +{ + // Need to be in sync with ones from ElemAttrs + //private final static int OFFSET_LOCAL_NAME = 0; + private final static int OFFSET_NS_URI = 1; + private final static int OFFSET_NS_PREFIX = 2; + private final static int OFFSET_VALUE = 3; + + /* + //////////////////////////////////////////////////////////// + // Attribute information + //////////////////////////////////////////////////////////// + */ + + /** + * Container object that has enough information about attributes to + * be able to implement attribute accessor methods of this class. + */ + final ElemAttrs mAttrs; + + /** + * Array needed for accessing actual String components of the attributes + */ + final String[] mRawAttrs; + + /** + * Lazily created List that contains Attribute instances contained + * in this list. Created only if there are at least 2 attributes. + */ + private ArrayList mAttrList = null; + + /* + //////////////////////////////////////////////////////////// + // Life cycle + //////////////////////////////////////////////////////////// + */ + + protected CompactStartElement(Location loc, QName name, BaseNsContext nsCtxt, + ElemAttrs attrs) + { + super(loc, name, nsCtxt); + mAttrs = attrs; + mRawAttrs = (attrs == null) ? null : attrs.getRawAttrs(); + } + + /* + //////////////////////////////////////////////////////////// + // StartElement implementation + //////////////////////////////////////////////////////////// + */ + + @Override + public Attribute getAttributeByName(QName name) + { + if (mAttrs == null) { + return null; + } + int ix = mAttrs.findIndex(name); + if (ix < 0) { + return null; + } + return constructAttr(mRawAttrs, ix, mAttrs.isDefault(ix)); + } + + @Override + public Iterator getAttributes() + { + if (mAttrList == null) { // List is lazily constructed as needed + if (mAttrs == null) { + return DataUtil.emptyIterator(); + } + String[] rawAttrs = mRawAttrs; + int rawLen = rawAttrs.length; + int defOffset = mAttrs.getFirstDefaultOffset(); + if (rawLen == 4) { + return DataUtil.singletonIterator(constructAttr(rawAttrs, 0, (defOffset == 0))); + } + ArrayList l = new ArrayList(rawLen >> 2); + for (int i = 0; i < rawLen; i += 4) { + l.add(constructAttr(rawAttrs, i, (i >= defOffset))); + } + mAttrList = l; + } + return mAttrList.iterator(); + } + + @Override + protected void outputNsAndAttr(Writer w) throws IOException + { + if (mNsCtxt != null) { + mNsCtxt.outputNamespaceDeclarations(w); + } + + String[] raw = mRawAttrs; + if (raw != null) { + for (int i = 0, len = raw.length; i < len; i += 4) { + w.write(' '); + String prefix = raw[i + OFFSET_NS_PREFIX]; + if (prefix != null && prefix.length() > 0) { + w.write(prefix); + w.write(':'); + } + w.write(raw[i]); // local name + w.write("=\""); + TextEscaper.writeEscapedAttrValue(w, raw[i + OFFSET_VALUE]); + w.write('"'); + } + } + } + + @Override + protected void outputNsAndAttr(XMLStreamWriter w) throws XMLStreamException + { + if (mNsCtxt != null) { + mNsCtxt.outputNamespaceDeclarations(w); + } + String[] raw = mRawAttrs; + if (raw != null) { + for (int i = 0, len = raw.length; i < len; i += 4) { + String ln = raw[i]; + String prefix = raw[i + OFFSET_NS_PREFIX]; + String nsURI = raw[i + OFFSET_NS_URI]; + w.writeAttribute(prefix, nsURI, ln, raw[i + OFFSET_VALUE]); + } + } + } + + /* + //////////////////////////////////////////////////////////// + // Internal methods + //////////////////////////////////////////////////////////// + */ + + protected Attribute constructAttr(String[] raw, int rawIndex, boolean isDef) + { + return new AttributeEventImpl(getLocation(), raw[rawIndex], raw[rawIndex+1], + raw[rawIndex+2], raw[rawIndex+3], !isDef); + } +} diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/evt/DefaultEventAllocator.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/evt/DefaultEventAllocator.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/evt/DefaultEventAllocator.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/evt/DefaultEventAllocator.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,289 @@ +/* Woodstox XML processor + * + * Copyright (c) 2004 Tatu Saloranta, tatu.saloranta@iki.fi + * + * Licensed under the License specified in file LICENSE, included with + * the source code. + * You may not use this file except in compliance with the License. + * + * 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 com.ctc.wstx.evt; + +import java.util.*; + +import javax.xml.namespace.QName; +import javax.xml.namespace.NamespaceContext; +import javax.xml.stream.*; +import javax.xml.stream.events.Attribute; +import javax.xml.stream.events.Namespace; +import javax.xml.stream.events.XMLEvent; +import javax.xml.stream.util.XMLEventAllocator; +import javax.xml.stream.util.XMLEventConsumer; + +import org.codehaus.stax2.*; +import org.codehaus.stax2.ri.evt.*; + +import com.ctc.wstx.cfg.ErrorConsts; +import com.ctc.wstx.dtd.DTDSubset; +import com.ctc.wstx.ent.EntityDecl; +import com.ctc.wstx.exc.WstxException; +import com.ctc.wstx.sr.ElemAttrs; +import com.ctc.wstx.sr.ElemCallback; +import com.ctc.wstx.sr.StreamReaderImpl; +import com.ctc.wstx.util.BaseNsContext; + +/** + * Straight-forward implementation of {@link XMLEventAllocator}, to be + * used with Woodstox' event reader. + *

+ * One of few complications here is the way start elements are constructed. + * The pattern used is double-indirection, needed to get a callback from + * the stream reader, with data we need for constructing even Object... + * but without stream reader having any understanding of event Objects + * per se. + *

+ * 03-Dec-2004, TSa: One additional twist is that it's now possible to + * create slightly faster event handling, by indicating that the + * fully accurate Location information is not necessary. If so, + * allocator will just use one shared Location object passed to + * all event objects constructed. + */ +public class DefaultEventAllocator + extends ElemCallback + implements XMLEventAllocator, XMLStreamConstants +{ + final static DefaultEventAllocator sStdInstance = new DefaultEventAllocator(true); + + /* + /////////////////////////////////////////////////////////// + // Configuration + /////////////////////////////////////////////////////////// + */ + + protected final boolean mAccurateLocation; + + /* + /////////////////////////////////////////////////////////// + // Recycled objects + /////////////////////////////////////////////////////////// + */ + + /** + * Last used location info; only relevant to non-accurate-location + * allocators. + */ + protected Location mLastLocation = null; + + /** + * @param accurateLocation If true, allocator will construct instances + * that have accurate location information; if false, instances + * will only have some generic shared Location info. Latter option + * will reduce memory usage/thrashing a bit, and may improve speed. + */ + protected DefaultEventAllocator(boolean accurateLocation) { + mAccurateLocation = accurateLocation; + } + + public static DefaultEventAllocator getDefaultInstance() { + /* Default (accurate location) instance can be shared as it + * has no state + */ + return sStdInstance; + } + + public static DefaultEventAllocator getFastInstance() { + /* Can not share instances, due to QName caching, as well as because + * of Location object related state + */ + return new DefaultEventAllocator(false); + } + + /* + /////////////////////////////////////////////////////////// + // XMLEventAllocator implementation + /////////////////////////////////////////////////////////// + */ + + @Override + public XMLEvent allocate(XMLStreamReader r) throws XMLStreamException + { + Location loc; + + // Need to keep track of accurate location info? + if (mAccurateLocation) { + loc = r.getLocation(); + } else { + loc = mLastLocation; + /* And even if we can just share one instance, we need that + * first instance... + */ + if (loc == null) { + loc = mLastLocation = r.getLocation(); + } + } + + switch (r.getEventType()) { + case CDATA: + return new CharactersEventImpl(loc, r.getText(), true); + case CHARACTERS: + return new CharactersEventImpl(loc, r.getText(), false); + case COMMENT: + return new CommentEventImpl(loc, r.getText()); + case DTD: + // Not sure if we really need this defensive coding but... + if (r instanceof XMLStreamReader2) { + XMLStreamReader2 sr2 = (XMLStreamReader2) r; + DTDInfo dtd = sr2.getDTDInfo(); + return new WDTD(loc, + dtd.getDTDRootName(), + dtd.getDTDSystemId(), dtd.getDTDPublicId(), + dtd.getDTDInternalSubset(), + (DTDSubset) dtd.getProcessedDTD()); + } + /* No way to get all information... the real big problem is + * that of how to access root name: it's obligatory for + * DOCTYPE construct. :-/ + */ + return new WDTD(loc, null, r.getText()); + + case END_DOCUMENT: + return new EndDocumentEventImpl(loc); + + case END_ELEMENT: + return new EndElementEventImpl(loc, r); + + case PROCESSING_INSTRUCTION: + return new ProcInstrEventImpl(loc, r.getPITarget(), r.getPIData()); + case SPACE: + { + CharactersEventImpl ch = new CharactersEventImpl(loc, r.getText(), false); + ch.setWhitespaceStatus(true); + return ch; + } + case START_DOCUMENT: + return new StartDocumentEventImpl(loc, r); + + case START_ELEMENT: + { + /* Creating the event is bit complicated, as the stream + * reader is not to know anything about event objects. + * To do this, we do double-indirection, which means that + * this object actually gets a callback: + */ + /* 19-Jul-2006, TSa: WSTX-61 points out that the code was + * assuming it's always Woodstox reader we had... not + * necessarily so. + */ + if (r instanceof StreamReaderImpl) { + StreamReaderImpl sr = (StreamReaderImpl) r; + BaseStartElement be = (BaseStartElement) sr.withStartElement(this, loc); + if (be == null) { // incorrect state + throw new WstxException("Trying to create START_ELEMENT when current event is " + +ErrorConsts.tokenTypeDesc(sr.getEventType()), + loc); + } + return be; + } + /* Ok, not woodstox impl, will be bit more work (plus less + * efficient, and may miss some info)... but can be done. + */ + NamespaceContext nsCtxt = null; + if (r instanceof XMLStreamReader2) { + nsCtxt = ((XMLStreamReader2) r).getNonTransientNamespaceContext(); + } + Map attrs; + { + int attrCount = r.getAttributeCount(); + if (attrCount < 1) { + attrs = null; + } else { + attrs = new LinkedHashMap(); + for (int i = 0; i < attrCount; ++i) { + QName aname = r.getAttributeName(i); + attrs.put(aname, new AttributeEventImpl(loc, aname, r.getAttributeValue(i), r.isAttributeSpecified(i))); + } + } + } + List ns; + { + int nsCount = r.getNamespaceCount(); + if (nsCount < 1) { + ns = null; + } else { + ns = new ArrayList(nsCount); + for (int i = 0; i < nsCount; ++i) { + ns.add(NamespaceEventImpl.constructNamespace(loc, r.getNamespacePrefix(i), r.getNamespaceURI(i))); + } + } + } + + return SimpleStartElement.construct(loc, r.getName(), attrs, ns, nsCtxt); + } + + case ENTITY_REFERENCE: + { + /* 19-Jul-2006, TSa: Let's also allow other impls, although + * we can't get actual declaration if so... + */ + if (r instanceof StreamReaderImpl) { + EntityDecl ed = ((StreamReaderImpl) r).getCurrentEntityDecl(); + if (ed == null) { // undefined? + // We'll still know the name though... + return new WEntityReference(loc, r.getLocalName()); + } + return new WEntityReference(loc, ed); + } + return new WEntityReference(loc, r.getLocalName()); + } + + + /* Following 2 types should never get in here; they are directly + * handled by DTDReader, and can only be accessed via DTD event + * element. + */ + case ENTITY_DECLARATION: + case NOTATION_DECLARATION: + /* Following 2 types should never get in here; they are directly + * handled by the reader, and can only be accessed via start + * element. + */ + case NAMESPACE: + case ATTRIBUTE: + throw new WstxException("Internal error: should not get " + +ErrorConsts.tokenTypeDesc(r.getEventType())); + default: + throw new IllegalStateException("Unrecognized event type "+r.getEventType()+"."); + } + } + + @Override + public void allocate(XMLStreamReader r, XMLEventConsumer consumer) + throws XMLStreamException + { + consumer.add(allocate(r)); + } + + @Override + public XMLEventAllocator newInstance() { + return new DefaultEventAllocator(mAccurateLocation); + } + + /* + /////////////////////////////////////////////////////////// + // ElemCallback implementation + /////////////////////////////////////////////////////////// + */ + + @Override + public Object withStartElement(Location loc, QName name, + BaseNsContext nsCtxt, ElemAttrs attrs, boolean wasEmpty) + { + return new CompactStartElement(loc, name, nsCtxt, attrs); + } +} diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/evt/MergedNsContext.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/evt/MergedNsContext.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/evt/MergedNsContext.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/evt/MergedNsContext.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,224 @@ +package com.ctc.wstx.evt; + +import java.io.IOException; +import java.io.Writer; +import java.util.*; + +import javax.xml.XMLConstants; +import javax.xml.namespace.NamespaceContext; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamWriter; +import javax.xml.stream.events.Namespace; + +import com.ctc.wstx.util.BaseNsContext; +import com.ctc.wstx.util.DataUtil; + +/** + * Hierarchic {@link NamespaceContext} implementation used when constructing + * event and namespace information explicitly via + * {@link javax.xml.stream.XMLEventFactory}, + * not by a stream reader. + *

+ * TODO: + *

    + *
  • Figure out a way to check for namespace masking; tricky but not + * impossible to determine + *
  • + *
+ */ +public class MergedNsContext + extends BaseNsContext +{ + final NamespaceContext mParentCtxt; + + /** + * List of {@link Namespace} instances. + */ + final List mNamespaces; + + Map mNsByPrefix = null; + + Map mNsByURI = null; + + protected MergedNsContext(NamespaceContext parentCtxt, List localNs) + { + mParentCtxt = parentCtxt; + if (localNs == null){ + mNamespaces = Collections.emptyList(); + } else { + mNamespaces = localNs; + } + } + + public static BaseNsContext construct(NamespaceContext parentCtxt, + List localNs) + { + return new MergedNsContext(parentCtxt, localNs); + } + + /* + ///////////////////////////////////////////// + // NamespaceContext API + ///////////////////////////////////////////// + */ + + @Override + public String doGetNamespaceURI(String prefix) + { + // Note: base class checks for 'known' problems and prefixes: + if (mNsByPrefix == null) { + mNsByPrefix = buildByPrefixMap(); + } + Namespace ns = mNsByPrefix.get(prefix); + if (ns == null && mParentCtxt != null) { + return mParentCtxt.getNamespaceURI(prefix); + } + return (ns == null) ? null : ns.getNamespaceURI(); + } + + @Override + public String doGetPrefix(String nsURI) + { + // Note: base class checks for 'known' problems and prefixes: + if (mNsByURI == null) { + mNsByURI = buildByNsURIMap(); + } + Namespace ns = mNsByURI.get(nsURI); + if (ns == null && mParentCtxt != null) { + return mParentCtxt.getPrefix(nsURI); + } + return (ns == null) ? null : ns.getPrefix(); + } + + @Override + public Iterator doGetPrefixes(String nsURI) + { + // Note: base class checks for 'known' problems and prefixes: + ArrayList l = null; + + for (int i = 0, len = mNamespaces.size(); i < len; ++i) { + Namespace ns = mNamespaces.get(i); + String uri = ns.getNamespaceURI(); + if (uri == null) { + uri = ""; + } + if (uri.equals(nsURI)) { + if (l == null) { + l = new ArrayList(); + } + String prefix = ns.getPrefix(); + l.add((prefix == null) ? "" : prefix); + } + } + + if (mParentCtxt != null) { + @SuppressWarnings("unchecked") + Iterator it = /*(Iterator)*/mParentCtxt.getPrefixes(nsURI); + if (l == null) { + return it; + } + while (it.hasNext()) { + l.add(it.next()); + } + } + + if (l == null) { + return DataUtil.emptyIterator(); + } + return l.iterator(); + } + + /* + ///////////////////////////////////////////// + // Extended API + ///////////////////////////////////////////// + */ + + /** + * Method that returns information about namespace definition declared + * in this scope; not including ones declared in outer scopes. + */ + @Override + public Iterator getNamespaces() { + return mNamespaces.iterator(); + } + + @Override + public void outputNamespaceDeclarations(Writer w) throws IOException + { + for (int i = 0, len = mNamespaces.size(); i < len; ++i) { + Namespace ns = mNamespaces.get(i); + w.write(' '); + w.write(XMLConstants.XMLNS_ATTRIBUTE); + if (!ns.isDefaultNamespaceDeclaration()) { + w.write(':'); + w.write(ns.getPrefix()); + } + w.write("=\""); + w.write(ns.getNamespaceURI()); + w.write('"'); + } + } + + /** + * Method called by the matching start element class to + * output all namespace declarations active in current namespace + * scope, if any. + */ + @Override + public void outputNamespaceDeclarations(XMLStreamWriter w) throws XMLStreamException + { + for (int i = 0, len = mNamespaces.size(); i < len; ++i) { + Namespace ns = mNamespaces.get(i); + if (ns.isDefaultNamespaceDeclaration()) { + w.writeDefaultNamespace(ns.getNamespaceURI()); + } else { + w.writeNamespace(ns.getPrefix(), ns.getNamespaceURI()); + } + } + } + + /* + ///////////////////////////////////////////// + // Private methods: + ///////////////////////////////////////////// + */ + + private Map buildByPrefixMap() + { + int len = mNamespaces.size(); + if (len == 0) { + return Collections.emptyMap(); + } + + LinkedHashMap m = new LinkedHashMap(1 + len + (len>>1)); + for (int i = 0; i < len; ++i) { + Namespace ns = mNamespaces.get(i); + String prefix = ns.getPrefix(); + if (prefix == null) { // shouldn't happen but... + prefix = ""; + } + m.put(prefix, ns); + } + return m; + } + + private Map buildByNsURIMap() + { + int len = mNamespaces.size(); + if (len == 0) { + return Collections.emptyMap(); + } + + LinkedHashMap m = new LinkedHashMap(1 + len + (len>>1)); + for (int i = 0; i < len; ++i) { + Namespace ns = mNamespaces.get(i); + String uri = ns.getNamespaceURI(); + if (uri == null) { // shouldn't happen but... + uri = ""; + } + m.put(uri, ns); + } + return m; + } +} diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/evt/package.html libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/evt/package.html --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/evt/package.html 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/evt/package.html 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,4 @@ + +Package contains Woodstox implementation of the StAX event layer; functionality +that is built on top of stream readers and writers. + diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/evt/SimpleStartElement.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/evt/SimpleStartElement.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/evt/SimpleStartElement.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/evt/SimpleStartElement.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,171 @@ +package com.ctc.wstx.evt; + +import java.io.IOException; +import java.io.Writer; +import java.util.*; + +import javax.xml.namespace.NamespaceContext; +import javax.xml.namespace.QName; +import javax.xml.stream.Location; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamWriter; +import javax.xml.stream.events.Attribute; +import javax.xml.stream.events.Namespace; +import javax.xml.stream.events.StartElement; + +import com.ctc.wstx.io.TextEscaper; +import com.ctc.wstx.util.BaseNsContext; +import com.ctc.wstx.util.DataUtil; + +/** + * Wstx {@link StartElement} implementation used when event is constructed + * from already objectified data, for example when constructed by the event + * factory. + */ +public class SimpleStartElement + extends BaseStartElement +{ + final Map mAttrs; + + /* + ///////////////////////////////////////////// + // Life cycle + ///////////////////////////////////////////// + */ + + protected SimpleStartElement(Location loc, QName name, BaseNsContext nsCtxt, + Map attr) + { + super(loc, name, nsCtxt); + mAttrs = attr; + } + + /** + * Factory method called when a start element needs to be constructed + * from an external source (most likely, non-woodstox stream reader). + */ + public static SimpleStartElement construct(Location loc, QName name, + Map attrs, List ns, + NamespaceContext nsCtxt) + { + BaseNsContext myCtxt = MergedNsContext.construct(nsCtxt, ns); + return new SimpleStartElement(loc, name, myCtxt, attrs); + } + + public static SimpleStartElement construct(Location loc, QName name, + Iterator attrs, Iterator ns, + NamespaceContext nsCtxt) + { + Map attrMap; + if (attrs == null || !attrs.hasNext()) { + attrMap = null; + } else { + attrMap = new LinkedHashMap(); + do { + Attribute attr = attrs.next(); + attrMap.put(attr.getName(), attr); + } while (attrs.hasNext()); + } + + BaseNsContext myCtxt; + if (ns != null && ns.hasNext()) { + ArrayList l = new ArrayList(); + do { + l.add(ns.next()); // cast to catch type problems early + } while (ns.hasNext()); + myCtxt = MergedNsContext.construct(nsCtxt, l); + } else { + /* Doh. Need specificially 'our' namespace context, to get them + * output properly... + */ + if (nsCtxt == null) { + myCtxt = null; + } else if (nsCtxt instanceof BaseNsContext) { + myCtxt = (BaseNsContext) nsCtxt; + } else { + myCtxt = MergedNsContext.construct(nsCtxt, null); + } + } + return new SimpleStartElement(loc, name, myCtxt, attrMap); + } + + /* + ///////////////////////////////////////////// + // Public API + ///////////////////////////////////////////// + */ + + @Override + public Attribute getAttributeByName(QName name) + { + if (mAttrs == null) { + return null; + } + return mAttrs.get(name); + } + + @Override + public Iterator getAttributes() + { + if (mAttrs == null) { + return DataUtil.emptyIterator(); + } + return mAttrs.values().iterator(); + } + + @Override + protected void outputNsAndAttr(Writer w) throws IOException + { + // First namespace declarations, if any: + if (mNsCtxt != null) { + mNsCtxt.outputNamespaceDeclarations(w); + } + // Then attributes, if any: + if (mAttrs != null && mAttrs.size() > 0) { + for (Attribute attr : mAttrs.values()) { + // Let's only output explicit attribute values: + if (!attr.isSpecified()) { + continue; + } + + w.write(' '); + QName name = attr.getName(); + String prefix = name.getPrefix(); + if (prefix != null && prefix.length() > 0) { + w.write(prefix); + w.write(':'); + } + w.write(name.getLocalPart()); + w.write("=\""); + String val = attr.getValue(); + if (val != null && val.length() > 0) { + TextEscaper.writeEscapedAttrValue(w, val); + } + w.write('"'); + } + } + } + + @Override + protected void outputNsAndAttr(XMLStreamWriter w) throws XMLStreamException + { + // First namespace declarations, if any: + if (mNsCtxt != null) { + mNsCtxt.outputNamespaceDeclarations(w); + } + // Then attributes, if any: + if (mAttrs != null && mAttrs.size() > 0) { + for (Attribute attr : mAttrs.values()) { + // Let's only output explicit attribute values: + if (!attr.isSpecified()) { + continue; + } + QName name = attr.getName(); + String prefix = name.getPrefix(); + String ln = name.getLocalPart(); + String nsURI = name.getNamespaceURI(); + w.writeAttribute(prefix, nsURI, ln, attr.getValue()); + } + } + } +} diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/evt/WDTD.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/evt/WDTD.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/evt/WDTD.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/evt/WDTD.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,97 @@ +package com.ctc.wstx.evt; + +import java.util.ArrayList; +import java.util.List; + +import javax.xml.stream.Location; +import javax.xml.stream.events.EntityDeclaration; +import javax.xml.stream.events.NotationDeclaration; + +import org.codehaus.stax2.ri.evt.DTDEventImpl; + +import com.ctc.wstx.dtd.DTDSubset; + +/** + * Event that contains all StAX accessible information read from internal + * and external DTD subsets. + */ +public class WDTD + extends DTDEventImpl +{ + /** + * Internal DTD Object that contains combined information from internal + * and external subsets. + */ + final DTDSubset mSubset; + + /* + ///////////////////////////////////////////////////// + // Lazily constructed objects + ///////////////////////////////////////////////////// + */ + + List mEntities = null; + + List mNotations = null; + + /* + ///////////////////////////////////////////////////// + // Constuctors + ///////////////////////////////////////////////////// + */ + + public WDTD(Location loc, String rootName, + String sysId, String pubId, String intSubset, + DTDSubset dtdSubset) + { + super(loc, rootName, sysId, pubId, intSubset, dtdSubset); + mSubset = dtdSubset; + } + + public WDTD(Location loc, String rootName, + String sysId, String pubId, String intSubset) + { + this(loc, rootName, sysId, pubId, intSubset, null); + } + + /** + * Constructor used when only partial information is available... + */ + public WDTD(Location loc, String rootName, String intSubset) + { + this(loc, rootName, null, null, intSubset, null); + } + + public WDTD(Location loc, String fullText) + { + super(loc, fullText); + mSubset = null; + } + + /* + ///////////////////////////////////////////////////// + // Accessors + ///////////////////////////////////////////////////// + */ + + @Override + public List getEntities() + { + if (mEntities == null && (mSubset != null)) { + /* Better make a copy, so that caller can not modify list + * DTD has, which may be shared (since DTD subset instances + * are cached and reused) + */ + mEntities = new ArrayList(mSubset.getGeneralEntityList()); + } + return mEntities; + } + + @Override + public List getNotations() { + if (mNotations == null && (mSubset != null)) { + mNotations = new ArrayList(mSubset.getNotationList()); + } + return mNotations; + } +} diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/evt/WEntityDeclaration.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/evt/WEntityDeclaration.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/evt/WEntityDeclaration.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/evt/WEntityDeclaration.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,119 @@ +package com.ctc.wstx.evt; + +import java.io.IOException; +import java.io.Writer; + +import javax.xml.stream.Location; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.events.EntityDeclaration; + +import org.codehaus.stax2.XMLStreamWriter2; +import org.codehaus.stax2.ri.evt.BaseEventImpl; + +import com.ctc.wstx.ent.EntityDecl; +import com.ctc.wstx.exc.WstxIOException; + +/** + * Simple implementation of StAX entity declaration events; for the + * most just wraps a {@link EntityDecl} instance. + */ +public abstract class WEntityDeclaration + extends BaseEventImpl + implements EntityDeclaration +{ + public WEntityDeclaration(Location loc) + { + super(loc); + } + + @Override + public abstract String getBaseURI(); + + @Override + public abstract String getName(); + + @Override + public abstract String getNotationName(); + + @Override + public abstract String getPublicId(); + + @Override + public abstract String getReplacementText(); + + @Override + public abstract String getSystemId(); + + /* + /////////////////////////////////////////// + // Implementation of abstract base methods + /////////////////////////////////////////// + */ + + @Override + public int getEventType() { + return ENTITY_DECLARATION; + } + + public abstract void writeEnc(Writer w) throws IOException; + + @Override + public void writeAsEncodedUnicode(Writer w) throws XMLStreamException + { + try { + writeEnc(w); + } catch (IOException ie) { + throw new WstxIOException(ie); + } + } + + /** + * This method does not make much sense for this event type -- the reason + * being that the entity declarations can only be written as part of + * a DTD (internal or external subset), not separately. Can basically + * choose to either skip silently (output nothing), or throw an + * exception. + */ + @Override + public void writeUsing(XMLStreamWriter2 w) throws XMLStreamException + { + /* Fail silently, or throw an exception? Let's do latter; at least + * then we'll get useful (?) bug reports! + */ + throw new XMLStreamException("Can not write entity declarations using an XMLStreamWriter"); + } + + /* + /////////////////////////////////////////// + // Standard method impl: note, copied + // from Stax2 RI "EntityDeclarationEventImpl" + /////////////////////////////////////////// + */ + + @Override + public boolean equals(Object o) + { + if (o == this) return true; + if (o == null) return false; + + if (!(o instanceof EntityDeclaration)) return false; + + EntityDeclaration other = (EntityDeclaration) o; + return stringsWithNullsEqual(getName(), other.getName()) + && stringsWithNullsEqual(getBaseURI(), other.getBaseURI()) + && stringsWithNullsEqual(getNotationName(), other.getNotationName()) + && stringsWithNullsEqual(getPublicId(), other.getPublicId()) + && stringsWithNullsEqual(getReplacementText(), other.getReplacementText()) + && stringsWithNullsEqual(getSystemId(), other.getSystemId()) + ; + } + + @Override + public int hashCode() + { + /* Hmmh. Could try using most of the data, but really, name + * should be enough for most use cases + */ + return getName().hashCode(); + } +} diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/evt/WEntityReference.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/evt/WEntityReference.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/evt/WEntityReference.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/evt/WEntityReference.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,45 @@ +package com.ctc.wstx.evt; + +import javax.xml.stream.Location; +import javax.xml.stream.events.EntityReference; +import javax.xml.stream.events.EntityDeclaration; + +import org.codehaus.stax2.ri.evt.EntityReferenceEventImpl; + +/** + * We need a slightly specialized version to support concept of + * undeclared entities, which can be used in (non-default, non-standard) + * mode where undeclared entities are allowed to be handled. + */ +public class WEntityReference + extends EntityReferenceEventImpl + implements EntityReference +{ + final String mName; + + public WEntityReference(Location loc, EntityDeclaration decl) + { + super(loc, decl); + mName = null; + } + + /** + * This constructor gets called for undeclared/defined entities: we will + * still know the name (from the reference), but not how it's defined + * (since it is not defined). + */ + public WEntityReference(Location loc, String name) + { + super(loc, (EntityDeclaration) null); + mName = name; + } + + @Override + public String getName() + { + if (mName != null) { + return mName; + } + return super.getName(); + } +} diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/evt/WNotationDeclaration.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/evt/WNotationDeclaration.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/evt/WNotationDeclaration.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/evt/WNotationDeclaration.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,43 @@ +package com.ctc.wstx.evt; + +import java.net.URL; + +import javax.xml.stream.Location; + +import org.codehaus.stax2.ri.evt.NotationDeclarationEventImpl; + +/** + * Woodstox implementation of {@link org.codehaus.stax2.evt.NotationDeclaration2}. + * The only required addition is that of passing in the Base URI. + * + * @author Tatu Saloranta + * + * @since 4.0.0 + */ +public class WNotationDeclaration + extends NotationDeclarationEventImpl +{ + /** + * Base URL that can be used to resolve the notation reference if + * necessary. + */ + final URL _baseURL; + + public WNotationDeclaration(Location loc, + String name, String pubId, String sysId, + URL baseURL) + { + super(loc, name, pubId, sysId); + _baseURL = baseURL; + } + + @Override + public String getBaseURI() + { + if (_baseURL == null) { + return super.getBaseURI(); + } + return _baseURL.toExternalForm(); + } +} + diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/evt/WstxEventReader.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/evt/WstxEventReader.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/evt/WstxEventReader.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/evt/WstxEventReader.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,87 @@ +/* Woodstox XML processor + * + * Copyright (c) 2004- Tatu Saloranta, tatu.saloranta@iki.fi + * + * Licensed under the License specified in the file LICENSE which is + * included with the source code. + * You may not use this file except in compliance with the License. + * + * 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 com.ctc.wstx.evt; + +import javax.xml.stream.*; +import javax.xml.stream.util.XMLEventAllocator; + +import org.codehaus.stax2.XMLStreamReader2; +import org.codehaus.stax2.ri.Stax2EventReaderImpl; + +import com.ctc.wstx.cfg.ErrorConsts; +import com.ctc.wstx.exc.WstxParsingException; + +/** + * Woodstox version, based on generic Stax reference implementation + * baseline of {@link Stax2EventReaderImpl}. + */ +public class WstxEventReader + extends Stax2EventReaderImpl +{ + public WstxEventReader(XMLEventAllocator a, XMLStreamReader2 r) + { + super(a, r); + } + + /* + ////////////////////////////////////////////////////// + // Impl of abstract methods + ////////////////////////////////////////////////////// + */ + + @Override + protected String getErrorDesc(int errorType, int currEvent) + { + // Defaults are mostly fine, except we can easily add event type desc + switch (errorType) { + case ERR_GETELEMTEXT_NOT_START_ELEM: + return ErrorConsts.ERR_STATE_NOT_STELEM+", got "+ErrorConsts.tokenTypeDesc(currEvent); + case ERR_GETELEMTEXT_NON_TEXT_EVENT: + return "Expected a text token, got "+ErrorConsts.tokenTypeDesc(currEvent); + case ERR_NEXTTAG_NON_WS_TEXT: + return "Only all-whitespace CHARACTERS/CDATA (or SPACE) allowed for nextTag(), got "+ErrorConsts.tokenTypeDesc(currEvent); + case ERR_NEXTTAG_WRONG_TYPE: + return "Got "+ErrorConsts.tokenTypeDesc(currEvent)+", instead of START_ELEMENT, END_ELEMENT or SPACE"; + } + return null; + } + + @Override + public boolean isPropertySupported(String name) + { + return ((XMLStreamReader2)getStreamReader()).isPropertySupported(name); + } + + @Override + public boolean setProperty(String name, Object value) + { + return ((XMLStreamReader2)getStreamReader()).setProperty(name, value); + } + + + /* + ////////////////////////////////////////////////////// + // Overrides + ////////////////////////////////////////////////////// + */ + + @Override + protected void reportProblem(String msg, Location loc) + throws XMLStreamException + { + throw new WstxParsingException(msg, loc); + } +} diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/exc/package.html libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/exc/package.html --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/exc/package.html 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/exc/package.html 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,4 @@ + +Package that contains all exceptions Woodstox readers and writers throw. +Exceptions generally extend {@link javax.xml.stream.XMLStreamException}. + diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/exc/WstxEOFException.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/exc/WstxEOFException.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/exc/WstxEOFException.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/exc/WstxEOFException.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,16 @@ +package com.ctc.wstx.exc; + +import javax.xml.stream.Location; + +/** + * Exception thrown during parsing, if an unexpected EOF is encountered. + * Location usually signals starting position of current Node. + */ +@SuppressWarnings("serial") +public class WstxEOFException + extends WstxParsingException +{ + public WstxEOFException(String msg, Location loc) { + super(msg, loc); + } +} diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/exc/WstxException.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/exc/WstxException.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/exc/WstxException.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/exc/WstxException.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,97 @@ +/* Woodstox XML processor + * + * Copyright (c) 2004 Tatu Saloranta, tatu.saloranta@iki.fi + * + * Licensed under the License specified in file LICENSE, included with + * the source code. + * You may not use this file except in compliance with the License. + * + * 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 com.ctc.wstx.exc; + +import javax.xml.stream.Location; +import javax.xml.stream.XMLStreamException; + +import com.ctc.wstx.util.StringUtil; + +/** + * Base class for all implementatations of {@link XMLStreamException} + * Wstx uses. + */ +@SuppressWarnings("serial") +public class WstxException + extends XMLStreamException +{ + /** + * D'oh. Super-class munges and hides the message, have to duplicate here + */ + final protected String mMsg; + + public WstxException(String msg) { + super(msg); + mMsg = msg; + } + + public WstxException(Throwable th) { + super(th.getMessage(), th); + mMsg = th.getMessage(); + } + + public WstxException(String msg, Location loc) { + super(msg, loc); + mMsg = msg; + } + + public WstxException(String msg, Location loc, Throwable th) { + super(msg, loc, th); + mMsg = msg; + } + + /** + * Method is overridden for two main reasons: first, default method + * does not display public/system id information, even if it exists, and + * second, default implementation can not handle nested Location + * information. + */ + @Override + public String getMessage() + { + String locMsg = getLocationDesc(); + /* Better not use super's message if we do have location information, + * since parent's message contains (part of) Location + * info; something we can regenerate better... + */ + if (locMsg == null) { + return super.getMessage(); + } + StringBuilder sb = new StringBuilder(mMsg.length() + locMsg.length() + 20); + sb.append(mMsg); + StringUtil.appendLF(sb); + sb.append(" at "); + sb.append(locMsg); + return sb.toString(); + } + + @Override + public String toString() { + return getClass().getName()+": "+getMessage(); + } + + /* + //////////////////////////////////////////////////////// + // Internal methods: + //////////////////////////////////////////////////////// + */ + + protected String getLocationDesc() + { + Location loc = getLocation(); + return (loc == null) ? null : loc.toString(); + } +} diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/exc/WstxIOException.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/exc/WstxIOException.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/exc/WstxIOException.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/exc/WstxIOException.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,20 @@ +package com.ctc.wstx.exc; + +import java.io.IOException; + +/** + * Simple wrapper for {@link IOException}s; needed when StAX does not expose + * underlying I/O exceptions via its methods. + */ +@SuppressWarnings("serial") +public class WstxIOException + extends WstxException +{ + public WstxIOException(IOException ie) { + super(ie); + } + + public WstxIOException(String msg) { + super(msg); + } +} diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/exc/WstxLazyException.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/exc/WstxLazyException.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/exc/WstxLazyException.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/exc/WstxLazyException.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,56 @@ +/* Woodstox XML processor + * + * Copyright (c) 2004 Tatu Saloranta, tatu.saloranta@iki.fi + * + * Licensed under the License specified in file LICENSE, included with + * the source code. + * You may not use this file except in compliance with the License. + * + * 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 com.ctc.wstx.exc; + +import javax.xml.stream.XMLStreamException; + +/** + * Alternative exception class Woodstox code uses when it is not allowed + * to throw an instance of {@link XMLStreamException}; this generally + * happens when doing lazy parsing. + */ +@SuppressWarnings("serial") +public class WstxLazyException + extends RuntimeException +{ + final XMLStreamException mOrig; + + public WstxLazyException(XMLStreamException origEx) + { + super(origEx.getMessage(), origEx); + mOrig = origEx; + } + + public static void throwLazily(XMLStreamException ex) + throws WstxLazyException + { + throw new WstxLazyException(ex); + } + + /** + * Need to override this, to be able to dynamically construct and + * display the location information... + */ + @Override + public String getMessage() { + return "["+getClass().getName()+"] "+mOrig.getMessage(); + } + + @Override + public String toString() { + return "["+getClass().getName()+"] "+mOrig.toString(); + } +} diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/exc/WstxOutputException.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/exc/WstxOutputException.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/exc/WstxOutputException.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/exc/WstxOutputException.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,15 @@ +package com.ctc.wstx.exc; + +/** + * Exception class used for notifying about well-formedness errors that + * writers would create. Such exceptions are thrown when strict output + * validation is enabled. + */ +@SuppressWarnings("serial") +public class WstxOutputException + extends WstxException +{ + public WstxOutputException(String msg) { + super(msg); + } +} diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/exc/WstxParsingException.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/exc/WstxParsingException.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/exc/WstxParsingException.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/exc/WstxParsingException.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,18 @@ +package com.ctc.wstx.exc; + +import javax.xml.stream.Location; + +/** + * Intermediate base class for reporting actual Wstx parsing problems. + */ +@SuppressWarnings("serial") +public class WstxParsingException + extends WstxException +{ + public WstxParsingException(String msg, Location loc) { + super(msg, loc); + } + + // !!! 13-Sep-2008, tatus: Only needed for DOMWrapping reader, for now + public WstxParsingException(String msg) { super(msg); } +} diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/exc/WstxUnexpectedCharException.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/exc/WstxUnexpectedCharException.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/exc/WstxUnexpectedCharException.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/exc/WstxUnexpectedCharException.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,25 @@ +package com.ctc.wstx.exc; + +import javax.xml.stream.Location; + +/** + * Generic exception type that indicates that tokenizer/parser encountered + * unexpected (but not necessarily invalid per se) character; character that + * is not legal in current context. Could happen, for example, if white space + * was missing between attribute value and name of next attribute. + */ +@SuppressWarnings("serial") +public class WstxUnexpectedCharException + extends WstxParsingException +{ + final char mChar; + + public WstxUnexpectedCharException(String msg, Location loc, char c) { + super(msg, loc); + mChar = c; + } + + public char getChar() { + return mChar; + } +} diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/exc/WstxValidationException.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/exc/WstxValidationException.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/exc/WstxValidationException.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/exc/WstxValidationException.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,101 @@ +package com.ctc.wstx.exc; + +import javax.xml.stream.Location; +import javax.xml.stream.XMLStreamException; + +import org.codehaus.stax2.validation.XMLValidationException; +import org.codehaus.stax2.validation.XMLValidationProblem; + +import com.ctc.wstx.util.StringUtil; + +/** + * Specific exception thrown when document has validation (DTD, W3C Schema) + * errors; things that are not well-formedness problems. + *

+ * The current implementation does not add much beyond basic + * {@link XMLValidationException}, except for fixing some problems that + * underlying {@link XMLStreamException} has. + *

+ * Note that some of the code is shared with {@link WstxException}. Unfortunately + * it is not possible to extend it, however, since it extends basic + * {@link XMLStreamException}, not {@link XMLValidationException}. + *

+ * One more thing to note: unlike some other exception classes, these + * exceptions do not have chained root causes. That's why no special + * handling is necessary for setting the root cause in backwards compatible + * way. + */ +@SuppressWarnings("serial") +public class WstxValidationException + extends XMLValidationException +{ + protected WstxValidationException(XMLValidationProblem cause, String msg) + { + super(cause, msg); + } + + protected WstxValidationException(XMLValidationProblem cause, String msg, + Location loc) + { + super(cause, msg, loc); + } + + public static WstxValidationException create(XMLValidationProblem cause) + { + // Should always get a message + Location loc = cause.getLocation(); + if (loc == null) { + return new WstxValidationException(cause, cause.getMessage()); + } + return new WstxValidationException(cause, cause.getMessage(), loc); + } + + /* + ///////////////////////////////////////////////////////// + // Overridden methods from XMLStreamException + ///////////////////////////////////////////////////////// + */ + + /** + * Method is overridden for two main reasons: first, default method + * does not display public/system id information, even if it exists, and + * second, default implementation can not handle nested Location + * information. + */ + @Override + public String getMessage() + { + String locMsg = getLocationDesc(); + /* Better not use super's message if we do have location information, + * since parent's message contains (part of) Location + * info; something we can regenerate better... + */ + if (locMsg == null) { + return super.getMessage(); + } + String msg = getValidationProblem().getMessage(); + StringBuilder sb = new StringBuilder(msg.length() + locMsg.length() + 20); + sb.append(msg); + StringUtil.appendLF(sb); + sb.append(" at "); + sb.append(locMsg); + return sb.toString(); + } + + @Override + public String toString() { + return getClass().getName()+": "+getMessage(); + } + + /* + //////////////////////////////////////////////////////// + // Internal methods: + //////////////////////////////////////////////////////// + */ + + protected String getLocationDesc() + { + Location loc = getLocation(); + return (loc == null) ? null : loc.toString(); + } +} diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/io/AsciiReader.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/io/AsciiReader.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/io/AsciiReader.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/io/AsciiReader.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,134 @@ +/* Woodstox XML processor + * + * Copyright (c) 2004 Tatu Saloranta, tatu.saloranta@iki.fi + * + * Licensed under the License specified in file LICENSE, included with + * the source code. + * You may not use this file except in compliance with the License. + * + * 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 com.ctc.wstx.io; + +import java.io.*; + +import com.ctc.wstx.api.ReaderConfig; +import com.ctc.wstx.cfg.XmlConsts; + +/** + * Optimized Reader that reads ascii content from an input stream. + * In addition to doing (hopefully) optimal conversion, it can also take + * array of "pre-read" (leftover) bytes; this is necessary when preliminary + * stream/reader is trying to figure out XML encoding. + */ +public final class AsciiReader + extends BaseReader +{ + boolean mXml11 = false; + + /** + * Total read character count; used for error reporting purposes + * (note: byte count is the same, due to fixed one-byte-per char mapping) + */ + int mCharCount = 0; + + /* + //////////////////////////////////////// + // Life-cycle + //////////////////////////////////////// + */ + + public AsciiReader(ReaderConfig cfg, InputStream in, byte[] buf, int ptr, int len, + boolean recycleBuffer) + { + super(cfg, in, buf, ptr, len, recycleBuffer); + } + + @Override + public void setXmlCompliancy(int xmlVersion) { + mXml11 = (xmlVersion == XmlConsts.XML_V_11); + } + + /* + //////////////////////////////////////// + // Public API + //////////////////////////////////////// + */ + + @Override + public int read(char[] cbuf, int start, int len) throws IOException + { + // Let's first ensure there's enough room... + if (start < 0 || (start+len) > cbuf.length) { + reportBounds(cbuf, start, len); + } + // Already EOF? + if (mByteBuffer == null) { + return -1; + } + if (len < 1) { + return 0; + } + + // Need to load more data? + int avail = mByteBufferEnd - mBytePtr; + if (avail <= 0) { + mCharCount += mByteBufferEnd; + // Let's always try to read full buffers, actually... + int count = readBytes(); + if (count <= 0) { + if (count == 0) { + reportStrangeStream(); + } + /* Let's actually then free the buffer right away; shouldn't + * yet close the underlying stream though? + */ + freeBuffers(); // to help GC? + return -1; + } + avail = count; + } + + // K, have at least one byte == char, good enough: + + if (len > avail) { + len = avail; + } + int i = mBytePtr; + int last = i + len; + + for (; i < last; ) { + char c = (char) mByteBuffer[i++]; + if (c >= CHAR_DEL) { + if (c > CHAR_DEL) { + reportInvalidAscii(c); + } else { + if (mXml11) { + int pos = mCharCount + mBytePtr; + reportInvalidXml11(c, pos, pos); + } + } + } + cbuf[start++] = c; + } + + mBytePtr = last; + return len; + } + + /* + //////////////////////////////////////// + // Internal methods + //////////////////////////////////////// + */ + + private void reportInvalidAscii(char c) throws IOException { + throw new CharConversionException("Invalid ascii byte; value above 7-bit ascii range ("+((int) c)+"; at pos #"+(mCharCount + mBytePtr)+")"); + } +} + diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/io/BaseInputSource.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/io/BaseInputSource.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/io/BaseInputSource.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/io/BaseInputSource.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,184 @@ +package com.ctc.wstx.io; + +import java.io.IOException; +import java.net.URL; + +import javax.xml.stream.XMLStreamException; + +/** + * Abstract base class that implements shared functionality that all current + * {@link WstxInputSource} implementations Woodstox includes need. + */ +public abstract class BaseInputSource + extends WstxInputSource +{ + final String mPublicId; + + /** + * URL for/from systemId points to original source of input, if known; null if not + * known (source constructed with just a stream or reader). Used for + * resolving references from the input that's read from this source. + * Can be overridden by reader; done if P_BASE_URL is changed on + * stream reader for which this input source is the currently + * active input source. + */ + SystemId mSystemId; + + /** + * Input buffer this input source uses, if any. + */ + protected char[] mBuffer; + + /** + * Length of the buffer, if buffer used + */ + protected int mInputLast; + + /* + //////////////////////////////////////////////////////////////// + // Saved location information; active information is directly + // handled by Reader, and then saved to input source when switching + // to a nested input source. + //////////////////////////////////////////////////////////////// + */ + + /** + * Number of characters read from the current input source prior to + * the current buffer + */ + long mSavedInputProcessed = 0; + + int mSavedInputRow = 1; + int mSavedInputRowStart = 0; + + int mSavedInputPtr = 0; + + /* + //////////////////////////////////////////////////////////////// + // Some simple lazy-loading/reusing support... + //////////////////////////////////////////////////////////////// + */ + + transient WstxInputLocation mParentLocation = null; + + /* + //////////////////////////////////////////////////////////////// + // Life-cycle + //////////////////////////////////////////////////////////////// + */ + protected BaseInputSource(WstxInputSource parent, String fromEntity, + String publicId, SystemId systemId) + { + super(parent, fromEntity); + mSystemId = systemId; + mPublicId = publicId; + } + + @Override + public void overrideSource(URL src) + { + //19-May-2014, tatu: I assume this should also override observed systemId... + mSystemId = SystemId.construct(src); + } + + @Override + public abstract boolean fromInternalEntity(); + + @Override + public URL getSource() throws IOException { + return (mSystemId == null) ? null : mSystemId.asURL(); + } + + @Override + public String getPublicId() { + return mPublicId; + } + + @Override + public String getSystemId() { + return (mSystemId == null) ? null : mSystemId.toString(); + } + + @Override + protected abstract void doInitInputLocation(WstxInputData reader); + + @Override + public abstract int readInto(WstxInputData reader) + throws IOException, XMLStreamException; + + @Override + public abstract boolean readMore(WstxInputData reader, int minAmount) + throws IOException, XMLStreamException; + + @Override + public void saveContext(WstxInputData reader) + { + // First actual input data + mSavedInputPtr = reader.mInputPtr; + + // then location + mSavedInputProcessed = reader.mCurrInputProcessed; + mSavedInputRow = reader.mCurrInputRow; + mSavedInputRowStart = reader.mCurrInputRowStart; + } + + @Override + public void restoreContext(WstxInputData reader) + { + reader.mInputBuffer = mBuffer; + reader.mInputEnd = mInputLast; + reader.mInputPtr = mSavedInputPtr; + + // then location + reader.mCurrInputProcessed = mSavedInputProcessed; + reader.mCurrInputRow = mSavedInputRow; + reader.mCurrInputRowStart = mSavedInputRowStart; + } + + @Override + public abstract void close() throws IOException; + + /* + ////////////////////////////////////////////////////////// + // Methods for accessing location information + ////////////////////////////////////////////////////////// + */ + + /** + * This method only gets called by the 'child' input source (for example, + * contents of an expanded entity), to get the enclosing context location. + */ + @Override + protected final WstxInputLocation getLocation() + { + // Note: columns are 1-based, need to add 1. + return getLocation(mSavedInputProcessed + mSavedInputPtr - 1L, + mSavedInputRow, + mSavedInputPtr - mSavedInputRowStart + 1); + } + + @Override + public final WstxInputLocation getLocation(long total, int row, int col) + { + WstxInputLocation pl; + + if (mParent == null) { + pl = null; + } else { + /* 13-Apr-2005, TSa: We can actually reuse parent location, since + * it can not change during lifetime of this child context... + */ + pl = mParentLocation; + if (pl == null) { + mParentLocation = pl = mParent.getLocation(); + } + pl = mParent.getLocation(); + } + /* !!! 15-Apr-2005, TSa: This will cause overflow for total count, + * but since StAX 1.0 API doesn't have any way to deal with that, + * let's just let that be... + */ + return new WstxInputLocation(pl, getPublicId(), getSystemId(), + total, row, col); + } +} diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/io/BaseReader.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/io/BaseReader.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/io/BaseReader.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/io/BaseReader.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,227 @@ +package com.ctc.wstx.io; + +import java.io.*; + +import com.ctc.wstx.api.ReaderConfig; + +/** + * Simple basic class for optimized Readers Woodstox has; implements + * "cookie-cutter" methods that are used by all actual implementations. + */ +abstract class BaseReader + extends Reader +{ + protected final static char NULL_CHAR = (char) 0; + protected final static char NULL_BYTE = (byte) 0; + + /** + * In xml 1.1, NEL (0x85) behaves much the way \n does (can + * be follow \r as part of the linefeed + */ + protected final static char CONVERT_NEL_TO = '\n'; + + /** + * In xml 1.1, LSEP bit like \n, or \r. Need to choose one as the + * result. Let's use \n, for simplicity + */ + protected final static char CONVERT_LSEP_TO = '\n'; + + /** + * DEL character is both the last ascii char, and illegal in xml 1.1. + */ + final static char CHAR_DEL = (char) 127; + + protected final ReaderConfig mConfig; + + private InputStream mIn; + + protected byte[] mByteBuffer; + + /** + * Pointer to the next available byte (if any), iff less than + * mByteBufferEnd + */ + protected int mBytePtr; + + /** + * Pointed to the end marker, that is, position one after the last + * valid available byte. + */ + protected int mByteBufferEnd; + + /** + * Flag that indicates whether the read buffer is to be recycled + * when Reader is closed or not. + */ + private final boolean mRecycleBuffer; + + /* + //////////////////////////////////////// + // Life-cycle + //////////////////////////////////////// + */ + + protected BaseReader(ReaderConfig cfg, InputStream in, byte[] buf, int ptr, int len, + boolean recycleBuffer) + { + mConfig = cfg; + mIn = in; + mByteBuffer = buf; + mBytePtr = ptr; + mByteBufferEnd = len; + mRecycleBuffer = recycleBuffer; + } + + /* + //////////////////////////////////////// + // Configuration + //////////////////////////////////////// + */ + + /** + * Method that can be called to indicate the xml conformance used + * when reading content using this reader. Some of the character + * validity checks need to be done at reader level, and sometimes + * they depend on xml level (for example, xml 1.1 has new linefeeds + * and both more and less restricted characters). + */ + public abstract void setXmlCompliancy(int xmlVersion); + + /** + * Method that can be used to see if we can actually modify the + * underlying buffer. This is the case if we are managing the buffer, + * but not if it was just given to us. + */ + protected final boolean canModifyBuffer() + { + return mRecycleBuffer; + } + + /* + //////////////////////////////////////// + // Reader API + //////////////////////////////////////// + */ + + @Override + public void close() throws IOException + { + InputStream in = mIn; + + if (in != null) { + mIn = null; + freeBuffers(); + in.close(); + } + } + + protected char[] mTmpBuf = null; + + /** + * Although this method is implemented by the base class, AND it should + * never be called by Woodstox code, let's still implement it bit more + * efficiently just in case + */ + @Override + public int read() throws IOException + { + if (mTmpBuf == null) { + mTmpBuf = new char[1]; + } + if (read(mTmpBuf, 0, 1) < 1) { + return -1; + } + return mTmpBuf[0]; + } + + /* + //////////////////////////////////////// + // Internal/package methods: + //////////////////////////////////////// + */ + + protected final InputStream getStream() { return mIn; } + + /** + * Method for reading as many bytes from the underlying stream as possible + * (that fit in the buffer), to the beginning of the buffer. + */ + protected final int readBytes() + throws IOException + { + mBytePtr = 0; + mByteBufferEnd = 0; + if (mIn != null) { + int count = mIn.read(mByteBuffer, 0, mByteBuffer.length); + if (count > 0) { + mByteBufferEnd = count; + } + return count; + } + return -1; + } + + /** + * Method for reading as many bytes from the underlying stream as possible + * (that fit in the buffer considering offset), to the specified offset. + * + * @return Number of bytes read, if any; -1 to indicate none available + * (that is, end of input) + */ + protected final int readBytesAt(int offset) + throws IOException + { + // shouldn't modify mBytePtr, assumed to be 'offset' + if (mIn != null) { + int count = mIn.read(mByteBuffer, offset, mByteBuffer.length - offset); + if (count > 0) { + mByteBufferEnd += count; + } + return count; + } + return -1; + } + + /** + * This method should be called along with (or instead of) normal + * close. After calling this method, no further reads should be tried. + * Method will try to recycle read buffers (if any). + */ + public final void freeBuffers() + { + /* 11-Apr-2005, TSa: Ok, we can release the buffer now, to be + * recycled by the next stream reader instantiated by this + * thread (if any). + */ + if (mRecycleBuffer) { + byte[] buf = mByteBuffer; + if (buf != null) { + mByteBuffer = null; + if (mConfig != null) { + mConfig.freeFullBBuffer(buf); + } + } + } + } + + protected void reportBounds(char[] cbuf, int start, int len) + throws IOException + { + throw new ArrayIndexOutOfBoundsException("read(buf,"+start+","+len+"), cbuf["+cbuf.length+"]"); + } + + protected void reportStrangeStream() + throws IOException + { + throw new IOException("Strange I/O stream, returned 0 bytes on read"); + } + + protected void reportInvalidXml11(int value, int bytePos, int charPos) + throws IOException + { + throw new CharConversionException("Invalid character 0x" + +Integer.toHexString(value) + +", can only be included in xml 1.1 using character entities (at char #"+charPos+", byte #"+bytePos+")"); + } +} + diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/io/BranchingReaderSource.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/io/BranchingReaderSource.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/io/BranchingReaderSource.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/io/BranchingReaderSource.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,159 @@ +package com.ctc.wstx.io; + +import java.io.IOException; +import java.io.Reader; + +import javax.xml.stream.XMLStreamException; + +import com.ctc.wstx.api.ReaderConfig; +import com.ctc.wstx.util.TextBuffer; + +/** + * Specialized input source that can "branch" input it reads; essentially + * both giving out read data AND also writing it out to a Writer. + *

+ * Currently this Reader is only used as the main-level Reader, to allow for + * branching of internal DTD subset to a text buffer if necessary. + */ +public final class BranchingReaderSource + extends ReaderSource +{ + + // // // Branching information + + TextBuffer mBranchBuffer = null; + + int mBranchStartOffset = 0; + + boolean mConvertLFs = false; + + /** + * Flag that indicates that last char from previous buffer was + * '\r', and that following '\n' (if there is one) needs to be + * ignored. + */ + boolean mGotCR = false; + + public BranchingReaderSource(ReaderConfig cfg, String pubId, SystemId sysId, + Reader r, boolean realClose) + { + /* null -> no parent, + * null -> not from explicit entity (no id/name) + */ + super(cfg, null, null, pubId, sysId, r, realClose); + } + + @Override + public int readInto(WstxInputData reader) + throws IOException, XMLStreamException + { + // Need to flush out branched content? + if (mBranchBuffer != null) { + if (mInputLast > mBranchStartOffset) { + appendBranched(mBranchStartOffset, mInputLast); + } + mBranchStartOffset = 0; + } + return super.readInto(reader); + } + + @Override + public boolean readMore(WstxInputData reader, int minAmount) + throws IOException, XMLStreamException + { + // Existing data to output to branch? + if (mBranchBuffer != null) { + int ptr = reader.mInputPtr; + int currAmount = mInputLast - ptr; + if (currAmount > 0) { + if (ptr > mBranchStartOffset) { + appendBranched(mBranchStartOffset, ptr); + } + mBranchStartOffset = 0; + } + } + return super.readMore(reader, minAmount); + } + + /* + ////////////////////////////////////////////////// + // Branching methods; used mostly to make a copy + // of parsed internal subsets. + ////////////////////////////////////////////////// + */ + + public void startBranch(TextBuffer tb, int startOffset, + boolean convertLFs) + { + mBranchBuffer = tb; + mBranchStartOffset = startOffset; + mConvertLFs = convertLFs; + mGotCR = false; + } + + /** + * Currently this input source does not implement branching + */ + public void endBranch(int endOffset) + { + if (mBranchBuffer != null) { + if (endOffset > mBranchStartOffset) { + appendBranched(mBranchStartOffset, endOffset); + } + // Let's also make sure no branching is done from this point on: + mBranchBuffer = null; + } + } + + /* + ////////////////////////////////////////////////// + // Internal methods + ////////////////////////////////////////////////// + */ + + private void appendBranched(int startOffset, int pastEnd) { + // Main tricky thing here is just replacing of linefeeds... + if (mConvertLFs) { + char[] inBuf = mBuffer; + /* this will also unshare() and ensure there's room for at + * least one more char + */ + char[] outBuf = mBranchBuffer.getCurrentSegment(); + int outPtr = mBranchBuffer.getCurrentSegmentSize(); + + // Pending \n to skip? + if (mGotCR) { + if (inBuf[startOffset] == '\n') { + ++startOffset; + } + } + + while (startOffset < pastEnd) { + char c = inBuf[startOffset++]; + if (c == '\r') { + if (startOffset < pastEnd) { + if (inBuf[startOffset] == '\n') { + ++startOffset; + } + } else { + mGotCR = true; + } + c = '\n'; + } + + // Ok, let's add char to output: + outBuf[outPtr++] = c; + + // Need more room? + if (outPtr >= outBuf.length) { + outBuf = mBranchBuffer.finishCurrentSegment(); + outPtr = 0; + } + } + + mBranchBuffer.setCurrentLength(outPtr); + } else { + mBranchBuffer.append(mBuffer, startOffset, pastEnd-startOffset); + } + } +} diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/io/BufferRecycler.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/io/BufferRecycler.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/io/BufferRecycler.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/io/BufferRecycler.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,108 @@ +package com.ctc.wstx.io; + +/** + * This is a small utility class, whose main functionality is to allow + * simple reuse of raw byte/char buffers. It is usually used through + * ThreadLocal member of the owning class pointing to + * instance of this class through a SoftReference. The + * end result is a low-overhead GC-cleanable recycling: hopefully + * ideal for use by stream readers. + *

+ * Regarding implementation: the key design goal is simplicity; and to + * that end, different types of buffers are handled separately. While + * code may look inelegant as a result (wouldn't it be neat to just + * have generic char[]/byte[] buffer accessors?), benefit is that + * no data structures are needed, just simple references. As long + * as usage pattern is well known (which it is, for stream readers) + * this should be highly optimal and robust implementation. + */ +public final class BufferRecycler +{ + private char[] mSmallCBuffer = null; // temp buffers + private char[] mMediumCBuffer = null; // text collector + private char[] mFullCBuffer = null; // for actual parsing buffer + + private byte[] mFullBBuffer = null; + + public BufferRecycler() { } + + // // // Char buffers: + + // // Small buffers, for temporary parsing + + public char[] getSmallCBuffer(int minSize) + { + char[] result = null; + if (mSmallCBuffer != null && mSmallCBuffer.length >= minSize) { + result = mSmallCBuffer; + mSmallCBuffer = null; + } +//System.err.println("DEBUG: Alloc CSmall: "+result); + return result; + } + + public void returnSmallCBuffer(char[] buffer) + { +//System.err.println("DEBUG: Return CSmall ("+buffer.length+"): "+buffer); + mSmallCBuffer = buffer; + } + + // // Medium buffers, for text output collection + + public char[] getMediumCBuffer(int minSize) + { + char[] result = null; + if (mMediumCBuffer != null && mMediumCBuffer.length >= minSize) { + result = mMediumCBuffer; + mMediumCBuffer = null; + } +//System.err.println("DEBUG: Alloc CMed: "+result); + return result; + } + + public void returnMediumCBuffer(char[] buffer) + { + mMediumCBuffer = buffer; +//System.err.println("DEBUG: Return CMed ("+buffer.length+"): "+buffer); + } + + // // Full buffers, for parser buffering + + public char[] getFullCBuffer(int minSize) + { + char[] result = null; + if (mFullCBuffer != null && mFullCBuffer.length >= minSize) { + result = mFullCBuffer; + mFullCBuffer = null; + } +//System.err.println("DEBUG: Alloc CFull: "+result); + return result; + } + + public void returnFullCBuffer(char[] buffer) + { + mFullCBuffer = buffer; +//System.err.println("DEBUG: Return CFull ("+buffer.length+"): "+buffer); + } + + // // // Byte buffers: + + // // Full byte buffers, for byte->char conversion (Readers) + + public byte[] getFullBBuffer(int minSize) + { + byte[] result = null; + if (mFullBBuffer != null && mFullBBuffer.length >= minSize) { + result = mFullBBuffer; + mFullBBuffer = null; + } +//System.err.println("DEBUG: Alloc BFull: "+result); + return result; + } + + public void returnFullBBuffer(byte[] buffer) + { + mFullBBuffer = buffer; +//System.err.println("DEBUG: Return BFull ("+buffer.length+"): "+buffer); + } +} diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/io/CharArraySource.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/io/CharArraySource.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/io/CharArraySource.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/io/CharArraySource.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,112 @@ +package com.ctc.wstx.io; + +import javax.xml.stream.Location; + +/** + * Input source that reads input from a static char array, usually used + * when expanding internal entities. It can also be used if the input + * given is a raw character array. + */ +public final class CharArraySource + extends BaseInputSource +{ + int mOffset; + + // // // Plus, location offset info: + + final Location mContentStart; + + protected CharArraySource(WstxInputSource parent, String fromEntity, + char[] chars, int offset, int len, + Location loc, SystemId sysId) + { + super(parent, fromEntity, loc.getPublicId(), sysId); + //loc.getSystemId()); + mBuffer = chars; + mOffset = offset; + mInputLast = offset + len; + mContentStart = loc; + } + + /** + * This is a hard-coded assumption, but yes, for now this source is + * only created from internal entities. + */ + @Override + public boolean fromInternalEntity() { + return true; + } + + /** + * Unlike with reader source, we won't start from beginning of a file, + * but usually from somewhere in the middle... + */ + @Override + protected void doInitInputLocation(WstxInputData reader) + { + reader.mCurrInputProcessed = mContentStart.getCharacterOffset(); + reader.mCurrInputRow = mContentStart.getLineNumber(); + /* 13-Apr-2005, TSa: Since column offsets reported by Location + * objects are 1-based, but internally we use 0-based counts, + * need to offset this start by 1 to begin with. + */ + reader.mCurrInputRowStart = -mContentStart.getColumnNumber() + 1; + } + + @Override + public int readInto(WstxInputData reader) + { + /* Shouldn't really try to read after closing, but it may be easier + * for caller not to have to keep track of open/close state... + */ + if (mBuffer == null) { + return -1; + } + + /* In general, there are only 2 states; either this has been + * read or not. Offset is used as the marker; plus, in case + * somehow we get a dummy char source (length of 0), it'll + * also prevent any reading. + */ + int len = mInputLast - mOffset; + if (len < 1) { + return -1; + } + reader.mInputBuffer = mBuffer; + reader.mInputPtr = mOffset; + reader.mInputEnd = mInputLast; + // Also, need to note the fact we're done + mOffset = mInputLast; + return len; + } + + @Override + public boolean readMore(WstxInputData reader, int minAmount) + { + /* Only case where this may work is if we haven't yet been + * read from at all. And that should mean caller also has no + * existing input... + */ + if (reader.mInputPtr >= reader.mInputEnd) { + int len = mInputLast - mOffset; + if (len >= minAmount) { + return (readInto(reader) > 0); + } + } + return false; + } + + @Override + public void close() + { + /* Let's help GC a bit, in case there might be back references + * to this Object from somewhere... + */ + mBuffer = null; + } + + @Override + public void closeCompletely() { + close(); + } +} diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/io/CharsetNames.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/io/CharsetNames.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/io/CharsetNames.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/io/CharsetNames.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,294 @@ +package com.ctc.wstx.io; + +import java.io.OutputStreamWriter; +import java.io.Writer; + +import com.ctc.wstx.util.StringUtil; + +/** + * Simple utility class that normalizes given character input character + * set names into canonical (within Woodstox, anyways) names. + */ +public final class CharsetNames +{ + /* + ////////////////////////////////////////////////// + // Canonical names used internally + ////////////////////////////////////////////////// + */ + + // // // Unicode variants: + + public final static String CS_US_ASCII = "US-ASCII"; + public final static String CS_UTF8 = "UTF-8"; + + /** + * This constants is intentionally vague, so that some other information + * will be needed to determine the endianness. + */ + public final static String CS_UTF16 = "UTF-16"; + + public final static String CS_UTF16BE = "UTF-16BE"; + public final static String CS_UTF16LE = "UTF-16LE"; + public final static String CS_UTF32 = "UTF-32"; + public final static String CS_UTF32BE = "UTF-32BE"; + public final static String CS_UTF32LE = "UTF-32LE"; + + // // // 8-bit ISO encodings: + + public final static String CS_ISO_LATIN1 = "ISO-8859-1"; + + // // // Japanese non-unicode encodings: + + public final static String CS_SHIFT_JIS = "Shift_JIS"; + + // // // Other oddities: + + /* There are tons of EBCDIC varieties, with similar but + * non-identical names. As a result, we can not give or use + * just a single canonical name for general use. + * However, we can choose a single one to use for bootstrapping; + * that is, for parsing xml declaration to know the "real" + * EBCDIC variant. + */ + public final static String CS_EBCDIC_SUBSET = "IBM037"; + + /* + ////////////////////////////////////////////////// + // Utility methods + ////////////////////////////////////////////////// + */ + + public static String normalize(String csName) + { + if (csName == null || csName.length() < 3) { + return csName; + } + + /* Canonical charset names here are from IANA recommendation: + * http://www.iana.org/assignments/character-sets + * but comparison is done loosely (case-insensitive, ignoring + * spacing, underscore vs. hyphen etc) to try to make detection + * as extensive as possible. + */ + + /* But first bit of pre-filtering: it seems like 'cs' prefix + * is applicable to pretty much all actual encodings (as per + * IANA recommendations; csASCII, csUcs4 etc). So, let's just + * strip out the prefix if so + */ + boolean gotCsPrefix = false; + char c = csName.charAt(0); + if (c == 'c' || c == 'C'){ + char d = csName.charAt(1); + if (d == 's' || d == 'S') { + csName = csName.substring(2); + c = csName.charAt(0); + gotCsPrefix = true; + } + } + + switch (c) { + case 'a': + case 'A': + if (StringUtil.equalEncodings(csName, "ASCII")) { + return CS_US_ASCII; + } + break; + + case 'c': + case 'C': + /* Tons of variants: let's assume 'cpXXX' is an EBCDIC + * variant, and should read 'IBMXXX' + */ + if (StringUtil.encodingStartsWith(csName, "cp")) { + return "IBM" + StringUtil.trimEncoding(csName, true).substring(2); + } + // Hmmh. There are boatloads of these... but what to do with them? + if (StringUtil.encodingStartsWith(csName, "cs")) { + // Well, "csIBMxx" means EBCDIC of "IBMxx" + if (StringUtil.encodingStartsWith(csName, "csIBM")) { + // So let's just peel off "cs" prefix: + return StringUtil.trimEncoding(csName, true).substring(2); + } + // !!! TBI + } + break; + + case 'e': + case 'E': + if (csName.startsWith("EBCDIC-CP-") || + csName.startsWith("ebcdic-cp-")) { + // EBCDIC, but which variety? + // Let's trim out prefix to make comparison easier: + String type = StringUtil.trimEncoding(csName, true).substring(8); + // Note: these are suggested encodings of Xerces + if (type.equals("US") || type.equals("CA") + || type.equals("WT") || type.equals("NL")) { + return "IBM037"; + } + if (type.equals("DK") || type.equals("NO")) { // Denmark, Norway + return "IBM277"; + } + if (type.equals("FI") || type.equals("SE")) { // Finland, Sweden + return "IBM278"; + } + if (type.equals("ROECE") || type.equals("YU")) { + return "IBM870"; + } + if (type.equals("IT")) return "IBM280"; + if (type.equals("ES")) return "IBM284"; + if (type.equals("GB")) return "IBM285"; + if (type.equals("FR")) return "IBM297"; + if (type.equals("AR1")) return "IBM420"; + if (type.equals("AR2")) return "IBM918"; + if (type.equals("HE")) return "IBM424"; + if (type.equals("CH")) return "IBM500"; + if (type.equals("IS")) return "IBM871"; + + // Dunno... let's just default to 037? + return CS_EBCDIC_SUBSET; + } + break; + case 'i': + case 'I': + if (StringUtil.equalEncodings(csName, "ISO-8859-1") + || StringUtil.equalEncodings(csName, "ISO-Latin1")) { + return CS_ISO_LATIN1; + } + if (StringUtil.encodingStartsWith(csName, "ISO-10646")) { + /* Hmmh. There are boatloads of alternatives here, it + * seems (see http://www.iana.org/assignments/character-sets + * for details) + */ + int ix = csName.indexOf("10646"); + String suffix = csName.substring(ix+5); + if (StringUtil.equalEncodings(suffix, "UCS-Basic")) { + return CS_US_ASCII; + } + if (StringUtil.equalEncodings(suffix, "Unicode-Latin1")) { + return CS_ISO_LATIN1; + } + if (StringUtil.equalEncodings(suffix, "UCS-2")) { + return CS_UTF16; // endianness? + } + if (StringUtil.equalEncodings(suffix, "UCS-4")) { + return CS_UTF32; // endianness? + } + if (StringUtil.equalEncodings(suffix, "UTF-1")) { + // "Universal Transfer Format (1), this is the multibyte encoding, that subsets ASCII-7"??? + return CS_US_ASCII; + } + if (StringUtil.equalEncodings(suffix, "J-1")) { + // Name: ISO-10646-J-1, Source: ISO 10646 Japanese, see RFC 1815. + // ... so what does that really mean? let's consider it ascii + return CS_US_ASCII; + } + if (StringUtil.equalEncodings(suffix, "US-ASCII")) { + return CS_US_ASCII; + } + } else if (StringUtil.encodingStartsWith(csName, "IBM")) { + // EBCDIC of some kind... what (if anything) to do? + // ... for now, return as is + return csName; + } + break; + case 'j': + case 'J': + if (StringUtil.equalEncodings(csName, "JIS_Encoding")) { + return CS_SHIFT_JIS; + } + break; + case 's': + case 'S': + if (StringUtil.equalEncodings(csName, "Shift_JIS")) { + return CS_SHIFT_JIS; + } + break; + case 'u': + case 'U': + if (csName.length() < 2) { // sanity check + break; + } + switch (csName.charAt(1)) { + case 'c': + case 'C': + if (StringUtil.equalEncodings(csName, "UCS-2")) { + return CS_UTF16; + } + if (StringUtil.equalEncodings(csName, "UCS-4")) { + return CS_UTF32; + } + break; + case 'n': // csUnicodeXxx, + case 'N': + if (gotCsPrefix) { + if (StringUtil.equalEncodings(csName, "Unicode")) { + return CS_UTF16; // need BOM + } + if (StringUtil.equalEncodings(csName, "UnicodeAscii")) { + return CS_ISO_LATIN1; + } + if (StringUtil.equalEncodings(csName, "UnicodeAscii")) { + return CS_US_ASCII; + } + } + break; + case 's': + case 'S': + if (StringUtil.equalEncodings(csName, "US-ASCII")) { + return CS_US_ASCII; + } + break; + case 't': + case 'T': + if (StringUtil.equalEncodings(csName, "UTF-8")) { + return CS_UTF8; + } + if (StringUtil.equalEncodings(csName, "UTF-16BE")) { + return CS_UTF16BE; + } + if (StringUtil.equalEncodings(csName, "UTF-16LE")) { + return CS_UTF16LE; + } + if (StringUtil.equalEncodings(csName, "UTF-16")) { + return CS_UTF16; + } + if (StringUtil.equalEncodings(csName, "UTF-32BE")) { + return CS_UTF32BE; + } + if (StringUtil.equalEncodings(csName, "UTF-32LE")) { + return CS_UTF32LE; + } + if (StringUtil.equalEncodings(csName, "UTF-32")) { + return CS_UTF32; + } + if (StringUtil.equalEncodings(csName, "UTF")) { + // 21-Jan-2006, TSa: ??? What is this to do... ? + return CS_UTF16; + } + } + break; + } + + return csName; + } + + /** + * Because of legacy encodings used by earlier JDK versions, we + * need to be careful when accessing encoding names via JDK + * classes. + */ + public static String findEncodingFor(Writer w) + { + if (w instanceof OutputStreamWriter) { + String enc = ((OutputStreamWriter) w).getEncoding(); + /* [WSTX-146]: It is important that we normalize this, since + * older JDKs return legacy encoding names ("UTF8" instead of + * canonical "UTF-8") + */ + return normalize(enc); + } + return null; + } +} diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/io/CompletelyCloseable.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/io/CompletelyCloseable.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/io/CompletelyCloseable.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/io/CompletelyCloseable.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,8 @@ +package com.ctc.wstx.io; + +import java.io.IOException; + +public interface CompletelyCloseable +{ + public void closeCompletely() throws IOException; +} diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/io/DefaultInputResolver.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/io/DefaultInputResolver.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/io/DefaultInputResolver.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/io/DefaultInputResolver.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,323 @@ +package com.ctc.wstx.io; + +import java.io.*; +import java.net.URL; + +import javax.xml.stream.XMLResolver; +import javax.xml.stream.XMLStreamException; +import javax.xml.transform.Source; +import javax.xml.transform.stream.StreamSource; + +import com.ctc.wstx.api.ReaderConfig; +import com.ctc.wstx.cfg.XmlConsts; +import com.ctc.wstx.util.URLUtil; + +/** + * Static utility class that implements the entity (external DTD subset, + * external parsed entities) resolution logics. + */ +public final class DefaultInputResolver +{ + /* + //////////////////////////// + // Life-cycle + //////////////////////////// + */ + + private DefaultInputResolver() { } + + /* + //////////////////////////// + // Public API + //////////////////////////// + */ + + /** + * Basic external resource resolver implementation; usable both with + * DTD and entity resolution. + * + * @param parent Input source that contains reference to be expanded. + * @param pathCtxt Reference context to use for resolving path, if + * known. If null, reference context of the parent will + * be used; and if that is null (which is possible), the + * current working directory will be assumed. + * @param entityName Name/id of the entity being expanded, if this is an + * entity expansion; null otherwise (for example, when resolving external + * subset). + * @param publicId Public identifier of the resource, if known; null/empty + * otherwise. Default implementation just ignores the identifier. + * @param systemId System identifier of the resource. Although interface + * allows null/empty, default implementation considers this an error. + * @param xmlVersion Xml version as declared by the main parsed + * document. Currently only relevant for checking that XML 1.0 document + * does not include XML 1.1 external parsed entities. + * If XML_V_UNKNOWN, no checks will be done. + * @param customResolver Custom resolver to use first for resolution, + * if any (may be null). + * @param cfg Reader configuration object used by the parser that is + * resolving the entity + * + * @return Input source, if entity could be resolved; null if it could + * not be resolved. In latter case processor may use its own default + * resolution mechanism. + */ + public static WstxInputSource resolveEntity + (WstxInputSource parent, URL pathCtxt, String entityName, + String publicId, String systemId, + XMLResolver customResolver, ReaderConfig cfg, int xmlVersion) + throws IOException, XMLStreamException + { + if (pathCtxt == null) { + pathCtxt = parent.getSource(); + if (pathCtxt == null) { + pathCtxt = URLUtil.urlFromCurrentDir(); + } + } + + // Do we have a custom resolver that may be able to resolve it? + if (customResolver != null) { + Object source = customResolver.resolveEntity(publicId, systemId, pathCtxt.toExternalForm(), entityName); + if (source != null) { + return sourceFrom(parent, cfg, entityName, xmlVersion, source); + } + } + + // Have to have a system id, then... + if (systemId == null) { + throw new XMLStreamException("Can not resolve " + +((entityName == null) ? "[External DTD subset]" : ("entity '"+entityName+"'"))+" without a system id (public id '" + +publicId+"')"); + } + URL url = URLUtil.urlFromSystemId(systemId, pathCtxt); + return sourceFromURL(parent, cfg, entityName, xmlVersion, url, publicId); + } + + /** + * A very simple utility expansion method used generally when the + * only way to resolve an entity is via passed resolver; and where + * failing to resolve it is not fatal. + */ + public static WstxInputSource resolveEntityUsing + (WstxInputSource refCtxt, String entityName, + String publicId, String systemId, + XMLResolver resolver, ReaderConfig cfg, int xmlVersion) + throws IOException, XMLStreamException + { + URL ctxt = (refCtxt == null) ? null : refCtxt.getSource(); + if (ctxt == null) { + ctxt = URLUtil.urlFromCurrentDir(); + } + Object source = resolver.resolveEntity(publicId, systemId, ctxt.toExternalForm(), entityName); + return (source == null) ? null : sourceFrom(refCtxt, cfg, entityName, xmlVersion, source); + } + + /** + * Factory method that accepts various types of Objects, and tries to + * create a {@link WstxInputSource} from it. Currently it's only called + * to locate external DTD subsets, when overriding default DOCTYPE + * declarations; not for entity expansion or for locating the main + * document entity. + * + * @param parent Input source context active when resolving a new + * "sub-source"; usually the main document source. + * @param refName Name of the entity to be expanded, if any; may be + * null (and currently always is) + * @param o Object that should provide the new input source; non-type safe + */ + protected static WstxInputSource sourceFrom(WstxInputSource parent, + ReaderConfig cfg, String refName, + int xmlVersion, Object o) + throws IllegalArgumentException, IOException, XMLStreamException + { + if (o instanceof Source) { + if (o instanceof StreamSource) { + return sourceFromSS(parent, cfg, refName, xmlVersion, (StreamSource) o); + } + /* !!! 05-Feb-2006, TSa: Could check if SAXSource actually has + * stream/reader available... ? + */ + throw new IllegalArgumentException("Can not use other Source objects than StreamSource: got "+o.getClass()); + } + if (o instanceof URL) { + return sourceFromURL(parent, cfg, refName, xmlVersion, (URL) o, null); + } + if (o instanceof InputStream) { + return sourceFromIS(parent, cfg, refName, xmlVersion, (InputStream) o, null, null); + } + if (o instanceof Reader) { + return sourceFromR(parent, cfg, refName, xmlVersion, (Reader) o, null, null); + } + if (o instanceof String) { + return sourceFromString(parent, cfg, refName, xmlVersion, (String) o); + } + if (o instanceof File) { + URL u = URLUtil.toURL((File) o); + return sourceFromURL(parent, cfg, refName, xmlVersion, u, null); + } + + throw new IllegalArgumentException("Unrecognized input argument type for sourceFrom(): "+o.getClass()); + } + + public static Reader constructOptimizedReader(ReaderConfig cfg, InputStream in, boolean isXml11, String encoding) + throws XMLStreamException + { + /* 03-Jul-2005, TSa: Since Woodstox' implementations of specialized + * readers are faster than default JDK ones (at least for 1.4, UTF-8 + * reader is especially fast...), let's use them if possible + */ + /* 17-Feb-2006, TSa: These should actually go via InputBootstrapper, + * since BOM may need to be skipped; xml 1.0 vs. 1.1 should be + * checked, and so on. Given encoding could be just verified + * against suggested one. + */ + int inputBufLen = cfg.getInputBufferLength(); + String normEnc = CharsetNames.normalize(encoding); + BaseReader r; + + // All of these use real InputStream, and use recyclable buffer + boolean recycleBuffer = true; + if (normEnc == CharsetNames.CS_UTF8) { + r = new UTF8Reader(cfg, in, cfg.allocFullBBuffer(inputBufLen), 0, 0, recycleBuffer); + } else if (normEnc == CharsetNames.CS_ISO_LATIN1) { + r = new ISOLatinReader(cfg, in, cfg.allocFullBBuffer(inputBufLen), 0, 0, recycleBuffer); + } else if (normEnc == CharsetNames.CS_US_ASCII) { + r = new AsciiReader(cfg, in, cfg.allocFullBBuffer(inputBufLen), 0, 0, recycleBuffer); + } else if (normEnc.startsWith(CharsetNames.CS_UTF32)) { + boolean isBE = (normEnc == CharsetNames.CS_UTF32BE); + r = new UTF32Reader(cfg, in, cfg.allocFullBBuffer(inputBufLen), 0, 0, recycleBuffer, isBE); + } else { + try { + return new InputStreamReader(in, encoding); + } catch (UnsupportedEncodingException ex) { + throw new XMLStreamException("[unsupported encoding]: "+ex); + } + } + + if (isXml11) { // only need to set if we are xml 1.1 compliant (1.0 is the default) + r.setXmlCompliancy(XmlConsts.XML_V_11); + } + + return r; + } + + /* + //////////////////////////// + // Internal methods + //////////////////////////// + */ + + @SuppressWarnings("resource") + private static WstxInputSource sourceFromSS(WstxInputSource parent, ReaderConfig cfg, + String refName, int xmlVersion, StreamSource ssrc) + throws IOException, XMLStreamException + { + InputBootstrapper bs; + Reader r = ssrc.getReader(); + String pubId = ssrc.getPublicId(); + String sysId0 = ssrc.getSystemId(); + URL ctxt = (parent == null) ? null : parent.getSource(); + URL url = (sysId0 == null || sysId0.length() == 0) ? null + : URLUtil.urlFromSystemId(sysId0, ctxt); + + final SystemId systemId = SystemId.construct(sysId0, (url == null) ? ctxt : url); + + if (r == null) { + InputStream in = ssrc.getInputStream(); + if (in == null) { // Need to try just resolving the system id then + if (url == null) { + throw new IllegalArgumentException("Can not create Stax reader for a StreamSource -- neither reader, input stream nor system id was set."); + } + in = URLUtil.inputStreamFromURL(url); + } + bs = StreamBootstrapper.getInstance(pubId, systemId, in); + } else { + bs = ReaderBootstrapper.getInstance(pubId, systemId, r, null); + } + + Reader r2 = bs.bootstrapInput(cfg, false, xmlVersion); + return InputSourceFactory.constructEntitySource + (cfg, parent, refName, bs, pubId, systemId, xmlVersion, r2); + } + + @SuppressWarnings("resource") + private static WstxInputSource sourceFromURL(WstxInputSource parent, ReaderConfig cfg, + String refName, int xmlVersion, + URL url, + String pubId) + throws IOException, XMLStreamException + { + /* And then create the input source. Note that by default URL's + * own input stream creation creates buffered reader -- for us + * that's useless and wasteful (adds one unnecessary level of + * caching, halving the speed due to copy operations needed), so + * let's avoid it. + */ + InputStream in = URLUtil.inputStreamFromURL(url); + SystemId sysId = SystemId.construct(url); + StreamBootstrapper bs = StreamBootstrapper.getInstance(pubId, sysId, in); + Reader r = bs.bootstrapInput(cfg, false, xmlVersion); + return InputSourceFactory.constructEntitySource + (cfg, parent, refName, bs, pubId, sysId, xmlVersion, r); + } + + /** + * We have multiple ways to look at what would it mean to get a String + * as the resolved result. The most straight-forward is to consider + * it literal replacement (with possible embedded entities), so let's + * use that (alternative would be to consider it to be a reference + * like URL -- those need to be returned as appropriate objects + * instead). + *

+ * Note: public to give access for unit tests that need it... + */ + public static WstxInputSource sourceFromString(WstxInputSource parent, ReaderConfig cfg, + String refName, int xmlVersion, + String refContent) + throws IOException, XMLStreamException + { + /* Last null -> no app-provided encoding (doesn't matter for non- + * main-level handling) + */ + return sourceFromR(parent, cfg, refName, xmlVersion, + new StringReader(refContent), null, refName); + } + + @SuppressWarnings("resource") + private static WstxInputSource sourceFromIS(WstxInputSource parent, + ReaderConfig cfg, String refName, int xmlVersion, + InputStream is, String pubId, String sysId) + throws IOException, XMLStreamException + { + StreamBootstrapper bs = StreamBootstrapper.getInstance(pubId, SystemId.construct(sysId), is); + Reader r = bs.bootstrapInput(cfg, false, xmlVersion); + URL ctxt = parent.getSource(); + + // If we got a real sys id, we do know the source... + if (sysId != null && sysId.length() > 0) { + ctxt = URLUtil.urlFromSystemId(sysId, ctxt); + } + return InputSourceFactory.constructEntitySource + (cfg, parent, refName, bs, pubId, SystemId.construct(sysId, ctxt), + xmlVersion, r); + } + + @SuppressWarnings("resource") + private static WstxInputSource sourceFromR(WstxInputSource parent, ReaderConfig cfg, + String refName, int xmlVersion, + Reader r, String pubId, String sysId) + throws IOException, XMLStreamException + { + /* Last null -> no app-provided encoding (doesn't matter for non- + * main-level handling) + */ + ReaderBootstrapper rbs = ReaderBootstrapper.getInstance(pubId, SystemId.construct(sysId), r, null); + // null -> no xml reporter... should have one? + Reader r2 = rbs.bootstrapInput(cfg, false, xmlVersion); + URL ctxt = (parent == null) ? null : parent.getSource(); + if (sysId != null && sysId.length() > 0) { + ctxt = URLUtil.urlFromSystemId(sysId, ctxt); + } + return InputSourceFactory.constructEntitySource + (cfg, parent, refName, rbs, pubId, SystemId.construct(sysId, ctxt), xmlVersion, r2); + } +} diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/io/EBCDICCodec.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/io/EBCDICCodec.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/io/EBCDICCodec.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/io/EBCDICCodec.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,322 @@ +/* Woodstox XML processor + * + * Copyright (c) 2004 Tatu Saloranta, tatu.saloranta@iki.fi + * + * Licensed under the License specified in file LICENSE, included with + * the source code. + * You may not use this file except in compliance with the License. + * + * 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 com.ctc.wstx.io; + +/** + * This is a container class for EBCDIC code page(s) that we need + * to properly bootstrap EBCDIC encoded xml documents. + */ +public final class EBCDICCodec +{ + final static int[] sCodePage037; + static { + /* First, let's fill these in as per: + * + * http://www.unicode.org/Public/MAPPINGS/VENDORS/MICSFT/EBCDIC/CP037.TXT + */ + int[] ch = new int[256]; + ch[0] = 0x0000; + ch[0x01] = 0x0001; + ch[0x02] = 0x0002; + ch[0x03] = 0x0003; + ch[0x04] = 0x009C; + ch[0x05] = 0x0009; + ch[0x06] = 0x0086; + ch[0x07] = 0x007F; + ch[0x08] = 0x0097; + ch[0x09] = 0x008D; + ch[0x0A] = 0x008E; + ch[0x0B] = 0x000B; + ch[0x0C] = 0x000C; + ch[0x0D] = 0x000D; + ch[0x0E] = 0x000E; + ch[0x0F] = 0x000F; + ch[0x10] = 0x0010; + ch[0x11] = 0x0011; + ch[0x12] = 0x0012; + ch[0x13] = 0x0013; + ch[0x14] = 0x009D; + ch[0x15] = 0x0085; + ch[0x16] = 0x0008; + ch[0x17] = 0x0087; + ch[0x18] = 0x0018; + ch[0x19] = 0x0019; + ch[0x1A] = 0x0092; + ch[0x1B] = 0x008F; + ch[0x1C] = 0x001C; + ch[0x1D] = 0x001D; + ch[0x1E] = 0x001E; + ch[0x1F] = 0x001F; + ch[0x20] = 0x0080; + ch[0x21] = 0x0081; + ch[0x22] = 0x0082; + ch[0x23] = 0x0083; + ch[0x24] = 0x0084; + ch[0x25] = 0x000A; + ch[0x26] = 0x0017; + ch[0x27] = 0x001B; + ch[0x28] = 0x0088; + ch[0x29] = 0x0089; + ch[0x2A] = 0x008A; + ch[0x2B] = 0x008B; + ch[0x2C] = 0x008C; + ch[0x2D] = 0x0005; + ch[0x2E] = 0x0006; + ch[0x2F] = 0x0007; + ch[0x30] = 0x0090; + ch[0x31] = 0x0091; + ch[0x32] = 0x0016; + ch[0x33] = 0x0093; + ch[0x34] = 0x0094; + ch[0x35] = 0x0095; + ch[0x36] = 0x0096; + ch[0x37] = 0x0004; + ch[0x38] = 0x0098; + ch[0x39] = 0x0099; + ch[0x3A] = 0x009A; + ch[0x3B] = 0x009B; + ch[0x3C] = 0x0014; + ch[0x3D] = 0x0015; + ch[0x3E] = 0x009E; + ch[0x3F] = 0x001A; + ch[0x40] = 0x0020; + ch[0x41] = 0x00A0; + ch[0x42] = 0x00E2; + ch[0x43] = 0x00E4; + ch[0x44] = 0x00E0; + ch[0x45] = 0x00E1; + ch[0x46] = 0x00E3; + ch[0x47] = 0x00E5; + ch[0x48] = 0x00E7; + ch[0x49] = 0x00F1; + ch[0x4A] = 0x00A2; + ch[0x4B] = 0x002E; + ch[0x4C] = 0x003C; + ch[0x4D] = 0x0028; + ch[0x4E] = 0x002B; + ch[0x4F] = 0x007C; + ch[0x50] = 0x0026; + ch[0x51] = 0x00E9; + ch[0x52] = 0x00EA; + ch[0x53] = 0x00EB; + ch[0x54] = 0x00E8; + ch[0x55] = 0x00ED; + ch[0x56] = 0x00EE; + ch[0x57] = 0x00EF; + ch[0x58] = 0x00EC; + ch[0x59] = 0x00DF; + ch[0x5A] = 0x0021; + ch[0x5B] = 0x0024; + ch[0x5C] = 0x002A; + ch[0x5D] = 0x0029; + ch[0x5E] = 0x003B; + ch[0x5F] = 0x00AC; + ch[0x60] = 0x002D; + ch[0x61] = 0x002F; + ch[0x62] = 0x00C2; + ch[0x63] = 0x00C4; + ch[0x64] = 0x00C0; + ch[0x65] = 0x00C1; + ch[0x66] = 0x00C3; + ch[0x67] = 0x00C5; + ch[0x68] = 0x00C7; + ch[0x69] = 0x00D1; + ch[0x6A] = 0x00A6; + ch[0x6B] = 0x002C; + ch[0x6C] = 0x0025; + ch[0x6D] = 0x005F; + ch[0x6E] = 0x003E; + ch[0x6F] = 0x003F; + ch[0x70] = 0x00F8; + ch[0x71] = 0x00C9; + ch[0x72] = 0x00CA; + ch[0x73] = 0x00CB; + ch[0x74] = 0x00C8; + ch[0x75] = 0x00CD; + ch[0x76] = 0x00CE; + ch[0x77] = 0x00CF; + ch[0x78] = 0x00CC; + ch[0x79] = 0x0060; + ch[0x7A] = 0x003A; + ch[0x7B] = 0x0023; + ch[0x7C] = 0x0040; + ch[0x7D] = 0x0027; + ch[0x7E] = 0x003D; + ch[0x7F] = 0x0022; + + ch[0x80] = 0x00D8; + ch[0x81] = 0x0061; + ch[0x82] = 0x0062; + ch[0x83] = 0x0063; + ch[0x84] = 0x0064; + ch[0x85] = 0x0065; + ch[0x86] = 0x0066; + ch[0x87] = 0x0067; + ch[0x88] = 0x0068; + ch[0x89] = 0x0069; + ch[0x8A] = 0x00AB; + ch[0x8B] = 0x00BB; + ch[0x8C] = 0x00F0; + ch[0x8D] = 0x00FD; + ch[0x8E] = 0x00FE; + ch[0x8F] = 0x00B1; + ch[0x90] = 0x00B0; + ch[0x91] = 0x006A; + ch[0x92] = 0x006B; + ch[0x93] = 0x006C; + ch[0x94] = 0x006D; + ch[0x95] = 0x006E; + ch[0x96] = 0x006F; + ch[0x97] = 0x0070; + ch[0x98] = 0x0071; + ch[0x99] = 0x0072; + ch[0x9A] = 0x00AA; + ch[0x9B] = 0x00BA; + ch[0x9C] = 0x00E6; + ch[0x9D] = 0x00B8; + ch[0x9E] = 0x00C6; + ch[0x9F] = 0x00A4; + ch[0xA0] = 0x00B5; + ch[0xA1] = 0x007E; + ch[0xA2] = 0x0073; + ch[0xA3] = 0x0074; + ch[0xA4] = 0x0075; + ch[0xA5] = 0x0076; + ch[0xA6] = 0x0077; + ch[0xA7] = 0x0078; + ch[0xA8] = 0x0079; + ch[0xA9] = 0x007A; + ch[0xAA] = 0x00A1; + ch[0xAB] = 0x00BF; + ch[0xAC] = 0x00D0; + ch[0xAD] = 0x00DD; + ch[0xAE] = 0x00DE; + ch[0xAF] = 0x00AE; + ch[0xB0] = 0x005E; + ch[0xB1] = 0x00A3; + ch[0xB2] = 0x00A5; + ch[0xB3] = 0x00B7; + ch[0xB4] = 0x00A9; + ch[0xB5] = 0x00A7; + ch[0xB6] = 0x00B6; + ch[0xB7] = 0x00BC; + ch[0xB8] = 0x00BD; + ch[0xB9] = 0x00BE; + ch[0xBA] = 0x005B; + ch[0xBB] = 0x005D; + ch[0xBC] = 0x00AF; + ch[0xBD] = 0x00A8; + ch[0xBE] = 0x00B4; + ch[0xBF] = 0x00D7; + ch[0xC0] = 0x007B; + ch[0xC1] = 0x0041; + ch[0xC2] = 0x0042; + ch[0xC3] = 0x0043; + ch[0xC4] = 0x0044; + ch[0xC5] = 0x0045; + ch[0xC6] = 0x0046; + ch[0xC7] = 0x0047; + ch[0xC8] = 0x0048; + ch[0xC9] = 0x0049; + ch[0xCA] = 0x00AD; + ch[0xCB] = 0x00F4; + ch[0xCC] = 0x00F6; + ch[0xCD] = 0x00F2; + ch[0xCE] = 0x00F3; + ch[0xCF] = 0x00F5; + ch[0xD0] = 0x007D; + ch[0xD1] = 0x004A; + ch[0xD2] = 0x004B; + ch[0xD3] = 0x004C; + ch[0xD4] = 0x004D; + ch[0xD5] = 0x004E; + ch[0xD6] = 0x004F; + ch[0xD7] = 0x0050; + ch[0xD8] = 0x0051; + ch[0xD9] = 0x0052; + ch[0xDA] = 0x00B9; + ch[0xDB] = 0x00FB; + ch[0xDC] = 0x00FC; + ch[0xDD] = 0x00F9; + ch[0xDE] = 0x00FA; + ch[0xDF] = 0x00FF; + ch[0xE0] = 0x005C; + ch[0xE1] = 0x00F7; + ch[0xE2] = 0x0053; + ch[0xE3] = 0x0054; + ch[0xE4] = 0x0055; + ch[0xE5] = 0x0056; + ch[0xE6] = 0x0057; + ch[0xE7] = 0x0058; + ch[0xE8] = 0x0059; + ch[0xE9] = 0x005A; + ch[0xEA] = 0x00B2; + ch[0xEB] = 0x00D4; + ch[0xEC] = 0x00D6; + ch[0xED] = 0x00D2; + ch[0xEE] = 0x00D3; + ch[0xEF] = 0x00D5; + ch[0xF0] = 0x0030; + ch[0xF1] = 0x0031; + ch[0xF2] = 0x0032; + ch[0xF3] = 0x0033; + ch[0xF4] = 0x0034; + ch[0xF5] = 0x0035; + ch[0xF6] = 0x0036; + ch[0xF7] = 0x0037; + ch[0xF8] = 0x0038; + ch[0xF9] = 0x0039; + ch[0xFA] = 0x00B3; + ch[0xFB] = 0x00DB; + ch[0xFC] = 0x00DC; + ch[0xFD] = 0x00D9; + ch[0xFE] = 0x00DA; + ch[0xFF] = 0x009F; + + /* And then massage it so we can catch problems with control + * chars same way as we'd do with, say, Latin1 input. + */ + for (int i = 0, len = ch.length; i < len; ++i) { + int c = ch[i]; + if (c >= 0x7F && c <= 0x9F) { + /* 21-Sep-2007, TSa: Hmmh. In a way, it should be dealt + * as per xml rules, and not allowed in xml declaration + * before encoding declaration. But that won't work well + * with real docs. Converting it earlier works better... + * so for now that seems the way it needs to be done. ;-/ + */ + if (c == 0x85) { + ch[i] = BaseReader.CONVERT_NEL_TO; + } else { + ch[i] = -c; + } + } + } + + sCodePage037 = ch; + } + + private EBCDICCodec() { } + + /** + * @return Code table for EBCDIC code page 037 (US, Canada etc) + */ + public static int[] getCp037Mapping() + { + return sCodePage037; + } +} + diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/io/InputBootstrapper.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/io/InputBootstrapper.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/io/InputBootstrapper.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/io/InputBootstrapper.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,530 @@ +package com.ctc.wstx.io; + +import java.io.*; + +import javax.xml.stream.Location; +import javax.xml.stream.XMLStreamException; + +import com.ctc.wstx.api.ReaderConfig; +import com.ctc.wstx.cfg.ErrorConsts; +import com.ctc.wstx.cfg.XmlConsts; +import com.ctc.wstx.exc.*; + +/** + * Abstract base class that defines common API used with both stream and + * reader-based input sources. Class is responsible for opening the physical + * input source, figure out encoding (if necessary; only for streams), and + * then handle (optional) XML declaration. + */ +public abstract class InputBootstrapper +{ + /* + //////////////////////////////////////////////////////////// + // Shared string consts + //////////////////////////////////////////////////////////// + */ + + protected final static String ERR_XMLDECL_KW_VERSION = "; expected keyword '"+XmlConsts.XML_DECL_KW_VERSION+"'"; + protected final static String ERR_XMLDECL_KW_ENCODING = "; expected keyword '"+XmlConsts.XML_DECL_KW_ENCODING+"'"; + protected final static String ERR_XMLDECL_KW_STANDALONE = "; expected keyword '"+XmlConsts.XML_DECL_KW_STANDALONE+"'"; + + protected final static String ERR_XMLDECL_END_MARKER = "; expected \"?>\" end marker"; + + protected final static String ERR_XMLDECL_EXP_SPACE = "; expected a white space"; + protected final static String ERR_XMLDECL_EXP_EQ = "; expected '=' after "; + protected final static String ERR_XMLDECL_EXP_ATTRVAL = "; expected a quote character enclosing value for "; + + /* + //////////////////////////////////////////////////////////// + // Other consts + //////////////////////////////////////////////////////////// + */ + + public final static char CHAR_NULL = (char) 0; + public final static char CHAR_SPACE = (char) 0x0020; + + public final static char CHAR_NEL = (char) 0x0085; + + public final static byte CHAR_CR = '\r'; + public final static byte CHAR_LF = '\n'; + + public final static byte BYTE_NULL = (byte) 0; + + public final static byte BYTE_CR = (byte) '\r'; + public final static byte BYTE_LF = (byte) '\n'; + + /* + //////////////////////////////////////////////////////////// + // Input source info + //////////////////////////////////////////////////////////// + */ + + protected final String mPublicId; + + protected final SystemId mSystemId; + + /* + //////////////////////////////////////////////////////////// + // Input location data (similar to one in WstxInputData) + //////////////////////////////////////////////////////////// + */ + + /** + * Current number of characters that were processed in previous blocks, + * before contents of current input buffer. + */ + protected int mInputProcessed = 0; + + /** + * Current row location of current point in input buffer, starting + * from 1 + */ + protected int mInputRow = 1; + + /** + * Current index of the first character of the current row in input + * buffer. Needed to calculate column position, if necessary; benefit + * of not having column itself is that this only has to be updated + * once per line. + */ + protected int mInputRowStart = 0; + + /* + //////////////////////////////////////// + // Info from XML declaration + //////////////////////////////////////// + */ + + //boolean mHadDeclaration = false; + + /** + * XML declaration from the input (1.0, 1.1 or 'unknown') + */ + int mDeclaredXmlVersion = XmlConsts.XML_V_UNKNOWN; + + /** + * Value of encoding pseudo-attribute from xml declaration, if + * one was found; null otherwise. + */ + String mFoundEncoding; + + String mStandalone; + + /** + * Flag that indicates whether input read from this input source + * needs to be xml 1.1 compliant or not; if not, xml 1.0 is assumed. + * State of this flag depends on parent context (if one existed), or if + * not, on xml declaration of this input source. + */ + boolean mXml11Handling = false; + + /* + //////////////////////////////////////// + // Temporary data + //////////////////////////////////////// + */ + + /** + * Need a short buffer to read in values of pseudo-attributes (version, + * encoding, standalone). Don't really need tons of space; just enough + * for the longest anticipated encoding id... and maybe few chars just + * in case (for additional white space that we ignore) + */ + final char[] mKeyword = new char[60]; + + /* + //////////////////////////////////////// + // Life-cycle + //////////////////////////////////////// + */ + + protected InputBootstrapper(String pubId, SystemId sysId) + { + mPublicId = pubId; + mSystemId = sysId; + } + + protected void initFrom(InputBootstrapper src) + { + mInputProcessed = src.mInputProcessed; + mInputRow = src.mInputRow; + mInputRowStart = src.mInputRowStart; + mDeclaredXmlVersion = src.mDeclaredXmlVersion; + mFoundEncoding = src.mFoundEncoding; + mStandalone = src.mStandalone; + mXml11Handling = src.mXml11Handling; + } + + /* + //////////////////////////////////////// + // Public API + //////////////////////////////////////// + */ + + /** + * @param xmlVersion Optional xml version identifier of the main parsed + * document (if not bootstrapping the main document). + * Currently only relevant for checking that XML 1.0 document does not + * include XML 1.1 external parsed entities. + * If null, no checks will be done; when bootstrapping parsing of the + * main document, null should be passed for this argument. + */ + public abstract Reader bootstrapInput(ReaderConfig cfg, boolean mainDoc, + int xmlVersion) + throws IOException, XMLStreamException; + + // // // Source information: + + public String getPublicId() { return mPublicId; } + + public SystemId getSystemId() { return mSystemId; } + + // // // XML declaration data: + + public int getDeclaredVersion() + { + return mDeclaredXmlVersion; + } + + /** + * @return True, if the input bootstrapped declared that it conforms + * to xml 1.1 (independent of where it was included from) + */ + public boolean declaredXml11() { + return (mDeclaredXmlVersion == XmlConsts.XML_V_11); + } + + public String getStandalone() { + return mStandalone; + } + + /** + * @return Encoding declaration found from the xml declaration, if any; + * null if none. + */ + public String getDeclaredEncoding() { + return mFoundEncoding; + } + + // // // Location/position info: + + /** + * @return Total number of characters read from bootstrapped input + * (stream, reader) + */ + public abstract int getInputTotal(); + + public int getInputRow() { + return mInputRow; + } + + public abstract int getInputColumn(); + + + // // // Misc other info + + /** + * Actual character encoding used by the underlying input source; + * may have been passed by the application, or auto-detected + * by byte stream boot strapper (can not be determined from a + * Reader source). + * + * @return Input encoding in use, if it could be determined or was + * passed by the calling application + */ + public abstract String getInputEncoding(); + + /* + //////////////////////////////////////// + // Package methods, parsing + //////////////////////////////////////// + */ + + /** + * @param xmlVersion Optional xml version identifier of the main parsed + * document (if not bootstrapping the main document). + * Currently only relevant for checking that XML 1.0 document does not + * include XML 1.1 external parsed entities. + * If null, no checks will be done; when bootstrapping parsing of the + * main document, null should be passed for this argument. + */ + protected void readXmlDecl(boolean isMainDoc, int xmlVersion) + throws IOException, WstxException + { + int c = getNextAfterWs(false); + + // First, version pseudo-attribute: + + if (c != 'v') { // version info obligatory for main docs + if (isMainDoc) { + reportUnexpectedChar(c, ERR_XMLDECL_KW_VERSION); + } + } else { // ok, should be version + mDeclaredXmlVersion = readXmlVersion(); + c = getWsOrChar('?'); + } + + /* 17-Feb-2006, TSa: Whether we are to be xml 1.1 compliant or not + * depends on parent context, if any; and if not, on actual + * xml declaration. But in former case, it is illegal to include + * xml 1.1 declared entities from xml 1.0 context. + */ + boolean thisIs11 = (mDeclaredXmlVersion == XmlConsts.XML_V_11); + if (xmlVersion != XmlConsts.XML_V_UNKNOWN) { // happens when reading main doc + mXml11Handling = (XmlConsts.XML_V_11 == xmlVersion); + // Can not refer to xml 1.1 entities from 1.0 doc: + if (thisIs11 && !mXml11Handling) { + reportXmlProblem(ErrorConsts.ERR_XML_10_VS_11); + } + } else { + mXml11Handling = thisIs11; + } + + // Then, 'encoding' + if (c != 'e') { // obligatory for external entities + if (!isMainDoc) { + reportUnexpectedChar(c, ERR_XMLDECL_KW_ENCODING); + } + } else { + mFoundEncoding = readXmlEncoding(); + c = getWsOrChar('?'); + } + + // Then, 'standalone' (for main doc) + if (isMainDoc && c == 's') { + mStandalone = readXmlStandalone(); + c = getWsOrChar('?'); + } + + // And finally, need to have closing markers + + if (c != '?') { + reportUnexpectedChar(c, ERR_XMLDECL_END_MARKER); + } + c = getNext(); + if (c != '>') { + reportUnexpectedChar(c, ERR_XMLDECL_END_MARKER); + } + } + + /** + * @return Xml version declaration read + */ + private final int readXmlVersion() + throws IOException, WstxException + { + int c = checkKeyword(XmlConsts.XML_DECL_KW_VERSION); + if (c != CHAR_NULL) { + reportUnexpectedChar(c, XmlConsts.XML_DECL_KW_VERSION); + } + c = handleEq(XmlConsts.XML_DECL_KW_VERSION); + int len = readQuotedValue(mKeyword, c); + + if (len == 3) { + if (mKeyword[0] == '1' && mKeyword[1] == '.') { + c = mKeyword[2]; + if (c == '0') { + return XmlConsts.XML_V_10; + } + if (c == '1') { + return XmlConsts.XML_V_11; + } + } + } + + // Nope; error. -1 indicates run off... + String got; + + if (len < 0) { + got = "'"+new String(mKeyword)+"[..]'"; + } else if (len == 0) { + got = ""; + } else { + got = "'"+new String(mKeyword, 0, len)+"'"; + } + reportPseudoAttrProblem(XmlConsts.XML_DECL_KW_VERSION, got, + XmlConsts.XML_V_10_STR, XmlConsts.XML_V_11_STR); + return XmlConsts.XML_V_UNKNOWN; // never gets here, but compiler needs it + } + + private final String readXmlEncoding() + throws IOException, WstxException + { + int c = checkKeyword(XmlConsts.XML_DECL_KW_ENCODING); + if (c != CHAR_NULL) { + reportUnexpectedChar(c, XmlConsts.XML_DECL_KW_ENCODING); + } + c = handleEq(XmlConsts.XML_DECL_KW_ENCODING); + + int len = readQuotedValue(mKeyword, c); + + /* Hmmh. How about "too long" encodings? Maybe just truncate them, + * for now? + */ + if (len == 0) { // let's still detect missing value... + reportPseudoAttrProblem(XmlConsts.XML_DECL_KW_ENCODING, null, + null, null); + } + + if (len < 0) { // will be truncated... + return new String(mKeyword); + } + return new String(mKeyword, 0, len); + } + + private final String readXmlStandalone() + throws IOException, WstxException + { + int c = checkKeyword(XmlConsts.XML_DECL_KW_STANDALONE); + if (c != CHAR_NULL) { + reportUnexpectedChar(c, XmlConsts.XML_DECL_KW_STANDALONE); + } + c = handleEq(XmlConsts.XML_DECL_KW_STANDALONE); + int len = readQuotedValue(mKeyword, c); + + if (len == 2) { + if (mKeyword[0] == 'n' && mKeyword[1] == 'o') { + return XmlConsts.XML_SA_NO; + } + } else if (len == 3) { + if (mKeyword[0] == 'y' && mKeyword[1] == 'e' + && mKeyword[2] == 's') { + return XmlConsts.XML_SA_YES; + } + } + + // Nope; error. -1 indicates run off... + String got; + + if (len < 0) { + got = "'"+new String(mKeyword)+"[..]'"; + } else if (len == 0) { + got = ""; + } else { + got = "'"+new String(mKeyword, 0, len)+"'"; + } + + reportPseudoAttrProblem(XmlConsts.XML_DECL_KW_STANDALONE, got, + XmlConsts.XML_SA_YES, XmlConsts.XML_SA_NO); + return got; // never gets here, but compiler can't figure it out + } + + private final int handleEq(String attr) + throws IOException, WstxException + { + int c = getNextAfterWs(false); + if (c != '=') { + reportUnexpectedChar(c, ERR_XMLDECL_EXP_EQ+"'"+attr+"'"); + } + + c = getNextAfterWs(false); + if (c != '"' && c != '\'') { + reportUnexpectedChar(c, ERR_XMLDECL_EXP_ATTRVAL+"'"+attr+"'"); + } + return c; + } + + /** + * Method that should get next character, which has to be either specified + * character (usually end marker), OR, any character as long as there' + * at least one space character before it. + */ + private final int getWsOrChar(int ok) + throws IOException, WstxException + { + int c = getNext(); + if (c == ok) { + return c; + } + if (c > CHAR_SPACE) { + reportUnexpectedChar(c, "; expected either '"+((char) ok)+"' or white space"); + } + if (c == CHAR_LF || c == CHAR_CR) { + // Need to push it back to be processed properly + pushback(); + } + return getNextAfterWs(false); + } + + /* + //////////////////////////////////////////////////////// + // Abstract parsing methods for sub-classes to implement + //////////////////////////////////////////////////////// + */ + + protected abstract void pushback(); + + protected abstract int getNext() + throws IOException, WstxException; + + protected abstract int getNextAfterWs(boolean reqWs) + throws IOException, WstxException; + + /** + * @return First character that does not match expected, if any; + * CHAR_NULL if match succeeded + */ + protected abstract int checkKeyword(String exp) + throws IOException, WstxException; + + protected abstract int readQuotedValue(char[] kw, int quoteChar) + throws IOException, WstxException; + + protected abstract Location getLocation(); + + /* + //////////////////////////////////////////////////////// + // Package methods available to sub-classes: + //////////////////////////////////////////////////////// + */ + + protected void reportNull() + throws WstxException + { + throw new WstxException("Illegal null byte in input stream", + getLocation()); + } + + protected void reportXmlProblem(String msg) + throws WstxException + { + throw new WstxParsingException(msg, getLocation()); + } + + protected void reportUnexpectedChar(int i, String msg) + throws WstxException + { + char c = (char) i; + String excMsg; + + // WTF? JDK thinks null char is just fine as?! + if (Character.isISOControl(c)) { + excMsg = "Unexpected character (CTRL-CHAR, code "+i+")"+msg; + } else { + excMsg = "Unexpected character '"+c+"' (code "+i+")"+msg; + } + Location loc = getLocation(); + throw new WstxUnexpectedCharException(excMsg, loc, c); + } + + /* + //////////////////////////////////////// + // Other private methods: + //////////////////////////////////////// + */ + + private final void reportPseudoAttrProblem(String attrName, String got, + String expVal1, String expVal2) + throws WstxException + { + String expStr = (expVal1 == null) ? "" : + ("; expected \""+expVal1+"\" or \""+expVal2+"\""); + + if (got == null || got.length() == 0) { + throw new WstxParsingException("Missing XML pseudo-attribute '"+attrName+"' value"+expStr, + getLocation()); + } + throw new WstxParsingException("Invalid XML pseudo-attribute '"+attrName+"' value "+got+expStr, + getLocation()); + } +} diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/io/InputSourceFactory.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/io/InputSourceFactory.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/io/InputSourceFactory.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/io/InputSourceFactory.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,76 @@ +package com.ctc.wstx.io; + +import java.io.Reader; +import java.net.URL; + +import javax.xml.stream.Location; + +import com.ctc.wstx.api.ReaderConfig; + +/** + * Factory class that creates instances of {@link WstxInputSource} to allow + * reading input from various sources. + */ +public final class InputSourceFactory +{ + //final static int DEFAULT_BUFFER_LENGTH = 4000; + + /** + * @param parent + * @param entityName Name of the entity expanded to create this input + * source: null when source created for the (main level) external + * DTD subset entity. + * @param xmlVersion Optional xml version identifier of the main parsed + * document. Currently only relevant for checking that XML 1.0 document + * does not include XML 1.1 external parsed entities. + * If unknown, no checks will be done. + */ + public static ReaderSource constructEntitySource + (ReaderConfig cfg, WstxInputSource parent, String entityName, InputBootstrapper bs, + String pubId, SystemId sysId, int xmlVersion, Reader r) + { + // true -> do close the underlying Reader at EOF + ReaderSource rs = new ReaderSource + (cfg, parent, entityName, pubId, sysId, r, true); + if (bs != null) { + rs.setInputOffsets(bs.getInputTotal(), bs.getInputRow(), + -bs.getInputColumn()); + } + return rs; + } + + /** + * Factory method used for creating the main-level document reader + * source. + */ + public static BranchingReaderSource constructDocumentSource + (ReaderConfig cfg, InputBootstrapper bs, String pubId, SystemId sysId, + Reader r, boolean realClose) + { + /* To resolve [WSTX-50] need to ensure that P_BASE_URL overrides + * the defaults if/as necessary + */ + URL url = cfg.getBaseURL(); + if (url != null) { + sysId = SystemId.construct(url); + } + BranchingReaderSource rs = new BranchingReaderSource(cfg, pubId, sysId, r, realClose); + if (bs != null) { + rs.setInputOffsets(bs.getInputTotal(), bs.getInputRow(), + -bs.getInputColumn()); + } + return rs; + } + + /** + * Factory method usually used to expand internal parsed entities; in + * which case context remains mostly the same. + */ + public static WstxInputSource constructCharArraySource + (WstxInputSource parent, String fromEntity, + char[] text, int offset, int len, Location loc, URL src) + { + SystemId sysId = SystemId.construct(loc.getSystemId(), src); + return new CharArraySource(parent, fromEntity, text, offset, len, loc, sysId); + } +} diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/io/ISOLatinReader.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/io/ISOLatinReader.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/io/ISOLatinReader.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/io/ISOLatinReader.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,133 @@ +/* Woodstox XML processor + * + * Copyright (c) 2004- Tatu Saloranta, tatu.saloranta@iki.fi + * + * Licensed under the License specified in file LICENSE, included with + * the source code. + * You may not use this file except in compliance with the License. + * + * 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 com.ctc.wstx.io; + +import java.io.*; + +import com.ctc.wstx.api.ReaderConfig; +import com.ctc.wstx.cfg.XmlConsts; + +/** + * Optimized Reader that reads ISO-Latin (aka ISO-8859-1) content from an + * input stream. + * In addition to doing (hopefully) optimal conversion, it can also take + * array of "pre-read" (leftover) bytes; this is necessary when preliminary + * stream/reader is trying to figure out XML encoding. + */ +public final class ISOLatinReader + extends BaseReader +{ + boolean mXml11 = false; + + /** + * Total read byte (and char) count; used for error reporting purposes + */ + int mByteCount = 0; + + /* + //////////////////////////////////////// + // Life-cycle + //////////////////////////////////////// + */ + + public ISOLatinReader(ReaderConfig cfg, InputStream in, byte[] buf, int ptr, int len, + boolean recycleBuffer) + { + super(cfg, in, buf, ptr, len, recycleBuffer); + } + + @Override + public void setXmlCompliancy(int xmlVersion) { + mXml11 = (xmlVersion == XmlConsts.XML_V_11); + } + + /* + //////////////////////////////////////// + // Public API + //////////////////////////////////////// + */ + + @Override + public int read(char[] cbuf, int start, int len) throws IOException + { + // Let's then ensure there's enough room... + if (start < 0 || (start+len) > cbuf.length) { + reportBounds(cbuf, start, len); + } + // Already EOF? + if (mByteBuffer == null) { + return -1; + } + if (len < 1) { // dummy call? + return 0; + } + + // Need to load more data? + int avail = mByteBufferEnd - mBytePtr; + if (avail <= 0) { + mByteCount += mByteBufferEnd; + // Let's always (try to) read full buffers + int count = readBytes(); + if (count <= 0) { + if (count == 0) { + reportStrangeStream(); + } + /* Let's actually then free the buffer right away; shouldn't + * yet close the underlying stream though? + */ + freeBuffers(); // to help GC? + return -1; + } + avail = count; + } + + /* K, have at least one byte == char, good enough; requiring more + * could block the calling thread too early + */ + + if (len > avail) { + len = avail; + } + int i = mBytePtr; + int last = i + len; + + if (mXml11) { + for (; i < last; ) { + char c = (char) (mByteBuffer[i++] & 0xFF); + if (c >= CHAR_DEL) { + if (c <= 0x9F) { + if (c == 0x85) { // NEL, let's convert? + c = CONVERT_NEL_TO; + } else if (c >= 0x7F) { // DEL, ctrl chars + int pos = mByteCount + i; + reportInvalidXml11(c, pos, pos); + } + } + } + cbuf[start++] = c; + + } + } else { + for (; i < last; ) { + cbuf[start++] = (char) (mByteBuffer[i++] & 0xFF); + } + } + + mBytePtr = last; + return len; + } +} + diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/io/MergedReader.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/io/MergedReader.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/io/MergedReader.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/io/MergedReader.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,154 @@ +package com.ctc.wstx.io; + +import java.io.*; + +import com.ctc.wstx.api.ReaderConfig; + +/** + * Simple {@link Reader} implementation that is used to "unwind" some + * data previously read from a Reader; so that as long as some of + * that data remains, it's returned; but as long as it's read, we'll + * just use data from the underlying original Reader. + * This is similar to {@link java.io.PushbackReader}, but with this class + * there's only one implicit pushback, when instance is constructed; not + * general pushback buffer and methods to use it. + */ +public final class MergedReader + extends Reader +{ + final ReaderConfig mConfig; + + final Reader mIn; + + /** + * This buffer contains the partially read remains left over after + * bootstrapper has consumed xml declaration (if one found). + * It is generally recycled and can be returned after having been + * read. + */ + char[] mData; + + int mPtr; + + final int mEnd; + + public MergedReader(ReaderConfig cfg, Reader in, char[] buf, int start, int end) + { + mConfig = cfg; + mIn = in; + mData = buf; + mPtr = start; + mEnd = end; + // sanity check: should not pass empty buffer + if (buf != null && start >= end) { + throw new IllegalArgumentException("Trying to construct MergedReader with empty contents (start "+start+", end "+end+")"); + } + } + + @Override + public void close() throws IOException + { + freeMergedBuffer(); + mIn.close(); + } + + @Override + public void mark(int readlimit) throws IOException + { + if (mData == null) { + mIn.mark(readlimit); + } + } + + @Override + public boolean markSupported() { + /* Only supports marks past the initial rewindable section... + */ + return (mData == null) && mIn.markSupported(); + } + + @Override + public int read() throws IOException + { + if (mData != null) { + int c = mData[mPtr++] & 0xFF; + if (mPtr >= mEnd) { + freeMergedBuffer(); + } + return c; + } + return mIn.read(); + } + + @Override + public int read(char[] cbuf) throws IOException { + return read(cbuf, 0, cbuf.length); + } + + @Override + public int read(char[] cbuf, int off, int len) throws IOException + { + if (mData != null) { + int avail = mEnd - mPtr; + if (len > avail) { + len = avail; + } + System.arraycopy(mData, mPtr, cbuf, off, len); + mPtr += len; + if (mPtr >= mEnd) { + freeMergedBuffer(); + } + return len; + } + + return mIn.read(cbuf, off, len); + } + + @Override + public boolean ready() throws IOException + { + return (mData != null) || mIn.ready(); + } + + @Override + public void reset() throws IOException + { + if (mData == null) { + mIn.reset(); + } + } + + @Override + public long skip(long n) throws IOException + { + long count = 0L; + + if (mData != null) { + int amount = mEnd - mPtr; + + if (amount > n) { // all in pushed back segment? + mPtr += (int) n; + return amount; + } + freeMergedBuffer(); + count += amount; + n -= amount; + } + + if (n > 0) { + count += mIn.skip(n); + } + return count; + } + + private void freeMergedBuffer() + { + if (mData != null) { + char[] data = mData; + mData = null; + if (mConfig != null) { + mConfig.freeSmallCBuffer(data); + } + } + } +} diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/io/MergedStream.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/io/MergedStream.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/io/MergedStream.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/io/MergedStream.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,146 @@ +package com.ctc.wstx.io; + +import java.io.*; + +import com.ctc.wstx.api.ReaderConfig; + +/** + * Simple {@link InputStream} implementation that is used to "unwind" some + * data previously read from an input stream; so that as long as some of + * that data remains, it's returned; but as long as it's read, we'll + * just use data from the underlying original stream. + * This is similar to {@link java.io.PushbackInputStream}, but here there's + * only one implicit pushback, when instance is constructed. + */ +public final class MergedStream + extends InputStream +{ + final ReaderConfig mConfig; + + final InputStream mIn; + + byte[] mData; + + int mPtr; + + final int mEnd; + + public MergedStream(ReaderConfig cfg, + InputStream in, byte[] buf, int start, int end) + { + mConfig = cfg; + mIn = in; + mData = buf; + mPtr = start; + mEnd = end; + } + + @Override + public int available() throws IOException + { + if (mData != null) { + return mEnd - mPtr; + } + return mIn.available(); + } + + @Override + public void close() throws IOException + { + freeMergedBuffer(); + mIn.close(); + } + + @Override + public void mark(int readlimit) { + if (mData == null) { + mIn.mark(readlimit); + } + } + + @Override + public boolean markSupported() { + /* Only supports marks past the initial rewindable section... + */ + return (mData == null) && mIn.markSupported(); + } + + @Override + public int read() throws IOException + { + if (mData != null) { + int c = mData[mPtr++] & 0xFF; + if (mPtr >= mEnd) { + freeMergedBuffer(); + } + return c; + } + return mIn.read(); + } + + @Override + public int read(byte[] b) throws IOException + { + return read(b, 0, b.length); + } + + @Override + public int read(byte[] b, int off, int len) throws IOException + { + if (mData != null) { + int avail = mEnd - mPtr; + if (len > avail) { + len = avail; + } + System.arraycopy(mData, mPtr, b, off, len); + mPtr += len; + if (mPtr >= mEnd) { + freeMergedBuffer(); + } + return len; + } + return mIn.read(b, off, len); + } + + @Override + public void reset() throws IOException + { + if (mData == null) { + mIn.reset(); + } + } + + @Override + public long skip(long n) throws IOException + { + long count = 0L; + + if (mData != null) { + int amount = mEnd - mPtr; + + if (amount > n) { // all in pushed back segment? + mPtr += (int) n; + return n; + } + freeMergedBuffer(); + count += amount; + n -= amount; + } + + if (n > 0) { + count += mIn.skip(n); + } + return count; + } + + private void freeMergedBuffer() + { + if (mData != null) { + byte[] data = mData; + mData = null; + if (mConfig != null) { + mConfig.freeFullBBuffer(data); + } + } + } +} diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/io/package.html libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/io/package.html --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/io/package.html 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/io/package.html 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,5 @@ + +Low-level classes that are used to abstract most details of stream I/O +access from actual parsing classes. Input source abstraction is used +to allow nested input necessary for proper entity expansion functionality. + diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/io/ReaderBootstrapper.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/io/ReaderBootstrapper.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/io/ReaderBootstrapper.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/io/ReaderBootstrapper.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,412 @@ +/* Woodstox XML processor + * + * Copyright (c) 2004- Tatu Saloranta, tatu.saloranta@iki.fi + * + * Licensed under the License specified in file LICENSE, included with + * the source code. + * You may not use this file except in compliance with the License. + * + * 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 com.ctc.wstx.io; + +import java.io.*; +import java.text.MessageFormat; + +import javax.xml.stream.Location; +import javax.xml.stream.XMLReporter; +import javax.xml.stream.XMLStreamException; + +import org.codehaus.stax2.validation.XMLValidationProblem; + +import com.ctc.wstx.api.ReaderConfig; +import com.ctc.wstx.cfg.ErrorConsts; +import com.ctc.wstx.cfg.ParsingErrorMsgs; +import com.ctc.wstx.exc.*; +import com.ctc.wstx.util.StringUtil; + +/** + * Input bootstrap class used when input comes from a Reader; in this case, + * encoding is already known, and thus encoding from XML declaration (if + * any) is only double-checked, not really used. + *

+ * Note: since the actual Reader to use after bootstrapping is pre-constructed, + * the local input buffer can (and should) be quite small. + */ +public final class ReaderBootstrapper + extends InputBootstrapper +{ + final static char CHAR_BOM_MARKER = (char) 0xFEFF; + + /* + //////////////////////////////////////// + // Configuration + //////////////////////////////////////// + */ + + /** + * Underlying Reader to use for reading content. + */ + final Reader mIn; + + /** + * Encoding identifier processing application passed in; if not null, + * will be compared to actual xml declaration based encoding (if + * declaration found) + */ + final String mInputEncoding; + + /* + /////////////////////////////////////////////////////////////// + // Input buffering + /////////////////////////////////////////////////////////////// + */ + + private char[] mCharBuffer; + + private int mInputPtr; + + private int mInputEnd; + + /* + //////////////////////////////////////// + // Life-cycle + //////////////////////////////////////// + */ + + private ReaderBootstrapper(String pubId, SystemId sysId, Reader r, String appEncoding) + { + super(pubId, sysId); + mIn = r; + if (appEncoding == null) { // may still be able to figure it out + if (r instanceof InputStreamReader) { + appEncoding = ((InputStreamReader) r).getEncoding(); + } + } + mInputEncoding = appEncoding; + } + + /* + //////////////////////////////////////// + // Public API + //////////////////////////////////////// + */ + + /** + * @param r Eventual reader that will be reading actual content, after + * bootstrapping finishes + * @param appEncoding Encoding that application declared; may be null. + * If not null, will be compared to actual declaration found; and + * incompatibility reported as a potential (but not necessarily fatal) + * problem. + */ + public static ReaderBootstrapper getInstance(String pubId, SystemId sysId, + Reader r, String appEncoding) + { + return new ReaderBootstrapper(pubId, sysId, r, appEncoding); + } + + /** + * Method called to do actual bootstrapping. + * + * @return Actual reader to use for reading xml content + */ + @Override + public Reader bootstrapInput(ReaderConfig cfg, boolean mainDoc, int xmlVersion) + throws IOException, XMLStreamException + { + /* First order of business: allocate input buffer. Not done during + * construction for simplicity; that way config object need not be + * passed before actual bootstrap method is called + */ + /* Let's make sure buffer is at least 6 chars (to know '") + */ + if (mInputEnd >= 7) { + char c = mCharBuffer[mInputPtr]; + + // BOM to skip? + if (c == CHAR_BOM_MARKER) { + c = mCharBuffer[++mInputPtr]; + } + if (c == '<') { + if (mCharBuffer[mInputPtr+1] == '?' + && mCharBuffer[mInputPtr+2] == 'x' + && mCharBuffer[mInputPtr+3] == 'm' + && mCharBuffer[mInputPtr+4] == 'l' + && mCharBuffer[mInputPtr+5] <= CHAR_SPACE) { + // Yup, got the declaration ok! + mInputPtr += 6; // skip declaration + readXmlDecl(mainDoc, xmlVersion); + + if (mFoundEncoding != null && mInputEncoding != null) { + verifyXmlEncoding(cfg); + } + } + } else { + /* We may also get something that would be invalid xml + * ("garbage" char; neither '<' nor space). If so, and + * it's one of "well-known" cases, we can not only throw + * an exception but also indicate a clue as to what is likely + * to be wrong. + */ + /* Specifically, UTF-8 read via, say, ISO-8859-1 reader, can + * "leak" marker (0xEF, 0xBB, 0xBF). While we could just eat + * it, there's bound to be other problems cropping up, so let's + * inform about the problem right away. + */ + if (c == 0xEF) { + throw new WstxIOException("Unexpected first character (char code 0xEF), not valid in xml document: could be mangled UTF-8 BOM marker. Make sure that the Reader uses correct encoding or pass an InputStream instead"); + } + } + } + + /* Ok, now; do we have unused chars we have read that need to + * be merged in? + */ + if (mInputPtr < mInputEnd) { + return new MergedReader(cfg, mIn, mCharBuffer, mInputPtr, mInputEnd); + } + + return mIn; + } + + @Override + public String getInputEncoding() { + return mInputEncoding; + } + + @Override + public int getInputTotal() { + return mInputProcessed + mInputPtr; + } + + @Override + public int getInputColumn() { + return (mInputPtr - mInputRowStart); + } + + /* + //////////////////////////////////////// + // Internal methods, parsing + //////////////////////////////////////// + */ + + protected void verifyXmlEncoding(ReaderConfig cfg) + throws XMLStreamException + { + String inputEnc = mInputEncoding; + + // Close enough? + if (StringUtil.equalEncodings(inputEnc, mFoundEncoding)) { + return; + } + + /* Ok, maybe the difference is just with endianness indicator? + * (UTF-16BE vs. UTF-16)? + */ + // !!! TBI + + XMLReporter rep = cfg.getXMLReporter(); + if (rep != null) { + Location loc = getLocation(); + String msg = MessageFormat.format(ErrorConsts.W_MIXED_ENCODINGS, + new Object[] { mFoundEncoding, + inputEnc }); + String type = ErrorConsts.WT_XML_DECL; + /* 30-May-2008, tatus: Should wrap all the info as XMValidationProblem + * since that's Woodstox' contract wrt. relatedInformation field. + */ + XMLValidationProblem prob = new XMLValidationProblem(loc, msg, XMLValidationProblem.SEVERITY_WARNING, type); + rep.report(msg, type, prob, loc); + } + } + + /* + ///////////////////////////////////////////////////// + // Internal methods, loading input data + ///////////////////////////////////////////////////// + */ + + protected boolean initialLoad(int minimum) + throws IOException + { + mInputPtr = 0; + mInputEnd = 0; + + while (mInputEnd < minimum) { + int count = mIn.read(mCharBuffer, mInputEnd, + mCharBuffer.length - mInputEnd); + if (count < 1) { + return false; + } + mInputEnd += count; + } + return true; + } + + protected void loadMore() + throws IOException, WstxException + { + /* Need to make sure offsets are properly updated for error + * reporting purposes, and do this now while previous amounts + * are still known. + */ + mInputProcessed += mInputEnd; + mInputRowStart -= mInputEnd; + + mInputPtr = 0; + mInputEnd = mIn.read(mCharBuffer, 0, mCharBuffer.length); + if (mInputEnd < 1) { + throw new WstxEOFException(ParsingErrorMsgs.SUFFIX_IN_XML_DECL, + getLocation()); + } + } + + /* + ///////////////////////////////////////////////////// + // Implementations of abstract parsing methods + ///////////////////////////////////////////////////// + */ + + @Override + protected void pushback() { + --mInputPtr; + } + + @Override + protected int getNext() + throws IOException, WstxException + { + return (mInputPtr < mInputEnd) ? + mCharBuffer[mInputPtr++] : nextChar(); + } + + @Override + protected int getNextAfterWs(boolean reqWs) + throws IOException, WstxException + { + int count = 0; + + while (true) { + char c = (mInputPtr < mInputEnd) ? + mCharBuffer[mInputPtr++] : nextChar(); + + if (c > CHAR_SPACE) { + if (reqWs && count == 0) { + reportUnexpectedChar(c, ERR_XMLDECL_EXP_SPACE); + } + return c; + } + if (c == CHAR_CR || c == CHAR_LF) { + skipCRLF(c); + } else if (c == CHAR_NULL) { + reportNull(); + } + ++count; + } + } + + /** + * @return First character that does not match expected, if any; + * CHAR_NULL if match succeeded + */ + @Override + protected int checkKeyword(String exp) + throws IOException, WstxException + { + int len = exp.length(); + + for (int ptr = 1; ptr < len; ++ptr) { + char c = (mInputPtr < mInputEnd) ? + mCharBuffer[mInputPtr++] : nextChar(); + + if (c != exp.charAt(ptr)) { + return c; + } + if (c == CHAR_NULL) { + reportNull(); + } + } + + return CHAR_NULL; + } + + @Override + protected int readQuotedValue(char[] kw, int quoteChar) + throws IOException, WstxException + { + int i = 0; + int len = kw.length; + + while (true) { + char c = (mInputPtr < mInputEnd) ? + mCharBuffer[mInputPtr++] : nextChar(); + if (c == CHAR_CR || c == CHAR_LF) { + skipCRLF(c); + } else if (c == CHAR_NULL) { + reportNull(); + } + if (c == quoteChar) { + return (i < len) ? i : -1; + } + // Let's just truncate longer values, but match quote + if (i < len) { + kw[i++] = c; + } + } + } + + @Override + protected Location getLocation() + { + return new WstxInputLocation(null, mPublicId, mSystemId, + mInputProcessed + mInputPtr - 1, + mInputRow, mInputPtr - mInputRowStart); + } + + /* + ///////////////////////////////////////////////////// + // Internal methods, single-byte access methods + ///////////////////////////////////////////////////// + */ + + protected char nextChar() + throws IOException, WstxException + { + if (mInputPtr >= mInputEnd) { + loadMore(); + } + return mCharBuffer[mInputPtr++]; + } + + protected void skipCRLF(char lf) + throws IOException, WstxException + { + if (lf == CHAR_CR) { + char c = (mInputPtr < mInputEnd) ? + mCharBuffer[mInputPtr++] : nextChar(); + if (c != BYTE_LF) { + --mInputPtr; // pushback if not 2-char/byte lf + } + } + ++mInputRow; + mInputRowStart = mInputPtr; + } +} diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/io/ReaderSource.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/io/ReaderSource.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/io/ReaderSource.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/io/ReaderSource.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,208 @@ +package com.ctc.wstx.io; + +import java.io.IOException; +import java.io.Reader; + +import javax.xml.stream.XMLStreamException; + +import com.ctc.wstx.api.ReaderConfig; +import com.ctc.wstx.exc.WstxException; + +/** + * Input source that reads input via a Reader. + */ +public class ReaderSource + extends BaseInputSource +{ + final ReaderConfig mConfig; + + /** + * Underlying Reader to read character data from + */ + protected Reader mReader; + + /** + * If true, will close the underlying Reader when this source is closed; + * if false will leave it open. + */ + final boolean mDoRealClose; + + int mInputProcessed = 0; + int mInputRow = 1; + int mInputRowStart = 0; + + public ReaderSource(ReaderConfig cfg, WstxInputSource parent, String fromEntity, + String pubId, SystemId sysId, + Reader r, boolean realClose) + { + super(parent, fromEntity, pubId, sysId); + mConfig = cfg; + mReader = r; + mDoRealClose = realClose; + int bufSize = cfg.getInputBufferLength(); + mBuffer = cfg.allocFullCBuffer(bufSize); + } + + /** + * Method called to change the default offsets this source has. Generally + * done when the underlying Reader had been partially read earlier (like + * reading the xml declaration before starting real parsing). + */ + public void setInputOffsets(int proc, int row, int rowStart) + { + mInputProcessed = proc; + mInputRow = row; + mInputRowStart = rowStart; + } + + /** + * Input location is easy to set, as we'll start from the beginning + * of a File. + */ + @Override + protected void doInitInputLocation(WstxInputData reader) + { + reader.mCurrInputProcessed = mInputProcessed; + reader.mCurrInputRow = mInputRow; + reader.mCurrInputRowStart = mInputRowStart; + } + + /** + * This is a hard-coded assumption, for now this source is + * only created from external entities + */ + @Override + public boolean fromInternalEntity() { + return false; + } + + @Override + public int readInto(WstxInputData reader) + throws IOException, XMLStreamException + { + /* Shouldn't really try to read after closing, but it may be easier + * for caller not to have to keep track of closure... + */ + if (mBuffer == null) { + return -1; + } + int count = mReader.read(mBuffer, 0, mBuffer.length); + if (count < 1) { + /* Let's prevent caller from accidentally being able to access + * data, first. + */ + mInputLast = 0; + reader.mInputPtr = 0; + reader.mInputEnd = 0; + if (count == 0) { + /* Sanity check; should never happen with correctly written + * Readers: + */ + throw new WstxException("Reader (of type "+mReader.getClass().getName()+") returned 0 characters, even when asked to read up to "+mBuffer.length, getLocation()); + } + return -1; + } + reader.mInputBuffer = mBuffer; + reader.mInputPtr = 0; + mInputLast = count; + reader.mInputEnd = count; + + return count; + } + + @Override + public boolean readMore(WstxInputData reader, int minAmount) + throws IOException, XMLStreamException + { + /* Shouldn't really try to read after closing, but it may be easier + * for caller not to have to keep track of closure... + */ + if (mBuffer == null) { + return false; + } + + int ptr = reader.mInputPtr; + int currAmount = mInputLast - ptr; + + // Let's first adjust caller's data appropriately: + /* Since we are essentially removing 'ptr' chars that we + * have used already, they count as past chars. Also, since + * offsets are reduced by 'ptr', need to adjust linefeed offset + * marker as well. + */ + reader.mCurrInputProcessed += ptr; + reader.mCurrInputRowStart -= ptr; + + // Existing data to move? + if (currAmount > 0) { + System.arraycopy(mBuffer, ptr, mBuffer, 0, currAmount); + minAmount -= currAmount; + } + reader.mInputBuffer = mBuffer; + reader.mInputPtr = 0; + mInputLast = currAmount; + + while (minAmount > 0) { + int amount = mBuffer.length - currAmount; + int actual = mReader.read(mBuffer, currAmount, amount); + if (actual < 1) { + if (actual == 0) { // sanity check: + throw new WstxException("Reader (of type "+mReader.getClass().getName()+") returned 0 characters, even when asked to read up to "+amount, getLocation()); + } + reader.mInputEnd = mInputLast = currAmount; + return false; + } + currAmount += actual; + minAmount -= actual; + } + reader.mInputEnd = mInputLast = currAmount; + return true; + } + + @Override + public void close() throws IOException + { + /* Buffer gets nullified by call to close() or closeCompletely(), + * no need to call second time + */ + if (mBuffer != null) { // so that it's ok to call multiple times + closeAndRecycle(mDoRealClose); + } + } + + @Override + public void closeCompletely() throws IOException + { + /* Only need to call if the Reader is not yet null... since + * buffer may have been cleaned by a call to close() + */ + if (mReader != null) { // so that it's ok to call multiple times + closeAndRecycle(true); + } + } + + private void closeAndRecycle(boolean fullClose) + throws IOException + { + char[] buf = mBuffer; + + // Can we recycle buffers? + if (buf != null) { + mBuffer = null; + mConfig.freeFullCBuffer(buf); + } + + // How about Reader; close and/or recycle its buffers? + if (mReader != null) { + if (mReader instanceof BaseReader) { + ((BaseReader) mReader).freeBuffers(); + } + if (fullClose) { + Reader r = mReader; + mReader = null; + r.close(); + } + } + } +} + diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/io/StreamBootstrapper.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/io/StreamBootstrapper.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/io/StreamBootstrapper.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/io/StreamBootstrapper.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,1020 @@ +package com.ctc.wstx.io; + +import java.io.*; + +import javax.xml.stream.Location; +import javax.xml.stream.XMLStreamException; + +import com.ctc.wstx.api.ReaderConfig; +import com.ctc.wstx.cfg.ParsingErrorMsgs; +import com.ctc.wstx.cfg.XmlConsts; +import com.ctc.wstx.exc.*; + +/** + * Input bootstrap class used with streams, when encoding is not known + * (when encoding is specified by application, a reader is constructed, + * and then reader-based bootstrapper is used). + *

after last valid byte in the buffer + */ + private StreamBootstrapper(String pubId, SystemId sysId, byte[] data, int start, int end) + { + super(pubId, sysId); + mIn = null; + mRecycleBuffer = false; + mByteBuffer = data; + mInputPtr = start; + mInputEnd = end; + } + + /* + //////////////////////////////////////// + // Public API + //////////////////////////////////////// + */ + + /** + * Factory method used when the underlying data provider is an + * actual stream. + */ + public static StreamBootstrapper getInstance(String pubId, SystemId sysId, InputStream in) + { + return new StreamBootstrapper(pubId, sysId, in); + } + + /** + * Factory method used when the underlying data provider is a pre-allocated + * block source, and no stream is used. + * Additionally the buffer passed is not owned by the bootstrapper + * or Reader that is created, so it is not to be recycled. + */ + public static StreamBootstrapper getInstance(String pubId, SystemId sysId, byte[] data, int start, int end) + { + return new StreamBootstrapper(pubId, sysId, data, start, end); + } + + @Override + public Reader bootstrapInput(ReaderConfig cfg, boolean mainDoc, int xmlVersion) + throws IOException, XMLStreamException + { + String normEnc = null; + + // First, let's get the buffers... + int bufSize = cfg.getInputBufferLength(); + if (bufSize < MIN_BUF_SIZE) { + bufSize = MIN_BUF_SIZE; + } + if (mByteBuffer == null) { // non-null if we were passed a buffer + mByteBuffer = cfg.allocFullBBuffer(bufSize); + } + + resolveStreamEncoding(); + + if (hasXmlDecl()) { + // note: readXmlDecl will set mXml11Handling too + readXmlDecl(mainDoc, xmlVersion); + if (mFoundEncoding != null) { + normEnc = verifyXmlEncoding(mFoundEncoding); + } + } else { + /* We'll actually then just inherit whatever main doc had... + * (or in case there was no parent, just copy the 'unknown') + */ + mXml11Handling = (XmlConsts.XML_V_11 == xmlVersion); + } + + // Now, have we figured out the encoding? + + if (normEnc == null) { // not via xml declaration + /* 21-Sep-2007, TSa: As with any non-UTF-8 encoding, declaration + * isn't optional any more. Besides, we need that information + * anyway to know which variant it is. + */ + if (mEBCDIC) { + if (mFoundEncoding == null || mFoundEncoding.length() == 0) { + reportXmlProblem("Missing encoding declaration: underlying encoding looks like an EBCDIC variant, but no xml encoding declaration found"); + } + // Hmmh. What should be the canonical name? Let's just use found encoding? + normEnc = mFoundEncoding; + } else if (mBytesPerChar == 2) { // UTF-16, BE/LE + normEnc = mBigEndian ? CharsetNames.CS_UTF16BE : CharsetNames.CS_UTF16LE; + } else if (mBytesPerChar == 4) { // UCS-4... ? + /* 22-Mar-2005, TSa: JDK apparently has no way of dealing + * with these encodings... not sure if and how it should + * be dealt with, really. Name could be UCS-4xx... or + * perhaps UTF-32xx + */ + normEnc = mBigEndian ? CharsetNames.CS_UTF32BE : CharsetNames.CS_UTF32LE; + } else { + // Ok, default has to be UTF-8, as per XML specs + normEnc = CharsetNames.CS_UTF8; + } + } + + mInputEncoding = normEnc; + + /* And then the reader. Let's figure out if we can use our own fast + * implementations first: + */ + BaseReader r; + + // Normalized, can thus use straight equality checks now + if (normEnc == CharsetNames.CS_UTF8) { + r = new UTF8Reader(cfg, mIn, mByteBuffer, mInputPtr, mInputEnd, mRecycleBuffer); + } else if (normEnc == CharsetNames.CS_ISO_LATIN1) { + r = new ISOLatinReader(cfg, mIn, mByteBuffer, mInputPtr, mInputEnd, mRecycleBuffer); + } else if (normEnc == CharsetNames.CS_US_ASCII) { + r = new AsciiReader(cfg, mIn, mByteBuffer, mInputPtr, mInputEnd, mRecycleBuffer); + } else if (normEnc.startsWith(CharsetNames.CS_UTF32)) { + // let's augment with actual endianness info + if (normEnc == CharsetNames.CS_UTF32) { + mInputEncoding = mBigEndian ? CharsetNames.CS_UTF32BE : CharsetNames.CS_UTF32LE; + } + r = new UTF32Reader(cfg, mIn, mByteBuffer, mInputPtr, mInputEnd, + mRecycleBuffer, mBigEndian); + } else { + // Nah, JDK needs to try it + // Ok; first, do we need to merge stuff back? + InputStream in = mIn; + if (mInputPtr < mInputEnd) { + in = new MergedStream(cfg, in, mByteBuffer, mInputPtr, mInputEnd); + } + /* 20-Jan-2006, TSa: Ok; although it is possible to declare + * stream as 'UTF-16', JDK may need help in figuring out + * the right order, so let's be explicit: + */ + if (normEnc == CharsetNames.CS_UTF16) { + mInputEncoding = normEnc = mBigEndian ? CharsetNames.CS_UTF16BE : CharsetNames.CS_UTF16LE; + } + try { + return new InputStreamReader(in, normEnc); + } catch (UnsupportedEncodingException usex) { + throw new WstxIOException("Unsupported encoding: "+usex.getMessage()); + } + } + + if (mXml11Handling) { + r.setXmlCompliancy(XmlConsts.XML_V_11); + } + + return r; + } + + /** + * Since this class only gets used when encoding is not explicitly + * passed, need use the encoding that was auto-detected... + */ + @Override + public String getInputEncoding() { + return mInputEncoding; + } + + @Override + public int getInputTotal() { + int total = mInputProcessed + mInputPtr; + if (mBytesPerChar > 1) { + total /= mBytesPerChar; + } + return total; + } + + @Override + public int getInputColumn() { + int col = mInputPtr - mInputRowStart; + if (mBytesPerChar > 1) { + col /= mBytesPerChar; + } + return col; + } + + /* + //////////////////////////////////////// + // Internal methods, parsing + //////////////////////////////////////// + */ + + /** + * Method called to try to figure out physical encoding the underlying + * input stream uses. + */ + protected void resolveStreamEncoding() + throws IOException, WstxException + { + // Let's first set defaults: + mBytesPerChar = 0; + mBigEndian = true; + + /* Ok; first just need 4 bytes for determining bytes-per-char from + * BOM or first char(s) of likely xml declaration: + */ + if (ensureLoaded(4)) { + bomblock: + do { // BOM/auto-detection block + int quartet = (mByteBuffer[0] << 24) + | ((mByteBuffer[1] & 0xFF) << 16) + | ((mByteBuffer[2] & 0xFF) << 8) + | (mByteBuffer[3] & 0xFF); + + /* Handling of (usually) optional BOM (required for + * multi-byte formats); first 32-bit charsets: + */ + switch (quartet) { + case 0x0000FEFF: + mBigEndian = true; + mInputPtr = mBytesPerChar = 4; + break bomblock; + case 0xFFFE0000: // UCS-4, LE? + mInputPtr = mBytesPerChar = 4; + mBigEndian = false; + break bomblock; + case 0x0000FFFE: // UCS-4, in-order... + reportWeirdUCS4("2143"); + break bomblock; + case 0x0FEFF0000: // UCS-4, in-order... + reportWeirdUCS4("3412"); + break bomblock; + } + + // Ok, if not, how about 16-bit encoding BOMs? + int msw = quartet >>> 16; + if (msw == 0xFEFF) { // UTF-16, BE + mInputPtr = mBytesPerChar = 2; + mBigEndian = true; + break; + } + if (msw == 0xFFFE) { // UTF-16, LE + mInputPtr = mBytesPerChar = 2; + mBigEndian = false; + break; + } + + // And if not, then UTF-8 BOM? + if ((quartet >>> 8) == 0xEFBBBF) { // UTF-8 + mInputPtr = 3; + mBytesPerChar = 1; + mBigEndian = true; // doesn't really matter + break; + } + + /* And if that wasn't succesful, how about auto-detection + * for ' 0); + + // Let's update location markers to ignore BOM. + mInputProcessed = -mInputPtr; + mInputRowStart = mInputPtr; + } + + /* Hmmh. If we haven't figured it out, let's just assume + * UTF-8 as per XML specs: + */ + mByteSizeFound = (mBytesPerChar != 0); + if (!mByteSizeFound) { + mBytesPerChar = 1; + mBigEndian = true; // doesn't matter + } + } + + /** + * @return Normalized encoding name + */ + protected String verifyXmlEncoding(String enc) + throws WstxException + { + enc = CharsetNames.normalize(enc); + + // Let's actually verify we got matching information: + if (enc == CharsetNames.CS_UTF8) { + verifyEncoding(enc, 1); + } else if (enc == CharsetNames.CS_ISO_LATIN1) { + verifyEncoding(enc, 1); + } else if (enc == CharsetNames.CS_US_ASCII) { + verifyEncoding(enc, 1); + } else if (enc == CharsetNames.CS_UTF16) { + // BOM is obligatory, to know the ordering + /* 22-Mar-2005, TSa: Actually, since we don't have a + * custom decoder, so the underlying JDK Reader may + * have dealt with it transparently... so we can not + * really throw an exception here. + */ + //if (!mHadBOM) { + //reportMissingBOM(enc); + //} + verifyEncoding(enc, 2); + } else if (enc == CharsetNames.CS_UTF16LE) { + verifyEncoding(enc, 2, false); + } else if (enc == CharsetNames.CS_UTF16BE) { + verifyEncoding(enc, 2, true); + + } else if (enc == CharsetNames.CS_UTF32) { + // Do we require a BOM here? we can live without it... + //if (!mHadBOM) { + // reportMissingBOM(enc); + //} + verifyEncoding(enc, 4); + } else if (enc == CharsetNames.CS_UTF32LE) { + verifyEncoding(enc, 4, false); + } else if (enc == CharsetNames.CS_UTF32BE) { + verifyEncoding(enc, 4, true); + } + return enc; + } + + /* + ///////////////////////////////////////////////////// + // Internal methods, loading input data + ///////////////////////////////////////////////////// + */ + + protected boolean ensureLoaded(int minimum) + throws IOException + { + /* Let's assume here buffer has enough room -- this will always + * be true for the limited used this method gets + */ + int gotten = (mInputEnd - mInputPtr); + while (gotten < minimum) { + int count = (mIn == null) ? -1 : mIn.read(mByteBuffer, mInputEnd, mByteBuffer.length - mInputEnd); + if (count < 1) { + return false; + } + mInputEnd += count; + gotten += count; + } + return true; + } + + protected void loadMore() + throws IOException, WstxException + { + /* Need to make sure offsets are properly updated for error + * reporting purposes, and do this now while previous amounts + * are still known. + */ + /* Note: at this point these are all in bytes, not chars (for multibyte + * encodings) + */ + mInputProcessed += mInputEnd; + mInputRowStart -= mInputEnd; + + mInputPtr = 0; + mInputEnd = (mIn == null) ? -1 : mIn.read(mByteBuffer, 0, mByteBuffer.length); + if (mInputEnd < 1) { + throw new WstxEOFException(ParsingErrorMsgs.SUFFIX_IN_XML_DECL, + getLocation()); + } + } + + /* + ///////////////////////////////////////////////////// + // Implementations of abstract parsing methods + ///////////////////////////////////////////////////// + */ + + @Override + protected void pushback() { + if (mBytesPerChar < 0) { + mInputPtr += mBytesPerChar; + } else { + mInputPtr -= mBytesPerChar; + } + } + + @Override + protected int getNext() + throws IOException, WstxException + { + if (mBytesPerChar != 1) { + if (mBytesPerChar == -1) { // need to translate + return nextTranslated(); + } + return nextMultiByte(); + } + byte b = (mInputPtr < mInputEnd) ? + mByteBuffer[mInputPtr++] : nextByte(); + return (b & 0xFF); + } + + @Override + protected int getNextAfterWs(boolean reqWs) + throws IOException, WstxException + { + int count; + + if (mBytesPerChar == 1) { // single byte + count = skipSbWs(); + } else { + if (mBytesPerChar == -1) { // translated + count = skipTranslatedWs(); + } else { // multi byte + count = skipMbWs(); + } + } + + if (reqWs && count == 0) { + reportUnexpectedChar(getNext(), ERR_XMLDECL_EXP_SPACE); + } + + // inlined getNext() + if (mBytesPerChar != 1) { + if (mBytesPerChar == -1) { // translated + return nextTranslated(); + } + return nextMultiByte(); + } + byte b = (mInputPtr < mInputEnd) ? + mByteBuffer[mInputPtr++] : nextByte(); + return (b & 0xFF); + } + + /** + * @return First character that does not match expected, if any; + * CHAR_NULL if match succeeded + */ + @Override + protected int checkKeyword(String exp) + throws IOException, WstxException + { + if (mBytesPerChar != 1) { + if (mBytesPerChar == -1) { + return checkTranslatedKeyword(exp); + } + return checkMbKeyword(exp); + } + return checkSbKeyword(exp); + } + + @Override + protected int readQuotedValue(char[] kw, int quoteChar) + throws IOException, WstxException + { + int i = 0; + int len = kw.length; + boolean simple = (mBytesPerChar == 1); + boolean mb = !simple && (mBytesPerChar > 1); + + while (i < len) { + int c; + + if (simple) { + byte b = (mInputPtr < mInputEnd) ? + mByteBuffer[mInputPtr++] : nextByte(); + if (b == BYTE_NULL) { + reportNull(); + } + if (b == BYTE_CR || b == BYTE_LF) { + skipSbLF(b); + b = BYTE_LF; + } + c = (b & 0xFF); + } else { + if (mb) { + c = nextMultiByte(); + if (c == CHAR_CR || c == CHAR_LF) { + skipMbLF(c); + c = CHAR_LF; + } + } else { + c = nextTranslated(); + if (c == CHAR_CR || c == CHAR_LF) { + skipTranslatedLF(c); + c = CHAR_LF; + } + } + } + + if (c == quoteChar) { + return (i < len) ? i : -1; + } + + if (i < len) { + kw[i++] = (char) c; + } + } + + /* If we end up this far, we ran out of buffer space... let's let + * caller figure that out, though + */ + return -1; + } + + protected boolean hasXmlDecl() + throws IOException, WstxException + { + /* Separate handling for common and fast case; 1/variable byte + * encodings that have ASCII subset: + */ + if (mBytesPerChar == 1) { + /* However... there has to be at least 6 bytes available; and if + * so, can check the 'signature' easily: + */ + if (ensureLoaded(6)) { + if (mByteBuffer[mInputPtr] == '<' + && mByteBuffer[mInputPtr+1] == '?' + && mByteBuffer[mInputPtr+2] == 'x' + && mByteBuffer[mInputPtr+3] == 'm' + && mByteBuffer[mInputPtr+4] == 'l' + && ((mByteBuffer[mInputPtr+5] & 0xFF) <= CHAR_SPACE)) { + + // Let's skip stuff so far: + mInputPtr += 6; + return true; + } + } + } else if (mBytesPerChar == -1) { // translated (EBCDIC) + if (ensureLoaded(6)) { + int start = mInputPtr; // if we have to 'unread' chars + if (nextTranslated() == '<' + && nextTranslated() == '?' + && nextTranslated() == 'x' + && nextTranslated() == 'm' + && nextTranslated() == 'l' + && nextTranslated() <= CHAR_SPACE) { + return true; + } + mInputPtr = start; // push data back + } + } else { + // ... and then for slower fixed-multibyte encodings: + + // Is there enough data for checks? + if (ensureLoaded (6 * mBytesPerChar)) { + int start = mInputPtr; // if we have to 'unread' chars + if (nextMultiByte() == '<' + && nextMultiByte() == '?' + && nextMultiByte() == 'x' + && nextMultiByte() == 'm' + && nextMultiByte() == 'l' + && nextMultiByte() <= CHAR_SPACE) { + return true; + } + mInputPtr = start; // push data back + } + } + + return false; + } + + @Override + protected Location getLocation() + { + /* Ok; for fixed-size multi-byte encodings, need to divide numbers + * to get character locations. For variable-length encodings the + * good thing is that xml declaration only uses shortest codepoints, + * ie. char count == byte count. + */ + int total = mInputProcessed + mInputPtr; + int col = mInputPtr - mInputRowStart; + + if (mBytesPerChar > 1) { + total /= mBytesPerChar; + col /= mBytesPerChar; + } + + return new WstxInputLocation(null, mPublicId, mSystemId, + total - 1, // 0-based + mInputRow, col); + } + + /* + ///////////////////////////////////////////////////// + // Internal methods, single-byte access methods + ///////////////////////////////////////////////////// + */ + + protected byte nextByte() + throws IOException, WstxException + { + if (mInputPtr >= mInputEnd) { + loadMore(); + } + return mByteBuffer[mInputPtr++]; + } + + protected int skipSbWs() + throws IOException, WstxException + { + int count = 0; + + while (true) { + byte b = (mInputPtr < mInputEnd) ? + mByteBuffer[mInputPtr++] : nextByte(); + + if ((b & 0xFF) > CHAR_SPACE) { + --mInputPtr; + break; + } + if (b == BYTE_CR || b == BYTE_LF) { + skipSbLF(b); + } else if (b == BYTE_NULL) { + reportNull(); + } + ++count; + } + return count; + } + + protected void skipSbLF(byte lfByte) + throws IOException, WstxException + { + if (lfByte == BYTE_CR) { + byte b = (mInputPtr < mInputEnd) ? + mByteBuffer[mInputPtr++] : nextByte(); + if (b != BYTE_LF) { + --mInputPtr; // pushback if not 2-char/byte lf + } + } + ++mInputRow; + mInputRowStart = mInputPtr; + } + + /** + * @return First character that does not match expected, if any; + * CHAR_NULL if match succeeded + */ + protected int checkSbKeyword(String expected) + throws IOException, WstxException + { + int len = expected.length(); + + for (int ptr = 1; ptr < len; ++ptr) { + byte b = (mInputPtr < mInputEnd) ? + mByteBuffer[mInputPtr++] : nextByte(); + + if (b == BYTE_NULL) { + reportNull(); + } + if ((b & 0xFF) != expected.charAt(ptr)) { + return (b & 0xFF); + } + } + + return CHAR_NULL; + } + + /* + ///////////////////////////////////////////////////// + // Internal methods, multi-byte/translated access/checks + ///////////////////////////////////////////////////// + */ + + protected int nextMultiByte() + throws IOException, WstxException + { + byte b = (mInputPtr < mInputEnd) ? + mByteBuffer[mInputPtr++] : nextByte(); + byte b2 = (mInputPtr < mInputEnd) ? + mByteBuffer[mInputPtr++] : nextByte(); + int c; + + if (mBytesPerChar == 2) { + if (mBigEndian) { + c = ((b & 0xFF) << 8) | (b2 & 0xFF); + } else { + c = (b & 0xFF) | ((b2 & 0xFF) << 8); + } + } else { + // Has to be 4 bytes + byte b3 = (mInputPtr < mInputEnd) ? + mByteBuffer[mInputPtr++] : nextByte(); + byte b4 = (mInputPtr < mInputEnd) ? + mByteBuffer[mInputPtr++] : nextByte(); + + if (mBigEndian) { + c = (b << 24) | ((b2 & 0xFF) << 16) + | ((b3 & 0xFF) << 8) | (b4 & 0xFF); + } else { + c = (b4 << 24) | ((b3 & 0xFF) << 16) + | ((b2 & 0xFF) << 8) | (b & 0xFF); + } + } + + // Let's catch null chars early + if (c == 0) { + reportNull(); + } + return c; + } + + protected int nextTranslated() + throws IOException, WstxException + { + byte b = (mInputPtr < mInputEnd) ? + mByteBuffer[mInputPtr++] : nextByte(); + int ch = mSingleByteTranslation[b & 0xFF]; + if (ch < 0) { // special char... won't care for now + ch = -ch; + } + return ch; + } + + protected int skipMbWs() + throws IOException, WstxException + { + int count = 0; + + while (true) { + int c = nextMultiByte(); + + if (c > CHAR_SPACE) { + mInputPtr -= mBytesPerChar; + break; + } + if (c == CHAR_CR || c == CHAR_LF) { + skipMbLF(c); + } else if (c == CHAR_NULL) { + reportNull(); + } + ++count; + } + return count; + } + + protected int skipTranslatedWs() + throws IOException, WstxException + { + int count = 0; + + while (true) { + int c = nextTranslated(); + + // Hmmh. Are we to accept NEL (0x85)? + if (c > CHAR_SPACE && c != CHAR_NEL) { + --mInputPtr; + break; + } + if (c == CHAR_CR || c == CHAR_LF) { + skipTranslatedLF(c); + } else if (c == CHAR_NULL) { + reportNull(); + } + ++count; + } + return count; + } + + protected void skipMbLF(int lf) + throws IOException, WstxException + { + if (lf == CHAR_CR) { + int c = nextMultiByte(); + if (c != CHAR_LF) { + mInputPtr -= mBytesPerChar; + } + } + ++mInputRow; + mInputRowStart = mInputPtr; + } + + protected void skipTranslatedLF(int lf) + throws IOException, WstxException + { + if (lf == CHAR_CR) { + int c = nextTranslated(); + if (c != CHAR_LF) { + mInputPtr -= 1; + } + } + ++mInputRow; + mInputRowStart = mInputPtr; + } + + /** + * @return First character that does not match expected, if any; + * CHAR_NULL if match succeeded + */ + protected int checkMbKeyword(String expected) + throws IOException, WstxException + { + int len = expected.length(); + + for (int ptr = 1; ptr < len; ++ptr) { + int c = nextMultiByte(); + if (c == BYTE_NULL) { + reportNull(); + } + if (c != expected.charAt(ptr)) { + return c; + } + } + + return CHAR_NULL; + } + + protected int checkTranslatedKeyword(String expected) + throws IOException, WstxException + { + int len = expected.length(); + + for (int ptr = 1; ptr < len; ++ptr) { + int c = nextTranslated(); + if (c == BYTE_NULL) { + reportNull(); + } + if (c != expected.charAt(ptr)) { + return c; + } + } + + return CHAR_NULL; + } + + /* + //////////////////////////////////////// + // Other private methods: + //////////////////////////////////////// + */ + + private void verifyEncoding(String id, int bpc) + throws WstxException + { + if (mByteSizeFound) { + /* Let's verify that if we matched an encoding, it's the same + * as what was declared... + */ + if (bpc != mBytesPerChar) { + // [WSTX-138]: Needs to detect EBCDIC discrepancy + if (mEBCDIC) { + reportXmlProblem("Declared encoding '"+id+"' incompatible with auto-detected physical encoding (EBCDIC variant), can not decode input since actual code page not known"); + } + reportXmlProblem("Declared encoding '"+id+"' uses "+bpc + +" bytes per character; but physical encoding appeared to use "+mBytesPerChar+"; cannot decode"); + } + } + } + + private void verifyEncoding(String id, int bpc, boolean bigEndian) + throws WstxException + { + if (mByteSizeFound) { + verifyEncoding(id, bpc); + + if (bigEndian != mBigEndian) { + String bigStr = bigEndian ? "big" : "little"; + reportXmlProblem + ("Declared encoding '"+id+"' has different endianness (" + +bigStr+" endian) than what physical ordering appeared to be; cannot decode"); + } + } + } + + private void reportWeirdUCS4(String type) + throws IOException + { + throw new CharConversionException("Unsupported UCS-4 endianness ("+type+") detected"); + } + + /* + private void reportMissingBOM(String enc) + throws WstxException + { + throw new WstxException("Missing BOM for encoding '"+enc+"'; can not be omitted", + getLocation()); + } + */ +} diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/io/SystemId.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/io/SystemId.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/io/SystemId.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/io/SystemId.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,67 @@ +package com.ctc.wstx.io; + +import java.io.IOException; +import java.net.URL; + +import com.ctc.wstx.util.URLUtil; + +/** + * Helper class that is used to defer construction of {@link URL} + * to help with cases where real URL is not actually needed, and + * incoming System Id may not even resolve properly. + *

+ * Note that class is meant to be accessed from a single thread, and + * is not designed as multi-thread safe. Specifically it is not to be + * used for caching or as a key, but strictly as System Id for processing + * of a single XML document. + * + * @since 4.4 + */ +public class SystemId +{ + protected URL mURL; + + protected String mSystemId; + + protected SystemId(String systemId, URL url) { + if (systemId == null && url == null) { + throw new IllegalArgumentException("Can not pass null for both systemId and url"); + } + mSystemId = systemId; + mURL = url; + } + + public static SystemId construct(String systemId) { + return (systemId == null) ? null : new SystemId(systemId, null); + } + + public static SystemId construct(URL url) { + return (url == null) ? null : new SystemId(null, url); + } + + public static SystemId construct(String systemId, URL url) { + if (systemId == null && url == null) { + return null; + } + return new SystemId(systemId, url); + } + + public URL asURL() throws IOException { + if (mURL == null) { + mURL = URLUtil.urlFromSystemId(mSystemId); + } + return mURL; + } + + public boolean hasResolvedURL() { + return (mURL != null); + } + + @Override + public String toString() { + if (mSystemId == null) { + mSystemId = mURL.toExternalForm(); + } + return mSystemId; + } +} diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/io/TextEscaper.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/io/TextEscaper.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/io/TextEscaper.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/io/TextEscaper.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,88 @@ +package com.ctc.wstx.io; + +import java.io.*; + +public final class TextEscaper +{ + private TextEscaper() { } + + /* + ///////////////////////////////////////////////////////////// + // Static utility methods, for non-state-aware escaping + ///////////////////////////////////////////////////////////// + */ + + public static void writeEscapedAttrValue(Writer w, String value) + throws IOException + { + int i = 0; + int len = value.length(); + do { + int start = i; + char c = '\u0000'; + + for (; i < len; ++i) { + c = value.charAt(i); + if (c == '<' || c == '&' || c == '"') { + break; + } + } + int outLen = i - start; + if (outLen > 0) { + w.write(value, start, outLen); + } + if (i < len) { + if (c == '<') { + w.write("<"); + } else if (c == '&') { + w.write("&"); + } else if (c == '"') { + w.write("""); + + } + } + } while (++i < len); + } + + /** + * Quoting method used when outputting content that will be part of + * DTD (internal/external subset). Additional quoting is needed for + * percentage char, which signals parameter entities. + */ + public static void outputDTDText(Writer w, char[] ch, int offset, int len) + throws IOException + { + int i = offset; + len += offset; + do { + int start = i; + char c = '\u0000'; + + for (; i < len; ++i) { + c = ch[i]; + if (c == '&' || c == '%' || c == '"') { + break; + } + } + int outLen = i - start; + if (outLen > 0) { + w.write(ch, start, outLen); + } + if (i < len) { + if (c == '&') { + /* Only need to quote to prevent it from being accidentally + * taken as part of char entity... + */ + w.write("&"); + } else if (c == '%') { + // Need to quote, to prevent use as Param Entity marker + w.write("%"); + } else if (c == '"') { + // Need to quote assuming it encloses entity value + w.write("""); + } + } + } while (++i < len); + } +} + diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/io/UTF32Reader.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/io/UTF32Reader.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/io/UTF32Reader.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/io/UTF32Reader.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,258 @@ +/* Woodstox XML processor + * + * Copyright (c) 2004 Tatu Saloranta, tatu.saloranta@iki.fi + * + * Licensed under the License specified in file LICENSE, included with + * the source code. + * You may not use this file except in compliance with the License. + * + * 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 com.ctc.wstx.io; + +import java.io.*; + +import com.ctc.wstx.api.ReaderConfig; +import com.ctc.wstx.cfg.XmlConsts; + +/** + * Since JDK does not come with UTF-32/UCS-4, let's implement a simple + * decoder to use. + */ +public final class UTF32Reader + extends BaseReader +{ + final boolean mBigEndian; + + boolean mXml11; + + /** + * Although input is fine with full Unicode set, Java still uses + * 16-bit chars, so we may have to split high-order chars into + * surrogate pairs. + */ + char mSurrogate = NULL_CHAR; + + /** + * Total read character count; used for error reporting purposes + */ + int mCharCount = 0; + + /** + * Total read byte count; used for error reporting purposes + */ + int mByteCount = 0; + + /* + //////////////////////////////////////// + // Life-cycle + //////////////////////////////////////// + */ + + public UTF32Reader(ReaderConfig cfg, InputStream in, byte[] buf, int ptr, int len, + boolean recycleBuffer, + boolean isBigEndian) + { + super(cfg, in, buf, ptr, len, recycleBuffer); + mBigEndian = isBigEndian; + } + + @Override + public void setXmlCompliancy(int xmlVersion) { + mXml11 = (xmlVersion == XmlConsts.XML_V_11); + } + + /* + //////////////////////////////////////// + // Public API + //////////////////////////////////////// + */ + + @Override + public int read(char[] cbuf, int start, int len) throws IOException + { + // Let's first ensure there's enough room... + if (start < 0 || (start+len) > cbuf.length) { + reportBounds(cbuf, start, len); + } + // Already EOF? + if (mByteBuffer == null) { + return -1; + } + if (len < 1) { + return 0; + } + + len += start; + int outPtr = start; + + // Ok, first; do we have a surrogate from last round? + if (mSurrogate != NULL_CHAR) { + cbuf[outPtr++] = mSurrogate; + mSurrogate = NULL_CHAR; + // No need to load more, already got one char + } else { + /* Note: we'll try to avoid blocking as much as possible. As a + * result, we only need to get 4 bytes for a full char. + */ + int left = (mByteBufferEnd - mBytePtr); + if (left < 4) { + if (!loadMore(left)) { // (legal) EOF? + return -1; + } + } + } + + byte[] buf = mByteBuffer; + + main_loop: + while (outPtr < len) { + int ptr = mBytePtr; + int ch; + + if (mBigEndian) { + ch = (buf[ptr] << 24) | ((buf[ptr+1] & 0xFF) << 16) + | ((buf[ptr+2] & 0xFF) << 8) | (buf[ptr+3] & 0xFF); + } else { + ch = (buf[ptr] & 0xFF) | ((buf[ptr+1] & 0xFF) << 8) + | ((buf[ptr+2] & 0xFF) << 16) | (buf[ptr+3] << 24); + } + mBytePtr += 4; + + // Does it need to be split to surrogates? + // (also, we can and need to verify illegal chars) + if (ch >= 0x7F) { + if (ch <= 0x9F) { + if (mXml11) { // high-order ctrl char detection... + if (ch != 0x85) { + reportInvalid(ch, outPtr-start, "(can only be included via entity in xml 1.1)"); + } + ch = CONVERT_NEL_TO; + } + } else if (ch >= 0xD800) { + // Illegal? + if (ch > XmlConsts.MAX_UNICODE_CHAR) { + reportInvalid(ch, outPtr-start, + "(above "+Integer.toHexString(XmlConsts.MAX_UNICODE_CHAR)+") "); + } + if (ch > 0xFFFF) { // need to split into surrogates? + ch -= 0x10000; // to normalize it starting with 0x0 + cbuf[outPtr++] = (char) (0xD800 + (ch >> 10)); + // hmmh. can this ever be 0? (not legal, at least?) + ch = (0xDC00 | (ch & 0x03FF)); + // Room for second part? + if (outPtr >= len) { // nope + mSurrogate = (char) ch; + break main_loop; + } + } else { // in 16-bit range... just need validity checks + if (ch < 0xE000) { + reportInvalid(ch, outPtr-start, "(a surrogate char) "); + } else if (ch >= 0xFFFE) { + reportInvalid(ch, outPtr-start, ""); + } + } + } else if (ch == 0x2028 && mXml11) { // LSEP + ch = CONVERT_LSEP_TO; + } + } + cbuf[outPtr++] = (char) ch; + if (mBytePtr >= mByteBufferEnd) { + break main_loop; + } + } + + len = outPtr - start; + mCharCount += len; + return len; + } + + /* + //////////////////////////////////////// + // Internal methods + //////////////////////////////////////// + */ + + private void reportUnexpectedEOF(int gotBytes, int needed) + throws IOException + { + int bytePos = mByteCount + gotBytes; + int charPos = mCharCount; + + throw new CharConversionException("Unexpected EOF in the middle of a 4-byte UTF-32 char: got " + +gotBytes+", needed "+needed + +", at char #"+charPos+", byte #"+bytePos+")"); + } + + private void reportInvalid(int value, int offset, String msg) + throws IOException + { + int bytePos = mByteCount + mBytePtr - 1; + int charPos = mCharCount + offset; + + throw new CharConversionException("Invalid UTF-32 character 0x" + +Integer.toHexString(value) + +msg+" at char #"+charPos+", byte #"+bytePos+")"); + } + + /** + * @param available Number of "unused" bytes in the input buffer + * + * @return True, if enough bytes were read to allow decoding of at least + * one full character; false if EOF was encountered instead. + */ + private boolean loadMore(int available) + throws IOException + { + mByteCount += (mByteBufferEnd - available); + + // Bytes that need to be moved to the beginning of buffer? + if (available > 0) { + /* 11-Nov-2008, TSa: can only move if we own the buffer; otherwise + * we are stuck with the data. + */ + if (mBytePtr > 0 && canModifyBuffer()) { + for (int i = 0; i < available; ++i) { + mByteBuffer[i] = mByteBuffer[mBytePtr+i]; + } + mBytePtr = 0; + mByteBufferEnd = available; + } + } else { + /* Ok; here we can actually reasonably expect an EOF, + * so let's do a separate read right away: + */ + int count = readBytes(); + if (count < 1) { + if (count < 0) { // -1 + freeBuffers(); // to help GC? + return false; + } + // 0 count is no good; let's err out + reportStrangeStream(); + } + } + + /* Need at least 4 bytes; if we don't get that many, it's an + * error. + */ + while (mByteBufferEnd < 4) { + int count = readBytesAt(mByteBufferEnd); + if (count < 1) { + if (count < 0) { // -1, EOF... no good! + freeBuffers(); // to help GC? + reportUnexpectedEOF(mByteBufferEnd, 4); + } + // 0 count is no good; let's err out + reportStrangeStream(); + } + } + return true; + } +} + diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/io/UTF8Reader.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/io/UTF8Reader.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/io/UTF8Reader.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/io/UTF8Reader.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,422 @@ +/* Woodstox XML processor + * + * Copyright (c) 2004 Tatu Saloranta, tatu.saloranta@iki.fi + * + * Licensed under the License specified in file LICENSE, included with + * the source code. + * You may not use this file except in compliance with the License. + * + * 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 com.ctc.wstx.io; + +import java.io.*; + +import com.ctc.wstx.api.ReaderConfig; +import com.ctc.wstx.cfg.XmlConsts; + +/** + * Optimized Reader that reads UTF-8 encoded content from an input stream. + * In addition to doing (hopefully) optimal conversion, it can also take + * array of "pre-read" (leftover) bytes; this is necessary when preliminary + * stream/reader is trying to figure out XML encoding. + */ +public final class UTF8Reader + extends BaseReader +{ + boolean mXml11 = false; + + char mSurrogate = NULL_CHAR; + + /** + * Total read character count; used for error reporting purposes + */ + int mCharCount = 0; + + /** + * Total read byte count; used for error reporting purposes + */ + int mByteCount = 0; + + /* + //////////////////////////////////////// + // Life-cycle + //////////////////////////////////////// + */ + + public UTF8Reader(ReaderConfig cfg, InputStream in, byte[] buf, int ptr, int len, + boolean recycleBuffer) + { + super(cfg, in, buf, ptr, len, recycleBuffer); + } + + @Override + public void setXmlCompliancy(int xmlVersion) { + mXml11 = (xmlVersion == XmlConsts.XML_V_11); + } + + /* + //////////////////////////////////////// + // Public API + //////////////////////////////////////// + */ + + @SuppressWarnings("cast") + @Override + public int read(char[] cbuf, int start, int len) throws IOException + { + // Let's first ensure there's enough room... + if (start < 0 || (start+len) > cbuf.length) { + reportBounds(cbuf, start, len); + } + // Already EOF? + if (mByteBuffer == null) { + return -1; + } + if (len < 1) { // dummy call? + return 0; + } + + len += start; + int outPtr = start; + + // Ok, first; do we have a surrogate from last round? + if (mSurrogate != NULL_CHAR) { + cbuf[outPtr++] = mSurrogate; + mSurrogate = NULL_CHAR; + // No need to load more, already got one char + } else { + /* To prevent unnecessary blocking (esp. with network streams), + * we'll only require decoding of a single char + */ + int left = (mByteBufferEnd - mBytePtr); + + /* So; only need to load more if we can't provide at least + * one more character. We need not do thorough check here, + * but let's check the common cases here: either completely + * empty buffer (left == 0), or one with less than max. byte + * count for a single char, and starting of a multi-byte + * encoding (this leaves possibility of a 2/3-byte char + * that is still fully accessible... but that can be checked + * by the load method) + */ + + if (left < 4) { + // Need to load more? + if (left < 1 || mByteBuffer[mBytePtr] < 0) { + if (!loadMore(left)) { // (legal) EOF? + return -1; + } + } + } + } + + /* This may look silly, but using a local var is indeed faster + * (if and when HotSpot properly gets things running) than + * member variable... + */ + byte[] buf = mByteBuffer; + int inPtr = mBytePtr; + int inBufLen = mByteBufferEnd; + + main_loop: + while (outPtr < len) { + // At this point we have at least one byte available + int c = (int) buf[inPtr++]; + + /* Let's first do the quickie loop for common case; 7-bit + * ascii: + */ + if (c >= 0) { // ascii? can probably loop, then + if (c == 0x7F && mXml11) { // DEL illegal in xml1.1 + int bytePos = mByteCount + inPtr - 1; + int charPos = mCharCount + (outPtr-start); + reportInvalidXml11(c, bytePos, charPos); + } + cbuf[outPtr++] = (char) c; // ok since MSB is never on + + /* Ok, how many such chars could we safely process + * without overruns? (will combine 2 in-loop comparisons + * into just one) + */ + int outMax = (len - outPtr); // max output + int inMax = (inBufLen - inPtr); // max input + int inEnd = inPtr + ((inMax < outMax) ? inMax : outMax); + + ascii_loop: + while (true) { + if (inPtr >= inEnd) { + break main_loop; + } + c = ((int) buf[inPtr++]) & 0xFF; + if (c >= 0x7F) { // DEL, or multi-byte + break ascii_loop; + } + cbuf[outPtr++] = (char) c; + } + if (c == 0x7F) { + if (mXml11) { // DEL illegal in xml1.1 + int bytePos = mByteCount + inPtr - 1; + int charPos = mCharCount + (outPtr-start); + reportInvalidXml11(c, bytePos, charPos); + } // but not in xml 1.0 + cbuf[outPtr++] = (char) c; + if(inPtr >= inEnd){ + break main_loop; + } + continue main_loop; + } + } + + int needed; + + // Ok; if we end here, we got multi-byte combination + if ((c & 0xE0) == 0xC0) { // 2 bytes (0x0080 - 0x07FF) + c = (c & 0x1F); + needed = 1; + } else if ((c & 0xF0) == 0xE0) { // 3 bytes (0x0800 - 0xFFFF) + c = (c & 0x0F); + needed = 2; + } else if ((c & 0xF8) == 0xF0) { + // 4 bytes; double-char BS, with surrogates and all... + c = (c & 0x0F); + needed = 3; + } else { + reportInvalidInitial(c & 0xFF, outPtr-start); + // never gets here... + needed = 1; + } + /* Do we have enough bytes? If not, let's just push back the + * byte and leave, since we have already gotten at least one + * char decoded. This way we will only block (with read from + * input stream) when absolutely necessary. + */ + if ((inBufLen - inPtr) < needed) { + --inPtr; + break main_loop; + } + + int d = (int) buf[inPtr++]; + if ((d & 0xC0) != 0x080) { + reportInvalidOther(d & 0xFF, outPtr-start); + } + c = (c << 6) | (d & 0x3F); + + if (needed > 1) { // needed == 1 means 2 bytes total + d = buf[inPtr++]; // 3rd byte + if ((d & 0xC0) != 0x080) { + reportInvalidOther(d & 0xFF, outPtr-start); + } + c = (c << 6) | (d & 0x3F); + if (needed > 2) { // 4 bytes? (need surrogates) + d = buf[inPtr++]; + if ((d & 0xC0) != 0x080) { + reportInvalidOther(d & 0xFF, outPtr-start); + } + c = (c << 6) | (d & 0x3F); + if (c > XmlConsts.MAX_UNICODE_CHAR) { + reportInvalid(c, outPtr-start, + "(above "+Integer.toHexString(XmlConsts.MAX_UNICODE_CHAR)+") "); + } + /* Ugh. Need to mess with surrogates. Ok; let's inline them + * there, then, if there's room: if only room for one, + * need to save the surrogate for the rainy day... + */ + c -= 0x10000; // to normalize it starting with 0x0 + cbuf[outPtr++] = (char) (0xD800 + (c >> 10)); + // hmmh. can this ever be 0? (not legal, at least?) + c = (0xDC00 | (c & 0x03FF)); + + // Room for second part? + if (outPtr >= len) { // nope + mSurrogate = (char) c; + break main_loop; + } + // sure, let's fall back to normal processing: + } else { + /* Otherwise, need to check that 3-byte chars are + * legal ones (should not expand to surrogates; + * 0xFFFE and 0xFFFF are illegal) + */ + if (c >= 0xD800) { + // But first, let's check max chars: + if (c < 0xE000) { + reportInvalid(c, outPtr-start, "(a surrogate character) "); + } else if (c >= 0xFFFE) { + reportInvalid(c, outPtr-start, ""); + } + } else if (mXml11 && c == 0x2028) { // LSEP? + /* 10-May-2006, TSa: Since LSEP is "non-associative", + * it needs additional handling. One way to do + * this is to convert preceding \r to \n. This + * should be implemented better when integrating + * decoder and tokenizer. + */ + if (outPtr > start && cbuf[outPtr-1] == '\r') { + cbuf[outPtr-1] = '\n'; + } + c = CONVERT_LSEP_TO; + } + } + } else { // (needed == 1) + if (mXml11) { // high-order ctrl char detection... + if (c <= 0x9F) { + if (c == 0x85) { // NEL, let's convert? + c = CONVERT_NEL_TO; + } else if (c >= 0x7F) { // DEL, ctrl chars + int bytePos = mByteCount + inPtr - 1; + int charPos = mCharCount + (outPtr-start); + reportInvalidXml11(c, bytePos, charPos); + } + } + } + } + cbuf[outPtr++] = (char) c; + if (inPtr >= inBufLen) { + break main_loop; + } + } + + mBytePtr = inPtr; + len = outPtr - start; + mCharCount += len; + return len; + } + + /* + //////////////////////////////////////// + // Internal methods + //////////////////////////////////////// + */ + + private void reportInvalidInitial(int mask, int offset) + throws IOException + { + // input (byte) ptr has been advanced by one, by now: + int bytePos = mByteCount + mBytePtr - 1; + int charPos = mCharCount + offset + 1; + + throw new CharConversionException("Invalid UTF-8 start byte 0x" + +Integer.toHexString(mask) + +" (at char #"+charPos+", byte #"+bytePos+")"); + } + + private void reportInvalidOther(int mask, int offset) + throws IOException + { + int bytePos = mByteCount + mBytePtr - 1; + int charPos = mCharCount + offset; + + throw new CharConversionException("Invalid UTF-8 middle byte 0x" + +Integer.toHexString(mask) + +" (at char #"+charPos+", byte #"+bytePos+")"); + } + + private void reportUnexpectedEOF(int gotBytes, int needed) + throws IOException + { + int bytePos = mByteCount + gotBytes; + int charPos = mCharCount; + + throw new CharConversionException("Unexpected EOF in the middle of a multi-byte char: got " + +gotBytes+", needed "+needed + +", at char #"+charPos+", byte #"+bytePos+")"); + } + + private void reportInvalid(int value, int offset, String msg) + throws IOException + { + int bytePos = mByteCount + mBytePtr - 1; + int charPos = mCharCount + offset; + + throw new CharConversionException("Invalid UTF-8 character 0x" + +Integer.toHexString(value)+msg + +" at char #"+charPos+", byte #"+bytePos+")"); + } + + /** + * @param available Number of "unused" bytes in the input buffer + * + * @return True, if enough bytes were read to allow decoding of at least + * one full character; false if EOF was encountered instead. + */ + private boolean loadMore(int available) + throws IOException + { + mByteCount += (mByteBufferEnd - available); + + // Bytes that need to be moved to the beginning of buffer? + if (available > 0) { + /* 11-Nov-2008, TSa: can only move if we own the buffer; otherwise + * we are stuck with the data. + */ + if (mBytePtr > 0 && canModifyBuffer()) { + for (int i = 0; i < available; ++i) { + mByteBuffer[i] = mByteBuffer[mBytePtr+i]; + } + mBytePtr = 0; + mByteBufferEnd = available; + } + } else { + /* Ok; here we can actually reasonably expect an EOF, + * so let's do a separate read right away: + */ + int count = readBytes(); + if (count < 1) { + if (count < 0) { // -1 + freeBuffers(); // to help GC? + return false; + } + // 0 count is no good; let's err out + reportStrangeStream(); + } + } + + /* We now have at least one byte... and that allows us to + * calculate exactly how many bytes we need! + */ + @SuppressWarnings("cast") + int c = (int) mByteBuffer[mBytePtr]; + if (c >= 0) { // single byte (ascii) char... cool, can return + return true; + } + + // Ok, a multi-byte char, let's check how many bytes we'll need: + int needed; + if ((c & 0xE0) == 0xC0) { // 2 bytes (0x0080 - 0x07FF) + needed = 2; + } else if ((c & 0xF0) == 0xE0) { // 3 bytes (0x0800 - 0xFFFF) + needed = 3; + } else if ((c & 0xF8) == 0xF0) { + // 4 bytes; double-char BS, with surrogates and all... + needed = 4; + } else { + reportInvalidInitial(c & 0xFF, 0); + // never gets here... but compiler whines without this: + needed = 1; + } + + /* And then we'll just need to load up to that many bytes; + * if an EOF is hit, that'll be an error. But we need not do + * actual decoding here, just load enough bytes. + */ + while ((mBytePtr + needed) > mByteBufferEnd) { + int count = readBytesAt(mByteBufferEnd); + if (count < 1) { + if (count < 0) { // -1, EOF... no good! + freeBuffers(); + reportUnexpectedEOF(mByteBufferEnd, needed); + } + // 0 count is no good; let's err out + reportStrangeStream(); + } + } + return true; + } +} + diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/io/UTF8Writer.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/io/UTF8Writer.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/io/UTF8Writer.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/io/UTF8Writer.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,423 @@ +package com.ctc.wstx.io; + +import java.io.*; + +import com.ctc.wstx.api.WriterConfig; + +/** + * Specialized buffering UTF-8 writer used by + * {@link com.ctc.wstx.sw.XmlWriter}. + * The main reason for custom version is to allow for efficient + * buffer recycling; the second benefit is that encoder has less + * overhead for short content encoding (compared to JDK default + * codecs). + */ +public final class UTF8Writer + extends Writer + implements CompletelyCloseable +{ + private final static int DEFAULT_BUF_LEN = 4000; + + final static int SURR1_FIRST = 0xD800; + final static int SURR1_LAST = 0xDBFF; + final static int SURR2_FIRST = 0xDC00; + final static int SURR2_LAST = 0xDFFF; + + final WriterConfig mConfig; + + final boolean mAutoCloseOutput; + + final OutputStream mOut; + + byte[] mOutBuffer; + + final int mOutBufferLast; + + int mOutPtr; + + /** + * When outputting chars from BMP, surrogate pairs need to be coalesced. + * To do this, both pairs must be known first; and since it is possible + * pairs may be split, we need temporary storage for the first half + */ + int mSurrogate = 0; + + public UTF8Writer(WriterConfig cfg, OutputStream out, boolean autoclose) + { + mConfig = cfg; + mAutoCloseOutput = autoclose; + mOut = out; + mOutBuffer = (mConfig == null) ? new byte[DEFAULT_BUF_LEN] : cfg.allocFullBBuffer(DEFAULT_BUF_LEN); + /* Max. expansion for a single char (in unmodified UTF-8) is + * 4 bytes (or 3 depending on how you view it -- 4 when recombining + * surrogate pairs) + */ + mOutBufferLast = mOutBuffer.length - 4; + mOutPtr = 0; + } + + /* + //////////////////////////////////////////////////////// + // CompletelyCloseable impl + //////////////////////////////////////////////////////// + */ + + @Override + public void closeCompletely() throws IOException { + _close(true); + } + + /* + //////////////////////////////////////////////////////// + // java.io.Writer implementation + //////////////////////////////////////////////////////// + */ + + /* !!! 30-Nov-2006, TSa: Due to co-variance between Appendable and + * Writer, this would not compile with javac 1.5, in 1.4 mode + * (source and target set to "1.4". Not a huge deal, but since + * the base impl is just fine, no point in overriding it. + */ + /* + public Writer append(char c) + throws IOException + // note: this is a JDK 1.5 method + { + write(c); + return this; + } + */ + + @Override + public void close() throws IOException { + _close(mAutoCloseOutput); + } + + @Override + public void flush() throws IOException + { + if (mOutPtr > 0 && mOutBuffer != null) { + mOut.write(mOutBuffer, 0, mOutPtr); + mOutPtr = 0; + } + mOut.flush(); + } + + @Override + public void write(char[] cbuf) throws IOException + { + write(cbuf, 0, cbuf.length); + } + + @Override + public void write(char[] cbuf, int off, int len) throws IOException + { + if (len < 2) { + if (len == 1) { + write(cbuf[off]); + } + return; + } + + // First: do we have a leftover surrogate to deal with? + if (mSurrogate > 0) { + char second = cbuf[off++]; + --len; + write(_convertSurrogate(second)); + // will have at least one more char + } + + int outPtr = mOutPtr; + byte[] outBuf = mOutBuffer; + int outBufLast = mOutBufferLast; // has 4 'spare' bytes + + // All right; can just loop it nice and easy now: + len += off; // len will now be the end of input buffer + + output_loop: + for (; off < len; ) { + /* First, let's ensure we can output at least 4 bytes + * (longest UTF-8 encoded codepoint): + */ + if (outPtr >= outBufLast) { + mOut.write(outBuf, 0, outPtr); + outPtr = 0; + } + + int c = cbuf[off++]; + // And then see if we have an Ascii char: + if (c < 0x80) { // If so, can do a tight inner loop: + outBuf[outPtr++] = (byte)c; + // Let's calc how many ascii chars we can copy at most: + int maxInCount = (len - off); + int maxOutCount = (outBufLast - outPtr); + + if (maxInCount > maxOutCount) { + maxInCount = maxOutCount; + } + maxInCount += off; + ascii_loop: + while (true) { + if (off >= maxInCount) { // done with max. ascii seq + continue output_loop; + } + c = cbuf[off++]; + if (c >= 0x80) { + break ascii_loop; + } + outBuf[outPtr++] = (byte) c; + } + } + + // Nope, multi-byte: + if (c < 0x800) { // 2-byte + outBuf[outPtr++] = (byte) (0xc0 | (c >> 6)); + outBuf[outPtr++] = (byte) (0x80 | (c & 0x3f)); + } else { // 3 or 4 bytes + // Surrogates? + if (c < SURR1_FIRST || c > SURR2_LAST) { + outBuf[outPtr++] = (byte) (0xe0 | (c >> 12)); + outBuf[outPtr++] = (byte) (0x80 | ((c >> 6) & 0x3f)); + outBuf[outPtr++] = (byte) (0x80 | (c & 0x3f)); + continue; + } + // Yup, a surrogate: + if (c > SURR1_LAST) { // must be from first range + mOutPtr = outPtr; + throwIllegal(c); + } + mSurrogate = c; + // and if so, followed by another from next range + if (off >= len) { // unless we hit the end? + break; + } + c = _convertSurrogate(cbuf[off++]); + if (c > 0x10FFFF) { // illegal, as per RFC 3629 + mOutPtr = outPtr; + throwIllegal(c); + } + outBuf[outPtr++] = (byte) (0xf0 | (c >> 18)); + outBuf[outPtr++] = (byte) (0x80 | ((c >> 12) & 0x3f)); + outBuf[outPtr++] = (byte) (0x80 | ((c >> 6) & 0x3f)); + outBuf[outPtr++] = (byte) (0x80 | (c & 0x3f)); + } + } + mOutPtr = outPtr; + } + + @Override + public void write(int c) throws IOException + { + // First; do we have a left over surrogate? + if (mSurrogate > 0) { + c = _convertSurrogate(c); + // If not, do we start with a surrogate? + } else if (c >= SURR1_FIRST && c <= SURR2_LAST) { + // Illegal to get second part without first: + if (c > SURR1_LAST) { + throwIllegal(c); + } + // First part just needs to be held for now + mSurrogate = c; + return; + } + + if (mOutPtr >= mOutBufferLast) { // let's require enough room, first + mOut.write(mOutBuffer, 0, mOutPtr); + mOutPtr = 0; + } + + if (c < 0x80) { // ascii + mOutBuffer[mOutPtr++] = (byte) c; + } else { + int ptr = mOutPtr; + if (c < 0x800) { // 2-byte + mOutBuffer[ptr++] = (byte) (0xc0 | (c >> 6)); + mOutBuffer[ptr++] = (byte) (0x80 | (c & 0x3f)); + } else if (c <= 0xFFFF) { // 3 bytes + mOutBuffer[ptr++] = (byte) (0xe0 | (c >> 12)); + mOutBuffer[ptr++] = (byte) (0x80 | ((c >> 6) & 0x3f)); + mOutBuffer[ptr++] = (byte) (0x80 | (c & 0x3f)); + } else { // 4 bytes + if (c > 0x10FFFF) { // illegal, as per RFC 3629 + throwIllegal(c); + } + mOutBuffer[ptr++] = (byte) (0xf0 | (c >> 18)); + mOutBuffer[ptr++] = (byte) (0x80 | ((c >> 12) & 0x3f)); + mOutBuffer[ptr++] = (byte) (0x80 | ((c >> 6) & 0x3f)); + mOutBuffer[ptr++] = (byte) (0x80 | (c & 0x3f)); + } + mOutPtr = ptr; + } + } + + @Override + public void write(String str) throws IOException + { + write(str, 0, str.length()); + } + + @Override + public void write(String str, int off, int len) throws IOException + { + if (len < 2) { + if (len == 1) { + write(str.charAt(off)); + } + return; + } + + // First: do we have a leftover surrogate to deal with? + if (mSurrogate > 0) { + char second = str.charAt(off++); + --len; + write(_convertSurrogate(second)); + // will have at least one more char (case of 1 char was checked earlier on) + } + + int outPtr = mOutPtr; + byte[] outBuf = mOutBuffer; + int outBufLast = mOutBufferLast; // has 4 'spare' bytes + + // All right; can just loop it nice and easy now: + len += off; // len will now be the end of input buffer + + output_loop: + for (; off < len; ) { + /* First, let's ensure we can output at least 4 bytes + * (longest UTF-8 encoded codepoint): + */ + if (outPtr >= outBufLast) { + mOut.write(outBuf, 0, outPtr); + outPtr = 0; + } + + int c = str.charAt(off++); + // And then see if we have an Ascii char: + if (c < 0x80) { // If so, can do a tight inner loop: + outBuf[outPtr++] = (byte)c; + // Let's calc how many ascii chars we can copy at most: + int maxInCount = (len - off); + int maxOutCount = (outBufLast - outPtr); + + if (maxInCount > maxOutCount) { + maxInCount = maxOutCount; + } + maxInCount += off; + ascii_loop: + while (true) { + if (off >= maxInCount) { // done with max. ascii seq + continue output_loop; + } + c = str.charAt(off++); + if (c >= 0x80) { + break ascii_loop; + } + outBuf[outPtr++] = (byte) c; + } + } + + // Nope, multi-byte: + if (c < 0x800) { // 2-byte + outBuf[outPtr++] = (byte) (0xc0 | (c >> 6)); + outBuf[outPtr++] = (byte) (0x80 | (c & 0x3f)); + } else { // 3 or 4 bytes + // Surrogates? + if (c < SURR1_FIRST || c > SURR2_LAST) { + outBuf[outPtr++] = (byte) (0xe0 | (c >> 12)); + outBuf[outPtr++] = (byte) (0x80 | ((c >> 6) & 0x3f)); + outBuf[outPtr++] = (byte) (0x80 | (c & 0x3f)); + continue; + } + // Yup, a surrogate: + if (c > SURR1_LAST) { // must be from first range + mOutPtr = outPtr; + throwIllegal(c); + } + mSurrogate = c; + // and if so, followed by another from next range + if (off >= len) { // unless we hit the end? + break; + } + c = _convertSurrogate(str.charAt(off++)); + if (c > 0x10FFFF) { // illegal, as per RFC 3629 + mOutPtr = outPtr; + throwIllegal(c); + } + outBuf[outPtr++] = (byte) (0xf0 | (c >> 18)); + outBuf[outPtr++] = (byte) (0x80 | ((c >> 12) & 0x3f)); + outBuf[outPtr++] = (byte) (0x80 | ((c >> 6) & 0x3f)); + outBuf[outPtr++] = (byte) (0x80 | (c & 0x3f)); + } + } + mOutPtr = outPtr; + } + + /* + //////////////////////////////////////////////////////////// + // Internal methods + //////////////////////////////////////////////////////////// + */ + + private final void _close(boolean forceClosing) + throws IOException + { + byte[] buf = mOutBuffer; + if (buf != null) { + mOutBuffer = null; + if (mOutPtr > 0) { + mOut.write(buf, 0, mOutPtr); + mOutPtr = 0; + } + if (mConfig != null) { + mConfig.freeFullBBuffer(buf); + } + } + + if (forceClosing) { + mOut.close(); + } + + /* Let's 'flush' orphan surrogate, no matter what; but only + * after cleanly closing everything else. + */ + int code = mSurrogate; + if (code > 0) { + mSurrogate = 0; + throwIllegal(code); + } + } + + /** + * Method called to calculate UTF codepoint, from a surrogate pair. + */ + private final int _convertSurrogate(int secondPart) + throws IOException + { + int firstPart = mSurrogate; + mSurrogate = 0; + + // Ok, then, is the second part valid? + if (secondPart < SURR2_FIRST || secondPart > SURR2_LAST) { + throw new IOException("Broken surrogate pair: first char 0x"+Integer.toHexString(firstPart)+", second 0x"+Integer.toHexString(secondPart)+"; illegal combination"); + } + return 0x10000 + ((firstPart - SURR1_FIRST) << 10) + (secondPart - SURR2_FIRST); + } + + private void throwIllegal(int code) + throws IOException + { + if (code > 0x10FFFF) { // over max? + throw new IOException("Illegal character point (0x"+Integer.toHexString(code)+") to output; max is 0x10FFFF as per RFC 3629"); + } + if (code >= SURR1_FIRST) { + if (code <= SURR1_LAST) { // Unmatched first part (closing without second part?) + throw new IOException("Unmatched first part of surrogate pair (0x"+Integer.toHexString(code)+")"); + } + throw new IOException("Unmatched second part of surrogate pair (0x"+Integer.toHexString(code)+")"); + } + + // should we ever get this? + throw new IOException("Illegal character point (0x"+Integer.toHexString(code)+") to output"); + } +} diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/io/WstxInputData.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/io/WstxInputData.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/io/WstxInputData.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/io/WstxInputData.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,470 @@ +/* Woodstox XML processor + * + * Copyright (c) 2004 Tatu Saloranta, tatu.saloranta@iki.fi + * + * Licensed under the License specified in file LICENSE, included with + * the source code. + * You may not use this file except in compliance with the License. + * + * 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 com.ctc.wstx.io; + +import com.ctc.wstx.util.XmlChars; + +/** + * Base class used by readers (specifically, by + * {@link com.ctc.wstx.sr.StreamScanner}, and its sub-classes) + * to encapsulate input buffer portion of the class. Philosophically + * this should probably be done via containment (composition), not + * sub-classing but for performance reason, this "core" class is generally + * extended from instead. + *

+ * Main reason for the input data portion to be factored out of main + * class is that this way it can also be passed to nested input handling + * Objects, which can then manipulate input buffers of the caller, + * efficiently. + */ +public class WstxInputData +{ + // // // Some well-known chars: + + /** + * Null-character is used as return value from some method(s), since + * it is not a legal character in an XML document. + */ + public final static char CHAR_NULL = '\u0000'; + public final static char INT_NULL = 0; + + public final static char CHAR_SPACE = (char) 0x0020; + public final static char INT_SPACE = 0x0020; + + /** + * This constant defines the highest Unicode character allowed + * in XML content. + */ + public final static int MAX_UNICODE_CHAR = 0x10FFFF; + + /* + //////////////////////////////////////////////////// + // Character validity constants, structs + //////////////////////////////////////////////////// + */ + + /** + * We will only use validity array for first 256 characters, mostly + * because after those characters it's easier to do fairly simple + * block checks. + */ + private final static int VALID_CHAR_COUNT = 0x100; + + // These are the same for both 1.0 and 1.1... +// private final static int FIRST_VALID_FOR_FIRST = 0x0041; // 'A' +// private final static int FIRST_VALID_FOR_REST = 0x002D; // '.' + + private final static byte NAME_CHAR_INVALID_B = (byte) 0; + private final static byte NAME_CHAR_ALL_VALID_B = (byte) 1; + private final static byte NAME_CHAR_VALID_NONFIRST_B = (byte) -1; + + private final static byte[] sCharValidity = new byte[VALID_CHAR_COUNT]; + + static { + /* First, since all valid-as-first chars are also valid-as-other chars, + * we'll initialize common chars: + */ + sCharValidity['_'] = NAME_CHAR_ALL_VALID_B; + for (int i = 0, last = ('z' - 'a'); i <= last; ++i) { + sCharValidity['A' + i] = NAME_CHAR_ALL_VALID_B; + sCharValidity['a' + i] = NAME_CHAR_ALL_VALID_B; + } + // not all are fully valid, but + for (int i = 0xC0; i < VALID_CHAR_COUNT; ++i) { + sCharValidity[i] = NAME_CHAR_ALL_VALID_B; + } + // ... now we can 'revert' ones not fully valid: + sCharValidity[0xD7] = NAME_CHAR_INVALID_B; + sCharValidity[0xF7] = NAME_CHAR_INVALID_B; + + /* And then we can proceed with ones only valid-as-other. + */ + sCharValidity['-'] = NAME_CHAR_VALID_NONFIRST_B; + sCharValidity['.'] = NAME_CHAR_VALID_NONFIRST_B; + sCharValidity[0xB7] = NAME_CHAR_VALID_NONFIRST_B; + for (int i = '0'; i <= '9'; ++i) { + sCharValidity[i] = NAME_CHAR_VALID_NONFIRST_B; + } + } + + /** + * Public identifiers only use 7-bit ascii range. + */ + private final static int VALID_PUBID_CHAR_COUNT = 0x80; + private final static byte[] sPubidValidity = new byte[VALID_PUBID_CHAR_COUNT]; +// private final static byte PUBID_CHAR_INVALID_B = (byte) 0; + private final static byte PUBID_CHAR_VALID_B = (byte) 1; + static { + for (int i = 0, last = ('z' - 'a'); i <= last; ++i) { + sPubidValidity['A' + i] = PUBID_CHAR_VALID_B; + sPubidValidity['a' + i] = PUBID_CHAR_VALID_B; + } + for (int i = '0'; i <= '9'; ++i) { + sPubidValidity[i] = PUBID_CHAR_VALID_B; + } + + // 3 main white space types are valid + sPubidValidity[0x0A] = PUBID_CHAR_VALID_B; + sPubidValidity[0x0D] = PUBID_CHAR_VALID_B; + sPubidValidity[0x20] = PUBID_CHAR_VALID_B; + + // And many of punctuation/separator ascii chars too: + sPubidValidity['-'] = PUBID_CHAR_VALID_B; + sPubidValidity['\''] = PUBID_CHAR_VALID_B; + sPubidValidity['('] = PUBID_CHAR_VALID_B; + sPubidValidity[')'] = PUBID_CHAR_VALID_B; + sPubidValidity['+'] = PUBID_CHAR_VALID_B; + sPubidValidity[','] = PUBID_CHAR_VALID_B; + sPubidValidity['.'] = PUBID_CHAR_VALID_B; + sPubidValidity['/'] = PUBID_CHAR_VALID_B; + sPubidValidity[':'] = PUBID_CHAR_VALID_B; + sPubidValidity['='] = PUBID_CHAR_VALID_B; + sPubidValidity['?'] = PUBID_CHAR_VALID_B; + sPubidValidity[';'] = PUBID_CHAR_VALID_B; + sPubidValidity['!'] = PUBID_CHAR_VALID_B; + sPubidValidity['*'] = PUBID_CHAR_VALID_B; + sPubidValidity['#'] = PUBID_CHAR_VALID_B; + sPubidValidity['@'] = PUBID_CHAR_VALID_B; + sPubidValidity['$'] = PUBID_CHAR_VALID_B; + sPubidValidity['_'] = PUBID_CHAR_VALID_B; + sPubidValidity['%'] = PUBID_CHAR_VALID_B; + } + + /* + //////////////////////////////////////////////////// + // Configuration + //////////////////////////////////////////////////// + */ + + /** + * Flag that indicates whether XML content is to be treated as per + * XML 1.1 specification or not (if not, it'll use xml 1.0). + */ + protected boolean mXml11 = false; + + /* + //////////////////////////////////////////////////// + // Current input data + //////////////////////////////////////////////////// + */ + + /** + * Current buffer from which data is read; generally data is read into + * buffer from input source, but not always (especially when using nested + * input contexts when expanding parsed entity references etc). + */ + protected char[] mInputBuffer; + + /** + * Pointer to next available character in buffer + */ + protected int mInputPtr = 0; + + /** + * Index of character after last available one in the buffer. + */ + protected int mInputEnd = 0; + + /* + //////////////////////////////////////////////////// + // Current input location information + //////////////////////////////////////////////////// + */ + + /** + * Number of characters that were contained in previous blocks + * (blocks that were already processed prior to the current buffer). + */ + protected long mCurrInputProcessed = 0L; + + /** + * Current row location of current point in input buffer, starting + * from 1 + */ + protected int mCurrInputRow = 1; + + /** + * Current index of the first character of the current row in input + * buffer. Needed to calculate column position, if necessary; benefit + * of not having column itself is that this only has to be updated + * once per line. + */ + protected int mCurrInputRowStart = 0; + + /* + //////////////////////////////////////////////////// + // Life-cycle + //////////////////////////////////////////////////// + */ + + protected WstxInputData() { + } + + /** + * Note: Only public due to sub-classes needing to call this on + * base class instance from different package (confusing?) + */ + public void copyBufferStateFrom(WstxInputData src) + { + mInputBuffer = src.mInputBuffer; + mInputPtr = src.mInputPtr; + mInputEnd = src.mInputEnd; + + mCurrInputProcessed = src.mCurrInputProcessed; + mCurrInputRow = src.mCurrInputRow; + mCurrInputRowStart = src.mCurrInputRowStart; + } + + /* + //////////////////////////////////////////////////// + // Public/package API, character classes + //////////////////////////////////////////////////// + */ + + /** + * Method that can be used to check whether specified character + * is a valid first character of an XML 1.0/1.1 name; except that + * colon (:) is not recognized as a start char here: caller has + * to verify it separately (since it generally affects namespace + * mapping of a qualified name). + */ + protected final boolean isNameStartChar(char c) + { + /* First, let's handle 7-bit ascii range (identical between xml + * 1.0 and 1.1) + */ + if (c <= 0x7A) { // 'z' or earlier + if (c >= 0x61) { // 'a' - 'z' are ok + return true; + } + if (c < 0x41) { // before 'A' just white space + return false; + } + return (c <= 0x5A) || (c == '_'); // 'A' - 'Z' and '_' are ok + } + /* Ok, otherwise need to use a big honking bit sets... which + * differ between 1.0 and 1.1 + */ + return mXml11 ? XmlChars.is11NameStartChar(c) : XmlChars.is10NameStartChar(c); + } + + /** + * Method that can be used to check whether specified character + * is a valid character of an XML 1.0/1.1 name as any other char than + * the first one; except that colon (:) is not recognized as valid here: + * caller has to verify it separately (since it generally affects namespace + * mapping of a qualified name). + */ + protected final boolean isNameChar(char c) + { + // First, let's handle 7-bit ascii range + if (c <= 0x7A) { // 'z' or earlier + if (c >= 0x61) { // 'a' - 'z' are ok + return true; + } + if (c <= 0x5A) { + if (c >= 0x41) { // 'A' - 'Z' ok too + return true; + } + // As are 0-9, '.' and '-' + return (c >= 0x30 && c <= 0x39) || (c == '.') || (c == '-'); + } + return (c == 0x5F); // '_' is ok too + } + return mXml11 ? XmlChars.is11NameChar(c) : XmlChars.is10NameChar(c); + } + + public final static boolean isNameStartChar(char c, boolean nsAware, boolean xml11) + { + /* First, let's handle 7-bit ascii range (identical between xml + * 1.0 and 1.1) + */ + if (c <= 0x7A) { // 'z' or earlier + if (c >= 0x61) { // 'a' - 'z' are ok + return true; + } + if (c < 0x41) { // before 'A' just white space (and colon) + if (c == ':' && !nsAware) { + return true; + } + return false; + } + return (c <= 0x5A) || (c == '_'); // 'A' - 'Z' and '_' are ok + } + /* Ok, otherwise need to use a big honking bit sets... which + * differ between 1.0 and 1.1 + */ + return xml11 ? XmlChars.is11NameStartChar(c) : XmlChars.is10NameStartChar(c); + } + + public final static boolean isNameChar(char c, boolean nsAware, boolean xml11) + { + // First, let's handle 7-bit ascii range + if (c <= 0x7A) { // 'z' or earlier + if (c >= 0x61) { // 'a' - 'z' are ok + return true; + } + if (c <= 0x5A) { + if (c >= 0x41) { // 'A' - 'Z' ok too + return true; + } + // As are 0-9, '.' and '-' + return (c >= 0x30 && c <= 0x39) || (c == '.') || (c == '-') + || (c == ':' && !nsAware); + } + return (c == 0x5F); // '_' is ok too + } + return xml11 ? XmlChars.is11NameChar(c) : XmlChars.is10NameChar(c); + } + + /** + * Method that can be called to check whether given String contains + * any characters that are not legal XML names. + * + * @return Index of the first illegal xml name characters, if any; + * -1 if the name is completely legal + */ + public final static int findIllegalNameChar(String name, boolean nsAware, boolean xml11) + { + int len = name.length(); + if (len < 1) { + return -1; + } + + char c = name.charAt(0); + + // First char legal? + if (c <= 0x7A) { // 'z' or earlier + if (c < 0x61) { // 'a' - 'z' (0x61 - 0x7A) are ok + if (c < 0x41) { // before 'A' just white space (except colon) + if (c != ':' || nsAware) { // ':' == 0x3A + return 0; + } + } else if ((c > 0x5A) && (c != '_')) { + // 'A' - 'Z' and '_' are ok + return 0; + } + } + } else { + if (xml11) { + if (!XmlChars.is11NameStartChar(c)) { + return 0; + } + } else { + if (!XmlChars.is10NameStartChar(c)) { + return 0; + } + } + } + + for (int i = 1; i < len; ++i) { + c = name.charAt(i); + if (c <= 0x7A) { // 'z' or earlier + if (c >= 0x61) { // 'a' - 'z' are ok + continue; + } + if (c <= 0x5A) { + if (c >= 0x41) { // 'A' - 'Z' ok too + continue; + } + // As are 0-9, '.' and '-' + if ((c >= 0x30 && c <= 0x39) || (c == '.') || (c == '-')) { + continue; + } + // And finally, colon, in non-ns-aware mode + if (c == ':' && !nsAware) { // ':' == 0x3A + continue; + } + } else if (c == 0x5F) { // '_' is ok too + continue; + } + } else { + if (xml11) { + if (XmlChars.is11NameChar(c)) { + continue; + } + } else { + if (XmlChars.is10NameChar(c)) { + continue; + } + } + } + return i; + } + + return -1; + } + + public final static int findIllegalNmtokenChar(String nmtoken, boolean nsAware, boolean xml11) + { + int len = nmtoken.length(); + // No special handling for the first char, just the loop + for (int i = 1; i < len; ++i) { + char c = nmtoken.charAt(i); + if (c <= 0x7A) { // 'z' or earlier + if (c >= 0x61) { // 'a' - 'z' are ok + continue; + } + if (c <= 0x5A) { + if (c >= 0x41) { // 'A' - 'Z' ok too + continue; + } + // As are 0-9, '.' and '-' + if ((c >= 0x30 && c <= 0x39) || (c == '.') || (c == '-')) { + continue; + } + // And finally, colon, in non-ns-aware mode + if (c == ':' && !nsAware) { // ':' == 0x3A + continue; + } + } else if (c == 0x5F) { // '_' is ok too + continue; + } + } else { + if (xml11) { + if (XmlChars.is11NameChar(c)) { + continue; + } + } else { + if (XmlChars.is10NameChar(c)) { + continue; + } + } + } + return i; + } + return -1; + } + + public final static boolean isSpaceChar(char c) + { + return (c <= CHAR_SPACE); + } + + @SuppressWarnings("cast") + public static String getCharDesc(char c) + { + int i = (int) c; + if (Character.isISOControl(c)) { + return "(CTRL-CHAR, code "+i+")"; + } + if (i > 255) { + return "'"+c+"' (code "+i+" / 0x"+Integer.toHexString(i)+")"; + } + return "'"+c+"' (code "+i+")"; + } + +} diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/io/WstxInputLocation.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/io/WstxInputLocation.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/io/WstxInputLocation.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/io/WstxInputLocation.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,199 @@ +/* Woodstox XML processor + * + * Copyright (c) 2004 Tatu Saloranta, tatu.saloranta@iki.fi + * + * Licensed under the License specified in file LICENSE, included with + * the source code. + * You may not use this file except in compliance with the License. + * + * 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 com.ctc.wstx.io; + +import java.io.Serializable; + +import javax.xml.stream.Location; + +import org.codehaus.stax2.XMLStreamLocation2; + +import com.ctc.wstx.util.StringUtil; + +/** + * Basic implementation of {@link Location}, used by Wstx readers. + */ +public class WstxInputLocation + implements Serializable, XMLStreamLocation2 +{ + private static final long serialVersionUID = 1L; + + private final static WstxInputLocation sEmptyLocation + = new WstxInputLocation(null, "", "", -1, -1, -1); + + /** + * Enclosing (parent) input location; location from which current + * location is derived. + */ + final protected WstxInputLocation mContext; + + final protected String mPublicId, mSystemId; + + final protected long mCharOffset; + final protected int mCol, mRow; + + transient protected String mDesc = null; + + /** + * @param ctxt Enclosing input location, if any + */ + public WstxInputLocation(WstxInputLocation ctxt, + String pubId, String sysId, + long charOffset, int row, int col) + { + mContext = ctxt; + mPublicId = pubId; + mSystemId = sysId; + /* Overflow? Can obviously only handle limited range of overflows, + * but let's do that at least? + */ + mCharOffset = charOffset; + mCol = col; + mRow = row; + } + + public WstxInputLocation(WstxInputLocation ctxt, + String pubId, SystemId sysId, long charOffset, int row, int col) + { + mContext = ctxt; + mPublicId = pubId; + mSystemId = (sysId == null) ? "N/A" : sysId.toString(); + mCharOffset = charOffset; + mCol = col; + mRow = row; + } + + public static WstxInputLocation getEmptyLocation() { + return sEmptyLocation; + } + + public long getCharacterOffsetLong() { return mCharOffset; } + + @Override + public int getCharacterOffset() { return (int)mCharOffset; } + @Override + public int getColumnNumber() { return mCol; } + @Override + public int getLineNumber() { return mRow; } + + @Override + public String getPublicId() { return mPublicId; } + @Override + public String getSystemId() { return mSystemId; } + + /* + //////////////////////////////////////////////////////// + // StAX 2 API: + //////////////////////////////////////////////////////// + */ + + @Override + public XMLStreamLocation2 getContext() { return mContext; } + + /* + //////////////////////////////////////////////////////// + // Overridden standard methods + //////////////////////////////////////////////////////// + */ + + @Override + public String toString() + { + if (mDesc == null) { + StringBuilder sb; + if (mContext != null) { + sb = new StringBuilder(200); + } else { + sb = new StringBuilder(80); + } + appendDesc(sb); + mDesc = sb.toString(); + } + return mDesc; + } + + @Override + public int hashCode() { + return ((int)mCharOffset) ^ (int)(0xffffffff & mCharOffset >> 32) ^ mRow ^ mCol + (mCol << 3); + } + + @Override + public boolean equals(Object o) { + if (!(o instanceof WstxInputLocation)) { + return false; + } + WstxInputLocation other = (WstxInputLocation) o; + // char offset should be good enough, without row/col: + if (other.getCharacterOffsetLong() != getCharacterOffsetLong()) { + return false; + } + String otherPub = other.getPublicId(); + if (otherPub == null) { + otherPub = ""; + } + if (!otherPub.equals(mPublicId)) { + return false; + } + String otherSys = other.getSystemId(); + if (otherSys == null) { + otherSys = ""; + } + return otherSys.equals(mSystemId); + } + + /* + //////////////////////////////////////////////////////// + // Internal methods: + //////////////////////////////////////////////////////// + */ + + private void appendDesc(StringBuilder sb) + { + String srcId; + + if (mSystemId != null) { + sb.append("[row,col,system-id]: "); + srcId = mSystemId; + } else if (mPublicId != null) { + sb.append("[row,col,public-id]: "); + srcId = mPublicId; + } else { + sb.append("[row,col {unknown-source}]: "); + srcId = null; + } + sb.append('['); + sb.append(mRow); + sb.append(','); + sb.append(mCol); + + // Uncomment for testing, to see the char offset: + //sb.append(" #").append(mCharOffset); + //sb.append("{").append(System.identityHashCode(this)).append("}"); + + if (srcId != null) { + sb.append(','); + sb.append('"'); + sb.append(srcId); + sb.append('"'); + } + sb.append(']'); + if (mContext != null) { + StringUtil.appendLF(sb); + sb.append(" from "); + mContext.appendDesc(sb); + } + } +} diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/io/WstxInputSource.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/io/WstxInputSource.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/io/WstxInputSource.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/io/WstxInputSource.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,248 @@ +/* Woodstox XML processor + * + * Copyright (c) 2004- Tatu Saloranta, tatu.saloranta@iki.fi + * + * Licensed under the License specified in file LICENSE, included with + * the source code. + * You may not use this file except in compliance with the License. + * + * 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 com.ctc.wstx.io; + +import java.io.IOException; +import java.net.URL; + +import javax.xml.stream.XMLStreamException; + +/** + * Interface that defines API actual parsers (stream readers) + * can use to read input from various input sources. + * Needed to abstract out details of getting input from primary input + * files, secondary (potentially cached) referenced documents, and from + * parsed entities, as well as for allowing hierarchic location + * information for error reporting. + */ +public abstract class WstxInputSource +{ + /** + * Parent in input source stack + */ + protected final WstxInputSource mParent; + + /** + * Name/id of the entity that was expanded to produce this input source; + * null if not entity-originated. Used for catching recursive expansions + * of entities. + */ + protected final String mFromEntity; + + /** + * Scope of the reader when this entity was initially expanded. Snapshot + * that will generally be used by the reader to match scoping + * limitations, such as proper nesting entity expansion with respect + * to element and declaration nesting. + */ + protected int mScopeId = 0; + + /** + * Number of parent entities that have been expanded to get to this + * input source; 0 for root-level input that is not generated via + * entity expansion. + */ + protected int mEntityDepth; + + /* + ////////////////////////////////////////////////////////// + // Life-cycle: + ////////////////////////////////////////////////////////// + */ + + protected WstxInputSource(WstxInputSource parent, String fromEntity) + { + mParent = parent; + mFromEntity = fromEntity; + } + + /** + * Method that can be called to override originally defined source. + * + * @param url New base URL to set; may be null. + * + * @since 4.0 + */ + public abstract void overrideSource(URL url); + + /* + ////////////////////////////////////////////////////////// + // Basic accessors: + ////////////////////////////////////////////////////////// + */ + + public final WstxInputSource getParent() { + return mParent; + } + + /** + * Method that checks if this input source expanded from the specified + * entity id, directly or by ancestor. + *

+ * Note that entity ids are expected to have been interned (using + * whatever uniqueness mechanism used), and thus can be simply + * identity checked. + */ + public boolean isOrIsExpandedFrom(String entityId) + { + if (entityId != null) { // should always be true + WstxInputSource curr = this; + while (curr != null) { + if (entityId == curr.mFromEntity) { + return true; + } + curr = curr.mParent; + } + } + return false; + } + + /** + * @return True, if this input source was directly expanded from an + * internal entity (general, parsed); false if not (from external + * entity, DTD ext. subset, main document) + */ + public abstract boolean fromInternalEntity(); + + /* + ////////////////////////////////////////////////////////// + // Location info: + ////////////////////////////////////////////////////////// + */ + + public abstract URL getSource() throws IOException; + + public abstract String getPublicId(); + + public abstract String getSystemId(); + + /** + * Method usually called to get a parent location for another input + * source. Works since at this point context (line, row, chars) information + * has already been saved to this object. + */ + protected abstract WstxInputLocation getLocation(); + + public abstract WstxInputLocation getLocation(long total, int row, int col); + + public String getEntityId() { return mFromEntity; } + + public int getScopeId() { return mScopeId; } + + public int getEntityDepth() { return mEntityDepth; } + + /* + ////////////////////////////////////////////////////////// + // Actual input handling + ////////////////////////////////////////////////////////// + */ + + /** + * Method called by Reader when current input has changed to come + * from this input source. Should reset/initialize input location + * information Reader keeps, for error messages to work ok. + * + * @param reader Reader whose data structures are to be used for + * returning data read + * @param currScopeId + */ + public final void initInputLocation(WstxInputData reader, int currScopeId, + int entityDepth) { + mScopeId = currScopeId; + mEntityDepth = entityDepth; + doInitInputLocation(reader); + } + + protected abstract void doInitInputLocation(WstxInputData reader); + + /** + * Method called to read at least one more char from input source, and + * update input data appropriately. + * + * @return Number of characters read from the input source (at least 1), + * if it had any input; -1 if input source has no more input. + */ + public abstract int readInto(WstxInputData reader) + throws IOException, XMLStreamException; + + /** + * Method called by reader when it has to have at least specified number + * of consequtive input characters in its buffer, and it currently does + * not have. If so, it asks input source to do whatever it has to do + * to try to get more data, if possible (including moving stuff in + * input buffer if necessary and possible). + * + * @return True if input source was able to provide specific number of + * characters or more; false if not. In latter case, source is free + * to return zero or more characters any way. + */ + public abstract boolean readMore(WstxInputData reader, int minAmount) + throws IOException, XMLStreamException; + + /** + * Method Reader calls when this input source is being stored, when + * a nested input source gets used instead (due to entity expansion). + * Needs to get location info from Reader and store it in this Object. + */ + public abstract void saveContext(WstxInputData reader); + + /** + * Method Reader calls when this input source is resumed as the + * current source. Needs to update Reader's input location data + * used for error messages etc. + */ + public abstract void restoreContext(WstxInputData reader); + + /** + * Method reader calls for this input source when it has encountered + * EOF. This may or may not close the underlying stream/reader; what + * happens depends on configuration + */ + public abstract void close() throws IOException; + + /** + * Method reader MAY call to force full closing of the underlying + * input stream(s)/reader(s). No checks are done regarding configuration, + * but input source object is to deal gracefully with multiple calls + * (ie. it's not an error for reader to call this more than once). + */ + public abstract void closeCompletely() throws IOException; + + /* + ////////////////////////////////////////////////////////// + // Overridden standard methods: + ////////////////////////////////////////////////////////// + */ + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(80); + sb.append("'); + return sb.toString(); + } +} diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/msv/AttributeProxy.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/msv/AttributeProxy.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/msv/AttributeProxy.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/msv/AttributeProxy.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,146 @@ +/* Woodstox XML processor + * + * Copyright (c) 2004- Tatu Saloranta, tatu.saloranta@iki.fi + * + * Licensed under the License specified in the file LICENSE which is + * included with the source code. + * You may not use this file except in compliance with the License. + * + * 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 com.ctc.wstx.msv; + +import org.codehaus.stax2.validation.ValidationContext; + +/** + * This is an implementation of SAX Attributes interface, that proxies + * requests to the {@link ValidationContext}. + * It is needed by some MSV components (specifically, W3C Schema Validator) + * for limited access to attribute values during start element validation. + */ +final class AttributeProxy + implements org.xml.sax.Attributes +{ + private final ValidationContext mContext; + + public AttributeProxy(ValidationContext ctxt) + { + mContext = ctxt; + } + + /* + /////////////////////////////////////////////// + // Attributes implementation + /////////////////////////////////////////////// + */ + + @Override + public int getIndex(String qName) + { + int cix = qName.indexOf(':'); + int acount = mContext.getAttributeCount(); + if (cix < 0) { // no prefix + for (int i = 0; i < acount; ++i) { + if (qName.equals(mContext.getAttributeLocalName(i))) { + String prefix = mContext.getAttributePrefix(i); + if (prefix == null || prefix.length() == 0) { + return i; + } + } + } + } else { + String prefix = qName.substring(0, cix); + String ln = qName.substring(cix+1); + + for (int i = 0; i < acount; ++i) { + if (ln.equals(mContext.getAttributeLocalName(i))) { + String p2 = mContext.getAttributePrefix(i); + if (p2 != null && prefix.equals(p2)) { + return i; + } + } + } + } + return -1; + } + + @Override + public int getIndex(String uri, String localName) { + return mContext.findAttributeIndex(uri, localName); + } + + @Override + public int getLength() { + return mContext.getAttributeCount(); + } + + @Override + public String getLocalName(int index) { + return mContext.getAttributeLocalName(index); + } + + @Override + public String getQName(int index) + { + String prefix = mContext.getAttributePrefix(index); + String ln = mContext.getAttributeLocalName(index); + + if (prefix == null || prefix.length() == 0) { + return ln; + } + StringBuilder sb = new StringBuilder(prefix.length() + 1 + ln.length()); + sb.append(prefix); + sb.append(':'); + sb.append(ln); + return sb.toString(); + } + + @Override + public String getType(int index) + { + return mContext.getAttributeType(index); + } + + @Override + public String getType(String qName) + { + return getType(getIndex(qName)); + } + + @Override + public String getType(String uri, String localName) + { + return getType(getIndex(uri, localName)); + } + + @Override + public String getURI(int index) + { + return mContext.getAttributeNamespace(index); + } + + @Override + public String getValue(int index) + { + return mContext.getAttributeValue(index); + } + + @Override + public String getValue(String qName) + { + return getValue(getIndex(qName)); + } + + @Override + public String getValue(String uri, String localName) + { + return mContext.getAttributeValue(uri, localName); + } +} + + diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/msv/BaseSchemaFactory.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/msv/BaseSchemaFactory.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/msv/BaseSchemaFactory.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/msv/BaseSchemaFactory.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,182 @@ +/* Woodstox XML processor + * + * Copyright (c) 2004- Tatu Saloranta, tatu.saloranta@iki.fi + * + * Licensed under the License specified in the file LICENSE which is + * included with the source code. + * You may not use this file except in compliance with the License. + * + * 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 com.ctc.wstx.msv; + +import java.io.*; +import java.net.URL; + +import javax.xml.parsers.SAXParserFactory; +import javax.xml.stream.*; + +import org.xml.sax.InputSource; +import org.xml.sax.Locator; +import org.codehaus.stax2.validation.*; + +import com.ctc.wstx.api.ValidatorConfig; +import com.ctc.wstx.exc.WstxIOException; +import com.ctc.wstx.util.URLUtil; + +/** + * Shared base class extended by concrete schema factory implementations. + */ +public abstract class BaseSchemaFactory + extends XMLValidationSchemaFactory +{ + protected static SAXParserFactory sSaxFactory; + + /** + * Current configurations for this factory + */ + protected final ValidatorConfig mConfig; + + protected BaseSchemaFactory(String schemaType) + { + super(schemaType); + mConfig = ValidatorConfig.createDefaults(); + } + + /* + //////////////////////////////////////////////////////////// + // Stax2, Configuration methods + //////////////////////////////////////////////////////////// + */ + + @Override + public boolean isPropertySupported(String propName) { + return mConfig.isPropertySupported(propName); + } + + @Override + public boolean setProperty(String propName, Object value) { + return mConfig.setProperty(propName, value); + } + + @Override + public Object getProperty(String propName) { + return mConfig.getProperty(propName); + } + + /* + //////////////////////////////////////////////////////////// + // Stax2, Factory methods + //////////////////////////////////////////////////////////// + */ + + @Override + public XMLValidationSchema createSchema(InputStream in, String encoding, + String publicId, String systemId) + throws XMLStreamException + { + InputSource src = new InputSource(in); + src.setEncoding(encoding); + src.setPublicId(publicId); + src.setSystemId(systemId); + return loadSchema(src, systemId); + } + + @Override + public XMLValidationSchema createSchema(Reader r, String publicId, + String systemId) + throws XMLStreamException + { + InputSource src = new InputSource(r); + src.setPublicId(publicId); + src.setSystemId(systemId); + return loadSchema(src, systemId); + } + + @SuppressWarnings("resource") + @Override + public XMLValidationSchema createSchema(URL url) + throws XMLStreamException + { + try { + InputStream in = URLUtil.inputStreamFromURL(url); + InputSource src = new InputSource(in); + src.setSystemId(url.toExternalForm()); + return loadSchema(src, url); + } catch (IOException ioe) { + throw new WstxIOException(ioe); + } + } + + @SuppressWarnings("deprecation") + @Override + public XMLValidationSchema createSchema(File f) + throws XMLStreamException + { + try { + return createSchema(f.toURL()); + } catch (IOException ioe) { + throw new WstxIOException(ioe); + } + } + + /* + //////////////////////////////////////////////////////////// + // Methods sub-classes need to implement + //////////////////////////////////////////////////////////// + */ + + protected abstract XMLValidationSchema loadSchema(InputSource src, Object sysRef) + throws XMLStreamException; + + /* + //////////////////////////////////////////////////////////// + // Internal/package methods + //////////////////////////////////////////////////////////// + */ + + /** + * We will essentially share a singleton sax parser factory; + * the reason being that constructing (or, rather, locating + * implementation class) is bit expensive. + */ + protected synchronized static SAXParserFactory getSaxFactory() + { + if (sSaxFactory == null) { + sSaxFactory = SAXParserFactory.newInstance(); + sSaxFactory.setNamespaceAware(true); + } + return sSaxFactory; + } + + /* + //////////////////////////////////////////////////////////// + // Helper classes + //////////////////////////////////////////////////////////// + */ + + final static class MyGrammarController + extends com.sun.msv.reader.util.IgnoreController + { + public String mErrorMsg = null; + + public MyGrammarController() { } + + //public void warning(Locator[] locs, String errorMessage) { } + + @Override + public void error(Locator[] locs, String msg, Exception nestedException ) + { + if (mErrorMsg == null) { + mErrorMsg = msg; + } else { + mErrorMsg = mErrorMsg + "; " + msg; + } + } + } +} diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/msv/GenericMsvValidator.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/msv/GenericMsvValidator.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/msv/GenericMsvValidator.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/msv/GenericMsvValidator.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,594 @@ +/* Woodstox XML processor + * + * Copyright (c) 2004- Tatu Saloranta, tatu.saloranta@iki.fi + * + * Licensed under the License specified in the file LICENSE which is + * included with the source code. + * You may not use this file except in compliance with the License. + * + * 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 com.ctc.wstx.msv; + +import java.util.*; + +import javax.xml.namespace.QName; +import javax.xml.stream.Location; +import javax.xml.stream.XMLStreamConstants; +import javax.xml.stream.XMLStreamException; + +import org.codehaus.stax2.validation.*; +import org.relaxng.datatype.Datatype; + +import com.sun.msv.grammar.IDContextProvider2; +import com.sun.msv.util.DatatypeRef; +import com.sun.msv.util.StartTagInfo; +import com.sun.msv.util.StringRef; +import com.sun.msv.verifier.Acceptor; +import com.sun.msv.verifier.DocumentDeclaration; +import com.sun.msv.verifier.regexp.StringToken; +import com.ctc.wstx.util.ElementId; +import com.ctc.wstx.util.ElementIdMap; +import com.ctc.wstx.util.PrefixedName; +import com.ctc.wstx.util.TextAccumulator; + +/** + * Generic validator instance to be used for all Multi-Schema Validator + * backed implementations. A common class can be used since functionality + * is almost identical between variants (RNG, W3C SChema); minor + * differences that exist can be configured by settings provided. + *

+ * Note about id context provider interface: while it'd be nice to + * separate that part out, it is unfortunately closely tied to the + * validation process. Hence it's directly implemented by this class. + */ +public final class GenericMsvValidator + extends XMLValidator + implements com.sun.msv.grammar.IDContextProvider2, + XMLStreamConstants +{ + /* + /////////////////////////////////////////////////////////// + // Configuration + /////////////////////////////////////////////////////////// + */ + + final XMLValidationSchema mParentSchema; + + final ValidationContext mContext; + + final DocumentDeclaration mVGM; + + /* + /////////////////////////////////////////////////////////// + // State, helper objects + /////////////////////////////////////////////////////////// + */ + + final ArrayList mAcceptors = new ArrayList(); + + Acceptor mCurrAcceptor = null; + + final TextAccumulator mTextAccumulator = new TextAccumulator(); + + /** + * Map that contains information about element id (values of attributes + * or textual content with type ID) declarations and references + */ + ElementIdMap mIdDefs; + + /* + /////////////////////////////////////////////////////////// + // State, positions + /////////////////////////////////////////////////////////// + */ + + String mCurrAttrPrefix; + + String mCurrAttrLocalName; + + /** + * Sometimes a problem object has to be temporarily + * stored, and only reported later on. This happens + * when exceptions can not be thrown via code outside + * of Woodstox (like validation methods in MSV that do + * callbacks). + */ + XMLValidationProblem mProblem; + + /* + /////////////////////////////////////////////////////////// + // Helper objects + /////////////////////////////////////////////////////////// + */ + + final StringRef mErrorRef = new StringRef(); + + /** + * StartTagInfo instance need not be thread-safe, and it is not immutable + * so let's reuse one instance during a single validation. + */ + final StartTagInfo mStartTag = new StartTagInfo("", "", "", null, (IDContextProvider2) null); + + /** + * Since `StartTagInfo` has no place for prefix, hold reference to one here + */ + protected String mStartTagPrefix = ""; + + /** + * This object provides limited access to attribute values of the + * currently validated element. + */ + final AttributeProxy mAttributeProxy; + + /* + /////////////////////////////////////////////////////////// + // Construction, configuration + /////////////////////////////////////////////////////////// + */ + + public GenericMsvValidator(XMLValidationSchema parent, ValidationContext ctxt, + DocumentDeclaration vgm) + { + mParentSchema = parent; + mContext = ctxt; + mVGM = vgm; + + mCurrAcceptor = mVGM.createAcceptor(); + mAttributeProxy = new AttributeProxy(ctxt); + } + + /* + /////////////////////////////////////////////////////////// + // IDContextProvider2 implementation: + // + // Core RelaxNG ValidationContext implementation + // (org.relaxng.datatype.ValidationContext, base interface + // of the id provider context) + /////////////////////////////////////////////////////////// + */ + + @Override + public String getBaseUri() { + return mContext.getBaseUri(); + } + + @Override + public boolean isNotation(String notationName) { + return mContext.isNotationDeclared(notationName); + } + + @Override + public boolean isUnparsedEntity(String entityName) { + return mContext.isUnparsedEntityDeclared(entityName); + } + + @Override + public String resolveNamespacePrefix(String prefix) { + return mContext.getNamespaceURI(prefix); + } + + /* + /////////////////////////////////////////////////////////// + // IDContextProvider2 implementation, extensions over + // core ValidationContext + /////////////////////////////////////////////////////////// + */ + + /** + *

+ * Note: we have to throw a dummy marker exception, which merely + * signals that a validation problem is to be reported. + * This is obviously messy, but has to do for now. + */ + @Override + public void onID(Datatype datatype, StringToken idToken) + throws IllegalArgumentException + { + if (mIdDefs == null) { + mIdDefs = new ElementIdMap(); + } + + int idType = datatype.getIdType(); + Location loc = mContext.getValidationLocation(); + PrefixedName elemPName = getElementPName(); + PrefixedName attrPName = getAttrPName(); + + if (idType == Datatype.ID_TYPE_ID) { + String idStr = idToken.literal.trim(); + ElementId eid = mIdDefs.addDefined(idStr, loc, elemPName, attrPName); + // We can detect dups by checking if Location is the one we passed: + if (eid.getLocation() != loc) { + mProblem = new XMLValidationProblem(loc, "Duplicate id '"+idStr+"', first declared at "+eid.getLocation()); + mProblem.setReporter(this); + } + } else if (idType == Datatype.ID_TYPE_IDREF) { + String idStr = idToken.literal.trim(); + mIdDefs.addReferenced(idStr, loc, elemPName, attrPName); + } else if (idType == Datatype.ID_TYPE_IDREFS) { + StringTokenizer tokens = new StringTokenizer(idToken.literal); + while (tokens.hasMoreTokens()) { + mIdDefs.addReferenced(tokens.nextToken(), loc, elemPName, attrPName); + } + } else { // sanity check + throw new IllegalStateException("Internal error: unexpected ID datatype: "+datatype); + } + } + + /* + /////////////////////////////////////////////////////////// + // XMLValidator implementation + /////////////////////////////////////////////////////////// + */ + + @Override + public XMLValidationSchema getSchema() { + return mParentSchema; + } + + /** + * Method called to update information about the newly encountered (start) + * element. At this point namespace information has been resolved, but + * no DTD validation has been done. Validator is to do these validations, + * including checking for attribute value (and existence) compatibility. + */ + @Override + public void validateElementStart(String localName, String uri, String prefix) + throws XMLStreamException + { + /* [WSTX-200]: If sub-tree we were to validate has ended, we + * have no current acceptor, and must quite. Ideally we would + * really handle this more cleanly but... + */ + if (mCurrAcceptor == null) { + return; + } + + // Very first thing: do we have text collected? + if (mTextAccumulator.hasText()) { + doValidateText(mTextAccumulator); + } + + /* 31-Mar-2006, TSa: MSV seems to require empty String for empty/no + * namespace, not null. + */ + if (uri == null) { + uri = ""; + } + + /* Do we need to properly fill it? Or could we just put local name? + * Looking at code, I do believe it's only used for error reporting + * purposes... + */ + //String qname = (prefix == null || prefix.length() == 0) ? localName : (prefix + ":" +localName); + String qname = localName; + mStartTag.reinit(uri, localName, qname, mAttributeProxy, this); + mStartTagPrefix = prefix; + + mCurrAcceptor = mCurrAcceptor.createChildAcceptor(mStartTag, mErrorRef); + /* As per documentation, the side-effect of getting the error message + * is that we also get a recoverable non-null acceptor... thus, should + * never (?) see null acceptor being returned + */ + if (mErrorRef.str != null) { + reportError(mErrorRef, START_ELEMENT, _qname(uri, localName, prefix)); + } + if (mProblem != null) { // pending problems (to throw exception on)? + XMLValidationProblem p = mProblem; + mProblem = null; + mContext.reportProblem(p); + } + mAcceptors.add(mCurrAcceptor); + } + + @Override + public String validateAttribute(String localName, String uri, + String prefix, String value) + throws XMLStreamException + { + mCurrAttrLocalName = localName; + mCurrAttrPrefix = prefix; + if (mCurrAcceptor != null) { + + String qname = localName; // for now, let's assume we don't need prefixed version + DatatypeRef typeRef = null; // for now, let's not care + + /* 31-Mar-2006, TSa: MSV seems to require empty String for empty/no + * namespace, not null. + */ + if (uri == null) { + uri = ""; + } + + if (!mCurrAcceptor.onAttribute2(uri, localName, qname, value, this, mErrorRef, typeRef) + || mErrorRef.str != null) { + reportError(mErrorRef, ATTRIBUTE, _qname(uri, localName, prefix)); + } + if (mProblem != null) { // pending problems (to throw exception on)? + XMLValidationProblem p = mProblem; + mProblem = null; + mContext.reportProblem(p); + } + } + // No normalization done by RelaxNG, is there? (at least nothing + // visible to callers that is) + return null; + } + + @Override + public String validateAttribute(String localName, String uri, String prefix, + char[] valueChars, int valueStart, int valueEnd) + throws XMLStreamException + { + int len = valueEnd - valueStart; + // This is very sub-optimal... but MSV doesn't deal with char arrays. + return validateAttribute(localName, uri, prefix, + new String(valueChars, valueStart, len)); + } + + @Override + public int validateElementAndAttributes() + throws XMLStreamException + { + // Not handling any attributes + mCurrAttrLocalName = mCurrAttrPrefix = ""; + if (mCurrAcceptor != null) { + /* start tag info is still intact here (only attributes sent + * since child acceptor was created) + */ + if (!mCurrAcceptor.onEndAttributes(mStartTag, mErrorRef) + || mErrorRef.str != null) { + reportError(mErrorRef, XMLStreamConstants.END_ELEMENT, _startTagAsQName()); + } + + int stringChecks = mCurrAcceptor.getStringCareLevel(); + switch (stringChecks) { + case Acceptor.STRING_PROHIBITED: // only WS + return XMLValidator.CONTENT_ALLOW_WS; + case Acceptor.STRING_IGNORE: // anything (mixed content models) + return XMLValidator.CONTENT_ALLOW_ANY_TEXT; + case Acceptor.STRING_STRICT: // validatable (data-oriented) + return XMLValidator.CONTENT_ALLOW_VALIDATABLE_TEXT; + default: + throw new IllegalArgumentException("Internal error: unexpected string care level value return by MSV: "+stringChecks); + } + } + + // If no acceptor, we are recovering, no need or use to validate text + return CONTENT_ALLOW_ANY_TEXT; + } + + /** + * @return Validation state that should be effective for the parent + * element state + */ + @Override + public int validateElementEnd(String localName, String uri, String prefix) + throws XMLStreamException + { + // Very first thing: do we have text collected? + /* 27-Feb-2009, TSa: [WSTX-191]: Actually MSV expects us to call + * validation anyway, in case there might be restriction(s) on + * textual content. Otherwise we'll get an error. + */ + doValidateText(mTextAccumulator); + + // [WSTX-200]: need to avoid problems when doing sub-tree + // validation... not a proper solution, but has to do for now + int lastIx = mAcceptors.size()-1; + if (lastIx < 0) { + return XMLValidator.CONTENT_ALLOW_WS; + } + Acceptor acc = (Acceptor)mAcceptors.remove(lastIx); + if (acc != null) { // may be null during error recovery? or not? + if (!acc.isAcceptState(mErrorRef) || mErrorRef.str != null) { + reportError(mErrorRef, XMLStreamConstants.END_ELEMENT, _qname(uri, localName, prefix)); + } + } + if (lastIx == 0) { // root closed + mCurrAcceptor = null; + } else { + mCurrAcceptor = (Acceptor) mAcceptors.get(lastIx-1); + } + if (mCurrAcceptor != null && acc != null) { + if (!mCurrAcceptor.stepForward(acc, mErrorRef) + || mErrorRef.str != null) { + reportError(mErrorRef, XMLStreamConstants.END_ELEMENT, _qname(uri, localName, prefix)); + } + int stringChecks = mCurrAcceptor.getStringCareLevel(); + switch (stringChecks) { + case Acceptor.STRING_PROHIBITED: // only WS + return XMLValidator.CONTENT_ALLOW_WS; + case Acceptor.STRING_IGNORE: // anything (mixed content models) + return XMLValidator.CONTENT_ALLOW_ANY_TEXT; + case Acceptor.STRING_STRICT: // validatable (data-oriented) + return XMLValidator.CONTENT_ALLOW_VALIDATABLE_TEXT; + default: + throw new IllegalArgumentException("Internal error: unexpected string care level value return by MSV: "+stringChecks); + } + } + return XMLValidator.CONTENT_ALLOW_ANY_TEXT; + } + + @Override + public void validateText(String text, boolean lastTextSegment) + throws XMLStreamException + { + /* If we got here, then it's likely we do need to call onText2(). + * (not guaranteed, though; in case of multiple parallel validators, + * only one of them may actually be interested) + */ + mTextAccumulator.addText(text); + if (lastTextSegment) { + doValidateText(mTextAccumulator); + } + } + + @Override + public void validateText(char[] cbuf, int textStart, int textEnd, + boolean lastTextSegment) + throws XMLStreamException + { + /* If we got here, then it's likely we do need to call onText(). + * (not guaranteed, though; in case of multiple parallel validators, + * only one of them may actually be interested) + */ + mTextAccumulator.addText(cbuf, textStart, textEnd); + if (lastTextSegment) { + doValidateText(mTextAccumulator); + } + } + + @Override + public void validationCompleted(boolean eod) + throws XMLStreamException + { + /* Ok, so, we should verify that there are no undefined + * IDREF/IDREFS references. But only if we hit EOF, not + * if validation was cancelled. + */ + if (eod) { + if (mIdDefs != null) { + ElementId ref = mIdDefs.getFirstUndefined(); + if (ref != null) { // problem! + String msg = "Undefined ID '"+ref.getId() + +"': referenced from element <" + +ref.getElemName()+">, attribute '" + +ref.getAttrName()+"'"; + reportError(msg, ref.getLocation()); + } + } + } + } + + /* + /////////////////////////////////////////////////////////// + // Attribute info access + /////////////////////////////////////////////////////////// + */ + + // // // Access to type info + + @Override + public String getAttributeType(int index) + { + // !!! TBI + return null; + } + + @Override + public int getIdAttrIndex() + { + // !!! TBI + return -1; + } + + @Override + public int getNotationAttrIndex() + { + // !!! TBI + return -1; + } + + /* + /////////////////////////////////////////////////////////// + // Internal methods + /////////////////////////////////////////////////////////// + */ + + PrefixedName getElementPName() + { + return PrefixedName.valueOf(mContext.getCurrentElementName()); + } + + PrefixedName getAttrPName() + { + return new PrefixedName(mCurrAttrPrefix, mCurrAttrLocalName); + } + + void doValidateText(TextAccumulator textAcc) + throws XMLStreamException + { + if (mCurrAcceptor != null) { + String str = textAcc.getAndClear(); + DatatypeRef typeRef = null; + if (!mCurrAcceptor.onText2(str, this, mErrorRef, typeRef) + || mErrorRef.str != null) { + reportError(mErrorRef, CDATA, _startTagAsQName()); + } + } + } + + private void reportError(StringRef errorRef, int type, QName name) throws XMLStreamException + { + String msg = errorRef.str; + errorRef.str = null; + if (msg == null || msg.isEmpty()) { + switch (type) { + case START_ELEMENT: + msg = "Unknown reason (at start element "+_name(name, "<", ">")+")"; + break; + case END_ELEMENT: + msg = "Unknown reason (at end element "+_name(name, "")+")"; + break; + case ATTRIBUTE: + msg = "Unknown reason (at attribute "+_name(name, "'", "'")+")"; + break; + case CDATA: + default: + msg = "Unknown reason (at CDATA section, inside element "+_name(name, "<", ">")+")"; + break; + } + } + reportError(msg); + } + + private void reportError(String msg) + throws XMLStreamException + { + reportError(msg, mContext.getValidationLocation()); + } + + private void reportError(String msg, Location loc) + throws XMLStreamException + { + XMLValidationProblem prob = new XMLValidationProblem(loc, msg, XMLValidationProblem.SEVERITY_ERROR); + prob.setReporter(this); + mContext.reportProblem(prob); + } + + private String _name(QName qn, String prefix, String suffix) { + if (qn == null) { + return "UNKNOWN"; + } + String name = qn.getLocalPart(); + String p = qn.getPrefix(); + if (p != null && !p.isEmpty()) { + name = p + ":" + name; + } + return prefix + name + suffix; + } + + private QName _startTagAsQName() { + return _qname(mStartTag.namespaceURI, mStartTag.localName, mStartTagPrefix); + } + + private QName _qname(String ns, String local, String prefix) { + if (prefix == null) { + prefix = ""; + } + if (ns == null) { + ns = ""; + } + // should we even allow this? + if (local == null) { + local = ""; + } + return new QName(ns, local, prefix); + } +} diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/msv/package.html libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/msv/package.html --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/msv/package.html 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/msv/package.html 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,5 @@ + +Package that contains Multi-Schema Validator (MSV) based validator +implementations for schema languages other than DTD. + + diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/msv/RelaxNGSchemaFactory.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/msv/RelaxNGSchemaFactory.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/msv/RelaxNGSchemaFactory.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/msv/RelaxNGSchemaFactory.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,83 @@ +/* Woodstox XML processor + * + * Copyright (c) 2004- Tatu Saloranta, tatu.saloranta@iki.fi + * + * Licensed under the License specified in the file LICENSE which is + * included with the source code. + * You may not use this file except in compliance with the License. + * + * 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 com.ctc.wstx.msv; + +import javax.xml.parsers.SAXParserFactory; +import javax.xml.stream.*; + +import org.xml.sax.InputSource; + +import org.codehaus.stax2.validation.*; + +import com.sun.msv.grammar.trex.TREXGrammar; +import com.sun.msv.reader.GrammarReaderController; +import com.sun.msv.reader.trex.ng.RELAXNGReader; + +/** + * This is a StAX2 schema factory that can parse and create schema instances + * for creating validators that validate documents to check their validity + * against specific Relax NG specifications. It requires + * Sun Multi-Schema Validator + * (http://www.sun.com/software/xml/developers/multischema/) + * to work, and acts as a quite thin wrapper layer (although not a completely + * trivial one, since MSV only exports SAX API, some adapting is needed) + */ +public class RelaxNGSchemaFactory + extends BaseSchemaFactory +{ + /** + * For now, there's no need for fine-grained error/problem reporting + * infrastructure, so let's just use a dummy controller. + */ + protected final GrammarReaderController mDummyController = + new com.sun.msv.reader.util.IgnoreController(); + + public RelaxNGSchemaFactory() + { + super(XMLValidationSchema.SCHEMA_ID_RELAXNG); + } + + /* + //////////////////////////////////////////////////////////// + // Non-public methods + //////////////////////////////////////////////////////////// + */ + + @Override + protected XMLValidationSchema loadSchema(InputSource src, Object sysRef) + throws XMLStreamException + { + /* 26-Oct-2007, TSa: Are sax parser factories safe to share? + * If not, should just create new instances for each + * parsed schema. + */ + /* Another thing; should we use a controller to get notified about + * errors in parsing? + */ + SAXParserFactory saxFactory = getSaxFactory(); + MyGrammarController ctrl = new MyGrammarController(); + TREXGrammar grammar = RELAXNGReader.parse(src, saxFactory, ctrl); + if (grammar == null) { + String msg = "Failed to load RelaxNG schema from '"+sysRef+"'"; + String emsg = ctrl.mErrorMsg; + if (emsg != null) { + msg = msg + ": "+emsg; + } + throw new XMLStreamException(msg); + } + return new RelaxNGSchema(grammar); + } +} diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/msv/RelaxNGSchema.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/msv/RelaxNGSchema.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/msv/RelaxNGSchema.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/msv/RelaxNGSchema.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,56 @@ +/* Woodstox XML processor + * + * Copyright (c) 2004- Tatu Saloranta, tatu.saloranta@iki.fi + * + * Licensed under the License specified in the file LICENSE which is + * included with the source code. + * You may not use this file except in compliance with the License. + * + * 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 com.ctc.wstx.msv; + +import javax.xml.stream.*; + +import org.codehaus.stax2.validation.*; + +import com.sun.msv.grammar.trex.TREXGrammar; +import com.sun.msv.verifier.regexp.REDocumentDeclaration; + +/** + * This is a validation schema instance based on a RELAX NG schema. It + * serves as a shareable "blueprint" for creating actual validator instances. + */ +public class RelaxNGSchema + implements XMLValidationSchema +{ + /** + * This is VGM (in MSV lingo); shareable schema blueprint, basically + * peer of this schema object. It will be used for creating actual + * validator peer, root Acceptor. + */ + protected final TREXGrammar mGrammar; + + public RelaxNGSchema(TREXGrammar grammar) + { + mGrammar = grammar; + } + + @Override + public String getSchemaType() { + return XMLValidationSchema.SCHEMA_ID_RELAXNG; + } + + @Override + public XMLValidator createValidator(ValidationContext ctxt) + throws XMLStreamException + { + REDocumentDeclaration dd = new REDocumentDeclaration(mGrammar); + return new GenericMsvValidator(this, ctxt, dd); + } +} diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/msv/W3CSchemaFactory.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/msv/W3CSchemaFactory.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/msv/W3CSchemaFactory.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/msv/W3CSchemaFactory.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,81 @@ +/* Woodstox XML processor + * + * Copyright (c) 2004- Tatu Saloranta, tatu.saloranta@iki.fi + * + * Licensed under the License specified in the file LICENSE which is + * included with the source code. + * You may not use this file except in compliance with the License. + * + * 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 com.ctc.wstx.msv; + +import javax.xml.parsers.SAXParserFactory; +import javax.xml.stream.*; + +import org.xml.sax.InputSource; + +import org.codehaus.stax2.validation.*; + +import com.sun.msv.grammar.xmlschema.XMLSchemaGrammar; +import com.sun.msv.reader.GrammarReaderController; +import com.sun.msv.reader.xmlschema.XMLSchemaReader; + +/** + * This is a StAX2 schema factory that can parse and create schema instances + * for creating validators that validate documents to check their validity + * against specific W3C Schema instances. It requires + * Sun Multi-Schema Validator + * (http://www.sun.com/software/xml/developers/multischema/) + * to work, and acts as a quite thin wrapper layer, similar to + * how matching RelaxNG validator works + */ +public class W3CSchemaFactory + extends BaseSchemaFactory +{ + /** + * For now, there's no need for fine-grained error/problem reporting + * infrastructure, so let's just use a dummy controller. + */ + protected final GrammarReaderController mDummyController = + new com.sun.msv.reader.util.IgnoreController(); + + public W3CSchemaFactory() + { + super(XMLValidationSchema.SCHEMA_ID_RELAXNG); + } + + /* + //////////////////////////////////////////////////////////// + // Non-public methods + //////////////////////////////////////////////////////////// + */ + + @Override + protected XMLValidationSchema loadSchema(InputSource src, Object sysRef) + throws XMLStreamException + { + /* 26-Oct-2007, TSa: Are sax parser factories safe to share? + * If not, should just create new instances for each + * parsed schema. + */ + SAXParserFactory saxFactory = getSaxFactory(); + + MyGrammarController ctrl = new MyGrammarController(); + XMLSchemaGrammar grammar = XMLSchemaReader.parse(src, saxFactory, ctrl); + if (grammar == null) { + String msg = "Failed to load W3C Schema from '"+sysRef+"'"; + String emsg = ctrl.mErrorMsg; + if (emsg != null) { + msg = msg + ": "+emsg; + } + throw new XMLStreamException(msg); + } + return new W3CSchema(grammar); + } +} diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/msv/W3CSchema.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/msv/W3CSchema.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/msv/W3CSchema.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/msv/W3CSchema.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,51 @@ +/* Woodstox XML processor + * + * Copyright (c) 2004- Tatu Saloranta, tatu.saloranta@iki.fi + * + * Licensed under the License specified in the file LICENSE which is + * included with the source code. + * You may not use this file except in compliance with the License. + * + * 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 com.ctc.wstx.msv; + +import javax.xml.stream.*; + +import org.codehaus.stax2.validation.*; + +import com.sun.msv.grammar.xmlschema.XMLSchemaGrammar; +import com.sun.msv.verifier.regexp.xmlschema.XSREDocDecl; + +/** + * This is a validation schema instance based on a W3C schema. It + * serves as a shareable "blueprint" for creating actual validator instances. + */ +public class W3CSchema + implements XMLValidationSchema +{ + protected final XMLSchemaGrammar mGrammar; + + public W3CSchema(XMLSchemaGrammar grammar) + { + mGrammar = grammar; + } + + @Override + public String getSchemaType() { + return XMLValidationSchema.SCHEMA_ID_W3C_SCHEMA; + } + + @Override + public XMLValidator createValidator(ValidationContext ctxt) + throws XMLStreamException + { + XSREDocDecl dd = new XSREDocDecl(mGrammar); + return new GenericMsvValidator(this, ctxt, dd); + } +} diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/osgi/InputFactoryProviderImpl.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/osgi/InputFactoryProviderImpl.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/osgi/InputFactoryProviderImpl.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/osgi/InputFactoryProviderImpl.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,26 @@ +package com.ctc.wstx.osgi; + +import java.util.Properties; + +import org.codehaus.stax2.XMLInputFactory2; +import org.codehaus.stax2.osgi.Stax2InputFactoryProvider; + +import com.ctc.wstx.api.ReaderConfig; +import com.ctc.wstx.stax.WstxInputFactory; + +public class InputFactoryProviderImpl + implements Stax2InputFactoryProvider +{ + @Override + public XMLInputFactory2 createInputFactory() { + return new WstxInputFactory(); + } + + protected Properties getProperties() + { + Properties props = new Properties(); + props.setProperty(OSGI_SVC_PROP_IMPL_NAME, ReaderConfig.getImplName()); + props.setProperty(OSGI_SVC_PROP_IMPL_VERSION, ReaderConfig.getImplVersion()); + return props; + } +} diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/osgi/OutputFactoryProviderImpl.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/osgi/OutputFactoryProviderImpl.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/osgi/OutputFactoryProviderImpl.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/osgi/OutputFactoryProviderImpl.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,26 @@ +package com.ctc.wstx.osgi; + +import java.util.Properties; + +import org.codehaus.stax2.XMLOutputFactory2; +import org.codehaus.stax2.osgi.Stax2OutputFactoryProvider; + +import com.ctc.wstx.api.ReaderConfig; +import com.ctc.wstx.stax.WstxOutputFactory; + +public class OutputFactoryProviderImpl + implements Stax2OutputFactoryProvider +{ + @Override + public XMLOutputFactory2 createOutputFactory() { + return new WstxOutputFactory(); + } + + protected Properties getProperties() + { + Properties props = new Properties(); + props.setProperty(OSGI_SVC_PROP_IMPL_NAME, ReaderConfig.getImplName()); + props.setProperty(OSGI_SVC_PROP_IMPL_VERSION, ReaderConfig.getImplVersion()); + return props; + } +} diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/osgi/package.html libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/osgi/package.html --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/osgi/package.html 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/osgi/package.html 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,5 @@ + +Contains classes that implement Stax2 OSGI providers for accessing +Stax2 input, output and validation scheme factories dynamically using +auto-discovery mechanism. + diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/osgi/ValidationSchemaFactoryProviderImpl.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/osgi/ValidationSchemaFactoryProviderImpl.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/osgi/ValidationSchemaFactoryProviderImpl.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/osgi/ValidationSchemaFactoryProviderImpl.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,84 @@ +package com.ctc.wstx.osgi; + +import java.util.Properties; + +import org.codehaus.stax2.validation.XMLValidationSchema; +import org.codehaus.stax2.validation.XMLValidationSchemaFactory; +import org.codehaus.stax2.osgi.Stax2ValidationSchemaFactoryProvider; + +import com.ctc.wstx.api.ValidatorConfig; +import com.ctc.wstx.dtd.DTDSchemaFactory; +import com.ctc.wstx.msv.RelaxNGSchemaFactory; +import com.ctc.wstx.msv.W3CSchemaFactory; + +public abstract class ValidationSchemaFactoryProviderImpl + implements Stax2ValidationSchemaFactoryProvider +{ + final String mSchemaType; + + protected ValidationSchemaFactoryProviderImpl(String st) + { + mSchemaType = st; + } + + public static ValidationSchemaFactoryProviderImpl[] createAll() + { + return new ValidationSchemaFactoryProviderImpl[] { + new DTD(), new RelaxNG(), new W3CSchema() + }; + } + + @Override + public abstract XMLValidationSchemaFactory createValidationSchemaFactory(); + + @Override + public String getSchemaType() { return mSchemaType; } + + public Properties getProperties() + { + Properties props = new Properties(); + props.setProperty(OSGI_SVC_PROP_IMPL_NAME, ValidatorConfig.getImplName()); + props.setProperty(OSGI_SVC_PROP_IMPL_VERSION, ValidatorConfig.getImplVersion()); + props.setProperty(OSGI_SVC_PROP_SCHEMA_TYPE, mSchemaType); + return props; + } + + /* + //////////////////////////////////////////////////////// + // Actual provider instances, one per type supported + //////////////////////////////////////////////////////// + */ + + final static class DTD + extends ValidationSchemaFactoryProviderImpl + { + DTD() { super(XMLValidationSchema.SCHEMA_ID_DTD); } + + @Override + public XMLValidationSchemaFactory createValidationSchemaFactory() { + return new DTDSchemaFactory(); + } + } + + final static class RelaxNG + extends ValidationSchemaFactoryProviderImpl + { + RelaxNG() { super(XMLValidationSchema.SCHEMA_ID_RELAXNG); } + + @Override + public XMLValidationSchemaFactory createValidationSchemaFactory() { + return new RelaxNGSchemaFactory(); + } + } + + final static class W3CSchema + extends ValidationSchemaFactoryProviderImpl + { + W3CSchema() { super(XMLValidationSchema.SCHEMA_ID_W3C_SCHEMA); } + + @Override + public XMLValidationSchemaFactory createValidationSchemaFactory() { + return new W3CSchemaFactory(); + } + } +} diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/osgi/WstxBundleActivator.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/osgi/WstxBundleActivator.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/osgi/WstxBundleActivator.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/osgi/WstxBundleActivator.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,46 @@ +package com.ctc.wstx.osgi; + +import org.osgi.framework.BundleActivator; +import org.osgi.framework.BundleContext; + +import org.codehaus.stax2.osgi.Stax2InputFactoryProvider; +import org.codehaus.stax2.osgi.Stax2OutputFactoryProvider; +import org.codehaus.stax2.osgi.Stax2ValidationSchemaFactoryProvider; + +/** + * This class is responsible for registering OSGi service(s) that Woodstox + * package provides. Currently it means registering all providers that are + * needed to instantiate input, output and validation schema factories; + * these are needed since JDK service-introspection (which is the standard + * Stax instance instantiation mechanism) does not work with OSGi. + */ +public class WstxBundleActivator + implements BundleActivator +{ + public WstxBundleActivator() { } + + /** + * Method called on activation. We need to register all providers we have at + * this point. + */ + @Override + public void start(BundleContext ctxt) + { + InputFactoryProviderImpl inputP = new InputFactoryProviderImpl(); + ctxt.registerService(Stax2InputFactoryProvider.class.getName(), inputP, inputP.getProperties()); + OutputFactoryProviderImpl outputP = new OutputFactoryProviderImpl(); + ctxt.registerService(Stax2OutputFactoryProvider.class.getName(), outputP, outputP.getProperties()); + ValidationSchemaFactoryProviderImpl[] impls = ValidationSchemaFactoryProviderImpl.createAll(); + for (int i = 0, len = impls.length; i < len; ++i) { + ValidationSchemaFactoryProviderImpl impl = impls[i]; + ctxt.registerService(Stax2ValidationSchemaFactoryProvider.class.getName(), impl, impl.getProperties()); + } + } + + @Override + public void stop(BundleContext ctxt) { + // Nothing to do here: OSGi automatically de-registers services upon + // deactivation. + } +} + diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/sax/package.html libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/sax/package.html --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/sax/package.html 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/sax/package.html 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,4 @@ + +Contains Woodstox SAX implementation. + + diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/sax/SAXFeature.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/sax/SAXFeature.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/sax/SAXFeature.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/sax/SAXFeature.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2004- Tatu Saloranta, tatu.saloranta@iki.fi + * + * Licensed under the License specified in file LICENSE, included with + * the source code. + * You may not use this file except in compliance with the License. + * + * 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 com.ctc.wstx.sax; + +import java.util.HashMap; + +/** + * Type safe (pre-Java5) enumeration for listing all currently (SAX 2.0.2) + * defined standard features + */ +public final class SAXFeature +{ + /** + * Since all standard features have same URI prefix, let's separate + * that prefix, from unique remainder of the feature URIs. + */ + public final static String STD_FEATURE_PREFIX = "http://xml.org/sax/features/"; + + final static HashMap sInstances = new HashMap(); + + // // // "Enum" values: + + final static SAXFeature EXTERNAL_GENERAL_ENTITIES = new SAXFeature("external-general-entities"); + final static SAXFeature EXTERNAL_PARAMETER_ENTITIES = new SAXFeature("external-parameter-entities"); + final static SAXFeature IS_STANDALONE = new SAXFeature("is-standalone"); + final static SAXFeature LEXICAL_HANDLER_PARAMETER_ENTITIES = new SAXFeature("lexical-handler/parameter-entities"); + final static SAXFeature NAMESPACES = new SAXFeature("namespaces"); + final static SAXFeature NAMESPACE_PREFIXES = new SAXFeature("namespace-prefixes"); + final static SAXFeature RESOLVE_DTD_URIS = new SAXFeature("resolve-dtd-uris"); + final static SAXFeature STRING_INTERNING = new SAXFeature("string-interning"); + final static SAXFeature UNICODE_NORMALIZATION_CHECKING = new SAXFeature("unicode-normalization-checking"); + final static SAXFeature USE_ATTRIBUTES2 = new SAXFeature("use-attributes2"); + final static SAXFeature USE_LOCATOR2 = new SAXFeature("use-locator2"); + final static SAXFeature USE_ENTITY_RESOLVER2 = new SAXFeature("use-entity-resolver2"); + final static SAXFeature VALIDATION = new SAXFeature("validation"); + final static SAXFeature XMLNS_URIS = new SAXFeature("xmlns-uris"); + final static SAXFeature XML_1_1 = new SAXFeature("xml-1.1"); + + private final String mSuffix; + + private SAXFeature(String suffix) + { + mSuffix = suffix; + sInstances.put(suffix, this); + } + + public static SAXFeature findByUri(String uri) + { + if (uri.startsWith(STD_FEATURE_PREFIX)) { + return findBySuffix(uri.substring(STD_FEATURE_PREFIX.length())); + } + return null; + } + + public static SAXFeature findBySuffix(String suffix) + { + return sInstances.get(suffix); + } + + public String getSuffix() { return mSuffix; } + + @Override + public String toString() { return STD_FEATURE_PREFIX + mSuffix; } +} diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/sax/SAXProperty.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/sax/SAXProperty.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/sax/SAXProperty.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/sax/SAXProperty.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2004- Tatu Saloranta, tatu.saloranta@iki.fi + * + * Licensed under the License specified in file LICENSE, included with + * the source code. + * You may not use this file except in compliance with the License. + * + * 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 com.ctc.wstx.sax; + +import java.util.HashMap; + +/** + * Type-safe (pre-Java5) enumeration of all currently (SAX 2.0.2) defined + * standard properties. + */ +public final class SAXProperty +{ + public final static String STD_PROPERTY_PREFIX = "http://xml.org/sax/properties/"; + + final static HashMap sInstances = new HashMap(); + + // // // "Enum" values: + + public final static SAXProperty DECLARATION_HANDLER = new SAXProperty("declaration-handler"); + public final static SAXProperty DOCUMENT_XML_VERSION = new SAXProperty("document-xml-version"); + public final static SAXProperty DOM_NODE = new SAXProperty("dom-node"); + public final static SAXProperty LEXICAL_HANDLER = new SAXProperty("lexical-handler"); + final static SAXProperty XML_STRING = new SAXProperty("xml-string"); + + private final String mSuffix; + + private SAXProperty(String suffix) + { + mSuffix = suffix; + sInstances.put(suffix, this); + } + + public static SAXProperty findByUri(String uri) + { + if (uri.startsWith(STD_PROPERTY_PREFIX)) { + return findBySuffix(uri.substring(STD_PROPERTY_PREFIX.length())); + } + return null; + } + + public static SAXProperty findBySuffix(String suffix) + { + return sInstances.get(suffix); + } + + public String getSuffix() { return mSuffix; } + + @Override + public String toString() { return STD_PROPERTY_PREFIX + mSuffix; } +} diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/sax/WrappedSaxException.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/sax/WrappedSaxException.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/sax/WrappedSaxException.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/sax/WrappedSaxException.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2004- Tatu Saloranta, tatu.saloranta@iki.fi + * + * Licensed under the License specified in file LICENSE, included with + * the source code. + * You may not use this file except in compliance with the License. + * + * 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 com.ctc.wstx.sax; + +import org.xml.sax.SAXException; + +/** + * Simple type-safe wrapper used for "tunneling" SAX exceptions + * through interfaces that do not allow them to be thrown. This + * is done by extending {@link RuntimeException}. + */ +@SuppressWarnings("serial") +public final class WrappedSaxException + extends RuntimeException +{ + final SAXException mCause; + + public WrappedSaxException(SAXException cause) + { + mCause = cause; + } + + public SAXException getSaxException() { return mCause; } + + @Override + public String toString() { return mCause.toString(); } +} diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/sax/WstxSAXParserFactory.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/sax/WstxSAXParserFactory.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/sax/WstxSAXParserFactory.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/sax/WstxSAXParserFactory.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,168 @@ +/* + * Copyright (c) 2004- Tatu Saloranta, tatu.saloranta@iki.fi + * + * Licensed under the License specified in file LICENSE, included with + * the source code. + * You may not use this file except in compliance with the License. + * + * 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 com.ctc.wstx.sax; + +import javax.xml.parsers.SAXParser; +import javax.xml.parsers.SAXParserFactory; + +import org.xml.sax.SAXNotRecognizedException; +import org.xml.sax.SAXNotSupportedException; + +import com.ctc.wstx.stax.WstxInputFactory; + +/** + * This is implementation of the main JAXP SAX factory, and as such + * acts as the entry point from JAXP. + *

+ * Note: most of the SAX features are not configurable as of yet. + * However, effort is made to recognize all existing standard features + * and properties, to allow using code to figure out existing + * capabilities automatically. + */ +public class WstxSAXParserFactory + extends SAXParserFactory +{ + protected final WstxInputFactory mStaxFactory; + + /** + * Sax feature that determines whether namespace declarations need + * to be also reported as attributes or not. + */ + protected boolean mFeatNsPrefixes = false; + + public WstxSAXParserFactory() + { + this(new WstxInputFactory()); + } + + /** + * @since 4.0.8 + */ + public WstxSAXParserFactory(WstxInputFactory f) + { + mStaxFactory = f; + /* defaults should be fine... except that for some weird + * reason, by default namespace support is defined to be off + */ + setNamespaceAware(true); + } + + @Override + public boolean getFeature(String name) + throws SAXNotRecognizedException, SAXNotSupportedException + { + SAXFeature stdFeat = SAXFeature.findByUri(name); + + if (stdFeat == SAXFeature.EXTERNAL_GENERAL_ENTITIES) { + return mStaxFactory.getConfig().willSupportExternalEntities(); + } else if (stdFeat == SAXFeature.EXTERNAL_PARAMETER_ENTITIES) { + return mStaxFactory.getConfig().willSupportExternalEntities(); + } else if (stdFeat == SAXFeature.IS_STANDALONE) { + // Not known at this point... + return false; + } else if (stdFeat == SAXFeature.LEXICAL_HANDLER_PARAMETER_ENTITIES) { + // !!! TODO: + return false; + } else if (stdFeat == SAXFeature.NAMESPACES) { + return mStaxFactory.getConfig().willSupportNamespaces(); + } else if (stdFeat == SAXFeature.NAMESPACE_PREFIXES) { + return mFeatNsPrefixes; + } else if (stdFeat == SAXFeature.RESOLVE_DTD_URIS) { + // !!! TODO: + return false; + } else if (stdFeat == SAXFeature.STRING_INTERNING) { + return mStaxFactory.getConfig().willInternNames(); + } else if (stdFeat == SAXFeature.UNICODE_NORMALIZATION_CHECKING) { + return false; + } else if (stdFeat == SAXFeature.USE_ATTRIBUTES2) { + return true; + } else if (stdFeat == SAXFeature.USE_LOCATOR2) { + return true; + } else if (stdFeat == SAXFeature.USE_ENTITY_RESOLVER2) { + return true; + } else if (stdFeat == SAXFeature.VALIDATION) { + return mStaxFactory.getConfig().willValidateWithDTD(); + } else if (stdFeat == SAXFeature.XMLNS_URIS) { + /* !!! TODO: default value should be false... but not sure + * if implementing that mode makes sense + */ + return true; + } else if (stdFeat == SAXFeature.XML_1_1) { + return true; + } else { + throw new SAXNotRecognizedException("Feature '"+name+"' not recognized"); + } + } + + @Override + public SAXParser newSAXParser() + { + return new WstxSAXParser(mStaxFactory, mFeatNsPrefixes); + } + + @Override + public void setFeature(String name, boolean value) + throws SAXNotRecognizedException, SAXNotSupportedException + { + boolean invalidValue = false; + boolean readOnly = false; + SAXFeature stdFeat = SAXFeature.findByUri(name); + + if (stdFeat == SAXFeature.EXTERNAL_GENERAL_ENTITIES) { + mStaxFactory.getConfig().doSupportExternalEntities(value); + } else if (stdFeat == SAXFeature.EXTERNAL_PARAMETER_ENTITIES) { + // !!! TODO + } else if (stdFeat == SAXFeature.IS_STANDALONE) { + readOnly = true; + } else if (stdFeat == SAXFeature.LEXICAL_HANDLER_PARAMETER_ENTITIES) { + // !!! TODO + } else if (stdFeat == SAXFeature.NAMESPACES) { + mStaxFactory.getConfig().doSupportNamespaces(value); + } else if (stdFeat == SAXFeature.NAMESPACE_PREFIXES) { + mFeatNsPrefixes = value; + } else if (stdFeat == SAXFeature.RESOLVE_DTD_URIS) { + // !!! TODO + } else if (stdFeat == SAXFeature.STRING_INTERNING) { + invalidValue = !value; + } else if (stdFeat == SAXFeature.UNICODE_NORMALIZATION_CHECKING) { + invalidValue = value; + } else if (stdFeat == SAXFeature.USE_ATTRIBUTES2) { + readOnly = true; + } else if (stdFeat == SAXFeature.USE_LOCATOR2) { + readOnly = true; + } else if (stdFeat == SAXFeature.USE_ENTITY_RESOLVER2) { + readOnly = true; + } else if (stdFeat == SAXFeature.VALIDATION) { + mStaxFactory.getConfig().doValidateWithDTD(value); + } else if (stdFeat == SAXFeature.XMLNS_URIS) { + invalidValue = !value; + } else if (stdFeat == SAXFeature.XML_1_1) { + readOnly = true; + } else { + throw new SAXNotRecognizedException("Feature '"+name+"' not recognized"); + } + + // Trying to modify read-only properties? + if (readOnly) { + throw new SAXNotSupportedException("Feature '"+name+"' is read-only, can not be modified"); + } + if (invalidValue) { + throw new SAXNotSupportedException("Trying to set invalid value for feature '"+name+"', '"+value+"'"); + } + } +} + + + diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/sax/WstxSAXParser.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/sax/WstxSAXParser.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/sax/WstxSAXParser.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/sax/WstxSAXParser.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,1497 @@ +/* + * Copyright (c) 2004- Tatu Saloranta, tatu.saloranta@iki.fi + * + * Licensed under the License specified in file LICENSE, included with + * the source code. + * You may not use this file except in compliance with the License. + * + * 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 com.ctc.wstx.sax; + +import java.io.*; +import java.net.URL; + +import javax.xml.XMLConstants; +import javax.xml.parsers.SAXParser; +import javax.xml.stream.Location; +import javax.xml.stream.XMLResolver; +import javax.xml.stream.XMLStreamConstants; +import javax.xml.stream.XMLStreamException; + +import org.xml.sax.*; +import org.xml.sax.helpers.DefaultHandler; +import org.xml.sax.ext.Attributes2; +import org.xml.sax.ext.DeclHandler; +import org.xml.sax.ext.LexicalHandler; +import org.xml.sax.ext.Locator2; + +//import org.codehaus.stax2.DTDInfo; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +import com.ctc.wstx.api.ReaderConfig; +import com.ctc.wstx.dtd.DTDEventListener; +import com.ctc.wstx.exc.WstxIOException; +import com.ctc.wstx.io.DefaultInputResolver; +import com.ctc.wstx.io.InputBootstrapper; +import com.ctc.wstx.io.ReaderBootstrapper; +import com.ctc.wstx.io.StreamBootstrapper; +import com.ctc.wstx.io.SystemId; +import com.ctc.wstx.sr.*; +import com.ctc.wstx.stax.WstxInputFactory; +import com.ctc.wstx.util.ExceptionUtil; +import com.ctc.wstx.util.URLUtil; + +/** + * This class implements parser part of JAXP and SAX interfaces; and + * effectively offers an alternative to using Stax input factory / + * stream reader combination. + */ +@SuppressWarnings("deprecation") +public class WstxSAXParser + extends SAXParser + implements Parser // SAX1 + ,XMLReader // SAX2 + ,Attributes2 // SAX2 + ,Locator2 // SAX2 + ,DTDEventListener // Woodstox-internal +{ + final static boolean FEAT_DEFAULT_NS_PREFIXES = false; + + /** + * We will need the factory reference mostly for constructing + * underlying stream reader we use. + */ + protected final WstxInputFactory mStaxFactory; + + protected final ReaderConfig mConfig; + + protected boolean mFeatNsPrefixes; + + /** + * Since the stream reader would mostly be just a wrapper around + * the underlying scanner (its main job is to implement Stax + * interface), we can and should just use the scanner. In effect, + * this class is then a replacement of BasicStreamReader, when + * using SAX interfaces. + */ + protected BasicStreamReader mScanner; + + protected AttributeCollector mAttrCollector; + + protected InputElementStack mElemStack; + + // // // Info from xml declaration + + protected String mEncoding; + protected String mXmlVersion; + protected boolean mStandalone; + + // // // Listeners attached: + + protected ContentHandler mContentHandler; + protected DTDHandler mDTDHandler; + private EntityResolver mEntityResolver; + private ErrorHandler mErrorHandler; + + private LexicalHandler mLexicalHandler; + private DeclHandler mDeclHandler; + + // // // State: + + /** + * Number of attributes accessible via {@link Attributes} and + * {@link Attributes2} interfaces, for the current start element. + *

+ * Note: does not include namespace declarations, even they are to + * be reported as attributes. + */ + protected int mAttrCount; + + /** + * Need to keep track of number of namespaces, if namespace declarations + * are to be reported along with attributes (see + * {@link #mFeatNsPrefixes}). + */ + protected int mNsCount = 0; + + /* + ///////////////////////////////////////////////// + // Life-cycle + ///////////////////////////////////////////////// + */ + + /** + *

+ * NOTE: this was a protected constructor for versions 4.0 + * and 3.2; changed to public in 4.1 + */ + public WstxSAXParser(WstxInputFactory sf, boolean nsPrefixes) + { + mStaxFactory = sf; + mFeatNsPrefixes = nsPrefixes; + mConfig = sf.createPrivateConfig(); + mConfig.doSupportDTDs(true); + /* Lazy parsing is a tricky thing: although most of the time + * it's useless with SAX, it is actually necessary to be able + * to properly model internal DTD subsets, for example. So, + * we can not really easily determine defaults. + */ + ResolverProxy r = new ResolverProxy(); + /* SAX doesn't distinguish between DTD (ext. subset, PEs) and + * entity (external general entities) resolvers, so let's + * assign them both: + */ + mConfig.setDtdResolver(r); + mConfig.setEntityResolver(r); + mConfig.setDTDEventListener(this); + + /* These settings do NOT make sense as generic defaults, but + * are helpful when using some test frameworks. Specifically, + * - DTD caching may remove calls to resolvers, changing + * observed behavior + * - Using min. segment length of 1 will force flushing of + * all content before entity expansion, which will + * completely serialize entity resolution calls wrt. + * CHARACTERS events. + */ + // !!! ONLY for testing; never remove for prod use + //mConfig.setShortestReportedTextSegment(1); + //mConfig.doCacheDTDs(false); + } + + /* + * This constructor is provided for two main use cases: testing, + * and introspection via SAX classes (as opposed to JAXP-based + * introspection). + */ + public WstxSAXParser() + { + this(new WstxInputFactory(), FEAT_DEFAULT_NS_PREFIXES); + } + + @Override + public final Parser getParser() { + return this; + } + + @Override + public final XMLReader getXMLReader() { + return this; + } + + /** + * Accessor used to allow configuring all standard Stax configuration + * settings that the underlying reader uses. + * + * @since 4.0.8 + */ + public final ReaderConfig getStaxConfig() { + return mConfig; + } + + /* + ///////////////////////////////////////////////// + // Configuration, SAXParser + ///////////////////////////////////////////////// + */ + + @Override + public boolean isNamespaceAware() { + return mConfig.willSupportNamespaces(); + } + + @Override + public boolean isValidating() { + return mConfig.willValidateWithDTD(); + } + + @Override + public Object getProperty(String name) + throws SAXNotRecognizedException, SAXNotSupportedException + { + SAXProperty prop = SAXProperty.findByUri(name); + if (prop == SAXProperty.DECLARATION_HANDLER) { + return mDeclHandler; + } else if (prop == SAXProperty.DOCUMENT_XML_VERSION) { + return mXmlVersion; + } else if (prop == SAXProperty.DOM_NODE) { + return null; + } else if (prop == SAXProperty.LEXICAL_HANDLER) { + return mLexicalHandler; + } else if (prop == SAXProperty.XML_STRING) { + return null; + } + + throw new SAXNotRecognizedException("Property '"+name+"' not recognized"); + } + + @Override + public void setProperty(String name, Object value) + throws SAXNotRecognizedException, SAXNotSupportedException + { + SAXProperty prop = SAXProperty.findByUri(name); + if (prop == SAXProperty.DECLARATION_HANDLER) { + mDeclHandler = (DeclHandler) value; + return; + } else if (prop == SAXProperty.DOCUMENT_XML_VERSION) { + ; // read-only + } else if (prop == SAXProperty.DOM_NODE) { + ; // read-only + } else if (prop == SAXProperty.LEXICAL_HANDLER) { + mLexicalHandler = (LexicalHandler) value; + return; + } else if (prop == SAXProperty.XML_STRING) { + ; // read-only + } else { + throw new SAXNotRecognizedException("Property '"+name+"' not recognized"); + } + + // Trying to modify read-only properties? + throw new SAXNotSupportedException("Property '"+name+"' is read-only, can not be modified"); + } + + /* + ///////////////////////////////////////////////// + // Overrides, SAXParser + ///////////////////////////////////////////////// + */ + + /* Have to override some methods from SAXParser; JDK + * implementation is sucky, as it tries to override + * many things it really should not... + */ + + @Override + public void parse(InputSource is, HandlerBase hb) + throws SAXException, IOException + { + if (hb != null) { + /* Ok: let's ONLY set if there are no explicit sets... not + * extremely clear, but JDK tries to set them always so + * let's at least do damage control. + */ + if (mContentHandler == null) { + setDocumentHandler(hb); + } + if (mEntityResolver == null) { + setEntityResolver(hb); + } + if (mErrorHandler == null) { + setErrorHandler(hb); + } + if (mDTDHandler == null) { + setDTDHandler(hb); + } + } + parse(is); + } + + @Override + public void parse(InputSource is, DefaultHandler dh) + throws SAXException, IOException + { + if (dh != null) { + /* Ok: let's ONLY set if there are no explicit sets... not + * extremely clear, but JDK tries to set them always so + * let's at least do damage control. + */ + if (mContentHandler == null) { + setContentHandler(dh); + } + if (mEntityResolver == null) { + setEntityResolver(dh); + } + if (mErrorHandler == null) { + setErrorHandler(dh); + } + if (mDTDHandler == null) { + setDTDHandler(dh); + } + } + parse(is); + } + + /* + ///////////////////////////////////////////////////// + // XLMReader (SAX2) implementation: cfg access + ///////////////////////////////////////////////////// + */ + + @Override + public ContentHandler getContentHandler() { + return mContentHandler; + } + + @Override + public DTDHandler getDTDHandler() { + return mDTDHandler; + } + + @Override + public EntityResolver getEntityResolver() { + return mEntityResolver; + } + + @Override + public ErrorHandler getErrorHandler() { + return mErrorHandler; + } + + @Override + public boolean getFeature(String name) + throws SAXNotRecognizedException + { + SAXFeature stdFeat = SAXFeature.findByUri(name); + + if (stdFeat == SAXFeature.EXTERNAL_GENERAL_ENTITIES) { + return mConfig.willSupportExternalEntities(); + } else if (stdFeat == SAXFeature.EXTERNAL_PARAMETER_ENTITIES) { + return mConfig.willSupportExternalEntities(); + } else if (stdFeat == SAXFeature.IS_STANDALONE) { + return mStandalone; + } else if (stdFeat == SAXFeature.LEXICAL_HANDLER_PARAMETER_ENTITIES) { + // !!! TODO: + return false; + } else if (stdFeat == SAXFeature.NAMESPACES) { + return mConfig.willSupportNamespaces(); + } else if (stdFeat == SAXFeature.NAMESPACE_PREFIXES) { + return !mConfig.willSupportNamespaces(); + } else if (stdFeat == SAXFeature.RESOLVE_DTD_URIS) { + // !!! TODO: + return false; + } else if (stdFeat == SAXFeature.STRING_INTERNING) { + return true; + } else if (stdFeat == SAXFeature.UNICODE_NORMALIZATION_CHECKING) { + return false; + } else if (stdFeat == SAXFeature.USE_ATTRIBUTES2) { + return true; + } else if (stdFeat == SAXFeature.USE_LOCATOR2) { + return true; + } else if (stdFeat == SAXFeature.USE_ENTITY_RESOLVER2) { + return true; + } else if (stdFeat == SAXFeature.VALIDATION) { + return mConfig.willValidateWithDTD(); + } else if (stdFeat == SAXFeature.XMLNS_URIS) { + /* !!! TODO: default value should be false... but not sure + * if implementing that mode makes sense + */ + return true; + } else if (stdFeat == SAXFeature.XML_1_1) { + return true; + } + + throw new SAXNotRecognizedException("Feature '"+name+"' not recognized"); + } + + // Already implemented for SAXParser + //public Object getProperty(String name) + + /* + ///////////////////////////////////////////////////// + // XLMReader (SAX2) implementation: cfg changing + ///////////////////////////////////////////////////// + */ + + @Override + public void setContentHandler(ContentHandler handler) { + mContentHandler = handler; + } + + @Override + public void setDTDHandler(DTDHandler handler) { + mDTDHandler = handler; + } + + @Override + public void setEntityResolver(EntityResolver resolver) { + mEntityResolver = resolver; + } + + @Override + public void setErrorHandler(ErrorHandler handler) { + mErrorHandler = handler; + } + + @Override + public void setFeature(String name, boolean value) + throws SAXNotRecognizedException, SAXNotSupportedException + { + boolean invalidValue = false; + boolean readOnly = false; + SAXFeature stdFeat = SAXFeature.findByUri(name); + + if (stdFeat == SAXFeature.EXTERNAL_GENERAL_ENTITIES) { + mConfig.doSupportExternalEntities(value); + } else if (stdFeat == SAXFeature.EXTERNAL_PARAMETER_ENTITIES) { + // !!! TODO + } else if (stdFeat == SAXFeature.IS_STANDALONE) { + readOnly = true; + } else if (stdFeat == SAXFeature.LEXICAL_HANDLER_PARAMETER_ENTITIES) { + // !!! TODO + } else if (stdFeat == SAXFeature.NAMESPACES) { + mConfig.doSupportNamespaces(value); + } else if (stdFeat == SAXFeature.NAMESPACE_PREFIXES) { + mFeatNsPrefixes = value; + } else if (stdFeat == SAXFeature.RESOLVE_DTD_URIS) { + // !!! TODO + } else if (stdFeat == SAXFeature.STRING_INTERNING) { + invalidValue = !value; + } else if (stdFeat == SAXFeature.UNICODE_NORMALIZATION_CHECKING) { + invalidValue = value; + } else if (stdFeat == SAXFeature.USE_ATTRIBUTES2) { + readOnly = true; + } else if (stdFeat == SAXFeature.USE_LOCATOR2) { + readOnly = true; + } else if (stdFeat == SAXFeature.USE_ENTITY_RESOLVER2) { + readOnly = true; + } else if (stdFeat == SAXFeature.VALIDATION) { + mConfig.doValidateWithDTD(value); + } else if (stdFeat == SAXFeature.XMLNS_URIS) { + invalidValue = !value; + } else if (stdFeat == SAXFeature.XML_1_1) { + readOnly = true; + } else { + throw new SAXNotRecognizedException("Feature '"+name+"' not recognized"); + } + + // Trying to modify read-only properties? + if (readOnly) { + throw new SAXNotSupportedException("Feature '"+name+"' is read-only, can not be modified"); + } + if (invalidValue) { + throw new SAXNotSupportedException("Trying to set invalid value for feature '"+name+"', '"+value+"'"); + } + } + + // Already implemented for SAXParser + //public void setProperty(String name, Object value) + + /* + ///////////////////////////////////////////////////// + // XLMReader (SAX2) implementation: parsing + ///////////////////////////////////////////////////// + */ + + @SuppressWarnings("resource") + @Override + public void parse(InputSource input) throws SAXException + { + mScanner = null; + String sysIdStr = input.getSystemId(); + ReaderConfig cfg = mConfig; + URL srcUrl = null; + + // Let's figure out input, first, before sending start-doc event + InputStream is = null; + Reader r = input.getCharacterStream(); + if (r == null) { + is = input.getByteStream(); + if (is == null) { + if (sysIdStr == null) { + throw new SAXException("Invalid InputSource passed: neither character or byte stream passed, nor system id specified"); + } + try { + srcUrl = URLUtil.urlFromSystemId(sysIdStr); + is = URLUtil.inputStreamFromURL(srcUrl); + } catch (IOException ioe) { + SAXException saxe = new SAXException(ioe); + ExceptionUtil.setInitCause(saxe, ioe); + throw saxe; + } + } + } + + if (mContentHandler != null) { + mContentHandler.setDocumentLocator(this); + mContentHandler.startDocument(); + } + + /* Note: since we are reusing the same config instance, need to + * make sure state is not carried forward. Thus: + */ + cfg.resetState(); + + try { + String inputEnc = input.getEncoding(); + String publicId = input.getPublicId(); + + // Got an InputStream and encoding? Can create a Reader: + if (r == null && (inputEnc != null && inputEnc.length() > 0)) { + r = DefaultInputResolver.constructOptimizedReader(cfg, is, false, inputEnc); + } + InputBootstrapper bs; + SystemId systemId = SystemId.construct(sysIdStr, srcUrl); + if (r != null) { + bs = ReaderBootstrapper.getInstance(publicId, systemId, r, inputEnc); + // false -> not for event reader; false -> no auto-closing + mScanner = (BasicStreamReader) mStaxFactory.createSR(cfg, systemId, bs, false, false); + } else { + bs = StreamBootstrapper.getInstance(publicId, systemId, is); + mScanner = (BasicStreamReader) mStaxFactory.createSR(cfg, systemId, bs, false, false); + } + + // Need to get xml declaration stuff out now: + { + String enc2 = mScanner.getEncoding(); + if (enc2 == null) { + enc2 = mScanner.getCharacterEncodingScheme(); + } + mEncoding = enc2; + } + mXmlVersion = mScanner.getVersion(); + mStandalone = mScanner.standaloneSet(); + mAttrCollector = mScanner.getAttributeCollector(); + mElemStack = mScanner.getInputElementStack(); + fireEvents(); + } catch (IOException io) { + throwSaxException(io); + } catch (XMLStreamException strex) { + throwSaxException(strex); + } finally { + if (mContentHandler != null) { + mContentHandler.endDocument(); + } + // Could try holding onto the buffers, too... but + // maybe it's better to allow them to be reclaimed, if + // needed by GC + if (mScanner != null) { + BasicStreamReader sr = mScanner; + mScanner = null; + try { + sr.close(); + } catch (XMLStreamException sex) { } + } + if (r != null) { + try { + r.close(); + } catch (IOException ioe) { } + } + if (is != null) { + try { + is.close(); + } catch (IOException ioe) { } + } + } + } + + @Override + public void parse(String systemId) throws SAXException + { + InputSource src = new InputSource(systemId); + parse(src); + } + + /* + ///////////////////////////////////////////////// + // Parsing loop, helper methods + ///////////////////////////////////////////////// + */ + + /** + * This is the actual "tight event loop" that will send all events + * between start and end document events. Although we could + * use the stream reader here, there's not much as it mostly + * just forwards requests to the scanner: and so we can as well + * just copy the little code stream reader's next() method has. + */ + private final void fireEvents() + throws IOException, SAXException, XMLStreamException + { + // First we are in prolog: + int type; + + /* Need to enable lazy parsing, to get DTD start events before + * its content events. Plus, can skip more efficiently too. + */ + mConfig.doParseLazily(false); + + while ((type = mScanner.next()) != XMLStreamConstants.START_ELEMENT) { + fireAuxEvent(type, false); + } + + // Now just starting the tree, need to process the START_ELEMENT + fireStartTag(); + + int depth = 1; + while (true) { + type = mScanner.next(); + if (type == XMLStreamConstants.START_ELEMENT) { + fireStartTag(); + ++depth; + } else if (type == XMLStreamConstants.END_ELEMENT) { + mScanner.fireSaxEndElement(mContentHandler); + if (--depth < 1) { + break; + } + } else if (type == XMLStreamConstants.CHARACTERS) { + mScanner.fireSaxCharacterEvents(mContentHandler); + } else { + fireAuxEvent(type, true); + } + } + + // And then epilog: + while (true) { + type = mScanner.next(); + if (type == XMLStreamConstants.END_DOCUMENT) { + break; + } + if (type == XMLStreamConstants.SPACE) { + // Not to be reported via SAX interface (which may or may not + // be different from Stax) + continue; + } + fireAuxEvent(type, false); + } + } + + private final void fireAuxEvent(int type, boolean inTree) + throws IOException, SAXException, XMLStreamException + { + switch (type) { + case XMLStreamConstants.COMMENT: + mScanner.fireSaxCommentEvent(mLexicalHandler); + break; + case XMLStreamConstants.CDATA: + if (mLexicalHandler != null) { + mLexicalHandler.startCDATA(); + mScanner.fireSaxCharacterEvents(mContentHandler); + mLexicalHandler.endCDATA(); + } else { + mScanner.fireSaxCharacterEvents(mContentHandler); + } + break; + case XMLStreamConstants.DTD: + if (mLexicalHandler != null) { + /* Note: this is bit tricky, since calling getDTDInfo() will + * trigger full reading of the subsets... but we need to + * get some info first, to be able to send dtd-start event, + * and only then get the rest. Thus, need to call separate + * accessors first: + */ + String rootName = mScanner.getDTDRootName(); + String sysId = mScanner.getDTDSystemId(); + String pubId = mScanner.getDTDPublicId(); + mLexicalHandler.startDTD(rootName, pubId, sysId); + // Ok, let's get rest (if any) read: + try { + /*DTDInfo dtdInfo =*/ mScanner.getDTDInfo(); + } catch (WrappedSaxException wse) { + throw wse.getSaxException(); + } + mLexicalHandler.endDTD(); + } + break; + case XMLStreamConstants.PROCESSING_INSTRUCTION: + mScanner.fireSaxPIEvent(mContentHandler); + break; + case XMLStreamConstants.SPACE: + // With SAX, only to be sent as an event if inside the + // tree, not from within prolog/epilog + if (inTree) { + mScanner.fireSaxSpaceEvents(mContentHandler); + } + break; + case XMLStreamConstants.ENTITY_REFERENCE: + /* Only occurs in non-entity-expanding mode; so effectively + * we are skipping the entity? + */ + if (mContentHandler != null) { + mContentHandler.skippedEntity(mScanner.getLocalName()); + } + break; + default: + if (type == XMLStreamConstants.END_DOCUMENT) { + throwSaxException("Unexpected end-of-input in "+(inTree ? "tree" : "prolog")); + } + throw new RuntimeException("Internal error: unexpected type, "+type); + } + } + + private final void fireStartTag() + throws SAXException + { + mAttrCount = mAttrCollector.getCount(); + if (mFeatNsPrefixes) { + /* 15-Dec-2006, TSa: Note: apparently namespace bindings that + * are added via defaulting are only visible via element + * stack. Thus, we MUST access things via element stack, + * not attribute collector; even though latter seems like + * the more direct route. See + * {@link NsInputElementStack#addNsBinding} for the method + * that injects such special namespace bindings (yes, it's + * a hack, afterthought) + */ + //mNsCount = mAttrCollector.getNsCount(); + mNsCount = mElemStack.getCurrentNsCount(); + } + mScanner.fireSaxStartElement(mContentHandler, this); + } + + /* + ///////////////////////////////////////////////// + // Parser (SAX1) implementation + ///////////////////////////////////////////////// + */ + + // Already implemented for XMLReader: + //public void parse(InputSource source) + //public void parse(String systemId) + //public void setEntityResolver(EntityResolver resolver) + //public void setErrorHandler(ErrorHandler handler) + + @Override + public void setDocumentHandler(DocumentHandler handler) { + setContentHandler(new DocHandlerWrapper(handler)); + } + + @Override + public void setLocale(java.util.Locale locale) { + // Not supported, let's just ignore + } + + /* + ///////////////////////////////////////////////////// + // Attributes (SAX2) implementation + ///////////////////////////////////////////////////// + */ + + @Override + public int getIndex(String qName) + { + if (mElemStack == null) { + return -1; + } + int ix = mElemStack.findAttributeIndex(null, qName); + // !!! In ns-as-attrs mode, should also match ns decls? + return ix; + } + + @Override + public int getIndex(String uri, String localName) + { + if (mElemStack == null) { + return -1; + } + int ix = mElemStack.findAttributeIndex(uri, localName); + // !!! In ns-as-attrs mode, should also match ns decls? + return ix; + } + + @Override + public int getLength() + { + return mAttrCount + mNsCount; + } + + @Override + public String getLocalName(int index) + { + if (index < mAttrCount) { + return (index < 0) ? null : mAttrCollector.getLocalName(index); + } + index -= mAttrCount; + if (index < mNsCount) { + /* As discussed in fireStartTag, we must use + * element stack, not attribute collector: + */ + //String prefix = mAttrCollector.getNsPrefix(index); + String prefix = mElemStack.getLocalNsPrefix(index); + return (prefix == null || prefix.length() == 0) ? + "xmlns" : prefix; + } + return null; + } + + @Override + public String getQName(int index) + { + if (index < mAttrCount) { + if (index < 0) { + return null; + } + String prefix = mAttrCollector.getPrefix(index); + String ln = mAttrCollector.getLocalName(index); + return (prefix == null || prefix.length() == 0) ? + ln : (prefix + ":" + ln); + } + index -= mAttrCount; + if (index < mNsCount) { + /* As discussed in fireStartTag, we must use + * element stack, not attribute collector: + */ + //String prefix = mAttrCollector.getNsPrefix(index); + String prefix = mElemStack.getLocalNsPrefix(index); + if (prefix == null || prefix.length() == 0) { + return "xmlns"; + } + return "xmlns:"+prefix; + } + return null; + } + + @Override + public String getType(int index) + { + if (index < mAttrCount) { + if (index < 0) { + return null; + } + /* Note: Woodstox will have separate type for enumerated values; + * SAX considers these NMTOKENs, so may need to convert (but + * note: some SAX impls also use "ENUMERATED") + */ + String type = mElemStack.getAttributeType(index); + // Let's count on it being interned: + if (type == "ENUMERATED") { + type = "NMTOKEN"; + } + return type; + } + // But how about namespace declarations... let's just call them CDATA? + index -= mAttrCount; + if (index < mNsCount) { + return "CDATA"; + } + return null; + } + + @Override + public String getType(String qName) { + return getType(getIndex(qName)); + } + + @Override + public String getType(String uri, String localName) { + return getType(getIndex(uri, localName)); + } + + @Override + public String getURI(int index) + { + if (index < mAttrCount) { + if (index < 0) { + return null; + } + String uri = mAttrCollector.getURI(index); + return (uri == null) ? "" : uri; + } + if ((index - mAttrCount) < mNsCount) { + return XMLConstants.XMLNS_ATTRIBUTE_NS_URI; + } + return null; + } + + @Override + public String getValue(int index) + { + if (index < mAttrCount) { + return (index < 0) ? null : mAttrCollector.getValue(index); + } + index -= mAttrCount; + if (index < mNsCount) { + /* As discussed in fireStartTag, we must use + * element stack, not attribute collector: + */ + //String uri = mAttrCollector.getNsURI(index); + String uri = mElemStack.getLocalNsURI(index); + return (uri == null) ? "" : uri; + } + return null; + } + + @Override + public String getValue(String qName) { + return getValue(getIndex(qName)); + } + + @Override + public String getValue(String uri, String localName) { + return getValue(getIndex(uri, localName)); + } + + /* + ///////////////////////////////////////////////////// + // Attributes2 (SAX2) implementation + ///////////////////////////////////////////////////// + */ + + @Override + public boolean isDeclared(int index) + { + if (index < mAttrCount) { + if (index >= 0) { + // !!! TODO: implement properly + return true; + } + } else { + index -= mAttrCount; + if (index < mNsCount) { + /* DTD and namespaces don't really play nicely together; + * and in general xmlns: pseudo-attributes are not declared... + * so not quite sure what to return here. For now, let's + * return true, to indicate they ought to be valid + */ + return true; + } + } + throwNoSuchAttribute(index); + return false; // never gets here + } + + @Override + public boolean isDeclared(String qName) { + return false; + } + + @Override + public boolean isDeclared(String uri, String localName) { + return false; + } + + @Override + public boolean isSpecified(int index) + { + if (index < mAttrCount) { + if (index >= 0) { + return mAttrCollector.isSpecified(index); + } + } else { + index -= mAttrCount; + if (index < mNsCount) { + /* Determining default-attr - based namespace declarations + * would need new accessors on Woodstox... but they are + * extremely rare, too + */ + return true; + } + } + throwNoSuchAttribute(index); + return false; // never gets here + } + + @Override + public boolean isSpecified(String qName) + { + int ix = getIndex(qName); + if (ix < 0) { + throw new IllegalArgumentException("No attribute with qName '"+qName+"'"); + } + return isSpecified(ix); + } + + @Override + public boolean isSpecified(String uri, String localName) + { + int ix = getIndex(uri, localName); + if (ix < 0) { + throw new IllegalArgumentException("No attribute with uri "+uri+", local name '"+localName+"'"); + } + return isSpecified(ix); + } + + /* + ///////////////////////////////////////////////////// + // Locator (SAX1) implementation + ///////////////////////////////////////////////////// + */ + + @Override + public int getColumnNumber() + { + if (mScanner != null) { + Location loc = mScanner.getLocation(); + return loc.getColumnNumber(); + } + return -1; + } + + @Override + public int getLineNumber() + { + if (mScanner != null) { + Location loc = mScanner.getLocation(); + return loc.getLineNumber(); + } + return -1; + } + + @Override + public String getPublicId() + { + if (mScanner != null) { + Location loc = mScanner.getLocation(); + return loc.getPublicId(); + } + return null; + } + + @Override + public String getSystemId() { + if (mScanner != null) { + Location loc = mScanner.getLocation(); + return loc.getSystemId(); + } + return null; + } + + /* + ///////////////////////////////////////////////////// + // Locator2 (SAX2) implementation + ///////////////////////////////////////////////////// + */ + + @Override + public String getEncoding() { + return mEncoding; + } + + @Override + public String getXMLVersion() { + return mXmlVersion; + } + + /* + ///////////////////////////////////////////////////// + // DTDEventListener (woodstox internal API) impl + ///////////////////////////////////////////////////// + */ + + @Override + public boolean dtdReportComments() + { + return (mLexicalHandler != null); + } + + @Override + public void dtdComment(char[] data, int offset, int len) + { + if (mLexicalHandler != null) { + try { + mLexicalHandler.comment(data, offset, len); + } catch (SAXException sex) { + throw new WrappedSaxException(sex); + } + } + } + + @Override + public void dtdProcessingInstruction(String target, String data) + { + if (mContentHandler != null) { + try { + mContentHandler.processingInstruction(target, data); + } catch (SAXException sex) { + throw new WrappedSaxException(sex); + } + } + } + + @Override + public void dtdSkippedEntity(String name) + { + if (mContentHandler != null) { + try { + mContentHandler.skippedEntity(name); + } catch (SAXException sex) { + throw new WrappedSaxException(sex); + } + } + } + + // DTD declarations that must be exposed + @Override + public void dtdNotationDecl(String name, String publicId, String systemId, URL baseURL) + throws XMLStreamException + { + if (mDTDHandler != null) { + /* 24-Nov-2006, TSa: Note: SAX expects system identifiers to + * be fully resolved when reported... + */ + if (systemId != null && systemId.indexOf(':') < 0) { + try { + systemId = URLUtil.urlFromSystemId(systemId, baseURL).toExternalForm(); + } catch (IOException ioe) { + throw new WstxIOException(ioe); + } + } + try { + mDTDHandler.notationDecl(name, publicId, systemId); + } catch (SAXException sex) { + throw new WrappedSaxException(sex); + } + } + } + + @Override + public void dtdUnparsedEntityDecl(String name, String publicId, String systemId, String notationName, URL baseURL) + throws XMLStreamException + { + if (mDTDHandler != null) { + // SAX expects system id to be fully resolved? + if (systemId.indexOf(':') < 0) { // relative path... + try { + systemId = URLUtil.urlFromSystemId(systemId, baseURL).toExternalForm(); + } catch (IOException ioe) { + throw new WstxIOException(ioe); + } + } + try { + mDTDHandler.unparsedEntityDecl(name, publicId, systemId, notationName); + } catch (SAXException sex) { + throw new WrappedSaxException(sex); + } + } + } + + // DTD declarations that can be exposed + + @Override + public void attributeDecl(String eName, String aName, String type, String mode, String value) + { + if (mDeclHandler != null) { + try { + mDeclHandler.attributeDecl(eName, aName, type, mode, value); + } catch (SAXException sex) { + throw new WrappedSaxException(sex); + } + } + } + + @Override + public void dtdElementDecl(String name, String model) + { + if (mDeclHandler != null) { + try { + mDeclHandler.elementDecl(name, model); + } catch (SAXException sex) { + throw new WrappedSaxException(sex); + } + } + } + + @Override + public void dtdExternalEntityDecl(String name, String publicId, String systemId) + { + if (mDeclHandler != null) { + try { + mDeclHandler.externalEntityDecl(name, publicId, systemId); + } catch (SAXException sex) { + throw new WrappedSaxException(sex); + } + } + } + + @Override + public void dtdInternalEntityDecl(String name, String value) + { + if (mDeclHandler != null) { + try { + mDeclHandler.internalEntityDecl(name, value); + } catch (SAXException sex) { + throw new WrappedSaxException(sex); + } + } + } + + /* + ///////////////////////////////////////////////// + // Internal methods + ///////////////////////////////////////////////// + */ + + private void throwSaxException(Exception src) + throws SAXException + { + SAXParseException se = new SAXParseException(src.getMessage(), /*(Locator)*/ this, src); + ExceptionUtil.setInitCause(se, src); + if (mErrorHandler != null) { + mErrorHandler.fatalError(se); + } + throw se; + } + + private void throwSaxException(String msg) + throws SAXException + { + SAXParseException se = new SAXParseException(msg, /*(Locator)*/ this); + if (mErrorHandler != null) { + mErrorHandler.fatalError(se); + } + throw se; + } + + private void throwNoSuchAttribute(int index) + { + throw new IllegalArgumentException("No attribute with index "+index+" (have "+(mAttrCount+mNsCount)+" attributes)"); + } + + /* + ///////////////////////////////////////////////// + // Helper class for dealing with entity resolution + ///////////////////////////////////////////////// + */ + + /** + * Simple helper class that converts from Stax API into SAX + * EntityResolver call(s) + */ + final class ResolverProxy + implements XMLResolver + { + public ResolverProxy() { } + + @Override + public Object resolveEntity(String publicID, String systemID, String baseURI, String namespace) + throws XMLStreamException + { + if (mEntityResolver != null) { + try { + /* Hmmh. SAX expects system id to have been mangled prior + * to call... this may work, depending on stax impl: + */ + URL url = new URL(baseURI); + String ref = new URL(url, systemID).toExternalForm(); + InputSource isrc = mEntityResolver.resolveEntity(publicID, ref); + if (isrc != null) { + //System.err.println("Debug: succesfully resolved '"+publicID+"', '"+systemID+"'"); + InputStream in = isrc.getByteStream(); + if (in != null) { + return in; + } + Reader r = isrc.getCharacterStream(); + if (r != null) { + return r; + } + } + + // Returning null should be fine, actually... + return null; + } catch (IOException ex) { + throw new WstxIOException(ex); + } catch (Exception ex) { + throw new XMLStreamException(ex.getMessage(), ex); + } + } + return null; + } + } + + /* + ///////////////////////////////////////////////// + // Helper classes for SAX1 support + ///////////////////////////////////////////////// + */ + + final static class DocHandlerWrapper + implements ContentHandler + { + final DocumentHandler mDocHandler; + + final AttributesWrapper mAttrWrapper = new AttributesWrapper(); + + DocHandlerWrapper(DocumentHandler h) + { + mDocHandler = h; + } + + @Override + public void characters(char[] ch, int start, int length) + throws SAXException + { + mDocHandler.characters(ch, start, length); + } + + @Override + public void endDocument() throws SAXException + { + mDocHandler.endDocument(); + } + + @Override + public void endElement(String uri, String localName, String qName) + throws SAXException + { + if (qName == null) { + qName = localName; + } + mDocHandler.endElement(qName); + } + + @Override + public void endPrefixMapping(String prefix) + { + // no equivalent in SAX1, ignore + } + + @Override + public void ignorableWhitespace(char[] ch, int start, int length) + throws SAXException + { + mDocHandler.ignorableWhitespace(ch, start, length); + } + + @Override + public void processingInstruction(String target, String data) + throws SAXException + { + mDocHandler.processingInstruction(target, data); + } + + @Override + public void setDocumentLocator(Locator locator) { + mDocHandler.setDocumentLocator(locator); + } + + @Override + public void skippedEntity(String name) { + // no equivalent in SAX1, ignore + } + + @Override + public void startDocument() throws SAXException + { + mDocHandler.startDocument(); + } + + @Override + public void startElement(String uri, String localName, String qName, + Attributes attrs) + throws SAXException + { + if (qName == null) { + qName = localName; + } + // Also, need to wrap Attributes to look like AttributeLost + mAttrWrapper.setAttributes(attrs); + mDocHandler.startElement(qName, mAttrWrapper); + } + + @Override + public void startPrefixMapping(String prefix, String uri) { + // no equivalent in SAX1, ignore + } + } + + final static class AttributesWrapper + implements AttributeList + { + Attributes mAttrs; + + public AttributesWrapper() { } + + public void setAttributes(Attributes a) { + mAttrs = a; + } + + @Override + public int getLength() { + return mAttrs.getLength(); + } + + @Override + public String getName(int i) { + String n = mAttrs.getQName(i); + return (n == null) ? mAttrs.getLocalName(i) : n; + } + + @Override + public String getType(int i) { + return mAttrs.getType(i); + } + + @Override + public String getType(String name) { + return mAttrs.getType(name); + } + + @Override + public String getValue(int i) { + return mAttrs.getValue(i); + } + + @Override + public String getValue(String name) { + return mAttrs.getValue(name); + } + } +} + diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/sr/AttributeCollector.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/sr/AttributeCollector.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/sr/AttributeCollector.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/sr/AttributeCollector.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,1174 @@ +/* Woodstox XML processor + * + * Copyright (c) 2004- Tatu Saloranta, tatu.saloranta@iki.fi + * + * Licensed under the License specified in file LICENSE, included with + * the source code. + * You may not use this file except in compliance with the License. + * + * 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 com.ctc.wstx.sr; + +import java.io.IOException; +import java.util.Arrays; + +import javax.xml.XMLConstants; +import javax.xml.stream.Location; +import javax.xml.stream.XMLStreamException; +import javax.xml.namespace.QName; + +import org.codehaus.stax2.ri.typed.CharArrayBase64Decoder; +import org.codehaus.stax2.ri.typed.ValueDecoderFactory; +import org.codehaus.stax2.typed.Base64Variant; +import org.codehaus.stax2.typed.TypedArrayDecoder; +import org.codehaus.stax2.typed.TypedValueDecoder; +import org.codehaus.stax2.typed.TypedXMLStreamException; +import org.codehaus.stax2.validation.XMLValidator; + +import com.ctc.wstx.api.ReaderConfig; +import com.ctc.wstx.cfg.ErrorConsts; +import com.ctc.wstx.sw.XmlWriter; +import com.ctc.wstx.util.*; + +/** + * Shared base class that defines API stream reader uses to communicate + * with the attribute collector implementation, independent of whether it's + * operating in namespace-aware or non-namespace modes. + * Collector class is used to build up attribute lists; for the most part + * will just hold references to few specialized {@link TextBuilder}s that + * are used to create efficient semi-shared value Strings. + */ +public final class AttributeCollector +{ + final static int INT_SPACE = 0x0020; + + /** + * Threshold value that indicates minimum length for lists instances + * that need a Map structure, for fast attribute access by fully-qualified + * name. + */ + protected final static int LONG_ATTR_LIST_LEN = 4; + + /** + * Expected typical maximum number of attributes for any element; + * chosen to minimize need to resize, while trying not to waste space. + * Dynamically grown; better not to set too high to avoid excessive + * overhead for small attribute-less documents. + */ + protected final static int EXP_ATTR_COUNT = 12; + + protected final static int EXP_NS_COUNT = 6; + + /** + * This value is used to indicate that we shouldn't keep track + * of index of xml:id attribute -- generally done when Xml:id + * support is disabled + */ + protected final static int XMLID_IX_DISABLED = -2; + + protected final static int XMLID_IX_NONE = -1; + + protected final static InternCache sInternCache = InternCache.getInstance(); + + /* + /////////////////////////////////////////////////////////// + // Configuration + /////////////////////////////////////////////////////////// + */ + + // // Settings for matching Xml:id attribute + + final String mXmlIdPrefix; + final String mXmlIdLocalName; + + /* + /////////////////////////////////////////////////////////// + // Collected attribute (incl namespace attrs) information: + /////////////////////////////////////////////////////////// + */ + + /** + * Array of attributes collected for this element. + */ + protected Attribute[] mAttributes; + + /** + * Actual number of attributes collected, including attributes + * added via default values. + */ + protected int mAttrCount; + + /** + * Number of attribute values actually parsed, not including + * ones created via default value expansion. Equal to or less than + * {@link #mAttrCount}. + */ + protected int mNonDefCount; + + /** + * Array of namespace declaration attributes collected for this element; + * not used in non-namespace-aware mode + */ + protected Attribute[] mNamespaces; + + /** + * Number of valid namespace declarations in {@link #mNamespaces}. + */ + protected int mNsCount; + + /** + * Flag to indicate whether the default namespace has already been declared + * for the current element. + */ + protected boolean mDefaultNsDeclared = false; + + /** + * Index of "xml:id" attribute, if one exists for the current + * element; {@link #XMLID_IX_NONE} if none. + */ + protected int mXmlIdAttrIndex; + + /* + /////////////////////////////////////////////////////////// + // Attribute (and ns) value builders + /////////////////////////////////////////////////////////// + */ + + /** + * TextBuilder into which values of all attributes are appended + * to, including default valued ones (defaults are added after + * explicit ones). + * Constructed lazily, if and when needed (not needed + * for short attribute-less docs) + */ + protected TextBuilder mValueBuilder = null; + + /** + * TextBuilder into which values of namespace URIs are added (including + * URI for the default namespace, if one defined). + */ + private final TextBuilder mNamespaceBuilder = new TextBuilder(EXP_NS_COUNT); + + /* + ////////////////////////////////////////////////////////////// + // Information that defines "Map-like" data structure used for + // quick access to attribute values by fully-qualified name + ////////////////////////////////////////////////////////////// + */ + + /** + * Encoding of a data structure that contains mapping from + * attribute names to attribute index in main attribute name arrays. + *

+ * Data structure contains two separate areas; main hash area (with + * size mAttrHashSize), and remaining spillover area + * that follows hash area up until (but not including) + * mAttrSpillEnd index. + * Main hash area only contains indexes (index+1; 0 signifying empty slot) + * to actual attributes; spillover area has both hash and index for + * any spilled entry. Spilled entries are simply stored in order + * added, and need to be searched using linear search. In case of both + * primary hash hits and spills, eventual comparison with the local + * name needs to be done with actual name array. + */ + protected int[] mAttrMap = null; + + /** + * Size of hash area in mAttrMap; generally at least 20% + * more than number of attributes (mAttrCount). + */ + protected int mAttrHashSize; + + /** + * Pointer to int slot right after last spill entr, in + * mAttrMap array. + */ + protected int mAttrSpillEnd; + + protected int mMaxAttributesPerElement; + protected int mMaxAttributeSize; + + /* + /////////////////////////////////////////////// + // Life-cycle: + /////////////////////////////////////////////// + */ + + protected AttributeCollector(ReaderConfig cfg, boolean nsAware) + { + mXmlIdAttrIndex = cfg.willDoXmlIdTyping() ? XMLID_IX_NONE : XMLID_IX_DISABLED; + if (nsAware) { + mXmlIdPrefix = "xml"; + mXmlIdLocalName = "id"; + } else { + mXmlIdPrefix = null; + mXmlIdLocalName = "xml:id"; + } + mMaxAttributesPerElement = cfg.getMaxAttributesPerElement(); + mMaxAttributeSize = cfg.getMaxAttributeSize(); + } + + /** + * Method called to allow reusing of collector, usually right before + * starting collecting attributes for a new start tag. + */ + /** + * Method called to allow reusing of collector, usually right before + * starting collecting attributes for a new start tag. + *

+ * Note: public only so that it can be called by unit tests. + */ + public void reset() + { + if (mNsCount > 0) { + mNamespaceBuilder.reset(); + mDefaultNsDeclared = false; + mNsCount = 0; + } + + /* No need to clear attr name, or NS prefix Strings; they are + * canonicalized and will be referenced by symbol table in any + * case... so we can save trouble of cleaning them up. This Object + * will get GC'ed soon enough, after parser itself gets disposed of. + */ + if (mAttrCount > 0) { + mValueBuilder.reset(); + mAttrCount = 0; + if (mXmlIdAttrIndex >= 0) { + mXmlIdAttrIndex = XMLID_IX_NONE; + } + } + /* Note: attribute values will be cleared later on, when validating + * namespaces. This so that we know how much to clean up; and + * occasionally can also just avoid clean up (when resizing) + */ + } + + /** + * Method that can be called to force space normalization (remove + * leading/trailing spaces, replace non-spaces white space with + * spaces, collapse spaces to one) on specified attribute. + * Currently called by {@link InputElementStack} to force + * normalization of Xml:id attribute + */ + public void normalizeSpacesInValue(int index) + { + // StringUtil has a method, but it works on char arrays... + char[] attrCB = mValueBuilder.getCharBuffer(); + String normValue = StringUtil.normalizeSpaces + (attrCB, getValueStartOffset(index), getValueStartOffset(index+1)); + if (normValue != null) { + mAttributes[index].setValue(normValue); + } + } + + /* + /////////////////////////////////////////////// + // Public accesors (for stream reader) + /////////////////////////////////////////////// + */ + + /** + * @return Number of namespace declarations collected, including + * possible default namespace declaration + */ + protected int getNsCount() { + return mNsCount; + } + + public boolean hasDefaultNs() { + return mDefaultNsDeclared; + } + + // // // Direct access to attribute/NS prefixes/localnames/URI + + public final int getCount() { + return mAttrCount; + } + + /** + * @return Number of attributes that were explicitly specified; may + * be less than the total count due to attributes created using + * attribute default values + */ + public int getSpecifiedCount() { + return mNonDefCount; + } + + public String getNsPrefix(int index) { + if (index < 0 || index >= mNsCount) { + throwIndex(index); + } + // for NS decls, local name is stored in prefix + return mNamespaces[index].mLocalName; + } + + public String getNsURI(int index) { + if (index < 0 || index >= mNsCount) { + throwIndex(index); + } + return mNamespaces[index].mNamespaceURI; + } + + // // // Direct access to attribute/NS prefixes/localnames/URI + + public String getPrefix(int index) { + if (index < 0 || index >= mAttrCount) { + throwIndex(index); + } + return mAttributes[index].mPrefix; + } + + public String getLocalName(int index) { + if (index < 0 || index >= mAttrCount) { + throwIndex(index); + } + return mAttributes[index].mLocalName; + } + + public String getURI(int index) { + if (index < 0 || index >= mAttrCount) { + throwIndex(index); + } + return mAttributes[index].mNamespaceURI; + } + + public QName getQName(int index) { + if (index < 0 || index >= mAttrCount) { + throwIndex(index); + } + return mAttributes[index].getQName(); + } + + /** + *

+ * Note: the main reason this method is defined at this level, and + * made final, is performance. JIT may be able to fully inline this + * method, even when reference is via this base class. This is important + * since this is likely to be the most often called method of the + * collector instances. + */ + public final String getValue(int index) + { + if (index < 0 || index >= mAttrCount) { + throwIndex(index); + } + String full = mValueBuilder.getAllValues(); + Attribute attr = mAttributes[index]; + ++index; + if (index < mAttrCount) { // not last + int endOffset = mAttributes[index].mValueStartOffset; + return attr.getValue(full, endOffset); + } + // last can be optimized bit more: + return attr.getValue(full); + } + + public String getValue(String nsURI, String localName) + { + // Primary hit? + int hashSize = mAttrHashSize; + if (hashSize == 0) { // sanity check, for 'no attributes' + return null; + } + int hash = localName.hashCode(); + if (nsURI != null) { + if (nsURI.length() == 0) { + nsURI = null; + } else { + hash ^= nsURI.hashCode(); + } + } + int ix = mAttrMap[hash & (hashSize-1)]; + if (ix == 0) { // nothing in here; no spills either + return null; + } + --ix; + + // Is primary candidate match? + if (mAttributes[ix].hasQName(nsURI, localName)) { + return getValue(ix); + } + + /* Nope, need to traverse spill list, which has 2 entries for + * each spilled attribute id; first for hash value, second index. + */ + for (int i = hashSize, len = mAttrSpillEnd; i < len; i += 2) { + if (mAttrMap[i] != hash) { + continue; + } + /* Note: spill indexes are not off-by-one, since there's no need + * to mask 0 + */ + ix = mAttrMap[i+1]; + if (mAttributes[ix].hasQName(nsURI, localName)) { + return getValue(ix); + } + } + + return null; + } + + public int getMaxAttributesPerElement() { + return mMaxAttributesPerElement; + } + + public void setMaxAttributesPerElement(int maxAttributesPerElement) { + this.mMaxAttributesPerElement = maxAttributesPerElement; + } + + public int findIndex(String localName) { + return findIndex(null, localName); + } + + public int findIndex(String nsURI, String localName) + { + /* Note: most of the code is from getValue().. could refactor + * code, performance is bit of concern (one more method call + * if index access was separate). + * See comments on that method, for logics. + */ + + // Primary hit? + int hashSize = mAttrHashSize; + if (hashSize == 0) { // sanity check, for 'no attributes' + return -1; + } + int hash = localName.hashCode(); + if (nsURI != null) { + if (nsURI.length() == 0) { + nsURI = null; + } else { + hash ^= nsURI.hashCode(); + } + } + int ix = mAttrMap[hash & (hashSize-1)]; + if (ix == 0) { // nothing in here; no spills either + return -1; + } + --ix; + + // Is primary candidate match? + if (mAttributes[ix].hasQName(nsURI, localName)) { + return ix; + } + + /* Nope, need to traverse spill list, which has 2 entries for + * each spilled attribute id; first for hash value, second index. + */ + for (int i = hashSize, len = mAttrSpillEnd; i < len; i += 2) { + if (mAttrMap[i] != hash) { + continue; + } + /* Note: spill indexes are not off-by-one, since there's no need + * to mask 0 + */ + ix = mAttrMap[i+1]; + if (mAttributes[ix].hasQName(nsURI, localName)) { + return ix; + } + } + return -1; + } + + public final boolean isSpecified(int index) { + return (index < mNonDefCount); + } + + public final int getXmlIdAttrIndex() { + return mXmlIdAttrIndex; + } + + /* + ////////////////////////////////////////////////////// + // Type-safe accessors to support TypedXMLStreamReader + ////////////////////////////////////////////////////// + */ + + /** + * Method called to decode the whole attribute value as a single + * typed value. + * Decoding is done using the decoder provided. + */ + public final void decodeValue(int index, TypedValueDecoder tvd) + throws IllegalArgumentException + { + if (index < 0 || index >= mAttrCount) { + throwIndex(index); + } + /* Should be faster to pass the char array even if we might + * have a String + */ + // Either way, need to trim before passing: + char[] buf = mValueBuilder.getCharBuffer(); + int start = mAttributes[index].mValueStartOffset; + int end = getValueStartOffset(index+1); + + while (true) { + if (start >= end) { + tvd.handleEmptyValue(); + return; + } + if (!StringUtil.isSpace(buf[start])) { + break; + } + ++start; + } + // Trailing space? + while (--end > start && StringUtil.isSpace(buf[end])) { } + tvd.decode(buf, start, end+1); + } + + /** + * Method called to decode the attribute value that consists of + * zero or more space-separated tokens. + * Decoding is done using the decoder provided. + * @return Number of tokens decoded + */ + public final int decodeValues(int index, TypedArrayDecoder tad, + InputProblemReporter rep) + throws XMLStreamException + { + if (index < 0 || index >= mAttrCount) { + throwIndex(index); + } + // Char[] faster than String... and no need to trim here: + return decodeValues(tad, rep, + mValueBuilder.getCharBuffer(), + mAttributes[index].mValueStartOffset, + getValueStartOffset(index+1)); + } + + public final byte[] decodeBinary(int index, Base64Variant v, CharArrayBase64Decoder dec, + InputProblemReporter rep) + throws XMLStreamException + { + if (index < 0 || index >= mAttrCount) { + throwIndex(index); + } + /* No point in trying to use String representation, even if one + * available, faster to process from char[] + */ + Attribute attr = mAttributes[index]; + char[] cbuf = mValueBuilder.getCharBuffer(); + int start = attr.mValueStartOffset; + int end = getValueStartOffset(index+1); + int len = end-start; + dec.init(v, true, cbuf, start, len, null); + try { + return dec.decodeCompletely(); + } catch (IllegalArgumentException iae) { + // Need to convert to a checked stream exception + String lexical = new String(cbuf, start, len); + throw new TypedXMLStreamException(lexical, iae.getMessage(), rep.getLocation(), iae); + } + } + + private final static int decodeValues(TypedArrayDecoder tad, + InputProblemReporter rep, + final char[] buf, int ptr, final int end) + throws XMLStreamException + { + int start = ptr; + int count = 0; + + try { + decode_loop: + while (ptr < end) { + // First, any space to skip? + while (buf[ptr] <= INT_SPACE) { + if (++ptr >= end) { + break decode_loop; + } + } + // Then let's figure out non-space char (token) + start = ptr; + ++ptr; + while (ptr < end && buf[ptr] > INT_SPACE) { + ++ptr; + } + int tokenEnd = ptr; + ++ptr; // to skip trailing space (or, beyond end) + // Ok, decode... any more room? + ++count; + if (tad.decodeValue(buf, start, tokenEnd)) { + if (!checkExpand(tad)) { + break; + } + } + } + } catch (IllegalArgumentException iae) { + // Need to convert to a checked stream exception + Location loc = rep.getLocation(); + String lexical = new String(buf, start, (ptr-start)); + throw new TypedXMLStreamException(lexical, iae.getMessage(), loc, iae); + } + return count; + } + + /** + * Internal method used to see if we can expand the buffer that + * the array decoder has. Bit messy, but simpler than having + * separately typed instances; and called rarely so that performance + * downside of instanceof is irrelevant. + */ + private final static boolean checkExpand(TypedArrayDecoder tad) + { + if (tad instanceof ValueDecoderFactory.BaseArrayDecoder) { + ((ValueDecoderFactory.BaseArrayDecoder) tad).expand(); + return true; + } + return false; + } + + /* + /////////////////////////////////////////////// + // Accessors for accessing helper objects + /////////////////////////////////////////////// + */ + + /** + * Method for getting start pointer within shared value buffer + * for given attribute. It is also the same as end pointer + * for preceding attribute, if any. + */ + protected int getValueStartOffset(int index) + { + if (index < mAttrCount) { + return mAttributes[index].mValueStartOffset; + } + return mValueBuilder.getCharSize(); + } + + protected char[] getSharedValueBuffer() + { + return mValueBuilder.getCharBuffer(); + } + + /** + * Method called to resolve and initialize specified collected + * namespace declaration + * + * @return Attribute that contains specified namespace declaration + */ + protected Attribute resolveNamespaceDecl(int index, boolean internURI) + { + Attribute ns = mNamespaces[index]; + String full = mNamespaceBuilder.getAllValues(); + String uri; + + if (mNsCount == 0) { + uri = full; + } else { + ++index; + if (index < mNsCount) { // not last + int endOffset = mNamespaces[index].mValueStartOffset; + uri = ns.getValue(full, endOffset); + } else { // is last + uri = ns.getValue(full); + } + } + if (internURI && uri.length() > 0) { + uri = sInternCache.intern(uri); + } + ns.mNamespaceURI = uri; + return ns; + } + + /** + * Method needed by event creating code, to build a non-transient + * attribute container, to use with XMLEvent objects (specifically + * implementation of StartElement event). + */ + public ElemAttrs buildAttrOb() + { + int count = mAttrCount; + if (count == 0) { + return null; + } + // If we have actual attributes, let's first just create the + // raw array that has all attribute information: + String[] raw = new String[count << 2]; + for (int i = 0; i < count; ++i) { + Attribute attr = mAttributes[i]; + int ix = (i << 2); + raw[ix] = attr.mLocalName; + raw[ix+1] = attr.mNamespaceURI; + raw[ix+2] = attr.mPrefix; + raw[ix+3] = getValue(i); + } + + // Do we have a "short" list? + if (count < LONG_ATTR_LIST_LEN) { + return new ElemAttrs(raw, mNonDefCount); + } + + // Ok, nope; we need to also pass the Map information... + /* 02-Feb-2009, TSa: Must make a copy of the Map array now, + * otherwise could get overwritten. + */ + int amapLen = mAttrMap.length; + int[] amap = new int[amapLen]; + // TODO: JDK 1.6 has Arrays.copyOf(), should use with Woodstox 6 + System.arraycopy(mAttrMap, 0, amap, 0, amapLen); + return new ElemAttrs(raw, mNonDefCount, + amap, mAttrHashSize, mAttrSpillEnd); + } + + protected void validateAttribute(int index, XMLValidator vld) + throws XMLStreamException + { + Attribute attr = mAttributes[index]; + String normValue = vld.validateAttribute + (attr.mLocalName, attr.mNamespaceURI, attr.mPrefix, + mValueBuilder.getCharBuffer(), + getValueStartOffset(index), + getValueStartOffset(index+1)); + + if (normValue != null) { + attr.setValue(normValue); + } + } + + /* + /////////////////////////////////////////////// + // Attribute, namespace decl building + /////////////////////////////////////////////// + */ + + /** + * Low-level accessor method that attribute validation code may call + * for certain types of attributes; generally only for id and idref/idrefs + * attributes. It returns the underlying 'raw' attribute value buffer + * for direct access. + */ + public final TextBuilder getAttrBuilder(String attrPrefix, String attrLocalName) throws XMLStreamException + { + /* Ok: we have parsed prefixed-name of a regular + * attribute. So let's initialize the instance... + */ + if (mAttrCount == 0) { + if (mAttributes == null) { + allocBuffers(); + } + mAttributes[0] = new Attribute(attrPrefix, attrLocalName, 0); + } else { + int valueStart = mValueBuilder.getCharSize(); + if (mAttrCount >= mAttributes.length) { + if ((mAttrCount + mNsCount) >= mMaxAttributesPerElement) { + throw new XMLStreamException("Attribute limit ("+mMaxAttributesPerElement+") exceeded"); + } + mAttributes = (Attribute[]) DataUtil.growArrayBy50Pct(mAttributes); + } + Attribute curr = mAttributes[mAttrCount]; + if (curr == null) { + mAttributes[mAttrCount] = new Attribute(attrPrefix, attrLocalName, valueStart); + } else { + curr.reset(attrPrefix, attrLocalName, valueStart); + } + } + ++mAttrCount; + // 25-Sep-2006, TSa: Need to keep track of xml:id attribute? + if (attrLocalName == mXmlIdLocalName) { + if (attrPrefix == mXmlIdPrefix) { + if (mXmlIdAttrIndex != XMLID_IX_DISABLED) { + mXmlIdAttrIndex = mAttrCount - 1; + } + } + } + /* Can't yet create attribute map by name, since we only know + * name prefix, not necessarily matching URI. + */ + return mValueBuilder; + } + + /** + * Method called by validator to insert an attribute that has a default + * value and wasn't yet included in collector's attribute set. + * + * @return Index of the newly added attribute, if added; -1 to indicate + * this was a duplicate + */ + public int addDefaultAttribute(String localName, String uri, String prefix, + String value) throws XMLStreamException + { + int attrIndex = mAttrCount; + if (attrIndex < 1) { + /* had no explicit attributes... better initialize now, then. + * Let's just use hash area of 4, and + */ + initHashArea(); + } + + /* Ok, first, since we do want to verify that we can not accidentally + * add duplicates, let's first try to add entry to Map, since that + * will catch dups. + */ + int hash = localName.hashCode(); + if (uri != null && uri.length() > 0) { + hash ^= uri.hashCode(); + } + int index = hash & (mAttrHashSize - 1); + int[] map = mAttrMap; + if (map[index] == 0) { // whoa, have room... + map[index] = attrIndex+1; // add 1 to get 1-based index (0 is empty marker) + } else { // nah, collision... + int currIndex = map[index]-1; // Index of primary collision entry + int spillIndex = mAttrSpillEnd; + map = spillAttr(uri, localName, map, currIndex, spillIndex, + hash, mAttrHashSize); + if (map == null) { // dup! + return -1; // could return negation (-(index+1)) of the prev index? + } + map[++spillIndex] = attrIndex; // no need to specifically avoid 0 + mAttrMap = map; + mAttrSpillEnd = ++spillIndex; + } + + /* Can reuse code; while we don't really need the builder, + * we need to add/reset attribute + */ + getAttrBuilder(prefix, localName); + Attribute attr = mAttributes[mAttrCount-1]; + attr.mNamespaceURI = uri; + attr.setValue(value); + // attribute count has been updated; index is one less than count + return (mAttrCount-1); + } + + /** + * Low-level mutator method that attribute validation code may call + * for certain types of attributes, when it wants to handle the whole + * validation and normalization process by itself. It is generally + * only called for id and idref/idrefs attributes, as those values + * are usually normalized. + */ + public final void setNormalizedValue(int index, String value) + { + mAttributes[index].setValue(value); + } + + /** + * @return null if the default namespace URI has been already declared + * for the current element; TextBuilder to add URI to if not. + */ + public TextBuilder getDefaultNsBuilder() throws XMLStreamException + { + if (mDefaultNsDeclared) { + return null; + } + mDefaultNsDeclared = true; + return getNsBuilder(null); + } + + /** + * @return null if prefix has been already declared; TextBuilder to + * add value to if not. + */ + public TextBuilder getNsBuilder(String prefix) throws XMLStreamException + { + // first: must verify that it's not a dup + if (mNsCount == 0) { + if (mNamespaces == null) { + mNamespaces = new Attribute[EXP_NS_COUNT]; + } + mNamespaces[0] = new Attribute(null, prefix, 0); + } else { + int len = mNsCount; + /* Ok: must ensure that there are no duplicate namespace + * declarations (ie. decls with same prefix being bound) + */ + if (prefix != null) { // null == default ns + for (int i = 0; i < len; ++i) { + // note: for ns decls, bound prefix is in 'local name' + if (prefix == mNamespaces[i].mLocalName) { + return null; + } + } + } + if (len >= mNamespaces.length) { + if ((mAttrCount + mNsCount) >= mMaxAttributesPerElement) { + throw new XMLStreamException("Attribute limit ("+mMaxAttributesPerElement+") exceeded"); + } + mNamespaces = (Attribute[]) DataUtil.growArrayBy50Pct(mNamespaces); + } + int uriStart = mNamespaceBuilder.getCharSize(); + Attribute curr = mNamespaces[len]; + if (curr == null) { + mNamespaces[len] = new Attribute(null, prefix, uriStart); + } else { + curr.reset(null, prefix, uriStart); + } + } + ++mNsCount; + return mNamespaceBuilder; + } + + /** + * Method called to resolve namespace URIs from attribute prefixes. + *

+ * Note: public only so that it can be called by unit tests. + * + * @param rep Reporter to use for reporting well-formedness problems + * @param ns Namespace prefix/URI mappings active for this element + * + * @return Index of xml:id attribute, if any, -1 if not + */ + public int resolveNamespaces(InputProblemReporter rep, StringVector ns) + throws XMLStreamException + { + int attrCount = mAttrCount; + + /* Let's now set number of 'real' attributes, to allow figuring + * out number of attributes created via default value expansion + */ + mNonDefCount = attrCount; + + if (attrCount < 1) { + // Checked if doing access by FQN: + mAttrHashSize = mAttrSpillEnd = 0; + // And let's just bail out, too... + return mXmlIdAttrIndex; + } + for (int i = 0; i < attrCount; ++i) { + Attribute attr = mAttributes[i]; + String prefix = attr.mPrefix; + // Attributes' ns URI is null after reset, so can skip setting "no namespace" + if (prefix != null) { + if (prefix == "xml") { + attr.mNamespaceURI = XMLConstants.XML_NS_URI; + } else { + String uri = ns.findLastFromMap(prefix); + if (uri == null) { + rep.throwParseError(ErrorConsts.ERR_NS_UNDECLARED_FOR_ATTR, + prefix, attr.mLocalName); + } + attr.mNamespaceURI = uri; + } + } + } + + /* Ok, finally, let's create attribute map, to allow efficient + * access by prefix+localname combination. Could do it on-demand, + * but this way we can check for duplicates right away. + */ + int[] map = mAttrMap; + + /* What's minimum size to contain at most 80% full hash area, + * plus 1/8 spill area (12.5% spilled entries, two ints each)? + */ + int hashCount = 4; + { + int min = attrCount + (attrCount >> 2); // == 80% fill rate + /* Need to get 2^N size that can contain all elements, with + * 80% fill rate + */ + while (hashCount < min) { + hashCount += hashCount; // 2x + } + // And then add the spill area + mAttrHashSize = hashCount; + min = hashCount + (hashCount >> 4); // 12.5 x 2 ints + if (map == null || map.length < min) { + map = new int[min]; + } else { + /* Need to clear old hash entries (if any). But note that + * spilled entries we can leave alone -- they are just ints, + * and get overwritten if and as needed + */ + Arrays.fill(map, 0, hashCount, 0); + } + } + + { + int mask = hashCount-1; + int spillIndex = hashCount; + + // Ok, array's fine, let's hash 'em in! + for (int i = 0; i < attrCount; ++i) { + Attribute attr = mAttributes[i]; + String name = attr.mLocalName; + int hash = name.hashCode(); + String uri = attr.mNamespaceURI; + if (uri != null) { + hash ^= uri.hashCode(); + } + int index = hash & mask; + // Hash slot available? + if (map[index] == 0) { + map[index] = i+1; // since 0 is marker + } else { + int currIndex = map[index]-1; + /* nope, need to spill; let's extract most of that code to + * a separate method for clarity (and maybe it'll be + * easier to inline by JVM too) + */ + map = spillAttr(uri, name, map, currIndex, spillIndex, + hash, hashCount); + if (map == null) { + throwDupAttr(rep, currIndex); + // never returns here... + } else { // let's use else to keep FindBugs happy + map[++spillIndex] = i; // no need to specifically avoid 0 + ++spillIndex; + } + } + } + mAttrSpillEnd = spillIndex; + } + mAttrMap = map; + return mXmlIdAttrIndex; + } + + /* + /////////////////////////////////////////////// + // Package/core methods: + /////////////////////////////////////////////// + */ + + protected void throwIndex(int index) { + throw new IllegalArgumentException("Invalid index "+index+"; current element has only "+getCount()+" attributes"); + } + + /** + * @deprecated Since 5.0.3 + */ + @Deprecated + public void writeAttribute(int index, XmlWriter xw) throws IOException, XMLStreamException { + writeAttribute(index, xw, null); + } + + /** + * Method that basically serializes the specified (read-in) attribute + * using Writers provided. Serialization is done by + * writing out (fully-qualified) name + * of the attribute, followed by the equals sign and quoted value. + */ + public void writeAttribute(int index, XmlWriter xw, XMLValidator validator) + throws IOException, XMLStreamException + { + // Note: here we assume index checks have been done by caller + Attribute attr = mAttributes[index]; + String ln = attr.mLocalName; + String prefix = attr.mPrefix; + final String value = getValue(index); + if (prefix == null || prefix.length() == 0) { + xw.writeAttribute(ln, value); + } else { + xw.writeAttribute(prefix, ln, value); + } + if (validator != null) { + validator.validateAttribute(ln, attr.mNamespaceURI, prefix, value); + } + } + + /** + * Method called to initialize buffers that need not be immediately + * initialized + */ + protected final void allocBuffers() + { + if (mAttributes == null) { + mAttributes = new Attribute[8]; + } + if (mValueBuilder == null) { + mValueBuilder = new TextBuilder(EXP_ATTR_COUNT); + } + } + + /* + /////////////////////////////////////////////// + // Internal methods: + /////////////////////////////////////////////// + */ + + /** + * @return Null, if attribute is a duplicate (to indicate error); + * map itself, or resized version, otherwise. + */ + private int[] spillAttr(String uri, String name, + int[] map, int currIndex, int spillIndex, + int hash, int hashCount) + { + // Do we have a dup with primary entry? + /* Can do equality comp for local name, as they + * are always canonicalized: + */ + Attribute oldAttr = mAttributes[currIndex]; + if (oldAttr.mLocalName == name) { + // URIs may or may not be interned though: + String currURI = oldAttr.mNamespaceURI; + if (currURI == uri || (currURI != null && currURI.equals(uri))) { + return null; + } + } + + /* Is there room to spill into? (need to 2 int spaces; one for hash, + * the other for index) + */ + if ((spillIndex + 1)>= map.length) { + // Let's just add room for 4 spills... + map = DataUtil.growArrayBy(map, 8); + } + // Let's first ensure we aren't adding a dup: + for (int j = hashCount; j < spillIndex; j += 2) { + if (map[j] == hash) { + currIndex = map[j+1]; + Attribute attr = mAttributes[currIndex]; + if (attr.mLocalName == name) { + String currURI = attr.mNamespaceURI; + if (currURI == uri || (currURI != null && currURI.equals(uri))) { + return null; + } + } + } + } + map[spillIndex] = hash; + return map; + } + + /** + * Method called to ensure hash area will be properly set up in + * cases where initially no room was needed, but default attribute(s) + * is being added. + */ + private void initHashArea() + { + /* Let's use small hash area of size 4, and one spill; don't + * want too big (need to clear up room), nor too small (only + * collisions) + */ + mAttrHashSize = mAttrSpillEnd = 4; + if (mAttrMap == null || mAttrMap.length < mAttrHashSize) { + mAttrMap = new int[mAttrHashSize+1]; + } + mAttrMap[0] = mAttrMap[1] = mAttrMap[2] = mAttrMap[3] = 0; + allocBuffers(); + } + + /** + * Method that can be used to get the specified attribute value, + * by getting it written using Writer passed in. Can potentially + * save one String allocation, since no (temporary) Strings need + * to be created. + */ + /* + protected final void writeValue(int index, Writer w) + throws IOException + { + mValueBuilder.getEntry(index, w); + } + */ + + protected void throwDupAttr(InputProblemReporter rep, int index) + throws XMLStreamException + { + rep.throwParseError("Duplicate attribute '"+getQName(index)+"'."); + } +} diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/sr/Attribute.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/sr/Attribute.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/sr/Attribute.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/sr/Attribute.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,153 @@ +/* Woodstox XML processor + * + * Copyright (c) 2004- Tatu Saloranta, tatu.saloranta@iki.fi + * + * Licensed under the License specified in file LICENSE, included with + * the source code. + * You may not use this file except in compliance with the License. + * + * 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 com.ctc.wstx.sr; + +import javax.xml.namespace.QName; + +import com.ctc.wstx.compat.QNameCreator; + +/** + * Container for information collected regarding a single element + * attribute instance. Used for both regular explicit attributes + * and values added via attribute value defaulting. + *

+ * This class is not exposed outside of the package and is considered + * part of internal implementation. + * + * @since 4.1 + */ +final class Attribute +{ + // // // Name information + + protected String mLocalName; + + protected String mPrefix; + + protected String mNamespaceURI; + + // // // Value information + + /** + * Numeric offset within text builder that denotes pointer + * to the first character of the value for this attribute + * (or namespace). End offset is derived by looking at + * start pointer of the following attribute; or total + * length for the last entry + */ + protected int mValueStartOffset; + + /** + * Value as a String iff it has been requested once; stored + * here in case it will be accessed again. + */ + protected String mReusableValue; + + /* + ////////////////////////////////////////////////// + // Life-cycle + ////////////////////////////////////////////////// + */ + + public Attribute(String prefix, String localName, int valueStart) + { + mLocalName = localName; + mPrefix = prefix; + mValueStartOffset = valueStart; + } + + public void reset(String prefix, String localName, int valueStart) + { + mLocalName = localName; + mPrefix = prefix; + mValueStartOffset = valueStart; + mNamespaceURI = null; + mReusableValue = null; + } + + /** + * Method called to inject specific value for this attribute. + */ + public void setValue(String value) { + mReusableValue = value; + } + + /* + ////////////////////////////////////////////////// + // Accessors + ////////////////////////////////////////////////// + */ + + /** + * @param uri Namespace URI of the attribute, if any; MUST be + * given as null if no namespace + * @param localName Local name to match. Note: is NOT guaranteed + * to have been interned + * + * @return True if qualified name of this attribute is the same + * as what arguments describe + */ + protected boolean hasQName(String uri, String localName) + { + if (localName != mLocalName && !localName.equals(mLocalName)) { + return false; + } + if (mNamespaceURI == uri) { + return true; + } + if (uri == null) { + return (mNamespaceURI == null) || mNamespaceURI.length() == 0; + } + return (mNamespaceURI != null && uri.equals(mNamespaceURI)); + } + + public QName getQName() + { + if (mPrefix == null) { + if (mNamespaceURI == null) { + return new QName(mLocalName); + } + return new QName(mNamespaceURI, mLocalName); + } + String uri = mNamespaceURI; + if (uri == null) { // Some QName impls (older JDKs) don't like nulls + uri = ""; + } + // For [WSTX-174] need to use indirection: + return QNameCreator.create(uri, mLocalName, mPrefix); + } + + /** + * Method called if this attribute is the last one with value + * in the buffer. If so, end value is implied + */ + public String getValue(String allValues) + { + if (mReusableValue == null) { + mReusableValue = (mValueStartOffset == 0) ? + allValues : allValues.substring(mValueStartOffset); + } + return mReusableValue; + } + + public String getValue(String allValues, int endOffset) + { + if (mReusableValue == null) { + mReusableValue = allValues.substring(mValueStartOffset, endOffset); + } + return mReusableValue; + } +} diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/sr/BasicStreamReader.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/sr/BasicStreamReader.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/sr/BasicStreamReader.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/sr/BasicStreamReader.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,5619 @@ +/* Woodstox XML processor + * + * Copyright (c) 2004- Tatu Saloranta, tatu.saloranta@iki.fi + * + * Licensed under the License specified in file LICENSE, included with + * the source code. + * You may not use this file except in compliance with the License. + * + * 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 com.ctc.wstx.sr; + +import java.io.*; +import java.text.MessageFormat; +import java.util.Map; + +import org.xml.sax.Attributes; +import org.xml.sax.ContentHandler; +import org.xml.sax.SAXException; +import org.xml.sax.ext.LexicalHandler; + +import javax.xml.namespace.NamespaceContext; +import javax.xml.namespace.QName; +import javax.xml.stream.Location; +import javax.xml.stream.XMLStreamException; + +import org.codehaus.stax2.AttributeInfo; +import org.codehaus.stax2.DTDInfo; +import org.codehaus.stax2.LocationInfo; +import org.codehaus.stax2.XMLStreamLocation2; +import org.codehaus.stax2.XMLStreamProperties; +import org.codehaus.stax2.XMLStreamReader2; +import org.codehaus.stax2.typed.TypedXMLStreamException; +import org.codehaus.stax2.validation.*; + +import com.ctc.wstx.api.ReaderConfig; +import com.ctc.wstx.api.WstxInputProperties; +import com.ctc.wstx.cfg.ErrorConsts; +import com.ctc.wstx.cfg.XmlConsts; +import com.ctc.wstx.dtd.MinimalDTDReader; +import com.ctc.wstx.ent.EntityDecl; +import com.ctc.wstx.exc.WstxException; +import com.ctc.wstx.io.*; +import com.ctc.wstx.util.DefaultXmlSymbolTable; +import com.ctc.wstx.util.TextBuffer; +import com.ctc.wstx.util.TextBuilder; + +/** + * Partial implementation of {@link XMLStreamReader2} consisting of + * all functionality other than DTD-validation-specific parts, and + * Typed Access API (Stax2 v3.0), which are implemented at + * sub-classes. + * + * @author Tatu Saloranta + */ +public abstract class BasicStreamReader + extends StreamScanner + implements StreamReaderImpl, DTDInfo, LocationInfo +{ + /* + /////////////////////////////////////////////////////////////////////// + // Constants + /////////////////////////////////////////////////////////////////////// + */ + + // // // Standalone values: + + final static int DOC_STANDALONE_UNKNOWN = 0; + final static int DOC_STANDALONE_YES = 1; + final static int DOC_STANDALONE_NO = 2; + + // // // Main state consts: + + final static int STATE_PROLOG = 0; // Before root element + final static int STATE_TREE = 1; // Parsing actual XML tree + final static int STATE_EPILOG = 2; // After root element has been closed + final static int STATE_MULTIDOC_HACK = 3; // State "between" multiple documents (in multi-doc mode) + final static int STATE_CLOSED = 4; // After reader has been closed + + // // // Tokenization state consts: + + // no idea as to what comes next (unknown type): + final static int TOKEN_NOT_STARTED = 0; + + // token type figured out, but not long enough: + final static int TOKEN_STARTED = 1; + + /* minimum token length returnable achieved; only used for + * CHARACTERS event which allow fragments to be returned (and for + * CDATA in some limited cases) + */ + final static int TOKEN_PARTIAL_SINGLE = 2; + + /* a single physical event has been successfully tokenized; as with + * partial, only used with CDATA and CHARACTERS (meaningless for others, + * which should only use TOKEN_FULL_COALESCED, TOKEN_NOT_STARTED or + * TOKEN_STARTED. + */ + final static int TOKEN_FULL_SINGLE = 3; + + /* all adjacent (text) events have been tokenized and coalesced (for + * CDATA and CHARACTERS), or that the full event has been parsed (for + * others) + */ + final static int TOKEN_FULL_COALESCED = 4; + + // // // Bit masks used for quick type comparisons + + /** + * This mask covers all types for which basic {@link #getText} method + * can be called. + */ + final protected static int MASK_GET_TEXT = + (1 << CHARACTERS) | (1 << CDATA) | (1 << SPACE) + | (1 << COMMENT) | (1 << DTD) | (1 << ENTITY_REFERENCE); + + /** + * This mask covers all types for which extends getTextXxx + * methods can be called; which is less than those for which + * {@link #getText} can be called. Specifically, DTD and + * ENTITY_REFERENCE types do not support these extended + */ + final protected static int MASK_GET_TEXT_XXX = + (1 << CHARACTERS) | (1 << CDATA) | (1 << SPACE) | (1 << COMMENT); + + /** + * This mask is used with Stax2 getText() method (one that takes + * Writer as an argument): accepts even wider range of event types. + */ + final protected static int MASK_GET_TEXT_WITH_WRITER = + (1 << CHARACTERS) | (1 << CDATA) | (1 << SPACE) + | (1 << COMMENT) | (1 << DTD) | (1 << ENTITY_REFERENCE) + | (1 << PROCESSING_INSTRUCTION); + + final protected static int MASK_GET_ELEMENT_TEXT = + (1 << CHARACTERS) | (1 << CDATA) | (1 << SPACE) + | (1 << ENTITY_REFERENCE); + + + // // // Indicator of type of text in text event (WRT white space) + + final static int ALL_WS_UNKNOWN = 0x0000; + final static int ALL_WS_YES = 0x0001; + final static int ALL_WS_NO = 0x0002; + + /* 2 magic constants used for enabling/disabling indentation checks: + * (to minimize negative impact for both small docs, and large + * docs with non-regular white space) + */ + + private final static int INDENT_CHECK_START = 16; + + private final static int INDENT_CHECK_MAX = 40; + + // // // Shared namespace symbols + + final protected static String sPrefixXml = DefaultXmlSymbolTable.getXmlSymbol(); + + final protected static String sPrefixXmlns = DefaultXmlSymbolTable.getXmlnsSymbol(); + + /* + /////////////////////////////////////////////////////////////////////// + // Configuration + /////////////////////////////////////////////////////////////////////// + */ + + // note: mConfig defined in base class + + /** + * Set of locally stored configuration flags + */ + protected final int mConfigFlags; + + // // // Various extracted settings: + + protected final boolean mCfgCoalesceText; + + protected final boolean mCfgReportTextAsChars; + protected final boolean mCfgLazyParsing; + + /** + * Minimum number of characters parser can return as partial text + * segment, IF it's not required to coalesce adjacent text + * segments. + */ + protected final int mShortestTextSegment; + + /* + /////////////////////////////////////////////////////////////////////// + // Symbol handling + /////////////////////////////////////////////////////////////////////// + */ + + /** + * Object to notify about shared stuff, such as symbol tables, as well + * as to query for additional config settings if necessary. + */ + final protected ReaderCreator mOwner; + + /* + /////////////////////////////////////////////////////////////////////// + // Additional XML document information, in addition to what StreamScanner has + /////////////////////////////////////////////////////////////////////// + */ + + /** + * Status about "stand-aloneness" of document; set to 'yes'/'no'/'unknown' + * based on whether there was xml declaration, and if so, whether + * it had standalone attribute. + */ + protected int mDocStandalone = DOC_STANDALONE_UNKNOWN; + + /* + /////////////////////////////////////////////////////////////////////// + // DOCTYPE information from document type declaration (if any found) + /////////////////////////////////////////////////////////////////////// + */ + + /** + * Prefix of root element, as dictated by DOCTYPE declaration; null + * if no DOCTYPE declaration, or no root prefix + */ + protected String mRootPrefix; + + /** + * Local name of root element, as dictated by DOCTYPE declaration; null + * if no DOCTYPE declaration. + */ + protected String mRootLName; + + /** + * Public id of the DTD, if one exists and has been parsed. + */ + protected String mDtdPublicId; + + /** + * System id of the DTD, if one exists and has been parsed. + */ + protected String mDtdSystemId; + + /* + /////////////////////////////////////////////////////////////////////// + // Information about currently open subtree, content + /////////////////////////////////////////////////////////////////////// + */ + + /** + * TextBuffer mostly used to collect non-element textual content + * (text, CDATA, comment content, pi data) + */ + final protected TextBuffer mTextBuffer; + + /** + * Currently open element tree + */ + final protected InputElementStack mElementStack; + + /** + * Object that stores information about currently accessible attributes. + */ + final protected AttributeCollector mAttrCollector; + + /* + /////////////////////////////////////////////////////////////////////// + // Tokenization state + /////////////////////////////////////////////////////////////////////// + */ + + /// Flag set when DOCTYPE declaration has been parsed + protected boolean mStDoctypeFound = false; + + /** + * State of the current token; one of M_ - constants from above. + *

+ * Initially set to fully tokenized, since it's the virtual + * START_DOCUMENT event that we fully know by now (parsed by + * bootstrapper) + */ + protected int mTokenState = TOKEN_FULL_COALESCED; + + /** + * Threshold value that defines tokenization state that needs to be + * achieved to "finish" current logical text segment (which + * may consist of adjacent CDATA and text segments; or be a complete + * physical segment; or just even a fragment of such a segment) + */ + protected final int mStTextThreshold; + + /** + * Sized of currentTextLength for CDATA, CHARACTERS, WHITESPACE. + * When segmenting, this records to size of all the segments + * so we can track if the text length has exceeded limits. + */ + protected int mCurrTextLength; + + /// Flag that indicates current start element is an empty element + protected boolean mStEmptyElem = false; + + /** + * Main parsing/tokenization state (STATE_xxx) + */ + protected int mParseState; + + /** + * Current state of the stream, ie token value returned by + * {@link #getEventType}. Needs to be initialized to START_DOCUMENT, + * since that's the state it starts in. + */ + protected int mCurrToken = START_DOCUMENT; + + /** + * Additional information sometimes stored (when generating dummy + * events in multi-doc mode, for example) temporarily when + * {@link #mCurrToken} is already populated. + */ + protected int mSecondaryToken = START_DOCUMENT; + + /** + * Status of current (text) token's "whitespaceness", that is, + * whether it is or is not all white space. + */ + protected int mWsStatus; + + /** + * Flag that indicates that textual content (CDATA, CHARACTERS) is to + * be validated within current element's scope. Enabled if one of + * validators returns {@link XMLValidator#CONTENT_ALLOW_VALIDATABLE_TEXT}, + * and will prevent lazy parsing of text. + */ + protected boolean mValidateText = false; + + /** + * Counter used for determining whether we are to try to heuristically + * "intern" white space that seems to be used for indentation purposes + */ + protected int mCheckIndentation; + + /** + * Due to the way Stax API does not allow throwing stream exceptions + * from many methods for which Woodstox would need to throw one + * (especially getText and its variations), we may need + * to delay throwing an exception until {@link #next} is called next + * time. If so, this variable holds the pending stream exception. + */ + protected XMLStreamException mPendingException = null; + + /* + /////////////////////////////////////////////////////////////////////// + // DTD information (entities, content spec stub) + /////////////////////////////////////////////////////////////////////// + */ + + /** + * Entities parsed from internal/external DTD subsets. Although it + * will remain null for this class, extended classes make use of it, + * plus, to be able to share some of entity resolution code, instance + * is left here even though it semantically belongs to the sub-class. + */ + protected Map mGeneralEntities = null; + + /** + * Mode information needed at this level; mostly to check what kind + * of textual content (if any) is allowed in current element + * context. Constants come from + * {@link XMLValidator}, + * (like {@link XMLValidator#CONTENT_ALLOW_VALIDATABLE_TEXT}). + * Only used inside tree; ignored for prolog/epilog (which + * have straight-forward static rules). + */ + protected int mVldContent = XMLValidator.CONTENT_ALLOW_ANY_TEXT; + + /** + * Configuration from {@link XMLStreamProperties.RETURN_NULL_FOR_DEFAULT_NAMESPACE} + * + * @since 4.1.2 + */ + protected boolean mReturnNullForDefaultNamespace; + + /* + /////////////////////////////////////////////////////////////////////// + // Instance construction, initialization + /////////////////////////////////////////////////////////////////////// + */ + + /** + * @param elemStack Input element stack to use; if null, will create + * instance locally. + * @param forER Override indicator; if true, this stream reader will be + * used by an event reader, and should modify some of the base config + * settings appropriately. If false, configuration settings are to + * be used as is. + */ + protected BasicStreamReader(InputBootstrapper bs, + BranchingReaderSource input, ReaderCreator owner, + ReaderConfig cfg, InputElementStack elemStack, + boolean forER) + throws XMLStreamException + { + super(input, cfg, cfg.getEntityResolver()); + + mOwner = owner; + + mTextBuffer = TextBuffer.createRecyclableBuffer(cfg); + + // // // First, configuration settings: + + mConfigFlags = cfg.getConfigFlags(); + mCfgCoalesceText = (mConfigFlags & CFG_COALESCE_TEXT) != 0; + mCfgReportTextAsChars = (mConfigFlags & CFG_REPORT_CDATA) == 0; + mXml11 = cfg.isXml11(); + + // Can only use canonical white space if we are normalizing lfs + mCheckIndentation = mNormalizeLFs ? 16 : 0; + + /* 30-Sep-2005, TSa: Let's not do lazy parsing when access is via + * Event API. Reason is that there will be no performance benefit + * (event objects always access full info right after traversal), + * but the wrapping of stream exceptions within runtime exception + * wrappers would happen, which is inconvenient (loss of stack trace, + * not catching all exceptions as expected) + */ + mCfgLazyParsing = !forER && ((mConfigFlags & CFG_LAZY_PARSING) != 0); + + /* There are a few derived settings used during tokenization that + * need to be initialized now... + */ + if (mCfgCoalesceText) { + mStTextThreshold = TOKEN_FULL_COALESCED; + mShortestTextSegment = Integer.MAX_VALUE; + } else { + mStTextThreshold = TOKEN_PARTIAL_SINGLE; + if (forER) { + /* 30-Sep-2005, TSa: No point in returning runt segments for event readers + * (due to event object overhead, less convenient); let's just force + * returning of full length segments. + */ + mShortestTextSegment = Integer.MAX_VALUE; + } else { + mShortestTextSegment = cfg.getShortestReportedTextSegment(); + } + } + + // // // Then handling of xml declaration data: + + mDocXmlVersion = bs.getDeclaredVersion(); + mDocInputEncoding = bs.getInputEncoding(); + mDocXmlEncoding = bs.getDeclaredEncoding(); + + String sa = bs.getStandalone(); + if (sa == null) { + mDocStandalone = DOC_STANDALONE_UNKNOWN; + } else { + if (XmlConsts.XML_SA_YES.equals(sa)) { + mDocStandalone = DOC_STANDALONE_YES; + } else { + mDocStandalone = DOC_STANDALONE_NO; + } + } + + /* Ok; either we got declaration or not, but in either case we can + * now initialize prolog parsing settings, without having to really + * parse anything more. + */ + /* 07-Oct-2005, TSa: Except, if we are in fragment mode, in which + * case we are kind of "in tree" mode... + */ + mParseState = mConfig.inputParsingModeFragment() ? + STATE_TREE : STATE_PROLOG; + + // // // And then connecting element stack and attribute collector + + mElementStack = elemStack; + mAttrCollector = elemStack.getAttrCollector(); + + // And finally, location information may have offsets: + input.initInputLocation(this, mCurrDepth, 0); + + elemStack.connectReporter(this); + mReturnNullForDefaultNamespace = mConfig.returnNullForDefaultNamespace(); + } + + protected static InputElementStack createElementStack(ReaderConfig cfg) + { + return new InputElementStack(cfg, cfg.willSupportNamespaces()); + } + + /* + /////////////////////////////////////////////////////////////////////// + // XMLStreamReader, document info + /////////////////////////////////////////////////////////////////////// + */ + + /** + * As per Stax (1.0) specs, needs to return whatever xml declaration + * claimed encoding is, if any; or null if no xml declaration found. + *

+ * Note: method name is rather confusing (compare to {@link #getEncoding}). + */ + @Override + public String getCharacterEncodingScheme() { + return mDocXmlEncoding; + } + + /** + * As per Stax (1.0) specs, needs to return whatever parser determined + * the encoding was, if it was able to figure it out. If not (there are + * cases where this can not be found; specifically when being passed a + * {@link Reader}), it should return null. + */ + @Override + public String getEncoding() { + return mDocInputEncoding; + } + + @Override + public String getVersion() + { + if (mDocXmlVersion == XmlConsts.XML_V_10) { + return XmlConsts.XML_V_10_STR; + } + if (mDocXmlVersion == XmlConsts.XML_V_11) { + return XmlConsts.XML_V_11_STR; + } + return null; // unknown + } + + @Override + public boolean isStandalone() { + return mDocStandalone == DOC_STANDALONE_YES; + } + + @Override + public boolean standaloneSet() { + return mDocStandalone != DOC_STANDALONE_UNKNOWN; + } + + /* + /////////////////////////////////////////////////////////////////////// + // Public API, configuration + /////////////////////////////////////////////////////////////////////// + */ + + @Override + public Object getProperty(String name) + { + /* 18-Nov-2008, TSa: As per [WSTX-50], should report the + * actual Base URL. It can be overridden by matching + * setProperty, but if not, is set to actual source + * of content being parsed. + */ + if (WstxInputProperties.P_BASE_URL.equals(name)) { + try { + return mInput.getSource(); + } catch (IOException e) { // not optimal but... + throw new IllegalStateException(e); + } + } + /* 23-Apr-2008, TSa: Let's NOT throw IllegalArgumentException + * for unknown property; JavaDocs do not suggest it needs + * to be done (different from that of XMLInputFactory + * and XMLStreamWriter specification) + */ + return mConfig.safeGetProperty(name); + } + + /* + /////////////////////////////////////////////////////////////////////// + // XMLStreamReader, current state + /////////////////////////////////////////////////////////////////////// + */ + + // // // Attribute access: + + @Override + public int getAttributeCount() { + if (mCurrToken != START_ELEMENT) { + throw new IllegalStateException(ErrorConsts.ERR_STATE_NOT_STELEM); + } + return mAttrCollector.getCount(); + } + + @Override + public String getAttributeLocalName(int index) { + if (mCurrToken != START_ELEMENT) { + throw new IllegalStateException(ErrorConsts.ERR_STATE_NOT_STELEM); + } + return mAttrCollector.getLocalName(index); + } + + @Override + public QName getAttributeName(int index) { + if (mCurrToken != START_ELEMENT) { + throw new IllegalStateException(ErrorConsts.ERR_STATE_NOT_STELEM); + } + return mAttrCollector.getQName(index); + } + + @Override + public String getAttributeNamespace(int index) { + if (mCurrToken != START_ELEMENT) { + throw new IllegalStateException(ErrorConsts.ERR_STATE_NOT_STELEM); + } + // Internally it's marked as null, externally need to see "" + String uri = mAttrCollector.getURI(index); + return (uri == null) ? XmlConsts.ATTR_NO_NS_URI : uri; + } + + @Override + public String getAttributePrefix(int index) { + if (mCurrToken != START_ELEMENT) { + throw new IllegalStateException(ErrorConsts.ERR_STATE_NOT_STELEM); + } + // Internally it's marked as null, externally need to see "" + String p = mAttrCollector.getPrefix(index); + return (p == null) ? XmlConsts.ATTR_NO_PREFIX : p; + } + + @Override + public String getAttributeType(int index) { + if (mCurrToken != START_ELEMENT) { + throw new IllegalStateException(ErrorConsts.ERR_STATE_NOT_STELEM); + } + // Attr. collector doesn't know it, elem stack does: + return mElementStack.getAttributeType(index); + } + + @Override + public String getAttributeValue(int index) { + if (mCurrToken != START_ELEMENT) { + throw new IllegalStateException(ErrorConsts.ERR_STATE_NOT_STELEM); + } + return mAttrCollector.getValue(index); + } + + @Override + public String getAttributeValue(String nsURI, String localName) { + if (mCurrToken != START_ELEMENT) { + throw new IllegalStateException(ErrorConsts.ERR_STATE_NOT_STELEM); + } + return mAttrCollector.getValue(nsURI, localName); + } + + /** + * From StAX specs: + *

+ * Reads the content of a text-only element, an exception is thrown if + * this is not a text-only element. + * Regardless of value of javax.xml.stream.isCoalescing this method always + * returns coalesced content. + *
Precondition: the current event is START_ELEMENT. + *
Postcondition: the current event is the corresponding END_ELEMENT. + *
+ */ + @Override + public String getElementText() + throws XMLStreamException + { + if (mCurrToken != START_ELEMENT) { + throwParseError(ErrorConsts.ERR_STATE_NOT_STELEM, null, null); + } + /* Ok, now: with START_ELEMENT we know that it's not partially + * processed; that we are in-tree (not prolog or epilog). + * The only possible complication would be: + */ + if (mStEmptyElem) { + /* And if so, we'll then get 'virtual' close tag; things + * are simple as location info was set when dealing with + * empty start element; and likewise, validation (if any) + * has been taken care of + */ + mStEmptyElem = false; + mCurrToken = END_ELEMENT; + return ""; + } + + // First need to find a textual event + while (true) { + int type = next(); + if (type == END_ELEMENT) { + return ""; + } + if (type == COMMENT || type == PROCESSING_INSTRUCTION) { + continue; + } + if (((1 << type) & MASK_GET_ELEMENT_TEXT) == 0) { + throw _constructUnexpectedInTyped(type); + } + break; + } + + if (mTokenState < TOKEN_FULL_COALESCED) { + readCoalescedText(mCurrToken, false); + } + + /* Ok: then a quick check; if it looks like we are directly + * followed by the end tag, we need not construct String + * quite yet. + */ + if ((mInputPtr + 1) < mInputEnd && + mInputBuffer[mInputPtr] == '<' && mInputBuffer[mInputPtr+1] == '/') { + // Note: next() has validated text, no need for more validation + mInputPtr += 2; + mCurrToken = END_ELEMENT; + // must first get text, as call to readEndElem may break it: + String result = mTextBuffer.contentsAsString(); + // Can by-pass next(), nextFromTree(), in this case: + readEndElem(); + // and then return results + return result; + } + + // Otherwise, we'll need to do slower processing + int extra = 1 + (mTextBuffer.size() >> 1); // let's add 50% space + StringBuilder sb = mTextBuffer.contentsAsStringBuilder(extra); + int type; + + while ((type = next()) != END_ELEMENT) { + if (((1 << type) & MASK_GET_ELEMENT_TEXT) != 0) { + if (mTokenState < mStTextThreshold) { + finishToken(false); + } + verifyLimit("Text size", mConfig.getMaxTextLength(), sb.length()); + mTextBuffer.contentsToStringBuilder(sb); + continue; + } + if (type != COMMENT && type != PROCESSING_INSTRUCTION) { + throw _constructUnexpectedInTyped(type); + } + } + // Note: calls next() have validated text, no need for more validation + return sb.toString(); + } + + /** + * Returns type of the last event returned; or START_DOCUMENT before + * any events has been explicitly returned. + */ + @Override + public int getEventType() + { + /* Only complication -- multi-part coalesced text is to be reported + * as CHARACTERS always, never as CDATA (StAX specs). + */ + if (mCurrToken == CDATA) { + if (mCfgCoalesceText || mCfgReportTextAsChars) { + return CHARACTERS; + } + } + return mCurrToken; + } + + @Override + public String getLocalName() + { + // Note: for this we need not (yet) finish reading element + if (mCurrToken == START_ELEMENT || mCurrToken == END_ELEMENT) { + return mElementStack.getLocalName(); + } + if (mCurrToken == ENTITY_REFERENCE) { + /* 30-Sep-2005, TSa: Entity will be null in non-expanding mode + * if no definition was found: + */ + return (mCurrEntity == null) ? mCurrName: mCurrEntity.getName(); + } + throw new IllegalStateException("Current state not START_ELEMENT, END_ELEMENT or ENTITY_REFERENCE"); + } + + // // // getLocation() defined in StreamScanner + + @Override + public QName getName() + { + if (mCurrToken != START_ELEMENT && mCurrToken != END_ELEMENT) { + throw new IllegalStateException(ErrorConsts.ERR_STATE_NOT_ELEM); + } + return mElementStack.getCurrentElementName(); + } + + // // // Namespace access + + @Override + public NamespaceContext getNamespaceContext() { + /* Unlike other getNamespaceXxx methods, this is available + * for all events. + * Note that the context is "live", ie. remains active (but not + * static) even through calls to next(). StAX compliant apps + * should not count on this behaviour, however. + */ + return mElementStack; + } + + @Override + public int getNamespaceCount() { + if (mCurrToken != START_ELEMENT && mCurrToken != END_ELEMENT) { + throw new IllegalStateException(ErrorConsts.ERR_STATE_NOT_ELEM); + } + return mElementStack.getCurrentNsCount(); + } + + @Override + public String getNamespacePrefix(int index) { + if (mCurrToken != START_ELEMENT && mCurrToken != END_ELEMENT) { + throw new IllegalStateException(ErrorConsts.ERR_STATE_NOT_ELEM); + } + // Internally it's marked as null, externally need to see "" or null, depending + String p = mElementStack.getLocalNsPrefix(index); + if (p == null) { + return mReturnNullForDefaultNamespace ? null : XmlConsts.ATTR_NO_PREFIX; + } + return p; + } + + @Override + public String getNamespaceURI() { + if (mCurrToken != START_ELEMENT && mCurrToken != END_ELEMENT) { + throw new IllegalStateException(ErrorConsts.ERR_STATE_NOT_ELEM); + } + // Internally it's marked as null, externally need to see "" + String uri = mElementStack.getNsURI(); + return (uri == null) ? XmlConsts.ELEM_NO_NS_URI : uri; + } + + @Override + public String getNamespaceURI(int index) + { + if (mCurrToken != START_ELEMENT && mCurrToken != END_ELEMENT) { + throw new IllegalStateException(ErrorConsts.ERR_STATE_NOT_ELEM); + } + // Internally it's marked as null, externally need to see "" + String uri = mElementStack.getLocalNsURI(index); + return (uri == null) ? XmlConsts.ATTR_NO_NS_URI : uri; + } + + @Override + public String getNamespaceURI(String prefix) + { + if (mCurrToken != START_ELEMENT && mCurrToken != END_ELEMENT) { + throw new IllegalStateException(ErrorConsts.ERR_STATE_NOT_ELEM); + } + /* Note: this will need to return null if no URI found for + * the prefix, so we can't mask it. + */ + return mElementStack.getNamespaceURI(prefix); + } + + @Override + public String getPIData() { + if (mCurrToken != PROCESSING_INSTRUCTION) { + throw new IllegalStateException(ErrorConsts.ERR_STATE_NOT_PI); + } + if (mTokenState <= TOKEN_STARTED) { + safeFinishToken(); + } + return mTextBuffer.contentsAsString(); + } + + @Override + public String getPITarget() { + if (mCurrToken != PROCESSING_INSTRUCTION) { + throw new IllegalStateException(ErrorConsts.ERR_STATE_NOT_PI); + } + // Target is always parsed automatically, not lazily... + return mCurrName; + } + + @Override + public String getPrefix() { + if (mCurrToken != START_ELEMENT && mCurrToken != END_ELEMENT) { + throw new IllegalStateException(ErrorConsts.ERR_STATE_NOT_ELEM); + } + // Internally it's marked as null, externally need to see "" + String p = mElementStack.getPrefix(); + return (p == null) ? XmlConsts.ELEM_NO_PREFIX : p; + } + + @Override + public String getText() + { + final int currToken = mCurrToken; + if (((1 << currToken) & MASK_GET_TEXT) == 0) { + throwNotTextual(currToken); + } + if (mTokenState < mStTextThreshold) { + safeFinishToken(); + } + if (currToken == ENTITY_REFERENCE) { + return (mCurrEntity == null) ? null : mCurrEntity.getReplacementText(); + } + if (currToken == DTD) { + // 16-Aug-2004, TSa: Hmmh. Specs are bit ambiguous on whether this + // should return just the internal subset, or the whole thing... + return getDTDInternalSubset(); + } + return mTextBuffer.contentsAsString(); + } + + @Override + public char[] getTextCharacters() + { + final int currToken = mCurrToken; + if (((1 << currToken) & MASK_GET_TEXT_XXX) == 0) { + throwNotTextXxx(currToken); + } + if (mTokenState < mStTextThreshold) { + safeFinishToken(); + } + if (currToken == ENTITY_REFERENCE) { + return mCurrEntity.getReplacementChars(); + } + if (currToken == DTD) { + return getDTDInternalSubsetArray(); + } + return mTextBuffer.getTextBuffer(); + } + + @Override + public int getTextCharacters(int sourceStart, char[] target, int targetStart, int len) + { + final int currToken = mCurrToken; + if (((1 << currToken) & MASK_GET_TEXT_XXX) == 0) { + throwNotTextXxx(currToken); + } + if (mTokenState < mStTextThreshold) { + safeFinishToken(); + } + return mTextBuffer.contentsToArray(sourceStart, target, targetStart, len); + } + + @Override + public int getTextLength() + { + final int currToken = mCurrToken; + if (((1 << currToken) & MASK_GET_TEXT_XXX) == 0) { + throwNotTextXxx(currToken); + } + if (mTokenState < mStTextThreshold) { + safeFinishToken(); + } + return mTextBuffer.size(); + } + + @Override + public int getTextStart() + { + final int currToken = mCurrToken; + if (((1 << currToken) & MASK_GET_TEXT_XXX) == 0) { + throwNotTextXxx(currToken); + } + if (mTokenState < mStTextThreshold) { + safeFinishToken(); + } + return mTextBuffer.getTextStart(); + } + + @Override + public boolean hasName() { + return (mCurrToken == START_ELEMENT) || (mCurrToken == END_ELEMENT); + } + + @Override + public boolean hasNext() { + // 08-Oct-2005, TSa: In multi-doc mode, we have different criteria... + return (mCurrToken != END_DOCUMENT) + || (mParseState == STATE_MULTIDOC_HACK); + } + + @Override + public boolean hasText() { + return (((1 << mCurrToken) & MASK_GET_TEXT) != 0); + } + + @Override + public boolean isAttributeSpecified(int index) + { + /* No need to check for ATTRIBUTE since we never return that... + */ + if (mCurrToken != START_ELEMENT) { + throw new IllegalStateException(ErrorConsts.ERR_STATE_NOT_STELEM); + } + return mAttrCollector.isSpecified(index); + } + + @Override + public boolean isCharacters() + { + /* 21-Dec-2005, TSa: Changed for 3.0 to work the same way as stax + * ref impl. + */ + //return (mCurrToken == CHARACTERS || mCurrToken == CDATA || mCurrToken == SPACE); + /* 21-Apr-2009, TSa: As per [WSTX-201], should be consistent with + * what getEventType() returns (affects CDATA, SPACE, in + * coalescing mode or when explicitly asked to return CDATA + * as CHARACTERS) + */ + return (CHARACTERS == getEventType()); + } + + @Override + public boolean isEndElement() { + return (mCurrToken == END_ELEMENT); + } + + @Override + public boolean isStartElement() { + return (mCurrToken == START_ELEMENT); + } + + /** + *

+ * 05-Apr-2004, TSa: Could try to determine status when text is actually + * read. That'd prevent double reads... but would it slow down that + * one reading so that net effect would be negative? + */ + @Override + public boolean isWhiteSpace() + { + final int currToken = mCurrToken; + if (currToken == CHARACTERS || currToken == CDATA) { + if (mTokenState < mStTextThreshold) { + safeFinishToken(); + } + if (mWsStatus == ALL_WS_UNKNOWN) { + mWsStatus = mTextBuffer.isAllWhitespace() ? + ALL_WS_YES : ALL_WS_NO; + } + return mWsStatus == ALL_WS_YES; + } + return (currToken == SPACE); + } + + @Override + public void require(int type, String nsUri, String localName) + throws XMLStreamException + { + int curr = mCurrToken; + + /* There are some special cases; specifically, CDATA + * is sometimes reported as CHARACTERS. Let's be lenient by + * allowing both 'real' and reported types, for now. + */ + if (curr != type) { + if (curr == CDATA) { + if (mCfgCoalesceText || mCfgReportTextAsChars) { + curr = CHARACTERS; + } + } else if (curr == SPACE) { + // Hmmh. Should we require it to be empty or something? + //curr = CHARACTERS; + // For now, let's not change the check + } + } + + if (type != curr) { + throwParseError("Expected type "+tokenTypeDesc(type) + +", current type " + +tokenTypeDesc(curr)); + } + + if (localName != null) { + if (curr != START_ELEMENT && curr != END_ELEMENT + && curr != ENTITY_REFERENCE) { + throwParseError("Expected non-null local name, but current token not a START_ELEMENT, END_ELEMENT or ENTITY_REFERENCE (was "+tokenTypeDesc(mCurrToken)+")"); + } + String n = getLocalName(); + if (n != localName && !n.equals(localName)) { + throwParseError("Expected local name '"+localName+"'; current local name '"+n+"'."); + } + } + if (nsUri != null) { + if (curr != START_ELEMENT && curr != END_ELEMENT) { + throwParseError("Expected non-null NS URI, but current token not a START_ELEMENT or END_ELEMENT (was "+tokenTypeDesc(curr)+")"); + } + String uri = mElementStack.getNsURI(); + // No namespace? + if (nsUri.length() == 0) { + if (uri != null && uri.length() > 0) { + throwParseError("Expected empty namespace, instead have '"+uri+"'."); + } + } else { + if ((nsUri != uri) && !nsUri.equals(uri)) { + throwParseError("Expected namespace '"+nsUri+"'; have '" + +uri+"'."); + } + } + } + // Ok, fine, all's good + } + + /* + /////////////////////////////////////////////////////////////////////// + // XMLStreamReader, iterating + /////////////////////////////////////////////////////////////////////// + */ + + @Override + public final int next() throws XMLStreamException + { + /* 24-Sep-2006, TSa: We may have deferred an exception that occurred + * during parsing of the previous event. If so, now it needs to + * be thrown. + */ + if (mPendingException != null) { + XMLStreamException strEx = mPendingException; + mPendingException = null; + throw strEx; + } + + /* Note: can not yet accurately record the location, since the + * previous event might not yet be completely finished... + */ + if (mParseState == STATE_TREE) { + int type = nextFromTree(); + mCurrToken = type; + if (mTokenState < mStTextThreshold) { // incomplete? + /* Can remain incomplete if lazy parsing is enabled, + * and this is not a validatable text segment; otherwise + * must finish + */ + if (!mCfgLazyParsing || + (mValidateText && (type == CHARACTERS || type == CDATA))) { + finishToken(false); + } + } + + /* Special cases -- sometimes (when coalescing text, or + * when specifically configured to do so), CDATA and SPACE are + * to be reported as CHARACTERS, although we still will + * internally keep track of the real type. + */ + if (type == CDATA) { + if (mValidateText) { + mElementStack.validateText(mTextBuffer, false); + } + if (mCfgCoalesceText || mCfgReportTextAsChars) { + return CHARACTERS; + } + /* + } else if (type == SPACE) { + //if (mValidateText) { throw new IllegalStateException("Internal error: trying to validate SPACE event"); } + */ + mCurrTextLength += mTextBuffer.size(); + verifyLimit("Text size", mConfig.getMaxTextLength(), mCurrTextLength); + } else if (type == CHARACTERS) { + if (mValidateText) { + /* We may be able to determine that there will be + * no more text coming for this element: but only + * seeing the end tag marker (" + * Note: as per StAX 1.0 specs, this method does NOT close the underlying + * input reader. That is, unless the new StAX2 property + * {@link org.codehaus.stax2.XMLInputFactory2#P_AUTO_CLOSE_INPUT} is + * set to true. + */ + @Override + public void close() throws XMLStreamException + { + if (mParseState != STATE_CLOSED) { + mParseState = STATE_CLOSED; + /* Let's see if we should notify factory that symbol table + * has new entries, and may want to reuse this symbol table + * instead of current root. + */ + if (mCurrToken != END_DOCUMENT) { + mCurrToken = mSecondaryToken = END_DOCUMENT; + if (mSymbols.isDirty()) { + mOwner.updateSymbolTable(mSymbols); + } + } + /* Hmmh. Actually, we need to close all the dependant input + * sources, first, and then also call close() + * on the root input source object; it + * will only do real close if that was enabled earlier. + * The root input source also prevents multiple close() calls + * for the underlying source, so we need not check that here. + */ + closeAllInput(false); + // And finally, can now recycle low-level (text) buffers + mTextBuffer.recycle(true); + } + } + + /* + /////////////////////////////////////////////////////////////////////// + // XMLStreamReader2 (StAX2) implementation + /////////////////////////////////////////////////////////////////////// + */ + + @Override + @Deprecated + public Object getFeature(String name) { + throw new IllegalArgumentException(MessageFormat.format(ErrorConsts.ERR_UNKNOWN_FEATURE, new Object[] { name })); + } + + @Override + @Deprecated + public void setFeature(String name, Object value) { + throw new IllegalArgumentException(MessageFormat.format(ErrorConsts.ERR_UNKNOWN_FEATURE, new Object[] { name })); + } + + // NOTE: getProperty() defined in Stax 1.0 interface + + @Override + public boolean isPropertySupported(String name) { + // !!! TBI: not all these properties are really supported + return mConfig.isPropertySupported(name); + } + + /** + * @param name Name of the property to set + * @param value Value to set property to. + * + * @return True, if the specified property was succesfully + * set to specified value; false if its value was not changed + */ + @Override + public boolean setProperty(String name, Object value) + { + boolean ok = mConfig.setProperty(name, value); + /* To make [WSTX-50] work fully dynamically (i.e. allow + * setting BASE_URL after stream reader has been constructed) + * need to force + */ + if (ok && WstxInputProperties.P_BASE_URL.equals(name)) { + // Easiest to just access from config: may come in as a String etc + mInput.overrideSource(mConfig.getBaseURL()); + } + return ok; + } + + // // // StAX2, additional traversal methods + + @Override + public void skipElement() throws XMLStreamException + { + if (mCurrToken != START_ELEMENT) { + throw new IllegalStateException(ErrorConsts.ERR_STATE_NOT_STELEM); + } + int nesting = 1; // need one more end elements than start elements + + while (true) { + int type = next(); + if (type == START_ELEMENT) { + ++nesting; + } else if (type == END_ELEMENT) { + if (--nesting == 0) { + break; + } + } + } + } + + // // // StAX2, additional attribute access + + @Override + public AttributeInfo getAttributeInfo() throws XMLStreamException + { + if (mCurrToken != START_ELEMENT) { + throw new IllegalStateException(ErrorConsts.ERR_STATE_NOT_STELEM); + } + /* Although attribute collector knows about specific parsed + * information, the element stack has DTD-derived information (if + * any)... and knows how to call attribute collector when necessary. + */ + return mElementStack; + } + + // // // StAX2, Additional DTD access + + /** + * Since this class implements {@link DTDInfo}, method can just + * return this. + */ + @Override + public DTDInfo getDTDInfo() throws XMLStreamException + { + /* Let's not allow it to be accessed during other events -- that + * way callers won't count on it being available afterwards. + */ + if (mCurrToken != DTD) { + return null; + } + if (mTokenState < TOKEN_FULL_SINGLE) { // need to fully read it in now + finishToken(false); + } + return this; + } + + // // // StAX2, Additional location information + + /** + * Location information is always accessible, for this reader. + */ + @Override + public final LocationInfo getLocationInfo() { + return this; + } + + // // // StAX2, Pass-through text accessors + + + /** + * Method similar to {@link #getText()}, except + * that it just uses provided Writer to write all textual content. + * For further optimization, it may also be allowed to do true + * pass-through, thus possibly avoiding one temporary copy of the + * data. + *

+ * TODO: try to optimize to allow completely streaming pass-through: + * currently will still read all data in memory buffers before + * outputting + * + * @param w Writer to use for writing textual contents + * @param preserveContents If true, reader has to preserve contents + * so that further calls to getText will return + * proper conntets. If false, reader is allowed to skip creation + * of such copies: this can improve performance, but it also means + * that further calls to getText is not guaranteed to + * return meaningful data. + * + * @return Number of characters written to the reader + */ + @Override + public int getText(Writer w, boolean preserveContents) + throws IOException, XMLStreamException + { + final int currToken = mCurrToken; + if (((1 << currToken) & MASK_GET_TEXT_WITH_WRITER) == 0) { + throwNotTextual(currToken); + } + /* May need to be able to do fully streaming... but only for + * text events that have not yet been fully read; for other + * types there's less benefit, and for fully read ones, we + * already have everything ready. + */ + if (!preserveContents) { + if (currToken == CHARACTERS) { + int count = mTextBuffer.rawContentsTo(w); + /* Let's also clear whatever was collected (as allowed by + * method contract) previously, to both save memory, and + * to ensure caller doesn't accidentally try to access it + * (and get otherwise 'random' results). + */ + mTextBuffer.resetWithEmpty(); + if (mTokenState < TOKEN_FULL_SINGLE) { + count += readAndWriteText(w); + } + if (mCfgCoalesceText && + (mTokenState < TOKEN_FULL_COALESCED)) { + if (mCfgCoalesceText) { + count += readAndWriteCoalesced(w, false); + } + } + return count; + } else if (currToken == CDATA) { + int count = mTextBuffer.rawContentsTo(w); + mTextBuffer.resetWithEmpty(); // same as with CHARACTERS + if (mTokenState < TOKEN_FULL_SINGLE) { + count += readAndWriteCData(w); + } + if (mCfgCoalesceText && + (mTokenState < TOKEN_FULL_COALESCED)) { + if (mCfgCoalesceText) { + count += readAndWriteCoalesced(w, true); + } + } + return count; + } + } + if (mTokenState < mStTextThreshold) { + /* Otherwise, let's just finish the token; and due to guarantee + * by streaming method, let's try ensure we get it all. + */ + finishToken(false); // false -> shouldn't defer errors + } + if (currToken == ENTITY_REFERENCE) { + return mCurrEntity.getReplacementText(w); + } + if (currToken == DTD) { + char[] ch = getDTDInternalSubsetArray(); + if (ch != null) { + w.write(ch); + return ch.length; + } + return 0; + } + return mTextBuffer.rawContentsTo(w); + } + + // // // StAX 2, Other accessors + + /** + * @return Number of open elements in the stack; 0 when parser is in + * prolog/epilog, 1 inside root element and so on. + */ + @Override + public int getDepth() { + /* Note: we can not necessarily use mCurrDepth, since it is + * directly synchronized to the input (to catch unbalanced entity + * expansion WRT element nesting), and not to actual token values + * returned. + */ + return mElementStack.getDepth(); + } + + /** + * @return True, if cursor points to a start or end element that is + * constructed from 'empty' element (ends with '/>'); + * false otherwise. + */ + @Override + public boolean isEmptyElement() throws XMLStreamException { + return (mCurrToken == START_ELEMENT) ? mStEmptyElem : false; + } + + @Override + public NamespaceContext getNonTransientNamespaceContext() { + // null -> no Location info, not needed with basic API + return mElementStack.createNonTransientNsContext(null); + } + + @Override + public String getPrefixedName() + { + switch (mCurrToken) { + case START_ELEMENT: + case END_ELEMENT: + { + String prefix = mElementStack.getPrefix(); + String ln = mElementStack.getLocalName(); + + if (prefix == null) { + return ln; + } + StringBuilder sb = new StringBuilder(ln.length() + 1 + prefix.length()); + sb.append(prefix); + sb.append(':'); + sb.append(ln); + return sb.toString(); + } + case ENTITY_REFERENCE: + return getLocalName(); + case PROCESSING_INSTRUCTION: + return getPITarget(); + case DTD: + return getDTDRootName(); + + } + throw new IllegalStateException("Current state not START_ELEMENT, END_ELEMENT, ENTITY_REFERENCE, PROCESSING_INSTRUCTION or DTD"); + } + + @Override + public void closeCompletely() throws XMLStreamException { + closeAllInput(true); + } + + /* + /////////////////////////////////////////////////////////////////////// + // DTDInfo implementation (StAX 2) + /////////////////////////////////////////////////////////////////////// + */ + + /** + *

+ * Note: DTD-handling sub-classes need to override this method. + */ + @Override + public Object getProcessedDTD() { + return null; + } + + @Override + public String getDTDRootName() { + if (mRootPrefix == null) { + return mRootLName; + } + return mRootPrefix + ":" + mRootLName; + } + + @Override + public String getDTDPublicId() { + return mDtdPublicId; + } + + @Override + public String getDTDSystemId() { + return mDtdSystemId; + } + + /** + * @return Internal subset portion of the DOCTYPE declaration, if any; + * empty String if none + */ + @Override + public String getDTDInternalSubset() { + if (mCurrToken != DTD) { + return null; + } + return mTextBuffer.contentsAsString(); + } + + /** + * Internal method used by implementation + */ + private char[] getDTDInternalSubsetArray() { + /* Note: no checks for current state, but only because it's + * an internal method and callers are known to ensure it's ok + * to call this + */ + return mTextBuffer.contentsAsArray(); + } + + // // StAX2, v2.0 + + /** + * Sub-class will override this method + */ + @Override + public DTDValidationSchema getProcessedDTDSchema() { + return null; + } + + /* + /////////////////////////////////////////////////////////////////////// + // LocationInfo implementation (StAX 2) + /////////////////////////////////////////////////////////////////////// + */ + + // // // First, the "raw" offset accessors: + + @Override + public long getStartingByteOffset() { + /* 15-Apr-2005, TSa: No way to reliably keep track of byte offsets, + * at least for variable-length encodings... so let's just + * return -1 for now + */ + return -1L; + } + + @Override + public long getStartingCharOffset() { + return mTokenInputTotal; + } + + @Override + public long getEndingByteOffset() throws XMLStreamException + { + /* 15-Apr-2005, TSa: No way to reliably keep track of byte offsets, + * at least for variable-length encodings... so let's just + * return -1 for now + */ + return -1; + } + + @Override + public long getEndingCharOffset() throws XMLStreamException + { + // Need to get to the end of the token, if not there yet + if (mTokenState < mStTextThreshold) { + finishToken(false); + } + return mCurrInputProcessed + mInputPtr; + } + + // // // and then the object-based access methods: + + @Override + public final Location getLocation() { + return getStartLocation(); + } + + // public XMLStreamLocation2 getStartLocation() // from base class + // public XMLStreamLocation2 getCurrentLocation() // - "" - + + @Override + public final XMLStreamLocation2 getEndLocation() + throws XMLStreamException + { + // Need to get to the end of the token, if not there yet + if (mTokenState < mStTextThreshold) { + finishToken(false); + } + // And then we just need the current location! + return getCurrentLocation(); + } + + /* + /////////////////////////////////////////////////////////////////////// + // Stax2 validation + /////////////////////////////////////////////////////////////////////// + */ + + @Override + public XMLValidator validateAgainst(XMLValidationSchema schema) + throws XMLStreamException + { + // Not implemented by the basic reader: + return null; + } + + @Override + public XMLValidator stopValidatingAgainst(XMLValidationSchema schema) + throws XMLStreamException + { + // Not implemented by the basic reader: + return null; + } + + @Override + public XMLValidator stopValidatingAgainst(XMLValidator validator) + throws XMLStreamException + { + // Not implemented by the basic reader: + return null; + } + + @Override + public ValidationProblemHandler setValidationProblemHandler(ValidationProblemHandler h) + { + // Not implemented by the basic reader: + return null; + } + + /* + /////////////////////////////////////////////////////////////////////// + // StreamReaderImpl implementation + /////////////////////////////////////////////////////////////////////// + */ + + @Override + public EntityDecl getCurrentEntityDecl() { + return mCurrEntity; + } + + /** + * Method called by {@link com.ctc.wstx.evt.DefaultEventAllocator} + * to get double-indirection necessary for constructing start element + * events. + * + * @return Null, if stream does not point to start element; whatever + * callback returns otherwise. + */ + @Override + public Object withStartElement(ElemCallback cb, Location loc) + { + if (mCurrToken != START_ELEMENT) { + return null; + } + return cb.withStartElement(loc, getName(), + mElementStack.createNonTransientNsContext(loc), + mAttrCollector.buildAttrOb(), + mStEmptyElem); + } + + @Override + public boolean isNamespaceAware() { + return mCfgNsEnabled; + } + + /** + * Method needed by classes (like stream writer implementations) + * that want to have efficient direct access to element stack + * implementation + */ + @Override + public InputElementStack getInputElementStack() { + return mElementStack; + } + + /** + * Method needed by classes (like stream writer implementations) + * that want to have efficient direct access to attribute collector + * Object, for optimal attribute name and value access. + */ + @Override + public AttributeCollector getAttributeCollector() { + return mAttrCollector; + } + + /* + /////////////////////////////////////////////////////////////////////// + // Support for SAX XMLReader implementation + /////////////////////////////////////////////////////////////////////// + */ + + public void fireSaxStartElement(ContentHandler h, Attributes attrs) + throws SAXException + { + if (h != null) { + // First; any ns declarations? + int nsCount = mElementStack.getCurrentNsCount(); + for (int i = 0; i < nsCount; ++i) { + String prefix = mElementStack.getLocalNsPrefix(i); + String uri = mElementStack.getLocalNsURI(i); + h.startPrefixMapping((prefix == null) ? "" : prefix, uri); + } + + // Then start-elem event itself: + String uri = mElementStack.getNsURI(); + // Sax requires "" (not null) for ns uris... + h.startElement((uri == null) ? "" : uri, + mElementStack.getLocalName(), getPrefixedName(), attrs); + } + } + + public void fireSaxEndElement(ContentHandler h) + throws SAXException + { + if (h != null) { + /* Order of events is reversed (wrt. start-element): first + * the end tag event, then unbound prefixes + */ + String uri = mElementStack.getNsURI(); + // Sax requires "" (not null) for ns uris... + h.endElement((uri == null) ? "" : uri, + mElementStack.getLocalName(), getPrefixedName()); + // Any expiring ns declarations? + int nsCount = mElementStack.getCurrentNsCount(); + for (int i = 0; i < nsCount; ++i) { + String prefix = mElementStack.getLocalNsPrefix(i); + //String nsUri = mElementStack.getLocalNsURI(i); + h.endPrefixMapping((prefix == null) ? "" : prefix); + } + } + } + + public void fireSaxCharacterEvents(ContentHandler h) + throws XMLStreamException, SAXException + { + if (h != null) { + if (mPendingException != null) { + XMLStreamException sex = mPendingException; + mPendingException = null; + throw sex; + } + /* Let's not defer errors; SAXTest implies + * it's expected errors are thrown right away + */ + if (mTokenState < mStTextThreshold) { + finishToken(false); + } + mTextBuffer.fireSaxCharacterEvents(h); + } + } + + public void fireSaxSpaceEvents(ContentHandler h) + throws XMLStreamException, SAXException + { + if (h != null) { + if (mTokenState < mStTextThreshold) { + finishToken(false); // no error deferring + } + mTextBuffer.fireSaxSpaceEvents(h); + } + } + + public void fireSaxCommentEvent(LexicalHandler h) + throws XMLStreamException, SAXException + { + if (h != null) { + if (mTokenState < mStTextThreshold) { + finishToken(false); // no error deferring + } + mTextBuffer.fireSaxCommentEvent(h); + } + } + + public void fireSaxPIEvent(ContentHandler h) + throws XMLStreamException, SAXException + { + if (h != null) { + if (mTokenState < mStTextThreshold) { + finishToken(false); // no error deferring + } + h.processingInstruction(mCurrName, mTextBuffer.contentsAsString()); + } + } + + /* + /////////////////////////////////////////////////////////////////////// + // Internal methods, config access + /////////////////////////////////////////////////////////////////////// + */ + + protected final boolean hasConfigFlags(int flags) { + return (mConfigFlags & flags) == flags; + } + + /* + /////////////////////////////////////////////////////////////////////// + // Internal methods, parsing helper methods + /////////////////////////////////////////////////////////////////////// + */ + + /** + * @return Null, if keyword matches ok; String that contains erroneous + * keyword if not. + */ + protected String checkKeyword(char c, String expected) + throws XMLStreamException + { + int ptr = 0; + int len = expected.length(); + + while (expected.charAt(ptr) == c && ++ptr < len) { + if (mInputPtr < mInputEnd) { + c = mInputBuffer[mInputPtr++]; + } else { + int ci = getNext(); + if (ci < 0) { // EOF + break; + } + c = (char) ci; + } + } + + if (ptr == len) { + // Probable match... but let's make sure keyword is finished: + int i = peekNext(); + if (i < 0 || (!isNameChar((char) i) && i != ':')) { + return null; + } + // Nope, continues, need to find the rest: + } + + StringBuilder sb = new StringBuilder(expected.length() + 16); + sb.append(expected.substring(0, ptr)); + if (ptr < len) { + sb.append(c); + } + + while (true) { + if (mInputPtr < mInputEnd) { + c = mInputBuffer[mInputPtr++]; + } else { + int ci = getNext(); + if (ci < 0) { // EOF + break; + } + c = (char) ci; + } + if (!isNameChar(c)) { + // Let's push it back then + --mInputPtr; + break; + } + sb.append(c); + } + + return sb.toString(); + } + + protected void checkCData() throws XMLStreamException + { + String wrong = checkKeyword(getNextCharFromCurrent(SUFFIX_IN_CDATA), "CDATA"); + if (wrong != null) { + throwParseError("Unrecognized XML directive '"+wrong+"'; expected 'CDATA'."); + } + // Plus, need the bracket too: + char c = getNextCharFromCurrent(SUFFIX_IN_CDATA); + if (c != '[') { + throwUnexpectedChar(c, "excepted '[' after '= 3 + && (ch = resolveSimpleEntity(true)) != 0) { + // Ok, fine, c is whatever it is + ; + } else { // full entity just changes buffer... + ch = fullyResolveEntity(false); + if (ch == 0) { + // need to skip output, thusly (expanded to new input source) + continue; + } + } + if (ch <= 0xFFFF) { + c = (char) ch; + } else { + ch -= 0x10000; + if (outPtr >= outLen) { + outBuf = tb.bufferFull(1); + outLen = outBuf.length; + } + outBuf[outPtr++] = (char) ((ch >> 10) + 0xD800); + c = (char) ((ch & 0x3FF) + 0xDC00); + } + } + } else if (c == '<') { + throwUnexpectedChar(c, SUFFIX_IN_ATTR_VALUE); + } + + // Ok, let's just add char in, whatever it was + if (outPtr >= outLen) { + verifyLimit("Maximum attribute size", mConfig.getMaxAttributeSize(), tb.getCharSize()); + outBuf = tb.bufferFull(1); + outLen = outBuf.length; + } + outBuf[outPtr++] = c; + } + + // Fine; let's tell TextBuild we're done: + tb.setBufferSize(outPtr); + } + + /* + /////////////////////////////////////////////////////////////////////// + // Internal methods, parsing prolog (before root) and epilog + /////////////////////////////////////////////////////////////////////// + */ + + /** + * Method called to find type of next token in prolog; either reading + * just enough information to know the type (lazy parsing), or the + * full contents (non-lazy) + * + * @return True if we hit EOI, false otherwise + */ + private boolean nextFromProlog(boolean isProlog) + throws XMLStreamException + { + int i; + + // First, do we need to finish currently open token? + if (mTokenState < mStTextThreshold) { + mTokenState = TOKEN_FULL_COALESCED; + i = skipToken(); + // note: skipToken() updates the start location + } else { + // Need to update the start location... + mTokenInputTotal = mCurrInputProcessed + mInputPtr; + mTokenInputRow = mCurrInputRow; + mTokenInputCol = mInputPtr - mCurrInputRowStart; + i = getNext(); + } + + // Any white space to parse or skip? + if (i <= CHAR_SPACE && i >= 0) { + // Need to return as an event? + if (hasConfigFlags(CFG_REPORT_PROLOG_WS)) { + mCurrToken = SPACE; + if (readSpacePrimary((char) i, true)) { + /* no need to worry about coalescing, since CDATA is not + * allowed at this level... + */ + mTokenState = TOKEN_FULL_COALESCED; + } else { + if (mCfgLazyParsing) { + /* Let's not even bother checking if it's + * "long enough"; shouldn't usually matter, but few + * apps care to get multiple adjacent SPACE events... + */ + mTokenState = TOKEN_STARTED; + } else { + readSpaceSecondary(true); + mTokenState = TOKEN_FULL_COALESCED; + } + } + return false; + } + // If not, can skip it right away + --mInputPtr; // to handle linefeeds gracefully + i = getNextAfterWS(); + if (i >= 0) { + // ... after which location has to be reset properly: + /* 11-Apr-2005, TSa: But note that we need to "move back" + * column and total offset values by one, to compensate + * for the char that was read (row can not have changed, + * since it's non-WS, and thus non-lf/cr char) + */ + mTokenInputTotal = mCurrInputProcessed + mInputPtr - 1; + mTokenInputRow = mCurrInputRow; + mTokenInputCol = mInputPtr - mCurrInputRowStart - 1; + } + } + + // Did we hit EOI? + if (i < 0) { + handleEOF(isProlog); + mParseState = STATE_CLOSED; + return true; + } + + // Now we better have a lt... + if (i != '<') { + throwUnexpectedChar(i, (isProlog ? SUFFIX_IN_PROLOG : SUFFIX_IN_EPILOG) + +"; expected '<'"); + } + + // And then it should be easy to figure out type: + char c = getNextChar(isProlog ? SUFFIX_IN_PROLOG : SUFFIX_IN_EPILOG); + + if (c == '?') { // proc. inst + mCurrToken = readPIPrimary(); + } else if (c == '!') { // DOCTYPE or comment (or CDATA, but not legal here) + // Need to figure out bit more first... + nextFromPrologBang(isProlog); + } else if (c == '/') { // end tag not allowed... + if (isProlog) { + throwParseError("Unexpected character combination ' clean'n recycle + // It's ok to get EOF from epilog but not from prolog + if (isProlog) { + throwUnexpectedEOF(SUFFIX_IN_PROLOG); + } + return mCurrToken; + } + + /** + * Method called if a root-level element is found after the main + * root element was closed. This is legal in multi-doc parsing + * mode (and in fragment mode), but not in the default single-doc + * mode. + * @param c Character passed in (not currently used) + * + * @return Token to return + */ + private int handleExtraRoot(char c) + throws XMLStreamException + { + if (!mConfig.inputParsingModeDocuments()) { + /* Has to be single-doc mode, since fragment mode + * should never get here (since fragment mode never has epilog + * or prolog modes) + */ + throwParseError("Illegal to have multiple roots (start tag in epilog?)."); + } + // Need to push back the char, since it is the first char of elem name + --mInputPtr; + return handleMultiDocStart(START_ELEMENT); + } + + /** + * Method called when an event was encountered that indicates document + * boundary in multi-doc mode. Needs to trigger dummy + * END_DOCUMENT/START_DOCUMENT event combination, followed by the + * handling of the original event. + * + * @return Event type to return + */ + protected int handleMultiDocStart(int nextEvent) + { + mParseState = STATE_MULTIDOC_HACK; + mTokenState = TOKEN_FULL_COALESCED; // this is a virtual event after all... + mSecondaryToken = nextEvent; + return END_DOCUMENT; + } + + /** + * Method called to get the next event when we are "multi-doc hack" mode, + * during which extra END_DOCUMENT/START_DOCUMENT events need to be + * returned. + */ + private int nextFromMultiDocState() + throws XMLStreamException + { + if (mCurrToken == END_DOCUMENT) { + /* Ok; this is the initial step; need to advance: need to parse + * xml declaration if that was the cause, otherwise just clear + * up values. + */ + if (mSecondaryToken == START_DOCUMENT) { + handleMultiDocXmlDecl(); + } else { // Nah, DOCTYPE or start element... just need to clear decl info: + mDocXmlEncoding = null; + mDocXmlVersion = XmlConsts.XML_V_UNKNOWN; + mDocStandalone = DOC_STANDALONE_UNKNOWN; + } + return START_DOCUMENT; + } + if (mCurrToken == START_DOCUMENT) { + mParseState = STATE_PROLOG; // yup, we are now officially in prolog again... + + // Had an xml decl (ie. "real" START_DOCUMENT event) + if (mSecondaryToken == START_DOCUMENT) { // was a real xml decl + nextFromProlog(true); + return mCurrToken; + } + // Nah, start elem or DOCTYPE + if (mSecondaryToken == START_ELEMENT) { + handleRootElem(getNextChar(SUFFIX_IN_ELEMENT)); + return START_ELEMENT; + } + if (mSecondaryToken == DTD) { + mStDoctypeFound = true; + startDTD(); + return DTD; + } + } + throw new IllegalStateException("Internal error: unexpected state; current event " + +tokenTypeDesc(mCurrToken)+", sec. state: "+tokenTypeDesc(mSecondaryToken)); + } + + protected void handleMultiDocXmlDecl() + throws XMLStreamException + { + // Let's default these first + mDocStandalone = DOC_STANDALONE_UNKNOWN; + mDocXmlEncoding = null; + + char c = getNextInCurrAfterWS(SUFFIX_IN_XML_DECL); + String wrong = checkKeyword(c, XmlConsts.XML_DECL_KW_VERSION); + if (wrong != null) { + throwParseError(ErrorConsts.ERR_UNEXP_KEYWORD, wrong, XmlConsts.XML_DECL_KW_VERSION); + } + c = skipEquals(XmlConsts.XML_DECL_KW_VERSION, SUFFIX_IN_XML_DECL); + TextBuffer tb = mTextBuffer; + tb.resetInitialized(); + parseQuoted(XmlConsts.XML_DECL_KW_VERSION, c, tb); + + if (tb.equalsString(XmlConsts.XML_V_10_STR)) { + mDocXmlVersion = XmlConsts.XML_V_10; + mXml11 = false; + } else if (tb.equalsString(XmlConsts.XML_V_11_STR)) { + mDocXmlVersion = XmlConsts.XML_V_11; + mXml11 = true; + } else { + mDocXmlVersion = XmlConsts.XML_V_UNKNOWN; + mXml11 = false; + throwParseError("Unexpected xml version '"+tb.toString()+"'; expected '"+XmlConsts.XML_V_10_STR+"' or '"+XmlConsts.XML_V_11_STR+"'"); + } + + c = getNextInCurrAfterWS(SUFFIX_IN_XML_DECL); + + if (c != '?') { // '?' signals end... + if (c == 'e') { // encoding + wrong = checkKeyword(c, XmlConsts.XML_DECL_KW_ENCODING); + if (wrong != null) { + throwParseError(ErrorConsts.ERR_UNEXP_KEYWORD, wrong, XmlConsts.XML_DECL_KW_ENCODING); + } + c = skipEquals(XmlConsts.XML_DECL_KW_ENCODING, SUFFIX_IN_XML_DECL); + tb.resetWithEmpty(); + parseQuoted(XmlConsts.XML_DECL_KW_ENCODING, c, tb); + mDocXmlEncoding = tb.toString(); + /* should we verify encoding at this point? let's not, for now; + * since it's for information only, first declaration from + * bootstrapper is used for the whole stream. + */ + c = getNextInCurrAfterWS(SUFFIX_IN_XML_DECL); + } else if (c != 's') { + throwUnexpectedChar(c, " in xml declaration; expected either 'encoding' or 'standalone' pseudo-attribute"); + } + + // Standalone? + if (c == 's') { + wrong = checkKeyword(c, XmlConsts.XML_DECL_KW_STANDALONE); + if (wrong != null) { + throwParseError(ErrorConsts.ERR_UNEXP_KEYWORD, wrong, XmlConsts.XML_DECL_KW_STANDALONE); + } + c = skipEquals(XmlConsts.XML_DECL_KW_STANDALONE, SUFFIX_IN_XML_DECL); + tb.resetWithEmpty(); + parseQuoted(XmlConsts.XML_DECL_KW_STANDALONE, c, tb); + if (tb.equalsString(XmlConsts.XML_SA_YES)) { + mDocStandalone = DOC_STANDALONE_YES; + } else if (tb.equalsString(XmlConsts.XML_SA_NO)) { + mDocStandalone = DOC_STANDALONE_NO; + } else { + throwParseError("Unexpected xml '"+XmlConsts.XML_DECL_KW_STANDALONE+"' pseudo-attribute value '" + +tb.toString()+"'; expected '"+XmlConsts.XML_SA_YES+"' or '"+ + XmlConsts.XML_SA_NO+"'"); + } + c = getNextInCurrAfterWS(SUFFIX_IN_XML_DECL); + } + } + + if (c != '?') { + throwUnexpectedChar(c, " in xml declaration; expected '?>' as the end marker"); + } + c = getNextCharFromCurrent(SUFFIX_IN_XML_DECL); + if (c != '>') { + throwUnexpectedChar(c, " in xml declaration; expected '>' to close the declaration"); + } + } + + /** + * Method that checks that input following is of form + * '[S]* '=' [S]*' (as per XML specs, production #25). + * Will push back non-white space characters as necessary, in + * case no equals char is encountered. + */ + protected final char skipEquals(String name, String eofMsg) + throws XMLStreamException + { + char c = getNextInCurrAfterWS(eofMsg); + if (c != '=') { + throwUnexpectedChar(c, " in xml declaration; expected '=' to follow pseudo-attribute '"+name+"'"); + } + // trailing space? + return getNextInCurrAfterWS(eofMsg); + } + + /** + * Method called to parse quoted xml declaration pseudo-attribute values. + * Works similar to attribute value parsing, except no entities can be + * included, and in general need not be as picky (since caller is to + * verify contents). One exception is that we do check for linefeeds + * and lt chars, since they generally would indicate problems and + * are useful to catch early on (can happen if a quote is missed etc) + *

+ * Note: since it'll be called at most 3 times per document, this method + * is not optimized too much. + */ + protected final void parseQuoted(String name, char quoteChar, TextBuffer tbuf) + throws XMLStreamException + { + if (quoteChar != '"' && quoteChar != '\'') { + throwUnexpectedChar(quoteChar, " in xml declaration; waited ' or \" to start a value for pseudo-attribute '"+name+"'"); + } + char[] outBuf = tbuf.getCurrentSegment(); + int outPtr = 0; + + while (true) { + char c = (mInputPtr < mInputEnd) ? mInputBuffer[mInputPtr++] + : getNextChar(SUFFIX_IN_XML_DECL); + + if (c == quoteChar) { + break; + } + if (c < CHAR_SPACE || c == '<') { + throwUnexpectedChar(c, SUFFIX_IN_XML_DECL); + } else if (c == CHAR_NULL) { + throwNullChar(); + } + if (outPtr >= outBuf.length) { + outBuf = tbuf.finishCurrentSegment(); + outPtr = 0; + } + outBuf[outPtr++] = c; + } + tbuf.setCurrentLength(outPtr); + } + + /** + * Called after character sequence '<!' has been found; expectation is + * that it'll either be DOCTYPE declaration (if we are in prolog and + * haven't yet seen one), or a comment. CDATA is not legal here; + * it would start same way otherwise. + */ + private void nextFromPrologBang(boolean isProlog) + throws XMLStreamException + { + int i = getNext(); + if (i < 0) { + throwUnexpectedEOF(SUFFIX_IN_PROLOG); + } + if (i == 'D') { // Doctype declaration? + String keyw = checkKeyword('D', "DOCTYPE"); + if (keyw != null) { + throwParseError("Unrecognized XML directive ' + * + *. And we have already read the DOCTYPE token. + */ + + char c = getNextInCurrAfterWS(SUFFIX_IN_DTD); + if (mCfgNsEnabled) { + String str = parseLocalName(c); + c = getNextChar(SUFFIX_IN_DTD); + if (c == ':') { // Ok, got namespace and local name + mRootPrefix = str; + mRootLName = parseLocalName(getNextChar(SUFFIX_EOF_EXP_NAME)); + } else if (c <= CHAR_SPACE || c == '[' || c == '>') { + // ok to get white space or '[', or closing '>' + --mInputPtr; // pushback + mRootPrefix = null; + mRootLName = str; + } else { + throwUnexpectedChar(c, " in DOCTYPE declaration; expected '[' or white space."); + } + } else { + mRootLName = parseFullName(c); + mRootPrefix = null; + } + + // Ok, fine, what next? + c = getNextInCurrAfterWS(SUFFIX_IN_DTD); + if (c != '[' && c != '>') { + String keyw = null; + + if (c == 'P') { + keyw = checkKeyword(getNextChar(SUFFIX_IN_DTD), "UBLIC"); + if (keyw != null) { + keyw = "P" + keyw; + } else { + if (!skipWS(getNextChar(SUFFIX_IN_DTD))) { + throwUnexpectedChar(c, SUFFIX_IN_DTD+"; expected a space between PUBLIC keyword and public id"); + } + c = getNextCharFromCurrent(SUFFIX_IN_DTD); + if (c != '"' && c != '\'') { + throwUnexpectedChar(c, SUFFIX_IN_DTD+"; expected a public identifier."); + } + mDtdPublicId = parsePublicId(c, SUFFIX_IN_DTD); + if (mDtdPublicId.length() == 0) { + // According to XML specs, this isn't illegal? + // however, better report it as empty, not null. + //mDtdPublicId = null; + } + if (!skipWS(getNextChar(SUFFIX_IN_DTD))) { + throwUnexpectedChar(c, SUFFIX_IN_DTD+"; expected a space between public and system identifiers"); + } + c = getNextCharFromCurrent(SUFFIX_IN_DTD); + if (c != '"' && c != '\'') { + throwParseError(SUFFIX_IN_DTD+"; expected a system identifier."); + } + mDtdSystemId = parseSystemId(c, mNormalizeLFs, SUFFIX_IN_DTD); + if (mDtdSystemId.length() == 0) { + // According to XML specs, this isn't illegal? + // however, better report it as empty, not null. + //mDtdSystemId = null; + } + } + } else if (c == 'S') { + mDtdPublicId = null; + keyw = checkKeyword(getNextChar(SUFFIX_IN_DTD), "YSTEM"); + if (keyw != null) { + keyw = "S" + keyw; + } else { + c = getNextInCurrAfterWS(SUFFIX_IN_DTD); + if (c != '"' && c != '\'') { + throwUnexpectedChar(c, SUFFIX_IN_DTD+"; expected a system identifier."); + } + mDtdSystemId = parseSystemId(c, mNormalizeLFs, SUFFIX_IN_DTD); + if (mDtdSystemId.length() == 0) { + // According to XML specs, this isn't illegal? + mDtdSystemId = null; + } + } + } else { + if (!isNameStartChar(c)) { + throwUnexpectedChar(c, SUFFIX_IN_DTD+"; expected keywords 'PUBLIC' or 'SYSTEM'."); + } else { + --mInputPtr; + keyw = checkKeyword(c, "SYSTEM"); // keyword passed in doesn't matter + } + } + + if (keyw != null) { // error: + throwParseError("Unexpected keyword '"+keyw+"'; expected 'PUBLIC' or 'SYSTEM'"); + } + + // Ok, should be done with external DTD identifier: + c = getNextInCurrAfterWS(SUFFIX_IN_DTD); + } + + if (c == '[') { // internal subset + ; + } else { + if (c != '>') { + throwUnexpectedChar(c, SUFFIX_IN_DTD+"; expected closing '>'."); + } + } + + /* Actually, let's just push whatever char it is, back; this way + * we can lazily initialize text buffer with DOCTYPE declaration + * if/as necessary, even if there's no internal subset. + */ + --mInputPtr; // pushback + mTokenState = TOKEN_STARTED; + } + + /** + * This method gets called to handle remainder of DOCTYPE declaration, + * essentially the optional internal subset. This class implements the + * basic "ignore it" functionality, but can optionally still store copy + * of the contents to the read buffer. + *

+ * NOTE: Since this default implementation will be overridden by + * some sub-classes, make sure you do NOT change the method signature. + * + * @param copyContents If true, will copy contents of the internal + * subset of DOCTYPE declaration + * in the text buffer; if false, will just completely ignore the + * subset (if one found). + */ + protected void finishDTD(boolean copyContents) + throws XMLStreamException + { + /* We know there are no spaces, as this char was read and pushed + * back earlier... + */ + char c = getNextChar(SUFFIX_IN_DTD); + if (c == '[') { + // Do we need to get contents as text too? + if (copyContents) { + ((BranchingReaderSource) mInput).startBranch(mTextBuffer, mInputPtr, mNormalizeLFs); + } + + try { + MinimalDTDReader.skipInternalSubset(this, mInput, mConfig); + } finally { + /* Let's close branching in any and every case (may allow + * graceful recovery in error cases in future + */ + if (copyContents) { + /* Need to "push back" ']' got in the succesful case + * (that's -1 part below); + * in error case it'll just be whatever last char was. + */ + ((BranchingReaderSource) mInput).endBranch(mInputPtr-1); + } + } + + // And then we need closing '>' + c = getNextCharAfterWS(SUFFIX_IN_DTD_INTERNAL); + } + + if (c != '>') { + throwUnexpectedChar(c, "; expected '>' to finish DOCTYPE declaration."); + } + } + + /* + /////////////////////////////////////////////////////////////////////// + // Internal methods, main parsing (inside root) + /////////////////////////////////////////////////////////////////////// + */ + + /** + * Method called to parse beginning of the next event within + * document tree, and return its type. + */ + private final int nextFromTree() + throws XMLStreamException + { + int i; + + // First, do we need to finish currently open token? + if (mTokenState < mStTextThreshold) { + // No need to update state... will get taken care of + /* 03-Mar-2006, TSa: Let's add a sanity check here, temporarily, + * to ensure we never skip any textual content when it is + * to be validated + */ + if (mVldContent == XMLValidator.CONTENT_ALLOW_VALIDATABLE_TEXT) { + if (mCurrToken == CHARACTERS || mCurrToken == CDATA) { // should never happen + throwParseError("Internal error: skipping validatable text"); + } + } + i = skipToken(); + // note: skipToken() updates the start location + } else { + // Start/end elements are never unfinished (ie. are always + // completely read in) + if (mCurrToken == START_ELEMENT) { + // Start tag may be an empty tag: + if (mStEmptyElem) { + // and if so, we'll then get 'virtual' close tag: + mStEmptyElem = false; + // ... and location info is correct already + // 27-Feb-2009, TSa: but we do have to handle validation of the end tag now + int vld = mElementStack.validateEndElement(); + mVldContent = vld; + mValidateText = (vld == XMLValidator.CONTENT_ALLOW_VALIDATABLE_TEXT); + return END_ELEMENT; + } + } else if (mCurrToken == END_ELEMENT) { + // Close tag removes current element from stack + if (!mElementStack.pop()) { // false if root closed + // if so, we'll get to epilog, unless in fragment mode + if (!mConfig.inputParsingModeFragment()) { + return closeContentTree(); + } + // in fragment mode, fine, we'll just continue + } + } else if (mCurrToken == CDATA && mTokenState <= TOKEN_PARTIAL_SINGLE) { + /* Just returned a partial CDATA... that's ok, just need to + * know we won't get opening marker etc. + * The tricky part here is just to ensure there's at least + * one character; if not, need to just discard the empty + * 'event' (note that it is possible to have an initial + * empty CDATA event for truly empty CDATA block; but not + * partial ones!). Let's just read it like a new + * CData section first: + */ + // First, need to update the start location... + mTokenInputTotal = mCurrInputProcessed + mInputPtr; + mTokenInputRow = mCurrInputRow; + mTokenInputCol = mInputPtr - mCurrInputRowStart; + char c = (mInputPtr < mInputEnd) ? mInputBuffer[mInputPtr++] + : getNextChar(SUFFIX_IN_CDATA); + if (readCDataPrimary(c)) { // got it all! + // note: can not be in coalescing mode at this point; + // as we can never have partial cdata without unfinished token + // ... still need to have gotten at least 1 char though: + if (mTextBuffer.size() > 0) { + return CDATA; + } + // otherwise need to continue and parse the next event + } else { + // Hmmh. Have to verify we get at least one char from + // CData section; if so, we are good to go for now; + // if not, need to get that damn char first: + if (mTextBuffer.size() == 0 + && readCDataSecondary(mCfgLazyParsing + ? 1 : mShortestTextSegment)) { + // Ok, all of it read + if (mTextBuffer.size() > 0) { + // And had some contents + mTokenState = TOKEN_FULL_SINGLE; + return CDATA; + } + // if nothing read, we'll just fall back (see below) + } else { // good enough! + mTokenState = TOKEN_PARTIAL_SINGLE; + return CDATA; + } + } + + /* If we get here, it was the end of the section, without + * any more text inside CDATA, so let's just continue + */ + } + // Once again, need to update the start location info: + mTokenInputTotal = mCurrInputProcessed + mInputPtr; + mTokenInputRow = mCurrInputRow; + mTokenInputCol = mInputPtr - mCurrInputRowStart; + i = getNext(); + } + + if (i < 0) { + // 07-Oct-2005, TSa: May be ok in fragment mode (not otherwise), + // but we can just check if element stack has anything, as that handles all cases + if (!mElementStack.isEmpty()) { + throwUnexpectedEOF(); + } + return handleEOF(false); + } + + /* 26-Aug-2004, TSa: We have to deal with entities, usually, if + * they are the next thing; even in non-expanding mode there + * are entities and then there are entities... :-) + * Let's start with char entities; they can be expanded right away. + */ + while (i == '&') { + mWsStatus = ALL_WS_UNKNOWN; + + /* 30-Aug-2004, TSa: In some contexts entities are not + * allowed in any way, shape or form: + */ + if (mVldContent == XMLValidator.CONTENT_ALLOW_NONE) { + /* May be char entity, general entity; whatever it is it's + * invalid! + */ + reportInvalidContent(ENTITY_REFERENCE); + } + + /* Need to call different methods based on whether we can do + * automatic entity expansion or not: + */ + int ch = mCfgReplaceEntities ? + fullyResolveEntity(true) : resolveCharOnlyEntity(true); + + if (ch != 0) { + /* Char-entity... need to initialize text output buffer, then; + * independent of whether it'll be needed or not. + */ + /* 30-Aug-2004, TSa: In some contexts only white space is + * accepted... + */ + if (mVldContent <= XMLValidator.CONTENT_ALLOW_WS) { + // As per xml specs, only straight white space is legal + if (ch > CHAR_SPACE) { + /* 21-Sep-2008, TSa: Used to also require a call to + * 'mElementStack.reallyValidating', if only ws + * allowed, to cover the case where non-typing-dtd + * was only used to discover SPACE type. But + * now that we have CONTENT_ALLOW_WS_NONSTRICT, + * shouldn't be needed. + */ + //if (mVldContent < XMLValidator.CONTENT_ALLOW_WS || mElementStack.reallyValidating()) { + reportInvalidContent(CHARACTERS); + } + } + TextBuffer tb = mTextBuffer; + tb.resetInitialized(); + if (ch <= 0xFFFF) { + tb.append((char) ch); + } else { + ch -= 0x10000; + tb.append((char) ((ch >> 10) + 0xD800)); + tb.append((char) ((ch & 0x3FF) + 0xDC00)); + } + mTokenState = TOKEN_STARTED; + return CHARACTERS; + } + + /* Nope; was a general entity... in auto-mode, it's now been + * expanded; in non-auto, need to figure out entity itself. + */ + if (!mCfgReplaceEntities|| mCfgTreatCharRefsAsEntities) { + if (!mCfgTreatCharRefsAsEntities) { + final EntityDecl ed = resolveNonCharEntity(); + // Note: ed may still be null at this point + mCurrEntity = ed; + } + // Note: ed may still be null at this point + mTokenState = TOKEN_FULL_COALESCED; + /* + // let's not worry about non-parsed entities, since this is unexpanded mode + // ... although it'd be an error either way? Should we report it? + if (ed != null && !ed.isParsed()) { + throwParseError("Reference to unparsed entity '"+ed.getName()+"' from content not allowed."); + } + */ + return ENTITY_REFERENCE; + } + + // Otherwise automatic expansion fine; just need the next char: + i = getNextChar(SUFFIX_IN_DOC); + } + + if (i == '<') { // Markup + // And then it should be easy to figure out type: + char c = getNextChar(SUFFIX_IN_ELEMENT); + if (c == '?') { // proc. inst + // 30-Aug-2004, TSa: Not legal for EMPTY elements + if (mVldContent == XMLValidator.CONTENT_ALLOW_NONE) { + reportInvalidContent(PROCESSING_INSTRUCTION); + } + return readPIPrimary(); + } + + if (c == '!') { // CDATA or comment + // Need to figure out bit more first... + int type = nextFromTreeCommentOrCData(); + // 30-Aug-2004, TSa: Not legal for EMPTY elements + if (mVldContent == XMLValidator.CONTENT_ALLOW_NONE) { + reportInvalidContent(type); + } + return type; + } + if (c == '/') { // always legal (if name matches etc) + readEndElem(); + return END_ELEMENT; + } + + if (c == ':' || isNameStartChar(c)) { + /* Note: checking for EMPTY content type is done by the + * validator, no need to check here + */ + handleStartElem(c); + return START_ELEMENT; + } + if (c == '[') { + throwUnexpectedChar(c, " in content after '<' (malformed = mShortestTextSegment) { + mTokenState = TOKEN_PARTIAL_SINGLE; + } else { + mTokenState = TOKEN_STARTED; + } + } + return CHARACTERS; + } + + /** + * Method called when advacing stream past the end tag that closes + * the root element of the open document. + * Document can be either the singular one, in regular mode, or one of + * possibly multiple, in multi-doc mode: this method is never called + * in fragment mode. Method needs to update state properly and + * parse following epilog event (if any). + * + * @return Event following end tag of the root elemennt, if any; + * END_DOCUMENT otherwis.e + */ + private int closeContentTree() + throws XMLStreamException + { + mParseState = STATE_EPILOG; + // this call will update the location too... + if (nextFromProlog(false)) { + mSecondaryToken = 0; + } + /* 10-Apr-2006, TSa: Let's actually try to update + * SymbolTable here (after main xml tree); caller + * may not continue parsing after this. + */ + if (mSymbols.isDirty()) { + mOwner.updateSymbolTable(mSymbols); + } + /* May be able to recycle, but not certain; and + * definitely can not just clean contents (may + * contain space(s) read) + */ + mTextBuffer.recycle(false); + return mCurrToken; + } + + /** + * Method that takes care of parsing of start elements; including + * full parsing of namespace declarations and attributes, as well as + * namespace resolution. + */ + private final void handleStartElem(char c) + throws XMLStreamException + { + mTokenState = TOKEN_FULL_COALESCED; + boolean empty; + + if (mCfgNsEnabled) { + String str = parseLocalName(c); + c = (mInputPtr < mInputEnd) ? + mInputBuffer[mInputPtr++] : getNextCharFromCurrent(SUFFIX_EOF_EXP_NAME); + if (c == ':') { // Ok, got namespace and local name + c = (mInputPtr < mInputEnd) ? + mInputBuffer[mInputPtr++] : getNextCharFromCurrent(SUFFIX_EOF_EXP_NAME); + mElementStack.push(str, parseLocalName(c)); + c = (mInputPtr < mInputEnd) ? + mInputBuffer[mInputPtr++] : getNextCharFromCurrent(SUFFIX_IN_ELEMENT); + } else { + mElementStack.push(null, str); + // c is fine as + } + /* Enough about element name itself; let's then parse attributes + * and namespace declarations. Split into another method for clarity, + * and so that maybe JIT has easier time to optimize it separately. + */ + /* 04-Jul-2005, TSa: But hold up: we can easily check for a fairly + * common case of no attributes showing up, and us getting the + * closing '>' right away. Let's do that, since it can save + * a call to a rather long method. + */ + empty = (c == '>') ? false : handleNsAttrs(c); + } else { // Namespace handling not enabled: + mElementStack.push(null, parseFullName(c)); + c = (mInputPtr < mInputEnd) ? + mInputBuffer[mInputPtr++] : getNextCharFromCurrent(SUFFIX_IN_ELEMENT); + empty = (c == '>') ? false : handleNonNsAttrs(c); + } + if (!empty) { + ++mCurrDepth; // needed to match nesting with entity expansion + } + mStEmptyElem = empty; + + /* 27-Feb-2009, TSa: [WSTX-191]: We used to validate virtual + * end element here for empty elements, but it really should + * occur later on when actually returning that end element. + */ + int vld = mElementStack.resolveAndValidateElement(); + mVldContent = vld; + mValidateText = (vld == XMLValidator.CONTENT_ALLOW_VALIDATABLE_TEXT); + } + + /** + * @return True if this is an empty element; false if not + */ + private final boolean handleNsAttrs(char c) + throws XMLStreamException + { + AttributeCollector ac = mAttrCollector; + + while (true) { + if (c <= CHAR_SPACE) { + c = getNextInCurrAfterWS(SUFFIX_IN_ELEMENT, c); + } else if (c != '/' && c != '>') { + throwUnexpectedChar(c, " excepted space, or '>' or \"/>\""); + } + + if (c == '/') { + c = getNextCharFromCurrent(SUFFIX_IN_ELEMENT); + if (c != '>') { + throwUnexpectedChar(c, " expected '>'"); + } + return true; + } else if (c == '>') { + return false; + } else if (c == '<') { + throwParseError("Unexpected '<' character in element (missing closing '>'?)"); + } + + String prefix, localName; + String str = parseLocalName(c); + c = (mInputPtr < mInputEnd) ? + mInputBuffer[mInputPtr++] : getNextCharFromCurrent(SUFFIX_EOF_EXP_NAME); + if (c == ':') { // Ok, got namespace and local name + prefix = str; + c = (mInputPtr < mInputEnd) ? + mInputBuffer[mInputPtr++] : getNextCharFromCurrent(SUFFIX_EOF_EXP_NAME); + localName = parseLocalName(c); + } else { + --mInputPtr; // pushback + prefix = null; + localName = str; + } + + c = (mInputPtr < mInputEnd) ? + mInputBuffer[mInputPtr++] : getNextCharFromCurrent(SUFFIX_IN_ELEMENT); + if (c <= CHAR_SPACE) { + c = getNextInCurrAfterWS(SUFFIX_IN_ELEMENT, c); + } + if (c != '=') { + throwUnexpectedChar(c, " expected '='"); + } + c = (mInputPtr < mInputEnd) ? + mInputBuffer[mInputPtr++] : getNextCharFromCurrent(SUFFIX_IN_ELEMENT); + if (c <= CHAR_SPACE) { + c = getNextInCurrAfterWS(SUFFIX_IN_ELEMENT, c); + } + + // And then a quote: + if (c != '"' && c != '\'') { + throwUnexpectedChar(c, SUFFIX_IN_ELEMENT+" Expected a quote"); + } + + // And then the actual value + int startLen = -1; + TextBuilder tb; + + if (prefix == sPrefixXmlns) { // non-default namespace declaration + tb = ac.getNsBuilder(localName); + // returns null if it's a dupe: + if (null == tb) { + throwParseError("Duplicate declaration for namespace prefix '"+localName+"'."); + } + startLen = tb.getCharSize(); + } else if (localName == sPrefixXmlns && prefix == null) { + tb = ac.getDefaultNsBuilder(); + // returns null if default ns was already declared + if (null == tb) { + throwParseError("Duplicate default namespace declaration."); + } + } else { + tb = ac.getAttrBuilder(prefix, localName); + } + parseAttrValue(c, tb); + + /* 19-Jul-2004, TSa: Need to check that non-default namespace + * URI is NOT empty, as per XML namespace specs, #2, + * ("...In such declarations, the namespace name may not + * be empty.") + */ + /* (note: startLen is only set to first char position for + * non-default NS declarations, see above...) + */ + /* 04-Feb-2005, TSa: Namespaces 1.1 does allow this, though, + * so for xml 1.1 documents we need to allow it + */ + if (!mXml11) { + if (startLen >= 0 && tb.getCharSize() == startLen) { // is empty! + throwParseError(ErrorConsts.ERR_NS_EMPTY); + } + } + + // and then we need to iterate some more + c = (mInputPtr < mInputEnd) ? + mInputBuffer[mInputPtr++] : getNextCharFromCurrent(SUFFIX_IN_ELEMENT); + } + // never gets here + } + + /** + * @return True if this is an empty element; false if not + */ + private final boolean handleNonNsAttrs(char c) + throws XMLStreamException + { + AttributeCollector ac = mAttrCollector; + + while (true) { + if (c <= CHAR_SPACE) { + c = getNextInCurrAfterWS(SUFFIX_IN_ELEMENT, c); + } else if (c != '/' && c != '>') { + throwUnexpectedChar(c, " excepted space, or '>' or \"/>\""); + } + if (c == '/') { + c = getNextCharFromCurrent(SUFFIX_IN_ELEMENT); + if (c != '>') { + throwUnexpectedChar(c, " expected '>'"); + } + return true; + } else if (c == '>') { + return false; + } else if (c == '<') { + throwParseError("Unexpected '<' character in element (missing closing '>'?)"); + } + + String name = parseFullName(c); + TextBuilder tb = ac.getAttrBuilder(null, name); + c = (mInputPtr < mInputEnd) ? + mInputBuffer[mInputPtr++] : getNextCharFromCurrent(SUFFIX_IN_ELEMENT); + if (c <= CHAR_SPACE) { + c = getNextInCurrAfterWS(SUFFIX_IN_ELEMENT, c); + } + if (c != '=') { + throwUnexpectedChar(c, " expected '='"); + } + c = (mInputPtr < mInputEnd) ? + mInputBuffer[mInputPtr++] : getNextCharFromCurrent(SUFFIX_IN_ELEMENT); + if (c <= CHAR_SPACE) { + c = getNextInCurrAfterWS(SUFFIX_IN_ELEMENT, c); + } + + // And then a quote: + if (c != '"' && c != '\'') { + throwUnexpectedChar(c, SUFFIX_IN_ELEMENT+" Expected a quote"); + } + + // And then the actual value + parseAttrValue(c, tb); + // and then we need to iterate some more + c = (mInputPtr < mInputEnd) ? + mInputBuffer[mInputPtr++] : getNextCharFromCurrent(SUFFIX_IN_ELEMENT); + } + // never gets here + } + + /** + * Method called to completely read a close tag, and update element + * stack appropriately (including checking that tag matches etc). + */ + protected final void readEndElem() + throws XMLStreamException + { + mTokenState = TOKEN_FULL_COALESCED; // will be read completely + + if (mElementStack.isEmpty()) { + // Let's just offline this for clarity + reportExtraEndElem(); + return; // never gets here + } + + char c = (mInputPtr < mInputEnd) ? mInputBuffer[mInputPtr++] + : getNextCharFromCurrent(SUFFIX_IN_CLOSE_ELEMENT); + // Quick check first; missing name? + if (!isNameStartChar(c) && c != ':') { + if (c <= CHAR_SPACE) { // space + throwUnexpectedChar(c, "; missing element name?"); + } + throwUnexpectedChar(c, "; expected an element name."); + } + + /* Ok, now; good thing is we know exactly what to compare + * against... + */ + String expPrefix = mElementStack.getPrefix(); + String expLocalName = mElementStack.getLocalName(); + + // Prefix to match? + if (expPrefix != null && expPrefix.length() > 0) { + int len = expPrefix.length(); + int i = 0; + + while (true){ + if (c != expPrefix.charAt(i)) { + reportWrongEndPrefix(expPrefix, expLocalName, i); + return; // never gets here + } + if (++i >= len) { + break; + } + c = (mInputPtr < mInputEnd) ? mInputBuffer[mInputPtr++] + : getNextCharFromCurrent(SUFFIX_IN_CLOSE_ELEMENT); + } + // And then we should get a colon + c = (mInputPtr < mInputEnd) ? mInputBuffer[mInputPtr++] + : getNextCharFromCurrent(SUFFIX_IN_CLOSE_ELEMENT); + if (c != ':') { + reportWrongEndPrefix(expPrefix, expLocalName, i); + return; + } + c = (mInputPtr < mInputEnd) ? mInputBuffer[mInputPtr++] + : getNextCharFromCurrent(SUFFIX_IN_CLOSE_ELEMENT); + } + + // Ok, then, does the local name match? + int len = expLocalName.length(); + int i = 0; + + while (true){ + if (c != expLocalName.charAt(i)) { + // Not a match... + reportWrongEndElem(expPrefix, expLocalName, i); + return; // never gets here + } + if (++i >= len) { + break; + } + c = (mInputPtr < mInputEnd) ? mInputBuffer[mInputPtr++] + : getNextCharFromCurrent(SUFFIX_IN_CLOSE_ELEMENT); + } + + // Let's see if end element still continues, however? + c = (mInputPtr < mInputEnd) ? mInputBuffer[mInputPtr++] + : getNextCharFromCurrent(SUFFIX_IN_CLOSE_ELEMENT); + if (c <= CHAR_SPACE) { + c = getNextInCurrAfterWS(SUFFIX_IN_CLOSE_ELEMENT, c); + } else if (c == '>') { + ; + } else if (c == ':' || isNameChar(c)) { + reportWrongEndElem(expPrefix, expLocalName, len); + } + + // Ok, fine, match ok; now we just need the closing gt char. + if (c != '>') { + throwUnexpectedChar(c, SUFFIX_IN_CLOSE_ELEMENT+" Expected '>'."); + } + + // Finally, let's let validator detect if things are ok + int vld = mElementStack.validateEndElement(); + mVldContent = vld; + mValidateText = (vld == XMLValidator.CONTENT_ALLOW_VALIDATABLE_TEXT); + + // Plus verify WFC that start and end tags came from same entity + /* 13-Feb-2006, TSa: Are we about to close an element that + * started within a parent element? + * That's a GE/element nesting WFC violation... + */ + if (mCurrDepth == mInputTopDepth) { + handleGreedyEntityProblem(mInput); + } + --mCurrDepth; + } + + private void reportExtraEndElem() + throws XMLStreamException + { + String name = parseFNameForError(); + throwParseError("Unbalanced close tag ; no open start tag."); + } + + private void reportWrongEndPrefix(String prefix, String localName, int done) + throws XMLStreamException + { + --mInputPtr; // pushback + String fullName = prefix + ":" + localName; + String rest = parseFNameForError(); + String actName = fullName.substring(0, done) + rest; + throwParseError("Unexpected close tag ; expected ."); + } + + private void reportWrongEndElem(String prefix, String localName, int done) + throws XMLStreamException + { + --mInputPtr; // pushback + String fullName; + if (prefix != null && prefix.length() > 0) { + fullName = prefix + ":" + localName; + done += 1 + prefix.length(); + } else { + fullName = localName; + } + String rest = parseFNameForError(); + String actName = fullName.substring(0, done) + rest; + throwParseError("Unexpected close tag ; expected ."); + } + + /** + *

+ * Note: According to StAX 1.0, coalesced text events are always to be + * returned as CHARACTERS, never as CDATA. And since at this point we + * don't really know if there's anything to coalesce (but there may + * be), let's convert CDATA if necessary. + */ + private int nextFromTreeCommentOrCData() + throws XMLStreamException + { + char c = getNextCharFromCurrent(SUFFIX_IN_DOC); + if (c == '[') { + checkCData(); + /* Good enough; it is a CDATA section... but let's just also + * parse the easy ("free") stuff: + */ + c = (mInputPtr < mInputEnd) ? mInputBuffer[mInputPtr++] + : getNextCharFromCurrent(SUFFIX_IN_CDATA); + readCDataPrimary(c); // sets token state appropriately... + return CDATA; + } + if (c == '-' && getNextCharFromCurrent(SUFFIX_IN_DOC) == '-') { + mTokenState = TOKEN_STARTED; + return COMMENT; + } + throwParseError("Unrecognized XML directive; expected CDATA or comment (' + * Note: this method is to accurately update the location information + * to reflect where the next event will start (or, in case of EOF, where + * EOF was encountered, ie. where event would start, if there was one). + * + * @return Next character after node has been skipped, or -1 if EOF + * follows + */ + private int skipToken() + throws XMLStreamException + { + int result; + + main_switch: + switch (mCurrToken) { + case CDATA: + { + /* 30-Aug-2004, TSa: Need to be careful here: we may + * actually have finished with CDATA, but are just + * coalescing... if so, need to skip first part of + * skipping + */ + if (mTokenState <= TOKEN_PARTIAL_SINGLE) { + // Skipping CDATA is easy; just need to spot closing ]]> + skipCommentOrCData(SUFFIX_IN_CDATA, ']', false); + } + result = getNext(); + // ... except if coalescing, may need to skip more: + if (mCfgCoalesceText) { + result = skipCoalescedText(result); + } + } + break; + + case COMMENT: + skipCommentOrCData(SUFFIX_IN_COMMENT, '-', true); + result = 0; + break; + + case CHARACTERS: + { + result = skipTokenText(getNext()); + // ... except if coalescing, need to skip more: + if (mCfgCoalesceText) { + result = skipCoalescedText(result); + } + } + break; + + case DTD: + finishDTD(false); + result = 0; + break; + + case PROCESSING_INSTRUCTION: + while (true) { + char c = (mInputPtr < mInputEnd) + ? mInputBuffer[mInputPtr++] : getNextCharFromCurrent(SUFFIX_IN_PROC_INSTR); + if (c == '?') { + do { + c = (mInputPtr < mInputEnd) + ? mInputBuffer[mInputPtr++] : getNextCharFromCurrent(SUFFIX_IN_PROC_INSTR); + } while (c == '?'); + if (c == '>') { + result = 0; + break main_switch; + } + } + if (c < CHAR_SPACE) { + if (c == '\n' || c == '\r') { + skipCRLF(c); + } else if (c != '\t') { + throwInvalidSpace(c); + } + } + } + // never gets in here + + case SPACE: + + while (true) { + // Fairly easy to skip through white space... + while (mInputPtr < mInputEnd) { + char c = mInputBuffer[mInputPtr++]; + if (c > CHAR_SPACE) { // non-EOF non-WS? + result = c; + break main_switch; + } + if (c == '\n' || c == '\r') { + skipCRLF(c); + } else if (c != CHAR_SPACE && c != '\t') { + throwInvalidSpace(c); + } + } + if (!loadMore()) { + result = -1; + break main_switch; + } + } + // never gets in here + + case ENTITY_REFERENCE: // these should never end up in here... + case ENTITY_DECLARATION: + case NOTATION_DECLARATION: + case START_DOCUMENT: + case END_DOCUMENT: + // As are start/end document + throw new IllegalStateException("skipToken() called when current token is "+tokenTypeDesc(mCurrToken)); + + case ATTRIBUTE: + case NAMESPACE: + // These two are never returned by this class + case START_ELEMENT: + case END_ELEMENT: + /* Never called for elements tokens; start token handled + * differently, end token always completely read in the first place + */ + + default: + throw new IllegalStateException("Internal error: unexpected token "+tokenTypeDesc(mCurrToken)); + + } + + /* Ok; now we have 3 possibilities; result is: + * + * + 0 -> could reliably read the prev event, now need the + * following char/EOF + * + -1 -> hit EOF; can return it + * + something else -> this is the next char, return it. + * + * In first 2 cases, next event start offset is the current location; + * in third case, it needs to be backtracked by one char + */ + if (result < 1) { + mTokenInputRow = mCurrInputRow; + mTokenInputTotal = mCurrInputProcessed + mInputPtr; + mTokenInputCol = mInputPtr - mCurrInputRowStart; + return (result < 0) ? result : getNext(); + } + + // Ok, need to offset location, and return whatever we got: + mTokenInputRow = mCurrInputRow; + mTokenInputTotal = mCurrInputProcessed + mInputPtr - 1; + mTokenInputCol = mInputPtr - mCurrInputRowStart - 1; + return result; + } + + private void skipCommentOrCData(String errorMsg, char endChar, boolean preventDoubles) + throws XMLStreamException + { + /* Let's skip all chars except for double-ending chars in + * question (hyphen for comments, right brack for cdata) + */ + int count = 0; + while (true) { + char c; + while (true) { + if (mInputPtr >= mInputEnd) { + verifyLimit("Text size", mConfig.getMaxTextLength(), count); + c = getNextCharFromCurrent(errorMsg); + } else { + c = mInputBuffer[mInputPtr++]; + } + if (c < CHAR_SPACE) { + if (c == '\n' || c == '\r') { + skipCRLF(c); + } else if (c != '\t') { + throwInvalidSpace(c); + } + } else if (c == endChar) { + break; + } + ++count; + } + + // Now, we may be getting end mark; first need second marker char:. + c = getNextChar(errorMsg); + if (c == endChar) { // Probably? + // Now; we should be getting a '>', most likely. + c = getNextChar(errorMsg); + if (c == '>') { + break; + } + if (preventDoubles) { // if not, it may be a problem... + throwParseError("String '--' not allowed in comment (missing '>'?)"); + } + // Otherwise, let's loop to see if there is end + while (c == endChar) { + c = (mInputPtr < mInputEnd) + ? mInputBuffer[mInputPtr++] : getNextCharFromCurrent(errorMsg); + } + if (c == '>') { + break; + } + } + + // No match, did we get a linefeed? + if (c < CHAR_SPACE) { + if (c == '\n' || c == '\r') { + skipCRLF(c); + } else if (c != '\t') { + throwInvalidSpace(c); + } + } + // Let's continue from beginning, then + } + } + + /** + * Method called to skip past all following text and CDATA segments, + * until encountering something else (including a general entity, + * which may in turn expand to text). + * + * @return Character following all the skipped text and CDATA segments, + * if any; or -1 to denote EOF + */ + private int skipCoalescedText(int i) + throws XMLStreamException + { + while (true) { + // Ok, plain text or markup? + if (i == '<') { // markup, maybe CDATA? + // Need to distinguish "= 3 + && resolveSimpleEntity(true) != 0) { + ; + } else { + i = fullyResolveEntity(true); + /* Either way, it's just fine; we don't care about + * returned single-char value. + */ + } + } else { + /* Can only skip character entities; others need to + * be returned separately. + */ + if (resolveCharOnlyEntity(true) == 0) { + /* Now points to the char after ampersand, and we need + * to return the ampersand itself + */ + return i; + } + } + } else if (i < CHAR_SPACE) { + if (i == '\r' || i == '\n') { + skipCRLF((char) i); + } else if (i < 0) { // EOF + return i; + } else if (i != '\t') { + throwInvalidSpace(i); + } + + } + ++count; + verifyLimit("Text size", mConfig.getMaxTextLength(), count); + + // Hmmh... let's do quick looping here: + while (mInputPtr < mInputEnd) { + char c = mInputBuffer[mInputPtr++]; + if (c < CHAR_FIRST_PURE_TEXT) { // need to check it + i = c; + continue main_loop; + } + } + + i = getNext(); + } + // never gets here... + } + + /* + /////////////////////////////////////////////////////////////////////// + // Internal methods, parsing + /////////////////////////////////////////////////////////////////////// + */ + + protected void ensureFinishToken() throws XMLStreamException + { + if (mTokenState < mStTextThreshold) { + finishToken(false); + } + } + + protected void safeEnsureFinishToken() + { + if (mTokenState < mStTextThreshold) { + safeFinishToken(); + } + } + + protected void safeFinishToken() + { + try { + /* 24-Sep-2006, TSa: Let's try to reduce number of unchecked + * (wrapped) exceptions we throw, and defer some. For now, + * this is only for CHARACTERS (since it's always legal to + * split CHARACTERS segment); could be expanded in future. + */ + boolean deferErrors = (mCurrToken == CHARACTERS); + finishToken(deferErrors); + } catch (XMLStreamException strex) { + throwLazyError(strex); + } + } + + /** + * Method called to read in contents of the token completely, if not + * yet read. Generally called when caller needs to access anything + * other than basic token type (except for elements), text contents + * or such. + * + * @param deferErrors Flag to enable storing an exception to a + * variable, instead of immediately throwing it. If true, will + * just store the exception; if false, will not store, just throw. + */ + protected void finishToken(boolean deferErrors) + throws XMLStreamException + { + switch (mCurrToken) { + case CDATA: + if (mCfgCoalesceText) { + readCoalescedText(mCurrToken, deferErrors); + } else { + if (readCDataSecondary(Integer.MAX_VALUE)) { + mTokenState = TOKEN_FULL_SINGLE; + } else { // can this ever happen? + mTokenState = TOKEN_PARTIAL_SINGLE; + } + } + return; + + case CHARACTERS: + if (mCfgCoalesceText) { + /* 21-Sep-2005, TSa: It is often possible to optimize + * here: if we get '<' NOT followed by '!', it can not + * be CDATA, and thus we are done. + */ + if (mTokenState == TOKEN_FULL_SINGLE + && (mInputPtr + 1) < mInputEnd + && mInputBuffer[mInputPtr+1] != '!') { + mTokenState = TOKEN_FULL_COALESCED; + return; + } + readCoalescedText(mCurrToken, deferErrors); + } else { + if (readTextSecondary(mShortestTextSegment, deferErrors)) { + mTokenState = TOKEN_FULL_SINGLE; + } else { + mTokenState = TOKEN_PARTIAL_SINGLE; + } + } + return; + + case SPACE: + { + /* Only need to ensure there's no non-whitespace text + * when parsing 'real' ignorable white space (in validating + * mode, but that's implicit here) + */ + boolean prolog = (mParseState != STATE_TREE); + readSpaceSecondary(prolog); + mTokenState = TOKEN_FULL_COALESCED; + } + return; + + case COMMENT: + readComment(); + mTokenState = TOKEN_FULL_COALESCED; + return; + + case DTD: + + /* 05-Jan-2006, TSa: Although we shouldn't have to use finally + * here, it's probably better to do that for robustness + * (specifically, in case of a parsing problem, we don't want + * to remain in 'DTD partially read' case -- it's better + * to get in panic mode and skip the rest) + */ + try { + finishDTD(true); + } finally { + mTokenState = TOKEN_FULL_COALESCED; + } + return; + + case PROCESSING_INSTRUCTION: + readPI(); + mTokenState = TOKEN_FULL_COALESCED; + return; + + case START_ELEMENT: + case END_ELEMENT: // these 2 should never end up in here... + case ENTITY_REFERENCE: + case ENTITY_DECLARATION: + case NOTATION_DECLARATION: + case START_DOCUMENT: + case END_DOCUMENT: + throw new IllegalStateException("finishToken() called when current token is "+tokenTypeDesc(mCurrToken)); + + case ATTRIBUTE: + case NAMESPACE: + // These two are never returned by this class + default: + } + + throw new IllegalStateException("Internal error: unexpected token "+tokenTypeDesc(mCurrToken)); + } + + private void readComment() + throws XMLStreamException + { + char[] inputBuf = mInputBuffer; + int inputLen = mInputEnd; + int ptr = mInputPtr; + int start = ptr; + + // Let's first see if we can just share input buffer: + while (ptr < inputLen) { + char c = inputBuf[ptr++]; + if (c > '-') { + continue; + } + + if (c < CHAR_SPACE) { + if (c == '\n') { + markLF(ptr); + } else if (c == '\r') { + if (!mNormalizeLFs && ptr < inputLen) { + if (inputBuf[ptr] == '\n') { + ++ptr; + } + markLF(ptr); + } else { + --ptr; // pushback + break; + } + } else if (c != '\t') { + throwInvalidSpace(c); + } + } else if (c == '-') { + // Ok; need to get '->', can not get '--' + + if ((ptr + 1) >= inputLen) { + /* Can't check next 2, let's push '-' back, for rest of + * code to take care of + */ + --ptr; + break; + } + + if (inputBuf[ptr] != '-') { + // Can't skip, might be LF/CR + continue; + } + // Ok; either get '>' or error: + c = inputBuf[ptr+1]; + if (c != '>') { + throwParseError("String '--' not allowed in comment (missing '>'?)"); + } + mTextBuffer.resetWithShared(inputBuf, start, ptr-start-1); + mInputPtr = ptr + 2; + return; + } + } + + mInputPtr = ptr; + mTextBuffer.resetWithCopy(inputBuf, start, ptr-start); + readComment2(mTextBuffer); + } + + private void readComment2(TextBuffer tb) + throws XMLStreamException + { + /* Output pointers; calls will also ensure that the buffer is + * not shared, AND has room for at least one more char + */ + char[] outBuf = tb.getCurrentSegment(); + int outPtr = tb.getCurrentSegmentSize(); + int outLen = outBuf.length; + + while (true) { + char c = (mInputPtr < mInputEnd) ? + mInputBuffer[mInputPtr++] : getNextCharFromCurrent(SUFFIX_IN_COMMENT); + + if (c < CHAR_SPACE) { + if (c == '\n') { + markLF(); + } else if (c == '\r') { + if (skipCRLF(c)) { // got 2 char LF + if (!mNormalizeLFs) { + if (outPtr >= outLen) { // need more room? + outBuf = mTextBuffer.finishCurrentSegment(); + outLen = outBuf.length; + outPtr = 0; + } + outBuf[outPtr++] = c; + } + // And let's let default output the 2nd char + c = '\n'; + } else if (mNormalizeLFs) { // just \r, but need to convert + c = '\n'; // For Mac text + } + } else if (c != '\t') { + throwInvalidSpace(c); + } + } else if (c == '-') { // Ok; need to get '->', can not get '--' + c = getNextCharFromCurrent(SUFFIX_IN_COMMENT); + if (c == '-') { // Ok, has to be end marker then: + // Either get '>' or error: + c = getNextCharFromCurrent(SUFFIX_IN_COMMENT); + if (c != '>') { + throwParseError(ErrorConsts.ERR_HYPHENS_IN_COMMENT); + } + break; + } + + /* Not the end marker; let's just output the first hyphen, + * push the second char back , and let main + * code handle it. + */ + c = '-'; + --mInputPtr; + } + + // Need more room? + if (outPtr >= outLen) { + outBuf = mTextBuffer.finishCurrentSegment(); + outLen = outBuf.length; + outPtr = 0; + verifyLimit("Text size", mConfig.getMaxTextLength(), mTextBuffer.size()); + } + // Ok, let's add char to output: + outBuf[outPtr++] = c; + } + + // Ok, all done, then! + mTextBuffer.setCurrentLength(outPtr); + } + + /** + * Method that reads the primary part of a PI, ie. target, and also + * skips white space between target and data (if any data) + * + * @return Usually PROCESSING_INSTRUCTION; but may be + * different in multi-doc mode, if we actually hit a secondary + * xml declaration. + */ + private final int readPIPrimary() + throws XMLStreamException + { + // Ok, first we need the name: + String target = parseFullName(); + mCurrName = target; + + if (target.length() == 0) { + throwParseError(ErrorConsts.ERR_WF_PI_MISSING_TARGET); + } + + // As per XML specs, #17, case-insensitive 'xml' is illegal: + if (target.equalsIgnoreCase("xml")) { + // 07-Oct-2005, TSa: Still legal in multi-doc mode... + if (!mConfig.inputParsingModeDocuments()) { + throwParseError(ErrorConsts.ERR_WF_PI_XML_TARGET, target, null); + } + // Ok, let's just verify we get space then + char c = getNextCharFromCurrent(SUFFIX_IN_XML_DECL); + if (!isSpaceChar(c)) { + throwUnexpectedChar(c, "excepted a space in xml declaration after 'xml'"); + } + return handleMultiDocStart(START_DOCUMENT); + } + + // And then either white space before data, or end marker: + char c = (mInputPtr < mInputEnd) ? + mInputBuffer[mInputPtr++] : getNextCharFromCurrent(SUFFIX_IN_PROC_INSTR); + if (isSpaceChar(c)) { // Ok, space to skip + mTokenState = TOKEN_STARTED; + // Need to skip the WS... + skipWS(c); + } else { // Nope; apparently finishes right away... + mTokenState = TOKEN_FULL_COALESCED; + mTextBuffer.resetWithEmpty(); + // or does it? + if (c != '?' || getNextCharFromCurrent(SUFFIX_IN_PROC_INSTR) != '>') { + throwUnexpectedChar(c, ErrorConsts.ERR_WF_PI_XML_MISSING_SPACE); + } + } + + return PROCESSING_INSTRUCTION; + } + + /** + * Method that parses a processing instruction's data portion; at this + * point target has been parsed. + */ + private void readPI() + throws XMLStreamException + { + int ptr = mInputPtr; + int start = ptr; + char[] inputBuf = mInputBuffer; + int inputLen = mInputEnd; + + outer_loop: + while (ptr < inputLen) { + char c = inputBuf[ptr++]; + if (c < CHAR_SPACE) { + if (c == '\n') { + markLF(ptr); + } else if (c == '\r') { + if (ptr < inputLen && !mNormalizeLFs) { + if (inputBuf[ptr] == '\n') { + ++ptr; + } + markLF(ptr); + } else { + --ptr; // pushback + break; + } + } else if (c != '\t') { + throwInvalidSpace(c); + } + } else if (c == '?') { + // K; now just need '>' after zero or more '?'s + while (true) { + if (ptr >= inputLen) { + /* end of buffer; need to push back at least one of + * question marks (not all, since just one is needed + * to close the PI) + */ + --ptr; + break outer_loop; + } + c = inputBuf[ptr++]; + if (c == '>') { + mInputPtr = ptr; + // Need to discard trailing '?>' + mTextBuffer.resetWithShared(inputBuf, start, ptr-start-2); + return; + } + if (c != '?') { + // Not end, can continue, but need to push back last char, in case it's LF/CR + --ptr; + break; + } + } + } + } + + mInputPtr = ptr; + // No point in trying to share... let's just append + mTextBuffer.resetWithCopy(inputBuf, start, ptr-start); + readPI2(mTextBuffer); + } + + private void readPI2(TextBuffer tb) + throws XMLStreamException + { + char[] inputBuf = mInputBuffer; + int inputLen = mInputEnd; + int inputPtr = mInputPtr; + + /* Output pointers; calls will also ensure that the buffer is + * not shared, AND has room for one more char + */ + char[] outBuf = tb.getCurrentSegment(); + int outPtr = tb.getCurrentSegmentSize(); + + main_loop: + while (true) { + // Let's first ensure we have some data in there... + if (inputPtr >= inputLen) { + loadMoreFromCurrent(SUFFIX_IN_PROC_INSTR); + inputBuf = mInputBuffer; + inputPtr = mInputPtr; + inputLen = mInputEnd; + } + + // And then do chunks + char c = inputBuf[inputPtr++]; + if (c < CHAR_SPACE) { + if (c == '\n') { + markLF(inputPtr); + } else if (c == '\r') { + mInputPtr = inputPtr; + if (skipCRLF(c)) { // got 2 char LF + if (!mNormalizeLFs) { + // Special handling, to output 2 chars at a time: + if (outPtr >= outBuf.length) { // need more room? + outBuf = mTextBuffer.finishCurrentSegment(); + outPtr = 0; + } + outBuf[outPtr++] = c; + } + // And let's let default output the 2nd char, either way + c = '\n'; + } else if (mNormalizeLFs) { // just \r, but need to convert + c = '\n'; // For Mac text + } + /* Since skipCRLF() needs to peek(), buffer may have + * changed, even if there was no CR+LF. + */ + inputPtr = mInputPtr; + inputBuf = mInputBuffer; + inputLen = mInputEnd; + } else if (c != '\t') { + throwInvalidSpace(c); + } + } else if (c == '?') { // Ok, just need '>' after zero or more '?'s + mInputPtr = inputPtr; // to allow us to call getNextChar + + qmLoop: + while (true) { + c = (mInputPtr < mInputEnd) ? mInputBuffer[mInputPtr++] + : getNextCharFromCurrent(SUFFIX_IN_PROC_INSTR); + if (c == '>') { // got it! + break main_loop; + } else if (c == '?') { + if (outPtr >= outBuf.length) { // need more room? + outBuf = tb.finishCurrentSegment(); + outPtr = 0; + } + outBuf[outPtr++] = c; + } else { + /* Hmmh. Wasn't end mark after all. Thus, need to + * fall back to normal processing, with one more + * question mark (first one matched that wasn't + * yet output), + * reset variables, and go back to main loop. + */ + inputPtr = --mInputPtr; // push back last char + inputBuf = mInputBuffer; + inputLen = mInputEnd; + c = '?'; + break qmLoop; + } + } + } // if (c == '?) + + // Need more room? + if (outPtr >= outBuf.length) { + outBuf = tb.finishCurrentSegment(); + outPtr = 0; + } + // Ok, let's add char to output: + outBuf[outPtr++] = c; + + } // while (true) + + tb.setCurrentLength(outPtr); + } + + /** + * Method called to read the content of both current CDATA/CHARACTERS + * events, and all following consequtive events into the text buffer. + * At this point the current type is known, prefix (for CDATA) skipped, + * and initial consequtive contents (if any) read in. + * + * @param deferErrors Flag to enable storing an exception to a + * variable, instead of immediately throwing it. If true, will + * just store the exception; if false, will not store, just throw. + */ + protected void readCoalescedText(int currType, boolean deferErrors) + throws XMLStreamException + { + boolean wasCData; + + // Ok; so we may need to combine adjacent text/CDATA chunks. + if (currType == CHARACTERS || currType == SPACE) { + readTextSecondary(Integer.MAX_VALUE, deferErrors); + wasCData = false; + } else if (currType == CDATA) { + /* We may have actually really finished it, but just left + * the 'unfinished' flag due to need to coalesce... + */ + if (mTokenState <= TOKEN_PARTIAL_SINGLE) { + readCDataSecondary(Integer.MAX_VALUE); + } + wasCData = true; + } else { + throw new IllegalStateException("Internal error: unexpected token "+tokenTypeDesc(mCurrToken)+"; expected CHARACTERS, CDATA or SPACE."); + } + + // But how about additional text? + while (!deferErrors || (mPendingException == null)) { + if (mInputPtr >= mInputEnd) { + mTextBuffer.ensureNotShared(); + if (!loadMore()) { + // ??? Likely an error but let's just break + break; + } + } + // Let's peek, ie. not advance it yet + char c = mInputBuffer[mInputPtr]; + if (c == '<') { // CDATA, maybe? + // Need to distinguish ") or until + * first 'hole' in text (buffer end, 2-char lf to convert, entity). + *

+ * When the method is called, it's expected that the first character + * has been read as is in the current input buffer just before current + * pointer + * + * @param c First character in the CDATA segment (possibly part of end + * marker for empty segments + * + * @return True if the whole CDATA segment was completely read; this + * happens only if lt-char is hit; false if it's possible that + * it wasn't read (ie. end-of-buffer or entity encountered). + */ + private final boolean readCDataPrimary(char c) + throws XMLStreamException + { + mWsStatus = (c <= CHAR_SPACE) ? ALL_WS_UNKNOWN : ALL_WS_NO; + + int ptr = mInputPtr; + int inputLen = mInputEnd; + char[] inputBuf = mInputBuffer; + int start = ptr-1; + + while (true) { + if (c < CHAR_SPACE) { + if (c == '\n') { + markLF(ptr); + } else if (c == '\r') { + if (ptr >= inputLen) { // can't peek? + --ptr; + break; + } + if (mNormalizeLFs) { // can we do in-place Mac replacement? + if (inputBuf[ptr] == '\n') { // nope, 2 char lf + --ptr; + break; + } + inputBuf[ptr-1] = '\n'; // yup + } else { + // No LF normalization... can we just skip it? + if (inputBuf[ptr] == '\n') { + ++ptr; + } + } + markLF(ptr); + } else if (c != '\t') { + throwInvalidSpace(c); + } + } else if (c == ']') { + // Ok; need to get one or more ']'s, then '>' + if ((ptr + 1) >= inputLen) { // not enough room? need to push it back + --ptr; + break; + } + + // Needs to be followed by another ']'... + if (inputBuf[ptr] == ']') { + ++ptr; + inner_loop: + while (true) { + if (ptr >= inputLen) { + /* Need to push back last 2 right brackets; it may + * be end marker divided by input buffer boundary + */ + ptr -= 2; + break inner_loop; + } + c = inputBuf[ptr++]; + if (c == '>') { // Ok, got it! + mInputPtr = ptr; + ptr -= (start+3); + mTextBuffer.resetWithShared(inputBuf, start, ptr); + mTokenState = TOKEN_FULL_SINGLE; + return true; + } + if (c != ']') { + // Need to re-check this char (may be linefeed) + --ptr; + break inner_loop; + } + // Fall through to next round + } + } + } + + if (ptr >= inputLen) { // end-of-buffer? + break; + } + c = inputBuf[ptr++]; + } + + mInputPtr = ptr; + + /* If we end up here, we either ran out of input, or hit something + * which would leave 'holes' in buffer... fine, let's return then; + * we can still update shared buffer copy: would be too early to + * make a copy since caller may not even be interested in the + * stuff. + */ + int len = ptr - start; + mTextBuffer.resetWithShared(inputBuf, start, len); + if (mCfgCoalesceText || + (mTextBuffer.size() < mShortestTextSegment)) { + mTokenState = TOKEN_STARTED; + } else { + mTokenState = TOKEN_PARTIAL_SINGLE; + } + return false; + } + + /** + * @return True if the whole CData section was completely read (we + * hit the end marker); false if a shorter segment was returned. + */ + protected boolean readCDataSecondary(int shortestSegment) + throws XMLStreamException + { + // Input pointers + char[] inputBuf = mInputBuffer; + int inputLen = mInputEnd; + int inputPtr = mInputPtr; + + /* Output pointers; calls will also ensure that the buffer is + * not shared, AND has room for one more char + */ + char[] outBuf = mTextBuffer.getCurrentSegment(); + int outPtr = mTextBuffer.getCurrentSegmentSize(); + + while (true) { + if (inputPtr >= inputLen) { + loadMore(SUFFIX_IN_CDATA); + inputBuf = mInputBuffer; + inputPtr = mInputPtr; + inputLen = mInputEnd; + } + char c = inputBuf[inputPtr++]; + + if (c < CHAR_SPACE) { + if (c == '\n') { + markLF(inputPtr); + } else if (c == '\r') { + mInputPtr = inputPtr; + if (skipCRLF(c)) { // got 2 char LF + if (!mNormalizeLFs) { + // Special handling, to output 2 chars at a time: + outBuf[outPtr++] = c; + if (outPtr >= outBuf.length) { // need more room? + outBuf = mTextBuffer.finishCurrentSegment(); + outPtr = 0; + } + } + // And let's let default output the 2nd char, either way + c = '\n'; + } else if (mNormalizeLFs) { // just \r, but need to convert + c = '\n'; // For Mac text + } + /* Since skipCRLF() needs to peek(), buffer may have + * changed, even if there was no CR+LF. + */ + inputPtr = mInputPtr; + inputBuf = mInputBuffer; + inputLen = mInputEnd; + } else if (c != '\t') { + throwInvalidSpace(c); + } + } else if (c == ']') { + // Ok; need to get ']>' + mInputPtr = inputPtr; + if (checkCDataEnd(outBuf, outPtr)) { + return true; + } + inputPtr = mInputPtr; + inputBuf = mInputBuffer; + inputLen = mInputEnd; + + outBuf = mTextBuffer.getCurrentSegment(); + outPtr = mTextBuffer.getCurrentSegmentSize(); + continue; // need to re-process last (non-bracket) char + } + + // Ok, let's add char to output: + outBuf[outPtr++] = c; + + // Need more room? + if (outPtr >= outBuf.length) { + TextBuffer tb = mTextBuffer; + // Perhaps we have now enough to return? + if (!mCfgCoalesceText) { + tb.setCurrentLength(outBuf.length); + if (tb.size() >= shortestSegment) { + mInputPtr = inputPtr; + return false; + } + } + // If not, need more buffer space: + outBuf = tb.finishCurrentSegment(); + outPtr = 0; + // 17-Aug-2016, tatu: need to make sure to enforce size limits here too + verifyLimit("Text size", mConfig.getMaxTextLength(), mTextBuffer.size()); + } + } + // never gets here + } + + /** + * Method that will check, given the starting ']', whether there is + * ending ']]>' (including optional extra ']'s); if so, will updated + * output buffer with extra ]s, if not, will make sure input and output + * are positioned for further checking. + * + * @return True, if we hit the end marker; false if not. + */ + private boolean checkCDataEnd(char[] outBuf, int outPtr) + throws XMLStreamException + { + int bracketCount = 0; + char c; + do { + ++bracketCount; + c = (mInputPtr < mInputEnd) ? mInputBuffer[mInputPtr++] + : getNextCharFromCurrent(SUFFIX_IN_CDATA); + } while (c == ']'); + + boolean match = (bracketCount >= 2 && c == '>'); + if (match) { + bracketCount -= 2; + } + while (bracketCount > 0) { + --bracketCount; + outBuf[outPtr++] = ']'; + if (outPtr >= outBuf.length) { + /* Can't really easily return, even if we have enough + * stuff here, since we've more than one char... + */ + outBuf = mTextBuffer.finishCurrentSegment(); + outPtr = 0; + } + } + mTextBuffer.setCurrentLength(outPtr); + // Match? Can break, then: + if (match) { + return true; + } + // No match, need to push the last char back and admit defeat... + --mInputPtr; + return false; + } + + /** + * Method called to read in consecutive beginning parts of a text + * segment, up to either end of the segment (lt char) or until + * first 'hole' in text (buffer end, 2-char lf to convert, entity). + *

+ * When the method is called, it's expected that the first character + * has been read as is in the current input buffer just before current + * pointer + * + * @param c First character of the text segment + * + * @return True if the whole text segment was completely read; this + * happens only if lt-char is hit; false if it's possible that + * it wasn't read (ie. end-of-buffer or entity encountered). + */ + private final boolean readTextPrimary(char c) throws XMLStreamException + { + int ptr = mInputPtr; + int start = ptr-1; + + // First: can we heuristically canonicalize ws used for indentation? + if (c <= CHAR_SPACE) { + int len = mInputEnd; + /* Even without indentation removal, it's good idea to + * 'convert' \r or \r\n into \n (by replacing or skipping first + * char): this may allow reusing the buffer. + * But note that conversion MUST be enabled -- this is toggled + * by code that includes internal entities, to prevent replacement + * of CRs from int. general entities, as applicable. + */ + do { + // We'll need at least one char, no matter what: + if (ptr < len && mNormalizeLFs) { + if (c == '\r') { + c = '\n'; + if (mInputBuffer[ptr] == c) { + // Ok, whatever happens, can 'skip' \r, to point to following \n: + ++start; + // But if that's buffer end, can't skip that + if (++ptr >= len) { + break; + } + } else { + mInputBuffer[start] = c; + } + } else if (c != '\n') { + break; + } + markLF(ptr); + if (mCheckIndentation > 0) { + ptr = readIndentation(c, ptr); + if (ptr < 0) { // success! + return true; + } + } + // If we got this far, we skipped a lf, need to read next char + c = mInputBuffer[ptr++]; + } + } while (false); + + // can we figure out indentation? + mWsStatus = ALL_WS_UNKNOWN; + } else { + mWsStatus = ALL_WS_NO; + } + + char[] inputBuf = mInputBuffer; + int inputLen = mInputEnd; + + // Let's first see if we can just share input buffer: + while (true) { + if (c < CHAR_FIRST_PURE_TEXT) { + if (c == '<') { + mInputPtr = --ptr; + mTextBuffer.resetWithShared(inputBuf, start, ptr-start); + return true; + } + if (c < CHAR_SPACE) { + if (c == '\n') { + markLF(ptr); + } else if (c == '\r') { + if (ptr >= inputLen) { // can't peek? + --ptr; + break; + } + if (mNormalizeLFs) { // can we do in-place Mac replacement? + if (inputBuf[ptr] == '\n') { // nope, 2 char lf + --ptr; + break; + } + /* This would otherwise be risky (may modify value of + * a shared entity value), but since DTDs are cached/accessed + * based on properties including lf-normalization there's no + * harm in 'fixing' it in place. + */ + inputBuf[ptr-1] = '\n'; // yup + } else { + // No LF normalization... can we just skip it? + if (inputBuf[ptr] == '\n') { + ++ptr; + } + } + markLF(ptr); + } else if (c != '\t') { + // Should consume invalid char, but not include in result + mInputPtr = ptr; + mTextBuffer.resetWithShared(inputBuf, start, ptr-start-1); + /* Let's defer exception, provided we got at least + * one valid character (if not, better throw + * exception right away) + */ + boolean deferErrors = (ptr - start) > 1; + mPendingException = throwInvalidSpace(c, deferErrors); + return true; + } + } else if (c == '&') { + // Let's push it back and break + --ptr; + break; + } else if (c == '>') { + // Let's see if we got ']]>'? + if ((ptr - start) >= 3) { + if (inputBuf[ptr-3] == ']' && inputBuf[ptr-2] == ']') { + /* Let's include ']]' in there, not '>' (since that + * makes it non-wellformed): but need to consume + * that char nonetheless + */ + mInputPtr = ptr; + mTextBuffer.resetWithShared(inputBuf, start, ptr-start-1); + mPendingException = throwWfcException(ErrorConsts.ERR_BRACKET_IN_TEXT, true); + return true; // and we are fully done + } + } + } + } // if (char in lower code range) + + if (ptr >= inputLen) { // end-of-buffer? + break; + } + c = inputBuf[ptr++]; + } + mInputPtr = ptr; + + /* If we end up here, we either ran out of input, or hit something + * which would leave 'holes' in buffer... fine, let's return then; + * we can still update shared buffer copy: would be too early to + * make a copy since caller may not even be interested in the + * stuff. + */ + mTextBuffer.resetWithShared(inputBuf, start, ptr - start); + return false; + } + + /** + * + * @param deferErrors Flag to enable storing an exception to a + * variable, instead of immediately throwing it. If true, will + * just store the exception; if false, will not store, just throw. + * + * @return True if the text segment was completely read ('<' was hit, + * or in non-entity-expanding mode, a non-char entity); false if + * it may still continue + */ + protected final boolean readTextSecondary(int shortestSegment, boolean deferErrors) + throws XMLStreamException + { + /* Output pointers; calls will also ensure that the buffer is + * not shared, AND has room for at least one more char + */ + char[] outBuf = mTextBuffer.getCurrentSegment(); + int outPtr = mTextBuffer.getCurrentSegmentSize(); + int inputPtr = mInputPtr; + char[] inputBuffer = mInputBuffer; + int inputLen = mInputEnd; + + while (true) { + if (inputPtr >= inputLen) { + /* 07-Oct-2005, TSa: Let's not throw an exception for EOF from + * here -- in fragment mode, it shouldn't be thrown, and in + * other modes we might as well first return text, and only + * then throw an exception: no need to do that yet. + */ + mInputPtr = inputPtr; + if (!loadMore()) { + break; + } + inputPtr = mInputPtr; + inputBuffer = mInputBuffer; + inputLen = mInputEnd; + } + char c = inputBuffer[inputPtr++]; + + // Most common case is we don't have special char, thus: + if (c < CHAR_FIRST_PURE_TEXT) { + if (c < CHAR_SPACE) { + if (c == '\n') { + markLF(inputPtr); + } else if (c == '\r') { + mInputPtr = inputPtr; + if (skipCRLF(c)) { // got 2 char LF + if (!mNormalizeLFs) { + // Special handling, to output 2 chars at a time: + outBuf[outPtr++] = c; + if (outPtr >= outBuf.length) { // need more room? + outBuf = mTextBuffer.finishCurrentSegment(); + outPtr = 0; + } + } + // And let's let default output the 2nd char + c = '\n'; + } else if (mNormalizeLFs) { // just \r, but need to convert + c = '\n'; // For Mac text + } + /* note: skipCRLF() may change ptr and len, but since + * it does not close input source, it won't change + * actual buffer object: + */ + //inputBuffer = mInputBuffer; + inputLen = mInputEnd; + inputPtr = mInputPtr; + } else if (c != '\t') { + mTextBuffer.setCurrentLength(outPtr); + mInputPtr = inputPtr; + mPendingException = throwInvalidSpace(c, deferErrors); + break; + } + } else if (c == '<') { // end is nigh! + mInputPtr = inputPtr-1; + break; + } else if (c == '&') { + mInputPtr = inputPtr; + int ch; + if (mCfgReplaceEntities) { // can we expand all entities? + if ((inputLen - inputPtr) >= 3 + && (ch = resolveSimpleEntity(true)) != 0) { + // Ok, it's fine then + } else { + ch = fullyResolveEntity(true); + if (ch == 0) { + // Input buffer changed, nothing to output quite yet: + inputBuffer = mInputBuffer; + inputLen = mInputEnd; + inputPtr = mInputPtr; + continue; + } + // otherwise char is now fine... + } + } else { + /* Nope, can only expand char entities; others need + * to be separately handled. + */ + ch = resolveCharOnlyEntity(true); + if (ch == 0) { // some other entity... + /* can't expand; underlying pointer now points to + * char after ampersand, need to rewind + */ + --mInputPtr; + break; + } + // .. otherwise we got char we needed + } + if (ch <= 0xFFFF) { + c = (char) ch; + } else { + ch -= 0x10000; + // need more room? + if (outPtr >= outBuf.length) { + outBuf = mTextBuffer.finishCurrentSegment(); + outPtr = 0; + } + outBuf[outPtr++] = (char) ((ch >> 10) + 0xD800); + if (outPtr >= outBuf.length) { + if ((outBuf = _expandOutputForText(inputPtr, outBuf, Integer.MAX_VALUE)) == null) { // got enough, leave + return false; + } + outPtr = 0; + } + c = (char) ((ch & 0x3FF) + 0xDC00); + } + inputPtr = mInputPtr; + // not quite sure why this is needed... but it is: + inputLen = mInputEnd; + } else if (c == '>') { + // Let's see if we got ']]>'? + /* 21-Apr-2005, TSa: But we can NOT check the output buffer + * as it contains _expanded_ stuff... only input side. + * For now, 98% accuracy has to do, as we may not be able + * to access previous buffer's contents. But at least we + * won't produce false positives from entity expansion + */ + if (inputPtr > 2) { // can we do it here? + // Since mInputPtr has been advanced, -1 refers to '>' + if (inputBuffer[inputPtr-3] == ']' + && inputBuffer[inputPtr-2] == ']') { + mInputPtr = inputPtr; + /* We have already added ']]' into output buffer... + * should be ok, since only with '>' does it become + * non-wellformed. + */ + mTextBuffer.setCurrentLength(outPtr); + mPendingException = throwWfcException(ErrorConsts.ERR_BRACKET_IN_TEXT, deferErrors); + break; + } + } else { + /* 21-Apr-2005, TSa: No good way to verify it, + * at this point. Should come back and think of how + * to properly handle this (rare) possibility. + */ + ; + } + } + } + // Ok, let's add char to output: + outBuf[outPtr++] = c; + + // Need more room? + if (outPtr >= outBuf.length) { + if ((outBuf = _expandOutputForText(inputPtr, outBuf, shortestSegment)) == null) { // got enough, leave + return false; + } + verifyLimit("Text size", mConfig.getMaxTextLength(), mTextBuffer.size()); + outPtr = 0; + } + } + mTextBuffer.setCurrentLength(outPtr); + return true; + } + + private final char[] _expandOutputForText(int inputPtr, char[] outBuf, + int shortestSegment) + { + TextBuffer tb = mTextBuffer; + // Perhaps we have now enough to return? + tb.setCurrentLength(outBuf.length); + if (tb.size() >= shortestSegment) { + mInputPtr = inputPtr; + return null; + } + // If not, need more buffer space: + return tb.finishCurrentSegment(); + } + + /** + * Method called to try to parse and canonicalize white space that + * has a good chance of being white space with somewhat regular + * structure; specifically, something that looks like typical + * indentation. + *

+ * Note: Caller guarantees that there will be at least 2 characters + * available in the input buffer. And method has to ensure that if + * it does not find a match, it will return pointer value such + * that there is at least one valid character remaining. + * + * @return -1, if the content was determined to be canonicalizable + * (indentation) white space; and thus fully parsed. Otherwise + * pointer (value to set to mInputPtr) to the next character + * to process (not processed by this method) + */ + private final int readIndentation(char c, int ptr) + throws XMLStreamException + { + /* We need to verify that: + * (a) we can read enough contiguous data to do determination + * (b) sequence is a linefeed, with either zero or more following + * spaces, or zero or more tabs; and followed by non-directive + * tag (start/end tag) + * and if so, we can use a canonical shared representation of + * this even. + */ + final int inputLen = mInputEnd; + final char[] inputBuf = mInputBuffer; + int start = ptr-1; + final char lf = c; + + // Note: caller guarantees at least one more char in the input buffer + ws_loop: + do { // dummy loop to allow for break (which indicates failure) + c = inputBuf[ptr++]; + if (c == ' ' || c == '\t') { // indentation? + // Need to limit to maximum + int lastIndCharPos = (c == ' ') ? TextBuffer.MAX_INDENT_SPACES : TextBuffer.MAX_INDENT_TABS; + lastIndCharPos += ptr; + if (lastIndCharPos > inputLen) { + lastIndCharPos = inputLen; + } + + inner_loop: + while (true) { + if (ptr >= lastIndCharPos) { // overflow; let's backtrack + --ptr; + break ws_loop; + } + char d = inputBuf[ptr++]; + if (d != c) { + if (d == '<') { // yup, got it! + break inner_loop; + } + --ptr; // caller needs to reprocess it + break ws_loop; // nope, blew it + } + } + // This means we had success case; let's fall through + } else if (c != '<') { // nope, can not be + --ptr; // simpler if we just push it back; needs to be processed later on + break ws_loop; + } + + // Ok; we got '<'... just need any other char than '!'... + if (ptr < inputLen && inputBuf[ptr] != '!') { + // Voila! + mInputPtr = --ptr; // need to push back that '<' too + mTextBuffer.resetWithIndentation(ptr - start - 1, c); + // One more thing: had a positive match, need to note it + if (mCheckIndentation < INDENT_CHECK_MAX) { + mCheckIndentation += INDENT_CHECK_START; + } + mWsStatus = ALL_WS_YES; + return -1; + } + // Nope: need to push '<' back, then + --ptr; + } while (false); + + // Ok, nope... caller can/need to take care of it: + /* Also, we may need to subtract indentation check count to possibly + * disable this check if it doesn't seem to work. + */ + --mCheckIndentation; + /* Also; if lf we got was \r, need to convert it now (this + * method only gets called in lf converting mode) + * (and yes, it is safe to modify input buffer at this point; + * see calling method for details) + */ + if (lf == '\r') { + inputBuf[start] = '\n'; + } + return ptr; + } + + /** + * Reading whitespace should be very similar to reading normal text; + * although couple of simplifications can be made. Further, since this + * method is very unlikely to be of much performance concern, some + * optimizations are left out, where it simplifies code. + * + * @param c First white space characters; known to contain white space + * at this point + * @param prologWS If true, is reading white space outside XML tree, + * and as such can get EOF. If false, should not get EOF, nor be + * followed by any other char than < + * + * @return True if the whole white space segment was read; false if + * something prevented that (end of buffer, replaceable 2-char lf) + */ + private final boolean readSpacePrimary(char c, boolean prologWS) + throws XMLStreamException + { + int ptr = mInputPtr; + char[] inputBuf = mInputBuffer; + int inputLen = mInputEnd; + int start = ptr-1; + + // Let's first see if we can just share input buffer: + while (true) { + /* 30-Aug-2006, TSa: Let's not check for validity errors yet, + * even if we could detect problems at this point. + * This because it's not always + * an error (in dtd-aware, non-validating mode); but also since + * that way we can first return all space we got, and only + * indicate error when next token is to be accessed. + */ + if (c > CHAR_SPACE) { // End of whitespace + mInputPtr = --ptr; + mTextBuffer.resetWithShared(mInputBuffer, start, ptr-start); + return true; + } + + if (c == '\n') { + markLF(ptr); + } else if (c == '\r') { + if (ptr >= mInputEnd) { // can't peek? + --ptr; + break; + } + if (mNormalizeLFs) { // can we do in-place Mac replacement? + if (inputBuf[ptr] == '\n') { // nope, 2 char lf + --ptr; + break; + } + inputBuf[ptr-1] = '\n'; // yup + } else { + // No LF normalization... can we just skip it? + if (inputBuf[ptr] == '\n') { + ++ptr; + } + } + markLF(ptr); + } else if (c != CHAR_SPACE && c != '\t') { + throwInvalidSpace(c); + } + if (ptr >= inputLen) { // end-of-buffer? + break; + } + c = inputBuf[ptr++]; + } + + mInputPtr = ptr; + + /* Ok, couldn't read it completely, let's just return whatever + * we did get as shared data + */ + mTextBuffer.resetWithShared(inputBuf, start, ptr - start); + return false; + } + + /** + * This is very similar to readSecondaryText(); called when we need + * to read in rest of (ignorable) white space segment. + * + * @param prologWS True if the ignorable white space is within prolog + * (or epilog); false if it's within xml tree. + */ + private void readSpaceSecondary(boolean prologWS) + throws XMLStreamException + { + /* Let's not bother optimizing input. However, we can easily optimize + * output, since it's easy to do, yet has more effect on performance + * than localizing input variables. + */ + char[] outBuf = mTextBuffer.getCurrentSegment(); + int outPtr = mTextBuffer.getCurrentSegmentSize(); + + while (true) { + if (mInputPtr >= mInputEnd) { + /* 07-Oct-2005, TSa: Let's not throw an exception yet -- + * can return SPACE, and let exception be thrown + * when trying to fetch next event. + */ + if (!loadMore()) { + break; + } + } + char c = mInputBuffer[mInputPtr]; + if (c > CHAR_SPACE) { // end of WS? + break; + } + ++mInputPtr; + if (c == '\n') { + markLF(); + } else if (c == '\r') { + if (skipCRLF(c)) { + if (!mNormalizeLFs) { + // Special handling, to output 2 chars at a time: + outBuf[outPtr++] = c; + if (outPtr >= outBuf.length) { // need more room? + outBuf = mTextBuffer.finishCurrentSegment(); + outPtr = 0; + } + } + c = '\n'; + } else if (mNormalizeLFs) { + c = '\n'; // For Mac text + } + } else if (c != CHAR_SPACE && c != '\t') { + throwInvalidSpace(c); + } + + // Ok, let's add char to output: + outBuf[outPtr++] = c; + + // Need more room? + if (outPtr >= outBuf.length) { + outBuf = mTextBuffer.finishCurrentSegment(); + outPtr = 0; + } + } + mTextBuffer.setCurrentLength(outPtr); + } + + /** + * Method called to read the contents of the current CHARACTERS + * event, and write all contents using the specified Writer. + * + * @param w Writer to use for writing out textual content parsed + * + * @return Total number of characters written using the writer + */ + private int readAndWriteText(Writer w) + throws IOException, XMLStreamException + { + mTokenState = TOKEN_FULL_SINGLE; // we'll read it all + + /* We should be able to mostly just use the input buffer at this + * point; exceptions being two-char linefeeds (when converting + * to single ones) and entities (which likewise can expand or + * shrink), both of which require flushing and/or single byte + * output. + */ + int start = mInputPtr; + int count = 0; + + main_loop: + while (true) { + char c; + // Reached the end of buffer? Need to flush, then + if (mInputPtr >= mInputEnd) { + int len = mInputPtr - start; + if (len > 0) { + w.write(mInputBuffer, start, len); + count += len; + } + c = getNextChar(SUFFIX_IN_TEXT); + start = mInputPtr-1; // needs to be prior to char we got + } else { + c = mInputBuffer[mInputPtr++]; + } + // Most common case is we don't have a special char, thus: + if (c < CHAR_FIRST_PURE_TEXT) { + if (c < CHAR_SPACE) { + if (c == '\n') { + markLF(); + } else if (c == '\r') { + char d; + if (mInputPtr >= mInputEnd) { + /* If we can't peek easily, let's flush past stuff + * and load more... (have to flush, since new read + * will overwrite inbut buffers) + */ + int len = mInputPtr - start; + if (len > 0) { + w.write(mInputBuffer, start, len); + count += len; + } + d = getNextChar(SUFFIX_IN_TEXT); + start = mInputPtr; // to mark 'no past content' + } else { + d = mInputBuffer[mInputPtr++]; + } + if (d == '\n') { + if (mNormalizeLFs) { + /* Let's flush content prior to 2-char LF, and + * start the new segment on the second char... + * this way, no mods are needed for the buffer, + * AND it'll also work on split 2-char lf! + */ + int len = mInputPtr - 2 - start; + if (len > 0) { + w.write(mInputBuffer, start, len); + count += len; + } + start = mInputPtr-1; // so '\n' is the first char + } else { + ; // otherwise it's good as is + } + } else { // not 2-char... need to replace? + --mInputPtr; + if (mNormalizeLFs) { + mInputBuffer[mInputPtr-1] = '\n'; + } + } + markLF(); + } else if (c != '\t') { + throwInvalidSpace(c); + } + } else if (c == '<') { // end is nigh! + break main_loop; + } else if (c == '&') { + /* Have to flush all stuff, since entities pretty much + * force it; input buffer won't be contiguous + */ + int len = mInputPtr - 1 - start; // -1 to remove ampersand + if (len > 0) { + w.write(mInputBuffer, start, len); + count += len; + } + int ch; + if (mCfgReplaceEntities) { // can we expand all entities? + if ((mInputEnd - mInputPtr) < 3 + || (ch = resolveSimpleEntity(true)) == 0) { + ch = fullyResolveEntity(true); + } + } else { + ch = resolveCharOnlyEntity(true); + if (ch == 0) { // some other entity... + /* can't expand, so, let's just bail out... but + * let's also ensure no text is added twice, as + * all prev text was just flushed, but resolve + * may have moved input buffer around. + */ + start = mInputPtr; + break main_loop; + } + } + if (ch != 0) { + if (ch <= 0xFFFF) { + c = (char) ch; + } else { + ch -= 0x10000; + w.write((char) ((ch >> 10) + 0xD800)); + c = (char) ((ch & 0x3FF) + 0xDC00); + } + w.write(c); + ++count; + } + start = mInputPtr; + } else if (c == '>') { // did we get ']]>'? + /* 21-Apr-2005, TSa: But we can NOT check the output buffer + * (see comments in readTextSecondary() for details) + */ + if (mInputPtr >= 2) { // can we do it here? + if (mInputBuffer[mInputPtr-2] == ']' + && mInputBuffer[mInputPtr-1] == ']') { + // Anything to flush? + int len = mInputPtr - start; + if (len > 0) { + w.write(mInputBuffer, start, len); + } + throwParseError(ErrorConsts.ERR_BRACKET_IN_TEXT); + } + } else { + ; // !!! TBI: how to check past boundary? + } + } else if (c == CHAR_NULL) { + throwNullChar(); + } + } + } // while (true) + + /* Need to push back '<' or '&', whichever caused us to + * get out... + */ + --mInputPtr; + + // Anything left to flush? + int len = mInputPtr - start; + if (len > 0) { + w.write(mInputBuffer, start, len); + count += len; + } + return count; + } + + /** + * Method called to read the contents of the current (possibly partially + * read) CDATA + * event, and write all contents using the specified Writer. + * + * @param w Writer to use for writing out textual content parsed + * + * @return Total number of characters written using the writer for + * the current CDATA event + */ + private int readAndWriteCData(Writer w) + throws IOException, XMLStreamException + { + mTokenState = TOKEN_FULL_SINGLE; // we'll read it all + + /* Ok; here we can basically have 2 modes; first the big loop to + * gather all data up until a ']'; and then another loop to see + * if ']' is part of ']]>', and after this if no end marker found, + * go back to the first part. + */ + char c = (mInputPtr < mInputEnd) ? + mInputBuffer[mInputPtr++] : getNextChar(SUFFIX_IN_CDATA); + int count = 0; + + main_loop: + while (true) { + int start = mInputPtr-1; + + quick_loop: + while (true) { + if (c > CHAR_CR_LF_OR_NULL) { + if (c == ']') { + break quick_loop; + } + } else { + if (c < CHAR_SPACE) { + if (c == '\n') { + markLF(); + } else if (c == '\r') { + char d; + if (mInputPtr >= mInputEnd) { + /* If we can't peek easily, let's flush past stuff + * and load more... (have to flush, since new read + * will overwrite inbut buffers) + */ + int len = mInputPtr - start; + if (len > 0) { + w.write(mInputBuffer, start, len); + count += len; + } + d = getNextChar(SUFFIX_IN_CDATA); + start = mInputPtr; // to mark 'no past content' + } else { + d = mInputBuffer[mInputPtr++]; + } + if (d == '\n') { + if (mNormalizeLFs) { + /* Let's flush content prior to 2-char LF, and + * start the new segment on the second char... + * this way, no mods are needed for the buffer, + * AND it'll also work on split 2-char lf! + */ + int len = mInputPtr - 2 - start; + if (len > 0) { + w.write(mInputBuffer, start, len); + count += len; + } + start = mInputPtr-1; // so '\n' is the first char + } else { + // otherwise it's good as is + } + } else { // not 2-char... need to replace? + --mInputPtr; + if (mNormalizeLFs) { + mInputBuffer[mInputPtr-1] = '\n'; + } + } + markLF(); + } else if (c != '\t') { + throwInvalidSpace(c); + } + } + } + // Reached the end of buffer? Need to flush, then + if (mInputPtr >= mInputEnd) { + int len = mInputPtr - start; + if (len > 0) { + w.write(mInputBuffer, start, len); + count += len; + } + start = 0; + c = getNextChar(SUFFIX_IN_CDATA); + } else { + c = mInputBuffer[mInputPtr++]; + } + } // while (true) + + // Anything to flush once we hit ']'? + { + /* -1 since the last char in there (a '[') is NOT to be + * output at this point + */ + int len = mInputPtr - start - 1; + if (len > 0) { + w.write(mInputBuffer, start, len); + count += len; + } + } + + /* Ok; we only get this far when we hit a ']'. We got one, + * so let's see if we can find at least one more bracket, + * immediately followed by '>'... + */ + int bracketCount = 0; + do { + ++bracketCount; + c = (mInputPtr < mInputEnd) ? mInputBuffer[mInputPtr++] + : getNextCharFromCurrent(SUFFIX_IN_CDATA); + } while (c == ']'); + + boolean match = (bracketCount >= 2 && c == '>'); + if (match) { + bracketCount -= 2; + } + while (bracketCount > 0) { + --bracketCount; + w.write(']'); + ++count; + } + if (match) { + break main_loop; + } + /* Otherwise we'll just loop; now c is properly set to be + * the next char as well. + */ + } // while (true) + + return count; + } + + /** + * @return Number of characters written to Writer during the call + */ + private int readAndWriteCoalesced(Writer w, boolean wasCData) + throws IOException, XMLStreamException + { + mTokenState = TOKEN_FULL_COALESCED; + int count = 0; + + /* Ok, so what do we have next? CDATA, CHARACTERS, or something + * else? + */ + main_loop: + while (true) { + if (mInputPtr >= mInputEnd) { + if (!loadMore()) { + /* Shouldn't normally happen, but let's just let + * caller deal with it... + */ + break main_loop; + } + } + // Let's peek, ie. not advance it yet + char c = mInputBuffer[mInputPtr]; + if (c == '<') { // CDATA, maybe? + // Need to distinguish " CHAR_SPACE) { + return false; + } + while (true) { + // Linefeed? + if (c == '\n' || c == '\r') { + skipCRLF(c); + } else if (c != CHAR_SPACE && c != '\t') { + throwInvalidSpace(c); + } + if (mInputPtr >= mInputEnd) { + // Let's see if current source has more + if (!loadMoreFromCurrent()) { + return true; + } + } + c = mInputBuffer[mInputPtr]; + if (c > CHAR_SPACE) { // not WS? Need to return + return true; + } + ++mInputPtr; + } + } + + /* + /////////////////////////////////////////////////////////////////////// + // Abstract method implementations + /////////////////////////////////////////////////////////////////////// + */ + + @Override + protected EntityDecl findEntity(String id, Object arg) + throws XMLStreamException + { + EntityDecl ed = mConfig.findCustomInternalEntity(id); + if (ed == null && mGeneralEntities != null) { + ed = mGeneralEntities.get(id); + } + /* 05-Mar-2006, TSa: Externally declared entities are illegal + * if we were declared as "standalone='yes'"... + */ + if (mDocStandalone == DOC_STANDALONE_YES) { + if (ed != null && ed.wasDeclaredExternally()) { + throwParseError(ErrorConsts.ERR_WF_ENTITY_EXT_DECLARED, ed.getName(), null); + } + } + return ed; + } + + @Override + protected void handleUndeclaredEntity(String id) + throws XMLStreamException + { + throwParseError(((mDocStandalone == DOC_STANDALONE_YES) ? + ErrorConsts.ERR_WF_GE_UNDECLARED_SA : + ErrorConsts.ERR_WF_GE_UNDECLARED), + id, null); + } + + @Override + protected void handleIncompleteEntityProblem(WstxInputSource closing) + throws XMLStreamException + { + String top = mElementStack.isEmpty() ? "[ROOT]" : mElementStack.getTopElementDesc(); + throwParseError("Unexpected end of entity expansion for entity &{0}; was expecting a close tag for element <{1}>", + closing.getEntityId(), top); + } + + /* + /////////////////////////////////////////////////////////////////////// + // Internal methods, validation, error handling and reporting + /////////////////////////////////////////////////////////////////////// + */ + + /** + * This problem gets reported if an entity tries to expand to + * a close tag matching start tag that did not came from the same + * entity (but from parent). + */ + protected void handleGreedyEntityProblem(WstxInputSource input) + throws XMLStreamException + { + String top = mElementStack.isEmpty() ? "[ROOT]" : mElementStack.getTopElementDesc(); + throwParseError("Improper GE/element nesting: entity &" + +input.getEntityId()+" contains closing tag for <"+top+">"); + } + + private void throwNotTextual(int type) { + throw new IllegalStateException("Not a textual event (" + +tokenTypeDesc(type)+")"); + } + + private void throwNotTextXxx(int type) { + throw new IllegalStateException("getTextXxx() methods can not be called on " + +tokenTypeDesc(type)); + } + + protected void throwNotTextualOrElem(int type) { + throw new IllegalStateException(MessageFormat.format(ErrorConsts.ERR_STATE_NOT_ELEM_OR_TEXT, + new Object[] { tokenTypeDesc(type) })); + } + + /** + * Method called when we get an EOF within content tree + */ + protected void throwUnexpectedEOF() throws WstxException { + throwUnexpectedEOF("; was expecting a close tag for element <"+mElementStack.getTopElementDesc()+">"); + } + + /** + * Method called to report a problem with + */ + protected XMLStreamException _constructUnexpectedInTyped(int nextToken) { + if (nextToken == START_ELEMENT) { + return _constructTypeException("Element content can not contain child START_ELEMENT when using Typed Access methods", null); + } + return _constructTypeException("Expected a text token, got "+tokenTypeDesc(nextToken), null); + } + + protected TypedXMLStreamException _constructTypeException(String msg, String lexicalValue) { + return new TypedXMLStreamException(lexicalValue, msg, getStartLocation()); + } + + /** + * Stub method implemented by validating parsers, to report content + * that's not valid for current element context. Defined at this + * level since some such problems need to be caught at low-level; + * however, details of error reports are not needed here. + * + * @param evtType Type of event that contained unexpected content + */ + protected void reportInvalidContent(int evtType) throws XMLStreamException { + // should never happen; sub-class has to override: + throwParseError("Internal error: sub-class should override method"); + } +} diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/sr/CompactNsContext.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/sr/CompactNsContext.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/sr/CompactNsContext.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/sr/CompactNsContext.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,256 @@ +package com.ctc.wstx.sr; + +import java.io.IOException; +import java.io.Writer; +import java.util.ArrayList; +import java.util.Iterator; + +import javax.xml.XMLConstants; +import javax.xml.stream.Location; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamWriter; +import javax.xml.stream.events.Namespace; + +// This is unfortunate dependency, but... +import org.codehaus.stax2.ri.evt.NamespaceEventImpl; + +import com.ctc.wstx.util.BaseNsContext; +import com.ctc.wstx.util.DataUtil; + +/** + * Simple implementation of separate non-transient namespace context + * object. Created for start-element event by transient namespace + * instance updated by stream reader. + *

+ * Note about implementation: Location information is only needed (and + * only needs to passed) if access is made via extended interface; one + * that can return information about actual Namespace event objects. + */ +public final class CompactNsContext + extends BaseNsContext +{ + final Location mLocation; + + /** + * Array that contains 2 Strings for each declared default namespace + * (including default namespace declarations); first is the prefix, + * second URI. + */ + final String[] mNamespaces; + + /** + * Number of entries in {@link #mNamespaces} (which is twice the number + * of bindings) + */ + final int mNsLength; + + /** + * Index of first namespace pair in mNamespaces that is declared + * in scope of element for which this context was constructed. May be + * equal to {@link #mNsLength} (which indicates there are no local + * bindings). + */ + final int mFirstLocalNs; + + /** + * List only needed to support List accessor from start-element event; + * created lazily if/as needed. + */ + transient ArrayList mNsList; + + public CompactNsContext(Location loc, + String[] namespaces, int nsLen, + int firstLocal) + { + mLocation = loc; + mNamespaces = namespaces; + mNsLength = nsLen; + mFirstLocalNs = firstLocal; + } + + /** + * @param prefix Non-null, non-empty prefix (base-class verifies these + * constraints) to find namespace URI for. + */ + @Override + public String doGetNamespaceURI(String prefix) + { + /* Let's search from beginning towards end; this way we'll first + * find the innermost (or, in case of same-level declaration, last) + * declaration for prefix. + */ + // (note: default namespace will be there too) + String[] ns = mNamespaces; + if (prefix.length() == 0) { + for (int i = mNsLength-2; i >= 0; i -= 2) { + if (ns[i] == null) { + return ns[i+1]; + } + } + return null; // default ns not bound + } + for (int i = mNsLength-2; i >= 0; i -= 2) { + if (prefix.equals(ns[i])) { + return ns[i+1]; + } + } + return null; + } + + @Override + public String doGetPrefix(String nsURI) + { + // Note: base class checks for 'known' problems and prefixes: + + String[] ns = mNamespaces; + int len = mNsLength; + + main_loop: + for (int i = len-1; i > 0; i -= 2) { + if (nsURI.equals(ns[i])) { + /* 29-Sep-2004, TSa: Actually, need to make sure that this + * declaration is not masked by a later declaration. + * This happens when same prefix is declared on a later + * entry (ie. for child element) + */ + String prefix = ns[i-1]; + for (int j = i+1; j < len; j += 2) { + // Prefixes are interned, can do straight equality check + if (ns[j] == prefix) { + continue main_loop; // was masked! + } + } + String uri = ns[i-1]; + /* 19-Mar-2006, TSa: Empty namespaces are represented by + * null prefixes; but need to be represented as empty + * strings (to distinguish from unbound URIs). + */ + return (uri == null) ? "" : uri; + } + } + return null; + } + + @Override + public Iterator doGetPrefixes(String nsURI) + { + // Note: base class checks for 'known' problems and prefixes: + + String[] ns = mNamespaces; + int len = mNsLength; + String first = null; + ArrayList all = null; + + main_loop: + for (int i = len-1; i > 0; i -= 2) { + String currNS = ns[i]; + if (currNS == nsURI || currNS.equals(nsURI)) { + /* 29-Sep-2004, TSa: Need to ensure it's not masked by + * a later ns declaration in a child element. + */ + String prefix = ns[i-1]; + for (int j = i+1; j < len; j += 2) { + // Prefixes are interned, can do straight equality check + if (ns[j] == prefix) { + continue main_loop; // was masked, need to ignore + } + } + /* 19-Mar-2006, TSa: Empty namespaces are represented by + * null prefixes; but need to be represented as empty + * strings (to distinguish from unbound URIs). + */ + if (prefix == null) { + prefix = ""; + } + if (first == null) { + first = prefix; + } else { + if (all == null) { + all = new ArrayList(); + all.add(first); + } + all.add(prefix); + } + } + } + if (all != null) { + return all.iterator(); + } + if (first != null) { + return DataUtil.singletonIterator(first); + } + return DataUtil.emptyIterator(); + } + + /* + /////////////////////////////////////////////////////// + // Extended API, needed by Wstx classes + /////////////////////////////////////////////////////// + */ + + @Override + public Iterator getNamespaces() + { + if (mNsList == null) { + int firstLocal = mFirstLocalNs; + int len = mNsLength - firstLocal; + if (len == 0) { // can this happen? + return DataUtil.emptyIterator(); + } + if (len == 2) { // only one NS + return DataUtil.singletonIterator(NamespaceEventImpl.constructNamespace + (mLocation, + mNamespaces[firstLocal], + mNamespaces[firstLocal+1])); + } + ArrayList l = new ArrayList(len >> 1); + String[] ns = mNamespaces; + for (len = mNsLength; firstLocal < len; + firstLocal += 2) { + l.add(NamespaceEventImpl.constructNamespace(mLocation, ns[firstLocal], + ns[firstLocal+1])); + } + mNsList = l; + } + return mNsList.iterator(); + } + + /** + * Method called by {@link com.ctc.wstx.evt.CompactStartElement} + * to output all 'local' namespace declarations active in current + * namespace scope, if any. Local means that declaration was done in + * scope of current element, not in a parent element. + */ + @Override + public void outputNamespaceDeclarations(Writer w) throws IOException + { + String[] ns = mNamespaces; + for (int i = mFirstLocalNs, len = mNsLength; i < len; i += 2) { + w.write(' '); + w.write(XMLConstants.XMLNS_ATTRIBUTE); + String prefix = ns[i]; + if (prefix != null && prefix.length() > 0) { + w.write(':'); + w.write(prefix); + } + w.write("=\""); + w.write(ns[i+1]); + w.write('"'); + } + } + + @Override + public void outputNamespaceDeclarations(XMLStreamWriter w) throws XMLStreamException + { + String[] ns = mNamespaces; + for (int i = mFirstLocalNs, len = mNsLength; i < len; i += 2) { + String nsURI = ns[i+1]; + String prefix = ns[i]; + if (prefix != null && prefix.length() > 0) { + w.writeNamespace(prefix, nsURI); + } else { + w.writeDefaultNamespace(nsURI); + } + } + } +} diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/sr/ElemAttrs.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/sr/ElemAttrs.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/sr/ElemAttrs.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/sr/ElemAttrs.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,228 @@ +package com.ctc.wstx.sr; + +import javax.xml.namespace.QName; + +/** + * Container class that is constructed with enough raw attribute information, + * to be able to lazily construct full attribute objects, to be accessed + * via Iterator, or fully-qualified name. + *

+ * Implementation note: code for using Map-like structure is unfortunately + * cut'n pasted from {@link AttributeCollector}. Problem + * with refactoring is that it's 90% the same code, but not 100%. + *

+ * Although instances of this class are constructed by stream readers, + * it is actually used by element event objects. + */ +public final class ElemAttrs +{ + //private final static int OFFSET_LOCAL_NAME = 0; + private final static int OFFSET_NS_URI = 1; + //private final static int OFFSET_NS_PREFIX = 2; + //private final static int OFFSET_VALUE = 3; + + /** + * Array that contains 4 Strings for each attribute; + * localName, URI, prefix, value. Can be used to lazily construct + * structure(s) needed to return Iterator for accessing all + * attributes. + */ + private final String[] mRawAttrs; + + /** + * Raw offset (in mRawAttrs) of the first attribute + * instance that was created through default value expansion. + */ + private final int mDefaultOffset; + + /* + ////////////////////////////////////////////////////////////// + // Information that defines "Map-like" data structure used for + // quick access to attribute values by fully-qualified name + // (only used for "long" lists) + ////////////////////////////////////////////////////////////// + */ + + // // // For full explanation, see source for AttributeCollector + + private final int[] mAttrMap; + + private final int mAttrHashSize; + + private final int mAttrSpillEnd; + + /** + * Method called to create "short" attribute list; list that has + * only few entries, and can thus be searched for attributes using + * linear search, without using any kind of Map structure. + *

+ * Currently the limit is 4 attributes; 1, 2 or 3 attribute lists are + * considered short, 4 or more 'long'. + * + * @param rawAttrs Array that contains 4 Strings for each attribute; + * localName, URI, prefix, value. Can be used to lazily construct + * structure(s) needed to return Iterator for accessing all + * attributes. + * @param defOffset Index of the first default attribute, if any; + * number of all attributes if none + */ + public ElemAttrs(String[] rawAttrs, int defOffset) + { + mRawAttrs = rawAttrs; + mAttrMap = null; + mAttrHashSize = 0; + mAttrSpillEnd = 0; + mDefaultOffset = (defOffset << 2); + } + + /** + * Method called to create "long" attribute list; list that has + * a few entries, and efficient access by fully-qualified name should + * not be done by linear search. + * + * @param rawAttrs Array that contains 4 Strings for each attribute; + * localName, URI, prefix, value. Can be used to lazily construct + * structure(s) needed to return Iterator for accessing all + * attributes. + */ + public ElemAttrs(String[] rawAttrs, int defOffset, + int[] attrMap, int hashSize, int spillEnd) + { + mRawAttrs = rawAttrs; + mDefaultOffset = (defOffset << 2); + mAttrMap = attrMap; + mAttrHashSize = hashSize; + mAttrSpillEnd = spillEnd; + } + + /* + //////////////////////////////////////////////////// + // Public API + //////////////////////////////////////////////////// + */ + + public String[] getRawAttrs() { + return mRawAttrs; + } + + public int findIndex(QName name) + { + // Do we have a Map to do lookup against? + if (mAttrMap != null) { // yup + return findMapIndex(name.getNamespaceURI(), name.getLocalPart()); + } + + // Nope, linear search: + String ln = name.getLocalPart(); + String uri = name.getNamespaceURI(); + boolean defaultNs = (uri == null || uri.length() == 0); + String[] raw = mRawAttrs; + + for (int i = 0, len = raw.length; i < len; i += 4) { + if (!ln.equals(raw[i])) { + continue; + } + String thisUri = raw[i+OFFSET_NS_URI]; + if (defaultNs) { + if (thisUri == null || thisUri.length() == 0) { + return i; + } + } else { // non-default NS + if (thisUri != null && + (thisUri == uri || thisUri.equals(uri))) { + return i; + } + } + } + return -1; + } + + public int getFirstDefaultOffset() { + return mDefaultOffset; + } + + public boolean isDefault(int ix) { + return (ix >= mDefaultOffset); + } + + /* + //////////////////////////////////////////////////// + // Internal methods + //////////////////////////////////////////////////// + */ + + /** + *

+ * Note: this method is very similar to + * {@link com.ctc.wstx.sr.AttributeCollector#getAttrValue}; basically + * most of it was cut'n pasted. Would be nice to refactor, but it's + * bit hard to do that since data structures are not 100% identical + * (mostly attribute storage, not Map structure itself). + */ + private final int findMapIndex(String nsURI, String localName) + { + // Primary hit? + int hash = localName.hashCode(); + if (nsURI == null) { + nsURI = ""; // just to simplify comparisons -- array contains nulls + } else if (nsURI.length() > 0) { + hash ^= nsURI.hashCode(); + } + int ix = mAttrMap[hash & (mAttrHashSize - 1)]; + if (ix == 0) { // nothing in here; no spills either + return -1; + } + // Index is "one off" (since 0 indicates 'null), 4 Strings per attr + ix = (ix - 1) << 2; + + // Is primary candidate match? + String[] raw = mRawAttrs; + String thisName = raw[ix]; + /* Equality first, since although equals() checks that too, it's + * very likely to match (if interning Strings), and we can save + * a method call. + */ + if (thisName == localName || thisName.equals(localName)) { + String thisURI = raw[ix+OFFSET_NS_URI]; + if (thisURI == nsURI) { + return ix; + } + if (thisURI == null) { + if (nsURI.length() == 0) { + return ix; + } + } else if (thisURI.equals(nsURI)) { + return ix; + } + } + + /* Nope, need to traverse spill list, which has 2 entries for + * each spilled attribute id; first for hash value, second index. + */ + for (int i = mAttrHashSize, len = mAttrSpillEnd; i < len; i += 2) { + if (mAttrMap[i] != hash) { + continue; + } + /* Note: spill indexes are not off-by-one, since there's no need + * to mask 0 + */ + ix = mAttrMap[i+1] << 2; // ... but there are 4 Strings for each attr + thisName = raw[ix]; + if (thisName == localName || thisName.equals(localName)) { + String thisURI = raw[ix+1]; + if (thisURI == nsURI) { + return ix; + } + if (thisURI == null) { + if (nsURI.length() == 0) { + return ix; + } + } else if (thisURI.equals(nsURI)) { + return ix; + } + } + } + + return -1; + } +} diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/sr/ElemCallback.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/sr/ElemCallback.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/sr/ElemCallback.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/sr/ElemCallback.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,18 @@ +package com.ctc.wstx.sr; + +import javax.xml.stream.Location; +import javax.xml.namespace.QName; + +import com.ctc.wstx.util.BaseNsContext; + +/** + * Abstract base class that defines set of simple callbacks to be + * called by the stream reader, passing information about element + * that the stream currently points to, if any. + */ +public abstract class ElemCallback +{ + public abstract Object withStartElement(Location loc, QName name, + BaseNsContext nsCtxt, ElemAttrs attrs, + boolean wasEmpty); +} diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/sr/Element.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/sr/Element.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/sr/Element.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/sr/Element.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,99 @@ +/* Woodstox XML processor + * + * Copyright (c) 2004- Tatu Saloranta, tatu.saloranta@iki.fi + * + * Licensed under the License specified in file LICENSE, included with + * the source code. + * You may not use this file except in compliance with the License. + * + * 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 com.ctc.wstx.sr; + +/** + * Container for information collected regarding a single + * (start) element instance. + *

+ * This class is not exposed outside of the package and is considered + * part of internal implementation. + * + * @since 4.1 + */ +final class Element +{ + // // // Element name + + protected String mLocalName; + + /** + * Prefix this element has, if any; null if none + */ + protected String mPrefix; + + /** + * Namespace this element is in + */ + protected String mNamespaceURI; + + /** + * Default namespace for this element. + */ + protected String mDefaultNsURI; + + // // // Namespace support + + /** + * Offset within namespace array, maintained by + * {@link InputElementStack} that owns this element. + */ + protected int mNsOffset; + + // // // Back links to parent element(s) + + /** + * Parent element, if any; null for root + */ + protected Element mParent; + + /** + * Count of child elements + */ + protected int mChildCount; + + /* + ///////////////////////////////////////////////////////// + // Life-cycle + ///////////////////////////////////////////////////////// + */ + + public Element(Element parent, int nsOffset, String prefix, String ln) + { + mParent = parent; + mNsOffset = nsOffset; + mPrefix = prefix; + mLocalName = ln; + } + + public void reset(Element parent, int nsOffset, String prefix, String ln) + { + mParent = parent; + mNsOffset = nsOffset; + mPrefix = prefix; + mLocalName = ln; + mChildCount = 0; + } + + /** + * Method called to temporarily "store" this Element for later reuse. + */ + public void relink(Element next) + { + mParent = next; + } +} + diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/sr/InputElementStack.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/sr/InputElementStack.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/sr/InputElementStack.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/sr/InputElementStack.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,1077 @@ +/* Woodstox XML processor + * + * Copyright (c) 2004- Tatu Saloranta, tatu.saloranta@iki.fi + * + * Licensed under the License specified in file LICENSE, included with + * the source code. + * You may not use this file except in compliance with the License. + * + * 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 com.ctc.wstx.sr; + +import java.util.*; + +import javax.xml.XMLConstants; +import javax.xml.namespace.NamespaceContext; +import javax.xml.namespace.QName; +import javax.xml.stream.Location; +import javax.xml.stream.XMLStreamException; + +import org.codehaus.stax2.AttributeInfo; +import org.codehaus.stax2.validation.ValidationContext; +import org.codehaus.stax2.validation.XMLValidator; +import org.codehaus.stax2.validation.XMLValidationProblem; +import org.codehaus.stax2.validation.XMLValidationSchema; +import org.codehaus.stax2.validation.ValidatorPair; + +import com.ctc.wstx.api.ReaderConfig; +import com.ctc.wstx.api.WstxInputProperties; +import com.ctc.wstx.cfg.ErrorConsts; +import com.ctc.wstx.cfg.XmlConsts; +import com.ctc.wstx.compat.QNameCreator; +import com.ctc.wstx.dtd.DTDValidatorBase; // unfortunate dependency +import com.ctc.wstx.util.*; + +/** + * Shared base class that defines API stream reader uses to communicate + * with the element stack implementation, independent of whether it's + * operating in namespace-aware or non-namespace modes. + * Element stack class is used for storing nesting information about open + * elements, and for namespace-aware mode, also information about + * namespaces active (including default namespace), during parsing of + * XML input. + *

+ * This class also implements {@link NamespaceContext}, since it has all + * the information necessary, so parser can just return element stack + * instance as necesary. + */ +public final class InputElementStack + implements AttributeInfo, NamespaceContext, ValidationContext +{ + final static int ID_ATTR_NONE = -1; + + /* + /////////////////////////////////////////////////////////// + // Configuration + /////////////////////////////////////////////////////////// + */ + + protected final boolean mNsAware; + + protected final AttributeCollector mAttrCollector; + + protected final ReaderConfig mConfig; + + protected InputProblemReporter mReporter = null; + + /** + * Object that will need to be consulted about namespace bindings, + * since it has some knowledge about default namespace declarations + * (has default attribute value expansion). + */ + protected NsDefaultProvider mNsDefaultProvider; + + /* + /////////////////////////////////////////////////////////// + // Element, namespace information + /////////////////////////////////////////////////////////// + */ + + protected int mDepth = 0; + protected long mTotalElements = 0; + + /** + * Vector that contains all currently active namespaces; one String for + * prefix, another for matching URI. Does also include default name + * spaces (at most one per level). + */ + protected final StringVector mNamespaces = new StringVector(64); + + /** + * Currently open element, if any; null outside root element. + */ + protected Element mCurrElement; + + protected boolean mMayHaveNsDefaults = false; + + /* + /////////////////////////////////////////////////////////// + // Element validation (optional), attribute typing + /////////////////////////////////////////////////////////// + */ + + /** + * Optional validator object that will get called if set, + * and that can validate xml content. Note that it is possible + * that this is set to a proxy object that calls multiple + * validators in sequence. + */ + protected XMLValidator mValidator = null; + + /** + * Index of the attribute with type of ID, if known (most likely + * due to Xml:id support); -1 if not available, or no ID attribute + * for current element. + */ + protected int mIdAttrIndex = ID_ATTR_NONE; + + /* + /////////////////////////////////////////////////////////// + // Simple 1-slot QName cache; used for improving + // efficiency of code that uses QNames extensively + // (like StAX Event API implementation) + /////////////////////////////////////////////////////////// + */ + + protected String mLastLocalName = null; + protected String mLastPrefix = null; + protected String mLastNsURI = null; + + protected QName mLastName = null; + + /* + /////////////////////////////////////////////////////////// + // Other simple caching + /////////////////////////////////////////////////////////// + */ + + // Non-transient NamespaceContext caching; mostly for event API + + /** + * Last potentially shareable NamespaceContext created by + * this stack. This reference is cleared each time bindings + * change (either due to a start element with new bindings, or due + * to the matching end element that closes scope of such binding(s)). + */ + protected BaseNsContext mLastNsContext = null; + + // Chain of reusable Element instances + + protected Element mFreeElement = null; + + /* + /////////////////////////////////////////////////////////// + // Life-cycle (create, update state) + /////////////////////////////////////////////////////////// + */ + + protected InputElementStack(ReaderConfig cfg, boolean nsAware) + { + mConfig = cfg; + mNsAware = nsAware; + mAttrCollector = new AttributeCollector(cfg, nsAware); + } + + protected void connectReporter(InputProblemReporter rep) + { + mReporter = rep; + } + + protected XMLValidator addValidator(XMLValidator vld) + { + if (mValidator == null) { + mValidator = vld; + } else { + mValidator = new ValidatorPair(mValidator, vld); + } + return vld; + } + + /** + * Method called to connect the automatically handled DTD validator + * (one detected from DOCTYPE, loaded and completely handled by + * the stream reader without application calling validation methods). + * Handled separately, since its behaviour is potentially different + * from that of explicitly added validators. + */ + protected void setAutomaticDTDValidator(XMLValidator validator, NsDefaultProvider nsDefs) + { + mNsDefaultProvider = nsDefs; + addValidator(validator); + } + + /* + /////////////////////////////////////////////////////////// + // Start/stop validation + /////////////////////////////////////////////////////////// + */ + + public XMLValidator validateAgainst(XMLValidationSchema schema) + throws XMLStreamException + { + /* Should we first check if we maybe already have a validator + * for the schema? + */ + return addValidator(schema.createValidator(this)); + } + + + + public XMLValidator stopValidatingAgainst(XMLValidationSchema schema) + throws XMLStreamException + { + XMLValidator[] results = new XMLValidator[2]; + if (ValidatorPair.removeValidator(mValidator, schema, results)) { // found + XMLValidator found = results[0]; + mValidator = results[1]; + found.validationCompleted(false); + return found; + } + return null; + } + + public XMLValidator stopValidatingAgainst(XMLValidator validator) + throws XMLStreamException + { + XMLValidator[] results = new XMLValidator[2]; + if (ValidatorPair.removeValidator(mValidator, validator, results)) { // found + XMLValidator found = results[0]; + mValidator = results[1]; + found.validationCompleted(false); + return found; + } + return null; + } + + /* + /////////////////////////////////////////////////////////// + // Accessors: + /////////////////////////////////////////////////////////// + */ + + /** + * This is a method called by the reader to ensure that we have at + * least one 'real' validator. This is only needed to ensure that + * validation problems that the reader can detect (illegal textual + * content) can be reported as validity errors. Since the validator + * API does not have a good way to cleanly deal with such a possibility, + * the check is rather fragile, but should work for now: essentially + * we need at least one validator object that either is not a sub-class + * of DTDValidatorBase or returns true for + * reallyValidating. + *

+ * !!! TODO: remove need for this method (and method itself) with + * Woodstox 4.0, by adding necessary support in Stax2 XMLValidator + * interface. + */ + protected boolean reallyValidating() + { + if (mValidator == null) { // no validators, no validation + // (although, should never get called if no validators) + return false; + } + if (!(mValidator instanceof DTDValidatorBase)) { + // note: happens for validator pair, for one + return true; + } + return ((DTDValidatorBase) mValidator).reallyValidating(); + } + + /** + * Method called by {@link BasicStreamReader}, to retrieve the + * attribute collector it needs for some direct access. + */ + public final AttributeCollector getAttrCollector() { + return mAttrCollector; + } + + /** + * Method called to construct a non-transient NamespaceContext instance; + * generally needed when creating events to return from event-based + * iterators. + */ + public BaseNsContext createNonTransientNsContext(Location loc) + { + // Have an instance we can reuse? Great! + if (mLastNsContext != null) { + return mLastNsContext; + } + + // No namespaces declared at this point? Easy, as well: + int totalNsSize = mNamespaces.size(); + if (totalNsSize < 1) { + return (mLastNsContext = EmptyNamespaceContext.getInstance()); + } + + // Otherwise, we need to create a new non-empty context: + int localCount = getCurrentNsCount() << 1; + BaseNsContext nsCtxt = new CompactNsContext + (loc, /*getDefaultNsURI(),*/ + mNamespaces.asArray(), totalNsSize, + totalNsSize - localCount); + /* And it can be shared if there are no new ('local', ie. included + * within this start element) bindings -- if there are, underlying + * array might be shareable, but offsets wouldn't be) + */ + if (localCount == 0) { + mLastNsContext = nsCtxt; + } + return nsCtxt; +} + + /** + * Method called by the stream reader to add new (start) element + * into the stack in namespace-aware mode; called when a start element + * is encountered during parsing, but only in ns-aware mode. + * @throws XMLStreamException + */ + public final void push(String prefix, String localName) throws XMLStreamException + { + if (++mDepth > mConfig.getMaxElementDepth()) { + throw new XMLStreamException("Maximum Element Depth limit ("+mConfig.getMaxElementDepth()+") Exceeded"); + } + if (++mTotalElements > mConfig.getMaxElementCount()) { + throw new XMLStreamException("Maximum Element Count limit ("+mConfig.getMaxElementCount()+") Exceeded"); + } + String defaultNs = (mCurrElement == null) ? + XmlConsts.DEFAULT_NAMESPACE_URI : mCurrElement.mDefaultNsURI; + if (mCurrElement != null) { + ++mCurrElement.mChildCount; + final int max = mConfig.getMaxChildrenPerElement(); + if (max > 0 && mCurrElement.mChildCount > max) { + throw new XMLStreamException("Maximum Number of Child Elements limit ("+max+") Exceeded"); + } + } + + if (mFreeElement == null) { + mCurrElement = new Element(mCurrElement, mNamespaces.size(), prefix, localName); + } else { + Element newElem = mFreeElement; + mFreeElement = newElem.mParent; + newElem.reset(mCurrElement, mNamespaces.size(), prefix, localName); + mCurrElement = newElem; + } + mCurrElement.mDefaultNsURI = defaultNs; + mAttrCollector.reset(); + + /* 20-Feb-2006, TSa: Hmmh. Namespace default provider unfortunately + * needs an advance warning... + */ + if (mNsDefaultProvider != null) { + mMayHaveNsDefaults = mNsDefaultProvider.mayHaveNsDefaults(prefix, localName); + } + } + + /** + * Method called by the stream reader to remove the topmost (start) + * element from the stack; + * called when an end element is encountered during parsing. + * + * @return True if stack has more elements; false if not (that is, + * root element closed) + */ + public final boolean pop() throws XMLStreamException + { + if (mCurrElement == null) { + throw new IllegalStateException("Popping from empty stack"); + } + --mDepth; + + Element child = mCurrElement; + Element parent = child.mParent; + mCurrElement = parent; + + // Let's do simple recycling of Element instances... + child.relink(mFreeElement); + mFreeElement = child; + + // Need to purge namespaces? + int nsCount = mNamespaces.size() - child.mNsOffset; + if (nsCount > 0) { // 2 entries for each NS mapping: + mLastNsContext = null; // let's invalidate ns ctxt too, if we had one + mNamespaces.removeLast(nsCount); + } + return (parent != null); + } + + /** + * Method called to resolve element and attribute namespaces (in + * namespace-aware mode), and do optional validation using pluggable + * validator object. + * + * @return Text content validation state that should be effective + * for the fully resolved element context + */ + public int resolveAndValidateElement() + throws XMLStreamException + { + if (mDepth == 0) { // just a simple sanity check + throw new IllegalStateException("Calling validate() on empty stack."); + } + AttributeCollector ac = mAttrCollector; + + // Any namespace declarations? + { + int nsCount = ac.getNsCount(); + if (nsCount > 0) { + /* let's first invalidate old (possibly) shared ns ctxt too, + * if we had one; new one can be created at a later point + */ + mLastNsContext = null; + + boolean internNsUris = mConfig.willInternNsURIs(); + for (int i = 0; i < nsCount; ++i) { + Attribute ns = ac.resolveNamespaceDecl(i, internNsUris); + String nsUri = ns.mNamespaceURI; + // note: for namespaces, prefix is stored as local name + String prefix = ns.mLocalName; + + /* 18-Jul-2004, TSa: Need to check that 'xml' and 'xmlns' + * prefixes are not re-defined (and 'xmlns' not even + * defined to its correct ns). + */ + if (prefix == "xmlns") { + // xmlns can never be declared, even to its correct URI + mReporter.throwParseError(ErrorConsts.ERR_NS_REDECL_XMLNS); + } else if (prefix == "xml") { + // whereas xml is ok, as long as it's same URI: + if (!nsUri.equals(XMLConstants.XML_NS_URI)) { + mReporter.throwParseError(ErrorConsts.ERR_NS_REDECL_XML, + nsUri, null); + } + /* 09-Feb-2006, TSa: Hmmh. Now, should this explicit + * xml declaration be visible to the app? SAX API + * seem to ignore it. + */ + //mNamespaces.addStrings(prefix, nsUri); + } else { // ok, valid prefix, so far + /* 17-Mar-2006, TSa: Unbinding default NS needs to + * result in null being added: + */ + if (nsUri == null || nsUri.length() == 0) { + nsUri = XmlConsts.DEFAULT_NAMESPACE_URI; + } + // The default ns binding needs special handling: + if (prefix == null) { + mCurrElement.mDefaultNsURI = nsUri; + } + + /* But then let's ensure that URIs matching xml + * and xmlns are not being bound to anything else + */ + if (internNsUris) { // identity comparison is ok: + if (nsUri == XMLConstants.XML_NS_URI) { + mReporter.throwParseError(ErrorConsts.ERR_NS_REDECL_XML_URI, prefix, null); + } else if (nsUri == XMLConstants.XMLNS_ATTRIBUTE_NS_URI) { + mReporter.throwParseError(ErrorConsts.ERR_NS_REDECL_XMLNS_URI); + } + } else { // need to check equals() + if (nsUri.equals(XMLConstants.XML_NS_URI)) { + mReporter.throwParseError(ErrorConsts.ERR_NS_REDECL_XML_URI, prefix, null); + } else if (nsUri.equals(XMLConstants.XMLNS_ATTRIBUTE_NS_URI)) { + mReporter.throwParseError(ErrorConsts.ERR_NS_REDECL_XMLNS_URI); + } + } + /* and at any rate, binding needs to be added, to + * be visible to the app (including def ns): + */ + mNamespaces.addStrings(prefix, nsUri); + } + } + } + } + + /* 20-Feb-2006, TSa: Any attribute defaults for namespace declaration + * pseudo-attributes? + */ + if (mMayHaveNsDefaults) { + mNsDefaultProvider.checkNsDefaults(this); + } + + // Then, let's set element's namespace, if any: + String prefix = mCurrElement.mPrefix; + String ns; + + if (prefix == null) { // use default NS, if any + ns = mCurrElement.mDefaultNsURI; + } else if (prefix == "xml") { + ns = XMLConstants.XML_NS_URI; + } else { + // Need to find namespace with the prefix: + ns = mNamespaces.findLastFromMap(prefix); + /* 07-Sep-2007, TSa: "no namespace" should now be indicated + * by an empty string, however, due to historical reasons + * let's be bit defensive and allow nulls for the same too + */ + if (ns == null || ns.length() == 0) { + mReporter.throwParseError(ErrorConsts.ERR_NS_UNDECLARED, prefix, null); + } + } + mCurrElement.mNamespaceURI = ns; + + // And finally, resolve attributes' namespaces too: + int xmlidIx = ac.resolveNamespaces(mReporter, mNamespaces); + mIdAttrIndex = xmlidIx; + + XMLValidator vld = mValidator; + /* If we have no validator(s), nothing more to do, + * except perhaps little bit of Xml:id handling: + */ + if (vld == null) { // no validator in use + if (xmlidIx >= 0) { // need to normalize xml:id, still? + ac.normalizeSpacesInValue(xmlidIx); + } + return XMLValidator.CONTENT_ALLOW_ANY_TEXT; + } + + // Otherwise need to call relevant validation methods. + + /* First, a call to check if the element itself may be acceptable + * within structure: + */ + vld.validateElementStart + (mCurrElement.mLocalName, mCurrElement.mNamespaceURI, mCurrElement.mPrefix); + + // Then attributes, if any: + int attrLen = ac.getCount(); + if (attrLen > 0) { + for (int i = 0; i < attrLen; ++i) { + ac.validateAttribute(i, mValidator); + } + } + + /* And finally let's wrap things up to see what textual content + * is allowed as child content, if any: + */ + return mValidator.validateElementAndAttributes(); + } + + /** + * Method called after parsing (but before returning) end element, + * to allow for pluggable validators to verify correctness of + * the content model for the closing element. + * + * @return Validation state that should be effective for the parent + * element state + */ + public int validateEndElement() + throws XMLStreamException + { + if (mValidator == null) { // should never be null if we get here + return XMLValidator.CONTENT_ALLOW_ANY_TEXT; + } + int result = mValidator.validateElementEnd + (mCurrElement.mLocalName, mCurrElement.mNamespaceURI, mCurrElement.mPrefix); + if (mDepth == 1) { // root closing + mValidator.validationCompleted(true); + } + return result; + } + + /* + /////////////////////////////////////////////////////////// + // AttributeInfo methods (StAX2) + /////////////////////////////////////////////////////////// + */ + + @Override + public final int getAttributeCount() { + return mAttrCollector.getCount(); + } + + @Override + public final int findAttributeIndex(String nsURI, String localName) { + return mAttrCollector.findIndex(nsURI, localName); + } + + /** + * Default implementation just indicates it does not know of such + * attributes; this because that requires DTD information that only + * some implementations have. + */ + @Override + public final int getIdAttributeIndex() + { + if (mIdAttrIndex >= 0) { + return mIdAttrIndex; + } + return (mValidator == null) ? -1 : mValidator.getIdAttrIndex(); + } + + /** + * Default implementation just indicates it does not know of such + * attributes; this because that requires DTD information that only + * some implementations have. + */ + @Override + public final int getNotationAttributeIndex() + { + return (mValidator == null) ? -1 : + mValidator.getNotationAttrIndex(); + } + + /* + /////////////////////////////////////////////////////////// + // Implementation of NamespaceContext: + /////////////////////////////////////////////////////////// + */ + + @Override + public final String getNamespaceURI(String prefix) + { + if (prefix == null) { + throw new IllegalArgumentException(ErrorConsts.ERR_NULL_ARG); + } + if (prefix.length() == 0) { + if (mDepth == 0) { // unexpected... but let's not err at this point + /* 07-Sep-2007, TSa: Default/"no namespace" does map to + * "URI" of empty String. + */ + return XmlConsts.DEFAULT_NAMESPACE_URI; + } + return mCurrElement.mDefaultNsURI; + } + if (prefix.equals(XMLConstants.XML_NS_PREFIX)) { + return XMLConstants.XML_NS_URI; + } + if (prefix.equals(XMLConstants.XMLNS_ATTRIBUTE)) { + return XMLConstants.XMLNS_ATTRIBUTE_NS_URI; + } + /* Ok, need to find the match, if any; starting from end of the + * list of active namespaces. Note that we can not count on prefix + * being interned/canonicalized. + */ + return mNamespaces.findLastNonInterned(prefix); + } + + @Override + public final String getPrefix(String nsURI) + { + if (nsURI == null || nsURI.length() == 0) { + throw new IllegalArgumentException("Illegal to pass null/empty prefix as argument."); + } + if (nsURI.equals(XMLConstants.XML_NS_URI)) { + return XMLConstants.XML_NS_PREFIX; + } + if (nsURI.equals(XMLConstants.XMLNS_ATTRIBUTE_NS_URI)) { + return XMLConstants.XMLNS_ATTRIBUTE; + } + /* Ok, need to find the match, if any; starting from end of the + * list of active namespaces. Note that we can not count on prefix + * being interned/canonicalized. + */ + String prefix = null; + + // 29-Sep-2004, TSa: Need to check for namespace masking, too... + String[] strs = mNamespaces.getInternalArray(); + int len = mNamespaces.size(); + + main_loop: + for (int index = len-1; index > 0; index -= 2) { + if (nsURI.equals(strs[index])) { + // Ok, is prefix masked? + prefix = strs[index-1]; + for (int j = index+1; j < len; j += 2) { + if (strs[j] == prefix) { // masked! + prefix = null; + continue main_loop; + } + } + // nah, it's good + // 17-Mar-2006, TSa: ... but default NS has prefix null... + if (prefix == null) { + prefix = ""; + } + break main_loop; + } + } + + return prefix; + } + + @Override + public final Iterator getPrefixes(String nsURI) + { + if (nsURI == null || nsURI.length() == 0) { + throw new IllegalArgumentException("Illegal to pass null/empty prefix as argument."); + } + if (nsURI.equals(XMLConstants.XML_NS_URI)) { + return DataUtil.singletonIterator(XMLConstants.XML_NS_PREFIX); + } + if (nsURI.equals(XMLConstants.XMLNS_ATTRIBUTE_NS_URI)) { + return DataUtil.singletonIterator(XMLConstants.XMLNS_ATTRIBUTE); + } + + // 29-Sep-2004, TSa: Need to check for namespace masking, too... + String[] strs = mNamespaces.getInternalArray(); + int len = mNamespaces.size(); + ArrayList l = null; + + main_loop: + for (int index = len-1; index > 0; index -= 2) { + if (nsURI.equals(strs[index])) { + // Ok, is prefix masked? + String prefix = strs[index-1]; + for (int j = index+1; j < len; j += 2) { + if (strs[j] == prefix) { // masked! + continue main_loop; + } + } + // nah, it's good! + if (l == null) { + l = new ArrayList(); + } + l.add(prefix); + } + } + + if (l == null) { + return DataUtil.emptyIterator(); + } + return l.iterator(); + } + + /* + /////////////////////////////////////////////////////////// + // ValidationContext + /////////////////////////////////////////////////////////// + */ + + @Override + public final String getXmlVersion() + { + return mConfig.isXml11() ? XmlConsts.XML_V_11_STR : XmlConsts.XML_V_10_STR; + } + + // Part of Stax2, see above: + //public int getAttributeCount(); + + @Override + public String getAttributeLocalName(int index) { + return getAttrCollector().getLocalName(index); + } + + @Override + public String getAttributeNamespace(int index) { + return getAttrCollector().getURI(index); + } + + @Override + public String getAttributePrefix(int index) { + return getAttrCollector().getPrefix(index); + } + + @Override + public String getAttributeValue(int index) { + return getAttrCollector().getValue(index); + } + + @Override + public String getAttributeValue(String nsURI, String localName) + { + int ix = findAttributeIndex(nsURI, localName); + return (ix < 0) ? null : getAttributeValue(ix); + } + + // Part of Stax2, see above: + //public int findAttributeIndex(String nsURI, String localName); + + @Override + public boolean isNotationDeclared(String name) + { + // !!! TBI + return false; + } + + @Override + public boolean isUnparsedEntityDeclared(String name) + { + // !!! TBI + return false; + } + + @Override + public String getBaseUri() { + // !!! TBI + return null; + } + + @Override + public final QName getCurrentElementName() + { + if (mDepth == 0) { + return null; + } + String prefix = mCurrElement.mPrefix; + /* 17-Mar-2006, TSa: We only map prefix to empty String because + * some QName impls barf on nulls. Otherwise we will always + * use null to indicate missing prefixes. + */ + if (prefix == null) { + prefix = ""; + } + /* 03-Dec-2004, TSa: Maybe we can just reuse the last QName + * object created, if we have same data? (happens if + * state hasn't changed, or we got end element for a leaf + * element, or repeating leaf elements) + */ + String nsURI = mCurrElement.mNamespaceURI; + String ln = mCurrElement.mLocalName; + + /* Since we generally intern most Strings, can do identity + * comparisons here: + */ + if (ln != mLastLocalName) { + mLastLocalName = ln; + mLastPrefix = prefix; + mLastNsURI = nsURI; + } else if (prefix != mLastPrefix) { + mLastPrefix = prefix; + mLastNsURI = nsURI; + } else if (nsURI != mLastNsURI) { + mLastNsURI = nsURI; + } else { + return mLastName; + } + QName n = QNameCreator.create(nsURI, ln, prefix); + mLastName = n; + return n; + } + + // This was defined above for NamespaceContext + //public String getNamespaceURI(String prefix); + + @Override + public Location getValidationLocation() { + return mReporter.getLocation(); + } + + @Override + public void reportProblem(XMLValidationProblem problem) + throws XMLStreamException + { + mReporter.reportValidationProblem(problem); + } + + /** + * Method called by actual validator instances when attributes with + * default values have no explicit values for the element; if so, + * default value needs to be added as if it was parsed from the + * element. + */ + @Override + public int addDefaultAttribute(String localName, String uri, String prefix, + String value) throws XMLStreamException + { + return mAttrCollector.addDefaultAttribute(localName, uri, prefix, value); + } + + /* + /////////////////////////////////////////////////////////// + // Support for NsDefaultProvider + /////////////////////////////////////////////////////////// + */ + + public boolean isPrefixLocallyDeclared(String internedPrefix) + { + if (internedPrefix != null && internedPrefix.length() == 0) { // default ns + internedPrefix = null; + } + + int offset = mCurrElement.mNsOffset; + for (int len = mNamespaces.size(); offset < len; offset += 2) { + // both interned, can use identity comparison + String thisPrefix = mNamespaces.getString(offset); + if (thisPrefix == internedPrefix) { + return true; + } + } + return false; + } + + /** + * Callback method called by the namespace default provider. At + * this point we can trust it to only call this method with somewhat + * valid arguments (no dups etc). + */ + public void addNsBinding(String prefix, String uri) + { + // Unbind? (xml 1.1...) + if ((uri == null) || (uri.length() == 0)) { + uri = null; + } + + // Default ns declaration? + if ((prefix == null) || (prefix.length() == 0)) { + prefix = null; + mCurrElement.mDefaultNsURI = uri; + } + mNamespaces.addStrings(prefix, uri); + } + + /* + /////////////////////////////////////////////////////////// + // Support for validation: + /////////////////////////////////////////////////////////// + */ + + public final void validateText(TextBuffer tb, boolean lastTextSegment) + throws XMLStreamException + { + tb.validateText(mValidator, lastTextSegment); + } + + public final void validateText(String contents, boolean lastTextSegment) + throws XMLStreamException + { + mValidator.validateText(contents, lastTextSegment); + } + + /* + /////////////////////////////////////////////////////////// + // Accessors: + /////////////////////////////////////////////////////////// + */ + + // // // Generic stack information: + + public final boolean isNamespaceAware() { + return mNsAware; + } + + // // // Generic stack information: + + public final boolean isEmpty() { + return mDepth == 0; + } + + /** + * @return Number of open elements in the stack; 0 when parser is in + * prolog/epilog, 1 inside root element and so on. + */ + public final int getDepth() { return mDepth; } + + // // // Information about element at top of stack: + + public final String getDefaultNsURI() { + if (mDepth == 0) { + throw new IllegalStateException("Illegal access, empty stack."); + } + return mCurrElement.mDefaultNsURI; + } + + public final String getNsURI() { + if (mDepth == 0) { + throw new IllegalStateException("Illegal access, empty stack."); + } + return mCurrElement.mNamespaceURI; + } + + public final String getPrefix() { + if (mDepth == 0) { + throw new IllegalStateException("Illegal access, empty stack."); + } + return mCurrElement.mPrefix; + } + + public final String getLocalName() { + if (mDepth == 0) { + throw new IllegalStateException("Illegal access, empty stack."); + } + return mCurrElement.mLocalName; + } + + public final boolean matches(String prefix, String localName) + { + if (mDepth == 0) { + throw new IllegalStateException("Illegal access, empty stack."); + } + String thisPrefix = mCurrElement.mPrefix; + if (prefix == null || prefix.length() == 0) { // no name space + if (thisPrefix != null && thisPrefix.length() > 0) { + return false; + } + } else { + if (thisPrefix != prefix && !thisPrefix.equals(prefix)) { + return false; + } + } + + String thisName = mCurrElement.mLocalName; + return (thisName == localName) || thisName.equals(localName); + } + + public final String getTopElementDesc() + { + if (mDepth == 0) { + throw new IllegalStateException("Illegal access, empty stack."); + } + String name = mCurrElement.mLocalName; + String prefix = mCurrElement.mPrefix; + if (prefix == null) { // no name space + return name; + } + return prefix + ":" + name; + } + + // // // Namespace information: + + /** + * @return Number of active prefix/namespace mappings for current scope, + * including mappings from enclosing elements. + */ + public final int getTotalNsCount() { + return mNamespaces.size() >> 1; + } + + /** + * @return Number of active prefix/namespace mappings for current scope, + * NOT including mappings from enclosing elements. + */ + public final int getCurrentNsCount() + { + // Need not check for empty stack; should return 0 properly + return (mNamespaces.size() - mCurrElement.mNsOffset) >> 1; + } + + public final String getLocalNsPrefix(int index) + { + int offset = mCurrElement.mNsOffset; + int localCount = (mNamespaces.size() - offset); + index <<= 1; // 2 entries, prefix/URI for each NS + if (index < 0 || index >= localCount) { + throwIllegalIndex(index >> 1, localCount >> 1); + } + return mNamespaces.getString(offset + index); + } + + public final String getLocalNsURI(int index) + { + int offset = mCurrElement.mNsOffset; + int localCount = (mNamespaces.size() - offset); + index <<= 1; // 2 entries, prefix/URI for each NS + if (index < 0 || index >= localCount) { + throwIllegalIndex(index >> 1, localCount >> 1); + } + return mNamespaces.getString(offset + index + 1); + } + + private void throwIllegalIndex(int index, int localCount) + { + throw new IllegalArgumentException("Illegal namespace index " + +(index >> 1)+"; current scope only has " + +(localCount >> 1)+" namespace declarations."); + } + + // // // DTD-derived attribute information: + + /** + * @return Schema (DTD, RNG, W3C Schema) based type of the attribute + * in specified index + */ + @Override + public final String getAttributeType(int index) + { + if (index == mIdAttrIndex && index >= 0) { // second check to ensure -1 is not passed + return "ID"; + } + return (mValidator == null) ? WstxInputProperties.UNKNOWN_ATTR_TYPE : + mValidator.getAttributeType(index); + } +} diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/sr/InputProblemReporter.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/sr/InputProblemReporter.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/sr/InputProblemReporter.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/sr/InputProblemReporter.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,53 @@ +package com.ctc.wstx.sr; + +import javax.xml.stream.Location; +import javax.xml.stream.XMLStreamException; + +import org.codehaus.stax2.validation.XMLValidationProblem; + +/** + * Interface implemented by input reader, and used by other components to + * report problem that are related to current input position. + */ +public interface InputProblemReporter +{ + /* + //////////////////////////////////////////////////// + // Methods for reporting "hard" errors: + //////////////////////////////////////////////////// + */ + + public void throwParseError(String msg) throws XMLStreamException; + public void throwParseError(String msg, Object arg, Object arg2) + throws XMLStreamException; + + /* + /////////////////////////////////////////////////////// + // Reporting validation problems + /////////////////////////////////////////////////////// + */ + + public void reportValidationProblem(XMLValidationProblem prob) + throws XMLStreamException; + public void reportValidationProblem(String msg) + throws XMLStreamException; + public void reportValidationProblem(String msg, Object arg, Object arg2) + throws XMLStreamException; + + /* + /////////////////////////////////////////////////////// + // Methods for reporting other "soft" (recoverable) problems + /////////////////////////////////////////////////////// + */ + + public void reportProblem(Location loc, String probType, String format, Object arg, Object arg2) + throws XMLStreamException; + + /* + //////////////////////////////////////////////////// + // Supporting methods needed by reporting + //////////////////////////////////////////////////// + */ + + public Location getLocation(); +} diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/sr/NsDefaultProvider.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/sr/NsDefaultProvider.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/sr/NsDefaultProvider.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/sr/NsDefaultProvider.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,44 @@ +/* Woodstox XML processor + * + * Copyright (c) 2004- Tatu Saloranta, tatu.saloranta@iki.fi + * + * Licensed under the License specified in file LICENSE, included with + * the source code. + * You may not use this file except in compliance with the License. + * + * 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 com.ctc.wstx.sr; + +import javax.xml.stream.XMLStreamException; + +/** + * Interface only used by Woodstox core. The main reason for the interface + * is to reduce coupling with the input element stack and dtd validator + * instances: while dtd validator needs to be able to inject namespace + * declarations based on attribute default values, it should not have to + * know too much about element stack implementation, and vice versa. + * As a result, this interface defines API input element stack calls + * on the dtd validator instance. Validator instance then refers to the + * input element stack base class to do callbacks if and as necessary. + */ +public interface NsDefaultProvider +{ + public boolean mayHaveNsDefaults(String elemPrefix, String elemLN); + + /** + * Method called by the input element stack to indicate that + * it has just added local namespace declarations from the + * current element, and is about to start resolving element + * and attribute namespace bindings. This provider instance is + * to add namespace declarations from attribute defaults, if + * any, using callbacks to the input element stack. + */ + public void checkNsDefaults(InputElementStack nsStack) + throws XMLStreamException; +} diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/sr/package.html libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/sr/package.html --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/sr/package.html 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/sr/package.html 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,4 @@ + +This package contains supporting code for handling namespace information; +element stacks that keep track of elements parsed and such. + diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/sr/ReaderCreator.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/sr/ReaderCreator.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/sr/ReaderCreator.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/sr/ReaderCreator.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,34 @@ +package com.ctc.wstx.sr; + +import com.ctc.wstx.dtd.DTDId; +import com.ctc.wstx.dtd.DTDSubset; +import com.ctc.wstx.util.SymbolTable; + +/** + * Interface that defines callbacks readers can use to access settings + * of the input factory that created them, as well as update cached + * data factory may store (shared symbol tables, cached DTDs etc). + *

+ * Note that readers in general should only access the configuration info + * when they are created (from constructor). + */ +public interface ReaderCreator +{ + /* + /////////////////////////////////////////////////////// + // Methods for accessing configuration info + /////////////////////////////////////////////////////// + */ + + public DTDSubset findCachedDTD(DTDId id); + + /* + /////////////////////////////////////////////////////// + // Methods for updating information factory has + /////////////////////////////////////////////////////// + */ + + public void updateSymbolTable(SymbolTable t); + + public void addCachedDTD(DTDId id, DTDSubset extSubset); +} diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/sr/StreamReaderImpl.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/sr/StreamReaderImpl.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/sr/StreamReaderImpl.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/sr/StreamReaderImpl.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,28 @@ +package com.ctc.wstx.sr; + +import javax.xml.stream.*; + +import org.codehaus.stax2.XMLStreamReader2; + +import com.ctc.wstx.ent.EntityDecl; + +/** + * Interface that defines "internal Woodstox API". It is used to decouple + * parts of the Woodstox that need to know something more about woodstox + * stream reader implementation, but not about implementation details. + * Specifically, there are some simple dependencies from the stream + * writer; they should only need to refer to this interface. + */ +public interface StreamReaderImpl + extends XMLStreamReader2 +{ + public EntityDecl getCurrentEntityDecl(); + + public Object withStartElement(ElemCallback cb, Location loc); + + public boolean isNamespaceAware(); + + public AttributeCollector getAttributeCollector(); + + public InputElementStack getInputElementStack(); +} diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/sr/StreamScanner.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/sr/StreamScanner.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/sr/StreamScanner.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/sr/StreamScanner.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,2469 @@ +/* Woodstox XML processor + * + * Copyright (c) 2004- Tatu Saloranta, tatu.saloranta@iki.fi + * + * Licensed under the License specified in file LICENSE, included with + * the source code. + * You may not use this file except in compliance with the License. + * + * 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 com.ctc.wstx.sr; + +import java.io.FileNotFoundException; +import java.io.IOException; +import java.net.URL; +import java.text.MessageFormat; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +import javax.xml.stream.Location; +import javax.xml.stream.XMLInputFactory; +import javax.xml.stream.XMLReporter; +import javax.xml.stream.XMLResolver; +import javax.xml.stream.XMLStreamException; + +import org.codehaus.stax2.XMLReporter2; +import org.codehaus.stax2.XMLStreamLocation2; +import org.codehaus.stax2.validation.XMLValidationProblem; + +import com.ctc.wstx.api.ReaderConfig; +import com.ctc.wstx.cfg.ErrorConsts; +import com.ctc.wstx.cfg.InputConfigFlags; +import com.ctc.wstx.cfg.ParsingErrorMsgs; +import com.ctc.wstx.cfg.XmlConsts; +import com.ctc.wstx.dtd.MinimalDTDReader; +import com.ctc.wstx.ent.EntityDecl; +import com.ctc.wstx.ent.IntEntity; +import com.ctc.wstx.exc.*; +import com.ctc.wstx.io.DefaultInputResolver; +import com.ctc.wstx.io.WstxInputData; +import com.ctc.wstx.io.WstxInputLocation; +import com.ctc.wstx.io.WstxInputSource; +import com.ctc.wstx.util.ExceptionUtil; +import com.ctc.wstx.util.SymbolTable; +import com.ctc.wstx.util.TextBuffer; + +/** + * Abstract base class that defines some basic functionality that all + * Woodstox reader classes (main XML reader, DTD reader) extend from. + */ +public abstract class StreamScanner + extends WstxInputData + implements InputProblemReporter, + InputConfigFlags, ParsingErrorMsgs +{ + + // // // Some well-known chars: + + /** + * Last (highest) char code of the three, LF, CR and NULL + */ + public final static char CHAR_CR_LF_OR_NULL = (char) 13; + + public final static int INT_CR_LF_OR_NULL = 13; + + /** + * Character that allows quick check of whether a char can potentially + * be some kind of markup, WRT input stream processing; + * has to contain linefeeds, &, < and > (">" only matters when + * quoting text, as part of "]]>") + */ + protected final static char CHAR_FIRST_PURE_TEXT = (char) ('>' + 1); + + + /** + * First character in Unicode (ie one with lowest id) that is legal + * as part of a local name (all valid name chars minus ':'). Used + * for doing quick check for local name end; usually name ends in + * a whitespace or equals sign. + */ + protected final static char CHAR_LOWEST_LEGAL_LOCALNAME_CHAR = '-'; + + /* + /////////////////////////////////////////////////////////////////////// + // Character validity constants, structs + /////////////////////////////////////////////////////////////////////// + */ + + /** + * We will only use validity array for first 256 characters, mostly + * because after those characters it's easier to do fairly simple + * block checks. + */ + private final static int VALID_CHAR_COUNT = 0x100; + + private final static byte NAME_CHAR_INVALID_B = (byte) 0; + private final static byte NAME_CHAR_ALL_VALID_B = (byte) 1; + private final static byte NAME_CHAR_VALID_NONFIRST_B = (byte) -1; + + private final static byte[] sCharValidity = new byte[VALID_CHAR_COUNT]; + + static { + // First, since all valid-as-first chars are also valid-as-other chars, + // we'll initialize common chars: + sCharValidity['_'] = NAME_CHAR_ALL_VALID_B; + for (int i = 0, last = ('z' - 'a'); i <= last; ++i) { + sCharValidity['A' + i] = NAME_CHAR_ALL_VALID_B; + sCharValidity['a' + i] = NAME_CHAR_ALL_VALID_B; + } + for (int i = 0xC0; i < 0xF6; ++i) { // not all are fully valid, but + sCharValidity[i] = NAME_CHAR_ALL_VALID_B; + } + // ... now we can 'revert' ones not fully valid: + sCharValidity[0xD7] = NAME_CHAR_INVALID_B; + sCharValidity[0xF7] = NAME_CHAR_INVALID_B; + + // And then we can proceed with ones only valid-as-other. + sCharValidity['-'] = NAME_CHAR_VALID_NONFIRST_B; + sCharValidity['.'] = NAME_CHAR_VALID_NONFIRST_B; + sCharValidity[0xB7] = NAME_CHAR_VALID_NONFIRST_B; + for (int i = '0'; i <= '9'; ++i) { + sCharValidity[i] = NAME_CHAR_VALID_NONFIRST_B; + } + } + + /** + * Public identifiers only use 7-bit ascii range. + */ + private final static int VALID_PUBID_CHAR_COUNT = 0x80; + private final static byte[] sPubidValidity = new byte[VALID_PUBID_CHAR_COUNT]; +// private final static byte PUBID_CHAR_INVALID_B = (byte) 0; + private final static byte PUBID_CHAR_VALID_B = (byte) 1; + static { + for (int i = 0, last = ('z' - 'a'); i <= last; ++i) { + sPubidValidity['A' + i] = PUBID_CHAR_VALID_B; + sPubidValidity['a' + i] = PUBID_CHAR_VALID_B; + } + for (int i = '0'; i <= '9'; ++i) { + sPubidValidity[i] = PUBID_CHAR_VALID_B; + } + + // 3 main white space types are valid + sPubidValidity[0x0A] = PUBID_CHAR_VALID_B; + sPubidValidity[0x0D] = PUBID_CHAR_VALID_B; + sPubidValidity[0x20] = PUBID_CHAR_VALID_B; + + // And many of punctuation/separator ascii chars too: + sPubidValidity['-'] = PUBID_CHAR_VALID_B; + sPubidValidity['\''] = PUBID_CHAR_VALID_B; + sPubidValidity['('] = PUBID_CHAR_VALID_B; + sPubidValidity[')'] = PUBID_CHAR_VALID_B; + sPubidValidity['+'] = PUBID_CHAR_VALID_B; + sPubidValidity[','] = PUBID_CHAR_VALID_B; + sPubidValidity['.'] = PUBID_CHAR_VALID_B; + sPubidValidity['/'] = PUBID_CHAR_VALID_B; + sPubidValidity[':'] = PUBID_CHAR_VALID_B; + sPubidValidity['='] = PUBID_CHAR_VALID_B; + sPubidValidity['?'] = PUBID_CHAR_VALID_B; + sPubidValidity[';'] = PUBID_CHAR_VALID_B; + sPubidValidity['!'] = PUBID_CHAR_VALID_B; + sPubidValidity['*'] = PUBID_CHAR_VALID_B; + sPubidValidity['#'] = PUBID_CHAR_VALID_B; + sPubidValidity['@'] = PUBID_CHAR_VALID_B; + sPubidValidity['$'] = PUBID_CHAR_VALID_B; + sPubidValidity['_'] = PUBID_CHAR_VALID_B; + sPubidValidity['%'] = PUBID_CHAR_VALID_B; + } + + /* + /////////////////////////////////////////////////////////////////////// + // Basic configuration + /////////////////////////////////////////////////////////////////////// + */ + + /** + * Copy of the configuration object passed by the factory. + * Contains immutable settings for this reader (or in case + * of DTD parsers, reader that uses it) + */ + protected final ReaderConfig mConfig; + + // // // Various extracted settings: + + /** + * If true, Reader is namespace aware, and should do basic checks + * (usually enforcing limitations on having colons in names) + */ + protected final boolean mCfgNsEnabled; + + // Extracted standard on/off settings: + + /** + * note: left non-final on purpose: sub-class may need to modify + * the default value after construction. + */ + protected boolean mCfgReplaceEntities; + + /* + /////////////////////////////////////////////////////////////////////// + // Symbol handling, if applicable + /////////////////////////////////////////////////////////////////////// + */ + + final SymbolTable mSymbols; + + /** + * Local full name for the event, if it has one (note: element events + * do NOT use this variable; those names are stored in element stack): + * target for processing instructions. + *

+ * Currently used for proc. instr. target, and entity name (at least + * when current entity reference is null). + *

+ * Note: this variable is generally not cleared, since it comes from + * a symbol table, ie. this won't be the only reference. + */ + protected String mCurrName; + + /* + /////////////////////////////////////////////////////////////////////// + // Input handling + /////////////////////////////////////////////////////////////////////// + */ + + /** + * Currently active input source; contains link to parent (nesting) input + * sources, if any. + */ + protected WstxInputSource mInput; + + /** + * Top-most input source this reader can use; due to input source + * chaining, this is not necessarily the root of all input; for example, + * external DTD subset reader's root input still has original document + * input as its parent. + */ + protected final WstxInputSource mRootInput; + + /** + * Custom resolver used to handle external entities that are to be expanded + * by this reader (external param/general entity expander) + */ + protected XMLResolver mEntityResolver = null; + + /** + * This is the current depth of the input stack (same as what input + * element stack would return as its depth). + * It is used to enforce input scope constraints for nesting of + * elements (for xml reader) and dtd declaration (for dtd reader) + * with regards to input block (entity expansion) boundaries. + *

+ * Basically this value is compared to {@link #mInputTopDepth}, which + * indicates what was the depth at the point where the currently active + * input scope/block was started. + */ + protected int mCurrDepth; + + protected int mInputTopDepth; + + /** + * Number of times a parsed general entity has been expanded; used for + * (optionally) limiting number of expansion to guard against + * denial-of-service attacks like "Billion Laughs". + * + * @since 4.3 + */ + protected int mEntityExpansionCount; + + /** + * Flag that indicates whether linefeeds in the input data are to + * be normalized or not. + * Xml specs mandate that the line feeds are only normalized + * when they are from the external entities (main doc, external + * general/parsed entities), so normalization has to be + * suppressed when expanding internal general/parsed entities. + */ + protected boolean mNormalizeLFs; + + /* + /////////////////////////////////////////////////////////////////////// + // Buffer(s) for local name(s) and text content + /////////////////////////////////////////////////////////////////////// + */ + + /** + * Temporary buffer used if local name can not be just directly + * constructed from input buffer (name is on a boundary or such). + */ + protected char[] mNameBuffer = null; + + /* + /////////////////////////////////////////////////////////////////////// + // Information about starting location of event + // Reader is pointing to; updated on-demand + /////////////////////////////////////////////////////////////////////// + */ + + // // // Location info at point when current token was started + + /** + * Total number of characters read before start of current token. + * For big (gigabyte-sized) sizes are possible, needs to be long, + * unlike pointers and sizes related to in-memory buffers. + */ + protected long mTokenInputTotal = 0; + + /** + * Input row on which current token starts, 1-based + */ + protected int mTokenInputRow = 1; + + /** + * Column on input row that current token starts; 0-based (although + * in the end it'll be converted to 1-based) + */ + protected int mTokenInputCol = 0; + + /* + /////////////////////////////////////////////////////////////////////// + // XML document information (from doc decl if one was found) common to + // all entities (main xml document, external DTD subset) + /////////////////////////////////////////////////////////////////////// + */ + + /** + * Input stream encoding, if known (passed in, or determined by + * auto-detection); null if not. + */ + protected String mDocInputEncoding = null; + + /** + * Character encoding from xml declaration, if any; null if no + * declaration, or it didn't specify encoding. + */ + protected String mDocXmlEncoding = null; + + /** + * XML version as declared by the document; one of constants + * from {@link XmlConsts} (like {@link XmlConsts#XML_V_10}). + */ + protected int mDocXmlVersion = XmlConsts.XML_V_UNKNOWN; + + /** + * Cache of internal character entities; + */ + protected Map mCachedEntities; + + /** + * Flag for whether or not character references should be treated as entities + */ + protected boolean mCfgTreatCharRefsAsEntities; + + /** + * Entity reference stream currently points to. + */ + protected EntityDecl mCurrEntity; + + /* + /////////////////////////////////////////////////////////////////////// + // Life-cycle + /////////////////////////////////////////////////////////////////////// + */ + + /** + * Constructor used when creating a complete new (main-level) reader that + * does not share its input buffers or state with another reader. + */ + protected StreamScanner(WstxInputSource input, ReaderConfig cfg, + XMLResolver res) + { + super(); + mInput = input; + // 17-Jun-2004, TSa: Need to know root-level input source + mRootInput = input; + + mConfig = cfg; + mSymbols = cfg.getSymbols(); + int cf = cfg.getConfigFlags(); + mCfgNsEnabled = (cf & CFG_NAMESPACE_AWARE) != 0; + mCfgReplaceEntities = (cf & CFG_REPLACE_ENTITY_REFS) != 0; + + mNormalizeLFs = mConfig.willNormalizeLFs(); + mInputBuffer = null; + mInputPtr = mInputEnd = 0; + mEntityResolver = res; + + mCfgTreatCharRefsAsEntities = mConfig.willTreatCharRefsAsEnts(); + if (mCfgTreatCharRefsAsEntities) { + mCachedEntities = new HashMap(); + } else { + mCachedEntities = Collections.emptyMap(); + } + } + + /* + /////////////////////////////////////////////////////////////////////// + // Package API + /////////////////////////////////////////////////////////////////////// + */ + + /** + * Method that returns location of the last character returned by this + * reader; that is, location "one less" than the currently pointed to + * location. + */ + protected WstxInputLocation getLastCharLocation() + { + return mInput.getLocation(mCurrInputProcessed + mInputPtr - 1, + mCurrInputRow, mInputPtr - mCurrInputRowStart); + } + + protected URL getSource() throws IOException { + return mInput.getSource(); + } + + protected String getSystemId() { + return mInput.getSystemId(); + } + + /* + /////////////////////////////////////////////////////////////////////// + // Partial `LocationInfo` implementation (not implemented + // by this base class, but is by some sub-classes) + /////////////////////////////////////////////////////////////////////// + */ + + /** + * Returns location of last properly parsed token; as per StAX specs, + * apparently needs to be the end of current event, which is the same + * as the start of the following event (or EOF if that's next). + */ + @Override + public abstract Location getLocation(); + + public XMLStreamLocation2 getStartLocation() + { + // note: +1 is used as columns are 1-based... + return mInput.getLocation(mTokenInputTotal, + mTokenInputRow, mTokenInputCol + 1); + } + + public XMLStreamLocation2 getCurrentLocation() + { + return mInput.getLocation(mCurrInputProcessed + mInputPtr, + mCurrInputRow, mInputPtr - mCurrInputRowStart + 1); + } + + /* + /////////////////////////////////////////////////////////////////////// + // InputProblemReporter implementation + /////////////////////////////////////////////////////////////////////// + */ + + public WstxException throwWfcException(String msg, boolean deferErrors) + throws WstxException + { + WstxException ex = constructWfcException(msg); + if (!deferErrors) { + throw ex; + } + return ex; + } + + @Override + public void throwParseError(String msg) throws XMLStreamException { + throwParseError(msg, null, null); + } + + /** + * Throws generic parse error with specified message and current parsing + * location. + *

+ * Note: public access only because core code in other packages needs + * to access it. + */ + @Override + public void throwParseError(String format, Object arg, Object arg2) + throws XMLStreamException + { + String msg = (arg != null || arg2 != null) ? + MessageFormat.format(format, new Object[] { arg, arg2 }) : format; + throw constructWfcException(msg); + } + + public void reportProblem(String probType, String format, Object arg, Object arg2) + throws XMLStreamException + { + XMLReporter rep = mConfig.getXMLReporter(); + if (rep != null) { + _reportProblem(rep, probType, + MessageFormat.format(format, new Object[] { arg, arg2 }), null); + } + } + + @Override + public void reportProblem(Location loc, String probType, + String format, Object arg, Object arg2) + throws XMLStreamException + { + XMLReporter rep = mConfig.getXMLReporter(); + if (rep != null) { + String msg = (arg != null || arg2 != null) ? + MessageFormat.format(format, new Object[] { arg, arg2 }) : format; + _reportProblem(rep, probType, msg, loc); + } + } + + protected void _reportProblem(XMLReporter rep, String probType, String msg, Location loc) + throws XMLStreamException + { + if (loc == null) { + loc = getLastCharLocation(); + } + _reportProblem(rep, new XMLValidationProblem(loc, msg, XMLValidationProblem.SEVERITY_ERROR, probType)); + } + + protected void _reportProblem(XMLReporter rep, XMLValidationProblem prob) + throws XMLStreamException + { + if (rep != null) { + Location loc = prob.getLocation(); + if (loc == null) { + loc = getLastCharLocation(); + prob.setLocation(loc); + } + // Backwards-compatibility fix: add non-null type, if missing: + if (prob.getType() == null) { + prob.setType(ErrorConsts.WT_VALIDATION); + } + // [WSTX-154]: was catching and dropping thrown exception: shouldn't. + // [WTSX-157]: need to support XMLReporter2 + if (rep instanceof XMLReporter2) { + ((XMLReporter2) rep).report(prob); + } else { + rep.report(prob.getMessage(), prob.getType(), prob, loc); + } + } + } + + /** + *

+ * Note: this is the base implementation used for implementing + * ValidationContext + */ + @Override + public void reportValidationProblem(XMLValidationProblem prob) + throws XMLStreamException + { + // !!! TBI: Fail-fast vs. deferred modes? + /* For now let's implement basic functionality: warnings get + * reported via XMLReporter, errors and fatal errors result in + * immediate exceptions. + */ + /* 27-May-2008, TSa: [WSTX-153] Above is incorrect: as per Stax + * javadocs for XMLReporter, both warnings and non-fatal errors + * (which includes all validation errors) should be reported via + * XMLReporter interface, and only fatals should cause an + * immediate stream exception (by-passing reporter) + */ + if (prob.getSeverity() > XMLValidationProblem.SEVERITY_ERROR) { + throw WstxValidationException.create(prob); + } + XMLReporter rep = mConfig.getXMLReporter(); + if (rep != null) { + _reportProblem(rep, prob); + } else { + /* If no reporter, regular non-fatal errors are to be reported + * as exceptions as well, for backwards compatibility + */ + if (prob.getSeverity() >= XMLValidationProblem.SEVERITY_ERROR) { + throw WstxValidationException.create(prob); + } + } + } + + public void reportValidationProblem(String msg, int severity) + throws XMLStreamException + { + reportValidationProblem(new XMLValidationProblem(getLastCharLocation(), + msg, severity)); + } + + @Override + public void reportValidationProblem(String msg) + throws XMLStreamException + { + reportValidationProblem(new XMLValidationProblem(getLastCharLocation(), msg, + XMLValidationProblem.SEVERITY_ERROR)); + } + + public void reportValidationProblem(Location loc, String msg) + throws XMLStreamException + { + reportValidationProblem(new XMLValidationProblem(loc, msg)); + } + + @Override + public void reportValidationProblem(String format, Object arg, Object arg2) + throws XMLStreamException + { + reportValidationProblem(MessageFormat.format(format, new Object[] { arg, arg2 })); + } + + /* + /////////////////////////////////////////////////////////////////////// + // Other error reporting methods + /////////////////////////////////////////////////////////////////////// + */ + + protected WstxException constructWfcException(String msg) + { + return new WstxParsingException(msg, getLastCharLocation()); + } + + /** + * Construct and return a {@link XMLStreamException} to throw + * as a result of a failed Typed Access operation (but one not + * caused by a Well-Formedness Constraint or Validation Constraint + * problem) + */ + /* + protected WstxException _constructTypeException(String msg) + { + // Hmmh. Should there be a distinct sub-type? + return new WstxParsingException(msg, getLastCharLocation()); + } + */ + + protected WstxException constructFromIOE(IOException ioe) + { + return new WstxIOException(ioe); + } + + protected WstxException constructNullCharException() + { + return new WstxUnexpectedCharException("Illegal character (NULL, unicode 0) encountered: not valid in any content", + getLastCharLocation(), CHAR_NULL); + } + + protected void throwUnexpectedChar(int i, String msg) throws WstxException + { + char c = (char) i; + String excMsg = "Unexpected character "+getCharDesc(c)+msg; + throw new WstxUnexpectedCharException(excMsg, getLastCharLocation(), c); + } + + protected void throwNullChar() throws WstxException { + throw constructNullCharException(); + } + + protected void throwInvalidSpace(int i) throws WstxException { + throwInvalidSpace(i, false); + } + + protected WstxException throwInvalidSpace(int i, boolean deferErrors) + throws WstxException + { + char c = (char) i; + WstxException ex; + if (c == CHAR_NULL) { + ex = constructNullCharException(); + } else { + String msg = "Illegal character ("+getCharDesc(c)+")"; + if (mXml11) { + msg += " [note: in XML 1.1, it could be included via entity expansion]"; + } + ex = new WstxUnexpectedCharException(msg, getLastCharLocation(), c); + } + if (!deferErrors) { + throw ex; + } + return ex; + } + + protected void throwUnexpectedEOF(String msg) + throws WstxException + { + throw new WstxEOFException("Unexpected EOF"+(msg == null ? "" : msg), + getLastCharLocation()); + } + + /** + * Similar to {@link #throwUnexpectedEOF}, but only indicates ending + * of an input block. Used when reading a token that can not span + * input block boundaries (ie. can not continue past end of an + * entity expansion). + */ + protected void throwUnexpectedEOB(String msg) + throws WstxException + { + throw new WstxEOFException("Unexpected end of input block"+(msg == null ? "" : msg), + getLastCharLocation()); + } + + protected void throwFromIOE(IOException ioe) throws WstxException { + throw new WstxIOException(ioe); + } + + protected void throwFromStrE(XMLStreamException strex) + throws WstxException + { + if (strex instanceof WstxException) { + throw (WstxException) strex; + } + throw new WstxException(strex); + } + + /** + * Method called to report an error, when caller's signature only + * allows runtime exceptions to be thrown. + */ + protected void throwLazyError(Exception e) + { + if (e instanceof XMLStreamException) { + WstxLazyException.throwLazily((XMLStreamException) e); + } + ExceptionUtil.throwRuntimeException(e); + } + + protected String tokenTypeDesc(int type) { + return ErrorConsts.tokenTypeDesc(type); + } + + /* + /////////////////////////////////////////////////////////////////////// + // Input buffer handling + /////////////////////////////////////////////////////////////////////// + */ + + /** + * Returns current input source this source uses. + *

+ * Note: public only because some implementations are on different + * package. + */ + public final WstxInputSource getCurrentInput() { + return mInput; + } + + protected final int inputInBuffer() { + return mInputEnd - mInputPtr; + } + + @SuppressWarnings("cast") + protected final int getNext() throws XMLStreamException + { + if (mInputPtr >= mInputEnd) { + if (!loadMore()) { + return -1; + } + } + return (int) mInputBuffer[mInputPtr++]; + } + + /** + * Similar to {@link #getNext}, but does not advance pointer + * in input buffer. + *

+ * Note: this method only peeks within current input source; + * it does not close it and check nested input source (if any). + * This is necessary when checking keywords, since they can never + * cross input block boundary. + */ + @SuppressWarnings("cast") + protected final int peekNext() + throws XMLStreamException + { + if (mInputPtr >= mInputEnd) { + if (!loadMoreFromCurrent()) { + return -1; + } + } + return (int) mInputBuffer[mInputPtr]; + } + + protected final char getNextChar(String errorMsg) + throws XMLStreamException + { + if (mInputPtr >= mInputEnd) { + loadMore(errorMsg); + } + return mInputBuffer[mInputPtr++]; + } + + /** + * Similar to {@link #getNextChar}, but will not read more characters + * from parent input source(s) if the current input source doesn't + * have more content. This is often needed to prevent "runaway" content, + * such as comments that start in an entity but do not have matching + * close marker inside entity; XML specification specifically states + * such markup is not legal. + */ + protected final char getNextCharFromCurrent(String errorMsg) + throws XMLStreamException + { + if (mInputPtr >= mInputEnd) { + loadMoreFromCurrent(errorMsg); + } + return mInputBuffer[mInputPtr++]; + } + + /** + * Method that will skip through zero or more white space characters, + * and return either the character following white space, or -1 to + * indicate EOF (end of the outermost input source)/ + */ + @SuppressWarnings("cast") + protected final int getNextAfterWS() + throws XMLStreamException + { + if (mInputPtr >= mInputEnd) { + if (!loadMore()) { + return -1; + } + } + char c = mInputBuffer[mInputPtr++]; + while (c <= CHAR_SPACE) { + // Linefeed? + if (c == '\n' || c == '\r') { + skipCRLF(c); + } else if (c != CHAR_SPACE && c != '\t') { + throwInvalidSpace(c); + } + // Still a white space? + if (mInputPtr >= mInputEnd) { + if (!loadMore()) { + return -1; + } + } + c = mInputBuffer[mInputPtr++]; + } + return (int) c; + } + + protected final char getNextCharAfterWS(String errorMsg) + throws XMLStreamException + { + if (mInputPtr >= mInputEnd) { + loadMore(errorMsg); + } + + char c = mInputBuffer[mInputPtr++]; + while (c <= CHAR_SPACE) { + // Linefeed? + if (c == '\n' || c == '\r') { + skipCRLF(c); + } else if (c != CHAR_SPACE && c != '\t') { + throwInvalidSpace(c); + } + + // Still a white space? + if (mInputPtr >= mInputEnd) { + loadMore(errorMsg); + } + c = mInputBuffer[mInputPtr++]; + } + return c; + } + + protected final char getNextInCurrAfterWS(String errorMsg) + throws XMLStreamException + { + return getNextInCurrAfterWS(errorMsg, getNextCharFromCurrent(errorMsg)); + } + + protected final char getNextInCurrAfterWS(String errorMsg, char c) + throws XMLStreamException + { + while (c <= CHAR_SPACE) { + // Linefeed? + if (c == '\n' || c == '\r') { + skipCRLF(c); + } else if (c != CHAR_SPACE && c != '\t') { + throwInvalidSpace(c); + } + + // Still a white space? + if (mInputPtr >= mInputEnd) { + loadMoreFromCurrent(errorMsg); + } + c = mInputBuffer[mInputPtr++]; + } + return c; + } + + /** + * Method called when a CR has been spotted in input; checks if next + * char is LF, and if so, skips it. Note that next character has to + * come from the current input source, to qualify; it can never come + * from another (nested) input source. + * + * @return True, if passed in char is '\r' and next one is '\n'. + */ + protected final boolean skipCRLF(char c) + throws XMLStreamException + { + boolean result; + + if (c == '\r' && peekNext() == '\n') { + ++mInputPtr; + result = true; + } else { + result = false; + } + ++mCurrInputRow; + mCurrInputRowStart = mInputPtr; + return result; + } + + protected final void markLF() { + ++mCurrInputRow; + mCurrInputRowStart = mInputPtr; + } + + protected final void markLF(int inputPtr) { + ++mCurrInputRow; + mCurrInputRowStart = inputPtr; + } + + /** + * Method to push back last character read; can only be called once, + * that is, no more than one char can be guaranteed to be succesfully + * returned. + */ + protected final void pushback() { --mInputPtr; } + + /* + /////////////////////////////////////////////////////////////////////// + // Sub-class overridable input handling methods + /////////////////////////////////////////////////////////////////////// + */ + + /** + * Method called when an entity has been expanded (new input source + * has been created). Needs to initialize location information and change + * active input source. + * + * @param entityId Name of the entity being expanded + */ + protected void initInputSource(WstxInputSource newInput, boolean isExt, + String entityId) + throws XMLStreamException + { + // Let's make sure new input will be read next time input is needed: + mInputPtr = 0; + mInputEnd = 0; + /* Plus, reset the input location so that'll be accurate for + * error reporting etc. + */ + mInputTopDepth = mCurrDepth; + + // [WSTX-296]: Check for entity expansion depth against configurable limit + int entityDepth = mInput.getEntityDepth() + 1; + verifyLimit("Maximum entity expansion depth", mConfig.getMaxEntityDepth(), entityDepth); + mInput = newInput; + mInput.initInputLocation(this, mCurrDepth, entityDepth); + + /* 21-Feb-2006, TSa: Linefeeds are NOT normalized when expanding + * internal entities (XML, 2.11) + */ + if (isExt) { + mNormalizeLFs = true; + } else { + mNormalizeLFs = false; + } + } + + /** + * Method that will try to read one or more characters from currently + * open input sources; closing input sources if necessary. + * + * @return true if reading succeeded (or may succeed), false if + * we reached EOF. + */ + protected boolean loadMore() + throws XMLStreamException + { + WstxInputSource input = mInput; + do { + /* Need to make sure offsets are properly updated for error + * reporting purposes, and do this now while previous amounts + * are still known. + */ + mCurrInputProcessed += mInputEnd; + verifyLimit("Maximum document characters", mConfig.getMaxCharacters(), mCurrInputProcessed); + mCurrInputRowStart -= mInputEnd; + int count; + try { + count = input.readInto(this); + if (count > 0) { + return true; + } + input.close(); + } catch (IOException ioe) { + throw constructFromIOE(ioe); + } + if (input == mRootInput) { + /* Note: no need to check entity/input nesting in this + * particular case, since it will be handled by higher level + * parsing code (results in an unexpected EOF) + */ + return false; + } + WstxInputSource parent = input.getParent(); + if (parent == null) { // sanity check! + throwNullParent(input); + } + /* 13-Feb-2006, TSa: Ok, do we violate a proper nesting constraints + * with this input block closure? + */ + if (mCurrDepth != input.getScopeId()) { + handleIncompleteEntityProblem(input); + } + + mInput = input = parent; + input.restoreContext(this); + mInputTopDepth = input.getScopeId(); + /* 21-Feb-2006, TSa: Since linefeed normalization needs to be + * suppressed for internal entity expansion, we may need to + * change the state... + */ + if (!mNormalizeLFs) { + mNormalizeLFs = !input.fromInternalEntity(); + } + // Maybe there are leftovers from that input in buffer now? + } while (mInputPtr >= mInputEnd); + + return true; + } + + protected final boolean loadMore(String errorMsg) + throws XMLStreamException + { + if (!loadMore()) { + throwUnexpectedEOF(errorMsg); + } + return true; + } + + protected boolean loadMoreFromCurrent() + throws XMLStreamException + { + // Need to update offsets properly + mCurrInputProcessed += mInputEnd; + mCurrInputRowStart -= mInputEnd; + verifyLimit("Maximum document characters", mConfig.getMaxCharacters(), mCurrInputProcessed); + try { + int count = mInput.readInto(this); + return (count > 0); + } catch (IOException ie) { + throw constructFromIOE(ie); + } + } + + protected final boolean loadMoreFromCurrent(String errorMsg) + throws XMLStreamException + { + if (!loadMoreFromCurrent()) { + throwUnexpectedEOB(errorMsg); + } + return true; + } + + /** + * Method called to make sure current main-level input buffer has at + * least specified number of characters available consequtively, + * without having to call {@link #loadMore}. It can only be called + * when input comes from main-level buffer; further, call can shift + * content in input buffer, so caller has to flush any data still + * pending. In short, caller has to know exactly what it's doing. :-) + *

+ * Note: method does not check for any other input sources than the + * current one -- if current source can not fulfill the request, a + * failure is indicated. + * + * @return true if there's now enough data; false if not (EOF) + */ + protected boolean ensureInput(int minAmount) + throws XMLStreamException + { + int currAmount = mInputEnd - mInputPtr; + if (currAmount >= minAmount) { + return true; + } + try { + return mInput.readMore(this, minAmount); + } catch (IOException ie) { + throw constructFromIOE(ie); + } + } + + protected void closeAllInput(boolean force) + throws XMLStreamException + { + WstxInputSource input = mInput; + while (true) { + try { + if (force) { + input.closeCompletely(); + } else { + input.close(); + } + } catch (IOException ie) { + throw constructFromIOE(ie); + } + if (input == mRootInput) { + break; + } + WstxInputSource parent = input.getParent(); + if (parent == null) { // sanity check! + throwNullParent(input); + } + mInput = input = parent; + } + } + + /** + * @param curr Input source currently in use + */ + protected void throwNullParent(WstxInputSource curr) + { + throw new IllegalStateException(ErrorConsts.ERR_INTERNAL); + //throw new IllegalStateException("Internal error: null parent for input source '"+curr+"'; should never occur (should have stopped at root input '"+mRootInput+"')."); + } + + /* + /////////////////////////////////////////////////////////////////////// + // Entity resolution + /////////////////////////////////////////////////////////////////////// + */ + + /** + * Method that tries to resolve a character entity, or (if caller so + * specifies), a pre-defined internal entity (lt, gt, amp, apos, quot). + * It will succeed iff: + *

    + *
  1. Entity in question is a simple character entity (either one of + * 5 pre-defined ones, or using decimal/hex notation), AND + *
  2. + *
  3. Entity fits completely inside current input buffer. + *
  4. + *
+ * If so, character value of entity is returned. Character 0 is returned + * otherwise; if so, caller needs to do full resolution. + *

+ * Note: On entry we are guaranteed there are at least 3 more characters + * in this buffer; otherwise we shouldn't be called. + * + * @param checkStd If true, will check pre-defined internal entities + * (gt, lt, amp, apos, quot); if false, will only check actual + * character entities. + * + * @return (Valid) character value, if entity is a character reference, + * and could be resolved from current input buffer (does not span + * buffer boundary); null char (code 0) if not (either non-char + * entity, or spans input buffer boundary). + */ + protected int resolveSimpleEntity(boolean checkStd) + throws XMLStreamException + { + char[] buf = mInputBuffer; + int ptr = mInputPtr; + char c = buf[ptr++]; + + // Numeric reference? + if (c == '#') { + c = buf[ptr++]; + int value = 0; + int inputLen = mInputEnd; + if (c == 'x') { // hex + while (ptr < inputLen) { + c = buf[ptr++]; + if (c == ';') { + break; + } + value = value << 4; + if (c <= '9' && c >= '0') { + value += (c - '0'); + } else if (c >= 'a' && c <= 'f') { + value += (10 + (c - 'a')); + } else if (c >= 'A' && c <= 'F') { + value += (10 + (c - 'A')); + } else { + mInputPtr = ptr; // so error points to correct char + throwUnexpectedChar(c, "; expected a hex digit (0-9a-fA-F)."); + } + /* Need to check for overflow; easiest to do right as + * it happens... + */ + if (value > MAX_UNICODE_CHAR) { + reportUnicodeOverflow(); + } + } + } else { // numeric (decimal) + while (c != ';') { + if (c <= '9' && c >= '0') { + value = (value * 10) + (c - '0'); + // Overflow? + if (value > MAX_UNICODE_CHAR) { + reportUnicodeOverflow(); + } + } else { + mInputPtr = ptr; // so error points to correct char + throwUnexpectedChar(c, "; expected a decimal number."); + } + if (ptr >= inputLen) { + break; + } + c = buf[ptr++]; + } + } + /* We get here either if we got it all, OR if we ran out of + * input in current buffer. + */ + if (c == ';') { // got the full thing + mInputPtr = ptr; + validateChar(value); + return value; + } + + /* If we ran out of input, need to just fall back, gets + * resolved via 'full' resolution mechanism. + */ + } else if (checkStd) { + /* Caller may not want to resolve these quite yet... + * (when it wants separate events for non-char entities) + */ + if (c == 'a') { // amp or apos? + c = buf[ptr++]; + + if (c == 'm') { // amp? + if (buf[ptr++] == 'p') { + if (ptr < mInputEnd && buf[ptr++] == ';') { + mInputPtr = ptr; + return '&'; + } + } + } else if (c == 'p') { // apos? + if (buf[ptr++] == 'o') { + int len = mInputEnd; + if (ptr < len && buf[ptr++] == 's') { + if (ptr < len && buf[ptr++] == ';') { + mInputPtr = ptr; + return '\''; + } + } + } + } + } else if (c == 'g') { // gt? + if (buf[ptr++] == 't' && buf[ptr++] == ';') { + mInputPtr = ptr; + return '>'; + } + } else if (c == 'l') { // lt? + if (buf[ptr++] == 't' && buf[ptr++] == ';') { + mInputPtr = ptr; + return '<'; + } + } else if (c == 'q') { // quot? + if (buf[ptr++] == 'u' && buf[ptr++] == 'o') { + int len = mInputEnd; + if (ptr < len && buf[ptr++] == 't') { + if (ptr < len && buf[ptr++] == ';') { + mInputPtr = ptr; + return '"'; + } + } + } + } + } + return 0; + } + + /** + * Method called to resolve character entities, and only character + * entities (except that pre-defined char entities -- amp, apos, lt, + * gt, quote -- MAY be "char entities" in this sense, depending on + * arguments). + * Otherwise it is to return the null char; if so, + * the input pointer will point to the same point as when method + * entered (char after ampersand), plus the ampersand itself is + * guaranteed to be in the input buffer (so caller can just push it + * back if necessary). + *

+ * Most often this method is called when reader is not to expand + * non-char entities automatically, but to return them as separate + * events. + *

+ * Main complication here is that we need to do 5-char lookahead. This + * is problematic if chars are on input buffer boundary. This is ok + * for the root level input buffer, but not for some nested buffers. + * However, according to XML specs, such split entities are actually + * illegal... so we can throw an exception in those cases. + * + * @param checkStd If true, will check pre-defined internal entities + * (gt, lt, amp, apos, quot) as character entities; if false, will only + * check actual 'real' character entities. + * + * @return (Valid) character value, if entity is a character reference, + * and could be resolved from current input buffer (does not span + * buffer boundary); null char (code 0) if not (either non-char + * entity, or spans input buffer boundary). + */ + protected int resolveCharOnlyEntity(boolean checkStd) + throws XMLStreamException + { + //int avail = inputInBuffer(); + int avail = mInputEnd - mInputPtr; + if (avail < 6) { + // split entity, or buffer boundary + /* Don't want to lose leading '&' (in case we can not expand + * the entity), so let's push it back first + */ + --mInputPtr; + /* Shortest valid reference would be 3 chars ('&a;'); which + * would only be legal from an expanded entity... + */ + if (!ensureInput(6)) { + avail = inputInBuffer(); + if (avail < 3) { + throwUnexpectedEOF(SUFFIX_IN_ENTITY_REF); + } + } else { + avail = 6; + } + // ... and now we can move pointer back as well: + ++mInputPtr; + } + + /* Ok, now we have one more character to check, and that's enough + * to determine type decisively. + */ + char c = mInputBuffer[mInputPtr]; + + // A char reference? + if (c == '#') { // yup + ++mInputPtr; + return resolveCharEnt(null); + } + + // nope... except may be a pre-def? + if (checkStd) { + if (c == 'a') { + char d = mInputBuffer[mInputPtr+1]; + if (d == 'm') { + if (avail >= 4 + && mInputBuffer[mInputPtr+2] == 'p' + && mInputBuffer[mInputPtr+3] == ';') { + mInputPtr += 4; + return '&'; + } + } else if (d == 'p') { + if (avail >= 5 + && mInputBuffer[mInputPtr+2] == 'o' + && mInputBuffer[mInputPtr+3] == 's' + && mInputBuffer[mInputPtr+4] == ';') { + mInputPtr += 5; + return '\''; + } + } + } else if (c == 'l') { + if (avail >= 3 + && mInputBuffer[mInputPtr+1] == 't' + && mInputBuffer[mInputPtr+2] == ';') { + mInputPtr += 3; + return '<'; + } + } else if (c == 'g') { + if (avail >= 3 + && mInputBuffer[mInputPtr+1] == 't' + && mInputBuffer[mInputPtr+2] == ';') { + mInputPtr += 3; + return '>'; + } + } else if (c == 'q') { + if (avail >= 5 + && mInputBuffer[mInputPtr+1] == 'u' + && mInputBuffer[mInputPtr+2] == 'o' + && mInputBuffer[mInputPtr+3] == 't' + && mInputBuffer[mInputPtr+4] == ';') { + mInputPtr += 5; + return '"'; + } + } + } + return 0; + } + + /** + * Reverse of {@link #resolveCharOnlyEntity}; will only resolve entity + * if it is NOT a character entity (or pre-defined 'generic' entity; + * amp, apos, lt, gt or quot). Only used in cases where entities + * are to be separately returned unexpanded (in non-entity-replacing + * mode); which means it's never called from dtd handler. + */ + protected EntityDecl resolveNonCharEntity() + throws XMLStreamException + { + //int avail = inputInBuffer(); + int avail = mInputEnd - mInputPtr; + if (avail < 6) { + // split entity, or buffer boundary + /* Don't want to lose leading '&' (in case we can not expand + * the entity), so let's push it back first + */ + --mInputPtr; + + /* Shortest valid reference would be 3 chars ('&a;'); which + * would only be legal from an expanded entity... + */ + if (!ensureInput(6)) { + avail = inputInBuffer(); + if (avail < 3) { + throwUnexpectedEOF(SUFFIX_IN_ENTITY_REF); + } + } else { + avail = 6; + } + // ... and now we can move pointer back as well: + ++mInputPtr; + } + + // We don't care about char entities: + char c = mInputBuffer[mInputPtr]; + if (c == '#') { + return null; + } + + /* 19-Aug-2004, TSa: Need special handling for pre-defined + * entities; they are not counted as 'real' general parsed + * entities, but more as character entities... + */ + + // have chars at least up to mInputPtr+4 by now + if (c == 'a') { + char d = mInputBuffer[mInputPtr+1]; + if (d == 'm') { + if (avail >= 4 + && mInputBuffer[mInputPtr+2] == 'p' + && mInputBuffer[mInputPtr+3] == ';') { + // If not automatically expanding: + //return sEntityAmp; + // mInputPtr += 4; + return null; + } + } else if (d == 'p') { + if (avail >= 5 + && mInputBuffer[mInputPtr+2] == 'o' + && mInputBuffer[mInputPtr+3] == 's' + && mInputBuffer[mInputPtr+4] == ';') { + return null; + } + } + } else if (c == 'l') { + if (avail >= 3 + && mInputBuffer[mInputPtr+1] == 't' + && mInputBuffer[mInputPtr+2] == ';') { + return null; + } + } else if (c == 'g') { + if (avail >= 3 + && mInputBuffer[mInputPtr+1] == 't' + && mInputBuffer[mInputPtr+2] == ';') { + return null; + } + } else if (c == 'q') { + if (avail >= 5 + && mInputBuffer[mInputPtr+1] == 'u' + && mInputBuffer[mInputPtr+2] == 'o' + && mInputBuffer[mInputPtr+3] == 't' + && mInputBuffer[mInputPtr+4] == ';') { + return null; + } + } + + // Otherwise, let's just parse in generic way: + ++mInputPtr; // since we already read the first letter + String id = parseEntityName(c); + mCurrName = id; + + return findEntity(id, null); + } + + /** + * Method that does full resolution of an entity reference, be it + * character entity, internal entity or external entity, including + * updating of input buffers, and depending on whether result is + * a character entity (or one of 5 pre-defined entities), returns + * char in question, or null character (code 0) to indicate it had + * to change input source. + * + * @param allowExt If true, is allowed to expand external entities + * (expanding text); if false, is not (expanding attribute value). + * + * @return Either single-character replacement (which is NOT to be + * reparsed), or null char (0) to indicate expansion is done via + * input source. + */ + protected int fullyResolveEntity(boolean allowExt) + throws XMLStreamException + { + char c = getNextCharFromCurrent(SUFFIX_IN_ENTITY_REF); + // Do we have a (numeric) character entity reference? + if (c == '#') { // numeric + final StringBuffer originalSurface = new StringBuffer("#"); + int ch = resolveCharEnt(originalSurface); + if (mCfgTreatCharRefsAsEntities) { + final char[] originalChars = new char[originalSurface.length()]; + originalSurface.getChars(0, originalSurface.length(), originalChars, 0); + mCurrEntity = getIntEntity(ch, originalChars); + return 0; + } + return ch; + } + + String id = parseEntityName(c); + + // Perhaps we have a pre-defined char reference? + c = id.charAt(0); + /* + * 16-May-2004, TSa: Should custom entities (or ones defined in int/ext subset) override + * pre-defined settings for these? + */ + char d = CHAR_NULL; + if (c == 'a') { // amp or apos? + if (id.equals("amp")) { + d = '&'; + } else if (id.equals("apos")) { + d = '\''; + } + } else if (c == 'g') { // gt? + if (id.length() == 2 && id.charAt(1) == 't') { + d = '>'; + } + } else if (c == 'l') { // lt? + if (id.length() == 2 && id.charAt(1) == 't') { + d = '<'; + } + } else if (c == 'q') { // quot? + if (id.equals("quot")) { + d = '"'; + } + } + + if (d != CHAR_NULL) { + if (mCfgTreatCharRefsAsEntities) { + final char[] originalChars = new char[id.length()]; + id.getChars(0, id.length(), originalChars, 0); + mCurrEntity = getIntEntity(d, originalChars); + return 0; + } + return d; + } + + final EntityDecl e = expandEntity(id, allowExt, null); + if (mCfgTreatCharRefsAsEntities) { + mCurrEntity = e; + } + return 0; + } + + /** + * Returns an entity (possibly from cache) for the argument character using the encoded + * representation in mInputBuffer[entityStartPos ... mInputPtr-1]. + */ + protected EntityDecl getIntEntity(int ch, final char[] originalChars) + { + String cacheKey = new String(originalChars); + + IntEntity entity = mCachedEntities.get(cacheKey); + if (entity == null) { + String repl; + if (ch <= 0xFFFF) { + repl = Character.toString((char) ch); + } else { + StringBuffer sb = new StringBuffer(2); + ch -= 0x10000; + sb.append((char) ((ch >> 10) + 0xD800)); + sb.append((char) ((ch & 0x3FF) + 0xDC00)); + repl = sb.toString(); + } + entity = IntEntity.create(new String(originalChars), repl); + mCachedEntities.put(cacheKey, entity); + } + return entity; + } + + + /** + * Helper method that will try to expand a parsed entity (parameter or + * generic entity). + *

+ * note: called by sub-classes (dtd parser), needs to be protected. + * + * @param id Name of the entity being expanded + * @param allowExt Whether external entities can be expanded or not; if + * not, and the entity to expand would be external one, an exception + * will be thrown + */ + protected EntityDecl expandEntity(String id, boolean allowExt, + Object extraArg) + throws XMLStreamException + { + mCurrName = id; + + EntityDecl ed = findEntity(id, extraArg); + + if (ed == null) { + /* 30-Sep-2005, TSa: As per [WSTX-5], let's only throw exception + * if we have to resolve it (otherwise it's just best-effort, + * and null is ok) + */ + /* 02-Oct-2005, TSa: Plus, [WSTX-4] adds "undeclared entity + * resolver" + */ + if (mCfgReplaceEntities) { + mCurrEntity = expandUnresolvedEntity(id); + } + return null; + } + + if (!mCfgTreatCharRefsAsEntities || this instanceof MinimalDTDReader) { + expandEntity(ed, allowExt); + } + + return ed; + } + + /** + *

+ * note: defined as private for documentation, ie. it's just called + * from within this class (not sub-classes), from one specific method + * (see above) + * + * @param ed Entity to be expanded + * @param allowExt Whether external entities are allowed or not. + */ + private void expandEntity(EntityDecl ed, boolean allowExt) + throws XMLStreamException + { + String id = ed.getName(); + + /* Very first thing; we can immediately check if expanding + * this entity would result in infinite recursion: + */ + if (mInput.isOrIsExpandedFrom(id)) { + throwRecursionError(id); + } + + /* Should not refer unparsed entities from attribute values + * or text content (except via notation mechanism, but that's + * not parsed here) + */ + if (!ed.isParsed()) { + throwParseError("Illegal reference to unparsed external entity \"{0}\"", id, null); + } + + // 28-Jun-2004, TSa: Do we support external entity expansion? + boolean isExt = ed.isExternal(); + if (isExt) { + if (!allowExt) { // never ok in attribute value... + throwParseError("Encountered a reference to external parsed entity \"{0}\" when expanding attribute value: not legal as per XML 1.0/1.1 #3.1", id, null); + } + if (!mConfig.willSupportExternalEntities()) { + throwParseError("Encountered a reference to external entity \"{0}\", but stream reader has feature \"{1}\" disabled", + id, XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES); + } + } + verifyLimit("Maximum entity expansion count", mConfig.getMaxEntityCount(), ++mEntityExpansionCount); + // First, let's give current context chance to save its stuff + WstxInputSource oldInput = mInput; + oldInput.saveContext(this); + WstxInputSource newInput = null; + try { + newInput = ed.expand(oldInput, mEntityResolver, mConfig, mDocXmlVersion); + } catch (FileNotFoundException fex) { + /* Let's catch and rethrow this just so we get more meaningful + * description (with input source position etc) + */ + throwParseError("(was {0}) {1}", fex.getClass().getName(), fex.getMessage()); + } catch (IOException ioe) { + throw constructFromIOE(ioe); + } + /* And then we'll need to make sure new input comes from the new + * input source + */ + initInputSource(newInput, isExt, id); + } + + /** + *

+ * note: only called from the local expandEntity() method + */ + private EntityDecl expandUnresolvedEntity(String id) + throws XMLStreamException + { + XMLResolver resolver = mConfig.getUndeclaredEntityResolver(); + if (resolver != null) { + /* Ok, we can check for recursion here; but let's only do that + * if there is any chance that it might get resolved by + * the special resolver (it must have been resolved this way + * earlier, too...) + */ + if (mInput.isOrIsExpandedFrom(id)) { + throwRecursionError(id); + } + + WstxInputSource oldInput = mInput; + oldInput.saveContext(this); + // null, null -> no public or system ids + int xmlVersion = mDocXmlVersion; + // 05-Feb-2006, TSa: If xmlVersion not explicitly known, defaults to 1.0 + if (xmlVersion == XmlConsts.XML_V_UNKNOWN) { + xmlVersion = XmlConsts.XML_V_10; + } + WstxInputSource newInput; + try { + newInput = DefaultInputResolver.resolveEntityUsing + (oldInput, id, null, null, resolver, mConfig, xmlVersion); + if (mCfgTreatCharRefsAsEntities) { + return new IntEntity(WstxInputLocation.getEmptyLocation(), newInput.getEntityId(), + newInput.getSource(), new char[]{}, WstxInputLocation.getEmptyLocation()); + } + } catch (IOException ioe) { + throw constructFromIOE(ioe); + } + if (newInput != null) { + // true -> is external + initInputSource(newInput, true, id); + return null; + } + } + handleUndeclaredEntity(id); + return null; + } + + /* + /////////////////////////////////////////////////////////////////////// + // Abstract methods for sub-classes to implement + /////////////////////////////////////////////////////////////////////// + */ + + /** + * Abstract method for sub-classes to implement, for finding + * a declared general or parsed entity. + * + * @param id Identifier of the entity to find + * @param arg Optional argument passed from caller; needed by DTD + * reader. + */ + protected abstract EntityDecl findEntity(String id, Object arg) + throws XMLStreamException; + + /** + * This method gets called if a declaration for an entity was not + * found in entity expanding mode (enabled by default for xml reader, + * always enabled for dtd reader). + */ + protected abstract void handleUndeclaredEntity(String id) + throws XMLStreamException; + + protected abstract void handleIncompleteEntityProblem(WstxInputSource closing) + throws XMLStreamException; + + /* + /////////////////////////////////////////////////////////////////////// + // Basic tokenization + /////////////////////////////////////////////////////////////////////// + */ + + /** + * Method that will parse name token (roughly equivalent to XML specs; + * although bit lenier for more efficient handling); either uri prefix, + * or local name. + *

+ * Much of complexity in this method has to do with the intention to + * try to avoid any character copies. In this optimal case algorithm + * would be fairly simple. However, this only works if all data is + * already in input buffer... if not, copy has to be made halfway + * through parsing, and that complicates things. + *

+ * One thing to note is that String returned has been canonicalized + * and (if necessary) added to symbol table. It can thus be compared + * against other such (usually id) Strings, with simple equality operator. + * + * @param c First character of the name; not yet checked for validity + * + * @return Canonicalized name String (which may have length 0, if + * EOF or non-name-start char encountered) + */ + protected String parseLocalName(char c) + throws XMLStreamException + { + /* Has to start with letter, or '_' (etc); we won't allow ':' as that + * is taken as namespace separator; no use trying to optimize + * heavily as it's 98% likely it is a valid char... + */ + if (!isNameStartChar(c)) { + if (c == ':') { + throwUnexpectedChar(c, " (missing namespace prefix?)"); + } + throwUnexpectedChar(c, " (expected a name start character)"); + } + + int ptr = mInputPtr; + int hash = c; + final int inputLen = mInputEnd; + int startPtr = ptr-1; // already read previous char + final char[] inputBuf = mInputBuffer; + + /* After which there may be zero or more name chars + * we have to consider + */ + while (true) { + if (ptr >= inputLen) { + /* Ok, identifier may continue past buffer end, need + * to continue with part 2 (separate method, as this is + * not as common as having it all in buffer) + */ + mInputPtr = ptr; + return parseLocalName2(startPtr, hash); + } + // Ok, we have the char... is it a name char? + c = inputBuf[ptr]; + if (c < CHAR_LOWEST_LEGAL_LOCALNAME_CHAR) { + break; + } + if (!isNameChar(c)) { + break; + } + hash = (hash * 31) + c; + ++ptr; + } + mInputPtr = ptr; + return mSymbols.findSymbol(mInputBuffer, startPtr, ptr - startPtr, hash); + } + + /** + * Second part of name token parsing; called when name can continue + * past input buffer end (so only part was read before calling this + * method to read the rest). + *

+ * Note that this isn't heavily optimized, on assumption it's not + * called very often. + */ + protected String parseLocalName2(int start, int hash) + throws XMLStreamException + { + int ptr = mInputEnd - start; + // Let's assume fairly short names + char[] outBuf = getNameBuffer(ptr+8); + + if (ptr > 0) { + System.arraycopy(mInputBuffer, start, outBuf, 0, ptr); + } + + int outLen = outBuf.length; + while (true) { + // note: names can not cross input block (entity) boundaries... + if (mInputPtr >= mInputEnd) { + if (!loadMoreFromCurrent()) { + break; + } + } + char c = mInputBuffer[mInputPtr]; + if (c < CHAR_LOWEST_LEGAL_LOCALNAME_CHAR) { + break; + } + if (!isNameChar(c)) { + break; + } + ++mInputPtr; + if (ptr >= outLen) { + mNameBuffer = outBuf = expandBy50Pct(outBuf); + outLen = outBuf.length; + } + outBuf[ptr++] = c; + hash = (hash * 31) + c; + } + // Still need to canonicalize the name: + return mSymbols.findSymbol(outBuf, 0, ptr, hash); + } + + /** + * Method that will parse 'full' name token; what full means depends on + * whether reader is namespace aware or not. If it is, full name means + * local name with no namespace prefix (PI target, entity/notation name); + * if not, name can contain arbitrary number of colons. Note that + * element and attribute names are NOT parsed here, so actual namespace + * prefix separation can be handled properly there. + *

+ * Similar to {@link #parseLocalName}, much of complexity stems from + * trying to avoid copying name characters from input buffer. + *

+ * Note that returned String will be canonicalized, similar to + * {@link #parseLocalName}, but without separating prefix/local name. + * + * @return Canonicalized name String (which may have length 0, if + * EOF or non-name-start char encountered) + */ + protected String parseFullName() + throws XMLStreamException + { + if (mInputPtr >= mInputEnd) { + loadMoreFromCurrent(); + } + return parseFullName(mInputBuffer[mInputPtr++]); + } + + protected String parseFullName(char c) + throws XMLStreamException + { + // First char has special handling: + if (!isNameStartChar(c)) { + if (c == ':') { // no name.... generally an error: + if (mCfgNsEnabled) { + throwNsColonException(parseFNameForError()); + } + // Ok, that's fine actually + } else { + if (c <= CHAR_SPACE) { + throwUnexpectedChar(c, " (missing name?)"); + } + throwUnexpectedChar(c, " (expected a name start character)"); + } + } + + int ptr = mInputPtr; + int hash = c; + int inputLen = mInputEnd; + int startPtr = ptr-1; // to account for the first char + + /* After which there may be zero or more name chars + * we have to consider + */ + while (true) { + if (ptr >= inputLen) { + /* Ok, identifier may continue past buffer end, need + * to continue with part 2 (separate method, as this is + * not as common as having it all in buffer) + */ + mInputPtr = ptr; + return parseFullName2(startPtr, hash); + } + c = mInputBuffer[ptr]; + if (c == ':') { // colon only allowed in non-NS mode + if (mCfgNsEnabled) { + mInputPtr = ptr; + throwNsColonException(new String(mInputBuffer, startPtr, ptr - startPtr) + parseFNameForError()); + } + } else { + if (c < CHAR_LOWEST_LEGAL_LOCALNAME_CHAR) { + break; + } + if (!isNameChar(c)) { + break; + } + } + hash = (hash * 31) + c; + ++ptr; + } + mInputPtr = ptr; + return mSymbols.findSymbol(mInputBuffer, startPtr, ptr - startPtr, hash); + } + + @SuppressWarnings("cast") + protected String parseFullName2(int start, int hash) + throws XMLStreamException + { + int ptr = mInputEnd - start; + // Let's assume fairly short names + char[] outBuf = getNameBuffer(ptr+8); + + if (ptr > 0) { + System.arraycopy(mInputBuffer, start, outBuf, 0, ptr); + } + + int outLen = outBuf.length; + while (true) { + /* 06-Sep-2004, TSa: Name tokens are not allowed to continue + * past entity expansion ranges... that is, all characters + * have to come from the same input source. Thus, let's only + * load things from same input level + */ + if (mInputPtr >= mInputEnd) { + if (!loadMoreFromCurrent()) { + break; + } + } + char c = mInputBuffer[mInputPtr]; + if (c == ':') { // colon only allowed in non-NS mode + if (mCfgNsEnabled) { + throwNsColonException(new String(outBuf, 0, ptr) + c + parseFNameForError()); + } + } else if (c < CHAR_LOWEST_LEGAL_LOCALNAME_CHAR) { + break; + } else if (!isNameChar(c)) { + break; + } + ++mInputPtr; + + if (ptr >= outLen) { + mNameBuffer = outBuf = expandBy50Pct(outBuf); + outLen = outBuf.length; + } + outBuf[ptr++] = c; + hash = (hash * 31) + (int) c; + } + + // Still need to canonicalize the name: + return mSymbols.findSymbol(outBuf, 0, ptr, hash); + } + + /** + * Method called to read in full name, including unlimited number of + * namespace separators (':'), for the purpose of displaying name in + * an error message. Won't do any further validations, and parsing + * is not optimized: main need is just to get more meaningful error + * messages. + */ + protected String parseFNameForError() + throws XMLStreamException + { + StringBuilder sb = new StringBuilder(100); + while (true) { + char c; + + if (mInputPtr < mInputEnd) { + c = mInputBuffer[mInputPtr++]; + } else { // can't error here, so let's accept EOF for now: + int i = getNext(); + if (i < 0) { + break; + } + c = (char) i; + } + if (c != ':' && !isNameChar(c)) { + --mInputPtr; + break; + } + sb.append(c); + } + return sb.toString(); + } + + protected final String parseEntityName(char c) + throws XMLStreamException + { + String id = parseFullName(c); + // Needs to be followed by a semi-colon, too.. from same input source: + if (mInputPtr >= mInputEnd) { + if (!loadMoreFromCurrent()) { + throwParseError("Missing semicolon after reference for entity \"{0}\"", id, null); + } + } + c = mInputBuffer[mInputPtr++]; + if (c != ';') { + throwUnexpectedChar(c, "; expected a semi-colon after the reference for entity '"+id+"'"); + } + return id; + } + + /** + * Note: does not check for number of colons, amongst other things. + * Main idea is to skip through what superficially seems like a valid + * id, nothing more. This is only done when really skipping through + * something we do not care about at all: not even whether names/ids + * would be valid (for example, when ignoring internal DTD subset). + * + * @return Length of skipped name. + */ + protected int skipFullName(char c) + throws XMLStreamException + { + if (!isNameStartChar(c)) { + --mInputPtr; + return 0; + } + + /* After which there may be zero or more name chars + * we have to consider + */ + int count = 1; + while (true) { + c = (mInputPtr < mInputEnd) ? + mInputBuffer[mInputPtr++] : getNextChar(SUFFIX_EOF_EXP_NAME); + if (c != ':' && !isNameChar(c)) { + break; + } + ++count; + } + return count; + } + + /** + * Simple parsing method that parses system ids, which are generally + * used in entities (from DOCTYPE declaration to internal/external + * subsets). + *

+ * NOTE: returned String is not canonicalized, on assumption that + * external ids may be longish, and are not shared all that often, as + * they are generally just used for resolving paths, if anything. + *
+ * Also note that this method is not heavily optimized, as it's not + * likely to be a bottleneck for parsing. + */ + protected final String parseSystemId(char quoteChar, boolean convertLFs, + String errorMsg) + throws XMLStreamException + { + char[] buf = getNameBuffer(-1); + int ptr = 0; + + while (true) { + char c = (mInputPtr < mInputEnd) ? + mInputBuffer[mInputPtr++] : getNextChar(errorMsg); + if (c == quoteChar) { + break; + } + /* ??? 14-Jun-2004, TSa: Should we normalize linefeeds or not? + * It seems like we should, for all input... so that's the way it + * works. + */ + if (c == '\n') { + markLF(); + } else if (c == '\r') { + if (peekNext() == '\n') { + ++mInputPtr; + if (!convertLFs) { + /* The only tricky thing; need to preserve 2-char LF; need to + * output one char from here, then can fall back to default: + */ + if (ptr >= buf.length) { + buf = expandBy50Pct(buf); + } + buf[ptr++] = '\r'; + } + c = '\n'; + } else if (convertLFs) { + c = '\n'; + } + } + + // Other than that, let's just append it: + if (ptr >= buf.length) { + buf = expandBy50Pct(buf); + } + buf[ptr++] = c; + } + + return (ptr == 0) ? "" : new String(buf, 0, ptr); + } + + /** + * Simple parsing method that parses system ids, which are generally + * used in entities (from DOCTYPE declaration to internal/external + * subsets). + *

+ * As per xml specs, the contents are actually normalized. + *

+ * NOTE: returned String is not canonicalized, on assumption that + * external ids may be longish, and are not shared all that often, as + * they are generally just used for resolving paths, if anything. + *
+ * Also note that this method is not heavily optimized, as it's not + * likely to be a bottleneck for parsing. + */ + protected final String parsePublicId(char quoteChar, String errorMsg) + throws XMLStreamException + { + char[] buf = getNameBuffer(-1); + int ptr = 0; + boolean spaceToAdd = false; + + while (true) { + char c = (mInputPtr < mInputEnd) ? + mInputBuffer[mInputPtr++] : getNextChar(errorMsg); + if (c == quoteChar) { + break; + } + if (c == '\n') { + markLF(); + spaceToAdd = true; + continue; + } else if (c == '\r') { + if (peekNext() == '\n') { + ++mInputPtr; + } + spaceToAdd = true; + continue; + } else if (c == CHAR_SPACE) { + spaceToAdd = true; + continue; + } else { + // Verify it's a legal pubid char (see XML spec, #13, from 2.3) + if ((c >= VALID_PUBID_CHAR_COUNT) + || sPubidValidity[c] != PUBID_CHAR_VALID_B) { + throwUnexpectedChar(c, " in public identifier"); + } + } + + // Other than that, let's just append it: + if (ptr >= buf.length) { + buf = expandBy50Pct(buf); + } + /* Space-normalization means scrapping leading and trailing + * white space, and coalescing remaining ws into single spaces. + */ + if (spaceToAdd) { // pending white space to add? + if (c == CHAR_SPACE) { // still a space; let's skip + continue; + } + /* ok: if we have non-space, we'll either forget about + * space(s) (if nothing has been output, ie. leading space), + * or output a single space (in-between non-white space) + */ + spaceToAdd = false; + if (ptr > 0) { + buf[ptr++] = CHAR_SPACE; + if (ptr >= buf.length) { + buf = expandBy50Pct(buf); + } + } + } + buf[ptr++] = c; + } + + return (ptr == 0) ? "" : new String(buf, 0, ptr); + } + + protected final void parseUntil(TextBuffer tb, char endChar, boolean convertLFs, + String errorMsg) + throws XMLStreamException + { + // Let's first ensure we have some data in there... + if (mInputPtr >= mInputEnd) { + loadMore(errorMsg); + } + while (true) { + // Let's loop consequtive 'easy' spans: + char[] inputBuf = mInputBuffer; + int inputLen = mInputEnd; + int ptr = mInputPtr; + int startPtr = ptr; + while (ptr < inputLen) { + char c = inputBuf[ptr++]; + if (c == endChar) { + int thisLen = ptr - startPtr - 1; + if (thisLen > 0) { + tb.append(inputBuf, startPtr, thisLen); + } + mInputPtr = ptr; + return; + } + if (c == '\n') { + mInputPtr = ptr; // markLF() requires this + markLF(); + } else if (c == '\r') { + if (!convertLFs && ptr < inputLen) { + if (inputBuf[ptr] == '\n') { + ++ptr; + } + mInputPtr = ptr; + markLF(); + } else { + int thisLen = ptr - startPtr - 1; + if (thisLen > 0) { + tb.append(inputBuf, startPtr, thisLen); + } + mInputPtr = ptr; + c = getNextChar(errorMsg); + if (c != '\n') { + --mInputPtr; // pusback + tb.append(convertLFs ? '\n' : '\r'); + } else { + if (convertLFs) { + tb.append('\n'); + } else { + tb.append('\r'); + tb.append('\n'); + } + } + startPtr = ptr = mInputPtr; + markLF(); + } + } + } + int thisLen = ptr - startPtr; + if (thisLen > 0) { + tb.append(inputBuf, startPtr, thisLen); + } + loadMore(errorMsg); + startPtr = ptr = mInputPtr; + inputBuf = mInputBuffer; + inputLen = mInputEnd; + } + } + + /* + /////////////////////////////////////////////////////////////////////// + // Internal methods + /////////////////////////////////////////////////////////////////////// + */ + + private int resolveCharEnt(StringBuffer originalCharacters) + throws XMLStreamException + { + int value = 0; + char c = getNextChar(SUFFIX_IN_ENTITY_REF); + + if (originalCharacters != null) { + originalCharacters.append(c); + } + + if (c == 'x') { // hex + while (true) { + c = (mInputPtr < mInputEnd) ? mInputBuffer[mInputPtr++] + : getNextCharFromCurrent(SUFFIX_IN_ENTITY_REF); + if (c == ';') { + break; + } + + if (originalCharacters != null) { + originalCharacters.append(c); + } + value = value << 4; + if (c <= '9' && c >= '0') { + value += (c - '0'); + } else if (c >= 'a' && c <= 'f') { + value += 10 + (c - 'a'); + } else if (c >= 'A' && c <= 'F') { + value += 10 + (c - 'A'); + } else { + throwUnexpectedChar(c, "; expected a hex digit (0-9a-fA-F)."); + } + // Overflow? + if (value > MAX_UNICODE_CHAR) { + reportUnicodeOverflow(); + } + } + } else { // numeric (decimal) + while (c != ';') { + if (c <= '9' && c >= '0') { + value = (value * 10) + (c - '0'); + // Overflow? + if (value > MAX_UNICODE_CHAR) { + reportUnicodeOverflow(); + } + } else { + throwUnexpectedChar(c, "; expected a decimal number."); + } + c = (mInputPtr < mInputEnd) ? mInputBuffer[mInputPtr++] + : getNextCharFromCurrent(SUFFIX_IN_ENTITY_REF); + + if (originalCharacters != null && c != ';') { + originalCharacters.append(c); + } + } + } + validateChar(value); + return value; + } + + /** + * Method that will verify that expanded Unicode codepoint is a valid + * XML content character. + */ + private final void validateChar(int value) + throws XMLStreamException + { + /* 24-Jan-2006, TSa: Ok, "high" Unicode chars are problematic, + * need to be reported by a surrogate pair.. + */ + if (value >= 0xD800) { + if (value < 0xE000) { // no surrogates via entity expansion + reportIllegalChar(value); + } + if (value > 0xFFFF) { + // Within valid range at all? + if (value > MAX_UNICODE_CHAR) { + reportUnicodeOverflow(); + } + } else if (value >= 0xFFFE) { // 0xFFFE and 0xFFFF are illegal too + reportIllegalChar(value); + } + // Ok, fine as is + } else if (value < 32) { + if (value == 0) { + throwParseError("Invalid character reference: null character not allowed in XML content."); + } + // XML 1.1 allows most other chars; 1.0 does not: + if (!mXml11 && + (value != 0x9 && value != 0xA && value != 0xD)) { + reportIllegalChar(value); + } + } + } + + protected final char[] getNameBuffer(int minSize) + { + char[] buf = mNameBuffer; + + if (buf == null) { + mNameBuffer = buf = new char[(minSize > 48) ? (minSize+16) : 64]; + } else if (minSize >= buf.length) { // let's allow one char extra... + int len = buf.length; + len += (len >> 1); // grow by 50% + mNameBuffer = buf = new char[(minSize >= len) ? (minSize+16) : len]; + } + return buf; + } + + protected final char[] expandBy50Pct(char[] buf) + { + int len = buf.length; + char[] newBuf = new char[len + (len >> 1)]; + System.arraycopy(buf, 0, newBuf, 0, len); + return newBuf; + } + + /** + * Method called to throw an exception indicating that a name that + * should not be namespace-qualified (PI target, entity/notation name) + * is one, and reader is namespace aware. + */ + private void throwNsColonException(String name) + throws XMLStreamException + { + throwParseError("Illegal name \"{0}\" (PI target, entity/notation name): can not contain a colon (XML Namespaces 1.0#6)", name, null); + } + + private void throwRecursionError(String entityName) + throws XMLStreamException + { + throwParseError("Illegal entity expansion: entity \"{0}\" expands itself recursively.", entityName, null); + } + + private void reportUnicodeOverflow() + throws XMLStreamException + { + throwParseError("Illegal character entity: value higher than max allowed (0x{0})", Integer.toHexString(MAX_UNICODE_CHAR), null); + } + + private void reportIllegalChar(int value) + throws XMLStreamException + { + throwParseError("Illegal character entity: expansion character (code 0x{0}", Integer.toHexString(value), null); + } + + protected void verifyLimit(String type, long maxValue, long currentValue) + throws XMLStreamException + { + if (currentValue > maxValue) { + throw constructLimitViolation(type, maxValue); + } + } + + protected XMLStreamException constructLimitViolation(String type, long limit) + throws XMLStreamException + { + return new XMLStreamException(type+" limit ("+limit+") exceeded"); + } +} diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/sr/TypedStreamReader.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/sr/TypedStreamReader.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/sr/TypedStreamReader.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/sr/TypedStreamReader.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,787 @@ +/* Woodstox XML processor + * + * Copyright (c) 2004- Tatu Saloranta, tatu.saloranta@iki.fi + * + * Licensed under the License specified in file LICENSE, included with + * the source code. + * You may not use this file except in compliance with the License. + * + * 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 com.ctc.wstx.sr; + +import java.math.BigDecimal; +import java.math.BigInteger; + +import javax.xml.namespace.QName; +import javax.xml.stream.XMLStreamException; + +import org.codehaus.stax2.typed.Base64Variant; +import org.codehaus.stax2.typed.Base64Variants; +import org.codehaus.stax2.typed.TypedArrayDecoder; +import org.codehaus.stax2.typed.TypedValueDecoder; +import org.codehaus.stax2.typed.TypedXMLStreamException; +import org.codehaus.stax2.ri.Stax2Util; +import org.codehaus.stax2.ri.typed.ValueDecoderFactory; +import org.codehaus.stax2.ri.typed.CharArrayBase64Decoder; + +import com.ctc.wstx.api.ReaderConfig; +import com.ctc.wstx.cfg.ErrorConsts; +import com.ctc.wstx.io.BranchingReaderSource; +import com.ctc.wstx.io.InputBootstrapper; +import com.ctc.wstx.io.WstxInputData; + +/** + * Complete implementation of {@link org.codehaus.stax2.XMLStreamReader2}, + * including Typed Access API (Stax2 v3.0) implementation. + * Only functionality missing is DTD validation, which is provided by a + * specialized sub-class. + */ +public class TypedStreamReader + extends BasicStreamReader +{ + /** + * Mask of event types that are legal (starting) states + * to call Typed Access API from. + * + */ + final protected static int MASK_TYPED_ACCESS_ARRAY = + (1 << START_ELEMENT) + | (1 << END_ELEMENT) // for convenience + | (1 << CHARACTERS) | (1 << CDATA) | (1 << SPACE) + // Not ok for PI or COMMENT? Let's assume so + ; + + final protected static int MASK_TYPED_ACCESS_BINARY = + (1 << START_ELEMENT) // note: END_ELEMENT handled separately + | (1 << CHARACTERS) | (1 << CDATA) | (1 << SPACE) + ; + + /** + * Minimum length of text chunks to parse before base64 decoding. + * Will try to limit it to fit within regular result buffers. + */ + final static int MIN_BINARY_CHUNK = 2000; + + /** + * Factory used for constructing decoders we need for typed access + */ + protected ValueDecoderFactory _decoderFactory; + + /** + * Lazily-constructed decoder object for decoding base64 encoded + * element binary content. + */ + protected CharArrayBase64Decoder _base64Decoder = null; + + /* + //////////////////////////////////////////////////// + // Instance construction + //////////////////////////////////////////////////// + */ + + protected TypedStreamReader(InputBootstrapper bs, + BranchingReaderSource input, ReaderCreator owner, + ReaderConfig cfg, InputElementStack elemStack, + boolean forER) + throws XMLStreamException + { + super(bs, input, owner, cfg, elemStack, forER); + } + + /** + * Factory method for constructing readers. + * + * @param owner "Owner" of this reader, factory that created the reader; + * needed for returning updated symbol table information after parsing. + * @param input Input source used to read the XML document. + * @param cfg Object that contains reader configuration info. + */ + public static TypedStreamReader createStreamReader + (BranchingReaderSource input, ReaderCreator owner, ReaderConfig cfg, + InputBootstrapper bs, boolean forER) + throws XMLStreamException + { + + TypedStreamReader sr = new TypedStreamReader + (bs, input, owner, cfg, createElementStack(cfg), forER); + return sr; + } + + + /* + //////////////////////////////////////////////////////// + // TypedXMLStreamReader2 implementation, scalar elements + //////////////////////////////////////////////////////// + */ + + @Override + public boolean getElementAsBoolean() throws XMLStreamException + { + ValueDecoderFactory.BooleanDecoder dec = _decoderFactory().getBooleanDecoder(); + getElementAs(dec); + return dec.getValue(); + } + + @Override + public int getElementAsInt() throws XMLStreamException + { + ValueDecoderFactory.IntDecoder dec = _decoderFactory().getIntDecoder(); + getElementAs(dec); + return dec.getValue(); + } + + @Override + public long getElementAsLong() throws XMLStreamException + { + ValueDecoderFactory.LongDecoder dec = _decoderFactory().getLongDecoder(); + getElementAs(dec); + return dec.getValue(); + } + + @Override + public float getElementAsFloat() throws XMLStreamException + { + ValueDecoderFactory.FloatDecoder dec = _decoderFactory().getFloatDecoder(); + getElementAs(dec); + return dec.getValue(); + } + + @Override + public double getElementAsDouble() throws XMLStreamException + { + ValueDecoderFactory.DoubleDecoder dec = _decoderFactory().getDoubleDecoder(); + getElementAs(dec); + return dec.getValue(); + } + + @Override + public BigInteger getElementAsInteger() throws XMLStreamException + { + ValueDecoderFactory.IntegerDecoder dec = _decoderFactory().getIntegerDecoder(); + getElementAs(dec); + return dec.getValue(); + } + + @Override + public BigDecimal getElementAsDecimal() throws XMLStreamException + { + ValueDecoderFactory.DecimalDecoder dec = _decoderFactory().getDecimalDecoder(); + getElementAs(dec); + return dec.getValue(); + } + + @Override + public QName getElementAsQName() throws XMLStreamException + { + ValueDecoderFactory.QNameDecoder dec = _decoderFactory().getQNameDecoder(getNamespaceContext()); + getElementAs(dec); + return _verifyQName(dec.getValue()); + } + + @Override + public final byte[] getElementAsBinary() throws XMLStreamException + { + return getElementAsBinary(Base64Variants.getDefaultVariant()); + } + + @Override + public byte[] getElementAsBinary(Base64Variant v) throws XMLStreamException + { + // note: code here is similar to Base64DecoderBase.aggregateAll(), see comments there + Stax2Util.ByteAggregator aggr = _base64Decoder().getByteAggregator(); + byte[] buffer = aggr.startAggregation(); + while (true) { + int offset = 0; + int len = buffer.length; + + do { + int readCount = readElementAsBinary(buffer, offset, len, v); + if (readCount < 1) { // all done! + return aggr.aggregateAll(buffer, offset); + } + offset += readCount; + len -= readCount; + } while (len > 0); + buffer = aggr.addFullBlock(buffer); + } + } + + @Override + public void getElementAs(TypedValueDecoder tvd) throws XMLStreamException + { + if (mCurrToken != START_ELEMENT) { + throwParseError(ErrorConsts.ERR_STATE_NOT_STELEM); + } + /* Ok, now: with START_ELEMENT we know that it's not partially + * processed; that we are in-tree (not prolog or epilog). + * The only possible complication would be: + */ + if (mStEmptyElem) { + /* And if so, we'll then get 'virtual' close tag; things + * are simple as location info was set when dealing with + * empty start element; and likewise, validation (if any) + * has been taken care of + */ + mStEmptyElem = false; + mCurrToken = END_ELEMENT; + _handleEmptyValue(tvd); + return; + } + // First need to find a textual event + while (true) { + int type = next(); + if (type == END_ELEMENT) { + _handleEmptyValue(tvd); + return; + } + if (type == COMMENT || type == PROCESSING_INSTRUCTION) { + continue; + } + if (((1 << type) & MASK_GET_ELEMENT_TEXT) == 0) { + throwParseError("Expected a text token, got "+tokenTypeDesc(type)+"."); + } + break; + } + if (mTokenState < TOKEN_FULL_SINGLE) { + readCoalescedText(mCurrToken, false); + } + /* Ok: then a quick check; if it looks like we are directly + * followed by the end tag, we need not construct String + * quite yet. + */ + if ((mInputPtr + 1) < mInputEnd && + mInputBuffer[mInputPtr] == '<' && mInputBuffer[mInputPtr+1] == '/') { + // Note: next() has validated text, no need for more validation + mInputPtr += 2; + mCurrToken = END_ELEMENT; + /* Can by-pass next(), nextFromTree(), in this case. + * However, must do decoding first, and only then call + * readEndElem(), since this latter call may invalidate + * underlying input buffer (when end tag is at buffer + * boundary) + */ + try { // buffer now has all the data + mTextBuffer.decode(tvd); + } catch (IllegalArgumentException iae) { + throw _constructTypeException(iae, mTextBuffer.contentsAsString()); + } + readEndElem(); + return; + } + + // Otherwise, we'll need to do slower processing + int extra = 1 + (mTextBuffer.size() >> 1); // let's add 50% space + StringBuilder sb = mTextBuffer.contentsAsStringBuilder(extra); + int type; + + while ((type = next()) != END_ELEMENT) { + if (((1 << type) & MASK_GET_ELEMENT_TEXT) != 0) { + if (mTokenState < TOKEN_FULL_SINGLE) { + readCoalescedText(type, false); + } + mTextBuffer.contentsToStringBuilder(sb); + continue; + } + if (type != COMMENT && type != PROCESSING_INSTRUCTION) { + throwParseError("Expected a text token, got "+tokenTypeDesc(type)+"."); + } + } + // Note: calls next() have validated text, no need for more validation + String str = sb.toString(); + String tstr = Stax2Util.trimSpaces(str); + if (tstr == null) { + _handleEmptyValue(tvd); + } else { + try { + tvd.decode(tstr); + } catch (IllegalArgumentException iae) { + throw _constructTypeException(iae, str); + } + } + } + + /* + //////////////////////////////////////////////////////// + // TypedXMLStreamReader2 implementation, array elements + //////////////////////////////////////////////////////// + */ + + @Override + public int readElementAsIntArray(int[] value, int from, int length) throws XMLStreamException + { + return readElementAsArray(_decoderFactory().getIntArrayDecoder(value, from, length)); + } + + @Override + public int readElementAsLongArray(long[] value, int from, int length) throws XMLStreamException + { + return readElementAsArray(_decoderFactory().getLongArrayDecoder(value, from, length)); + } + + @Override + public int readElementAsFloatArray(float[] value, int from, int length) throws XMLStreamException + { + return readElementAsArray(_decoderFactory().getFloatArrayDecoder(value, from, length)); + } + + @Override + public int readElementAsDoubleArray(double[] value, int from, int length) throws XMLStreamException + { + return readElementAsArray(_decoderFactory().getDoubleArrayDecoder(value, from, length)); + } + + /** + * Method called to parse array of primitives. + *

+ * !!! 05-Sep-2008, tatu: Current implementation is not optimal + * either performance-wise, or from getting accurate Location + * for decoding problems. But it works otherwise, and we need + * to get Woodstox 4.0 out by the end of the year... so it'll + * do, for now. + * + * @return Number of elements decoded (if any were decoded), or + * -1 to indicate that no more values can be decoded. + */ + @Override + public final int readElementAsArray(TypedArrayDecoder dec) + throws XMLStreamException + { + int type = mCurrToken; + // First things first: must be acceptable start state: + if (((1 << type) & MASK_TYPED_ACCESS_ARRAY) == 0) { + throwNotTextualOrElem(type); + } + + // Are we just starting (START_ELEMENT)? + if (type == START_ELEMENT) { + // Empty? Not common, but can short-cut handling if occurs + if (mStEmptyElem) { + mStEmptyElem = false; + mCurrToken = END_ELEMENT; + return -1; + } + // Otherwise let's just find the first text segment + while (true) { + type = next(); + if (type == END_ELEMENT) { + // Simple... no textul content + return -1; + } + if (type == COMMENT || type == PROCESSING_INSTRUCTION) { + continue; + } + if (type == CHARACTERS || type == CDATA) { + break; + } + // otherwise just not legal (how about SPACE, unexpanded entities?) + throw _constructUnexpectedInTyped(type); + } + } + + int count = 0; + while (type != END_ELEMENT) { + /* Ok then: we will have a valid textual type. Just need to + * ensure current segment is completed. Plus, for current impl, + * also need to coalesce to prevent artificial CDATA/text + * boundary from splitting tokens + */ + if (type == CHARACTERS || type == CDATA || type == SPACE) { + if (mTokenState < TOKEN_FULL_SINGLE) { + readCoalescedText(type, false); + } + } else if (type == COMMENT || type == PROCESSING_INSTRUCTION) { + type = next(); + continue; + } else { + throw _constructUnexpectedInTyped(type); + } + count += mTextBuffer.decodeElements(dec, this); + if (!dec.hasRoom()) { + break; + } + type = next(); + } + + // If nothing was found, needs to be indicated via -1, not 0 + return (count > 0) ? count : -1; + } + + /* + //////////////////////////////////////////////////////// + // TypedXMLStreamReader2 implementation, binary data + //////////////////////////////////////////////////////// + */ + + @Override + public final int readElementAsBinary(byte[] resultBuffer, int offset, int maxLength) + throws XMLStreamException + { + return readElementAsBinary(resultBuffer, offset, maxLength, Base64Variants.getDefaultVariant()); + } + + @Override + public int readElementAsBinary(byte[] resultBuffer, int offset, int maxLength, Base64Variant v) + throws XMLStreamException + { + if (resultBuffer == null) { + throw new IllegalArgumentException("resultBuffer is null"); + } + if (offset < 0) { + throw new IllegalArgumentException("Illegal offset ("+offset+"), must be [0, "+resultBuffer.length+"["); + } + if (maxLength < 1 || (offset + maxLength) > resultBuffer.length) { + if (maxLength == 0) { // special case, allowed, but won't do anything + return 0; + } + throw new IllegalArgumentException("Illegal maxLength ("+maxLength+"), has to be positive number, and offset+maxLength can not exceed"+resultBuffer.length); + } + + final CharArrayBase64Decoder dec = _base64Decoder(); + int type = mCurrToken; + // First things first: must be acceptable start state: + if (((1 << type) & MASK_TYPED_ACCESS_BINARY) == 0) { + if (type == END_ELEMENT) { + // Minor complication: may have unflushed stuff (non-padded versions) + if (!dec.hasData()) { + return -1; + } + } else { + throwNotTextualOrElem(type); + } + } else if (type == START_ELEMENT) { // just starting (START_ELEMENT)? + if (mStEmptyElem) { // empty element? simple... + mStEmptyElem = false; + mCurrToken = END_ELEMENT; + return -1; + } + // Otherwise let's just find the first text segment + while (true) { + type = next(); + if (type == END_ELEMENT) { + // Simple... no textual content + return -1; + } + if (type == COMMENT || type == PROCESSING_INSTRUCTION) { + continue; + } + /* 12-Dec-2009, tatu: Important: in coalescing mode we may + * have incomplete segment that needs to be completed + */ + if (mTokenState < mStTextThreshold) { + finishToken(false); + } + _initBinaryChunks(v, dec, type, true); + break; + } + } + + int totalCount = 0; + + main_loop: + while (true) { + // Ok, decode: + int count; + try { + count = dec.decode(resultBuffer, offset, maxLength); + } catch (IllegalArgumentException iae) { + // !!! 26-Sep-2008, tatus: should try to figure out which char (etc) triggered problem to pass with typed exception + throw _constructTypeException(iae.getMessage(), ""); + } + offset += count; + totalCount += count; + maxLength -= count; + + /* And if we filled the buffer we are done. Or, an edge + * case: reached END_ELEMENT (for non-padded variant) + */ + if (maxLength < 1 || mCurrToken == END_ELEMENT) { + break; + } + // Otherwise need to advance to the next event + while (true) { + type = next(); + if (type == COMMENT || type == PROCESSING_INSTRUCTION + || type == SPACE) { // space is ignorable too + continue; + } + if (type == END_ELEMENT) { + /* Just need to verify we don't have partial stuff + * (missing one to three characters of a full quartet + * that encodes 1 - 3 bytes). Also: non-padding + * variants can be in incomplete state, from which + * data may need to be flushed... + */ + int left = dec.endOfContent(); + if (left < 0) { // incomplete, error + throw _constructTypeException("Incomplete base64 triplet at the end of decoded content", ""); + } else if (left > 0) { // 1 or 2 more bytes of data, loop some more + continue main_loop; + } + // Otherwise, no more data, we are done + break main_loop; + } + /* 12-Dec-2009, tatu: Important: in coalescing mode we may + * have incomplete segment that needs to be completed + */ + if (mTokenState < mStTextThreshold) { + finishToken(false); + } + _initBinaryChunks(v, dec, type, false); + break; + } + } + + // If nothing was found, needs to be indicated via -1, not 0 + return (totalCount > 0) ? totalCount : -1; + } + + private final void _initBinaryChunks(Base64Variant v, CharArrayBase64Decoder dec, int type, boolean isFirst) + throws XMLStreamException + { + if (type == CHARACTERS) { + if (mTokenState < mStTextThreshold) { + mTokenState = readTextSecondary(MIN_BINARY_CHUNK, false) + ? TOKEN_FULL_SINGLE : TOKEN_PARTIAL_SINGLE; + } + } else if (type == CDATA) { + if (mTokenState < mStTextThreshold) { + mTokenState = readCDataSecondary(MIN_BINARY_CHUNK) + ? TOKEN_FULL_SINGLE : TOKEN_PARTIAL_SINGLE; + } + } else { + throw _constructUnexpectedInTyped(type); + } + mTextBuffer.initBinaryChunks(v, dec, isFirst); + } + + /* + /////////////////////////////////////////////////////////// + // TypedXMLStreamReader2 implementation, scalar attributes + /////////////////////////////////////////////////////////// + */ + + @Override + public int getAttributeIndex(String namespaceURI, String localName) + { + // Note: cut'n pasted from "getAttributeInfo()" + if (mCurrToken != START_ELEMENT) { + throw new IllegalStateException(ErrorConsts.ERR_STATE_NOT_STELEM); + } + return mElementStack.findAttributeIndex(namespaceURI, localName); + } + + @Override + public boolean getAttributeAsBoolean(int index) throws XMLStreamException + { + ValueDecoderFactory.BooleanDecoder dec = _decoderFactory().getBooleanDecoder(); + getAttributeAs(index, dec); + return dec.getValue(); + } + + @Override + public int getAttributeAsInt(int index) throws XMLStreamException + { + ValueDecoderFactory.IntDecoder dec = _decoderFactory().getIntDecoder(); + getAttributeAs(index, dec); + return dec.getValue(); + } + + @Override + public long getAttributeAsLong(int index) throws XMLStreamException + { + ValueDecoderFactory.LongDecoder dec = _decoderFactory().getLongDecoder(); + getAttributeAs(index, dec); + return dec.getValue(); + } + + @Override + public float getAttributeAsFloat(int index) throws XMLStreamException + { + ValueDecoderFactory.FloatDecoder dec = _decoderFactory().getFloatDecoder(); + getAttributeAs(index, dec); + return dec.getValue(); + } + + @Override + public double getAttributeAsDouble(int index) throws XMLStreamException + { + ValueDecoderFactory.DoubleDecoder dec = _decoderFactory().getDoubleDecoder(); + getAttributeAs(index, dec); + return dec.getValue(); + } + + @Override + public BigInteger getAttributeAsInteger(int index) throws XMLStreamException + { + ValueDecoderFactory.IntegerDecoder dec = _decoderFactory().getIntegerDecoder(); + getAttributeAs(index, dec); + return dec.getValue(); + } + + @Override + public BigDecimal getAttributeAsDecimal(int index) throws XMLStreamException + { + ValueDecoderFactory.DecimalDecoder dec = _decoderFactory().getDecimalDecoder(); + getAttributeAs(index, dec); + return dec.getValue(); + } + + @Override + public QName getAttributeAsQName(int index) throws XMLStreamException + { + ValueDecoderFactory.QNameDecoder dec = _decoderFactory().getQNameDecoder(getNamespaceContext()); + getAttributeAs(index, dec); + return _verifyQName(dec.getValue()); + } + + @Override + public void getAttributeAs(int index, TypedValueDecoder tvd) throws XMLStreamException + { + if (mCurrToken != START_ELEMENT) { + throw new IllegalStateException(ErrorConsts.ERR_STATE_NOT_STELEM); + } + try { + mAttrCollector.decodeValue(index, tvd); + } catch (IllegalArgumentException iae) { + throw _constructTypeException(iae, mAttrCollector.getValue(index)); + } + } + + @Override + public int[] getAttributeAsIntArray(int index) throws XMLStreamException + { + ValueDecoderFactory.IntArrayDecoder dec = _decoderFactory().getIntArrayDecoder(); + getAttributeAsArray(index, dec); + return dec.getValues(); + } + + @Override + public long[] getAttributeAsLongArray(int index) throws XMLStreamException + { + ValueDecoderFactory.LongArrayDecoder dec = _decoderFactory().getLongArrayDecoder(); + getAttributeAsArray(index, dec); + return dec.getValues(); + } + + @Override + public float[] getAttributeAsFloatArray(int index) throws XMLStreamException + { + ValueDecoderFactory.FloatArrayDecoder dec = _decoderFactory().getFloatArrayDecoder(); + getAttributeAsArray(index, dec); + return dec.getValues(); + } + + @Override + public double[] getAttributeAsDoubleArray(int index) throws XMLStreamException + { + ValueDecoderFactory.DoubleArrayDecoder dec = _decoderFactory().getDoubleArrayDecoder(); + getAttributeAsArray(index, dec); + return dec.getValues(); + } + + /** + * Method that allows reading contents of an attribute as an array + * of whitespace-separate tokens, decoded using specified decoder. + * + * @return Number of tokens decoded, 0 if none found + */ + @Override + public int getAttributeAsArray(int index, TypedArrayDecoder tad) throws XMLStreamException + { + if (mCurrToken != START_ELEMENT) { + throw new IllegalStateException(ErrorConsts.ERR_STATE_NOT_STELEM); + } + return mAttrCollector.decodeValues(index, tad, this); + } + + @Override + public byte[] getAttributeAsBinary(int index) throws XMLStreamException + { + return getAttributeAsBinary(index, Base64Variants.getDefaultVariant()); + } + + @Override + public byte[] getAttributeAsBinary(int index, Base64Variant v) throws XMLStreamException { + return mAttrCollector.decodeBinary(index, v, _base64Decoder(), this); + } + + /* + ///////////////////////////////////////////////////// + // Internal helper methods + ///////////////////////////////////////////////////// + */ + + /** + * Method called to verify validity of the parsed QName element + * or attribute value. At this point binding of a prefixed name + * (if qname has a prefix) has been verified, and thereby prefix + * also must be valid (since there must have been a preceding + * declaration). But local name might still not be a legal + * well-formed xml name, so let's verify that. + */ + protected QName _verifyQName(QName n) + throws TypedXMLStreamException + { + String ln = n.getLocalPart(); + int ix = WstxInputData.findIllegalNameChar(ln, mCfgNsEnabled, mXml11); + if (ix >= 0) { + String prefix = n.getPrefix(); + String pname = (prefix != null && prefix.length() > 0) ? + (prefix + ":" +ln) : ln; + throw _constructTypeException("Invalid local name \""+ln+"\" (character at #"+ix+" is invalid)", pname); + } + return n; + } + + protected ValueDecoderFactory _decoderFactory() + { + if (_decoderFactory == null) { + _decoderFactory = new ValueDecoderFactory(); + } + return _decoderFactory; + } + + protected CharArrayBase64Decoder _base64Decoder() + { + if (_base64Decoder == null) { + _base64Decoder = new CharArrayBase64Decoder(); + } + return _base64Decoder; + } + + /** + * Method called to handle value that has empty String + * as representation. This will usually either lead to an + * exception, or parsing to the default value for the + * type in question (null for nullable types and so on). + */ + private void _handleEmptyValue(TypedValueDecoder dec) + throws XMLStreamException + { + try { // default action is to throw an exception + dec.handleEmptyValue(); + } catch (IllegalArgumentException iae) { + throw _constructTypeException(iae, ""); + } + } + + /** + * Method called to wrap or convert given conversion-fail exception + * into a full {@link TypedXMLStreamException}, + * + * @param iae Problem as reported by converter + * @param lexicalValue Lexical value (element content, attribute value) + * that could not be converted succesfully. + */ + protected TypedXMLStreamException _constructTypeException(IllegalArgumentException iae, String lexicalValue) + { + return new TypedXMLStreamException(lexicalValue, iae.getMessage(), getStartLocation(), iae); + } +} + diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/sr/ValidatingStreamReader.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/sr/ValidatingStreamReader.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/sr/ValidatingStreamReader.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/sr/ValidatingStreamReader.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,626 @@ +/* Woodstox XML processor + * + * Copyright (c) 2004- Tatu Saloranta, tatu.saloranta@iki.fi + * + * Licensed under the License specified in the file LICENSE which is + * included with the source code. + * You may not use this file except in compliance with the License. + * + * 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 com.ctc.wstx.sr; + +import java.io.FileNotFoundException; +import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; +import java.net.URL; +import java.util.*; + +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.events.NotationDeclaration; + +import org.codehaus.stax2.XMLInputFactory2; +import org.codehaus.stax2.validation.*; + +import com.ctc.wstx.api.ReaderConfig; +import com.ctc.wstx.cfg.ErrorConsts; +import com.ctc.wstx.cfg.XmlConsts; +import com.ctc.wstx.io.*; +import com.ctc.wstx.dtd.DTDId; +import com.ctc.wstx.dtd.DTDSubset; +import com.ctc.wstx.dtd.DTDValidatorBase; +import com.ctc.wstx.dtd.FullDTDReader; +import com.ctc.wstx.ent.EntityDecl; +import com.ctc.wstx.util.URLUtil; + +/** + * Implementation of {@link org.codehaus.stax2.XMLStreamReader2} + * that builds on {@link TypedStreamReader} and adds full DTD-handling + * including DTD validation + * + * @author Tatu Saloranta + * @author Benson Margulies + */ +public class ValidatingStreamReader + extends TypedStreamReader +{ + /* + /////////////////////////////////////////////////////////////////////// + // Constants for standard StAX properties: + /////////////////////////////////////////////////////////////////////// + */ + + final static String STAX_PROP_ENTITIES = "javax.xml.stream.entities"; + + final static String STAX_PROP_NOTATIONS = "javax.xml.stream.notations"; + + /* + /////////////////////////////////////////////////////////////////////// + // Validation (DTD) information (entities, ...) + /////////////////////////////////////////////////////////////////////// + */ + + // // // Note: some members that logically belong here, are actually + // // // part of superclass + + /** + * Combined DTD set, constructed from parsed internal and external + * entities (which may have been set via override DTD functionality). + */ + DTDValidationSchema mDTD = null; + + /** + * Validating reader keeps of automatically created DTD-based + * validator, since its handling may differ from that of application + * managed validators. + */ + XMLValidator mAutoDtdValidator = null; + + /** + * Flag that indicates whether a DTD validator has been automatically + * set (as per DOCTYPE declaration or override) + */ + boolean mDtdValidatorSet = false; + + /** + * Custom validation problem handler, if any. + */ + protected ValidationProblemHandler mVldProbHandler = null; + + /* + /////////////////////////////////////////////////////////////////////// + // Life-cycle (ctors) + /////////////////////////////////////////////////////////////////////// + */ + + private ValidatingStreamReader(InputBootstrapper bs, + BranchingReaderSource input, ReaderCreator owner, + ReaderConfig cfg, InputElementStack elemStack, + boolean forER) + throws XMLStreamException + { + super(bs, input, owner, cfg, elemStack, forER); + } + + /** + * Factory method for constructing readers. + * + * @param owner "Owner" of this reader, factory that created the reader; + * needed for returning updated symbol table information after parsing. + * @param input Input source used to read the XML document. + * @param cfg Object that contains reader configuration info. + * @param bs Bootstrapper to use, for reading xml declaration etc. + * @param forER True if this reader is to be (configured to be) used by + * an event reader. Will cause some changes to default settings, as + * required by contracts Woodstox XMLEventReader implementation has + * (with respect to lazy parsing, short text segments etc) + */ + public static ValidatingStreamReader createValidatingStreamReader + (BranchingReaderSource input, ReaderCreator owner, + ReaderConfig cfg, InputBootstrapper bs, boolean forER) + throws XMLStreamException + { + ValidatingStreamReader sr = new ValidatingStreamReader + (bs, input, owner, cfg, createElementStack(cfg), forER); + return sr; + } + + /* + /////////////////////////////////////////////////////////////////////// + // Public API, configuration + /////////////////////////////////////////////////////////////////////// + */ + + @Override + public Object getProperty(String name) + { + // DTD-specific properties... + if (name.equals(STAX_PROP_ENTITIES)) { + safeEnsureFinishToken(); + if (mDTD == null || !(mDTD instanceof DTDSubset)) { + return null; + } + List l = ((DTDSubset) mDTD).getGeneralEntityList(); + /* Let's make a copy, so that caller can not modify + * DTD's internal list instance + */ + return new ArrayList(l); + } + if (name.equals(STAX_PROP_NOTATIONS)) { + safeEnsureFinishToken(); + if (mDTD == null || !(mDTD instanceof DTDSubset)) { + return null; + } + /* Let's make a copy, so that caller can not modify + * DTD's internal list instance + */ + List l = ((DTDSubset) mDTD).getNotationList(); + return new ArrayList(l); + } + return super.getProperty(name); + } + + /* + /////////////////////////////////////////////////////////////////////// + // XMLStreamReader2 (StAX2) implementation + /////////////////////////////////////////////////////////////////////// + */ + + // // // StAX2, per-reader configuration + + /* + /////////////////////////////////////////////////////////////////////// + // DTDInfo implementation (StAX 2) + /////////////////////////////////////////////////////////////////////// + */ + + @Override + public Object getProcessedDTD() { + return getProcessedDTDSchema(); + } + + @Override + public DTDValidationSchema getProcessedDTDSchema() { + DTDValidationSchema dtd = mConfig.getDTDOverride(); + if (dtd == null) { + dtd = mDTD; + } + return mDTD; + } + + /* + /////////////////////////////////////////////////////////////////////// + // Stax2 validation + /////////////////////////////////////////////////////////////////////// + */ + + @Override + public XMLValidator validateAgainst(XMLValidationSchema schema) + throws XMLStreamException + { + return mElementStack.validateAgainst(schema); + } + + @Override + public XMLValidator stopValidatingAgainst(XMLValidationSchema schema) + throws XMLStreamException + { + return mElementStack.stopValidatingAgainst(schema); + } + + @Override + public XMLValidator stopValidatingAgainst(XMLValidator validator) + throws XMLStreamException + { + return mElementStack.stopValidatingAgainst(validator); + } + + @Override + public ValidationProblemHandler setValidationProblemHandler(ValidationProblemHandler h) + { + ValidationProblemHandler oldH = mVldProbHandler; + mVldProbHandler = h; + return oldH; + } + + /* + /////////////////////////////////////////////////////////////////////// + // Private methods, DOCTYPE handling + /////////////////////////////////////////////////////////////////////// + */ + + /** + * This method gets called to handle remainder of DOCTYPE declaration, + * essentially the optional internal subset. Internal subset, if such + * exists, is always read, but whether its contents are added to the + * read buffer depend on passed-in argument. + *

+ * NOTE: Since this method overrides the default implementation, make + * sure you do NOT change the method signature. + * + * @param copyContents If true, will copy contents of the internal + * subset of DOCTYPE declaration + * in the text buffer (in addition to parsing it for actual use); if + * false, will only do parsing. + */ + @Override + protected void finishDTD(boolean copyContents) + throws XMLStreamException + { + if (!hasConfigFlags(CFG_SUPPORT_DTD)) { + super.finishDTD(copyContents); + return; + } + + /* We know there are no spaces, as this char was read and pushed + * back earlier... + */ + char c = getNextChar(SUFFIX_IN_DTD); + DTDSubset intSubset = null; + + /* Do we have an internal subset? Note that we have earlier checked + * that it has to be either '[' or closing '>'. + */ + if (c == '[') { + // Do we need to copy the contents of int. subset in the buffer? + if (copyContents) { + ((BranchingReaderSource) mInput).startBranch(mTextBuffer, mInputPtr, mNormalizeLFs); + } + + try { + intSubset = FullDTDReader.readInternalSubset(this, mInput, mConfig, + hasConfigFlags(CFG_VALIDATE_AGAINST_DTD), + mDocXmlVersion); + } finally { + /* Let's close branching in any and every case (may allow + * graceful recovery in error cases in future + */ + if (copyContents) { + /* Need to "push back" ']' got in the succesful case + * (that's -1 part below); + * in error case it'll just be whatever last char was. + */ + ((BranchingReaderSource) mInput).endBranch(mInputPtr-1); + } + } + + // And then we need closing '>' + c = getNextCharAfterWS(SUFFIX_IN_DTD_INTERNAL); + } + + if (c != '>') { + throwUnexpectedChar(c, "; expected '>' to finish DOCTYPE declaration."); + } + + /* But, then, we also may need to read the external subset, if + * one was defined: + */ + /* 19-Sep-2004, TSa: That does not need to be done, however, if + * there's a DTD override set. + */ + + mDTD = mConfig.getDTDOverride(); + if (mDTD != null) { + // We have earlier override that's already parsed + } else { // Nope, no override + DTDSubset extSubset = null; + + /* 05-Mar-2006, TSa: If standalone was specified as "yes", we + * should not rely on any external declarations, so shouldn't + * we really just skip the external subset? + */ + /* Alas: SAX (Xerces) still tries to read it... should we + * do the Right Thing, or follow the leader? For now, let's + * just follow the wrong example. + */ + + //if (mDocStandalone != DOC_STANDALONE_YES) { + if (true) { + if (mDtdPublicId != null || mDtdSystemId != null) { + extSubset = findDtdExtSubset(mDtdPublicId, mDtdSystemId, intSubset); + } + } + if (intSubset == null) { + mDTD = extSubset; + } else if (extSubset == null) { + mDTD = intSubset; + } else { + mDTD = intSubset.combineWithExternalSubset(this, extSubset); + } + } + + + if (mDTD == null) { // only if specifically overridden not to have any + mGeneralEntities = null; + } else { + if (mDTD instanceof DTDSubset) { + mGeneralEntities = ((DTDSubset) mDTD).getGeneralEntityMap(); + } else { + /* Also, let's warn if using non-native DTD implementation, + * since entities and notations can not be accessed + */ + _reportProblem(mConfig.getXMLReporter(), ErrorConsts.WT_DT_DECL, + "Value to set for property '"+XMLInputFactory2.P_DTD_OVERRIDE + +"' not a native Woodstox DTD implementation (but "+mDTD.getClass()+"): can not access full entity or notation information", null); + } + /* 16-Jan-2006, TSa: Actually, we have both fully-validating mode, + * and non-validating-but-DTD-aware mode. In latter case, we'll + * still need to add a validator, but just to get type info + * and to add attribute default values if necessary. + */ + mAutoDtdValidator = mDTD.createValidator(/*(ValidationContext)*/ mElementStack); + mDtdValidatorSet = true; // so we won't get nags + NsDefaultProvider nsDefs = null; + if (mAutoDtdValidator instanceof DTDValidatorBase) { + DTDValidatorBase dtdv = (DTDValidatorBase) mAutoDtdValidator; + dtdv.setAttrValueNormalization(true); + // Do we have any attribute defaults for 'xmlns' or 'xmlns:*'? + if (dtdv.hasNsDefaults()) { + nsDefs = dtdv; + } + } + mElementStack.setAutomaticDTDValidator(mAutoDtdValidator, nsDefs); + } + } + + /** + * If there is an error handler established, call it. + */ + @Override + public void reportValidationProblem(XMLValidationProblem prob) + throws XMLStreamException + { + if (mVldProbHandler != null) { + // Fix for [WSTX-209] + mVldProbHandler.reportProblem(prob); + } else { + super.reportValidationProblem(prob); + } + } + + /** + * Method called right before handling the root element, by the base + * class. This allows for some initialization and checks to be done + * (not including ones that need access to actual element name) + */ + @Override + protected void initValidation() throws XMLStreamException + { + if (hasConfigFlags(CFG_VALIDATE_AGAINST_DTD) + && !mDtdValidatorSet) { + /* It's ok to miss it, but it may not be what caller wants. Either + * way, let's pass the info and continue + */ + reportProblem(null, ErrorConsts.WT_DT_DECL, ErrorConsts.W_MISSING_DTD, null, null); + } + } + + /* + /////////////////////////////////////////////////////////////////////// + // Private methods, external subset access + /////////////////////////////////////////////////////////////////////// + */ + + /** + * Method called by finishDTD, to locate the specified + * external DTD subset. Subset may be obtained from a cache, if cached + * copy exists and is compatible; if not, it will be read from the + * source identified by the public and/or system identifier passed. + */ + private DTDSubset findDtdExtSubset(String pubId, String sysId, + DTDSubset intSubset) + throws XMLStreamException + { + boolean cache = hasConfigFlags(CFG_CACHE_DTDS); + DTDId dtdId; + try { + dtdId = constructDtdId(pubId, sysId); + } catch (IOException ioe) { + throw constructFromIOE(ioe); + } + + if (cache) { + DTDSubset extSubset = findCachedSubset(dtdId, intSubset); + if (extSubset != null) { + return extSubset; + } + } + + // No useful cached copy? Need to read it then. + /* For now, we do require system identifier; otherwise we don't + * know how to resolve DTDs by public id. In future should + * probably also have some simple catalog resolving facility? + */ + if (sysId == null) { + throwParseError("Can not resolve DTD with public id \"{0}\"; missing system identifier", mDtdPublicId, null); + } + WstxInputSource src = null; + + try { + int xmlVersion = mDocXmlVersion; + // 05-Feb-2006, TSa: If xmlVersion not explicitly known, defaults to 1.0 + if (xmlVersion == XmlConsts.XML_V_UNKNOWN) { + xmlVersion = XmlConsts.XML_V_10; + } + /* null -> no explicit path context, use parent's + * null -> not an entity expansion, no name. + * Note, too, that we can NOT just pass mEntityResolver, since + * that's the one used for general entities, whereas ext subset + * should be resolved by the param entity resolver. + */ + src = DefaultInputResolver.resolveEntity + (mInput, null, null, pubId, sysId, mConfig.getDtdResolver(), + mConfig, xmlVersion); + } catch (FileNotFoundException fex) { + /* Let's catch and rethrow this just so we get more meaningful + * description (with input source position etc) + */ + throwParseError("(was {0}) {1}", fex.getClass().getName(), fex.getMessage()); + } catch (IOException ioe) { + throwFromIOE(ioe); + } + + DTDSubset extSubset = FullDTDReader.readExternalSubset(src, mConfig, intSubset, + hasConfigFlags(CFG_VALIDATE_AGAINST_DTD), + mDocXmlVersion); + + if (cache) { + /* Ok; can be cached, but only if it does NOT refer to + * parameter entities defined in the internal subset (if + * it does, there's no easy/efficient to check if it could + * be used later on, plus it's unlikely it could be) + */ + if (extSubset.isCachable()) { + mOwner.addCachedDTD(dtdId, extSubset); + } + } + + return extSubset; + } + + private DTDSubset findCachedSubset(DTDId id, DTDSubset intSubset) + throws XMLStreamException + { + DTDSubset extSubset = mOwner.findCachedDTD(id); + /* Ok, now; can use the cached copy iff it does not refer to + * any parameter entities internal subset (if one exists) + * defines: + */ + if (extSubset != null) { + if (intSubset == null || extSubset.isReusableWith(intSubset)) { + return extSubset; + } + } + return null; + } + + /** + * Method called to resolve path to external DTD subset, given + * system identifier. + */ + private URI resolveExtSubsetPath(String systemId) throws IOException + { + // Do we have a context to use for resolving? + URL ctxt = (mInput == null) ? null : mInput.getSource(); + + /* Ok, either got a context or not; let's create the URL based on + * the id, and optional context: + */ + if (ctxt == null) { + /* Call will try to figure out if system id has the protocol + * in it; if not, create a relative file, if it does, try to + * resolve it. + */ + return URLUtil.uriFromSystemId(systemId); + } + URL url = URLUtil.urlFromSystemId(systemId, ctxt); + try { + return new URI(url.toExternalForm()); + } catch (URISyntaxException e) { // should never occur... + throw new IOException("Failed to construct URI for external subset, URL = "+url.toExternalForm()+": "+e.getMessage()); + } + } + + protected DTDId constructDtdId(String pubId, String sysId) throws IOException + { + /* Following settings will change what gets stored as DTD, so + * they need to separate cached instances too: + */ + int significantFlags = mConfigFlags & + (CFG_NAMESPACE_AWARE + /* Let's optimize non-validating case; DTD info we need + * is less if so (no need to store content specs for one)... + * plus, eventual functionality may be different too. + */ + | CFG_VALIDATE_AGAINST_DTD + /* Also, whether we support dtd++ or not may change construction + * of settings... (currently does not, but could) + */ + | CFG_SUPPORT_DTDPP + /* Also, basic xml:id support does matter -- xml:id attribute + * type is verified only if it's enabled + */ + | CFG_XMLID_TYPING + ); + URI sysRef = (sysId == null || sysId.length() == 0) ? null : + resolveExtSubsetPath(sysId); + + /* 29-Mar-2006, TSa: Apparently public ids are not always very + * unique and/or can be mismatched with system ids, resulting + * in false matches if using public ids. As a result, by default + * Woodstox does NOT rely on public ids, when matching. + */ + boolean usePublicId = (mConfigFlags & CFG_CACHE_DTDS_BY_PUBLIC_ID) != 0; + if (usePublicId && pubId != null && pubId.length() > 0) { + return DTDId.construct(pubId, sysRef, significantFlags, mXml11); + } + if (sysRef == null) { + return null; + } + return DTDId.constructFromSystemId(sysRef, significantFlags, mXml11); + } + + protected DTDId constructDtdId(URI sysId) throws IOException + { + int significantFlags = mConfigFlags & + (CFG_NAMESPACE_AWARE + /* Let's optimize non-validating case; DTD info we need + * is less if so (no need to store content specs for one) + */ + | CFG_VALIDATE_AGAINST_DTD + /* Also, whether we support dtd++ or not may change construction + * of settings... (currently does not, but could) + */ + | CFG_SUPPORT_DTDPP + ); + return DTDId.constructFromSystemId(sysId, significantFlags, mXml11); + } + + /* + /////////////////////////////////////////////////////////////////////// + // Private methods, DTD validation support + /////////////////////////////////////////////////////////////////////// + */ + + /** + * Method called by lower-level parsing code when invalid content + * (anything inside element with 'empty' content spec; text inside + * non-mixed element etc) is found during basic scanning. Note + * that actual DTD element structure problems are not reported + * through this method. + */ + @Override + protected void reportInvalidContent(int evtType) + throws XMLStreamException + { + switch (mVldContent) { + case XMLValidator.CONTENT_ALLOW_NONE: + reportValidationProblem(ErrorConsts.ERR_VLD_EMPTY, + mElementStack.getTopElementDesc(), + ErrorConsts.tokenTypeDesc(evtType)); + break; + case XMLValidator.CONTENT_ALLOW_WS: + case XMLValidator.CONTENT_ALLOW_WS_NONSTRICT: // should this ever occur? + reportValidationProblem(ErrorConsts.ERR_VLD_NON_MIXED, + mElementStack.getTopElementDesc(), null); + break; + case XMLValidator.CONTENT_ALLOW_VALIDATABLE_TEXT: + case XMLValidator.CONTENT_ALLOW_ANY_TEXT: + /* Not 100% sure if this should ever happen... depends on + * interpretation of 'any' content model? + */ + reportValidationProblem(ErrorConsts.ERR_VLD_ANY, + mElementStack.getTopElementDesc(), + ErrorConsts.tokenTypeDesc(evtType)); + break; + default: // should never occur: + throwParseError("Internal error: trying to report invalid content for "+evtType); + } + } +} diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/stax/package.html libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/stax/package.html --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/stax/package.html 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/stax/package.html 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,3 @@ + +This package contains miscellaneous classes that implement Woodstox. + diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/stax/WstxEventFactory.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/stax/WstxEventFactory.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/stax/WstxEventFactory.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/stax/WstxEventFactory.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,124 @@ +/* Woodstox XML processor + * + * Copyright (c) 2004 Tatu Saloranta, tatu.saloranta@iki.fi + * + * Licensed under the License specified in file LICENSE, included with + * the source code. + * You may not use this file except in compliance with the License. + * + * 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 com.ctc.wstx.stax; + +import java.util.Iterator; + +import javax.xml.namespace.NamespaceContext; +import javax.xml.namespace.QName; +import javax.xml.stream.*; +import javax.xml.stream.events.*; + +import org.codehaus.stax2.ri.Stax2EventFactoryImpl; + +import com.ctc.wstx.compat.QNameCreator; +import com.ctc.wstx.evt.*; + +/** + * Implementation of {@link XMLEventFactory} to be used with + * Woodstox. Contains minimal additions on top of Stax2 RI. + */ +public final class WstxEventFactory + extends Stax2EventFactoryImpl +{ + public WstxEventFactory() { + super(); + } + + /* + ///////////////////////////////////////////////////////////// + // XMLEventFactory API + ///////////////////////////////////////////////////////////// + */ + + //public Attribute createAttribute(QName name, String value) + //public Attribute createAttribute(String localName, String value) + //public Attribute createAttribute(String prefix, String nsURI, String localName, String value) + //public Characters createCData(String content); + //public Characters createCharacters(String content); + //public Comment createComment(String text); + + /** + * Note: constructing DTD events this way means that there will be no + * internal presentation of actual DTD; no parsing is implied by + * construction. + */ + @Override + public DTD createDTD(String dtd) { + return new WDTD(mLocation, dtd); + } + + //public EndDocument createEndDocument() + + //public EndElement createEndElement(QName name, Iterator namespaces) + //public EndElement createEndElement(String prefix, String nsURI, String localName) + //public EndElement createEndElement(String prefix, String nsURI, String localName, Iterator ns) + + //public EntityReference createEntityReference(String name, EntityDeclaration decl) + + //public Characters createIgnorableSpace(String content) + + //public Namespace createNamespace(String nsURI) + //public Namespace createNamespace(String prefix, String nsUri) + + //public ProcessingInstruction createProcessingInstruction(String target, String data) + + //public Characters createSpace(String content) + + //public StartDocument createStartDocument() + //public StartDocument createStartDocument(String encoding) + //public StartDocument createStartDocument(String encoding, String version) + //public StartDocument createStartDocument(String encoding, String version, boolean standalone) + + //public StartElement createStartElement(QName name, Iterator attr, Iterator ns) + + //public StartElement createStartElement(String prefix, String nsURI, String localName) + + //public StartElement createStartElement(String prefix, String nsURI, String localName, Iterator attr, Iterator ns) + + //public StartElement createStartElement(String prefix, String nsURI, String localName, Iterator attr, Iterator ns, NamespaceContext nsCtxt) + + /* + ///////////////////////////////////////////////////////////// + // Internal/helper methods + ///////////////////////////////////////////////////////////// + */ + + @Override + protected QName createQName(String nsURI, String localName) { + return new QName(nsURI, localName); + } + + @Override + protected QName createQName(String nsURI, String localName, String prefix) { + // [WSTX-174]: some old app servers missing 3-arg QName ctor + return QNameCreator.create(nsURI, localName, prefix); + } + + /** + * Must override this method to use a more efficient StartElement + * implementation + */ + @SuppressWarnings("unchecked") + @Override + protected StartElement createStartElement(QName name, Iterator attr, + Iterator ns, NamespaceContext ctxt) + { + return SimpleStartElement.construct(mLocation, name, + (Iterator) attr, + (Iterator) ns, ctxt); + } +} diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/stax/WstxInputFactory.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/stax/WstxInputFactory.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/stax/WstxInputFactory.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/stax/WstxInputFactory.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,856 @@ +/* Woodstox XML processor + * + * Copyright (c) 2004- Tatu Saloranta, tatu.saloranta@iki.fi + * + * Licensed under the License specified in the file LICENSE which is + * included with the source code. + * You may not use this file except in compliance with the License. + * + * 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 com.ctc.wstx.stax; + +import java.io.*; +import java.net.URL; + +import javax.xml.stream.*; +import javax.xml.stream.util.XMLEventAllocator; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.sax.SAXSource; +import javax.xml.transform.stream.StreamSource; + +import org.xml.sax.InputSource; +import org.codehaus.stax2.XMLEventReader2; +import org.codehaus.stax2.XMLInputFactory2; +import org.codehaus.stax2.XMLStreamReader2; +import org.codehaus.stax2.io.Stax2Source; +import org.codehaus.stax2.io.Stax2ByteArraySource; +import org.codehaus.stax2.ri.Stax2FilteredStreamReader; +import org.codehaus.stax2.ri.Stax2ReaderAdapter; +import org.codehaus.stax2.ri.evt.Stax2EventReaderAdapter; +import org.codehaus.stax2.ri.evt.Stax2FilteredEventReader; + +import com.ctc.wstx.api.ReaderConfig; +import com.ctc.wstx.api.WstxInputProperties; +import com.ctc.wstx.cfg.InputConfigFlags; +import com.ctc.wstx.cfg.XmlConsts; +import com.ctc.wstx.dtd.DTDId; +import com.ctc.wstx.dtd.DTDSubset; +import com.ctc.wstx.dom.WstxDOMWrappingReader; +import com.ctc.wstx.evt.DefaultEventAllocator; +import com.ctc.wstx.evt.WstxEventReader; +import com.ctc.wstx.exc.WstxIOException; +import com.ctc.wstx.io.*; +import com.ctc.wstx.sr.ValidatingStreamReader; +import com.ctc.wstx.sr.ReaderCreator; +import com.ctc.wstx.util.DefaultXmlSymbolTable; +import com.ctc.wstx.util.SimpleCache; +import com.ctc.wstx.util.SymbolTable; +import com.ctc.wstx.util.URLUtil; + +/** + * Factory for creating various Stax objects (stream/event reader, + * writer). + * + *

+ * Currently supported configuration options fall into two categories. First, + * all properties from {@link XMLInputFactory} (such as, say, + * {@link XMLInputFactory#IS_NAMESPACE_AWARE}) are at least recognized, and + * most are supported. Second, there are additional properties, defined in + * constant class {@link WstxInputProperties}, that are supported. + * See {@link WstxInputProperties} for further explanation of these 'custom' + * properties. + * + * @author Tatu Saloranta + */ +public class WstxInputFactory + extends XMLInputFactory2 + implements ReaderCreator, + InputConfigFlags +{ + /** + * Let's limit max size to 3/4 of 16k, since this corresponds + * to 64k main hash index. This should not be too low, but could + * perhaps be further lowered? + */ + final static int MAX_SYMBOL_TABLE_SIZE = 12000; + + /** + * Number of generations should not matter as much as raw + * size... but let's still cap it at some number. 500 generations + * seems reasonable for flushing (note: does not count uses + * where no new symbols were added). + */ + final static int MAX_SYMBOL_TABLE_GENERATIONS = 500; + + /* + /////////////////////////////////////////////////////////// + // Actual storage of configuration settings + /////////////////////////////////////////////////////////// + */ + + /** + * Current configurations for this factory + */ + protected final ReaderConfig mConfig; + + // // // Stax - mandated objects: + + protected XMLEventAllocator mAllocator = null; + + // // // Other configuration objects: + + protected SimpleCache mDTDCache = null; + + /* + /////////////////////////////////////////////////////////// + // Objects shared by actual parsers + /////////////////////////////////////////////////////////// + */ + + /** + * 'Root' symbol table, used for creating actual symbol table instances, + * but never as is. + */ + final static SymbolTable mRootSymbols = DefaultXmlSymbolTable.getInstance(); + static { + /* By default, let's enable intern()ing of names (element, attribute, + * prefixes) added to symbol table. This is likely to make some + * access (attr by QName) and comparison of element/attr names + * more efficient. Although it will add some overhead on adding + * new symbols to symbol table that should be rather negligible. + * + * Also note that always doing intern()ing allows for more efficient + * access during DTD validation. + */ + mRootSymbols.setInternStrings(true); + } + + /** + * Actual current 'parent' symbol table; concrete instances will be + * created from this instance using makeChild method + */ + private SymbolTable mSymbols = mRootSymbols; + + /* + /////////////////////////////////////////////////////////// + // Life-cycle: + /////////////////////////////////////////////////////////// + */ + + public WstxInputFactory() { + mConfig = ReaderConfig.createFullDefaults(); + } + + /** + * Method that can be used to ensure that specified symbol is + * contained in the shared symbol table. This may occasionally + * be useful in pre-populating symbols; although it is unlikely + * to be commonly useful. + * + * @since 4.2.1 + */ + public void addSymbol(String symbol) + { + synchronized (mSymbols) { + mSymbols.findSymbol(symbol); + } + } + + /* + /////////////////////////////////////////////////////////// + // ReaderCreator implementation + /////////////////////////////////////////////////////////// + */ + + // // // Configuration access methods: + + /** + * Method readers created by this factory call, if DTD caching is + * enabled, to see if an external DTD (subset) has been parsed + * and cached earlier. + */ + @Override + public synchronized DTDSubset findCachedDTD(DTDId id) + { + return (mDTDCache == null) ? null : mDTDCache.find(id); + } + + // // // Callbacks for updating shared information + + /** + * Method individual parsers call to pass back symbol table that + * they updated, which may be useful for other parser to reuse, instead + * of previous base symbol table. + *

+ * Note: parser is only to call this method, if passed-in symbol + * table was modified, ie new entry/ies were added in addition to + * whatever was in root table. + */ + @Override + public synchronized void updateSymbolTable(SymbolTable t) + { + SymbolTable curr = mSymbols; + /* Let's only add if table was direct descendant; this prevents + * siblings from keeping overwriting settings (multiple direct + * children have additional symbols added) + */ + if (t.isDirectChildOf(curr)) { + /* 07-Apr-2006, TSa: Actually, since huge symbol tables + * might become hindrance more than benefit (either in + * pathological cases with random names; or with very + * long running processes), let's actually limit both + * number of generations, and, more imporantly, maximum + * size of the symbol table + */ + if (t.size() > MAX_SYMBOL_TABLE_SIZE || + t.version() > MAX_SYMBOL_TABLE_GENERATIONS) { + // If so, we'll reset from bare defaults + mSymbols = mRootSymbols; +//System.err.println("DEBUG: !!!! XXXXX Symbol Table Flush: size: "+t.size()+"; version: "+t.version()); + } else { + mSymbols.mergeChild(t); +//System.err.println("Debug: new symbol table: size: "+t.size()+"; version: "+t.version()); + } + } +//else System.err.println("Debug: skipping symbol table update"); + } + + @Override + public synchronized void addCachedDTD(DTDId id, DTDSubset extSubset) + { + if (mDTDCache == null) { + mDTDCache = new SimpleCache(mConfig.getDtdCacheSize()); + } + mDTDCache.add(id, extSubset); + } + + /* + ///////////////////////////////////////////////////// + // Stax, XMLInputFactory; factory methods + ///////////////////////////////////////////////////// + */ + + // // // Filtered reader factory methods + + @Override + public XMLEventReader createFilteredReader(XMLEventReader reader, EventFilter filter) { + return new Stax2FilteredEventReader(Stax2EventReaderAdapter.wrapIfNecessary(reader), filter); + } + + @Override + public XMLStreamReader createFilteredReader(XMLStreamReader reader, StreamFilter filter) + throws XMLStreamException + { + Stax2FilteredStreamReader fr = new Stax2FilteredStreamReader(reader, filter); + /* [WSTX-111] As per Stax 1.0 TCK, apparently the filtered + * reader is expected to be automatically forwarded to the first + * acceptable event. This is different from the way RI works, but + * since specs don't say anything about filtered readers, let's + * consider TCK to be "more formal" for now, and implement that + * behavior. + */ + if (!filter.accept(fr)) { // START_DOCUMENT ok? + // Ok, nope, this should do the trick: + fr.next(); + } + return fr; + } + + // // // Event reader factory methods + + @Override + public XMLEventReader createXMLEventReader(InputStream in) + throws XMLStreamException + { + // false for auto-close, since caller has access to the input stream + return new WstxEventReader(createEventAllocator(), + createSR(null, in, null, true, false)); + } + + @Override + public XMLEventReader createXMLEventReader(InputStream in, String enc) + throws XMLStreamException + { + // false for auto-close, since caller has access to the input stream + return new WstxEventReader(createEventAllocator(), + createSR(null, in, enc, true, false)); + } + + @Override + public XMLEventReader createXMLEventReader(Reader r) + throws XMLStreamException + { + // false for auto-close, since caller has access to the input stream + return new WstxEventReader(createEventAllocator(), + createSR(null, r, true, false)); + } + + @Override + public XMLEventReader createXMLEventReader(javax.xml.transform.Source source) + throws XMLStreamException + { + return new WstxEventReader(createEventAllocator(), + createSR(source, true)); + } + + @Override + public XMLEventReader createXMLEventReader(String systemId, InputStream in) + throws XMLStreamException + { + // false for auto-close, since caller has access to the input stream + return new WstxEventReader(createEventAllocator(), + createSR(SystemId.construct(systemId), in, null, true, false)); + } + + @Override + public XMLEventReader createXMLEventReader(String systemId, Reader r) + throws XMLStreamException + { + // false for auto-close, since caller has access to the reader + return new WstxEventReader(createEventAllocator(), + createSR(SystemId.construct(systemId), r, true, false)); + } + + @Override + public XMLEventReader createXMLEventReader(XMLStreamReader sr) + throws XMLStreamException + { + return new WstxEventReader(createEventAllocator(), Stax2ReaderAdapter.wrapIfNecessary(sr)); + } + + // // // Stream reader factory methods + + @Override + public XMLStreamReader createXMLStreamReader(InputStream in) + throws XMLStreamException + { + // false for auto-close, since caller has access to the input stream + return createSR(null, in, null, false, false); + } + + @Override + public XMLStreamReader createXMLStreamReader(InputStream in, String enc) + throws XMLStreamException + { + // false for auto-close, since caller has access to the input stream + return createSR(null, in, enc, false, false); + } + + @Override + public XMLStreamReader createXMLStreamReader(Reader r) + throws XMLStreamException + { + // false for auto-close, since caller has access to the reader + return createSR(null, r, false, false); + } + + @Override + public XMLStreamReader createXMLStreamReader(javax.xml.transform.Source src) + throws XMLStreamException + { + // false -> not for event. No definition for auto-close; called method will decide + return createSR(src, false); + } + + @Override + public XMLStreamReader createXMLStreamReader(String systemId, InputStream in) + throws XMLStreamException + { + // false for auto-close, since caller has access to the input stream + return createSR(SystemId.construct(systemId), in, null, false, false); + } + + @Override + public XMLStreamReader createXMLStreamReader(String systemId, Reader r) + throws XMLStreamException + { + // false for auto-close, since caller has access to the Reader + return createSR(SystemId.construct(systemId), r, false, false); + } + + /* + /////////////////////////////////////////////////////////// + // Stax, XMLInputFactory; generic accessors/mutators + /////////////////////////////////////////////////////////// + */ + + @Override + public Object getProperty(String name) + { + Object ob = mConfig.getProperty(name); + + if (ob == null) { + if (name.equals(XMLInputFactory.ALLOCATOR)) { + // Event allocator not available via J2ME subset... + return getEventAllocator(); + } + } + return ob; + } + + @Override + public void setProperty(String propName, Object value) + { + if (!mConfig.setProperty(propName, value)) { + if (XMLInputFactory.ALLOCATOR.equals(propName)) { + setEventAllocator((XMLEventAllocator) value); + } + } + } + + @Override + public XMLEventAllocator getEventAllocator() { + return mAllocator; + } + + @Override + public XMLReporter getXMLReporter() { + return mConfig.getXMLReporter(); + } + + @Override + public XMLResolver getXMLResolver() { + return mConfig.getXMLResolver(); + } + + @Override + public boolean isPropertySupported(String name) { + return mConfig.isPropertySupported(name); + } + + @Override + public void setEventAllocator(XMLEventAllocator allocator) { + mAllocator = allocator; + } + + @Override + public void setXMLReporter(XMLReporter r) { + mConfig.setXMLReporter(r); + } + + /** + * Note: it's preferable to use Wstx-specific + * {@link ReaderConfig#setEntityResolver} + * instead, if possible, since this just wraps passed in resolver. + */ + @Override + public void setXMLResolver(XMLResolver r) { + mConfig.setXMLResolver(r); + } + + /* + /////////////////////////////////////////////////////////// + // Stax2 implementation + /////////////////////////////////////////////////////////// + */ + + // // // Stax2, additional factory methods: + + @Override + public XMLEventReader2 createXMLEventReader(URL src) + throws XMLStreamException + { + /* true for auto-close, since caller has no access to the underlying + * input stream created from the URL + */ + return new WstxEventReader(createEventAllocator(), + createSR(createPrivateConfig(), src, true, true)); + } + + @Override + public XMLEventReader2 createXMLEventReader(File f) + throws XMLStreamException + { + /* true for auto-close, since caller has no access to the underlying + * input stream created from the File + */ + return new WstxEventReader(createEventAllocator(), + createSR(f, true, true)); + } + + @Override + public XMLStreamReader2 createXMLStreamReader(URL src) + throws XMLStreamException + { + /* true for auto-close, since caller has no access to the underlying + * input stream created from the URL + */ + return createSR(createPrivateConfig(), src, false, true); + } + + /** + * Convenience factory method that allows for parsing a document + * stored in the specified file. + */ + @Override + public XMLStreamReader2 createXMLStreamReader(File f) + throws XMLStreamException + { + /* true for auto-close, since caller has no access to the underlying + * input stream created from the File + */ + return createSR(f, false, true); + } + + // // // Stax2 "Profile" mutators + + @Override + public void configureForXmlConformance() { + mConfig.configureForXmlConformance(); + } + + @Override + public void configureForConvenience() { + mConfig.configureForConvenience(); + } + + @Override + public void configureForSpeed() { + mConfig.configureForSpeed(); + } + + @Override + public void configureForLowMemUsage() { + mConfig.configureForLowMemUsage(); + } + + @Override + public void configureForRoundTripping() { + mConfig.configureForRoundTripping(); + } + + /* + /////////////////////////////////////////////////////////// + // Woodstox-specific configuration access + /////////////////////////////////////////////////////////// + */ + + public ReaderConfig getConfig() { + return mConfig; + } + + /* + /////////////////////////////////////////////////////////// + // Internal methods: + /////////////////////////////////////////////////////////// + */ + + /** + * Bottleneck method used for creating ALL full stream reader instances + * (via other createSR() methods and directly) + * + * @param forER True, if the reader is being constructed to be used + * by an event reader; false if it is not (or the purpose is not known) + * @param autoCloseInput Whether the underlying input source should be + * actually closed when encountering EOF, or when close() + * is called. Will be true for input sources that are automatically + * managed by stream reader (input streams created for + * {@link java.net.URL} and {@link java.io.File} arguments, or when + * configuration settings indicate auto-closing is to be enabled + * (the default value is false as per Stax 1.0 specs). + */ + @SuppressWarnings("resource") + private XMLStreamReader2 doCreateSR(ReaderConfig cfg, SystemId systemId, + InputBootstrapper bs, boolean forER, boolean autoCloseInput) + throws XMLStreamException + { + /* Automatic closing of input: will happen always for some input + * types (ones application has no direct access to; but can also + * be explicitly enabled. + */ + if (!autoCloseInput) { + autoCloseInput = cfg.willAutoCloseInput(); + } + + Reader r; + try { + r = bs.bootstrapInput(cfg, true, XmlConsts.XML_V_UNKNOWN); + if (bs.declaredXml11()) { + cfg.enableXml11(true); + } + } catch (IOException ie) { + throw new WstxIOException(ie); + } + + /* null -> no public id available + * false -> don't close the reader when scope is closed. + */ + BranchingReaderSource input = InputSourceFactory.constructDocumentSource + (cfg, bs, null, systemId, r, autoCloseInput); + + return ValidatingStreamReader.createValidatingStreamReader(input, this, cfg, bs, forER); + } + + /** + * Method that is eventually called to create a (full) stream read + * instance. + *

+ * Note: defined as public method because it needs to be called by + * SAX implementation. + * + * @param systemId System id used for this reader (if any) + * @param bs Bootstrapper to use for creating actual underlying + * physical reader + * @param forER Flag to indicate whether it will be used via + * Event API (will affect some configuration settings), true if it + * will be, false if not (or not known) + * @param autoCloseInput Whether the underlying input source should be + * actually closed when encountering EOF, or when close() + * is called. Will be true for input sources that are automatically + * managed by stream reader (input streams created for + * {@link java.net.URL} and {@link java.io.File} arguments, or when + * configuration settings indicate auto-closing is to be enabled + * (the default value is false as per Stax 1.0 specs). + */ + public XMLStreamReader2 createSR(ReaderConfig cfg, String systemId, InputBootstrapper bs, + boolean forER, boolean autoCloseInput) + throws XMLStreamException + { + // 16-Aug-2004, TSa: Maybe we have a context? + URL src = cfg.getBaseURL(); + + // If not, maybe we can derive it from system id? + if ((src == null) && (systemId != null && systemId.length() > 0)) { + try { + src = URLUtil.urlFromSystemId(systemId); + } catch (IOException ie) { + throw new WstxIOException(ie); + } + } + return doCreateSR(cfg, SystemId.construct(systemId, src), bs, forER, autoCloseInput); + } + + public XMLStreamReader2 createSR(ReaderConfig cfg, SystemId systemId, InputBootstrapper bs, + boolean forER, boolean autoCloseInput) + throws XMLStreamException + { + return doCreateSR(cfg, systemId, bs, forER, autoCloseInput); + } + + @SuppressWarnings("resource") + protected XMLStreamReader2 createSR(SystemId systemId, InputStream in, String enc, + boolean forER, boolean autoCloseInput) + throws XMLStreamException + { + // sanity check: + if (in == null) { + throw new IllegalArgumentException("Null InputStream is not a valid argument"); + } + ReaderConfig cfg = createPrivateConfig(); + if (enc == null || enc.length() == 0) { + return createSR(cfg, systemId, StreamBootstrapper.getInstance + (null, systemId, in), forER, autoCloseInput); + } + + /* !!! 17-Feb-2006, TSa: We don't yet know if it's xml 1.0 or 1.1; + * so have to specify 1.0 (which is less restrictive WRT input + * streams). Would be better to let bootstrapper deal with it + * though: + */ + Reader r = DefaultInputResolver.constructOptimizedReader(cfg, in, false, enc); + return createSR(cfg, systemId, ReaderBootstrapper.getInstance + (null, systemId, r, enc), forER, autoCloseInput); + } + + protected XMLStreamReader2 createSR(ReaderConfig cfg, URL src, + boolean forER, boolean autoCloseInput) + throws XMLStreamException + { + final SystemId systemId = SystemId.construct(src); + try { + return createSR(cfg, systemId, URLUtil.inputStreamFromURL(src), + forER, autoCloseInput); + } catch (IOException ioe) { + throw new WstxIOException(ioe); + } + } + + private XMLStreamReader2 createSR(ReaderConfig cfg, SystemId systemId, + InputStream in, boolean forER, boolean autoCloseInput) + throws XMLStreamException + { + return doCreateSR(cfg, systemId, + StreamBootstrapper.getInstance(null, systemId, in), + forER, autoCloseInput); + } + + protected XMLStreamReader2 createSR(SystemId systemId, Reader r, + boolean forER, boolean autoCloseInput) + throws XMLStreamException + { + return createSR(createPrivateConfig(), systemId, + ReaderBootstrapper.getInstance + (null, systemId, r, null), forER, autoCloseInput); + } + + @SuppressWarnings("resource") + protected XMLStreamReader2 createSR(File f, boolean forER, boolean autoCloseInput) + throws XMLStreamException + { + ReaderConfig cfg = createPrivateConfig(); + try { + /* 18-Nov-2008, TSa: If P_BASE_URL is set, and File reference is + * relative, let's resolve against base... + */ + if (!f.isAbsolute()) { + URL base = cfg.getBaseURL(); + if (base != null) { + URL src = new URL(base, f.getPath()); + return createSR(cfg, SystemId.construct(src), URLUtil.inputStreamFromURL(src), + forER, autoCloseInput); + } + } + final SystemId systemId = SystemId.construct(URLUtil.toURL(f)); + return createSR(cfg, systemId, new FileInputStream(f), forER, autoCloseInput); + + } catch (IOException ie) { + throw new WstxIOException(ie); + } + } + + /** + * Another internal factory method, used when dealing with a generic + * Source base type. One thing worth noting is that 'auto-closing' + * will be enabled if the input source or Reader is constructed (and + * thus owned) by Woodstox. + * + * @param forER True, if the reader is being constructed to be used + * by an event reader; false if it is not (or the purpose is not known) + */ + @SuppressWarnings("resource") + protected XMLStreamReader2 createSR(javax.xml.transform.Source src, + boolean forER) + throws XMLStreamException + { + ReaderConfig cfg = createPrivateConfig(); + Reader r = null; + InputStream in = null; + String pubId = null; + String sysId = null; + String encoding = null; + boolean autoCloseInput; + + InputBootstrapper bs = null; + + if (src instanceof Stax2Source) { + Stax2Source ss = (Stax2Source) src; + sysId = ss.getSystemId(); + pubId = ss.getPublicId(); + encoding = ss.getEncoding(); + + try { + /* 11-Nov-2008, TSa: Let's add optimized handling for byte-block + * source + */ + if (src instanceof Stax2ByteArraySource) { + Stax2ByteArraySource bas = (Stax2ByteArraySource) src; + bs = StreamBootstrapper.getInstance(pubId, SystemId.construct(sysId), bas.getBuffer(), bas.getBufferStart(), bas.getBufferEnd()); + } else { + in = ss.constructInputStream(); + if (in == null) { + r = ss.constructReader(); + } + } + } catch (IOException ioe) { + throw new WstxIOException(ioe); + } + /* Caller has no direct access to stream/reader, Woodstox + * owns it and thus has to close too + */ + autoCloseInput = true; + } else if (src instanceof StreamSource) { + StreamSource ss = (StreamSource) src; + sysId = ss.getSystemId(); + pubId = ss.getPublicId(); + in = ss.getInputStream(); + if (in == null) { + r = ss.getReader(); + } + /* Caller still has access to stream/reader; no need to + * force auto-close-input + */ + autoCloseInput = cfg.willAutoCloseInput(); + } else if (src instanceof SAXSource) { + SAXSource ss = (SAXSource) src; + /* 28-Jan-2006, TSa: Not a complete implementation, but maybe + * even this might help... + */ + sysId = ss.getSystemId(); + InputSource isrc = ss.getInputSource(); + if (isrc != null) { + encoding = isrc.getEncoding(); + in = isrc.getByteStream(); + if (in == null) { + r = isrc.getCharacterStream(); + } + } + /* Caller still has access to stream/reader; no need to + * force auto-close-input + */ + autoCloseInput = cfg.willAutoCloseInput(); + } else if (src instanceof DOMSource) { + DOMSource domSrc = (DOMSource) src; + // SymbolTable not used by the DOM-based 'reader': + return WstxDOMWrappingReader.createFrom(domSrc, cfg); + } else { + throw new IllegalArgumentException("Can not instantiate Stax reader for XML source type "+src.getClass()+" (unrecognized type)"); + } + if (bs == null) { // may have already created boostrapper... + if (r != null) { + bs = ReaderBootstrapper.getInstance(pubId, SystemId.construct(sysId), r, encoding); + } else if (in != null) { + bs = StreamBootstrapper.getInstance(pubId, SystemId.construct(sysId), in); + } else if (sysId != null && sysId.length() > 0) { + /* 26-Dec-2008, TSa: If we must construct URL from system id, + * it means caller will not have access to resulting + * stream, thus we will force auto-closing. + */ + autoCloseInput = true; + try { + return createSR(cfg, URLUtil.urlFromSystemId(sysId), + forER, autoCloseInput); + } catch (IOException ioe) { + throw new WstxIOException(ioe); + } + } else { + throw new XMLStreamException("Can not create Stax reader for the Source passed -- neither reader, input stream nor system id was accessible; can not use other types of sources (like embedded SAX streams)"); + } + } + return createSR(cfg, sysId, bs, forER, autoCloseInput); + } + + protected XMLEventAllocator createEventAllocator() + { + // Explicitly set allocate? + if (mAllocator != null) { + return mAllocator.newInstance(); + } + + /* Complete or fast one? Note: standard allocator is designed + * in such a way that newInstance() need not be called (calling + * it wouldn't do anything, anyway) + */ + return mConfig.willPreserveLocation() ? + DefaultEventAllocator.getDefaultInstance() + : DefaultEventAllocator.getFastInstance(); + } + + /** + * Method called to construct a copy of the factory's configuration + * object, such that two will be unlinked (changes to one are not + * reflect in the other). + *

+ * Note: only public so that other woodstox components outside of + * this package can access it. + */ + public ReaderConfig createPrivateConfig() + { + return mConfig.createNonShared(mSymbols.makeChild()); + } +} diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/stax/WstxOutputFactory.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/stax/WstxOutputFactory.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/stax/WstxOutputFactory.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/stax/WstxOutputFactory.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,387 @@ +/* Woodstox XML processor + * + * Copyright (c) 2004- Tatu Saloranta, tatu.saloranta@iki.fi + * + * Licensed under the License specified in the file LICENSE which is + * included with the source code. + * You may not use this file except in compliance with the License. + * + * 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 com.ctc.wstx.stax; + +import java.io.IOException; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.io.Writer; + +import javax.xml.stream.XMLEventWriter; +import javax.xml.stream.XMLOutputFactory; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamWriter; +import javax.xml.transform.Result; +import javax.xml.transform.dom.DOMResult; +import javax.xml.transform.sax.SAXResult; +import javax.xml.transform.stream.StreamResult; + +import org.codehaus.stax2.XMLOutputFactory2; +import org.codehaus.stax2.XMLStreamWriter2; +import org.codehaus.stax2.io.Stax2Result; +import org.codehaus.stax2.ri.Stax2EventWriterImpl; +import org.codehaus.stax2.ri.Stax2WriterAdapter; + +import com.ctc.wstx.api.WriterConfig; +import com.ctc.wstx.api.WstxOutputProperties; +import com.ctc.wstx.cfg.OutputConfigFlags; +import com.ctc.wstx.dom.WstxDOMWrappingWriter; +import com.ctc.wstx.exc.WstxIOException; +import com.ctc.wstx.io.CharsetNames; +import com.ctc.wstx.io.UTF8Writer; +import com.ctc.wstx.sw.AsciiXmlWriter; +import com.ctc.wstx.sw.BufferingXmlWriter; +import com.ctc.wstx.sw.ISOLatin1XmlWriter; +import com.ctc.wstx.sw.NonNsStreamWriter; +import com.ctc.wstx.sw.RepairingNsStreamWriter; +import com.ctc.wstx.sw.SimpleNsStreamWriter; +import com.ctc.wstx.sw.XmlWriter; +import com.ctc.wstx.util.URLUtil; + +/** + * Implementation of {@link XMLOutputFactory} for Wstx. + *

+ * TODO: + *

    + *
  • Implement outputter that creates SAX events (DOM-backed + * writer exists as of Woodstox 3.2) + *
  • + *
+ */ +public class WstxOutputFactory + extends XMLOutputFactory2 + implements OutputConfigFlags +{ + /* + /////////////////////////////////////////////////////////// + // Actual storage of configuration settings + /////////////////////////////////////////////////////////// + */ + + protected final WriterConfig mConfig; + + /* + /////////////////////////////////////////////////////////// + // Life-cycle + /////////////////////////////////////////////////////////// + */ + + public WstxOutputFactory() { + mConfig = WriterConfig.createFullDefaults(); + } + + /* + /////////////////////////////////////////////////////////// + // XMLOutputFactory API + /////////////////////////////////////////////////////////// + */ + + @Override + public XMLEventWriter createXMLEventWriter(OutputStream out) + throws XMLStreamException + { + return createXMLEventWriter(out, null); + } + + @Override + public XMLEventWriter createXMLEventWriter(OutputStream out, String enc) + throws XMLStreamException + { + if (out == null) { + throw new IllegalArgumentException("Null OutputStream is not a valid argument"); + } + return new Stax2EventWriterImpl(createSW(out, null, enc, false)); + } + + @Override + public XMLEventWriter createXMLEventWriter(javax.xml.transform.Result result) + throws XMLStreamException + { + return new Stax2EventWriterImpl(createSW(result)); + } + + @Override + public XMLEventWriter createXMLEventWriter(Writer w) + throws XMLStreamException + { + if (w == null) { + throw new IllegalArgumentException("Null Writer is not a valid argument"); + } + return new Stax2EventWriterImpl(createSW(null, w, null, false)); + } + + @Override + public XMLStreamWriter createXMLStreamWriter(OutputStream out) + throws XMLStreamException + { + return createXMLStreamWriter(out, null); + } + + @Override + public XMLStreamWriter createXMLStreamWriter(OutputStream out, String enc) + throws XMLStreamException + { + if (out == null) { + throw new IllegalArgumentException("Null OutputStream is not a valid argument"); + } + return createSW(out, null, enc, false); + } + + @Override + public XMLStreamWriter createXMLStreamWriter(javax.xml.transform.Result result) + throws XMLStreamException + { + return createSW(result); + } + + @Override + public XMLStreamWriter createXMLStreamWriter(Writer w) + throws XMLStreamException + { + if (w == null) { + throw new IllegalArgumentException("Null Writer is not a valid argument"); + } + return createSW(null, w, null, false); + } + + @Override + public Object getProperty(String name) { + return mConfig.getProperty(name); + } + + @Override + public boolean isPropertySupported(String name) { + return mConfig.isPropertySupported(name); + } + + @Override + public void setProperty(String name, Object value) + { + mConfig.setProperty(name, value); + } + + /* + /////////////////////////////////////////////////////////// + // Stax2 extensions + /////////////////////////////////////////////////////////// + */ + + // // // Stax2 additional (encoding-aware) factory methods + + @Override + public XMLEventWriter createXMLEventWriter(Writer w, String enc) + throws XMLStreamException + { + return new Stax2EventWriterImpl(createSW(null, w, enc, false)); + } + + @Override + public XMLEventWriter createXMLEventWriter(XMLStreamWriter sw) + throws XMLStreamException + { + XMLStreamWriter2 sw2 = Stax2WriterAdapter.wrapIfNecessary(sw); + return new Stax2EventWriterImpl(sw2); + } + + @Override + public XMLStreamWriter2 createXMLStreamWriter(Writer w, String enc) + throws XMLStreamException + { + return createSW(null, w, enc, false); + } + + // // // Stax2 "Profile" mutators + + @Override + public void configureForXmlConformance() { + mConfig.configureForXmlConformance(); + } + + @Override + public void configureForRobustness() { + mConfig.configureForRobustness(); + } + + @Override + public void configureForSpeed() { + mConfig.configureForSpeed(); + } + + /* + /////////////////////////////////////////////////////////// + // Woodstox-specific configuration access + /////////////////////////////////////////////////////////// + */ + + public WriterConfig getConfig() { + return mConfig; + } + + /* + /////////////////////////////////////////////////////////// + // Internal methods: + /////////////////////////////////////////////////////////// + */ + + /** + * Bottleneck factory method used internally; needs to take care of passing + * proper settings to stream writer. + * + * @param requireAutoClose Whether this result will always require + * auto-close be enabled (true); or only if application has + * requested it (false) + */ + @SuppressWarnings("resource") + private XMLStreamWriter2 createSW(OutputStream out, Writer w, String enc, + boolean requireAutoClose) + throws XMLStreamException + { + /* Need to ensure that the configuration object is not shared + * any more; otherwise later changes via factory could be + * visible half-way through output... + */ + WriterConfig cfg = mConfig.createNonShared(); + XmlWriter xw; + + boolean autoCloseOutput = requireAutoClose || mConfig.willAutoCloseOutput(); + + if (w == null) { + if (enc == null) { + enc = WstxOutputProperties.DEFAULT_OUTPUT_ENCODING; + } else { + /* Canonical ones are interned, so we may have + * normalized encoding already... + */ + if (enc != CharsetNames.CS_UTF8 + && enc != CharsetNames.CS_ISO_LATIN1 + && enc != CharsetNames.CS_US_ASCII) { + enc = CharsetNames.normalize(enc); + } + } + + try { + if (enc == CharsetNames.CS_UTF8) { + w = new UTF8Writer(cfg, out, autoCloseOutput); + xw = new BufferingXmlWriter(w, cfg, enc, autoCloseOutput, out, 16); + } else if (enc == CharsetNames.CS_ISO_LATIN1) { + xw = new ISOLatin1XmlWriter(out, cfg, autoCloseOutput); + } else if (enc == CharsetNames.CS_US_ASCII) { + xw = new AsciiXmlWriter(out, cfg, autoCloseOutput); + } else { + w = new OutputStreamWriter(out, enc); + xw = new BufferingXmlWriter(w, cfg, enc, autoCloseOutput, out, -1); + } + } catch (IOException ex) { + throw new XMLStreamException(ex); + } + } else { + // we may still be able to figure out the encoding: + if (enc == null) { + enc = CharsetNames.findEncodingFor(w); + } + try { + xw = new BufferingXmlWriter(w, cfg, enc, autoCloseOutput, null, -1); + } catch (IOException ex) { + throw new XMLStreamException(ex); + } + } + + return createSW(enc, cfg, xw); + } + + /** + * Called by {@link #createSW(OutputStream, Writer, String, boolean)} after all of the nessesary configuration + * logic is complete. + */ + protected XMLStreamWriter2 createSW(String enc, WriterConfig cfg, XmlWriter xw) { + if (cfg.willSupportNamespaces()) { + if (cfg.automaticNamespacesEnabled()) { + return new RepairingNsStreamWriter(xw, enc, cfg); + } + return new SimpleNsStreamWriter(xw, enc, cfg); + } + return new NonNsStreamWriter(xw, enc, cfg); + } + + @SuppressWarnings("resource") + private XMLStreamWriter2 createSW(Result res) + throws XMLStreamException + { + OutputStream out = null; + Writer w = null; + String encoding = null; + boolean requireAutoClose; + String sysId = null; + + if (res instanceof Stax2Result) { + Stax2Result sr = (Stax2Result) res; + try { + out = sr.constructOutputStream(); + if (out == null) { + w = sr.constructWriter(); + } + } catch (IOException ioe) { + throw new WstxIOException(ioe); + } + // yes, it's required since caller has no access to stream/writer: + requireAutoClose = true; + } else if (res instanceof StreamResult) { + StreamResult sr = (StreamResult) res; + out = sr.getOutputStream(); + sysId = sr.getSystemId(); + if (out == null) { + w = sr.getWriter(); + } + /* Caller owns it, only auto-close if requested to do so: + * (except that for system-id-only, it'll still be required, + * see code below) + */ + requireAutoClose = false; + } else if (res instanceof SAXResult) { + SAXResult sr = (SAXResult) res; + sysId = sr.getSystemId(); + if (sysId == null || sysId.length() == 0) { + throw new XMLStreamException("Can not create a stream writer for a SAXResult that does not have System Id (support for using SAX input source not implemented)"); + } + requireAutoClose = true; + } else if (res instanceof DOMResult) { + return WstxDOMWrappingWriter.createFrom(mConfig.createNonShared(), (DOMResult) res); + } else { + throw new IllegalArgumentException("Can not instantiate a writer for XML result type "+res.getClass()+" (unrecognized type)"); + } + + if (out != null) { + return createSW(out, null, encoding, requireAutoClose); + } + if (w != null) { + return createSW(null, w, encoding, requireAutoClose); + } + if (sysId != null && sysId.length() > 0) { + /* 26-Dec-2008, TSa: If we must construct URL from system id, + * it means caller will not have access to resulting + * stream, thus we will force auto-closing. + */ + requireAutoClose = true; + try { + out = URLUtil.outputStreamFromURL(URLUtil.urlFromSystemId(sysId)); + } catch (IOException ioe) { + throw new WstxIOException(ioe); + } + return createSW(out, null, encoding, requireAutoClose); + } + throw new XMLStreamException("Can not create Stax writer for passed-in Result -- neither writer, output stream or system id was accessible"); + } +} diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/sw/AsciiXmlWriter.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/sw/AsciiXmlWriter.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/sw/AsciiXmlWriter.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/sw/AsciiXmlWriter.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,767 @@ +/* Woodstox XML processor + * + * Copyright (c) 2004- Tatu Saloranta, tatu.saloranta@iki.fi + * + * Licensed under the License specified in file LICENSE, included with + * the source code. + * You may not use this file except in compliance with the License. + * + * 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 com.ctc.wstx.sw; + +import java.io.*; + +import javax.xml.stream.XMLStreamException; + +import com.ctc.wstx.api.WriterConfig; +import com.ctc.wstx.io.CharsetNames; + +/** + * Concrete implementation of {@link EncodingXmlWriter} used when output + * is to be encoded using 7-bit ascii (US-ASCII) encoding. + */ +public final class AsciiXmlWriter + extends EncodingXmlWriter +{ + public AsciiXmlWriter(OutputStream out, WriterConfig cfg, boolean autoclose) + throws IOException + { + super(out, cfg, CharsetNames.CS_US_ASCII, autoclose); + } + + @Override + public void writeRaw(char[] cbuf, int offset, int len) + throws IOException + { + if (mSurrogate != 0) { + throwUnpairedSurrogate(); + } + + int ptr = mOutputPtr; + while (len > 0) { + int max = mOutputBuffer.length - ptr; + if (max < 1) { // output buffer full? + mOutputPtr = ptr; + flushBuffer(); + ptr = 0; + max = mOutputBuffer.length; + } + // How much can we output? + if (max > len) { + max = len; + } + if (mCheckContent) { + for (int inEnd = offset + max; offset < inEnd; ++offset) { + int c = cbuf[offset]; + if (c < 32) { + if (c == '\n') { + // !!! TBI: line nr + } else if (c == '\r') { + // !!! TBI: line nr (and skipping \n that may follow) + } else if (c != '\t') { + mOutputPtr = ptr; + c = handleInvalidChar(c); + } + } else if (c > 0x7E) { + mOutputPtr = ptr; + if (c > 0x7F) { // 0x7F invalid in xml11 + handleInvalidAsciiChar(c); + } else if (mXml11) { + c = handleInvalidChar(c); + } + } + mOutputBuffer[ptr++] = (byte) c; + } + } else { + for (int inEnd = offset + max; offset < inEnd; ++offset) { + mOutputBuffer[ptr++] = (byte) cbuf[offset]; + } + } + len -= max; + } + mOutputPtr = ptr; + } + + @Override + public void writeRaw(String str, int offset, int len) + throws IOException + { + if (mSurrogate != 0) { + throwUnpairedSurrogate(); + } + int ptr = mOutputPtr; + while (len > 0) { + int max = mOutputBuffer.length - ptr; + if (max < 1) { // output buffer full? + mOutputPtr = ptr; + flushBuffer(); + ptr = 0; + max = mOutputBuffer.length; + } + // How much can we output? + if (max > len) { + max = len; + } + if (mCheckContent) { + for (int inEnd = offset + max; offset < inEnd; ++offset) { + int c = str.charAt(offset); + if (c < 32) { + if (c == '\n') { + // !!! TBI: line nr + } else if (c == '\r') { + // !!! TBI: line nr (and skipping \n that may follow) + } else if (c != '\t') { + mOutputPtr = ptr; + c = handleInvalidChar(c); + } + } else if (c > 0x7E) { + mOutputPtr = ptr; + if (c > 0x7F) { // 0x7F invalid in xml11 + handleInvalidAsciiChar(c); + } else if (mXml11) { + c = handleInvalidChar(c); + } + } + mOutputBuffer[ptr++] = (byte) c; + } + } else { + for (int inEnd = offset + max; offset < inEnd; ++offset) { + mOutputBuffer[ptr++] = (byte) str.charAt(offset); + } + } + len -= max; + } + mOutputPtr = ptr; + } + + @Override + protected void writeAttrValue(String data) + throws IOException + { + int offset = 0; + int len = data.length(); + int ptr = mOutputPtr; + + main_loop: + while (len > 0) { + int max = mOutputBuffer.length - ptr; + if (max < 1) { // output buffer full? + mOutputPtr = ptr; + flushBuffer(); + ptr = 0; + max = mOutputBuffer.length; + } + // Do we start with a surrogate? + if (mSurrogate != 0) { + int sec = data.charAt(offset++); + sec = calcSurrogate(sec); + mOutputPtr = ptr; + ptr = writeAsEntity(sec); + --len; + continue main_loop; + } + // How much can we output? + if (max > len) { + max = len; + } + inner_loop: + for (int inEnd = offset + max; offset < inEnd; ) { + int c = data.charAt(offset++); + if (c < 32) { + /* Need to quote all white space except for regular + * space chars, to preserve them (round-tripping) + */ + if (c == '\r') { + if (!mEscapeCR) { + mOutputBuffer[ptr++] = (byte) c; + continue; + } + } else if (c != '\n' && c != '\t') { + if (mCheckContent) { + if (!mXml11 || c == 0) { + c = handleInvalidChar(c); + mOutputBuffer[ptr++] = (byte) c; + continue; + } + } + } + // fall-through to char entity output + } else if (c < 0x7F) { + if (c != '<' && c != '&' && c != '"') { + mOutputBuffer[ptr++] = (byte) c; + continue; + } + // otherwise fall back on quoting + } else { + // Surrogate? + if (c >= SURR1_FIRST && c <= SURR2_LAST) { + mSurrogate = c; + // Last char needs special handling: + if (offset == inEnd) { + break inner_loop; + } + c = calcSurrogate(data.charAt(offset++)); + // Let's fall down to entity output + } + } + /* Has to be escaped as char entity; as such, also need + * to re-calc max. continguous data we can output + */ + mOutputPtr = ptr; + ptr = writeAsEntity(c); + len = data.length() - offset; + continue main_loop; + } + len -= max; + } + mOutputPtr = ptr; + } + + @Override + protected void writeAttrValue(char[] data, int offset, int len) + throws IOException + { + int ptr = mOutputPtr; + + main_loop: + while (len > 0) { + int max = mOutputBuffer.length - ptr; + if (max < 1) { // output buffer full? + mOutputPtr = ptr; + flushBuffer(); + ptr = 0; + max = mOutputBuffer.length; + } + // Do we start with a surrogate? + if (mSurrogate != 0) { + int sec = data[offset++]; + sec = calcSurrogate(sec); + mOutputPtr = ptr; + ptr = writeAsEntity(sec); + --len; + continue main_loop; + } + // How much can we output? + if (max > len) { + max = len; + } + inner_loop: + for (int inEnd = offset + max; offset < inEnd; ) { + int c = data[offset++]; + if (c < 32) { + /* Need to quote all white space except for regular + * space chars, to preserve them (round-tripping) + */ + if (c == '\r') { + if (!mEscapeCR) { + mOutputBuffer[ptr++] = (byte) c; + continue; + } + } else if (c != '\n' && c != '\t') { + if (mCheckContent) { + if (!mXml11 || c == 0) { + c = handleInvalidChar(c); + mOutputBuffer[ptr++] = (byte) c; + continue; + } + } + } + // fall-through to char entity output + } else if (c < 0x7F) { + if (c != '<' && c != '&' && c != '"') { + mOutputBuffer[ptr++] = (byte) c; + continue; + } + // otherwise fall back on quoting + } else { + // Surrogate? + if (c >= SURR1_FIRST && c <= SURR2_LAST) { + mSurrogate = c; + // Last char needs special handling: + if (offset == inEnd) { + break inner_loop; + } + c = calcSurrogate(data[offset++]); + // Let's fall down to entity output + } + } + /* Has to be escaped as char entity; as such, also need + * to re-calc max. contiguous data we can output + */ + mOutputPtr = ptr; + ptr = writeAsEntity(c); + max -= (inEnd - offset); // since we didn't loop completely + break inner_loop; + } + len -= max; + } + mOutputPtr = ptr; + } + + @Override + protected int writeCDataContent(String data) + throws IOException + { + // Note: mSurrogate can not be non-zero at this point, no need to check + + int offset = 0; + int len = data.length(); + if (!mCheckContent) { + writeRaw(data, offset, len); + return -1; + } + int ptr = mOutputPtr; + + main_loop: + while (len > 0) { + int max = mOutputBuffer.length - ptr; + if (max < 1) { // output buffer full? + mOutputPtr = ptr; + flushBuffer(); + ptr = 0; + max = mOutputBuffer.length; + } + // How much can we output? + if (max > len) { + max = len; + } + for (int inEnd = offset + max; offset < inEnd; ) { + int c = data.charAt(offset++); + if (c < 32) { + if (c == '\n') { + // !!! TBI: line nr + } else if (c == '\r') { + // !!! TBI: line nr (and skipping \n that may follow) + } else if (c != '\t') { + mOutputPtr = ptr; + c = handleInvalidChar(c); + } + } else if (c > 0x7E) { + mOutputPtr = ptr; + if (c > 0x7F) { // 0x7F invalid in xml11 + handleInvalidAsciiChar(c); + } else if (mXml11) { + c = handleInvalidChar(c); + } + } else if (c == '>') { // embedded "]]>"? + if (offset > 2 && data.charAt(offset-2) == ']' + && data.charAt(offset-3) == ']') { + if (!mFixContent) { + return offset-3; + } + /* Relatively easy fix; just need to close this + * section, and open a new one... + */ + mOutputPtr = ptr; + writeCDataEnd(); + writeCDataStart(); + writeAscii(BYTE_GT); + ptr = mOutputPtr; + /* No guarantees there's as much free room in the + * output buffer, thus, need to restart loop: + */ + len = data.length() - offset; + continue main_loop; + } + } + mOutputBuffer[ptr++] = (byte) c; + } + len -= max; + } + mOutputPtr = ptr; + return -1; + } + + @Override + protected int writeCDataContent(char[] cbuf, int start, int len) + throws IOException + { + // Note: mSurrogate can not be non-zero at this point, no need to check + + if (!mCheckContent) { + writeRaw(cbuf, start, len); + return -1; + } + + int ptr = mOutputPtr; + int offset = start; + + while (len > 0) { + int max = mOutputBuffer.length - ptr; + if (max < 1) { // output buffer full? + mOutputPtr = ptr; + flushBuffer(); + ptr = 0; + max = mOutputBuffer.length; + } + // How much can we output? + if (max > len) { + max = len; + } + inner_loop: + for (int inEnd = offset + max; offset < inEnd; ) { + int c = cbuf[offset++]; + if (c < 32) { + if (c == '\n') { + // !!! TBI: line nr + } else if (c == '\r') { + // !!! TBI: line nr (and skipping \n that may follow) + } else if (c != '\t') { + mOutputPtr = ptr; + c = handleInvalidChar(c); + } + } else if (c > 0x7E) { + mOutputPtr = ptr; + if (c > 0x7F) { // 0x7F invalid in xml11 + handleInvalidAsciiChar(c); + } else if (mXml11) { + c = handleInvalidChar(c); + } + } else if (c == '>') { // embedded "]]>"? + if (offset >= (start+3) && cbuf[offset-2] == ']' + && cbuf[offset-3] == ']') { + if (!mFixContent) { + return offset-3; + } + /* Relatively easy fix; just need to close this + * section, and open a new one... + */ + mOutputPtr = ptr; + writeCDataEnd(); + writeCDataStart(); + writeAscii(BYTE_GT); + ptr = mOutputPtr; + /* No guarantees there's as much free room in the + * output buffer, thus, need to restart loop: + */ + max -= (inEnd - offset); + break inner_loop; + } + } + mOutputBuffer[ptr++] = (byte) c; + } + len -= max; + } + mOutputPtr = ptr; + return -1; + } + + @Override + protected int writeCommentContent(String data) + throws IOException + { + // Note: mSurrogate can not be non-zero at this point, no need to check + + int offset = 0; + int len = data.length(); + if (!mCheckContent) { + writeRaw(data, offset, len); + return -1; + } + + int ptr = mOutputPtr; + + while (len > 0) { + int max = mOutputBuffer.length - ptr; + if (max < 1) { // output buffer full? + mOutputPtr = ptr; + flushBuffer(); + ptr = 0; + max = mOutputBuffer.length; + } + // How much can we output? + if (max > len) { + max = len; + } + inner_loop: + for (int inEnd = offset + max; offset < inEnd; ) { + int c = data.charAt(offset++); + if (c < 32) { + if (c == '\n') { + // !!! TBI: line nr + } else if (c == '\r') { + // !!! TBI: line nr (and skipping \n that may follow) + } else if (c != '\t') { + mOutputPtr = ptr; + c = handleInvalidChar(c); + } + } else if (c > 0x7E) { + mOutputPtr = ptr; + if (c > 0x7F) { // 0x7F invalid in xml11 + handleInvalidAsciiChar(c); + } else if (mXml11) { + c = handleInvalidChar(c); + } + } else if (c == '-') { // embedded "--"? + if (offset > 1 && data.charAt(offset-2) == '-') { + if (!mFixContent) { + return offset-2; + } + /* Quite easy to fix: just add an extra space + * in front. There will be room for that char; + * but may need to take that the following '-' + * also fits. + */ + mOutputBuffer[ptr++] = ' '; + if (ptr >= mOutputBuffer.length) { // whops. need to flush + mOutputPtr = ptr; + flushBuffer(); + ptr = 0; + } + mOutputBuffer[ptr++] = BYTE_HYPHEN; + /* Also, since we did output an extra char, better + * restart the loop (since max calculation is now + * off) + */ + max -= (inEnd - offset); + break inner_loop; + } + } + mOutputBuffer[ptr++] = (byte) c; + } + len -= max; + } + mOutputPtr = ptr; + return -1; + } + + @Override + protected int writePIData(String data) + throws IOException, XMLStreamException + { + // Note: mSurrogate can not be non-zero at this point, no need to check + + int offset = 0; + int len = data.length(); + if (!mCheckContent) { + writeRaw(data, offset, len); + return -1; + } + + int ptr = mOutputPtr; + while (len > 0) { + int max = mOutputBuffer.length - ptr; + if (max < 1) { // output buffer full? + mOutputPtr = ptr; + flushBuffer(); + ptr = 0; + max = mOutputBuffer.length; + } + // How much can we output? + if (max > len) { + max = len; + } + for (int inEnd = offset + max; offset < inEnd; ++offset) { + int c = data.charAt(offset); + if (c < 32) { + if (c == '\n') { + // !!! TBI: line nr + } else if (c == '\r') { + // !!! TBI: line nr (and skipping \n that may follow) + } else if (c != '\t') { + mOutputPtr = ptr; + c = handleInvalidChar(c); + } + } else if (c > 0x7E) { + mOutputPtr = ptr; + if (c > 0x7F) { // 0x7F invalid in xml11 + handleInvalidAsciiChar(c); + } else if (mXml11) { + c = handleInvalidChar(c); + } + } else if (c == '>') { // enclosed end marker ("?>")? + if (offset > 0 && data.charAt(offset-1) == '?') { + return offset-2; + } + } + mOutputBuffer[ptr++] = (byte) c; + } + len -= max; + } + mOutputPtr = ptr; + return -1; + } + + @Override + protected void writeTextContent(String data) throws IOException + { + int offset = 0; + int len = data.length(); + + main_loop: + while (len > 0) { + int max = mOutputBuffer.length - mOutputPtr; + if (max < 1) { // output buffer full? + flushBuffer(); + max = mOutputBuffer.length; + } + // Do we start with a surrogate? + if (mSurrogate != 0) { + int sec = data.charAt(offset++); + sec = calcSurrogate(sec); + writeAsEntity(sec); + --len; + continue main_loop; + } + // How much can we output? + if (max > len) { + max = len; + } + inner_loop: + for (int inEnd = offset + max; offset < inEnd; ) { + int c = data.charAt(offset++); + if (c < 32) { + if (c == '\n' || c == '\t') { // TODO: line count + mOutputBuffer[mOutputPtr++] = (byte) c; + continue; + } else if (c == '\r') { + if (!mEscapeCR) { + mOutputBuffer[mOutputPtr++] = (byte) c; + continue; + } + } else if (!mXml11 || c == 0) { // ok in xml1.1, as entity + if (mCheckContent) { + c = handleInvalidChar(c); + mOutputBuffer[mOutputPtr++] = (byte) c; + continue; + } + // otherwise... well, I guess we can just escape it + } + // \r, or xml1.1 + other whitespace, need to escape + } else if (c < 0x7F) { + if (c != '<' && c != '&') { + if (c != '>' || (offset > 1 && data.charAt(offset-2) != ']')) { + mOutputBuffer[mOutputPtr++] = (byte) c; + continue; + } + } + // otherwise fall back on quoting + } else { + // Surrogate? + if (c >= SURR1_FIRST && c <= SURR2_LAST) { + mSurrogate = c; + // Last char needs special handling: + if (offset == inEnd) { + break inner_loop; + } + c = calcSurrogate(data.charAt(offset++)); + // Let's fall down to entity output + } + } + /* Has to be escaped as char entity; as such, also need + * to re-calc max. continguous data we can output + */ + writeAsEntity(c); + len = data.length() - offset; + continue main_loop; + } + len -= max; + } + } + + @Override + protected void writeTextContent(char[] cbuf, int offset, int len) + throws IOException + { + main_loop: + while (len > 0) { + int max = mOutputBuffer.length - mOutputPtr; + if (max < 1) { // output buffer full? + flushBuffer(); + max = mOutputBuffer.length; + } + // Do we start with a surrogate? + if (mSurrogate != 0) { + int sec = cbuf[offset++]; + sec = calcSurrogate(sec); + writeAsEntity(sec); + --len; + continue main_loop; + } + // How much can we output? + if (max > len) { + max = len; + } + inner_loop: + for (int inEnd = offset + max; offset < inEnd; ) { + int c = cbuf[offset++]; + if (c < 32) { + if (c == '\n' || c == '\t') { // TODO: line count + mOutputBuffer[mOutputPtr++] = (byte) c; + continue; + } else if (c == '\r') { + if (!mEscapeCR) { + mOutputBuffer[mOutputPtr++] = (byte) c; + continue; + } + } else if (!mXml11 || c == 0) { // ok in xml1.1, as entity + if (mCheckContent) { + c = handleInvalidChar(c); + mOutputBuffer[mOutputPtr++] = (byte) c; + continue; + } + // otherwise... well, I guess we can just try to escape it + } + // \r, or xml1.1 + other whitespace, need to escape + } else if (c < 0x7F) { + if (c !='<' && c != '&') { + /* Since we can be conservative, it doesn't matter + * if second check is not exact + */ + if (c != '>' || (offset > 1 && cbuf[offset-2] != ']')) { + mOutputBuffer[mOutputPtr++] = (byte) c; + continue; + } + } + // otherwise fall back on quoting + } else { + // Surrogate? + if (c >= SURR1_FIRST && c <= SURR2_LAST) { + mSurrogate = c; + // Last char needs special handling: + if (offset == inEnd) { + break inner_loop; + } + c = calcSurrogate(cbuf[offset++]); + // Let's fall down to entity output + } + } + /* Has to be escaped as char entity; as such, also need + * to re-calc max. continguous data we can output + */ + writeAsEntity(c); + max -= (inEnd - offset); + break inner_loop; + } + len -= max; + } + } + + /* + //////////////////////////////////////////////////// + // Internal methods + //////////////////////////////////////////////////// + */ + + protected void handleInvalidAsciiChar(int c) + throws IOException + { + // First, let's flush any output we may have, to make debugging easier + flush(); + + /* 17-May-2006, TSa: Would really be useful if we could throw + * XMLStreamExceptions; esp. to indicate actual output location. + * However, this causes problem with methods that call us and + * can only throw IOExceptions (when invoked via Writer proxy). + * Need to figure out how to resolve this. + */ + throw new IOException("Invalid XML character (0x"+Integer.toHexString(c)+"); can only be output using character entity when using US-ASCII encoding"); + } +} + diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/sw/BaseNsStreamWriter.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/sw/BaseNsStreamWriter.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/sw/BaseNsStreamWriter.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/sw/BaseNsStreamWriter.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,772 @@ +/* Woodstox XML processor + * + * Copyright (c) 2004- Tatu Saloranta, tatu.saloranta@iki.fi + * + * Licensed under the License specified in the file LICENSE, + * included with the source code. + * You may not use this file except in compliance with the License. + * + * 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 com.ctc.wstx.sw; + +import java.io.IOException; + +import javax.xml.XMLConstants; +import javax.xml.namespace.NamespaceContext; +import javax.xml.namespace.QName; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.events.StartElement; + +import org.codehaus.stax2.ri.typed.AsciiValueEncoder; + +import com.ctc.wstx.api.EmptyElementHandler; +import com.ctc.wstx.api.WriterConfig; +import com.ctc.wstx.cfg.ErrorConsts; +import com.ctc.wstx.cfg.XmlConsts; +import com.ctc.wstx.exc.WstxIOException; +import com.ctc.wstx.util.DefaultXmlSymbolTable; + +/** + * Mid-level base class of namespace-aware stream writers. Contains + * shared functionality between repairing and non-repairing implementations. + */ +public abstract class BaseNsStreamWriter + extends TypedStreamWriter +{ + /* + //////////////////////////////////////////////////// + // Constants + //////////////////////////////////////////////////// + */ + + final protected static String sPrefixXml = DefaultXmlSymbolTable.getXmlSymbol(); + + final protected static String sPrefixXmlns = DefaultXmlSymbolTable.getXmlnsSymbol(); + + final protected static String ERR_NSDECL_WRONG_STATE = + "Trying to write a namespace declaration when there is no open start element."; + + /* + //////////////////////////////////////////////////// + // Configuration (options, features) + //////////////////////////////////////////////////// + */ + + // // // Additional specific config flags base class doesn't have + + /** + * True, if writer needs to automatically output namespace declarations + * (we are in repairing mode) + */ + final protected boolean mAutomaticNS; + + final protected EmptyElementHandler mEmptyElementHandler; + + /* + //////////////////////////////////////////////////// + // State information + //////////////////////////////////////////////////// + */ + + protected SimpleOutputElement mCurrElem = SimpleOutputElement.createRoot(); + + /** + * Optional "root" namespace context that application can set. If so, + * it can be used to lookup namespace/prefix mappings + */ + protected NamespaceContext mRootNsContext = null; + + /* + //////////////////////////////////////////////////// + // Pool for recycling SimpleOutputElement instances + //////////////////////////////////////////////////// + */ + + /* Note: although pooling of cheap objects like SimpleOutputElement + * is usually not a good idea, here profiling showed it to be a + * significant improvement. As long as instances are ONLY reused + * within context of a single writer, they stay in cheap ("Eden") + * GC area, and thus it should be a win. + */ + protected SimpleOutputElement mOutputElemPool = null; + + /** + * Although pooled objects are small, let's limit the pool size + * nonetheless, to optimize memory usage for deeply nested + * documents. In general, even just low number like 4 levels gets + * decent return, but 8 should get 99% hit rate. + */ + final static int MAX_POOL_SIZE = 8; + + protected int mPoolSize = 0; + + /* + //////////////////////////////////////////////////// + // Life-cycle (ctors) + //////////////////////////////////////////////////// + */ + + public BaseNsStreamWriter(XmlWriter xw, String enc, WriterConfig cfg, + boolean repairing) + { + super(xw, enc, cfg); + mAutomaticNS = repairing; + mEmptyElementHandler = cfg.getEmptyElementHandler(); + } + + /* + //////////////////////////////////////////////////// + // XMLStreamWriter API + //////////////////////////////////////////////////// + */ + + @Override + public NamespaceContext getNamespaceContext() { + return mCurrElem; + } + + @Override + public String getPrefix(String uri) { + return mCurrElem.getPrefix(uri); + } + + @Override + public abstract void setDefaultNamespace(String uri) + throws XMLStreamException; + + /** + *

+ * Note: Root namespace context works best if automatic prefix + * creation ("namespace/prefix repairing" in StAX lingo) is enabled. + */ + @Override + public void setNamespaceContext(NamespaceContext ctxt) + throws XMLStreamException + { + // This is only allowed before root element output: + if (mState != STATE_PROLOG) { + throwOutputError("Called setNamespaceContext() after having already output root element."); + } + + mRootNsContext = ctxt; + mCurrElem.setRootNsContext(ctxt); + } + + @Override + public void setPrefix(String prefix, String uri) + throws XMLStreamException + { + if (prefix == null) { + throw new NullPointerException("Can not pass null 'prefix' value"); + } + // Are we actually trying to set the default namespace? + if (prefix.length() == 0) { + setDefaultNamespace(uri); + return; + } + if (uri == null) { + throw new NullPointerException("Can not pass null 'uri' value"); + } + + /* 25-Sep-2004, TSa: Let's check that "xml" and "xmlns" are not + * (re-)defined to any other value, nor that value they + * are bound to are bound to other prefixes. + */ + /* 01-Apr-2005, TSa: And let's not leave it optional: such + * bindings should never succeed. + */ + // ... perhaps it really should be optional though? + { + if (prefix.equals(sPrefixXml)) { // prefix "xml" + if (!uri.equals(XMLConstants.XML_NS_URI)) { + throwOutputError(ErrorConsts.ERR_NS_REDECL_XML, uri); + } + } else if (prefix.equals(sPrefixXmlns)) { // prefix "xmlns" + if (!uri.equals(XMLConstants.XMLNS_ATTRIBUTE_NS_URI)) { + throwOutputError(ErrorConsts.ERR_NS_REDECL_XMLNS, uri); + } + } else { + // Neither of prefixes.. but how about URIs? + if (uri.equals(XMLConstants.XML_NS_URI)) { + throwOutputError(ErrorConsts.ERR_NS_REDECL_XML_URI, prefix); + } else if (uri.equals(XMLConstants.XMLNS_ATTRIBUTE_NS_URI)) { + throwOutputError(ErrorConsts.ERR_NS_REDECL_XMLNS_URI, prefix); + } + } + + /* 05-Feb-2005, TSa: Also, as per namespace specs; the 'empty' + * namespace URI can not be bound as a non-default namespace + * (ie. for any actual prefix) + */ + /* 04-Feb-2005, TSa: Namespaces 1.1 does allow this, though, + * so for xml 1.1 documents we need to allow it + */ + if (!mXml11) { + if (uri.length() == 0) { + throwOutputError(ErrorConsts.ERR_NS_EMPTY); + } + } + } + + doSetPrefix(prefix, uri); + } + + /** + * It's assumed calling this method implies caller just wants to add + * an attribute that does not belong to any namespace; as such no + * namespace checking or prefix generation is needed. + */ + @Override + public void writeAttribute(String localName, String value) + throws XMLStreamException + { + // No need to set mAnyOutput, nor close the element + if (!mStartElementOpen && mCheckStructure) { + reportNwfStructure(ErrorConsts.WERR_ATTR_NO_ELEM); + } + doWriteAttr(localName, null, null, value); + } + + @Override + public abstract void writeAttribute(String nsURI, String localName, String value) + throws XMLStreamException; + + @Override + public abstract void writeAttribute(String prefix, String nsURI, + String localName, String value) + throws XMLStreamException; + + /** + *

+ * Note: It is assumed caller just wants the element to belong to whatever + * is the current default namespace. + */ + @Override + public void writeEmptyElement(String localName) + throws XMLStreamException + { + checkStartElement(localName, null); + if (mValidator != null) { + mValidator.validateElementStart(localName, XmlConsts.ELEM_NO_NS_URI, XmlConsts.ELEM_NO_PREFIX); + } + mEmptyElement = true; + if (mOutputElemPool != null) { + SimpleOutputElement newCurr = mOutputElemPool; + mOutputElemPool = newCurr.reuseAsChild(mCurrElem, localName); + --mPoolSize; + mCurrElem = newCurr; + } else { + mCurrElem = mCurrElem.createChild(localName); + } + doWriteStartTag(localName); + + } + + @Override + public void writeEmptyElement(String nsURI, String localName) + throws XMLStreamException + { + writeStartOrEmpty(localName, nsURI); + mEmptyElement = true; + } + + @Override + public void writeEmptyElement(String prefix, String localName, String nsURI) + throws XMLStreamException + { + writeStartOrEmpty(prefix, localName, nsURI); + mEmptyElement = true; + } + + @Override + public void writeEndElement() + throws XMLStreamException + { + doWriteEndTag(null, mCfgAutomaticEmptyElems); + } + + /** + * This method is assumed to just use default namespace (if any), + * and no further checks should be done. + */ + @Override + public void writeStartElement(String localName) + throws XMLStreamException + { + checkStartElement(localName, null); + if (mValidator != null) { + mValidator.validateElementStart(localName, XmlConsts.ELEM_NO_NS_URI, XmlConsts.ELEM_NO_PREFIX); + } + mEmptyElement = false; + if (mOutputElemPool != null) { + SimpleOutputElement newCurr = mOutputElemPool; + mOutputElemPool = newCurr.reuseAsChild(mCurrElem, localName); + --mPoolSize; + mCurrElem = newCurr; + } else { + mCurrElem = mCurrElem.createChild(localName); + } + + doWriteStartTag(localName); + } + + @Override + public void writeStartElement(String nsURI, String localName) + throws XMLStreamException + { + writeStartOrEmpty(localName, nsURI); + mEmptyElement = false; + } + + @Override + public void writeStartElement(String prefix, String localName, String nsURI) + throws XMLStreamException + { + writeStartOrEmpty(prefix, localName, nsURI); + mEmptyElement = false; + } + + @Override + protected void writeTypedAttribute(String prefix, String nsURI, String localName, + AsciiValueEncoder enc) + throws XMLStreamException + { + if (!mStartElementOpen) { + throwOutputError(ErrorConsts.WERR_ATTR_NO_ELEM); + } + if (mCheckAttrs) { // still need to ensure no duplicate attrs? + mCurrElem.checkAttrWrite(nsURI, localName); + } + try { + if (mValidator == null) { + if (prefix == null || prefix.length() == 0) { + mWriter.writeTypedAttribute(localName, enc); + } else { + mWriter.writeTypedAttribute(prefix, localName, enc); + } + } else { + mWriter.writeTypedAttribute + (prefix, localName, nsURI, enc, mValidator, getCopyBuffer()); + } + } catch (IOException ioe) { + throw new WstxIOException(ioe); + } + } + + /* + //////////////////////////////////////////////////// + // Remaining XMLStreamWriter2 methods (StAX2) + //////////////////////////////////////////////////// + */ + + /** + * Similar to {@link #writeEndElement}, but never allows implicit + * creation of empty elements. + */ + @Override + public void writeFullEndElement() + throws XMLStreamException + { + doWriteEndTag(null, false); + } + + /* + //////////////////////////////////////////////////// + // Remaining ValidationContext methods (StAX2) + //////////////////////////////////////////////////// + */ + + @Override + public QName getCurrentElementName() { + return mCurrElem.getName(); + } + + @Override + public String getNamespaceURI(String prefix) { + return mCurrElem.getNamespaceURI(prefix); + } + + /* + ////////////////////////////////////////////////////////// + // Implementations for base-class defined abstract methods + ////////////////////////////////////////////////////////// + */ + + /** + * Method called by {@link javax.xml.stream.XMLEventWriter} implementation + * (instead of the version + * that takes no argument), so that we can verify it does match the + * start element, if necessary + */ + @Override + public void writeEndElement(QName name) + throws XMLStreamException + { + doWriteEndTag(mCheckStructure ? name : null, mCfgAutomaticEmptyElems); + } + + /** + * Method called to close an open start element, when another + * main-level element (not namespace declaration or attribute) + * is being output; except for end element which is handled differently. + * + * @param emptyElem If true, the element being closed is an empty + * element; if false, a separate stand-alone start element. + */ + @Override + protected void closeStartElement(boolean emptyElem) + throws XMLStreamException + { + mStartElementOpen = false; + + try { + if (emptyElem) { + mWriter.writeStartTagEmptyEnd(); + } else { + mWriter.writeStartTagEnd(); + } + } catch (IOException ioe) { + throw new WstxIOException(ioe); + } + + if (mValidator != null) { + mVldContent = mValidator.validateElementAndAttributes(); + } + + // Need bit more special handling for empty elements... + if (emptyElem) { + SimpleOutputElement curr = mCurrElem; + mCurrElem = curr.getParent(); + if (mCurrElem.isRoot()) { // Did we close the root? (isRoot() returns true for the virtual "document node") + mState = STATE_EPILOG; + } + if (mValidator != null) { + mVldContent = mValidator.validateElementEnd + (curr.getLocalName(), curr.getNamespaceURI(), curr.getPrefix()); + } + if (mPoolSize < MAX_POOL_SIZE) { + curr.addToPool(mOutputElemPool); + mOutputElemPool = curr; + ++mPoolSize; + } + } + } + + @Override + protected String getTopElementDesc() { + return mCurrElem.getNameDesc(); + } + + /* + //////////////////////////////////////////////////// + // Package methods sub-classes may also need + //////////////////////////////////////////////////// + */ + + /** + * Method that is called to ensure that we can start writing an + * element, both from structural point of view, and from syntactic + * (close previously open start element, if any). + */ + protected void checkStartElement(String localName, String prefix) + throws XMLStreamException + { + // Need to finish an open start element? + if (mStartElementOpen) { + closeStartElement(mEmptyElement); + } else if (mState == STATE_PROLOG) { + verifyRootElement(localName, prefix); + } else if (mState == STATE_EPILOG) { + if (mCheckStructure) { + String name = (prefix == null || prefix.length() == 0) ? + localName : (prefix + ":" + localName); + reportNwfStructure(ErrorConsts.WERR_PROLOG_SECOND_ROOT, name); + } + /* When outputting a fragment, need to reset this to the + * tree. No point in trying to verify the root element? + */ + mState = STATE_TREE; + } + } + + protected final void doWriteAttr(String localName, String nsURI, String prefix, + String value) + throws XMLStreamException + { + if (mCheckAttrs) { // still need to ensure no duplicate attrs? + mCurrElem.checkAttrWrite(nsURI, localName); + } + if (mValidator != null) { + // No need to get it normalized... even if validator does normalize + // it, we don't use that for anything + mValidator.validateAttribute(localName, nsURI, prefix, value); + } + try { + int vlen = value.length(); + // Worthwhile to make a local copy? + if (vlen >= ATTR_MIN_ARRAYCOPY) { + char[] buf = mCopyBuffer; + if (buf == null) { + mCopyBuffer = buf = mConfig.allocMediumCBuffer(DEFAULT_COPYBUFFER_LEN); + } + /* Ok, and in unlikely case of attribute values longer than + * buffer... for now, let's just skip those case + */ + if (vlen <= buf.length) { + value.getChars(0, vlen, buf, 0); + if (prefix != null && prefix.length() > 0) { + mWriter.writeAttribute(prefix, localName, buf, 0, vlen); + } else { + mWriter.writeAttribute(localName, buf, 0, vlen); + } + return; + } + } + if (prefix != null && prefix.length() > 0) { + mWriter.writeAttribute(prefix, localName, value); + } else { + mWriter.writeAttribute(localName, value); + } + } catch (IOException ioe) { + throw new WstxIOException(ioe); + } + } + + protected final void doWriteAttr(String localName, String nsURI, String prefix, + char[] buf, int start, int len) + throws XMLStreamException + { + if (mCheckAttrs) { // still need to ensure no duplicate attrs? + mCurrElem.checkAttrWrite(nsURI, localName); + } + if (mValidator != null) { + // No need to get it normalized... even if validator does normalize + // it, we don't use that for anything + mValidator.validateAttribute(localName, nsURI, prefix, buf, start, len); + } + try { + if (prefix != null && prefix.length() > 0) { + mWriter.writeAttribute(prefix, localName, buf, start, len); + } else { + mWriter.writeAttribute(localName, buf, start, len); + } + } catch (IOException ioe) { + throw new WstxIOException(ioe); + } + } + + protected void doWriteNamespace(String prefix, String nsURI) + throws XMLStreamException + { + try { + int vlen = nsURI.length(); + // Worthwhile to make a local copy? + if (vlen >= ATTR_MIN_ARRAYCOPY) { + char[] buf = mCopyBuffer; + if (buf == null) { + mCopyBuffer = buf = mConfig.allocMediumCBuffer(DEFAULT_COPYBUFFER_LEN); + } + // Let's not bother with too long, though + if (vlen <= buf.length) { + nsURI.getChars(0, vlen, buf, 0); + mWriter.writeAttribute(XMLConstants.XMLNS_ATTRIBUTE, prefix, buf, 0, vlen); + return; + } + } + mWriter.writeAttribute(XMLConstants.XMLNS_ATTRIBUTE, prefix, nsURI); + } catch (IOException ioe) { + throw new WstxIOException(ioe); + } + } + + protected void doWriteDefaultNs(String nsURI) + throws XMLStreamException + { + try { + int vlen = (nsURI == null) ? 0 : nsURI.length(); + // Worthwhile to make a local copy? + if (vlen >= ATTR_MIN_ARRAYCOPY) { + char[] buf = mCopyBuffer; + if (buf == null) { + mCopyBuffer = buf = mConfig.allocMediumCBuffer(DEFAULT_COPYBUFFER_LEN); + } + // Let's not bother with too long, though + if (vlen <= buf.length) { + nsURI.getChars(0, vlen, buf, 0); + mWriter.writeAttribute(XMLConstants.XMLNS_ATTRIBUTE, buf, 0, vlen); + return; + } + } + mWriter.writeAttribute(XMLConstants.XMLNS_ATTRIBUTE, nsURI); + } catch (IOException ioe) { + throw new WstxIOException(ioe); + } + } + + protected final void doWriteStartTag(String localName) + throws XMLStreamException + { + mAnyOutput = true; + mStartElementOpen = true; + try { + mWriter.writeStartTagStart(localName); + } catch (IOException ioe) { + throw new WstxIOException(ioe); + } + } + + protected final void doWriteStartTag(String prefix, String localName) + throws XMLStreamException + { + mAnyOutput = true; + mStartElementOpen = true; + try { + boolean hasPrefix = (prefix != null && prefix.length() > 0); + if (hasPrefix) { + mWriter.writeStartTagStart(prefix, localName); + } else { + mWriter.writeStartTagStart(localName); + } + } catch (IOException ioe) { + throw new WstxIOException(ioe); + } + } + + /** + * + * @param expName Name that the closing element should have; null + * if whatever is in stack should be used + * @param allowEmpty If true, is allowed to create the empty element + * if the closing element was truly empty; if false, has to write + * the full empty element no matter what + */ + protected void doWriteEndTag(QName expName, boolean allowEmpty) + throws XMLStreamException + { + /* First of all, do we need to close up an earlier empty element? + * (open start element that was not created via call to + * writeEmptyElement gets handled later on) + */ + if (mStartElementOpen && mEmptyElement) { + mEmptyElement = false; + closeStartElement(true); + } + + // Better have something to close... (to figure out what to close) + if (mState != STATE_TREE) { + // Have to always throw exception... don't necessarily know the name + reportNwfStructure("No open start element, when trying to write end element"); + } + + SimpleOutputElement thisElem = mCurrElem; + String prefix = thisElem.getPrefix(); + String localName = thisElem.getLocalName(); + String nsURI = thisElem.getNamespaceURI(); + + // Ok, and then let's pop that element from the stack + mCurrElem = thisElem.getParent(); + // Need to return the instance to pool? + if (mPoolSize < MAX_POOL_SIZE) { + thisElem.addToPool(mOutputElemPool); + mOutputElemPool = thisElem; + ++mPoolSize; + } + + if (mCheckStructure) { + if (expName != null) { + // Let's only check the local name, for now... + if (!localName.equals(expName.getLocalPart())) { + /* Only gets called when trying to output an XMLEvent... in + * which case names can actually be compared + */ + reportNwfStructure("Mismatching close element local name, '"+localName+"'; expected '"+expName.getLocalPart()+"'."); + } + } + } + + /* Now, do we have an unfinished start element (created via + * writeStartElement() earlier)? + */ + if (mStartElementOpen) { + /* Can't/shouldn't call closeStartElement, but need to do same + * processing. Thus, this is almost identical to closeStartElement: + */ + if (mValidator != null) { + /* Note: return value is not of much use, since the + * element will be closed right away... + */ + mVldContent = mValidator.validateElementAndAttributes(); + } + mStartElementOpen = false; + try { + //If an EmptyElementHandler is provided use it to determine if allowEmpty is set + if (mEmptyElementHandler != null) { + allowEmpty = mEmptyElementHandler.allowEmptyElement(prefix, localName, nsURI, allowEmpty); + } + // We could write an empty element, implicitly? + if (allowEmpty) { + mWriter.writeStartTagEmptyEnd(); + if (mCurrElem.isRoot()) { + mState = STATE_EPILOG; + } + if (mValidator != null) { + mVldContent = mValidator.validateElementEnd(localName, nsURI, prefix); + } + return; + } + // Nah, need to close open elem, and then output close elem + mWriter.writeStartTagEnd(); + } catch (IOException ioe) { + throw new WstxIOException(ioe); + } + } + + try { + mWriter.writeEndTag(prefix, localName); + } catch (IOException ioe) { + throw new WstxIOException(ioe); + } + + if (mCurrElem.isRoot()) { + mState = STATE_EPILOG; + } + + // Ok, time to validate... + if (mValidator != null) { + mVldContent = mValidator.validateElementEnd(localName, nsURI, prefix); + } + } + + /* + //////////////////////////////////////////////////// + // More abstract methods for sub-classes to implement + //////////////////////////////////////////////////// + */ + + public abstract void doSetPrefix(String prefix, String uri) + throws XMLStreamException; + + @Override + public abstract void writeDefaultNamespace(String nsURI) + throws XMLStreamException; + + @Override + public abstract void writeNamespace(String prefix, String nsURI) + throws XMLStreamException; + + @Override + public abstract void writeStartElement(StartElement elem) + throws XMLStreamException; + + protected abstract void writeStartOrEmpty(String localName, String nsURI) + throws XMLStreamException; + + protected abstract void writeStartOrEmpty(String prefix, String localName, String nsURI) + throws XMLStreamException; +} diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/sw/BaseStreamWriter.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/sw/BaseStreamWriter.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/sw/BaseStreamWriter.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/sw/BaseStreamWriter.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,1812 @@ +/* Woodstox XML processor + * + * Copyright (c) 2004- Tatu Saloranta, tatu.saloranta@iki.fi + * + * Licensed under the License specified in file LICENSE, included with + * the source code. + * You may not use this file except in compliance with the License. + * + * 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 com.ctc.wstx.sw; + +import java.io.IOException; +import java.io.Writer; +import java.text.MessageFormat; + +import javax.xml.namespace.NamespaceContext; +import javax.xml.namespace.QName; +import javax.xml.stream.Location; +import javax.xml.stream.XMLReporter; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamWriter; + +// unfortunate dependencies to StAX events: +import javax.xml.stream.events.Characters; +import javax.xml.stream.events.StartElement; + +import org.codehaus.stax2.DTDInfo; +import org.codehaus.stax2.XMLStreamLocation2; +import org.codehaus.stax2.XMLStreamReader2; +import org.codehaus.stax2.ri.Stax2WriterImpl; +import org.codehaus.stax2.validation.*; + +import com.ctc.wstx.api.*; +import com.ctc.wstx.cfg.ErrorConsts; +import com.ctc.wstx.cfg.OutputConfigFlags; +import com.ctc.wstx.cfg.XmlConsts; +import com.ctc.wstx.exc.*; +import com.ctc.wstx.io.WstxInputLocation; +import com.ctc.wstx.sr.StreamReaderImpl; +import com.ctc.wstx.sr.AttributeCollector; +import com.ctc.wstx.sr.InputElementStack; +import com.ctc.wstx.util.DataUtil; +import com.ctc.wstx.util.StringUtil; + +/** + * Base class for {@link XMLStreamWriter} implementations Woodstox has. + * Contains partial stream writer implementation, plus utility methods + * shared by concrete implementation classes. Main reason for such + * abstract base class is to allow other parts of Woodstox core to refer + * to any of stream writer implementations in general way. + */ +public abstract class BaseStreamWriter + extends Stax2WriterImpl + implements ValidationContext, OutputConfigFlags +{ + protected final static int STATE_PROLOG = 1; + protected final static int STATE_TREE = 2; + protected final static int STATE_EPILOG = 3; + + protected final static char CHAR_SPACE = ' '; + + /** + * This constant defines minimum length of a String, for which it + * is beneficial to do an intermediate copy (using String.getChars()), + * and iterate over intermediate array, instead of iterating using + * String.charAt(). Former is generally faster for longer Strings, but + * has some overhead for shorter Strings. Tests indicate that the + * threshold is somewhere between 8 and 16 characters, at least on + * x86 platform. + */ + protected final static int MIN_ARRAYCOPY = 12; + + protected final static int ATTR_MIN_ARRAYCOPY = 12; + + protected final static int DEFAULT_COPYBUFFER_LEN = 512; + + /* + /////////////////////////////////////////////////////////// + // Output objects + /////////////////////////////////////////////////////////// + */ + + /** + * Actual physical writer to output serialized XML content to + */ + protected final XmlWriter mWriter; + + /** + * Intermediate buffer into which characters of a String can be + * copied, in cases where such a copy followed by array access + * is faster than calling String.charAt() (which + * perhaps surprisingly is often case, and especially significant + * for longer buffers). + */ + protected char[] mCopyBuffer = null; + + /* + /////////////////////////////////////////////////////////// + // Per-factory configuration (options, features) + /////////////////////////////////////////////////////////// + */ + + protected final WriterConfig mConfig; + + // // // Specialized configuration flags, extracted from config flags: + + protected final boolean mCfgCDataAsText; + protected final boolean mCfgCopyDefaultAttrs; + protected final boolean mCfgAutomaticEmptyElems; + + // NOTE: can not be final, may be enabled when schema (etc) validation enabled + + protected boolean mCheckStructure; + protected boolean mCheckAttrs; + + /* + /////////////////////////////////////////////////////////// + // Per-writer configuration + /////////////////////////////////////////////////////////// + */ + + /** + * Encoding to use; may be passed from the factory (when + * a method that defines encoding is used), updated by + * a call to {@link #writeStartDocument}, or null if + * neither. Is passed to the escaping writer factory to + * allow escaping writers to do additional escaping if + * necessary (like encapsulating non-ascii chars in a doc + * encoded usig ascii). + */ + protected String mEncoding; + + /** + * Optional validator to use for validating output against + * one or more schemas, and/or for safe pretty-printing (indentation). + */ + protected XMLValidator mValidator = null; + + /** + * Since XML 1.1 has some differences to 1.0, we need to keep a flag + * to indicate if we were to output XML 1.1 document. + */ + protected boolean mXml11 = false; + + /** + * Custom validation problem handler, if any. + */ + protected ValidationProblemHandler mVldProbHandler = null; + + /* + //////////////////////////////////////////////////// + // State information + //////////////////////////////////////////////////// + */ + + protected int mState = STATE_PROLOG; + + /** + * Flag that is set to true first time something has been output. + * Generally needed to keep track of whether XML declaration + * (START_DOCUMENT) can be output or not. + */ + protected boolean mAnyOutput = false; + + /** + * Flag that is set during time that a start element is "open", ie. + * START_ELEMENT has been output (and possibly zero or more name + * space declarations and attributes), before other main-level + * constructs have been output. + */ + protected boolean mStartElementOpen = false; + + /** + * Flag that indicates that current element is an empty element (one + * that is explicitly defined as one, by calling a method -- NOT one + * that just happens to be empty). + * This is needed to know what to do when next non-ns/attr node + * is output; normally a new context is opened, but for empty + * elements not. + */ + protected boolean mEmptyElement = false; + + /** + * State value used with validation, to track types of content + * that is allowed at this point in output stream. Only used if + * validation is enabled: if so, value is determined via validation + * callbacks. + */ + protected int mVldContent = XMLValidator.CONTENT_ALLOW_ANY_TEXT; + + /** + * Value passed as the expected root element, when using the multiple + * argument {@link #writeDTD} method. Will be used in structurally + * validating mode (and in dtd-validating mode, since that automatically + * enables structural validation as well, to pre-filter well-formedness + * errors that validators might have trouble dealing with). + */ + protected String mDtdRootElem = null; + + protected boolean mReturnNullForDefaultNamespace; + + /* + //////////////////////////////////////////////////// + // Life-cycle + //////////////////////////////////////////////////// + */ + + protected BaseStreamWriter(XmlWriter xw, String enc, WriterConfig cfg) + { + mWriter = xw; + mEncoding = enc; + mConfig = cfg; + + int flags = cfg.getConfigFlags(); + + mCheckStructure = (flags & OutputConfigFlags.CFG_VALIDATE_STRUCTURE) != 0; + mCheckAttrs = (flags & OutputConfigFlags.CFG_VALIDATE_ATTR) != 0; + + mCfgAutomaticEmptyElems = (flags & OutputConfigFlags.CFG_AUTOMATIC_EMPTY_ELEMENTS) != 0; + mCfgCDataAsText = (flags & OutputConfigFlags.CFG_OUTPUT_CDATA_AS_TEXT) != 0; + mCfgCopyDefaultAttrs = (flags & OutputConfigFlags.CFG_COPY_DEFAULT_ATTRS) != 0; + + mReturnNullForDefaultNamespace = mConfig.returnNullForDefaultNamespace(); + } + + /* + /////////////////////////////////////////////////////////// + // XMLStreamWriter API + /////////////////////////////////////////////////////////// + */ + + @Override + public void close() + throws XMLStreamException + { + /* 19-Jul-2004, TSa: Hmmh. Let's actually close all still open + * elements, starting with currently open start (-> empty) + * element, if one exists, and then closing scopes by adding + * matching end elements. + */ + _finishDocument(false); + } + + @Override + public void flush() + throws XMLStreamException + { + /* Note: there have been changes to exact scope of flushing + * (with Woodstox versions 2.x and 3.x); but the current + * one of just flushing the underlying OutputStream or Writer + * should be the interpretation compatible with the Stax specs. + */ + try { + mWriter.flush(); + } catch (IOException ie) { + throw new WstxIOException(ie); + } + } + + @Override + public abstract NamespaceContext getNamespaceContext(); + + @Override + public abstract String getPrefix(String uri); + + @Override + public Object getProperty(String name) + { + /* These properties just exist for interoperability with + * toolkits that were designed to work with Sun's parser (which + * introduced properties) + */ + if (name.equals(WstxOutputProperties.P_OUTPUT_UNDERLYING_STREAM)) { + return mWriter.getOutputStream(); + } + if (name.equals(WstxOutputProperties.P_OUTPUT_UNDERLYING_WRITER)) { + return mWriter.getWriter(); + } + return mConfig.getProperty(name); + } + + @Override + public abstract void setDefaultNamespace(String uri) + throws XMLStreamException; + + @Override + public abstract void setNamespaceContext(NamespaceContext context) + throws XMLStreamException; + + @Override + public abstract void setPrefix(String prefix, String uri) + throws XMLStreamException; + + @Override + public abstract void writeAttribute(String localName, String value) + throws XMLStreamException; + + @Override + public abstract void writeAttribute(String nsURI, String localName, + String value) + throws XMLStreamException; + + @Override + public abstract void writeAttribute(String prefix, String nsURI, + String localName, String value) + throws XMLStreamException; + + @Override + public void writeCData(String data) + throws XMLStreamException + { + // 02-Dec-2004, TSa: Maybe the writer is to "re-direct" these + // writes as normal text? (sometimes useful to deal with broken + // XML parsers, for example) + if (mCfgCDataAsText) { + writeCharacters(data); + return; + } + + mAnyOutput = true; + // Need to finish an open start element? + if (mStartElementOpen) { + closeStartElement(mEmptyElement); + } + verifyWriteCData(); + if (mVldContent == XMLValidator.CONTENT_ALLOW_VALIDATABLE_TEXT + && mValidator != null) { + // Last arg is false, since we do not know if more text + // may be added with additional calls + mValidator.validateText(data, false); + } + int ix; + try { + ix = mWriter.writeCData(data); + } catch (IOException ioe) { + throw new WstxIOException(ioe); + } + if (ix >= 0) { // unfixable problems? + reportNwfContent(ErrorConsts.WERR_CDATA_CONTENT, DataUtil.Integer(ix)); + } + } + + @Override + public void writeCharacters(char[] text, int start, int len) + throws XMLStreamException + { + mAnyOutput = true; + // Need to finish an open start element? + if (mStartElementOpen) { + closeStartElement(mEmptyElement); + } + + // Not legal outside main element tree, except if it's all white space + if (mCheckStructure) { + if (inPrologOrEpilog()) { + if (!StringUtil.isAllWhitespace(text, start, len)) { + reportNwfStructure(ErrorConsts.WERR_PROLOG_NONWS_TEXT); + } + } + } + // 08-Dec-2005, TSa: validator-based validation? + if (mVldContent <= XMLValidator.CONTENT_ALLOW_WS) { + if (mVldContent == XMLValidator.CONTENT_ALLOW_NONE) { // never ok + reportInvalidContent(CHARACTERS); + } else { // all-ws is ok... + if (!StringUtil.isAllWhitespace(text, start, len)) { + reportInvalidContent(CHARACTERS); + } + } + } else if (mVldContent == XMLValidator.CONTENT_ALLOW_VALIDATABLE_TEXT) { + if (mValidator != null) { + // Last arg is false, since we do not know if more text + // may be added with additional calls + mValidator.validateText(text, start, start + len, false); + } + } + + if (len > 0) { // minor optimization + try { + // 21-Jun-2006, TSa: Fixing [WSTX-59]: no quoting can be done + // outside of element tree. + if (inPrologOrEpilog()) { + mWriter.writeRaw(text, start, len); + } else { + mWriter.writeCharacters(text, start, len); + } + } catch (IOException ioe) { + throw new WstxIOException(ioe); + } + } + } + + @Override + public void writeCharacters(String text) + throws XMLStreamException + { + mAnyOutput = true; + // Need to finish an open start element? + if (mStartElementOpen) { + closeStartElement(mEmptyElement); + } + + // Need to validate structure? + if (mCheckStructure) { + // Not valid in prolog/epilog, except if it's all white space: + if (inPrologOrEpilog()) { + if (!StringUtil.isAllWhitespace(text)) { + reportNwfStructure(ErrorConsts.WERR_PROLOG_NONWS_TEXT); + } + } + } + + /* 08-Dec-2005, TSa: validator-based validation? + * Note: although it'd be good to check validity first, we + * do not know allowed textual content before actually writing + * pending start element (if any)... so can't call this earlier + */ + if (mVldContent <= XMLValidator.CONTENT_ALLOW_WS) { + if (mVldContent == XMLValidator.CONTENT_ALLOW_NONE) { // never ok + reportInvalidContent(CHARACTERS); + } else { // all-ws is ok... + if (!StringUtil.isAllWhitespace(text)) { + reportInvalidContent(CHARACTERS); + } + } + } else if (mVldContent == XMLValidator.CONTENT_ALLOW_VALIDATABLE_TEXT) { + if (mValidator != null) { + /* Last arg is false, since we do not know if more text + * may be added with additional calls + */ + mValidator.validateText(text, false); + } + } + + // Ok, let's just write it out + /* 21-Jun-2006, TSa: Fixing [WSTX-59]: no quoting can be done + * outside of element tree. + */ + if (inPrologOrEpilog()) { + try { + mWriter.writeRaw(text); + } catch (IOException ioe) { + throw new WstxIOException(ioe); + } + return; + } + + /* Now, would it pay off to make an intermediate copy? + * String.getChars (which uses System.arraycopy()) is + * very fast compared to access via String.charAt. + */ + int len = text.length(); + if (len >= MIN_ARRAYCOPY) { + char[] buf = getCopyBuffer(); + + int offset = 0; + while (len > 0) { + int thisLen = (len > buf.length) ? buf.length : len; + text.getChars(offset, offset+thisLen, buf, 0); + try { + mWriter.writeCharacters(buf, 0, thisLen); + } catch (IOException ioe) { + throw new WstxIOException(ioe); + } + offset += thisLen; + len -= thisLen; + } + } else { // nope, let's just access String using charAt(). + try { + mWriter.writeCharacters(text); + } catch (IOException ioe) { + throw new WstxIOException(ioe); + } + } + } + + @Override + public void writeComment(String data) + throws XMLStreamException + { + mAnyOutput = true; + // Need to finish an open start element? + if (mStartElementOpen) { + closeStartElement(mEmptyElement); + } + + // 08-Dec-2005, TSa: validator-based validation? + if (mVldContent == XMLValidator.CONTENT_ALLOW_NONE) { + reportInvalidContent(COMMENT); + } + + /* No structural validation needed per se, for comments; they are + * allowed anywhere in XML content. However, content may need to + * be checked (by XmlWriter) + */ + int ix; + try { + ix = mWriter.writeComment(data); + } catch (IOException ioe) { + throw new WstxIOException(ioe); + } + + if (ix >= 0) { + reportNwfContent(ErrorConsts.WERR_COMMENT_CONTENT, DataUtil.Integer(ix)); + } + } + + @Override + public abstract void writeDefaultNamespace(String nsURI) + throws XMLStreamException; + + @Override + public void writeDTD(String dtd) + throws XMLStreamException + { + verifyWriteDTD(); + mDtdRootElem = ""; // marker to verify only one is output + try { + mWriter.writeDTD(dtd); + } catch (IOException ioe) { + throw new WstxIOException(ioe); + } + + /* 20-Dec-2005, TSa: Should we try to decipher what was actually + * written, for validation? + */ + } + + @Override + public abstract void writeEmptyElement(String localName) + throws XMLStreamException; + + @Override + public abstract void writeEmptyElement(String nsURI, String localName) + throws XMLStreamException; + + @Override + public abstract void writeEmptyElement(String prefix, String localName, String nsURI) + throws XMLStreamException; + + @Override + public void writeEndDocument() throws XMLStreamException + { + _finishDocument(false); + } + + @Override + public abstract void writeEndElement() throws XMLStreamException; + + @Override + public void writeEntityRef(String name) + throws XMLStreamException + { + mAnyOutput = true; + // Need to finish an open start element? + if (mStartElementOpen) { + closeStartElement(mEmptyElement); + } + + // Structurally, need to check we are not in prolog/epilog. + if (mCheckStructure) { + if (inPrologOrEpilog()) { + reportNwfStructure("Trying to output an entity reference outside main element tree (in prolog or epilog)"); + } + } + // 08-Dec-2005, TSa: validator-based validation? + if (mVldContent == XMLValidator.CONTENT_ALLOW_NONE) { + /* May be char entity, general entity; whatever it is it's + * invalid! + */ + reportInvalidContent(ENTITY_REFERENCE); + } + + //if (mValidator != null) { + /* !!! 11-Dec-2005, TSa: Should be able to use DTD based validators + * to check if entity has been declared... + */ + //} + + try { + mWriter.writeEntityReference(name); + } catch (IOException ioe) { + throw new WstxIOException(ioe); + } + } + + @Override + public abstract void writeNamespace(String prefix, String nsURI) + throws XMLStreamException; + + @Override + public void writeProcessingInstruction(String target) + throws XMLStreamException + { + writeProcessingInstruction(target, null); + } + + @Override + public void writeProcessingInstruction(String target, String data) + throws XMLStreamException + { + mAnyOutput = true; + // Need to finish an open start element? + if (mStartElementOpen) { + closeStartElement(mEmptyElement); + } + + // Structurally, PIs are always ok (content might not be) + // 08-Dec-2005, TSa: validator-based validation? + if (mVldContent == XMLValidator.CONTENT_ALLOW_NONE) { + reportInvalidContent(PROCESSING_INSTRUCTION); + } + int ix; + try { + ix = mWriter.writePI(target, data); + } catch (IOException ioe) { + throw new WstxIOException(ioe); + } + if (ix >= 0) { + throw new XMLStreamException("Illegal input: processing instruction content has embedded '?>' in it (index "+ix+")"); + } + } + + @Override + public void writeStartDocument() + throws XMLStreamException + { + /* 03-Feb-2005, TSa: As per StAX 1.0 specs, version should + * be "1.0", and encoding "utf-8" (yes, lower case... it's + * wrong, but specs mandate it) + */ + /* 11-Jan-2006, TSa: Let's actually rather use whatever was passed + * in, if anything; only if none then default to something else. + * Plus, what the heck; let's use properly capitalized value + * too (and ignore faulty def in stax specs). + */ + if (mEncoding == null) { + mEncoding = WstxOutputProperties.DEFAULT_OUTPUT_ENCODING; + } + writeStartDocument(mEncoding, WstxOutputProperties.DEFAULT_XML_VERSION); + } + + @Override + public void writeStartDocument(String version) + throws XMLStreamException + { + writeStartDocument(mEncoding, version); + } + + @Override + public void writeStartDocument(String encoding, String version) + throws XMLStreamException + { + doWriteStartDocument(version, encoding, null); + } + + protected void doWriteStartDocument(String version, String encoding, + String standAlone) + throws XMLStreamException + { + /* Not legal to output XML declaration if there has been ANY + * output prior... that is, if we validate the structure. + */ + if (mCheckStructure) { + if (mAnyOutput) { + reportNwfStructure("Can not output XML declaration, after other output has already been done."); + } + } + + mAnyOutput = true; + + if (mConfig.willValidateContent()) { + // !!! 06-May-2004, TSa: Should validate encoding? + /*if (encoding != null) { + }*/ + if (version != null && version.length() > 0) { + if (!(version.equals(XmlConsts.XML_V_10_STR) + || version.equals(XmlConsts.XML_V_11_STR))) { + reportNwfContent("Illegal version argument ('"+version + +"'); should only use '"+XmlConsts.XML_V_10_STR + +"' or '"+XmlConsts.XML_V_11_STR+"'"); + } + } + } + + if (version == null || version.length() == 0) { + version = WstxOutputProperties.DEFAULT_XML_VERSION; + } + + /* 04-Feb-2006, TSa: Need to know if we are writing XML 1.1 + * document... + */ + mXml11 = XmlConsts.XML_V_11_STR.equals(version); + if (mXml11) { + mWriter.enableXml11(); + } + + if (encoding != null && encoding.length() > 0) { + /* 03-May-2005, TSa: But what about conflicting encoding? Let's + * only update encoding, if it wasn't set. + */ + if (mEncoding == null || mEncoding.length() == 0) { + mEncoding = encoding; + } + } + try { + mWriter.writeXmlDeclaration(version, encoding, standAlone); + } catch (IOException ioe) { + throw new WstxIOException(ioe); + } + } + + @Override + public abstract void writeStartElement(String localName) + throws XMLStreamException; + + @Override + public abstract void writeStartElement(String nsURI, String localName) + throws XMLStreamException; + + @Override + public abstract void writeStartElement(String prefix, String localName, + String nsURI) + throws XMLStreamException; + + /* + /////////////////////////////////////////////////////////// + // XMLStreamWriter2 methods (StAX2) + /////////////////////////////////////////////////////////// + */ + + /** + * Method that essentially copies event that the specified reader has + * just read. + * + * @param sr Stream reader to use for accessing event to copy + * @param preserveEventData If true, writer is not allowed to change + * the state of the reader (so that all the data associated with the + * current event has to be preserved); if false, writer is allowed + * to use methods that may cause some data to be discarded. Setting + * this to false may improve the performance, since it may allow + * full no-copy streaming of data, especially textual contents. + */ + @Override + public void copyEventFromReader(XMLStreamReader2 sr, boolean preserveEventData) + throws XMLStreamException + { + try { + switch (sr.getEventType()) { + case START_DOCUMENT: + { + String version = sr.getVersion(); + // No real declaration? If so, we don't want to output anything, to replicate + // as closely as possible the source document + if (version == null || version.length() == 0) { + ; // no output if no real input + } else { + if (sr.standaloneSet()) { + writeStartDocument(sr.getVersion(), + sr.getCharacterEncodingScheme(), + sr.isStandalone()); + } else { + writeStartDocument(sr.getCharacterEncodingScheme(), + sr.getVersion()); + } + } + } + return; + + case END_DOCUMENT: + writeEndDocument(); + return; + + // Element start/end events: + case START_ELEMENT: + if (sr instanceof StreamReaderImpl) { + StreamReaderImpl impl = (StreamReaderImpl) sr; + copyStartElement(impl.getInputElementStack(), impl.getAttributeCollector()); + } else { // otherwise impl from Stax ref. impl (Stax2WriterImpl) has to do: + super.copyStartElement(sr); + } + return; + + case END_ELEMENT: + writeEndElement(); + return; + + case SPACE: + { + mAnyOutput = true; + // Need to finish an open start element? + if (mStartElementOpen) { + closeStartElement(mEmptyElement); + } + // No need to write as chars, should be pure space (caller should + // have verified); also, no escaping necessary. + + // 28-Mar-2017, tatu: Various optimization do not work well when validation so: + if (mValidator != null) { + writeCData(sr.getText()); + } else { + sr.getText(wrapAsRawWriter(), preserveEventData); + } + } + return; + + case CDATA: + + // First; is this to be changed to 'normal' text output? + // 28-Mar-2017, tatu: Various optimization do not work well when validation so: + if (mValidator != null) { + writeCData(sr.getText()); + return; + } + if (!mCfgCDataAsText) { + mAnyOutput = true; + // Need to finish an open start element? + if (mStartElementOpen) { + closeStartElement(mEmptyElement); + } + + // Not legal outside main element tree: + if (mCheckStructure) { + if (inPrologOrEpilog()) { + reportNwfStructure(ErrorConsts.WERR_PROLOG_CDATA); + } + } + // Note: no need to check content, since reader is assumed + // to have verified it to be valid XML. + mWriter.writeCDataStart(); + sr.getText(wrapAsRawWriter(), preserveEventData); + mWriter.writeCDataEnd(); + return; + } + // fall down if it is to be converted... + + case CHARACTERS: + + // 28-Mar-2017, tatu: Various optimization do not work well when validation so: + if (mValidator != null) { + writeCharacters(sr.getText()); + } else { + // Let's just assume content is fine... not 100% reliably + // true, but usually is (not true if input had a root + // element surrounding text, but omitted for output) + mAnyOutput = true; + // Need to finish an open start element? + if (mStartElementOpen) { + closeStartElement(mEmptyElement); + } + sr.getText(wrapAsTextWriter(), preserveEventData); + } + return; + + case COMMENT: + { + mAnyOutput = true; + if (mStartElementOpen) { + closeStartElement(mEmptyElement); + } + // No need to check for content (embedded '--'); reader + // is assumed to have verified it's ok (otherwise should + // have thrown an exception for non-well-formed XML) + mWriter.writeCommentStart(); + sr.getText(wrapAsRawWriter(), preserveEventData); + mWriter.writeCommentEnd(); + } + return; + + case PROCESSING_INSTRUCTION: + { + mWriter.writePIStart(sr.getPITarget(), true); + sr.getText(wrapAsRawWriter(), preserveEventData); + mWriter.writePIEnd(); + } + return; + + case DTD: + { + DTDInfo info = sr.getDTDInfo(); + if (info == null) { + // Hmmmh. It is legal for this to happen, for non-DTD-aware + // readers. But what is the right thing to do here? + throwOutputError("Current state DOCTYPE, but not DTDInfo Object returned -- reader doesn't support DTDs?"); + } + // Could optimize this a bit (stream the int. subset possible), + // but it's never going to occur more than once per document, + // so it's probably not much of a bottleneck, ever + writeDTD(info); + } + return; + + case ENTITY_REFERENCE: + writeEntityRef(sr.getLocalName()); + return; + + case ATTRIBUTE: + case NAMESPACE: + case ENTITY_DECLARATION: + case NOTATION_DECLARATION: + // Let's just fall back to throw the exception + } + } catch (IOException ioe) { + throw new WstxIOException(ioe); + } + throw new XMLStreamException("Unrecognized event type (" + +sr.getEventType()+"); not sure how to copy"); + } + + /* + /////////////////////////////////////////////////////////// + // StAX2, output handling + /////////////////////////////////////////////////////////// + */ + + @Override + public void closeCompletely() + throws XMLStreamException + { + _finishDocument(true); + } + + /* + /////////////////////////////////////////////////////////// + // StAX2, config + /////////////////////////////////////////////////////////// + */ + + // NOTE: getProperty() defined in Stax 1.0 interface + + @Override + public boolean isPropertySupported(String name) { + // !!! TBI: not all these properties are really supported + return mConfig.isPropertySupported(name); + } + + /** + * @param name Name of the property to set + * @param value Value to set property to. + * + * @return True, if the specified property was succesfully + * set to specified value; false if its value was not changed + */ + @Override + public boolean setProperty(String name, Object value) + { + /* Note: can not call local method, since it'll return false for + * recognized but non-mutable properties + */ + return mConfig.setProperty(name, value); + } + + @Override + public XMLValidator validateAgainst(XMLValidationSchema schema) + throws XMLStreamException + { + XMLValidator vld = schema.createValidator(this); + + if (mValidator == null) { + /* Need to enable other validation modes? Structural validation + * should always be done when we have other validators as well, + * as well as attribute uniqueness checks. + */ + mCheckStructure = true; + mCheckAttrs = true; + mValidator = vld; + } else { + mValidator = new ValidatorPair(mValidator, vld); + } + return vld; + } + + @Override + public XMLValidator stopValidatingAgainst(XMLValidationSchema schema) + throws XMLStreamException + { + XMLValidator[] results = new XMLValidator[2]; + XMLValidator found = null; + if (ValidatorPair.removeValidator(mValidator, schema, results)) { // found + found = results[0]; + mValidator = results[1]; + found.validationCompleted(false); + if (mValidator == null) { + resetValidationFlags(); + } + } + return found; + } + + @Override + public XMLValidator stopValidatingAgainst(XMLValidator validator) + throws XMLStreamException + { + XMLValidator[] results = new XMLValidator[2]; + XMLValidator found = null; + if (ValidatorPair.removeValidator(mValidator, validator, results)) { // found + found = results[0]; + mValidator = results[1]; + found.validationCompleted(false); + if (mValidator == null) { + resetValidationFlags(); + } + } + return found; + } + + @Override + public ValidationProblemHandler setValidationProblemHandler(ValidationProblemHandler h) + { + ValidationProblemHandler oldH = mVldProbHandler; + mVldProbHandler = h; + return oldH; + } + + private void resetValidationFlags() + { + int flags = mConfig.getConfigFlags(); + mCheckStructure = (flags & CFG_VALIDATE_STRUCTURE) != 0; + mCheckAttrs = (flags & CFG_VALIDATE_ATTR) != 0; + } + + /* + /////////////////////////////////////////////////////////// + // StAX2, other accessors, mutators + /////////////////////////////////////////////////////////// + */ + + @Override + public XMLStreamLocation2 getLocation() + { + return new WstxInputLocation(null, // no parent + null, (String) null, // pub/sys ids not yet known + mWriter.getAbsOffset(), + mWriter.getRow(), mWriter.getColumn()); + } + + @Override + public String getEncoding() { + return mEncoding; + } + + /* + /////////////////////////////////////////////////////////// + // StAX2, output methods + /////////////////////////////////////////////////////////// + */ + + @Override + public void writeCData(char[] cbuf, int start, int len) + throws XMLStreamException + { + /* 02-Dec-2004, TSa: Maybe the writer is to "re-direct" these + * writes as normal text? (sometimes useful to deal with broken + * XML parsers, for example) + */ + if (mCfgCDataAsText) { + writeCharacters(cbuf, start, len); + return; + } + + mAnyOutput = true; + // Need to finish an open start element? + if (mStartElementOpen) { + closeStartElement(mEmptyElement); + } + verifyWriteCData(); + if (mVldContent == XMLValidator.CONTENT_ALLOW_VALIDATABLE_TEXT + && mValidator != null) { + /* Last arg is false, since we do not know if more text + * may be added with additional calls + */ + mValidator.validateText(cbuf, start, start + len, false); + } + int ix; + try { + ix = mWriter.writeCData(cbuf, start, len); + } catch (IOException ioe) { + throw new WstxIOException(ioe); + } + if (ix >= 0) { // problems that could not to be fixed? + throwOutputError(ErrorConsts.WERR_CDATA_CONTENT, DataUtil.Integer(ix)); + } + } + + public void writeDTD(DTDInfo info) + throws XMLStreamException + { + writeDTD(info.getDTDRootName(), info.getDTDSystemId(), + info.getDTDPublicId(), info.getDTDInternalSubset()); + } + + @Override + public void writeDTD(String rootName, String systemId, String publicId, + String internalSubset) + throws XMLStreamException + { + verifyWriteDTD(); + mDtdRootElem = rootName; + try { + mWriter.writeDTD(rootName, systemId, publicId, internalSubset); + } catch (IOException ioe) { + throw new WstxIOException(ioe); + } + } + + @Override + public abstract void writeFullEndElement() throws XMLStreamException; + + @Override + public void writeStartDocument(String version, String encoding, + boolean standAlone) + throws XMLStreamException + { + doWriteStartDocument(version, encoding, standAlone ? "yes" : "no"); + } + + @Override + public void writeRaw(String text) + throws XMLStreamException + { + mAnyOutput = true; + if (mStartElementOpen) { + closeStartElement(mEmptyElement); + } + try { + mWriter.writeRaw(text, 0, text.length()); + } catch (IOException ioe) { + throw new WstxIOException(ioe); + } + } + + @Override + public void writeRaw(String text, int start, int offset) + throws XMLStreamException + { + mAnyOutput = true; + if (mStartElementOpen) { + closeStartElement(mEmptyElement); + } + try { + mWriter.writeRaw(text, start, offset); + } catch (IOException ioe) { + throw new WstxIOException(ioe); + } + } + + @Override + public void writeRaw(char[] text, int start, int offset) + throws XMLStreamException + { + mAnyOutput = true; + if (mStartElementOpen) { + closeStartElement(mEmptyElement); + } + try { + mWriter.writeRaw(text, start, offset); + } catch (IOException ioe) { + throw new WstxIOException(ioe); + } + } + + @Override + public void writeSpace(String text) + throws XMLStreamException + { + /* For now, let's just use writeRaw(): otherwise would need + * to add it to all backend writers: + */ + writeRaw(text); + } + + @Override + public void writeSpace(char[] text, int offset, int length) + throws XMLStreamException + { + // For now, let's just use writeRaw() (see above) + writeRaw(text, offset, length); + } + + /* + /////////////////////////////////////////////////////////// + // ValidationContext interface (StAX2, validation) + /////////////////////////////////////////////////////////// + */ + + @Override + public String getXmlVersion() { + return mXml11 ? XmlConsts.XML_V_11_STR : XmlConsts.XML_V_10_STR; + } + + @Override + public abstract QName getCurrentElementName(); + + @Override + public abstract String getNamespaceURI(String prefix); + + /** + * As of now, there is no way to specify the base URI. Could be improved + * in future, if xml:base is supported. + */ + @Override + public String getBaseUri() { + return null; + } + + @Override + public Location getValidationLocation() { + return getLocation(); + } + + @Override + public void reportProblem(XMLValidationProblem prob) + throws XMLStreamException + { + // Custom handler set? If so, it'll take care of it: + if (mVldProbHandler != null) { + mVldProbHandler.reportProblem(prob); + return; + } + + /* For now let's implement basic functionality: warnings get + * reported via XMLReporter, errors and fatal errors result in + * immediate exceptions. + */ + /* 27-May-2008, TSa: [WSTX-153] Above is incorrect: as per Stax + * javadocs for XMLReporter, both warnings and non-fatal errors + * (which includes all validation errors) should be reported via + * XMLReporter interface, and only fatals should cause an + * immediate stream exception (by-passing reporter) + */ + if (prob.getSeverity() > XMLValidationProblem.SEVERITY_ERROR) { + throw WstxValidationException.create(prob); + } + XMLReporter rep = mConfig.getProblemReporter(); + if (rep != null) { + doReportProblem(rep, prob); + } else { + /* If no reporter, regular non-fatal errors are to be reported + * as exceptions as well, for backwards compatibility + */ + if (prob.getSeverity() >= XMLValidationProblem.SEVERITY_ERROR) { + throw WstxValidationException.create(prob); + } + } + } + + /** + * Adding default attribute values does not usually make sense on + * output side, so the implementation is a NOP for now. + */ + @Override + public int addDefaultAttribute(String localName, String uri, String prefix, + String value) + { + // nothing to do, but to indicate we didn't add it... + return -1; + } + + // // // Notation/entity access: not (yet?) implemented + + @Override + public boolean isNotationDeclared(String name) { return false; } + + @Override + public boolean isUnparsedEntityDeclared(String name) { return false; } + + // // // Attribute access: not yet implemented: + + /* !!! TODO: Implement attribute access (iff validate-attributes + * enabled? + */ + + @Override + public int getAttributeCount() { return 0; } + + @Override + public String getAttributeLocalName(int index) { return null; } + + @Override + public String getAttributeNamespace(int index) { return null; } + + @Override + public String getAttributePrefix(int index) { return null; } + + @Override + public String getAttributeValue(int index) { return null; } + + @Override + public String getAttributeValue(String nsURI, String localName) { + return null; + } + + @Override + public String getAttributeType(int index) { + return ""; + } + + @Override + public int findAttributeIndex(String nsURI, String localName) { + return -1; + } + + /* + /////////////////////////////////////////////////////////// + // Package methods (ie not part of public API) + /////////////////////////////////////////////////////////// + */ + + /** + * Method that can be called to get a wrapper instance that + * can be used to essentially call the writeRaw + * method via regular Writer interface. + */ + public final Writer wrapAsRawWriter() + { + return mWriter.wrapAsRawWriter(); + } + + /** + * Method that can be called to get a wrapper instance that + * can be used to essentially call the writeCharacters + * method via regular Writer interface. + */ + public final Writer wrapAsTextWriter() + { + return mWriter.wrapAsTextWriter(); + } + + /** + * Method that is used by output classes to determine whether we + * are in validating mode. + *

+ * Note: current implementation of this method is not perfect; it + * may be possible it can return true even if we are only using a DTD + * to get some limited info, without validating? + */ + protected boolean isValidating() { + return (mValidator != null); + } + + /** + * Convenience method needed by {@link javax.xml.stream.XMLEventWriter} + * implementation, to use when + * writing a start element, and possibly its attributes and namespace + * declarations. + */ + public abstract void writeStartElement(StartElement elem) + throws XMLStreamException; + + /** + * Method called by {@link javax.xml.stream.XMLEventWriter} + * (instead of the version + * that takes no argument), so that we can verify it does match the + * start element if necessary. + */ + public abstract void writeEndElement(QName name) + throws XMLStreamException; + + /** + * Method called by {@link javax.xml.stream.XMLEventWriter} + * (instead of more generic + * text output methods), so that we can verify (if necessary) that + * this character output type is legal in this context. Specifically, + * it's not acceptable to add non-whitespace content outside root + * element (in prolog/epilog). + *

+ * Note: cut'n pasted from the main writeCharacters; not + * good... but done to optimize white-space cases. + */ + public void writeCharacters(Characters ch) + throws XMLStreamException + { + // Need to finish an open start element? + if (mStartElementOpen) { + closeStartElement(mEmptyElement); + } + + /* Not legal outside main element tree, except if it's all + * white space + */ + if (mCheckStructure) { + if (inPrologOrEpilog()) { + if (!ch.isIgnorableWhiteSpace() && !ch.isWhiteSpace()) { + reportNwfStructure(ErrorConsts.WERR_PROLOG_NONWS_TEXT); + } + } + } + + if (mVldContent <= XMLValidator.CONTENT_ALLOW_WS) { + if (mVldContent == XMLValidator.CONTENT_ALLOW_NONE) { // never ok + reportInvalidContent(CHARACTERS); + } else { // all-ws is ok... + if (!ch.isIgnorableWhiteSpace() && !ch.isWhiteSpace()) { + reportInvalidContent(CHARACTERS); + } + } + } else if (mVldContent == XMLValidator.CONTENT_ALLOW_VALIDATABLE_TEXT) { + if (mValidator != null) { + /* Last arg is false, since we do not know if more text + * may be added with additional calls + */ + mValidator.validateText(ch.getData(), false); + } + } + + // Ok, let's just write it out: + try { + mWriter.writeCharacters(ch.getData()); + } catch (IOException ioe) { + throw new WstxIOException(ioe); + } + } + + /** + * Method called to close an open start element, when another + * main-level element (not namespace declaration or attribute) + * is being output; except for end element which is handled differently. + */ + protected abstract void closeStartElement(boolean emptyElem) + throws XMLStreamException; + + protected final boolean inPrologOrEpilog() { + return (mState != STATE_TREE); + } + + /** + * @param forceRealClose If true, will force calling of close() on the + * underlying physical result (stream, writer). If false, will let + * XmlWriter decide whether to call close(); will be done if auto-closing + * enabled, but not otherwise. + */ + private final void _finishDocument(boolean forceRealClose) + throws XMLStreamException + { + // Is tree still open? + if (mState != STATE_EPILOG) { + if (mCheckStructure && mState == STATE_PROLOG) { + reportNwfStructure("Trying to write END_DOCUMENT when document has no root (ie. trying to output empty document)."); + } + // 20-Jul-2004, TSa: Need to close the open sub-tree, if it exists... + // First, do we have an open start element? + if (mStartElementOpen) { + closeStartElement(mEmptyElement); + } + // Then, one by one, need to close open scopes: + /* 17-Nov-2008, TSa: that is, if we are allowed to do it + * (see [WSTX-165]) + */ + if (mState != STATE_EPILOG && mConfig.automaticEndElementsEnabled()) { + do { + writeEndElement(); + } while (mState != STATE_EPILOG); + } + } + + /* And finally, inform the underlying writer that it should flush + * and release its buffers, and close components it uses if any. + */ + char[] buf = mCopyBuffer; + if (buf != null) { + mCopyBuffer = null; + mConfig.freeMediumCBuffer(buf); + } + try { + mWriter.close(forceRealClose); + } catch (IOException ie) { + throw new WstxIOException(ie); + } + } + + /** + * Implementation-dependant method called to fully copy START_ELEMENT + * event that the passed-in stream reader points to + */ + public abstract void copyStartElement(InputElementStack elemStack, + AttributeCollector attrCollector) + throws IOException, XMLStreamException; + + /** + * Method called before writing a QName via Typed Access API. + * In namespace-repairing mode it should take appropriate actions + * to ensure that the given namespace URI is bound to a namespace + * and return whatever it maps to. In non-repairing work no additional + * work is to be done and methods + * + * @return Prefix to use when writing out given QName as an element + * or attribute value + */ + public abstract String validateQNamePrefix(QName name) + throws XMLStreamException; + + /* + /////////////////////////////////////////////////////////// + // Package methods, validation + /////////////////////////////////////////////////////////// + */ + + protected final void verifyWriteCData() + throws XMLStreamException + { + // Not legal outside main element tree: + if (mCheckStructure) { + if (inPrologOrEpilog()) { + reportNwfStructure(ErrorConsts.WERR_PROLOG_CDATA); + } + } + // 08-Dec-2005, TSa: validator-based validation? + if (mVldContent <= XMLValidator.CONTENT_ALLOW_WS) { + // there's no ignorable white space CDATA... + reportInvalidContent(CDATA); + } + } + + protected final void verifyWriteDTD() + throws XMLStreamException + { + // 20-Nov-2004, TSa: can check that we are in prolog + if (mCheckStructure) { + if (mState != STATE_PROLOG) { + throw new XMLStreamException("Can not write DOCTYPE declaration (DTD) when not in prolog any more (state "+mState+"; start element(s) written)"); + } + // 20-Dec-2005, TSa: and that we only output one... + if (mDtdRootElem != null) { + throw new XMLStreamException("Trying to write multiple DOCTYPE declarations"); + } + } + } + + protected void verifyRootElement(String localName, String prefix) + throws XMLStreamException + { + /* Note: this check is bit lame, due to DOCTYPE declaration (and DTD + * in general) being namespace-ignorant... + */ + if (isValidating()) { + /* 17-Mar-2006, TSa: Ideally, this should be a validity + * problem? + */ + if (mDtdRootElem != null && mDtdRootElem.length() > 0) { + String wrongElem = null; + + /* Ugh. It is possible that we just don't know the prefix -- + * in repairing mode it's assigned after this check. So for + * now, let's only verify the local name + */ + if (localName.equals(mDtdRootElem)) { + // good + } else { + int lnLen = localName.length(); + int oldLen = mDtdRootElem.length(); + + if (oldLen > lnLen + && mDtdRootElem.endsWith(localName) + && mDtdRootElem.charAt(oldLen - lnLen - 1) == ':') { + // good also + } else { + if (prefix == null) { // doesn't and won't have one + wrongElem = localName; + } else if (prefix.length() == 0) { // don't know what it'd be + wrongElem = "[unknown]:"+localName; + } else { + wrongElem = prefix + ":" + localName; + } + } + } + if (wrongElem != null) { + reportValidationProblem(ErrorConsts.ERR_VLD_WRONG_ROOT, wrongElem, mDtdRootElem); + } + } + } + mState = STATE_TREE; + } + + /* + /////////////////////////////////////////////////////////// + // Package methods, basic output problem reporting + /////////////////////////////////////////////////////////// + */ + + protected static void throwOutputError(String msg) + throws XMLStreamException + { + throw new XMLStreamException(msg); + } + + protected static void throwOutputError(String format, Object arg) + throws XMLStreamException + { + String msg = MessageFormat.format(format, new Object[] { arg }); + throwOutputError(msg); + } + + /** + * Method called when an illegal method (namespace-specific method + * on non-ns writer) is called by the application. + */ + protected static void reportIllegalMethod(String msg) + throws XMLStreamException + { + throwOutputError(msg); + } + + /** + * This is the method called when an output method call violates + * structural well-formedness checks + * and {@link WstxOutputProperties#P_OUTPUT_VALIDATE_STRUCTURE} is + * is enabled. + */ + protected static void reportNwfStructure(String msg) + throws XMLStreamException + { + throwOutputError(msg); + } + + protected static void reportNwfStructure(String msg, Object arg) + throws XMLStreamException + { + throwOutputError(msg, arg); + } + + /** + * This is the method called when an output method call violates + * content well-formedness checks + * and {@link WstxOutputProperties#P_OUTPUT_VALIDATE_CONTENT} is + * is enabled. + */ + protected static void reportNwfContent(String msg) + throws XMLStreamException + { + throwOutputError(msg); + } + + protected static void reportNwfContent(String msg, Object arg) + throws XMLStreamException + { + throwOutputError(msg, arg); + } + + /** + * This is the method called when an output method call violates + * attribute well-formedness checks (trying to output dup attrs) + * and {@link WstxOutputProperties#P_OUTPUT_VALIDATE_NAMES} is + * is enabled. + */ + protected static void reportNwfAttr(String msg) + throws XMLStreamException + { + throwOutputError(msg); + } + + protected static void reportNwfAttr(String msg, Object arg) + throws XMLStreamException + { + throwOutputError(msg, arg); + } + + protected static void throwFromIOE(IOException ioe) + throws XMLStreamException + { + throw new WstxIOException(ioe); + } + + protected static void reportIllegalArg(String msg) + throws IllegalArgumentException + { + throw new IllegalArgumentException(msg); + } + + /* + /////////////////////////////////////////////////////////// + // Package methods, output validation problem reporting + /////////////////////////////////////////////////////////// + */ + + protected void reportInvalidContent(int evtType) + throws XMLStreamException + { + switch (mVldContent) { + case XMLValidator.CONTENT_ALLOW_NONE: + reportValidationProblem(ErrorConsts.ERR_VLD_EMPTY, + getTopElementDesc(), + ErrorConsts.tokenTypeDesc(evtType)); + break; + case XMLValidator.CONTENT_ALLOW_WS: + reportValidationProblem(ErrorConsts.ERR_VLD_NON_MIXED, + getTopElementDesc()); + break; + case XMLValidator.CONTENT_ALLOW_VALIDATABLE_TEXT: + case XMLValidator.CONTENT_ALLOW_ANY_TEXT: + /* Not 100% sure if this should ever happen... depends on + * interpretation of 'any' content model? + */ + reportValidationProblem(ErrorConsts.ERR_VLD_ANY, + getTopElementDesc(), + ErrorConsts.tokenTypeDesc(evtType)); + break; + default: // should never occur: + reportValidationProblem("Internal error: trying to report invalid content for "+evtType); + } + } + + public void reportValidationProblem(String msg, Location loc, int severity) + throws XMLStreamException + { + reportProblem(new XMLValidationProblem(loc, msg, severity)); + } + + public void reportValidationProblem(String msg, int severity) + throws XMLStreamException + { + reportProblem(new XMLValidationProblem(getValidationLocation(), + msg, severity)); + } + + public void reportValidationProblem(String msg) + throws XMLStreamException + { + reportProblem(new XMLValidationProblem(getValidationLocation(), + msg, + XMLValidationProblem.SEVERITY_ERROR)); + } + + public void reportValidationProblem(Location loc, String msg) + throws XMLStreamException + { + reportProblem(new XMLValidationProblem(loc, msg)); + } + + public void reportValidationProblem(String format, Object arg) + throws XMLStreamException + { + String msg = MessageFormat.format(format, new Object[] { arg }); + reportProblem(new XMLValidationProblem(getValidationLocation(), + msg)); + } + + public void reportValidationProblem(String format, Object arg, Object arg2) + throws XMLStreamException + { + String msg = MessageFormat.format(format, new Object[] { arg, arg2 }); + reportProblem(new XMLValidationProblem(getValidationLocation(), msg)); + } + + protected void doReportProblem(XMLReporter rep, String probType, String msg, Location loc) + throws XMLStreamException + { + if (loc == null) { + loc = getLocation(); + } + doReportProblem(rep, new XMLValidationProblem(loc, msg, XMLValidationProblem.SEVERITY_ERROR, probType)); + } + + protected void doReportProblem(XMLReporter rep, XMLValidationProblem prob) + throws XMLStreamException + { + if (rep != null) { + Location loc = prob.getLocation(); + if (loc == null) { + loc = getLocation(); + prob.setLocation(loc); + } + // Backwards-compatibility fix: add non-null type, if missing: + if (prob.getType() == null) { + prob.setType(ErrorConsts.WT_VALIDATION); + } + // [WSTX-154]: was catching and dropping thrown exception: shouldn't. + rep.report(prob.getMessage(), prob.getType(), prob, loc); + } + } + + /** + * Method needed for error message generation + */ + protected abstract String getTopElementDesc(); + + /* + /////////////////////////////////////////////////////////// + // Package methods, other + /////////////////////////////////////////////////////////// + */ + + protected final char[] getCopyBuffer() + { + char[] buf = mCopyBuffer; + if (buf == null) { + mCopyBuffer = buf = mConfig.allocMediumCBuffer(DEFAULT_COPYBUFFER_LEN); + } + return buf; + } + + protected final char[] getCopyBuffer(int minLen) + { + char[] buf = mCopyBuffer; + if (buf == null || minLen > buf.length) { + mCopyBuffer = buf = mConfig.allocMediumCBuffer(Math.max(DEFAULT_COPYBUFFER_LEN, minLen)); + } + return buf; + } + + @Override + public String toString() + { + return "[StreamWriter: "+getClass()+", underlying outputter: " + +((mWriter == null) ? "NULL" : mWriter.toString()+"]"); + } +} diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/sw/BufferingXmlWriter.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/sw/BufferingXmlWriter.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/sw/BufferingXmlWriter.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/sw/BufferingXmlWriter.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,1716 @@ +/* Woodstox XML processor + * + * Copyright (c) 2004- Tatu Saloranta, tatu.saloranta@iki.fi + * + * Licensed under the License specified in file LICENSE, included with + * the source code. + * You may not use this file except in compliance with the License. + * + * 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 com.ctc.wstx.sw; + +import java.io.IOException; +import java.io.OutputStream; +import java.io.Writer; +import java.util.Arrays; + +import javax.xml.stream.XMLStreamConstants; +import javax.xml.stream.XMLStreamException; + +import org.codehaus.stax2.ri.typed.AsciiValueEncoder; +import org.codehaus.stax2.validation.XMLValidator; + +import com.ctc.wstx.api.WriterConfig; +import com.ctc.wstx.io.CharsetNames; +import com.ctc.wstx.io.CompletelyCloseable; + +/** + * Concrete implementation of {@link XmlWriter} that will dispatch writes + * to another writer (of type {@link java.io.Writer}, and will NOT handle + * encoding. It will, however, do basic buffering such that the underlying + * Writer need (and thus, should) not do buffering. + *

+ * One design goal for this class is to avoid unnecessary buffering: since + * there will be another Writer doing the actual encoding, amount of + * buffering needed should still be limited. To this end, a threshold is + * used to define what's the threshold of writes that we do want to + * coalesce, ie. buffer. Writes bigger than this should in general proceed + * without buffering. + */ +public final class BufferingXmlWriter + extends XmlWriter + implements XMLStreamConstants +{ + /** + * Let's use a typical default to have a compromise between large + * enough chunks to output, and minimizing memory overhead. + * Compared to encoding writers, buffer size can be bit smaller + * since there's one more level of processing (at encoding), which + * may use bigger buffering. + */ + final static int DEFAULT_BUFFER_SIZE = 1000; + + /** + * Choosing threshold for 'small size' is a compromise between + * excessive buffering (high small size), and too many fragmented + * calls to the underlying writer (low small size). Let's just + * use about 1/4 of the full buffer size. + */ + final static int DEFAULT_SMALL_SIZE = 256; + + /** + * Highest valued character that may need to be encoded (minus charset + * encoding requirements) when writing attribute values. + */ + protected final static int HIGHEST_ENCODABLE_ATTR_CHAR = '<'; + + /** + * Highest valued character that may need to be encoded (minus charset + * encoding requirements) when writing attribute values. + */ + protected final static int HIGHEST_ENCODABLE_TEXT_CHAR = '>'; + + protected final static int[] QUOTABLE_TEXT_CHARS; + static { + int[] q = new int[4096]; + Arrays.fill(q, 0, 32, 1); + Arrays.fill(q, 127, 160, 1); + q['\t'] = 0; + q['\n'] = 0; + q['<'] = 1; + q['>'] = 1; + q['&'] = 1; + QUOTABLE_TEXT_CHARS = q; + } + + /* + //////////////////////////////////////////////// + // Output state, buffering + //////////////////////////////////////////////// + */ + + /** + * Actual Writer to use for outputting buffered data as appropriate. + */ + protected final Writer mOut; + + protected char[] mOutputBuffer; + + /** + * This is the threshold used to check what is considered a "small" + * write; small writes will be buffered until resulting size will + * be above the threshold. + */ + protected final int mSmallWriteSize; + + protected int mOutputPtr; + + protected int mOutputBufLen; + + /** + * Actual physical stream that the writer is using, if known. + * Not used for actual output, only needed so that calling + * application may (try to) figure out the original + * source. + */ + protected final OutputStream mUnderlyingStream; + + /* + //////////////////////////////////////////////// + // Encoding/escaping configuration + //////////////////////////////////////////////// + */ + + /** + * First Unicode character (one with lowest value) after (and including) + * which character entities have to be used. For + */ + private final int mEncHighChar; + + /** + * Character that is considered to be the enclosing quote character; + * for XML either single or double quote. + */ + final char mEncQuoteChar; + + /** + * Entity String to use for escaping the quote character. + */ + final String mEncQuoteEntity; + + /* + //////////////////////////////////////////////// + // Life-cycle + //////////////////////////////////////////////// + */ + + /** + * @param outs Underlying OutputStream that the writer + * (out) is using, if known. Needed to support + * (optional) access to the underlying stream + */ + public BufferingXmlWriter(Writer out, WriterConfig cfg, String enc, + boolean autoclose, + OutputStream outs, int bitsize) + throws IOException + { + super(cfg, enc, autoclose); + mOut = out; + mOutputBuffer = cfg.allocFullCBuffer(DEFAULT_BUFFER_SIZE); + mOutputBufLen = mOutputBuffer.length; + mSmallWriteSize = DEFAULT_SMALL_SIZE; + mOutputPtr = 0; + + mUnderlyingStream = outs; + + // Let's use double-quotes, as usual; alternative is apostrophe + mEncQuoteChar = '"'; + mEncQuoteEntity = """; + /* Note: let's actually exclude couple of illegal chars for + * unicode-based encoders. But we do not have to worry about + * surrogates quite here, fortunately. + */ + if (bitsize < 1) { + bitsize = guessEncodingBitSize(enc); + } + mEncHighChar = ((bitsize < 16) ? (1 << bitsize) : 0xFFFE); + } + + @Override + protected int getOutputPtr() { + return mOutputPtr; + } + + /* + //////////////////////////////////////////////// + // Raw access to underlying output objects + //////////////////////////////////////////////// + */ + + @Override + final protected OutputStream getOutputStream() { + return mUnderlyingStream; + } + + @Override + final protected Writer getWriter() { + return mOut; + } + + /* + //////////////////////////////////////////////// + // Low-level (pass-through) methods + //////////////////////////////////////////////// + */ + + @Override + public void close(boolean forceRealClose) throws IOException + { + flush(); + mTextWriter = null; + mAttrValueWriter = null; + + // Buffers to free? + char[] buf = mOutputBuffer; + if (buf != null) { + mOutputBuffer = null; + mConfig.freeFullCBuffer(buf); + } + // Plus may need to close the actual writer + if (forceRealClose || mAutoCloseOutput) { + /* 14-Nov-2008, TSa: To resolve [WSTX-163], need to have a way + * to force UTF8Writer to close the underlying stream... + */ + if (mOut instanceof CompletelyCloseable) { + ((CompletelyCloseable)mOut).closeCompletely(); + } else { + mOut.close(); + } + } + } + + @Override + public final void flush() throws IOException + { + flushBuffer(); + mOut.flush(); + } + + @Override + public void writeRaw(char[] cbuf, int offset, int len) throws IOException + { + if (mOut == null) { + return; + } + + // First; is the new request small or not? If yes, needs to be buffered + if (len < mSmallWriteSize) { // yup + // Does it fit in with current buffer? If not, need to flush first + if ((mOutputPtr + len) > mOutputBufLen) { + flushBuffer(); + } + System.arraycopy(cbuf, offset, mOutputBuffer, mOutputPtr, len); + mOutputPtr += len; + return; + } + + // Ok, not a small request. But buffer may have existing content? + int ptr = mOutputPtr; + if (ptr > 0) { + // If it's a small chunk, need to fill enough before flushing + if (ptr < mSmallWriteSize) { + /* Also, if we are to copy any stuff, let's make sure + * that we either copy it all in one chunk, or copy + * enough for non-small chunk, flush, and output remaining + * non-small chink (former possible if chunk we were requested + * to output is only slightly over 'small' size) + */ + int needed = (mSmallWriteSize - ptr); + + // Just need minimal copy: + System.arraycopy(cbuf, offset, mOutputBuffer, ptr, needed); + mOutputPtr = ptr + needed; + len -= needed; + offset += needed; + } + flushBuffer(); + } + + // And then we'll just write whatever we have left: + mOut.write(cbuf, offset, len); + } + + /** + * Method called to output typed values (int, long, double, float etc) + * that are known not to contain any escapable characters, or anything + * else beyond 7-bit ascii range. + */ + @Override + public final void writeRawAscii(char[] cbuf, int offset, int len) + throws IOException + { + // Can't optimize any further with buffering writer, so: + writeRaw(cbuf, offset, len); + } + + @Override + public void writeRaw(String str) throws IOException + { + if (mOut == null) { + return; + } + final int len = str.length(); + + // First; is the new request small or not? If yes, needs to be buffered + if (len < mSmallWriteSize) { // yup + // Does it fit in with current buffer? If not, need to flush first + if ((mOutputPtr + len) >= mOutputBufLen) { + flushBuffer(); + } + str.getChars(0, len, mOutputBuffer, mOutputPtr); + mOutputPtr += len; + return; + } + // Otherwise, let's just call the main method + writeRaw(str, 0, len); + } + + @Override + public void writeRaw(String str, int offset, int len) throws IOException + { + if (mOut == null) { + return; + } + + // First; is the new request small or not? If yes, needs to be buffered + if (len < mSmallWriteSize) { // yup + // Does it fit in with current buffer? If not, need to flush first + if ((mOutputPtr + len) >= mOutputBufLen) { + flushBuffer(); + } + str.getChars(offset, offset+len, mOutputBuffer, mOutputPtr); + mOutputPtr += len; + return; + } + + // Ok, not a small request. But buffer may have existing content? + int ptr = mOutputPtr; + if (ptr > 0) { + // If it's a small chunk, need to fill enough before flushing + if (ptr < mSmallWriteSize) { + /* Also, if we are to copy any stuff, let's make sure + * that we either copy it all in one chunk, or copy + * enough for non-small chunk, flush, and output remaining + * non-small chunk (former possible if chunk we were requested + * to output is only slightly over 'small' size) + */ + int needed = (mSmallWriteSize - ptr); + + // Just need minimal copy: + str.getChars(offset, offset+needed, mOutputBuffer, ptr); + mOutputPtr = ptr + needed; + len -= needed; + offset += needed; + } + flushBuffer(); + } + + // And then we'll just write whatever we have left: + mOut.write(str, offset, len); + } + + /* + //////////////////////////////////////////////// + // "Trusted" low-level output methods + //////////////////////////////////////////////// + */ + + @Override + public final void writeCDataStart() throws IOException { + fastWriteRaw(""); + } + + @Override + public final void writeCommentStart() throws IOException { + fastWriteRaw(""); + } + + @Override + public final void writePIStart(String target, boolean addSpace) throws IOException + { + fastWriteRaw('<', '?'); + fastWriteRaw(target); + if (addSpace) { + fastWriteRaw(' '); + } + } + + @Override + public final void writePIEnd() throws IOException { + fastWriteRaw('?', '>'); + } + + /* + //////////////////////////////////////////////// + // Higher-level output methods, text output + //////////////////////////////////////////////// + */ + + @Override + public int writeCData(String data) throws IOException + { + if (mCheckContent) { + int ix = verifyCDataContent(data); + if (ix >= 0) { + if (!mFixContent) { // Can we fix it? + return ix; + } + // Yes we can! (...Bob the Builder...) + writeSegmentedCData(data, ix); + return -1; + } + } + fastWriteRaw(""); + return -1; + } + + @Override + public int writeCData(char[] cbuf, int offset, int len) throws IOException + { + if (mCheckContent) { + int ix = verifyCDataContent(cbuf, offset, len); + if (ix >= 0) { + if (!mFixContent) { // Can we fix it? + return ix; + } + // Yes we can! (...Bob the Builder...) + writeSegmentedCData(cbuf, offset, len, ix); + return -1; + } + } + fastWriteRaw(""); + return -1; + } + + @Override + public void writeCharacters(String text) throws IOException + { + if (mOut == null) { + return; + } + if (mTextWriter != null) { // custom escaping? + mTextWriter.write(text); + return; + } + int inPtr = 0; + final int len = text.length(); + + // nope, default: + final int[] QC = QUOTABLE_TEXT_CHARS; + final int highChar = mEncHighChar; + final int MAXQC = Math.min(QC.length, highChar); + + main_loop: + while (true) { + String ent = null; + + inner_loop: + while (true) { + if (inPtr >= len) { + break main_loop; + } + char c = text.charAt(inPtr++); + + if (c < MAXQC) { + if (QC[c] != 0) { + if (c < 0x0020) { + if (c != ' ' && c != '\n' && c != '\t') { // fine as is + if (c == '\r') { + if (mEscapeCR) { + break inner_loop; + } + } else { + if (!mXml11 || c == 0) { + c = handleInvalidChar(c); // throws an error usually + ent = String.valueOf((char) c); + } else { + break inner_loop; // need quoting + } + } + } + } else if (c == '<') { + ent = "<"; + break inner_loop; + } else if (c == '&') { + ent = "&"; + break inner_loop; + } else if (c == '>') { + // Let's be conservative; and if there's any + // change it might be part of "]]>" quote it + if (inPtr < 2 || text.charAt(inPtr-2) == ']') { + ent = ">"; + break inner_loop; + } + } else if (c >= 0x7F) { + break; + } + } + } else if (c >= highChar) { + break inner_loop; + } + if (mOutputPtr >= mOutputBufLen) { + flushBuffer(); + } + mOutputBuffer[mOutputPtr++] = c; + } + if (ent != null) { + writeRaw(ent); + } else { + writeAsEntity(text.charAt(inPtr-1)); + } + } + } + + @Override + public void writeCharacters(char[] cbuf, int offset, int len) throws IOException + { + if (mOut == null) { + return; + } + if (mTextWriter != null) { // custom escaping? + mTextWriter.write(cbuf, offset, len); + return; + } + // nope, default: + final int[] QC = QUOTABLE_TEXT_CHARS; + final int highChar = mEncHighChar; + final int MAXQC = Math.min(QC.length, highChar); + len += offset; + do { + int c = 0; + int start = offset; + String ent = null; + + for (; offset < len; ++offset) { + c = cbuf[offset]; + + if (c < MAXQC) { + if (QC[c] != 0) { + // Ok, possibly needs quoting... further checks needed + if (c == '<') { + ent = "<"; + break; + } else if (c == '&') { + ent = "&"; + break; + } else if (c == '>') { + /* Let's be conservative; and if there's any + * change it might be part of "]]>" quote it + */ + if ((offset == start) || cbuf[offset-1] == ']') { + ent = ">"; + break; + } + } else if (c < 0x0020) { + if (c == '\n' || c == '\t') { // fine as is + ; + } else if (c == '\r') { + if (mEscapeCR) { + break; + } + } else { + if (!mXml11 || c == 0) { + c = handleInvalidChar(c); + // Hmmh. This is very inefficient, but... + ent = String.valueOf((char) c); + } + break; // need quoting + } + } else if (c >= 0x7F) { + break; + } + } + } else if (c >= highChar) { + break; + } + // otherwise fine + } + int outLen = offset - start; + if (outLen > 0) { + writeRaw(cbuf, start, outLen); + } + if (ent != null) { + writeRaw(ent); + ent = null; + } else if (offset < len) { + writeAsEntity(c); + } + } while (++offset < len); + } + + /** + * Method that will try to output the content as specified. If + * the content passed in has embedded "--" in it, it will either + * add an intervening space between consequtive hyphens (if content + * fixing is enabled), or return the offset of the first hyphen in + * multi-hyphen sequence. + */ + @Override + public int writeComment(String data) throws IOException + { + if (mCheckContent) { + int ix = verifyCommentContent(data); + if (ix >= 0) { + if (!mFixContent) { // Can we fix it? + return ix; + } + // Yes we can! (...Bob the Builder...) + writeSegmentedComment(data, ix); + return -1; + } + } + fastWriteRaw(""); + return -1; + } + + @Override + public void writeDTD(String data) throws IOException + { + writeRaw(data); + } + + @Override + public void writeDTD(String rootName, String systemId, String publicId, + String internalSubset) + throws IOException, XMLStreamException + { + fastWriteRaw(" 0) { + fastWriteRaw(' ', '['); + fastWriteRaw(internalSubset); + fastWriteRaw(']'); + } + fastWriteRaw('>'); + } + + @Override + public void writeEntityReference(String name) + throws IOException, XMLStreamException + { + if (mCheckNames) { + verifyNameValidity(name, mNsAware); + } + fastWriteRaw('&'); + fastWriteRaw(name); + fastWriteRaw(';'); + } + + @Override + public void writeXmlDeclaration(String version, String encoding, String standalone) + throws IOException + { + final char chQuote = (mUseDoubleQuotesInXmlDecl ? '"' : '\''); + + fastWriteRaw(" 0) { + fastWriteRaw(" encoding="); + fastWriteRaw(chQuote); + fastWriteRaw(encoding); + fastWriteRaw(chQuote); + } + if (standalone != null) { + fastWriteRaw(" standalone="); + fastWriteRaw(chQuote); + fastWriteRaw(standalone); + fastWriteRaw(chQuote); + } + fastWriteRaw('?', '>'); + } + + @Override + public int writePI(String target, String data) + throws IOException, XMLStreamException + { + if (mCheckNames) { + // As per namespace specs, can not have colon(s) + verifyNameValidity(target, mNsAware); + } + fastWriteRaw('<', '?'); + fastWriteRaw(target); + if (data != null && data.length() > 0) { + if (mCheckContent) { + int ix = data.indexOf('?'); + if (ix >= 0) { + ix = data.indexOf("?>", ix); + if (ix >= 0) { + return ix; + } + } + } + fastWriteRaw(' '); + // Data may be longer, let's call regular writeRaw method + writeRaw(data); + } + fastWriteRaw('?', '>'); + return -1; + } + + /* + //////////////////////////////////////////////////// + // Write methods, elements + //////////////////////////////////////////////////// + */ + + @Override + public void writeStartTagStart(String localName) + throws IOException, XMLStreamException + { + if (mCheckNames) { + verifyNameValidity(localName, mNsAware); + } + + int ptr = mOutputPtr; + int extra = (mOutputBufLen - ptr) - (1 + localName.length()); + if (extra < 0) { // split on boundary, slower + fastWriteRaw('<'); + fastWriteRaw(localName); + } else { + char[] buf = mOutputBuffer; + buf[ptr++] = '<'; + int len = localName.length(); + localName.getChars(0, len, buf, ptr); + mOutputPtr = ptr+len; + } + } + + @Override + public void writeStartTagStart(String prefix, String localName) + throws IOException, XMLStreamException + { + if (prefix == null || prefix.length() == 0) { // shouldn't happen + writeStartTagStart(localName); + return; + } + + if (mCheckNames) { + verifyNameValidity(prefix, mNsAware); + verifyNameValidity(localName, mNsAware); + } + + int ptr = mOutputPtr; + int len = prefix.length(); + int extra = (mOutputBufLen - ptr) - (2 + localName.length() + len); + if (extra < 0) { // across buffer boundary, slow case + fastWriteRaw('<'); + fastWriteRaw(prefix); + fastWriteRaw(':'); + fastWriteRaw(localName); + } else { // fast case, all inlined + char[] buf = mOutputBuffer; + buf[ptr++] = '<'; + prefix.getChars(0, len, buf, ptr); + ptr += len; + buf[ptr++] = ':'; + len = localName.length(); + localName.getChars(0, len, buf, ptr); + mOutputPtr = ptr+len; + } + } + + @Override + public void writeStartTagEnd() throws IOException { + fastWriteRaw('>'); + } + + @Override + public void writeStartTagEmptyEnd() throws IOException + { + int ptr = mOutputPtr; + if ((ptr + 3) >= mOutputBufLen) { + if (mOut == null) { + return; + } + flushBuffer(); + ptr = mOutputPtr; + } + char[] buf = mOutputBuffer; + if (mAddSpaceAfterEmptyElem) { + buf[ptr++] = ' '; + } + buf[ptr++] = '/'; + buf[ptr++] = '>'; + mOutputPtr = ptr; + } + + @Override + public void writeEndTag(String localName) throws IOException + { + int ptr = mOutputPtr; + int extra = (mOutputBufLen - ptr) - (3 + localName.length()); + if (extra < 0) { + fastWriteRaw('<', '/'); + fastWriteRaw(localName); + fastWriteRaw('>'); + } else { + char[] buf = mOutputBuffer; + buf[ptr++] = '<'; + buf[ptr++] = '/'; + int len = localName.length(); + localName.getChars(0, len, buf, ptr); + ptr += len; + buf[ptr++] = '>'; + mOutputPtr = ptr; + } + } + + @Override + public void writeEndTag(String prefix, String localName) throws IOException + { + if (prefix == null || prefix.length() == 0) { + writeEndTag(localName); + return; + } + int ptr = mOutputPtr; + int len = prefix.length(); + int extra = (mOutputBufLen - ptr) - (4 + localName.length() + len); + if (extra < 0) { + fastWriteRaw('<', '/'); + /* At this point, it is assumed caller knows that end tag + * matches with start tag, and that it (by extension) has been + * validated if and as necessary + */ + fastWriteRaw(prefix); + fastWriteRaw(':'); + fastWriteRaw(localName); + fastWriteRaw('>'); + } else { + char[] buf = mOutputBuffer; + buf[ptr++] = '<'; + buf[ptr++] = '/'; + prefix.getChars(0, len, buf, ptr); + ptr += len; + buf[ptr++] = ':'; + len = localName.length(); + localName.getChars(0, len, buf, ptr); + ptr += len; + buf[ptr++] = '>'; + mOutputPtr = ptr; + } + } + + /* + //////////////////////////////////////////////////// + // Write methods, attributes/ns + //////////////////////////////////////////////////// + */ + + @Override + public void writeAttribute(String localName, String value) + throws IOException, XMLStreamException + { + if (mOut == null) { + return; + } + if (mCheckNames) { + verifyNameValidity(localName, mNsAware); + } + int len = localName.length(); + if (((mOutputBufLen - mOutputPtr) - (3 + len)) < 0) { + fastWriteRaw(' '); + fastWriteRaw(localName); + fastWriteRaw('=', '"'); + } else { + int ptr = mOutputPtr; + char[] buf = mOutputBuffer; + buf[ptr++] = ' '; + localName.getChars(0, len, buf, ptr); + ptr += len; + buf[ptr++] = '='; + buf[ptr++] = '"'; + mOutputPtr = ptr; + } + + len = (value == null) ? 0 : value.length(); + if (len > 0) { + if (mAttrValueWriter != null) { // custom escaping? + mAttrValueWriter.write(value, 0, len); + } else { // nope, default + writeAttrValue(value, len); + } + } + fastWriteRaw('"'); + } + + @Override + public void writeAttribute(String localName, char[] value, int offset, int vlen) + throws IOException, XMLStreamException + { + if (mOut == null) { + return; + } + if (mCheckNames) { + verifyNameValidity(localName, mNsAware); + } + int len = localName.length(); + if (((mOutputBufLen - mOutputPtr) - (3 + len)) < 0) { + fastWriteRaw(' '); + fastWriteRaw(localName); + fastWriteRaw('=', '"'); + } else { + int ptr = mOutputPtr; + char[] buf = mOutputBuffer; + buf[ptr++] = ' '; + localName.getChars(0, len, buf, ptr); + ptr += len; + buf[ptr++] = '='; + buf[ptr++] = '"'; + mOutputPtr = ptr; + } + + if (vlen > 0) { + if (mAttrValueWriter != null) { // custom escaping? + mAttrValueWriter.write(value, offset, vlen); + } else { // nope, default + writeAttrValue(value, offset, vlen); + } + } + fastWriteRaw('"'); + } + + @Override + public void writeAttribute(String prefix, String localName, String value) + throws IOException, XMLStreamException + { + if (mOut == null) { + return; + } + if (mCheckNames) { + verifyNameValidity(prefix, mNsAware); + verifyNameValidity(localName, mNsAware); + } + int len = prefix.length(); + if (((mOutputBufLen - mOutputPtr) - (4 + localName.length() + len)) < 0) { + fastWriteRaw(' '); + if (len > 0) { + fastWriteRaw(prefix); + fastWriteRaw(':'); + } + fastWriteRaw(localName); + fastWriteRaw('=', '"'); + } else { + int ptr = mOutputPtr; + char[] buf = mOutputBuffer; + buf[ptr++] = ' '; + prefix.getChars(0, len, buf, ptr); + ptr += len; + buf[ptr++] = ':'; + len = localName.length(); + localName.getChars(0, len, buf, ptr); + ptr += len; + buf[ptr++] = '='; + buf[ptr++] = '"'; + mOutputPtr = ptr; + } + + len = (value == null) ? 0 : value.length(); + if (len > 0) { + if (mAttrValueWriter != null) { // custom escaping? + mAttrValueWriter.write(value, 0, len); + } else { // nope, default + writeAttrValue(value, len); + } + } + fastWriteRaw('"'); + } + + @Override + public void writeAttribute(String prefix, String localName, char[] value, int offset, int vlen) + throws IOException, XMLStreamException + { + if (mOut == null) { + return; + } + if (mCheckNames) { + verifyNameValidity(prefix, mNsAware); + verifyNameValidity(localName, mNsAware); + } + int len = prefix.length(); + if (((mOutputBufLen - mOutputPtr) - (4 + localName.length() + len)) < 0) { + fastWriteRaw(' '); + if (len > 0) { + fastWriteRaw(prefix); + fastWriteRaw(':'); + } + fastWriteRaw(localName); + fastWriteRaw('=', '"'); + } else { + int ptr = mOutputPtr; + char[] buf = mOutputBuffer; + buf[ptr++] = ' '; + prefix.getChars(0, len, buf, ptr); + ptr += len; + buf[ptr++] = ':'; + len = localName.length(); + localName.getChars(0, len, buf, ptr); + ptr += len; + buf[ptr++] = '='; + buf[ptr++] = '"'; + mOutputPtr = ptr; + } + if (vlen > 0) { + if (mAttrValueWriter != null) { // custom escaping? + mAttrValueWriter.write(value, offset, vlen); + } else { // nope, default + writeAttrValue(value, offset, vlen); + } + } + fastWriteRaw('"'); + } + + private final void writeAttrValue(String value, int len) + throws IOException + { + int inPtr = 0; + final char qchar = mEncQuoteChar; + int highChar = mEncHighChar; + + main_loop: + while (true) { // main_loop + String ent = null; + + inner_loop: + while (true) { + if (inPtr >= len) { + break main_loop; + } + char c = value.charAt(inPtr++); + if (c <= HIGHEST_ENCODABLE_ATTR_CHAR) { // special char? + if (c < 0x0020) { // tab, cr/lf need encoding too + if (c == '\r') { + if (mEscapeCR) { + break inner_loop; // quoting + } + } else if (c != '\n' && c != '\t' + && (!mXml11 || c == 0)) { + c = handleInvalidChar(c); + } else { + break inner_loop; // need quoting + } + } else if (c == qchar) { + ent = mEncQuoteEntity; + break inner_loop; + } else if (c == '<') { + ent = "<"; + break inner_loop; + } else if (c == '&') { + ent = "&"; + break inner_loop; + } + } else if (c >= highChar) { // out of range, have to escape + break inner_loop; + } + if (mOutputPtr >= mOutputBufLen) { + flushBuffer(); + } + mOutputBuffer[mOutputPtr++] = c; + } + if (ent != null) { + writeRaw(ent); + } else { + writeAsEntity(value.charAt(inPtr-1)); + } + } + } + + private final void writeAttrValue(char[] value, int offset, int len) + throws IOException + { + len += offset; + final char qchar = mEncQuoteChar; + int highChar = mEncHighChar; + + main_loop: + while (true) { // main_loop + String ent = null; + + inner_loop: + while (true) { + if (offset >= len) { + break main_loop; + } + char c = value[offset++]; + if (c <= HIGHEST_ENCODABLE_ATTR_CHAR) { // special char? + if (c < 0x0020) { // tab, cr/lf need encoding too + if (c == '\r') { + if (mEscapeCR) { + break inner_loop; // quoting + } + } else if (c != '\n' && c != '\t' + && (!mXml11 || c == 0)) { + c = handleInvalidChar(c); + } else { + break inner_loop; // need quoting + } + } else if (c == qchar) { + ent = mEncQuoteEntity; + break inner_loop; + } else if (c == '<') { + ent = "<"; + break inner_loop; + } else if (c == '&') { + ent = "&"; + break inner_loop; + } + } else if (c >= highChar) { // out of range, have to escape + break inner_loop; + } + if (mOutputPtr >= mOutputBufLen) { + flushBuffer(); + } + mOutputBuffer[mOutputPtr++] = c; + } + if (ent != null) { + writeRaw(ent); + } else { + writeAsEntity(value[offset-1]); + } + } + } + + /* + //////////////////////////////////////////////// + // Methods used by Typed Access API + //////////////////////////////////////////////// + */ + + @Override + public final void writeTypedElement(AsciiValueEncoder enc) + throws IOException + { + if (mOut == null) { + return; + } + + int free = mOutputBufLen - mOutputPtr; + if (enc.bufferNeedsFlush(free)) { + flush(); + } + while (true) { + mOutputPtr = enc.encodeMore(mOutputBuffer, mOutputPtr, mOutputBufLen); + // If no flushing needed, indicates that all data was encoded + if (enc.isCompleted()) { + break; + } + flush(); + } + } + + @Override + public final void writeTypedElement(AsciiValueEncoder enc, + XMLValidator validator, char[] copyBuffer) + throws IOException, XMLStreamException + { + if (mOut == null) { + return; + } + int free = mOutputBufLen - mOutputPtr; + if (enc.bufferNeedsFlush(free)) { + flush(); + } + int start = mOutputPtr; + while (true) { + mOutputPtr = enc.encodeMore(mOutputBuffer, mOutputPtr, mOutputBufLen); + // False -> can't be sure it's the whole remaining text + validator.validateText(mOutputBuffer, start, mOutputPtr, false); + if (enc.isCompleted()) { + break; + } + flush(); + start = mOutputPtr; + } + } + + @Override + public void writeTypedAttribute(String localName, AsciiValueEncoder enc) + throws IOException, XMLStreamException + { + if (mOut == null) { + return; + } + if (mCheckNames) { + verifyNameValidity(localName, mNsAware); + } + int len = localName.length(); + if ((mOutputPtr + 3 + len) > mOutputBufLen) { + fastWriteRaw(' '); + fastWriteRaw(localName); + fastWriteRaw('=', '"'); + } else { + int ptr = mOutputPtr; + char[] buf = mOutputBuffer; + buf[ptr++] = ' '; + localName.getChars(0, len, buf, ptr); + ptr += len; + buf[ptr++] = '='; + buf[ptr++] = '"'; + mOutputPtr = ptr; + } + + int free = mOutputBufLen - mOutputPtr; + if (enc.bufferNeedsFlush(free)) { + flush(); + } + while (true) { + mOutputPtr = enc.encodeMore(mOutputBuffer, mOutputPtr, mOutputBufLen); + if (enc.isCompleted()) { + break; + } + flush(); + } + fastWriteRaw('"'); + } + + @Override + public void writeTypedAttribute(String prefix, String localName, + AsciiValueEncoder enc) + throws IOException, XMLStreamException + { + if (mOut == null) { + return; + } + if (mCheckNames) { + verifyNameValidity(prefix, mNsAware); + verifyNameValidity(localName, mNsAware); + } + int plen = prefix.length(); + int llen = localName.length(); + + if ((mOutputPtr + 4 + plen + llen) > mOutputBufLen) { + writePrefixedName(prefix, localName); + fastWriteRaw('=', '"'); + } else { + int ptr = mOutputPtr; + char[] buf = mOutputBuffer; + buf[ptr++] = ' '; + if (plen > 0) { + prefix.getChars(0, plen, buf, ptr); + ptr += plen; + buf[ptr++] = ':'; + + } + localName.getChars(0, llen, buf, ptr); + ptr += llen; + buf[ptr++] = '='; + buf[ptr++] = '"'; + mOutputPtr = ptr; + } + + int free = mOutputBufLen - mOutputPtr; + if (enc.bufferNeedsFlush(free)) { + flush(); + } + while (true) { + mOutputPtr = enc.encodeMore(mOutputBuffer, mOutputPtr, mOutputBufLen); + if (enc.isCompleted()) { + break; + } + flush(); + } + + fastWriteRaw('"'); + } + + @Override + public void writeTypedAttribute(String prefix, String localName, String nsURI, + AsciiValueEncoder enc, + XMLValidator validator, char[] copyBuffer) + throws IOException, XMLStreamException + { + if (mOut == null) { + return; + } + if (prefix == null) { + prefix = ""; + } + if (nsURI == null) { + nsURI = ""; + } + int plen = prefix.length(); + if (mCheckNames) { + if (plen > 0) { + verifyNameValidity(prefix, mNsAware); + } + verifyNameValidity(localName, mNsAware); + } + if (((mOutputBufLen - mOutputPtr) - (4 + localName.length() + plen)) < 0) { + writePrefixedName(prefix, localName); + fastWriteRaw('=', '"'); + } else { + int ptr = mOutputPtr; + char[] buf = mOutputBuffer; + buf[ptr++] = ' '; + if (plen > 0) { + prefix.getChars(0, plen, buf, ptr); + ptr += plen; + buf[ptr++] = ':'; + + } + int llen = localName.length(); + localName.getChars(0, llen, buf, ptr); + ptr += llen; + buf[ptr++] = '='; + buf[ptr++] = '"'; + mOutputPtr = ptr; + } + + /* Tricky here is this: attributes to validate can not be + * split (validators expect complete values). So, if value + * won't fit as is, may need to aggregate using StringBuilder + */ + int free = mOutputBufLen - mOutputPtr; + if (enc.bufferNeedsFlush(free)) { + flush(); + } + int start = mOutputPtr; + + // First, let's see if one call is enough + mOutputPtr = enc.encodeMore(mOutputBuffer, mOutputPtr, mOutputBufLen); + if (enc.isCompleted()) { // yup + validator.validateAttribute(localName, nsURI, prefix, mOutputBuffer, start, mOutputPtr); + return; + } + + // If not, must combine first + StringBuilder sb = new StringBuilder(mOutputBuffer.length << 1); + sb.append(mOutputBuffer, start, mOutputPtr-start); + while (true) { + flush(); + start = mOutputPtr; + mOutputPtr = enc.encodeMore(mOutputBuffer, mOutputPtr, mOutputBufLen); + sb.append(mOutputBuffer, start, mOutputPtr-start); + // All done? + if (enc.isCompleted()) { + break; + } + } + fastWriteRaw('"'); + + // Then validate + String valueStr = sb.toString(); + validator.validateAttribute(localName, nsURI, prefix, valueStr); + } + + protected final void writePrefixedName(String prefix, String localName) + throws IOException + { + fastWriteRaw(' '); + if (prefix.length() > 0) { + fastWriteRaw(prefix); + fastWriteRaw(':'); + } + fastWriteRaw(localName); + } + + /* + //////////////////////////////////////////////////// + // Internal methods, buffering + //////////////////////////////////////////////////// + */ + + private final void flushBuffer() + throws IOException + { + if (mOutputPtr > 0 && mOutputBuffer != null) { + int ptr = mOutputPtr; + // Need to update location info, to keep it in sync + mLocPastChars += ptr; + mLocRowStartOffset -= ptr; + mOutputPtr = 0; + mOut.write(mOutputBuffer, 0, ptr); + } + } + + private final void fastWriteRaw(char c) + throws IOException + { + if (mOutputPtr >= mOutputBufLen) { + if (mOut == null) { + return; + } + flushBuffer(); + } + mOutputBuffer[mOutputPtr++] = c; + } + + private final void fastWriteRaw(char c1, char c2) + throws IOException + { + if ((mOutputPtr + 1) >= mOutputBufLen) { + if (mOut == null) { + return; + } + flushBuffer(); + } + mOutputBuffer[mOutputPtr++] = c1; + mOutputBuffer[mOutputPtr++] = c2; + } + + private final void fastWriteRaw(String str) + throws IOException + { + int len = str.length(); + int ptr = mOutputPtr; + if ((ptr + len) >= mOutputBufLen) { + if (mOut == null) { + return; + } + /* It's even possible that String is longer than the buffer (not + * likely, possible). If so, let's just call the full + * method: + */ + if (len > mOutputBufLen) { + writeRaw(str); + return; + } + flushBuffer(); + ptr = mOutputPtr; + } + str.getChars(0, len, mOutputBuffer, ptr); + mOutputPtr = ptr+len; + } + + /* + //////////////////////////////////////////////////// + // Internal methods, content verification/fixing + //////////////////////////////////////////////////// + */ + + /** + * @return Index at which a problem was found, if any; -1 if there's + * no problem. + */ + protected int verifyCDataContent(String content) + { + if (content != null && content.length() >= 3) { + int ix = content.indexOf(']'); + if (ix >= 0) { + return content.indexOf("]]>", ix); + } + } + return -1; + } + + protected int verifyCDataContent(char[] c, int start, int end) + { + if (c != null) { + start += 2; + /* Let's do simple optimization for search... + * (simple bayer-moore - like algorithm) + */ + while (start < end) { + char ch = c[start]; + if (ch == ']') { + ++start; // let's just move by one in this case + continue; + } + if (ch == '>') { // match? + if (c[start-1] == ']' + && c[start-2] == ']') { + return start-2; + } + } + start += 2; + } + } + return -1; + } + + protected int verifyCommentContent(String content) + { + int ix = content.indexOf('-'); + if (ix >= 0) { + /* actually, it's illegal to just end with '-' too, since + * that would cause invalid end marker '--->' + */ + if (ix < (content.length() - 1)) { + ix = content.indexOf("--", ix); + } + } + return ix; + } + + protected void writeSegmentedCData(String content, int index) + throws IOException + { + /* It's actually fairly easy, just split "]]>" into 2 pieces; + * for each ']]>'; first one containing "]]", second one ">" + * (as long as necessary) + */ + int start = 0; + while (index >= 0) { + fastWriteRaw(""); + start = index+2; + index = content.indexOf("]]>", start); + } + // Ok, then the last segment + fastWriteRaw(""); + } + + protected void writeSegmentedCData(char[] c, int start, int len, int index) + throws IOException + { + int end = start + len; + while (index >= 0) { + fastWriteRaw(""); + start = index+2; + index = verifyCDataContent(c, start, end); + } + // Ok, then the last segment + fastWriteRaw(""); + } + + protected void writeSegmentedComment(String content, int index) + throws IOException + { + int len = content.length(); + // First the special case (last char is hyphen): + if (index == (len-1)) { + fastWriteRaw(""); + return; + } + + /* Fixing comments is more difficult than that of CDATA segments'; + * this because CDATA can still contain embedded ']]'s, but + * comment neither allows '--' nor ending with '-->'; which means + * that it's impossible to just split segments. Instead we'll do + * something more intrusive, and embed single spaces between all + * '--' character pairs... it's intrusive, but comments are not + * supposed to contain any data, so that should be fine (plus + * at least result is valid, unlike contents as is) + */ + fastWriteRaw(""); + } + + /** + * Method used to figure out which part of the Unicode char set the + * encoding can natively support. Values returned are 7, 8 and 16, + * to indicate (respectively) "ascii", "ISO-Latin" and "native Unicode". + * These just best guesses, but should work ok for the most common + * encodings. + */ + public static int guessEncodingBitSize(String enc) + { + if (enc == null || enc.length() == 0) { // let's assume default is UTF-8... + return 16; + } + + // Let's see if we can find a normalized name, first: + enc = CharsetNames.normalize(enc); + + // Ok, first, do we have known ones; starting with most common: + if (enc == CharsetNames.CS_UTF8) { + return 16; // meaning up to 2^16 can be represented natively + } else if (enc == CharsetNames.CS_ISO_LATIN1) { + return 8; + } else if (enc == CharsetNames.CS_US_ASCII) { + return 7; + } else if (enc == CharsetNames.CS_UTF16 + || enc == CharsetNames.CS_UTF16BE + || enc == CharsetNames.CS_UTF16LE + || enc == CharsetNames.CS_UTF32BE + || enc == CharsetNames.CS_UTF32LE) { + return 16; + } + + /* Above and beyond well-recognized names, it might still be + * good to have more heuristics for as-of-yet unhandled cases... + * But, it's probably easier to only assume 8-bit clean (could + * even make it just 7, let's see how this works out) + */ + return 8; + } + + protected final void writeAsEntity(int c) + throws IOException + { + char[] buf = mOutputBuffer; + int ptr = mOutputPtr; + if ((ptr + 10) >= buf.length) { // &#x [up to 6 hex digits] ; + flushBuffer(); + ptr = mOutputPtr; + } + buf[ptr++] = '&'; + + // Can use more optimal notation for 8-bit ascii stuff: + if (c < 256) { + /* Also; although not really mandatory, let's also + * use pre-defined entities where possible. + */ + if (c == '&') { + buf[ptr++] = 'a'; + buf[ptr++] = 'm'; + buf[ptr++] = 'p'; + } else if (c == '<') { + buf[ptr++] = 'l'; + buf[ptr++] = 't'; + } else if (c == '>') { + buf[ptr++] = 'g'; + buf[ptr++] = 't'; + } else if (c == '\'') { + buf[ptr++] = 'a'; + buf[ptr++] = 'p'; + buf[ptr++] = 'o'; + buf[ptr++] = 's'; + } else if (c == '"') { + buf[ptr++] = 'q'; + buf[ptr++] = 'u'; + buf[ptr++] = 'o'; + buf[ptr++] = 't'; + } else { + buf[ptr++] = '#';; + buf[ptr++] = 'x';; + // Can use shortest quoting for tab, cr, lf: + if (c >= 16) { + int digit = (c >> 4); + buf[ptr++] = (char) ((digit < 10) ? ('0' + digit) : (('a' - 10) + digit)); + c &= 0xF; + } + buf[ptr++] = (char) ((c < 10) ? ('0' + c) : (('a' - 10) + c)); + } + } else { + buf[ptr++] = '#'; + buf[ptr++] = 'x'; + + // Ok, let's write the shortest possible sequence then: + int shift = 20; + int origPtr = ptr; + + do { + int digit = (c >> shift) & 0xF; + if (digit > 0 || (ptr != origPtr)) { + buf[ptr++] = (char) ((digit < 10) ? ('0' + digit) : (('a' - 10) + digit)); + } + shift -= 4; + } while (shift > 0); + c &= 0xF; + buf[ptr++] = (char) ((c < 10) ? ('0' + c) : (('a' - 10) + c)); + } + buf[ptr++] = ';'; + mOutputPtr = ptr; + } +} diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/sw/EncodingXmlWriter.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/sw/EncodingXmlWriter.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/sw/EncodingXmlWriter.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/sw/EncodingXmlWriter.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,980 @@ +/* Woodstox XML processor + * + * Copyright (c) 2004- Tatu Saloranta, tatu.saloranta@iki.fi + * + * Licensed under the License specified in file LICENSE, included with + * the source code. + * You may not use this file except in compliance with the License. + * + * 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 com.ctc.wstx.sw; + +import java.io.IOException; +import java.io.OutputStream; +import java.io.Writer; + +import javax.xml.stream.XMLStreamException; + +import org.codehaus.stax2.ri.typed.AsciiValueEncoder; +import org.codehaus.stax2.validation.XMLValidator; + +import com.ctc.wstx.api.WriterConfig; +import com.ctc.wstx.cfg.XmlConsts; +//import com.ctc.wstx.io.CompletelyCloseable; + +/** + * Intermediate base class used when outputting to streams that use + * an encoding that is compatible with 7-bit single-byte Ascii encoding. + * That means it can be used for UTF-8, ISO-Latin1 and pure Ascii. + *

+ * Implementation notes: + *

+ * Parts of surrogate handling are implemented here in the base class: + * storage for the first part of a split surrogate (only possible when + * character content is output split in multiple calls) is within + * base class. Also, simple checks for unmatched surrogate pairs are + * in writeAscii method, since it is the most convenient + * place to catch cases where a text segment ends with an unmatched + * surrogate pair half. + */ +public abstract class EncodingXmlWriter + extends XmlWriter +{ + /** + * Let's use a typical default to have a compromise between large + * enough chunks to output, and minimizing memory overhead. + * 4k should be close enough to a physical page to work out + * acceptably, without causing excessive (if temporary) memory usage. + */ + final static int DEFAULT_BUFFER_SIZE = 4000; + + final static byte BYTE_SPACE = (byte) ' '; + final static byte BYTE_COLON = (byte) ':'; + final static byte BYTE_SEMICOLON = (byte) ';'; + final static byte BYTE_LBRACKET = (byte) '['; + final static byte BYTE_RBRACKET = (byte) ']'; + final static byte BYTE_QMARK = (byte) '?'; + final static byte BYTE_EQ = (byte) '='; + final static byte BYTE_SLASH = (byte) '/'; + final static byte BYTE_HASH = (byte) '#'; + final static byte BYTE_HYPHEN = (byte) '-'; + + final static byte BYTE_LT = (byte) '<'; + final static byte BYTE_GT = (byte) '>'; + final static byte BYTE_AMP = (byte) '&'; + final static byte BYTE_QUOT = (byte) '"'; + final static byte BYTE_APOS = (byte) '\''; + + final static byte BYTE_A = (byte) 'a'; + final static byte BYTE_G = (byte) 'g'; + final static byte BYTE_L = (byte) 'l'; + final static byte BYTE_M = (byte) 'm'; + final static byte BYTE_O = (byte) 'o'; + final static byte BYTE_P = (byte) 'p'; + final static byte BYTE_Q = (byte) 'q'; + final static byte BYTE_S = (byte) 's'; + final static byte BYTE_T = (byte) 't'; + final static byte BYTE_U = (byte) 'u'; + final static byte BYTE_X = (byte) 'x'; + + /* + //////////////////////////////////////////////// + // Output state, buffering + //////////////////////////////////////////////// + */ + + /** + * Actual output stream to use for outputting encoded content as + * bytes. + */ + private final OutputStream mOut; + + protected byte[] mOutputBuffer; + + protected int mOutputPtr; + + /** + * In case a split surrogate pair is output (which can only successfully + * occur with either writeRaw or + * writeCharacters), the first part is temporarily stored + * within this member variable. + */ + protected int mSurrogate = 0; + + /* + //////////////////////////////////////////////// + // + //////////////////////////////////////////////// + */ + + public EncodingXmlWriter(OutputStream out, WriterConfig cfg, String encoding, + boolean autoclose) + throws IOException + { + super(cfg, encoding, autoclose); + mOut = out; + mOutputBuffer = cfg.allocFullBBuffer(DEFAULT_BUFFER_SIZE); + mOutputPtr = 0; + } + + /** + * This method is needed by the super class, to calculate hard + * byte/char offsets. + */ + @Override + protected int getOutputPtr() { + return mOutputPtr; + } + + /* + //////////////////////////////////////////////// + // Partial API implementation + //////////////////////////////////////////////// + */ + + @Override + final protected OutputStream getOutputStream() { + return mOut; + } + + @Override + final protected Writer getWriter() { + // No writers are involved with these implementations... + return null; + } + + @Override + public void close(boolean forceRealClose) throws IOException + { + flush(); + + // Buffers to free? + byte[] buf = mOutputBuffer; + if (buf != null) { + mOutputBuffer = null; + mConfig.freeFullBBuffer(buf); + } + // Plus may need to close the actual stream + if (forceRealClose || mAutoCloseOutput) { + /* 14-Nov-2008, TSa: Wrt [WSTX-163]; no need to + * check whether mOut implements CompletelyCloseable + * (unlike with BufferingXmlWriter) + */ + mOut.close(); + } + } + + @Override + public final void flush() throws IOException + { + flushBuffer(); + mOut.flush(); + } + + @Override + public abstract void writeRaw(char[] cbuf, int offset, int len) + throws IOException; + + @Override + public abstract void writeRaw(String str, int offset, int len) + throws IOException; + + /* + ////////////////////////////////////////////////// + // "Trusted" low-level output methods (that do not + // need to verify validity of input) + ////////////////////////////////////////////////// + */ + + @Override + public final void writeCDataStart() + throws IOException + { + writeAscii(""); + } + + @Override + public final void writeCommentStart() + throws IOException + { + writeAscii(""); + } + + @Override + public final void writePIStart(String target, boolean addSpace) + throws IOException + { + writeAscii(BYTE_LT, BYTE_QMARK); + writeRaw(target); + if (addSpace) { + writeAscii(BYTE_SPACE); + } + } + + @Override + public final void writePIEnd() throws IOException + { + writeAscii(BYTE_QMARK, BYTE_GT); + } + + /* + //////////////////////////////////////////////// + // Higher-level output methods, text output + //////////////////////////////////////////////// + */ + + @Override + public int writeCData(String data) throws IOException + { + writeAscii("= 0) { + return ix; + } + writeAscii("]]>"); + return -1; + } + + @Override + public int writeCData(char[] cbuf, int offset, int len) + throws IOException + { + writeAscii("= 0) { + return ix; + } + writeAscii("]]>"); + return -1; + } + + @Override + public final void writeCharacters(String data) + throws IOException + { + // Note: may get second part of a surrogate + if (mTextWriter != null) { // custom escaping? + mTextWriter.write(data); + } else { // nope, default: + writeTextContent(data); + } + } + + @Override + public final void writeCharacters(char[] cbuf, int offset, int len) + throws IOException + { + // Note: may get second part of a surrogate + if (mTextWriter != null) { // custom escaping? + mTextWriter.write(cbuf, offset, len); + } else { // nope, default: + writeTextContent(cbuf, offset, len); + } + } + + /** + * Method that will try to output the content as specified. If + * the content passed in has embedded "--" in it, it will either + * add an intervening space between consequtive hyphens (if content + * fixing is enabled), or return the offset of the first hyphen in + * multi-hyphen sequence. + */ + @Override + public int writeComment(String data) + throws IOException + { + writeAscii(""); + return -1; + } + + @Override + public void writeDTD(String data) + throws IOException + { + if (mSurrogate != 0) { + throwUnpairedSurrogate(); + } + writeRaw(data, 0, data.length()); + } + + @Override + public void writeDTD(String rootName, String systemId, String publicId, + String internalSubset) + throws IOException, XMLStreamException + { + writeAscii(" 0) { + writeAscii(BYTE_SPACE, BYTE_LBRACKET); + writeRaw(internalSubset, 0, internalSubset.length()); + writeAscii(BYTE_RBRACKET); + } + writeAscii(BYTE_GT); + } + + @Override + public void writeEntityReference(String name) + throws IOException, XMLStreamException + { + if (mSurrogate != 0) { + throwUnpairedSurrogate(); + } + writeAscii(BYTE_AMP); + writeName(name); + writeAscii(BYTE_SEMICOLON); + } + + @Override + public void writeXmlDeclaration(String version, String encoding, String standalone) + throws IOException + { + final byte byQuote = (mUseDoubleQuotesInXmlDecl ? BYTE_QUOT : BYTE_APOS); + + writeAscii(" 0) { + writeAscii(" encoding="); + writeAscii(byQuote); + // Should be ascii, but let's play it safe: + writeRaw(encoding, 0, encoding.length()); + writeAscii(byQuote); + } + if (standalone != null) { + writeAscii(" standalone="); + writeAscii(byQuote); + writeAscii(standalone); + writeAscii(byQuote); + } + writeAscii(BYTE_QMARK, BYTE_GT); + } + + @Override + public int writePI(String target, String data) + throws IOException, XMLStreamException + { + writeAscii(BYTE_LT, BYTE_QMARK); + writeName(target); + if (data != null && data.length() > 0) { + writeAscii(BYTE_SPACE); + int ix = writePIData(data); + if (ix >= 0) { // embedded "?>"? + return ix; + } + } + writeAscii(BYTE_QMARK, BYTE_GT); + return -1; + } + + /* + //////////////////////////////////////////////////// + // Write methods, elements + //////////////////////////////////////////////////// + */ + + @Override + public void writeStartTagStart(String localName) + throws IOException, XMLStreamException + { + writeAscii(BYTE_LT); + writeName(localName); + } + + @Override + public void writeStartTagStart(String prefix, String localName) + throws IOException, XMLStreamException + { + if (prefix == null || prefix.length() == 0) { + writeStartTagStart(localName); + return; + } + writeAscii(BYTE_LT); + writeName(prefix); + writeAscii(BYTE_COLON); + writeName(localName); + } + + @Override + public void writeStartTagEnd() + throws IOException + { + writeAscii(BYTE_GT); + } + + @Override + public void writeStartTagEmptyEnd() + throws IOException + { + if (mAddSpaceAfterEmptyElem) { + writeAscii(" />"); + } else { + writeAscii(BYTE_SLASH, BYTE_GT); + } + } + + @Override + public void writeEndTag(String localName) + throws IOException + { + writeAscii(BYTE_LT, BYTE_SLASH); + /* At this point, it is assumed caller knows that end tag + * matches with start tag, and that it (by extension) has been + * validated if and as necessary + */ + writeNameUnchecked(localName); + writeAscii(BYTE_GT); + } + + @Override + public void writeEndTag(String prefix, String localName) + throws IOException + { + writeAscii(BYTE_LT, BYTE_SLASH); + /* At this point, it is assumed caller knows that end tag + * matches with start tag, and that it (by extension) has been + * validated if and as necessary + */ + if (prefix != null && prefix.length() > 0) { + writeNameUnchecked(prefix); + writeAscii(BYTE_COLON); + } + writeNameUnchecked(localName); + writeAscii(BYTE_GT); + } + + /* + //////////////////////////////////////////////////// + // Write methods, attributes/ns + //////////////////////////////////////////////////// + */ + + @Override + public void writeAttribute(String localName, String value) + throws IOException, XMLStreamException + { + writeAscii(BYTE_SPACE); + writeName(localName); + writeAscii(BYTE_EQ, BYTE_QUOT); + + int len = value.length(); + if (len > 0) { + if (mAttrValueWriter != null) { // custom escaping? + mAttrValueWriter.write(value, 0, len); + } else { // nope, default + writeAttrValue(value); + } + } + writeAscii(BYTE_QUOT); + } + + @Override + public void writeAttribute(String localName, char[] value, int offset, int len) + throws IOException, XMLStreamException + { + writeAscii(BYTE_SPACE); + writeName(localName); + writeAscii(BYTE_EQ, BYTE_QUOT); + + if (len > 0) { + if (mAttrValueWriter != null) { // custom escaping? + mAttrValueWriter.write(value, offset, len); + } else { // nope, default + writeAttrValue(value, offset, len); + } + } + writeAscii(BYTE_QUOT); + } + + @Override + public void writeAttribute(String prefix, String localName, String value) + throws IOException, XMLStreamException + { + writeAscii(BYTE_SPACE); + writeName(prefix); + writeAscii(BYTE_COLON); + writeName(localName); + writeAscii(BYTE_EQ, BYTE_QUOT); + + int len = value.length(); + if (len > 0) { + if (mAttrValueWriter != null) { // custom escaping? + mAttrValueWriter.write(value, 0, len); + } else { // nope, default + writeAttrValue(value); + } + } + writeAscii(BYTE_QUOT); + } + + @Override + public void writeAttribute(String prefix, String localName, char[] value, int offset, int len) + throws IOException, XMLStreamException + { + writeAscii(BYTE_SPACE); + writeName(prefix); + writeAscii(BYTE_COLON); + writeName(localName); + writeAscii(BYTE_EQ, BYTE_QUOT); + + if (len > 0) { + if (mAttrValueWriter != null) { // custom escaping? + mAttrValueWriter.write(value, offset, len); + } else { // nope, default + writeAttrValue(value, offset, len); + } + } + writeAscii(BYTE_QUOT); + } + + /* + //////////////////////////////////////////////// + // Methods used by Typed Access API + //////////////////////////////////////////////// + */ + + /** + * Non-validating version of typed write method + */ + @Override + public final void writeTypedElement(AsciiValueEncoder enc) + throws IOException + { + if (mSurrogate != 0) { + throwUnpairedSurrogate(); + } + if (enc.bufferNeedsFlush(mOutputBuffer.length - mOutputPtr)) { + flush(); + } + while (true) { + mOutputPtr = enc.encodeMore(mOutputBuffer, mOutputPtr, mOutputBuffer.length); + // If no flushing needed, indicates that all data was encoded + if (enc.isCompleted()) { + break; + } + flush(); + } + } + + /** + * Validating version of typed write method + */ + @Override + public final void writeTypedElement(AsciiValueEncoder enc, + XMLValidator validator, char[] copyBuffer) + throws IOException, XMLStreamException + { + if (mSurrogate != 0) { + throwUnpairedSurrogate(); + } + + /* Ok, this gets trickier: can't use efficient direct-to-bytes + * encoding since validator won't be able to use it. Instead + * have to use temporary copy buffer. + */ + final int copyBufferLen = copyBuffer.length; + + // Copy buffer should never be too small, no need to check up front + do { + int ptr = enc.encodeMore(copyBuffer, 0, copyBufferLen); + + // False -> can't be sure it's the whole remaining text + validator.validateText(copyBuffer, 0, ptr, false); + writeRawAscii(copyBuffer, 0, ptr); + } while (!enc.isCompleted()); + } + + @Override + public void writeTypedAttribute(String localName, AsciiValueEncoder enc) + throws IOException, XMLStreamException + { + writeAscii(BYTE_SPACE); + writeName(localName); + writeAscii(BYTE_EQ, BYTE_QUOT); + + if (enc.bufferNeedsFlush(mOutputBuffer.length - mOutputPtr)) { + flush(); + } + while (true) { + mOutputPtr = enc.encodeMore(mOutputBuffer, mOutputPtr, mOutputBuffer.length); + if (enc.isCompleted()) { + break; + } + flush(); + } + writeAscii(BYTE_QUOT); + } + + @Override + public void writeTypedAttribute(String prefix, String localName, + AsciiValueEncoder enc) + throws IOException, XMLStreamException + { +System.err.println("DEBUG: write typed attr/0 '"+localName+"'"); + + writeAscii(BYTE_SPACE); + writeName(prefix); + writeAscii(BYTE_COLON); + writeName(localName); + writeAscii(BYTE_EQ, BYTE_QUOT); + + if (enc.bufferNeedsFlush(mOutputBuffer.length - mOutputPtr)) { + flush(); + } + while (true) { + mOutputPtr = enc.encodeMore(mOutputBuffer, mOutputPtr, mOutputBuffer.length); + if (enc.isCompleted()) { + break; + } + flush(); + } + writeAscii(BYTE_QUOT); + } + + @Override + public void writeTypedAttribute(String prefix, String localName, String nsURI, + AsciiValueEncoder enc, + XMLValidator validator, char[] copyBuffer) + throws IOException, XMLStreamException + { + boolean hasPrefix = (prefix != null && prefix.length() > 0); + if (nsURI == null) { + nsURI = ""; + } +System.err.println("DEBUG: write typed attr/1 '"+localName+"', vld == "+validator); + + //validator.validateAttribute(localName, nsURI, (hasPrefix ? prefix: ""), buf, offset, len); + + writeAscii(BYTE_SPACE); + if (hasPrefix) { + writeName(prefix); + writeAscii(BYTE_COLON); + } + writeName(localName); + writeAscii(BYTE_EQ, BYTE_QUOT); + + /* Ok, this gets trickier: can't use efficient direct-to-bytes + * encoding since validator won't be able to use it. Instead + * have to use temporary copy buffer. + * In addition, attributes to validate can not be + * split (validators expect complete values). So, if value + * won't fit as is, may need to aggregate using StringBuilder + */ + final int copyBufferLen = copyBuffer.length; + + // First, let's see if one call is enough + int last = enc.encodeMore(copyBuffer, 0, copyBufferLen); + writeRawAscii(copyBuffer, 0, last); + if (enc.isCompleted()) { + validator.validateAttribute(localName, nsURI, prefix, copyBuffer, 0, last); + return; + } + + // If not, must combine first + StringBuilder sb = new StringBuilder(copyBufferLen << 1); + sb.append(copyBuffer, 0, last); + do { + last = enc.encodeMore(copyBuffer, 0, copyBufferLen); + writeRawAscii(copyBuffer, 0, last); + sb.append(copyBuffer, 0, last); + } while (!enc.isCompleted()); + + writeAscii(BYTE_QUOT); + + // Then validate + String valueStr = sb.toString(); + validator.validateAttribute(localName, nsURI, prefix, valueStr); + + return; + } + + /* + //////////////////////////////////////////////// + // Methods for sub-classes to use + //////////////////////////////////////////////// + */ + + protected final void flushBuffer() + throws IOException + { + if (mOutputPtr > 0 && mOutputBuffer != null) { + int ptr = mOutputPtr; + mOutputPtr = 0; + mOut.write(mOutputBuffer, 0, ptr); + } + } + + protected final void writeAscii(byte b) + throws IOException + { + if (mSurrogate != 0) { + throwUnpairedSurrogate(); + } + if (mOutputPtr >= mOutputBuffer.length) { + flushBuffer(); + } + mOutputBuffer[mOutputPtr++] = b; + } + + protected final void writeAscii(byte b1, byte b2) + throws IOException + { + if (mSurrogate != 0) { + throwUnpairedSurrogate(); + } + if ((mOutputPtr + 1) >= mOutputBuffer.length) { + flushBuffer(); + } + mOutputBuffer[mOutputPtr++] = b1; + mOutputBuffer[mOutputPtr++] = b2; + } + + protected final void writeAscii(String str) + throws IOException + { + if (mSurrogate != 0) { + throwUnpairedSurrogate(); + } + + int len = str.length(); + int ptr = mOutputPtr; + byte[] buf = mOutputBuffer; + if ((ptr + len) >= buf.length) { + /* It's even possible that String is longer than the buffer (not + * likely, possible). If so, let's just call the full + * method: + */ + if (len > buf.length) { + writeRaw(str, 0, len); + return; + } + flushBuffer(); + ptr = mOutputPtr; + } + mOutputPtr += len; + for (int i = 0; i < len; ++i) { + buf[ptr++] = (byte)str.charAt(i); + } + } + + @Override + public final void writeRawAscii(char[] buf, int offset, int len) + throws IOException + { + if (mSurrogate != 0) { + throwUnpairedSurrogate(); + } + int ptr = mOutputPtr; + byte[] dst = mOutputBuffer; + if ((ptr + len) >= dst.length) { + if (len > dst.length) { + writeRaw(buf, offset, len); + return; + } + flushBuffer(); + ptr = mOutputPtr; + } + mOutputPtr += len; + for (int i = 0; i < len; ++i) { + dst[ptr+i] = (byte)buf[offset+i]; + } + } + + /** + * Entity writing can be optimized quite nicely, since it only + * needs to output ascii characters. + * + * @return New value of mOutputPtr + */ + protected final int writeAsEntity(int c) + throws IOException + { + byte[] buf = mOutputBuffer; + int ptr = mOutputPtr; + if ((ptr + 10) >= buf.length) { // &#x [up to 6 hex digits] ; + flushBuffer(); + ptr = mOutputPtr; + } + buf[ptr++] = BYTE_AMP; + + // Can use more optimal notation for 8-bit ascii stuff: + if (c < 256) { + /* Also; although not really mandatory, let's also + * use pre-defined entities where possible. + */ + if (c == '&') { + buf[ptr++] = BYTE_A; + buf[ptr++] = BYTE_M; + buf[ptr++] = BYTE_P; + } else if (c == '<') { + buf[ptr++] = BYTE_L; + buf[ptr++] = BYTE_T; + } else if (c == '>') { + buf[ptr++] = BYTE_G; + buf[ptr++] = BYTE_T; + } else if (c == '\'') { + buf[ptr++] = BYTE_A; + buf[ptr++] = BYTE_P; + buf[ptr++] = BYTE_O; + buf[ptr++] = BYTE_S; + } else if (c == '"') { + buf[ptr++] = BYTE_Q; + buf[ptr++] = BYTE_U; + buf[ptr++] = BYTE_O; + buf[ptr++] = BYTE_T; + } else { + buf[ptr++] = BYTE_HASH; + buf[ptr++] = BYTE_X; + // Can use shortest quoting for tab, cr, lf: + if (c >= 16) { + int digit = (c >> 4); + buf[ptr++] = (byte) ((digit < 10) ? ('0' + digit) : (('a' - 10) + digit)); + c &= 0xF; + } + buf[ptr++] = (byte) ((c < 10) ? ('0' + c) : (('a' - 10) + c)); + } + } else { + buf[ptr++] = BYTE_HASH; + buf[ptr++] = BYTE_X; + + // Ok, let's write the shortest possible sequence then: + int shift = 20; + int origPtr = ptr; + + do { + int digit = (c >> shift) & 0xF; + if (digit > 0 || (ptr != origPtr)) { + buf[ptr++] = (byte) ((digit < 10) ? ('0' + digit) : (('a' - 10) + digit)); + } + shift -= 4; + } while (shift > 0); + c &= 0xF; + buf[ptr++] = (byte) ((c < 10) ? ('0' + c) : (('a' - 10) + c)); + } + buf[ptr++] = BYTE_SEMICOLON; + mOutputPtr = ptr; + return ptr; + } + + protected final void writeName(String name) + throws IOException, XMLStreamException + { + if (mCheckNames) { + verifyNameValidity(name, mNsAware); + } + // TODO: maybe we could reuse some previously encoded names? + writeRaw(name, 0, name.length()); + } + + protected final void writeNameUnchecked(String name) + throws IOException + { + writeRaw(name, 0, name.length()); + } + + protected final int calcSurrogate(int secondSurr) + throws IOException + { + // First, let's verify first surrogate is valid: + int firstSurr = mSurrogate; + mSurrogate = 0; + if (firstSurr < SURR1_FIRST || firstSurr > SURR1_LAST) { + throwUnpairedSurrogate(firstSurr); + } + + // Then that the second one is: + if ((secondSurr < SURR2_FIRST) || (secondSurr > SURR2_LAST)) { + throwUnpairedSurrogate(secondSurr); + } + int ch = 0x10000 + ((firstSurr - SURR1_FIRST) << 10) + (secondSurr - SURR2_FIRST); + if (ch > XmlConsts.MAX_UNICODE_CHAR) { + throw new IOException("Illegal surrogate character pair, resulting code 0x"+Integer.toHexString(ch)+" above legal XML character range"); + } + return ch; + } + + protected final void throwUnpairedSurrogate() + throws IOException + { + int surr = mSurrogate; + mSurrogate = 0; + throwUnpairedSurrogate(surr); + } + + protected final void throwUnpairedSurrogate(int code) + throws IOException +{ + // Let's flush to make debugging easier + flush(); + throw new IOException("Unpaired surrogate character (0x"+Integer.toHexString(code)+")"); +} + + /* + //////////////////////////////////////////////// + // Abstract methods for sub-classes to define + //////////////////////////////////////////////// + */ + + protected abstract void writeAttrValue(String data) + throws IOException; + + protected abstract void writeAttrValue(char[] value, int offset, int len) + throws IOException; + + protected abstract int writeCDataContent(String data) + throws IOException; + + protected abstract int writeCDataContent(char[] cbuf, int start, int len) + throws IOException; + + protected abstract int writeCommentContent(String data) + throws IOException; + + protected abstract int writePIData(String data) + throws IOException, XMLStreamException; + + protected abstract void writeTextContent(String data) + throws IOException; + + protected abstract void writeTextContent(char[] cbuf, int start, int len) + throws IOException; +} diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/sw/ISOLatin1XmlWriter.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/sw/ISOLatin1XmlWriter.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/sw/ISOLatin1XmlWriter.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/sw/ISOLatin1XmlWriter.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,801 @@ +/* Woodstox XML processor + * + * Copyright (c) 2004- Tatu Saloranta, tatu.saloranta@iki.fi + * + * Licensed under the License specified in file LICENSE, included with + * the source code. + * You may not use this file except in compliance with the License. + * + * 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 com.ctc.wstx.sw; + +import java.io.*; + +import javax.xml.stream.XMLStreamException; + +import com.ctc.wstx.api.WriterConfig; +import com.ctc.wstx.io.CharsetNames; + +/** + * Concrete implementation of {@link EncodingXmlWriter} used when output + * is to be encoded using ISO-8859-1, aka ISO-Latin1 encoding. + *

+ * Regarding surrogate pair handling: most of the checks are in the base + * class, and here we only need to worry about writeRaw + * methods. + */ +public final class ISOLatin1XmlWriter + extends EncodingXmlWriter +{ + public ISOLatin1XmlWriter(OutputStream out, WriterConfig cfg, boolean autoclose) + throws IOException + { + super(out, cfg, CharsetNames.CS_ISO_LATIN1, autoclose); + } + + @Override + public void writeRaw(char[] cbuf, int offset, int len) + throws IOException + { + if (mSurrogate != 0) { + throwUnpairedSurrogate(); + } + + int ptr = mOutputPtr; + while (len > 0) { + int max = mOutputBuffer.length - ptr; + if (max < 1) { // output buffer full? + mOutputPtr = ptr; + flushBuffer(); + ptr = 0; + max = mOutputBuffer.length; + } + // How much can we output? + if (max > len) { + max = len; + } + if (mCheckContent) { + for (int inEnd = offset + max; offset < inEnd; ++offset) { + int c = cbuf[offset]; + if (c < 32) { + if (c == '\n') { + // !!! TBI: line nr + } else if (c == '\r') { + // !!! TBI: line nr (and skipping \n that may follow) + } else if (c != '\t') { + mOutputPtr = ptr; + c = handleInvalidChar(c); + } + } else if (c > 0x7E) { + if (c > 0xFF) { + mOutputPtr = ptr; + handleInvalidLatinChar(c); + } else if (mXml11) { + if (c < 0x9F && c != 0x85) { + mOutputPtr = ptr; + c = handleInvalidChar(c); + } + } + } + mOutputBuffer[ptr++] = (byte) c; + } + } else { + for (int inEnd = offset + max; offset < inEnd; ++offset) { + mOutputBuffer[ptr++] = (byte) cbuf[offset]; + } + } + len -= max; + } + mOutputPtr = ptr; + } + + @Override + public void writeRaw(String str, int offset, int len) + throws IOException + { + if (mSurrogate != 0) { + throwUnpairedSurrogate(); + } + int ptr = mOutputPtr; + while (len > 0) { + int max = mOutputBuffer.length - ptr; + if (max < 1) { // output buffer full? + mOutputPtr = ptr; + flushBuffer(); + ptr = 0; + max = mOutputBuffer.length; + } + // How much can we output? + if (max > len) { + max = len; + } + if (mCheckContent) { + for (int inEnd = offset + max; offset < inEnd; ++offset) { + int c = str.charAt(offset); + if (c < 32) { + if (c == '\n') { + // !!! TBI: line nr + } else if (c == '\r') { + // !!! TBI: line nr (and skipping \n that may follow) + } else if (c != '\t') { + mOutputPtr = ptr; + c = handleInvalidChar(c); + } + } else if (c > 0x7E) { + if (c > 0xFF) { + mOutputPtr = ptr; + handleInvalidLatinChar(c); + } else if (mXml11) { + if (c < 0x9F && c != 0x85) { + mOutputPtr = ptr; + c = handleInvalidChar(c); + } + } + } + mOutputBuffer[ptr++] = (byte) c; + } + } else { + for (int inEnd = offset + max; offset < inEnd; ++offset) { + mOutputBuffer[ptr++] = (byte) str.charAt(offset); + } + } + len -= max; + } + mOutputPtr = ptr; + } + + @Override + protected void writeAttrValue(String data) + throws IOException + { + int offset = 0; + int len = data.length(); + int ptr = mOutputPtr; + + main_loop: + while (len > 0) { + int max = mOutputBuffer.length - ptr; + if (max < 1) { // output buffer full? + mOutputPtr = ptr; + flushBuffer(); + ptr = 0; + max = mOutputBuffer.length; + } + // Do we start with a surrogate? + if (mSurrogate != 0) { + int sec = data.charAt(offset++); + sec = calcSurrogate(sec); + mOutputPtr = ptr; + ptr = writeAsEntity(sec); + --len; + continue main_loop; + } + // How much can we output? + if (max > len) { + max = len; + } + inner_loop: + for (int inEnd = offset + max; offset < inEnd; ) { + int c = data.charAt(offset++); + if (c < 32) { + /* Need to quote all white space except for regular + * space chars, to preserve them (round-tripping) + */ + if (c == '\r') { + if (!mEscapeCR) { + mOutputBuffer[ptr++] = (byte) c; + continue; + } + } else if (c != '\n' && c != '\t') { + if (mCheckContent) { + if (!mXml11 || c == 0) { + c = handleInvalidChar(c); + mOutputBuffer[ptr++] = (byte) c; + continue; + } + } + } + // fall-through to char entity output + } else if (c < 0x7F) { + if (c != '<' && c != '&' && c != '"') { + mOutputBuffer[ptr++] = (byte) c; + continue; + } + // otherwise fall back on quoting + } else if (c > 0x9F && c <= 0xFF) { + mOutputBuffer[ptr++] = (byte) c; + continue; // [WSTX-88] + } else { + // Surrogate? + if (c >= SURR1_FIRST && c <= SURR2_LAST) { + mSurrogate = c; + // Last char needs special handling: + if (offset == inEnd) { + break inner_loop; + } + c = calcSurrogate(data.charAt(offset++)); + // Let's fall down to entity output + } + } + /* Has to be escaped as char entity; as such, also need + * to re-calc max. continguous data we can output + */ + mOutputPtr = ptr; + ptr = writeAsEntity(c); + len = data.length() - offset; + continue main_loop; + } + len -= max; + } + mOutputPtr = ptr; + } + + @Override + protected void writeAttrValue(char[] data, int offset, int len) + throws IOException + { + int ptr = mOutputPtr; + + main_loop: + while (len > 0) { + int max = mOutputBuffer.length - ptr; + if (max < 1) { // output buffer full? + mOutputPtr = ptr; + flushBuffer(); + ptr = 0; + max = mOutputBuffer.length; + } + // Do we start with a surrogate? + if (mSurrogate != 0) { + int sec = data[offset++]; + sec = calcSurrogate(sec); + mOutputPtr = ptr; + ptr = writeAsEntity(sec); + --len; + continue main_loop; + } + // How much can we output? + if (max > len) { + max = len; + } + inner_loop: + for (int inEnd = offset + max; offset < inEnd; ) { + int c = data[offset++]; + if (c < 32) { + /* Need to quote all white space except for regular + * space chars, to preserve them (round-tripping) + */ + if (c == '\r') { + if (!mEscapeCR) { + mOutputBuffer[ptr++] = (byte) c; + continue; + } + } else if (c != '\n' && c != '\t') { + if (mCheckContent) { + if (!mXml11 || c == 0) { + c = handleInvalidChar(c); + mOutputBuffer[ptr++] = (byte) c; + continue; + } + } + } + // fall-through to char entity output + } else if (c < 0x7F) { + if (c != '<' && c != '&' && c != '"') { + mOutputBuffer[ptr++] = (byte) c; + continue; + } + // otherwise fall back on quoting + } else if (c > 0x9F && c <= 0xFF) { + mOutputBuffer[ptr++] = (byte) c; + continue; // [WSTX-88] + } else { + // Surrogate? + if (c >= SURR1_FIRST && c <= SURR2_LAST) { + mSurrogate = c; + // Last char needs special handling: + if (offset == inEnd) { + break inner_loop; + } + c = calcSurrogate(data[offset++]); + // Let's fall down to entity output + } + } + /* Has to be escaped as char entity; as such, also need + * to re-calc max. contiguous data we can output + */ + mOutputPtr = ptr; + ptr = writeAsEntity(c); + max -= (inEnd - offset); // since we didn't loop completely + break inner_loop; + } + len -= max; + } + mOutputPtr = ptr; + } + + @Override + protected int writeCDataContent(String data) + throws IOException + { + // Note: mSurrogate can not be non-zero at this point, no need to check + + int offset = 0; + int len = data.length(); + if (!mCheckContent) { + writeRaw(data, offset, len); + return -1; + } + int ptr = mOutputPtr; + + main_loop: + while (len > 0) { + int max = mOutputBuffer.length - ptr; + if (max < 1) { // output buffer full? + mOutputPtr = ptr; + flushBuffer(); + ptr = 0; + max = mOutputBuffer.length; + } + // How much can we output? + if (max > len) { + max = len; + } + for (int inEnd = offset + max; offset < inEnd; ) { + int c = data.charAt(offset++); + if (c < 32) { + if (c == '\n') { + // !!! TBI: line nr + } else if (c == '\r') { + // !!! TBI: line nr (and skipping \n that may follow) + } else if (c != '\t') { + mOutputPtr = ptr; + c = handleInvalidChar(c); + } + } else if (c > 0x7E) { + if (c > 0xFF) { + mOutputPtr = ptr; + handleInvalidLatinChar(c); + } else if (mXml11) { + if (c < 0x9F && c != 0x85) { + mOutputPtr = ptr; + c = handleInvalidChar(c); + } + } + } else if (c == '>') { // embedded "]]>"? + if (offset > 2 && data.charAt(offset-2) == ']' + && data.charAt(offset-3) == ']') { + if (!mFixContent) { + return offset-3; + } + /* Relatively easy fix; just need to close this + * section, and open a new one... + */ + mOutputPtr = ptr; + writeCDataEnd(); + writeCDataStart(); + writeAscii(BYTE_GT); + ptr = mOutputPtr; + /* No guarantees there's as much free room in the + * output buffer, thus, need to restart loop: + */ + len = data.length() - offset; + continue main_loop; + } + } + mOutputBuffer[ptr++] = (byte) c; + } + len -= max; + } + mOutputPtr = ptr; + return -1; + } + + @Override + protected int writeCDataContent(char[] cbuf, int start, int len) + throws IOException + { + // Note: mSurrogate can not be non-zero at this point, no need to check + + if (!mCheckContent) { + writeRaw(cbuf, start, len); + return -1; + } + + int ptr = mOutputPtr; + int offset = start; + + while (len > 0) { + int max = mOutputBuffer.length - ptr; + if (max < 1) { // output buffer full? + mOutputPtr = ptr; + flushBuffer(); + ptr = 0; + max = mOutputBuffer.length; + } + // How much can we output? + if (max > len) { + max = len; + } + inner_loop: + for (int inEnd = offset + max; offset < inEnd; ) { + int c = cbuf[offset++]; + if (c < 32) { + if (c == '\n') { + // !!! TBI: line nr + } else if (c == '\r') { + // !!! TBI: line nr (and skipping \n that may follow) + } else if (c != '\t') { + mOutputPtr = ptr; + c = handleInvalidChar(c); + } + } else if (c > 0x7E) { + if (c > 0xFF) { + mOutputPtr = ptr; + handleInvalidLatinChar(c); + } else if (mXml11) { + if (c < 0x9F && c != 0x85) { + mOutputPtr = ptr; + c = handleInvalidChar(c); + } + } + } else if (c == '>') { // embedded "]]>"? + if (offset >= (start+3) && cbuf[offset-2] == ']' + && cbuf[offset-3] == ']') { + if (!mFixContent) { + return offset-3; + } + /* Relatively easy fix; just need to close this + * section, and open a new one... + */ + mOutputPtr = ptr; + writeCDataEnd(); + writeCDataStart(); + writeAscii(BYTE_GT); + ptr = mOutputPtr; + /* No guarantees there's as much free room in the + * output buffer, thus, need to restart loop: + */ + max -= (inEnd - offset); + break inner_loop; + } + } + mOutputBuffer[ptr++] = (byte) c; + } + len -= max; + } + mOutputPtr = ptr; + return -1; + } + + @Override + protected int writeCommentContent(String data) + throws IOException + { + // Note: mSurrogate can not be non-zero at this point, no need to check + + int offset = 0; + int len = data.length(); + if (!mCheckContent) { + writeRaw(data, offset, len); + return -1; + } + + int ptr = mOutputPtr; + + while (len > 0) { + int max = mOutputBuffer.length - ptr; + if (max < 1) { // output buffer full? + mOutputPtr = ptr; + flushBuffer(); + ptr = 0; + max = mOutputBuffer.length; + } + // How much can we output? + if (max > len) { + max = len; + } + inner_loop: + for (int inEnd = offset + max; offset < inEnd; ) { + int c = data.charAt(offset++); + if (c < 32) { + if (c == '\n') { + // !!! TBI: line nr + } else if (c == '\r') { + // !!! TBI: line nr (and skipping \n that may follow) + } else if (c != '\t') { + mOutputPtr = ptr; + c = handleInvalidChar(c); + } + } else if (c > 0x7E) { + if (c > 0xFF) { + mOutputPtr = ptr; + handleInvalidLatinChar(c); + } else if (mXml11) { + if (c < 0x9F && c != 0x85) { + mOutputPtr = ptr; + c = handleInvalidChar(c); + } + } + } else if (c == '-') { // embedded "--"? + if (offset > 1 && data.charAt(offset-2) == '-') { + if (!mFixContent) { + return offset-2; + } + /* Quite easy to fix: just add an extra space + * in front. There will be room for that char; + * but may need to take that the following '-' + * also fits. + */ + mOutputBuffer[ptr++] = ' '; + if (ptr >= mOutputBuffer.length) { // whops. need to flush + mOutputPtr = ptr; + flushBuffer(); + ptr = 0; + } + mOutputBuffer[ptr++] = BYTE_HYPHEN; + /* Also, since we did output an extra char, better + * restart the loop (since max calculation is now + * off) + */ + max -= (inEnd - offset); + break inner_loop; + } + } + mOutputBuffer[ptr++] = (byte) c; + } + len -= max; + } + mOutputPtr = ptr; + return -1; + } + + @Override + protected int writePIData(String data) + throws IOException, XMLStreamException + { + // Note: mSurrogate can not be non-zero at this point, no need to check + + int offset = 0; + int len = data.length(); + if (!mCheckContent) { + writeRaw(data, offset, len); + return -1; + } + + int ptr = mOutputPtr; + while (len > 0) { + int max = mOutputBuffer.length - ptr; + if (max < 1) { // output buffer full? + mOutputPtr = ptr; + flushBuffer(); + ptr = 0; + max = mOutputBuffer.length; + } + // How much can we output? + if (max > len) { + max = len; + } + for (int inEnd = offset + max; offset < inEnd; ++offset) { + int c = data.charAt(offset); + if (c < 32) { + if (c == '\n') { + // !!! TBI: line nr + } else if (c == '\r') { + // !!! TBI: line nr (and skipping \n that may follow) + } else if (c != '\t') { + mOutputPtr = ptr; + c = handleInvalidChar(c); + } + } else if (c > 0x7E) { + if (c > 0xFF) { + mOutputPtr = ptr; + handleInvalidLatinChar(c); + } else if (mXml11) { + if (c < 0x9F && c != 0x85) { + mOutputPtr = ptr; + c = handleInvalidChar(c); + } + } + } else if (c == '>') { // enclosed end marker ("?>")? + if (offset > 0 && data.charAt(offset-1) == '?') { + return offset-2; + } + } + mOutputBuffer[ptr++] = (byte) c; + } + len -= max; + } + mOutputPtr = ptr; + return -1; + } + + @Override + protected void writeTextContent(String data) + throws IOException + { + int offset = 0; + int len = data.length(); + + main_loop: + while (len > 0) { + int max = mOutputBuffer.length - mOutputPtr; + if (max < 1) { // output buffer full? + flushBuffer(); + max = mOutputBuffer.length; + } + // Do we start with a surrogate? + if (mSurrogate != 0) { + int sec = data.charAt(offset++); + sec = calcSurrogate(sec); + writeAsEntity(sec); + --len; + continue main_loop; + } + // How much can we output? + if (max > len) { + max = len; + } + inner_loop: + for (int inEnd = offset + max; offset < inEnd; ) { + int c = data.charAt(offset++); + if (c < 32) { + if (c == '\n' || c == '\t') { // TODO: line count + mOutputBuffer[mOutputPtr++] = (byte) c; + continue; + } else if (c == '\r') { + if (!mEscapeCR) { + mOutputBuffer[mOutputPtr++] = (byte) c; + continue; + } + } else if (!mXml11 || c == 0) { // ok in xml1.1, as entity + if (mCheckContent) { + c = handleInvalidChar(c); + mOutputBuffer[mOutputPtr++] = (byte) c; + continue; + } + // otherwise... well, I guess we can just escape it + } + // \r, or xml1.1 + other whitespace, need to escape + } else if (c < 0x7F) { + if (c != '<' && c != '&') { + if (c != '>' || (offset > 1 && data.charAt(offset-2) != ']')) { + mOutputBuffer[mOutputPtr++] = (byte) c; + continue; + } + } + // otherwise fall back on quoting + } else if (c > 0x9F && c <= 0xFF) { + mOutputBuffer[mOutputPtr++] = (byte) c; + continue; // [WSTX-88] + } else { + // Surrogate? + if (c >= SURR1_FIRST && c <= SURR2_LAST) { + mSurrogate = c; + // Last char needs special handling: + if (offset == inEnd) { + break inner_loop; + } + c = calcSurrogate(data.charAt(offset++)); + // Let's fall down to entity output + } + } + /* Has to be escaped as char entity; as such, also need + * to re-calc max. continguous data we can output + */ + writeAsEntity(c); + len = data.length() - offset; + continue main_loop; + } + len -= max; + } + } + + @Override + protected void writeTextContent(char[] cbuf, int offset, int len) + throws IOException + { + main_loop: + while (len > 0) { + int max = mOutputBuffer.length - mOutputPtr; + if (max < 1) { // output buffer full? + flushBuffer(); + max = mOutputBuffer.length; + } + // Do we start with a surrogate? + if (mSurrogate != 0) { + int sec = cbuf[offset++]; + sec = calcSurrogate(sec); + writeAsEntity(sec); + --len; + continue main_loop; + } + // How much can we output? + if (max > len) { + max = len; + } + inner_loop: + for (int inEnd = offset + max; offset < inEnd; ) { + int c = cbuf[offset++]; + if (c < 32) { + if (c == '\n' || c == '\t') { // TODO: line count + mOutputBuffer[mOutputPtr++] = (byte) c; + continue; + } else if (c == '\r') { + if (!mEscapeCR) { + mOutputBuffer[mOutputPtr++] = (byte) c; + continue; + } + } else if (!mXml11 || c == 0) { // ok in xml1.1, as entity + if (mCheckContent) { + c = handleInvalidChar(c); + mOutputBuffer[mOutputPtr++] = (byte) c; + continue; + } + // otherwise... well, I guess we can just escape it + } + // \r, or xml1.1 + other whitespace, need to escape + } else if (c < 0x7F) { + if (c !='<' && c != '&') { + /* Since we can be conservative, it doesn't matter + * if second check is not exact + */ + if (c != '>' || (offset > 1 && cbuf[offset-2] != ']')) { + mOutputBuffer[mOutputPtr++] = (byte) c; + continue; + } + } + // otherwise fall back on quoting + } else if (c > 0x9F && c <= 0xFF) { + mOutputBuffer[mOutputPtr++] = (byte) c; + continue; // [WSTX-88] + } else { + // Surrogate? + if (c >= SURR1_FIRST && c <= SURR2_LAST) { + mSurrogate = c; + // Last char needs special handling: + if (offset == inEnd) { + break inner_loop; + } + c = calcSurrogate(cbuf[offset++]); + // Let's fall down to entity output + } + } + /* Has to be escaped as char entity; as such, also need + * to re-calc max. continguous data we can output + */ + writeAsEntity(c); + max -= (inEnd - offset); + break inner_loop; + } + len -= max; + } + } + + /* + //////////////////////////////////////////////////// + // Internal methods + //////////////////////////////////////////////////// + */ + + protected void handleInvalidLatinChar(int c) + throws IOException + { + // First, let's flush any output we may have, to make debugging easier + flush(); + + /* 17-May-2006, TSa: Would really be useful if we could throw + * XMLStreamExceptions; esp. to indicate actual output location. + * However, this causes problem with methods that call us and + * can only throw IOExceptions (when invoked via Writer proxy). + * Need to figure out how to resolve this. + */ + throw new IOException("Invalid XML character (0x"+Integer.toHexString(c)+"); can only be output using character entity when using ISO-8859-1 encoding"); + } +} diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/sw/NonNsStreamWriter.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/sw/NonNsStreamWriter.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/sw/NonNsStreamWriter.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/sw/NonNsStreamWriter.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,564 @@ +/* Woodstox XML processor + * + * Copyright (c) 2004- Tatu Saloranta, tatu.saloranta@iki.fi + * + * Licensed under the License specified in the file LICENSE which is + * included with the source code. + * You may not use this file except in compliance with the License. + * + * 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 com.ctc.wstx.sw; + +import java.io.IOException; +import java.util.*; + +import javax.xml.XMLConstants; +import javax.xml.namespace.NamespaceContext; +import javax.xml.namespace.QName; +import javax.xml.stream.XMLStreamWriter; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.events.Attribute; +import javax.xml.stream.events.StartElement; + +import org.codehaus.stax2.ri.typed.AsciiValueEncoder; + +import com.ctc.wstx.api.WriterConfig; +import com.ctc.wstx.cfg.ErrorConsts; +import com.ctc.wstx.cfg.XmlConsts; +import com.ctc.wstx.sr.AttributeCollector; +import com.ctc.wstx.sr.InputElementStack; +import com.ctc.wstx.util.EmptyNamespaceContext; +import com.ctc.wstx.util.StringVector; + +/** + * Implementation of {@link XMLStreamWriter} used when namespace support + * is not enabled. This means that only local names are used for elements + * and attributes; and if rudimentary namespace declarations need to be + * output, they are output using attribute writing methods. + */ +public class NonNsStreamWriter + extends TypedStreamWriter +{ + /* + //////////////////////////////////////////////////// + // State information + //////////////////////////////////////////////////// + */ + + /** + * Stack of currently open start elements; only local names + * are included. + */ + final StringVector mElements; + + /** + * Container for attribute names for current element; used only + * if uniqueness of attribute names is to be enforced. + *

+ * TreeSet is used mostly because clearing it up is faster than + * clearing up HashSet, and the only access is done by + * adding entries and see if an value was already set. + */ + TreeSet mAttrNames; + + /* + //////////////////////////////////////////////////// + // Life-cycle (ctors) + //////////////////////////////////////////////////// + */ + + public NonNsStreamWriter(XmlWriter xw, String enc, WriterConfig cfg) + { + super(xw, enc, cfg); + mElements = new StringVector(32); + } + + /* + //////////////////////////////////////////////////// + // XMLStreamWriter API + //////////////////////////////////////////////////// + */ + + @Override + public NamespaceContext getNamespaceContext() { + return EmptyNamespaceContext.getInstance(); + } + + @Override + public String getPrefix(String uri) { + return null; + } + + @Override + public void setDefaultNamespace(String uri) + throws XMLStreamException + { + reportIllegalArg("Can not set default namespace for non-namespace writer."); + } + + @Override + public void setNamespaceContext(NamespaceContext context) { + reportIllegalArg("Can not set NamespaceContext for non-namespace writer."); + } + + @Override + public void setPrefix(String prefix, String uri) throws XMLStreamException + { + reportIllegalArg("Can not set namespace prefix for non-namespace writer."); + } + + @Override + public void writeAttribute(String localName, String value) + throws XMLStreamException + { + // No need to set mAnyOutput, nor close the element + if (!mStartElementOpen && mCheckStructure) { + reportNwfStructure(ErrorConsts.WERR_ATTR_NO_ELEM); + } + if (mCheckAttrs) { + /* 11-Dec-2005, TSa: Should use a more efficient Set/Map value + * for this in future. + */ + if (mAttrNames == null) { + mAttrNames = new TreeSet(); + } + if (!mAttrNames.add(localName)) { + reportNwfAttr("Trying to write attribute '"+localName+"' twice"); + } + } + if (mValidator != null) { + /* No need to get it normalized... even if validator does normalize + * it, we don't use that for anything + */ + mValidator.validateAttribute(localName, XmlConsts.ATTR_NO_NS_URI, XmlConsts.ATTR_NO_PREFIX, value); + } + + try { + mWriter.writeAttribute(localName, value); + } catch (IOException ioe) { + throwFromIOE(ioe); + } + } + + @Override + public void writeAttribute(String nsURI, String localName, String value) + throws XMLStreamException + { + writeAttribute(localName, value); + } + + @Override + public void writeAttribute(String prefix, String nsURI, + String localName, String value) + throws XMLStreamException + { + writeAttribute(localName, value); + } + + @Override + public void writeDefaultNamespace(String nsURI) throws XMLStreamException + { + reportIllegalMethod("Can not call writeDefaultNamespace namespaces with non-namespace writer."); + } + + @Override + public void writeEmptyElement(String localName) throws XMLStreamException + { + doWriteStartElement(localName); + mEmptyElement = true; + } + + @Override + public void writeEmptyElement(String nsURI, String localName) throws XMLStreamException + { + writeEmptyElement(localName); + } + + @Override + public void writeEmptyElement(String prefix, String localName, String nsURI) throws XMLStreamException + { + writeEmptyElement(localName); + } + + @Override + public void writeEndElement() throws XMLStreamException { + doWriteEndTag(null, mCfgAutomaticEmptyElems); + } + + @Override + public void writeNamespace(String prefix, String nsURI) throws XMLStreamException + { + reportIllegalMethod("Can not set write namespaces with non-namespace writer."); + } + + @Override + public void writeStartElement(String localName) throws XMLStreamException + { + doWriteStartElement(localName); + mEmptyElement = false; + } + + @Override + public void writeStartElement(String nsURI, String localName) throws XMLStreamException { + writeStartElement(localName); + } + + @Override + public void writeStartElement(String prefix, String localName, String nsURI) + throws XMLStreamException + { + writeStartElement(localName); + } + + /* + //////////////////////////////////////////////////// + // Remaining XMLStreamWriter2 methods (StAX2) + //////////////////////////////////////////////////// + */ + + /** + * Similar to {@link #writeEndElement}, but never allows implicit + * creation of empty elements. + */ + @Override + public void writeFullEndElement() throws XMLStreamException { + doWriteEndTag(null, false); + } + + /* + //////////////////////////////////////////////////// + // Remaining ValidationContext methods (StAX2) + //////////////////////////////////////////////////// + */ + + @Override + public QName getCurrentElementName() { + if (mElements.isEmpty()) { + return null; + } + return new QName(mElements.getLastString()); + } + + @Override + public String getNamespaceURI(String prefix) { + return null; + } + + /* + //////////////////////////////////////////////////// + // Package methods: + //////////////////////////////////////////////////// + */ + + @Override + public void writeStartElement(StartElement elem) + throws XMLStreamException + { + QName name = elem.getName(); + writeStartElement(name.getLocalPart()); + @SuppressWarnings("unchecked") + Iterator it = elem.getAttributes(); + while (it.hasNext()) { + Attribute attr = it.next(); + name = attr.getName(); + writeAttribute(name.getLocalPart(), attr.getValue()); + } + } + + /** + * Method called by {@link javax.xml.stream.XMLEventWriter} implementation + * (instead of the version + * that takes no argument), so that we can verify it does match the + * start element, if necessary + */ + @Override + public void writeEndElement(QName name) throws XMLStreamException + { + doWriteEndTag(mCheckStructure ? name.getLocalPart() : null, + mCfgAutomaticEmptyElems); + } + + @Override + protected void writeTypedAttribute(String prefix, String nsURI, String localName, + AsciiValueEncoder enc) + throws XMLStreamException + { + // note: mostly copied from the other writeAttribute() method.. + if (!mStartElementOpen && mCheckStructure) { + reportNwfStructure(ErrorConsts.WERR_ATTR_NO_ELEM); + } + if (mCheckAttrs) { // doh. Not good, need to construct non-transient value... + if (mAttrNames == null) { + mAttrNames = new TreeSet(); + } + if (!mAttrNames.add(localName)) { + reportNwfAttr("Trying to write attribute '"+localName+"' twice"); + } + } + + try { + if (mValidator == null) { + mWriter.writeTypedAttribute(localName, enc); + } else { + mWriter.writeTypedAttribute(null, localName, null, enc, mValidator, getCopyBuffer()); + } + } catch (IOException ioe) { + throwFromIOE(ioe); + } + } + + /** + * Method called to close an open start element, when another + * main-level element (not namespace declaration or + * attribute) is being output; except for end element which is + * handled differently. + */ + @Override + protected void closeStartElement(boolean emptyElem) + throws XMLStreamException + { + mStartElementOpen = false; + if (mAttrNames != null) { + mAttrNames.clear(); + } + + try { + if (emptyElem) { + mWriter.writeStartTagEmptyEnd(); + } else { + mWriter.writeStartTagEnd(); + } + } catch (IOException ioe) { + throwFromIOE(ioe); + } + + if (mValidator != null) { + mVldContent = mValidator.validateElementAndAttributes(); + } + + // Need bit more special handling for empty elements... + if (emptyElem) { + String localName = mElements.removeLast(); + if (mElements.isEmpty()) { + mState = STATE_EPILOG; + } + if (mValidator != null) { + mVldContent = mValidator.validateElementEnd(localName, XmlConsts.ELEM_NO_NS_URI, XmlConsts.ELEM_NO_PREFIX); + } + } + } + + /** + * Element copier method implementation suitable to be used with + * non-namespace-aware writers. The only special thing here is that + * the copier can convert namespace declarations to equivalent + * attribute writes. + */ + @Override + public void copyStartElement(InputElementStack elemStack, + AttributeCollector attrCollector) + throws IOException, XMLStreamException + { + String ln = elemStack.getLocalName(); + boolean nsAware = elemStack.isNamespaceAware(); + + /* First, since we are not to output namespace stuff as is, + * we just need to copy the element: + */ + if (nsAware) { // but reader is ns-aware? Need to add prefix? + String prefix = elemStack.getPrefix(); + if (prefix != null && prefix.length() > 0) { // yup + ln = prefix + ":" + ln; + } + } + writeStartElement(ln); + + /* However, if there are any namespace declarations, we probably + * better output them just as 'normal' attributes: + */ + if (nsAware) { + int nsCount = elemStack.getCurrentNsCount(); + if (nsCount > 0) { + for (int i = 0; i < nsCount; ++i) { + String prefix = elemStack.getLocalNsPrefix(i); + if (prefix == null || prefix.length() == 0) { // default NS decl + prefix = XMLConstants.XML_NS_PREFIX; + } else { + prefix = "xmlns:"+prefix; + } + writeAttribute(prefix, elemStack.getLocalNsURI(i)); + } + } + } + + /* And then let's just output attributes, if any (whether to copy + * implicit, aka "default" attributes, is configurable) + */ + int attrCount = mCfgCopyDefaultAttrs ? + attrCollector.getCount() : + attrCollector.getSpecifiedCount(); + + if (attrCount > 0) { + for (int i = 0; i < attrCount; ++i) { + attrCollector.writeAttribute(i, mWriter, mValidator); + } + } + } + + @Override + protected String getTopElementDesc() { + return mElements.isEmpty() ? "#root" : mElements.getLastString(); + } + + @Override + public String validateQNamePrefix(QName name) { + // Can either strip prefix out, or return as is + return name.getPrefix(); + } + + /* + //////////////////////////////////////////////////// + // Internal methods + //////////////////////////////////////////////////// + */ + + private void doWriteStartElement(String localName) + throws XMLStreamException + { + mAnyOutput = true; + // Need to finish an open start element? + if (mStartElementOpen) { + closeStartElement(mEmptyElement); + } else if (mState == STATE_PROLOG) { + // 20-Dec-2005, TSa: Does this match DOCTYPE declaration? + verifyRootElement(localName, null); + } else if (mState == STATE_EPILOG) { + if (mCheckStructure) { + reportNwfStructure(ErrorConsts.WERR_PROLOG_SECOND_ROOT, localName); + } + // Outputting fragment? Better reset to tree, then... + mState = STATE_TREE; + } + + /* Note: need not check for CONTENT_ALLOW_NONE here, since the + * validator should handle this particular case... + */ + /*if (mVldContent == XMLValidator.CONTENT_ALLOW_NONE) { // EMPTY content + reportInvalidContent(START_ELEMENT); + }*/ + if (mValidator != null) { + mValidator.validateElementStart(localName, XmlConsts.ELEM_NO_NS_URI, XmlConsts.ELEM_NO_PREFIX); + } + + mStartElementOpen = true; + mElements.addString(localName); + try { + mWriter.writeStartTagStart(localName); + } catch (IOException ioe) { + throwFromIOE(ioe); + } + } + + /** + *

+ * Note: Caller has to do actual removal of the element from element + * stack, before calling this method. + * + * @param expName Name that the closing element should have; null + * if whatever is in stack should be used + * @param allowEmpty If true, is allowed to create the empty element + * if the closing element was truly empty; if false, has to write + * the full empty element no matter what + */ + private void doWriteEndTag(String expName, boolean allowEmpty) + throws XMLStreamException + { + /* First of all, do we need to close up an earlier empty element? + * (open start element that was not created via call to + * writeEmptyElement gets handled later on) + */ + if (mStartElementOpen && mEmptyElement) { + mEmptyElement = false; + // note: this method guarantees proper updates to validation + closeStartElement(true); + } + + // Better have something to close... (to figure out what to close) + if (mState != STATE_TREE) { + // Have to throw an exception always, don't know elem name + reportNwfStructure("No open start element, when trying to write end element"); + } + + /* Now, do we have an unfinished start element (created via + * writeStartElement() earlier)? + */ + String localName = mElements.removeLast(); + if (mCheckStructure) { + if (expName != null && !localName.equals(expName)) { + /* Only gets called when trying to output an XMLEvent... in + * which case names can actually be compared + */ + reportNwfStructure("Mismatching close element name, '"+localName+"'; expected '"+expName+"'."); + } + } + + /* Can't yet validate, since we have two paths; one for empty + * elements, another for non-empty... + */ + + // Got a half output start element to close? + if (mStartElementOpen) { + /* Can't/shouldn't call closeStartElement, but need to do same + * processing. Thus, this is almost identical to closeStartElement: + */ + if (mValidator != null) { + /* Note: return value is not of much use, since the + * element will be closed right away... + */ + mVldContent = mValidator.validateElementAndAttributes(); + } + mStartElementOpen = false; + if (mAttrNames != null) { + mAttrNames.clear(); + } + try { + // We could write an empty element, implicitly? + if (allowEmpty) { + mWriter.writeStartTagEmptyEnd(); + if (mElements.isEmpty()) { + mState = STATE_EPILOG; + } + if (mValidator != null) { + mVldContent = mValidator.validateElementEnd(localName, XmlConsts.ELEM_NO_NS_URI, XmlConsts.ELEM_NO_PREFIX); + } + return; + } + // Nah, need to close open elem, and then output close elem + mWriter.writeStartTagEnd(); + } catch (IOException ioe) { + throwFromIOE(ioe); + } + } + + try { + mWriter.writeEndTag(localName); + } catch (IOException ioe) { + throwFromIOE(ioe); + } + + if (mElements.isEmpty()) { + mState = STATE_EPILOG; + } + + // Ok, time to validate... + if (mValidator != null) { + mVldContent = mValidator.validateElementEnd(localName, XmlConsts.ELEM_NO_NS_URI, XmlConsts.ELEM_NO_PREFIX); + } + } +} diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/sw/OutputElementBase.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/sw/OutputElementBase.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/sw/OutputElementBase.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/sw/OutputElementBase.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,377 @@ +/* Woodstox XML processor + * + * Copyright (c) 2005 Tatu Saloranta, tatu.saloranta@iki.fi + * + * Licensed under the License specified in file LICENSE, included with + * the source code. + * You may not use this file except in compliance with the License. + * + * 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 com.ctc.wstx.sw; + +import java.util.*; + +import javax.xml.XMLConstants; +import javax.xml.namespace.NamespaceContext; +import javax.xml.stream.XMLStreamException; + +import com.ctc.wstx.util.BijectiveNsMap; +import com.ctc.wstx.util.DataUtil; + +/** + * Class that encapsulates information about a specific element in virtual + * output stack for namespace-aware writers. + * It provides support for URI-to-prefix mappings as well as namespace + * mapping generation. + *

+ * One noteworthy feature of the class is that it is designed to allow + * "short-term recycling", ie. instances can be reused within context + * of a simple document output. While reuse/recycling of such lightweight + * object is often useless or even counter productive, here it may + * be worth using, due to simplicity of the scheme (basically using + * a very simple free-elements linked list). + */ +public abstract class OutputElementBase + implements NamespaceContext +{ + public final static int PREFIX_UNBOUND = 0; + public final static int PREFIX_OK = 1; + public final static int PREFIX_MISBOUND = 2; + + final static String sXmlNsPrefix = XMLConstants.XML_NS_PREFIX; + final static String sXmlNsURI = XMLConstants.XML_NS_URI; + + /* + //////////////////////////////////////////// + // Namespace binding/mapping information + //////////////////////////////////////////// + */ + + /** + * Namespace context end application may have supplied, and that + * (if given) should be used to augment explicitly defined bindings. + */ + protected NamespaceContext mRootNsContext; + + protected String mDefaultNsURI; + + /** + * Mapping of namespace prefixes to URIs and back. + */ + protected BijectiveNsMap mNsMapping; + + /** + * True, if {@link #mNsMapping} is a shared copy from the parent; + * false if a local copy was created (which happens when namespaces + * get bound etc). + */ + protected boolean mNsMapShared; + + /* + //////////////////////////////////////////// + // Life-cycle + //////////////////////////////////////////// + */ + + /** + * Constructor for the virtual root element + */ + protected OutputElementBase() + { + mNsMapping = null; + mNsMapShared = false; + mDefaultNsURI = ""; + mRootNsContext = null; + } + + protected OutputElementBase(OutputElementBase parent, BijectiveNsMap ns) + { + mNsMapping = ns; + mNsMapShared = (ns != null); + mDefaultNsURI = parent.mDefaultNsURI; + mRootNsContext = parent.mRootNsContext; + } + + /** + * Method called to reuse a pooled instance. + */ + protected void relink(OutputElementBase parent) + { + mNsMapping = parent.mNsMapping; + mNsMapShared = (mNsMapping != null); + mDefaultNsURI = parent.mDefaultNsURI; + mRootNsContext = parent.mRootNsContext; + } + + protected abstract void setRootNsContext(NamespaceContext ctxt); + + /* + //////////////////////////////////////////// + // Public API, accessors + //////////////////////////////////////////// + */ + + public abstract boolean isRoot(); + + /** + * @return String presentation of the fully-qualified name, in + * "prefix:localName" format (no URI). Useful for error and + * debugging messages. + */ + public abstract String getNameDesc(); + + public final String getDefaultNsUri() { + return mDefaultNsURI; + } + + /* + //////////////////////////////////////////// + // Public API, ns binding, checking + //////////////////////////////////////////// + */ + + /** + * Method similar to {@link #getPrefix}, but one that will not accept + * the default namespace, only an explicit one. Usually used when + * trying to find a prefix for attributes. + */ + public final String getExplicitPrefix(String uri) + { + if (mNsMapping != null) { + String prefix = mNsMapping.findPrefixByUri(uri); + if (prefix != null) { + return prefix; + } + } + if (mRootNsContext != null) { + String prefix = mRootNsContext.getPrefix(uri); + if (prefix != null) { + // Hmmh... still can't use the default NS: + if (prefix.length() > 0) { + return prefix; + } + // ... should we try to find an explicit one? + } + } + return null; + } + + /** + * Method that verifies that passed-in prefix indeed maps to the specified + * namespace URI; and depending on how it goes returns a status for + * caller. + * + * @param isElement If true, rules for the default NS are those of elements + * (ie. empty prefix can map to non-default namespace); if false, + * rules are those of attributes (only non-default prefix can map to + * a non-default namespace). + * + * @return PREFIX_OK, if passed-in prefix matches matched-in namespace URI + * in current scope; PREFIX_UNBOUND if it's not bound to anything, + * and PREFIX_MISBOUND if it's bound to another URI. + * + * @throws XMLStreamException True if default (no) prefix is allowed to + * match a non-default URI (elements); false if not (attributes) + */ + public final int isPrefixValid(String prefix, String nsURI, + boolean isElement) + throws XMLStreamException + { + // Hmmm.... caller shouldn't really pass null. + if (nsURI == null) { + nsURI = ""; + } + + /* First thing is to see if specified prefix is bound to a namespace; + * and if so, verify it matches with data passed in: + */ + + // Checking default namespace? + if (prefix == null || prefix.length() == 0) { + if (isElement) { + // It's fine for elements only if the URI actually matches: + if (nsURI == mDefaultNsURI || nsURI.equals(mDefaultNsURI)) { + return PREFIX_OK; + } + } else { + /* Attributes never use the default namespace: "no prefix" + * can only mean "no namespace" + */ + if (nsURI.length() == 0) { + return PREFIX_OK; + } + } + return PREFIX_MISBOUND; + } + + /* Need to handle 'xml' prefix and its associated + * URI; they are always declared by default + */ + if (prefix.equals(sXmlNsPrefix)) { + // Should we thoroughly verify its namespace matches...? + // 01-Apr-2005, TSa: Yes, let's always check this + if (!nsURI.equals(sXmlNsURI)) { + throwOutputError("Namespace prefix '"+sXmlNsPrefix + +"' can not be bound to non-default namespace ('"+nsURI+"'); has to be the default '" + +sXmlNsURI+"'"); + } + return PREFIX_OK; + } + + // Nope checking some other namespace + String act; + + if (mNsMapping != null) { + act = mNsMapping.findUriByPrefix(prefix); + } else { + act = null; + } + + if (act == null && mRootNsContext != null) { + act = mRootNsContext.getNamespaceURI(prefix); + } + + // Not (yet) bound... + if (act == null) { + return PREFIX_UNBOUND; + } + + return (act == nsURI || act.equals(nsURI)) ? + PREFIX_OK : PREFIX_MISBOUND; + } + + /* + //////////////////////////////////////////// + // Public API, mutators + //////////////////////////////////////////// + */ + + public abstract void setDefaultNsUri(String uri); + + public final String generateMapping(String prefixBase, String uri, int[] seqArr) + { + // This is mostly cut'n pasted from addPrefix()... + if (mNsMapping == null) { + // Didn't have a mapping yet? Need to create one... + mNsMapping = BijectiveNsMap.createEmpty(); + } else if (mNsMapShared) { + /* Was shared with parent(s)? Need to create a derivative, to + * allow for nesting/scoping of new prefix + */ + mNsMapping = mNsMapping.createChild(); + mNsMapShared = false; + } + return mNsMapping.addGeneratedMapping(prefixBase, mRootNsContext, + uri, seqArr); + } + + public final void addPrefix(String prefix, String uri) + { + if (mNsMapping == null) { + // Didn't have a mapping yet? Need to create one... + mNsMapping = BijectiveNsMap.createEmpty(); + } else if (mNsMapShared) { + /* Was shared with parent(s)? Need to create a derivative, to + * allow for nesting/scoping of new prefix + */ + mNsMapping = mNsMapping.createChild(); + mNsMapShared = false; + } + mNsMapping.addMapping(prefix, uri); + } + + /* + ////////////////////////////////////////////////// + // NamespaceContext implementation + ////////////////////////////////////////////////// + */ + + @Override + public final String getNamespaceURI(String prefix) + { + if (prefix.length() == 0) { //default NS + return mDefaultNsURI; + } + if (mNsMapping != null) { + String uri = mNsMapping.findUriByPrefix(prefix); + if (uri != null) { + return uri; + } + } + return (mRootNsContext != null) ? + mRootNsContext.getNamespaceURI(prefix) : null; + } + + @Override + public final String getPrefix(String uri) + { + if (mDefaultNsURI.equals(uri)) { + return ""; + } + if (mNsMapping != null) { + String prefix = mNsMapping.findPrefixByUri(uri); + if (prefix != null) { + return prefix; + } + } + return (mRootNsContext != null) ? + mRootNsContext.getPrefix(uri) : null; + } + + @Override + public final Iterator getPrefixes(String uri) + { + List l = null; + + if (mDefaultNsURI.equals(uri)) { + l = new ArrayList(); + l.add(""); + } + if (mNsMapping != null) { + l = mNsMapping.getPrefixesBoundToUri(uri, l); + } + // How about the root namespace context? (if any) + /* Note: it's quite difficult to properly resolve masking, when + * combining these things (not impossible, just tricky); for now + * let's do best effort without worrying about masking: + */ + if (mRootNsContext != null) { + Iterator it = mRootNsContext.getPrefixes(uri); + while (it.hasNext()) { + String prefix = (String) it.next(); + if (prefix.length() == 0) { // default NS already checked + continue; + } + // slow check... but what the heck + if (l == null) { + l = new ArrayList(); + } else if (l.contains(prefix)) { // double-defined... + continue; + } + l.add(prefix); + } + } + if (l == null) { + return DataUtil.emptyIterator(); + } + return l.iterator(); + } + + /* + //////////////////////////////////////////// + // Internal methods + //////////////////////////////////////////// + */ + + protected final void throwOutputError(String msg) + throws XMLStreamException + { + throw new XMLStreamException(msg); + } +} diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/sw/RepairingNsStreamWriter.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/sw/RepairingNsStreamWriter.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/sw/RepairingNsStreamWriter.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/sw/RepairingNsStreamWriter.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,659 @@ +/* Woodstox XML processor + * + * Copyright (c) 2004- Tatu Saloranta, tatu.saloranta@iki.fi + * + * Licensed under the License specified in the file LICENSE, + * included with the source code. + * You may not use this file except in compliance with the License. + * + * Unless required by applicable law or agreed to in writing, softwar + * 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 com.ctc.wstx.sw; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + +import javax.xml.namespace.QName; +import javax.xml.stream.XMLStreamWriter; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.events.Attribute; +import javax.xml.stream.events.StartElement; + +import org.codehaus.stax2.ri.typed.AsciiValueEncoder; + +import com.ctc.wstx.api.WriterConfig; +import com.ctc.wstx.cfg.ErrorConsts; +import com.ctc.wstx.sr.AttributeCollector; +import com.ctc.wstx.sr.InputElementStack; + +/** + * Namespace-aware implementation of {@link XMLStreamWriter}, that does + * namespace repairing, ie resolves possible conflicts between prefixes + * (add new bindings as necessary), as well as automatically creates + * namespace declarations as necessary. + */ +public final class RepairingNsStreamWriter + extends BaseNsStreamWriter +{ + /* + /////////////////////////////////////////////////////////// + // Configuration (options, features) + /////////////////////////////////////////////////////////// + */ + + // // // Additional specific config flags base class doesn't have + + protected final String mAutomaticNsPrefix; + + /* + /////////////////////////////////////////////////////////// + // Additional state + /////////////////////////////////////////////////////////// + */ + + /** + * Sequence number used for generating dynamic namespace prefixes. + * Array used as a wrapper to allow for easy sharing of the sequence + * number. + */ + protected int[] mAutoNsSeq = null; + + protected String mSuggestedDefNs = null; + + /** + * Map that contains URI-to-prefix entries that point out suggested + * prefixes for URIs. These are populated by calls to + * {@link #setPrefix}, and they are only used as hints for binding; + * if there are conflicts, repairing writer can just use some other + * prefix. + */ + protected HashMap mSuggestedPrefixes = null; + + /* + /////////////////////////////////////////////////////////// + // Life-cycle (ctors) + /////////////////////////////////////////////////////////// + */ + + public RepairingNsStreamWriter(XmlWriter xw, String enc, WriterConfig cfg) + { + super(xw, enc, cfg, true); + mAutomaticNsPrefix = cfg.getAutomaticNsPrefix(); + } + + /* + /////////////////////////////////////////////////////////// + // XMLStreamWriter API + /////////////////////////////////////////////////////////// + */ + + //public NamespaceContext getNamespaceContext() + //public void setNamespaceContext(NamespaceContext context) + //public String getPrefix(String uri) + //public void setPrefix(String prefix, String uri) + //public void setDefaultNamespace(String uri) + + //public void writeAttribute(String localName, String value) + + @Override + public void writeAttribute(String nsURI, String localName, String value) + throws XMLStreamException + { + // No need to set mAnyOutput, nor close the element + if (!mStartElementOpen) { + throwOutputError(ErrorConsts.WERR_ATTR_NO_ELEM); + } + doWriteAttr(localName, nsURI, + findOrCreateAttrPrefix(null, nsURI, mCurrElem), + value); + } + + @Override + public void writeAttribute(String prefix, String nsURI, + String localName, String value) + throws XMLStreamException + { + if (!mStartElementOpen) { + throwOutputError(ErrorConsts.WERR_ATTR_NO_ELEM); + } + + doWriteAttr(localName, nsURI, findOrCreateAttrPrefix(prefix, nsURI, mCurrElem), + value); + } + + @Override + public void writeDefaultNamespace(String nsURI) + throws XMLStreamException + { + /* 01-Sep-2006, TSa: The use case for calling this method is that + * of caller may wanting to 'suggest' that + * such a namespace should indeed be bound at this level. This + * may be necessary for canonicalization, or for minimizing number + * of binding declarations (all children need the ns, but root + * itself not). + */ + if (!mStartElementOpen) { + throwOutputError(ERR_NSDECL_WRONG_STATE); + } + /* ... We have one complication though: if the current element + * uses default namespace, can not change it (attributes don't + * matter -- they never use the default namespace, but either don't + * belong to a namespace, or belong to one using explicit prefix) + */ + String prefix = mCurrElem.getPrefix(); + if (prefix != null && prefix.length() > 0) { // ok, can change it + mCurrElem.setDefaultNsUri(nsURI); + doWriteDefaultNs(nsURI); + } + } + + //public void writeEmptyElement(String localName) throws XMLStreamException + + @Override + public void writeNamespace(String prefix, String nsURI) + throws XMLStreamException + { + /* (see discussion in 'writeDefaultNamespace()' for details on + * if and how this method may get called in repairing mode) + */ + if (prefix == null || prefix.length() == 0) { + writeDefaultNamespace(nsURI); + return; + } + if (!mStartElementOpen) { + throwOutputError(ERR_NSDECL_WRONG_STATE); + } + /* 01-Sep-2006, TSa: Let's only add the declaration if the prefix + * is as of yet unbound. If we have to re-bind things in future, + * so be it -- for now, this should suffice (and if we have to + * add re-binding, must verify that no attribute, nor element + * itself, is using overridden prefix) + */ + int value = mCurrElem.isPrefixValid(prefix, nsURI, true); + if (value == SimpleOutputElement.PREFIX_UNBOUND) { + mCurrElem.addPrefix(prefix, nsURI); + doWriteNamespace(prefix, nsURI); + } + } + + /* + /////////////////////////////////////////////////////////// + // Package methods: + /////////////////////////////////////////////////////////// + */ + + /** + * With repairing writer, this is only taken as a suggestion as to how + * the caller would prefer prefixes to be mapped. + */ + @Override + public void setDefaultNamespace(String uri) + throws XMLStreamException + { + mSuggestedDefNs = (uri == null || uri.length() == 0) ? null : uri; + } + + @Override + public void doSetPrefix(String prefix, String uri) + throws XMLStreamException + { + /* Ok; let's assume that passing in a null or empty String as + * the URI means that we don't want passed prefix to be preferred + * for any URI. + */ + if (uri == null || uri.length() == 0) { + if (mSuggestedPrefixes != null) { + for (Iterator> it = mSuggestedPrefixes.entrySet().iterator(); + it.hasNext(); ) { + Map.Entry en = it.next(); + String thisP = en.getValue(); + if (thisP.equals(prefix)) { + it.remove(); + } + } + } + } else { + if (mSuggestedPrefixes == null) { + mSuggestedPrefixes = new HashMap(16); + } + mSuggestedPrefixes.put(uri, prefix); + } + } + + @Override + public void writeStartElement(StartElement elem) + throws XMLStreamException + { + /* In repairing mode this is simple: let's just pass info + * we have, and things should work... a-may-zing! + */ + QName name = elem.getName(); + writeStartElement(name.getPrefix(), name.getLocalPart(), + name.getNamespaceURI()); + @SuppressWarnings("unchecked") + Iterator it = elem.getAttributes(); + while (it.hasNext()) { + Attribute attr = it.next(); + name = attr.getName(); + writeAttribute(name.getPrefix(), name.getNamespaceURI(), + name.getLocalPart(), attr.getValue()); + } + } + + //public void writeEndElement(QName name) throws XMLStreamException + + @Override + protected void writeTypedAttribute(String prefix, String nsURI, String localName, + AsciiValueEncoder enc) + throws XMLStreamException + { + super.writeTypedAttribute(findOrCreateAttrPrefix(prefix, nsURI, mCurrElem), + nsURI, localName, enc); + } + + @Override + protected void writeStartOrEmpty(String localName, String nsURI) + throws XMLStreamException + { + checkStartElement(localName, ""); + + // First, need to find prefix matching URI, if any: + String prefix = findElemPrefix(nsURI, mCurrElem); + /* Then need to create the element, since it'll have to + * contain the new namespace binding, if one needed + * (changed to resolve [WSTX-135] as reported by Y-J Choi, + * who also proposed the solution) + */ + if (mOutputElemPool != null) { + SimpleOutputElement newCurr = mOutputElemPool; + mOutputElemPool = newCurr.reuseAsChild(mCurrElem, prefix, localName, nsURI); + --mPoolSize; + mCurrElem = newCurr; + } else { + mCurrElem = mCurrElem.createChild(prefix, localName, nsURI); + } + + if (prefix != null) { // prefix ok, easy, no need to overwrite + if (mValidator != null) { + mValidator.validateElementStart(localName, nsURI, prefix); + } + doWriteStartTag(prefix, localName); + } else { // no prefix, more work + prefix = generateElemPrefix(null, nsURI, mCurrElem); + if (mValidator != null) { + mValidator.validateElementStart(localName, nsURI, prefix); + } + mCurrElem.setPrefix(prefix); + doWriteStartTag(prefix, localName); + if (prefix == null || prefix.length() == 0) { // def NS + mCurrElem.setDefaultNsUri(nsURI); + doWriteDefaultNs(nsURI); + } else { // explicit NS + mCurrElem.addPrefix(prefix, nsURI); + doWriteNamespace(prefix, nsURI); + } + } + } + + @Override + protected void writeStartOrEmpty(String suggPrefix, String localName, String nsURI) + throws XMLStreamException + { + checkStartElement(localName, suggPrefix); + + // In repairing mode, better ensure validity: + String actPrefix = validateElemPrefix(suggPrefix, nsURI, mCurrElem); + if (actPrefix != null) { // fine, an existing binding we can use: + if (mValidator != null) { + mValidator.validateElementStart(localName, nsURI, actPrefix); + } + if (mOutputElemPool != null) { + SimpleOutputElement newCurr = mOutputElemPool; + mOutputElemPool = newCurr.reuseAsChild(mCurrElem, actPrefix, localName, nsURI); + --mPoolSize; + mCurrElem = newCurr; + } else { + mCurrElem = mCurrElem.createChild(actPrefix, localName, nsURI); + } + doWriteStartTag(actPrefix, localName); + } else { // nah, need to create a new binding... + /* Need to ensure that we'll pass "" as prefix, not null, so + * that it is understood as "I want to use the default NS", not + * as "whatever prefix, I don't care" + */ + if (suggPrefix == null) { + suggPrefix = ""; + } + actPrefix = generateElemPrefix(suggPrefix, nsURI, mCurrElem); + if (mValidator != null) { + mValidator.validateElementStart(localName, nsURI, actPrefix); + } + if (mOutputElemPool != null) { + SimpleOutputElement newCurr = mOutputElemPool; + mOutputElemPool = newCurr.reuseAsChild(mCurrElem, actPrefix, localName, nsURI); + --mPoolSize; + mCurrElem = newCurr; + } else { + mCurrElem = mCurrElem.createChild(actPrefix, localName, nsURI); + } + mCurrElem.setPrefix(actPrefix); + doWriteStartTag(actPrefix, localName); + if (actPrefix == null || actPrefix.length() == 0) { // def NS + mCurrElem.setDefaultNsUri(nsURI); + doWriteDefaultNs(nsURI); + } else { // explicit NS + mCurrElem.addPrefix(actPrefix, nsURI); + doWriteNamespace(actPrefix, nsURI); + } + } + } + + /** + * Element copier method implementation suitable for use with + * namespace-aware writers in repairing mode. + * The trickiest thing is having to properly + * order calls to setPrefix, writeNamespace + * and writeStartElement; the order writers expect is + * bit different from the order in which element information is + * passed in. + */ + @Override + public final void copyStartElement(InputElementStack elemStack, AttributeCollector ac) + throws IOException, XMLStreamException + { + /* In case of repairing stream writer, we can actually just + * go ahead and first output the element: stream writer should + * be able to resolve namespace mapping for the element + * automatically, as necessary. + */ + String prefix = elemStack.getPrefix(); + String uri = elemStack.getNsURI(); + writeStartElement(prefix, elemStack.getLocalName(), uri); + + /* 04-Sep-2006, TSa: Although we could really just ignore all + * namespace declarations, some apps prefer (or even expect...) + * that ns bindings are preserved as much as possible. So, let's + * just try to output them as they are (could optimize and skip + * ones related to the start element [same prefix or URI], but + * for now let's not bother) + */ + int nsCount = elemStack.getCurrentNsCount(); + if (nsCount > 0) { // yup, got some... + for (int i = 0; i < nsCount; ++i) { + writeNamespace(elemStack.getLocalNsPrefix(i), elemStack.getLocalNsURI(i)); + } + } + + /* And then let's just output attributes, if any (whether to copy + * implicit, aka "default" attributes, is configurable) + */ + int attrCount = mCfgCopyDefaultAttrs ? ac.getCount() : ac.getSpecifiedCount(); + + /* Unlike in non-ns and simple-ns modes, we can not simply literally + * copy the attributes here. It is possible that some namespace + * prefixes have been remapped... so need to be bit more careful. + */ + if (attrCount > 0) { + for (int i = 0; i < attrCount; ++i) { + // First; need to make sure that the prefix-to-ns mapping + // attribute has is valid... and can not output anything + // before that's done (since remapping will output a namespace + // declaration!) + uri = ac.getURI(i); + prefix = ac.getPrefix(i); + + // With attributes, missing/empty prefix always means 'no + // namespace', can take a shortcut: + if (prefix == null || prefix.length() == 0) { + ; + } else { + // and otherwise we'll always have a prefix as attributes + // can not make use of the def. namespace... + prefix = findOrCreateAttrPrefix(prefix, uri, mCurrElem); + } + /* Hmmh. Since the prefix we use may be different from what + * collector has, we can not use pass-through method of + * the collector, but need to call XmlWriter directly: + */ + if (prefix == null || prefix.length() == 0) { + mWriter.writeAttribute(ac.getLocalName(i), ac.getValue(i)); + } else { + mWriter.writeAttribute(prefix, ac.getLocalName(i), ac.getValue(i)); + } + } + } + } + + @Override + public String validateQNamePrefix(QName name) + throws XMLStreamException + { + /* Gets bit more complicated: we need to ensure that given URI + * is properly bound... + */ + String uri = name.getNamespaceURI(); + String suggPrefix = name.getPrefix(); + String actPrefix = validateElemPrefix(suggPrefix, uri, mCurrElem); + if (actPrefix == null) { // no suitable prefix, must bind + /* Need to ensure that we'll pass "" as prefix, not null, so + * that it is understood as "I want to use the default NS", not + * as "whatever prefix, I don't care" + */ + if (suggPrefix == null) { + suggPrefix = ""; + } + actPrefix = generateElemPrefix(suggPrefix, uri, mCurrElem); + if (actPrefix == null || actPrefix.length() == 0) { // def NS + writeDefaultNamespace(uri); + } else { + writeNamespace(actPrefix, uri); + } + } + return actPrefix; + } + + /* + /////////////////////////////////////////////////////////// + // Internal methods + /////////////////////////////////////////////////////////// + */ + + /** + * Method called to find an existing prefix for the given namespace, + * if any exists in the scope. If one is found, it's returned (including + * "" for the current default namespace); if not, null is returned. + * + * @param nsURI URI of namespace for which we need a prefix + */ + protected final String findElemPrefix(String nsURI, SimpleOutputElement elem) + throws XMLStreamException + { + /* Special case: empty NS URI can only be bound to the empty + * prefix... + */ + if (nsURI == null || nsURI.length() == 0) { + String currDefNsURI = elem.getDefaultNsUri(); + if (currDefNsURI != null && currDefNsURI.length() > 0) { + // Nope; won't do... has to be re-bound, but not here: + return null; + } + return ""; + } + return mCurrElem.getPrefix(nsURI); + } + + /** + * Method called after {@link #findElemPrefix} has returned null, + * to create and bind a namespace mapping for specified namespace. + */ + protected final String generateElemPrefix(String suggPrefix, String nsURI, + SimpleOutputElement elem) + throws XMLStreamException + { + /* Ok... now, since we do not have an existing mapping, let's + * see if we have a preferred prefix to use. + */ + /* Except if we need the empty namespace... that can only be + * bound to the empty prefix: + */ + if (nsURI == null || nsURI.length() == 0) { + return ""; + } + + /* Ok; with elements this is easy: the preferred prefix can + * ALWAYS be used, since it can mask preceding bindings: + */ + if (suggPrefix == null) { + // caller wants this URI to map as the default namespace? + if (mSuggestedDefNs != null && mSuggestedDefNs.equals(nsURI)) { + suggPrefix = ""; + } else { + suggPrefix = (mSuggestedPrefixes == null) ? null: + mSuggestedPrefixes.get(nsURI); + if (suggPrefix == null) { + /* 16-Oct-2005, TSa: We have 2 choices here, essentially; + * could make elements always try to override the def + * ns... or can just generate new one. Let's do latter + * for now. + */ + if (mAutoNsSeq == null) { + mAutoNsSeq = new int[1]; + mAutoNsSeq[0] = 1; + } + suggPrefix = elem.generateMapping(mAutomaticNsPrefix, nsURI, + mAutoNsSeq); + } + } + } + + // Ok; let's let the caller deal with bindings + return suggPrefix; + } + + /** + * Method called to somehow find a prefix for given namespace, to be + * used for a new start element; either use an existing one, or + * generate a new one. If a new mapping needs to be generated, + * it will also be automatically bound, and necessary namespace + * declaration output. + * + * @param suggPrefix Suggested prefix to bind, if any; may be null + * to indicate "no preference" + * @param nsURI URI of namespace for which we need a prefix + * @param elem Currently open start element, on which the attribute + * will be added. + */ + protected final String findOrCreateAttrPrefix(String suggPrefix, String nsURI, + SimpleOutputElement elem) + throws XMLStreamException + { + if (nsURI == null || nsURI.length() == 0) { + /* Attributes never use the default namespace; missing + * prefix always leads to the empty ns... so nothing + * special is needed here. + */ + return null; + } + // Maybe the suggested prefix is properly bound? + if (suggPrefix != null) { + int status = elem.isPrefixValid(suggPrefix, nsURI, false); + if (status == SimpleOutputElement.PREFIX_OK) { + return suggPrefix; + } + /* Otherwise, if the prefix is unbound, let's just bind + * it -- if caller specified a prefix, it probably prefers + * binding that prefix even if another prefix already existed? + * The remaining case (already bound to another URI) we don't + * want to touch, at least not yet: it may or not be safe + * to change binding, so let's just not try it. + */ + if (status == SimpleOutputElement.PREFIX_UNBOUND) { + elem.addPrefix(suggPrefix, nsURI); + doWriteNamespace(suggPrefix, nsURI); + return suggPrefix; + } + } + + // If not, perhaps there's another existing binding available? + String prefix = elem.getExplicitPrefix(nsURI); + if (prefix != null) { // already had a mapping for the URI... cool. + return prefix; + } + + /* Nope, need to create one. First, let's see if there's a + * preference... + */ + if (suggPrefix != null) { + prefix = suggPrefix; + } else if (mSuggestedPrefixes != null) { + prefix = mSuggestedPrefixes.get(nsURI); + // note: def ns is never added to suggested prefix map + } + + if (prefix != null) { + /* Can not use default namespace for attributes. + * Also, re-binding is tricky for attributes; can't + * re-bind anything that's bound on this scope... or + * used in this scope. So, to simplify life, let's not + * re-bind anything for attributes. + */ + if (prefix.length() == 0 + || (elem.getNamespaceURI(prefix) != null)) { + prefix = null; + } + } + + if (prefix == null) { + if (mAutoNsSeq == null) { + mAutoNsSeq = new int[1]; + mAutoNsSeq[0] = 1; + } + prefix = mCurrElem.generateMapping(mAutomaticNsPrefix, nsURI, + mAutoNsSeq); + } + + // Ok; so far so good: let's now bind and output the namespace: + elem.addPrefix(prefix, nsURI); + doWriteNamespace(prefix, nsURI); + return prefix; + } + + private final String validateElemPrefix(String prefix, String nsURI, + SimpleOutputElement elem) + throws XMLStreamException + { + /* 06-Feb-2005, TSa: Special care needs to be taken for the + * "empty" (or missing) namespace: + * (see comments from findOrCreatePrefix()) + */ + if (nsURI == null || nsURI.length() == 0) { + String currURL = elem.getDefaultNsUri(); + if (currURL == null || currURL.length() == 0) { + // Ok, good: + return ""; + } + // Nope, needs to be re-bound: + return null; + } + + int status = elem.isPrefixValid(prefix, nsURI, true); + if (status == SimpleOutputElement.PREFIX_OK) { + return prefix; + } + + /* Hmmh... now here's bit of dilemma: that particular prefix is + * either not bound, or is masked... but it is possible some other + * prefix would be bound. Should we search for another one, or + * try to re-define suggested one? Let's do latter, for now; + * caller can then (try to) bind the preferred prefix: + */ + return null; + } +} diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/sw/SimpleNsStreamWriter.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/sw/SimpleNsStreamWriter.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/sw/SimpleNsStreamWriter.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/sw/SimpleNsStreamWriter.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,346 @@ +/* Woodstox XML processor + * + * Copyright (c) 2004- Tatu Saloranta, tatu.saloranta@iki.fi + * + * Licensed under the License specified in the file LICENSE, + * included with the source code. + * You may not use this file except in compliance with the License. + * + * 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 com.ctc.wstx.sw; + +import java.io.IOException; +import java.util.Iterator; + +import javax.xml.XMLConstants; +import javax.xml.namespace.QName; +import javax.xml.stream.XMLStreamWriter; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.events.Attribute; +import javax.xml.stream.events.Namespace; +import javax.xml.stream.events.StartElement; + +import com.ctc.wstx.api.WriterConfig; +import com.ctc.wstx.cfg.ErrorConsts; +import com.ctc.wstx.sr.AttributeCollector; +import com.ctc.wstx.sr.InputElementStack; + +/** + * Namespace-aware implementation of {@link XMLStreamWriter}, that does + * not do namespace repairing, ie doesn't try to resolve possible + * conflicts between prefixes and namespace URIs, or automatically + * create namespace bindings. + */ +public class SimpleNsStreamWriter + extends BaseNsStreamWriter +{ + /* + //////////////////////////////////////////////////// + // Life-cycle (ctors) + //////////////////////////////////////////////////// + */ + + public SimpleNsStreamWriter(XmlWriter xw, String enc, WriterConfig cfg) + { + super(xw, enc, cfg, false); + } + + /* + //////////////////////////////////////////////////// + // XMLStreamWriter API + //////////////////////////////////////////////////// + */ + + //public NamespaceContext getNamespaceContext() + //public void setNamespaceContext(NamespaceContext context) + //public String getPrefix(String uri) + //public void setPrefix(String prefix, String uri) + + //public void writeAttribute(String localName, String value) + + @Override + public void writeAttribute(String nsURI, String localName, String value) + throws XMLStreamException + { + // No need to set mAnyOutput, nor close the element + if (!mStartElementOpen) { + throwOutputError(ErrorConsts.WERR_ATTR_NO_ELEM); + } + String prefix = mCurrElem.getExplicitPrefix(nsURI); + if (!mReturnNullForDefaultNamespace && prefix == null) { + throwOutputError("Unbound namespace URI '" + nsURI + "'"); + } + doWriteAttr(localName, nsURI, prefix, value); + } + + @Override + public void writeAttribute(String prefix, String nsURI, + String localName, String value) + throws XMLStreamException + { + if (!mStartElementOpen) { + throwOutputError(ErrorConsts.WERR_ATTR_NO_ELEM); + } + doWriteAttr(localName, nsURI, prefix, value); + } + + //public void writeEmptyElement(String localName) throws XMLStreamException + //public void writeEmptyElement(String nsURI, String localName) throws XMLStreamException + //public void writeEmptyElement(String prefix, String localName, String nsURI) throws XMLStreamException + + //public void writeEndElement() throws XMLStreamException + + @Override + public void writeDefaultNamespace(String nsURI) + throws XMLStreamException + { + if (!mStartElementOpen) { + throwOutputError(ERR_NSDECL_WRONG_STATE); + } + // 27-Mar-2007, TSa: Apparently TCK expects a binding to be added + setDefaultNamespace(nsURI); + doWriteDefaultNs(nsURI); + } + + @Override + public void writeNamespace(String prefix, String nsURI) + throws XMLStreamException + { + if (prefix == null || prefix.length() == 0 + || prefix.equals(XMLConstants.XMLNS_ATTRIBUTE)) { + writeDefaultNamespace(nsURI); + return; + } + + // No need to set mAnyOutput, and shouldn't close the element. + // But element needs to be open, obviously. + if (!mStartElementOpen) { + throwOutputError(ERR_NSDECL_WRONG_STATE); + } + /* 05-Feb-2005, TSa: Also, as per namespace specs; the 'empty' + * namespace URI can not be bound as a non-default namespace + * (ie. for any actual prefix) + */ + /* 04-Feb-2005, TSa: Namespaces 1.1 does allow this, though, + * so for xml 1.1 documents we need to allow it + */ + if (!mXml11) { + if (nsURI.length() == 0) { + throwOutputError(ErrorConsts.ERR_NS_EMPTY); + } + // 01-Apr-2005, TSa: Can we (and do we want to) verify NS consistency? + } + // 27-Mar-2007, TSa: Apparently TCK expects a binding to be added + setPrefix(prefix, nsURI); + doWriteNamespace(prefix, nsURI); + } + + /* + //////////////////////////////////////////////////// + // Package methods: + //////////////////////////////////////////////////// + */ + + @Override + public void setDefaultNamespace(String uri) throws XMLStreamException + { + mCurrElem.setDefaultNsUri(uri); + } + + @Override + public void doSetPrefix(String prefix, String uri) throws XMLStreamException + { + mCurrElem.addPrefix(prefix, uri); + } + + @Override + public void writeStartElement(StartElement elem) throws XMLStreamException + { + QName name = elem.getName(); + @SuppressWarnings("unchecked") + Iterator it = elem.getNamespaces(); + + while (it.hasNext()) { + Namespace ns = it.next(); + // First need to 'declare' namespace: + String prefix = ns.getPrefix(); + if (prefix == null || prefix.length() == 0) { + setDefaultNamespace(ns.getNamespaceURI()); + } else { + setPrefix(prefix, ns.getNamespaceURI()); + } + } + + /* Outputting element itself is fairly easy. The main question + * is whether namespaces match. Let's use simple heuristics: + * if writer is to do automatic prefix matching, let's only + * pass explicit prefix (not default one); otherwise we'll + * pass all parameters as is. + */ + /* Quick check first though: if URI part of QName is null, it's + * assumed element will just use whatever is current default + * namespace.... + */ + String nsURI = name.getNamespaceURI(); + if (nsURI == null) { + writeStartElement(name.getLocalPart()); + } else { + String prefix = name.getPrefix(); + writeStartElement(prefix, name.getLocalPart(), nsURI); + } + + // And now we need to output namespaces (including default), if any: + @SuppressWarnings("unchecked") + Iterator it2 = elem.getNamespaces(); + while (it2.hasNext()) { + Namespace ns = it2.next(); + String prefix = ns.getPrefix(); + if (prefix == null || prefix.length() == 0) { + writeDefaultNamespace(ns.getNamespaceURI()); + } else { + writeNamespace(prefix, ns.getNamespaceURI()); + } + } + + + // And finally, need to output attributes as well: + @SuppressWarnings("unchecked") + Iterator ait = elem.getAttributes(); + while (ait.hasNext()) { + Attribute attr = ait.next(); + name = attr.getName(); + nsURI = name.getNamespaceURI(); + // In non-default/empty namespace? + if (nsURI != null && nsURI.length() > 0) { + writeAttribute(name.getPrefix(), nsURI, + name.getLocalPart(), attr.getValue()); + } else { + writeAttribute(name.getLocalPart(), attr.getValue()); + } + } + } + + //public void writeEndElement(QName name) throws XMLStreamException + + @Override + protected void writeStartOrEmpty(String localName, String nsURI) + throws XMLStreamException + { + // Need a prefix... + String prefix = mCurrElem.getPrefix(nsURI); + if (prefix == null) { + throw new XMLStreamException("Unbound namespace URI '"+nsURI+"'"); + } + checkStartElement(localName, prefix); + if (mValidator != null) { + mValidator.validateElementStart(localName, nsURI, prefix); + } + + if (mOutputElemPool != null) { + SimpleOutputElement newCurr = mOutputElemPool; + mOutputElemPool = newCurr.reuseAsChild(mCurrElem, prefix, localName, nsURI); + --mPoolSize; + mCurrElem = newCurr; + } else { + mCurrElem = mCurrElem.createChild(prefix, localName, nsURI); + } + doWriteStartTag(prefix, localName); + } + + @Override + protected void writeStartOrEmpty(String prefix, String localName, String nsURI) + throws XMLStreamException + { + checkStartElement(localName, prefix); + if (mValidator != null) { + mValidator.validateElementStart(localName, nsURI, prefix); + } + + if (mOutputElemPool != null) { + SimpleOutputElement newCurr = mOutputElemPool; + mOutputElemPool = newCurr.reuseAsChild(mCurrElem, prefix, localName, nsURI); + --mPoolSize; + mCurrElem = newCurr; + } else { + mCurrElem = mCurrElem.createChild(prefix, localName, nsURI); + } + doWriteStartTag(prefix, localName); + } + + /** + * Element copier method implementation suitable to be used with + * namespace-aware writers in non-repairing (explicit namespaces) mode. + * The trickiest thing is having to properly + * order calls to setPrefix, writeNamespace + * and writeStartElement; the order writers expect is + * bit different from the order in which element information is + * passed in. + */ + @Override + public final void copyStartElement(InputElementStack elemStack, + AttributeCollector attrCollector) + throws IOException, XMLStreamException + { + // Any namespace declarations/bindings? + int nsCount = elemStack.getCurrentNsCount(); + if (nsCount > 0) { // yup, got some... + /* First, need to (or at least, should?) add prefix bindings: + * (may not be 100% required, but probably a good thing to do, + * just so that app code has access to prefixes then) + */ + for (int i = 0; i < nsCount; ++i) { + String prefix = elemStack.getLocalNsPrefix(i); + String uri = elemStack.getLocalNsURI(i); + if (prefix == null || prefix.length() == 0) { // default NS + setDefaultNamespace(uri); + } else { + setPrefix(prefix, uri); + } + } + } + + writeStartElement(elemStack.getPrefix(), + elemStack.getLocalName(), + elemStack.getNsURI()); + + if (nsCount > 0) { + // And then output actual namespace declarations: + for (int i = 0; i < nsCount; ++i) { + String prefix = elemStack.getLocalNsPrefix(i); + String uri = elemStack.getLocalNsURI(i); + + if (prefix == null || prefix.length() == 0) { // default NS + writeDefaultNamespace(uri); + } else { + writeNamespace(prefix, uri); + } + } + } + + /* And then let's just output attributes, if any (whether to copy + * implicit, aka "default" attributes, is configurable) + */ + int attrCount = mCfgCopyDefaultAttrs ? + attrCollector.getCount() : + attrCollector.getSpecifiedCount(); + + if (attrCount > 0) { + for (int i = 0; i < attrCount; ++i) { + attrCollector.writeAttribute(i, mWriter, mValidator); + } + } + } + + @Override + public String validateQNamePrefix(QName name) + { + // Good as is, let's not complicate things + return name.getPrefix(); + } +} diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/sw/SimpleOutputElement.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/sw/SimpleOutputElement.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/sw/SimpleOutputElement.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/sw/SimpleOutputElement.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,374 @@ +/* Woodstox XML processor + * + * Copyright (c) 2005 Tatu Saloranta, tatu.saloranta@iki.fi + * + * Licensed under the License specified in file LICENSE, included with + * the source code. + * You may not use this file except in compliance with the License. + * + * 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 com.ctc.wstx.sw; + +import java.util.*; + +import javax.xml.namespace.NamespaceContext; +import javax.xml.namespace.QName; +import javax.xml.stream.XMLStreamException; + +import com.ctc.wstx.compat.QNameCreator; +import com.ctc.wstx.util.BijectiveNsMap; + +/** + * Class that encapsulates information about a specific element in virtual + * output stack for namespace-aware writers. + * It provides support for URI-to-prefix mappings as well as namespace + * mapping generation. + *

+ * One noteworthy feature of the class is that it is designed to allow + * "short-term recycling", ie. instances can be reused within context + * of a simple document output. While reuse/recycling of such lightweight + * object is often useless or even counter productive, here it may + * be worth using, due to simplicity of the scheme (basically using + * a very simple free-elements linked list). + */ +public final class SimpleOutputElement + extends OutputElementBase +{ + /* + /////////////////////////////////////////////////////////////////////// + // Information about element itself: + /////////////////////////////////////////////////////////////////////// + */ + + /** + * Reference to the parent element, element enclosing this element. + * Null for root element. + * Non-final only to allow temporary pooling + * (on per-writer basis, to keep these short-lived). + */ + protected SimpleOutputElement mParent; + + /** + * Prefix that is used for the element. Can not be final, since sometimes + * it needs to be dynamically generated and bound after creating the + * element instance. + */ + protected String mPrefix; + + /** + * Local name of the element. + * Non-final only to allow reuse. + */ + protected String mLocalName; + + /** + * Namespace of the element, whatever {@link #mPrefix} maps to. + * Non-final only to allow reuse. + */ + protected String mURI; + + /* + /////////////////////////////////////////////////////////////////////// + // Attribute information + /////////////////////////////////////////////////////////////////////// + */ + + /** + * Map used to check for duplicate attribute declarations, if + * feature is enabled. + */ + protected HashSet mAttrSet = null; + + /* + /////////////////////////////////////////////////////////////////////// + // Life-cycle + /////////////////////////////////////////////////////////////////////// + */ + + /** + * Constructor for the virtual root element + */ + private SimpleOutputElement() + { + super(); + mParent = null; + mPrefix = null; + mLocalName = ""; + mURI = null; + } + + private SimpleOutputElement(SimpleOutputElement parent, + String prefix, String localName, String uri, + BijectiveNsMap ns) + { + super(parent, ns); + mParent = parent; + mPrefix = prefix; + mLocalName = localName; + mURI = uri; + } + + /** + * Method called to reuse a pooled instance. + * + * @returns Chained pooled instance that should now be head of the + * reuse chain + */ + private void relink(SimpleOutputElement parent, + String prefix, String localName, String uri) + { + super.relink(parent); + mParent = parent; + mPrefix = prefix; + mLocalName = localName; + mURI = uri; + mNsMapping = parent.mNsMapping; + mNsMapShared = (mNsMapping != null); + mDefaultNsURI = parent.mDefaultNsURI; + mRootNsContext = parent.mRootNsContext; + } + + public static SimpleOutputElement createRoot() + { + return new SimpleOutputElement(); + } + + /** + * Simplest factory method, which gets called when a 1-argument + * element output method is called. It is, then, assumed to + * use the default namespce. + */ + protected SimpleOutputElement createChild(String localName) + { + /* At this point we can also discard attribute Map; it is assumed + * that when a child element has been opened, no more attributes + * can be output. + */ + mAttrSet = null; + return new SimpleOutputElement(this, null, localName, + mDefaultNsURI, mNsMapping); + } + + /** + * @return New head of the recycle pool + */ + protected SimpleOutputElement reuseAsChild(SimpleOutputElement parent, + String localName) + { + mAttrSet = null; + SimpleOutputElement poolHead = mParent; + relink(parent, null, localName, mDefaultNsURI); + return poolHead; + } + + protected SimpleOutputElement reuseAsChild(SimpleOutputElement parent, + String prefix, String localName, + String uri) + { + mAttrSet = null; + SimpleOutputElement poolHead = mParent; + relink(parent, prefix, localName, uri); + return poolHead; + } + + /** + * Full factory method, used for 'normal' namespace qualified output + * methods. + */ + protected SimpleOutputElement createChild(String prefix, String localName, + String uri) + { + /* At this point we can also discard attribute Map; it is assumed + * that when a child element has been opened, no more attributes + * can be output. + */ + mAttrSet = null; + return new SimpleOutputElement(this, prefix, localName, uri, mNsMapping); + } + + /** + * Method called to temporarily link this instance to a pool, to + * allow reusing of instances with the same reader. + */ + protected void addToPool(SimpleOutputElement poolHead) + { + mParent = poolHead; + } + + /* + /////////////////////////////////////////////////////////////////////// + // Public API, accessors + /////////////////////////////////////////////////////////////////////// + */ + + public SimpleOutputElement getParent() { + return mParent; + } + + @Override + public boolean isRoot() { + // (Virtual) Root element has no parent... + return (mParent == null); + } + + /** + * @return String presentation of the fully-qualified name, in + * "prefix:localName" format (no URI). Useful for error and + * debugging messages. + */ + @Override + public String getNameDesc() { + if (mPrefix != null && mPrefix.length() > 0) { + return mPrefix + ":" +mLocalName; + } + if (mLocalName != null && mLocalName.length() > 0) { + return mLocalName; + } + return "#error"; // unexpected case + } + + public String getPrefix() { + return mPrefix; + } + + public String getLocalName() { + return mLocalName; + } + + public String getNamespaceURI() { + return mURI; + } + + public QName getName() { + return QNameCreator.create(mURI, mLocalName, mPrefix); + } + + /* + /////////////////////////////////////////////////////////////////////// + // Public API, ns binding, checking + /////////////////////////////////////////////////////////////////////// + */ + + public void checkAttrWrite(String nsURI, String localName) + throws XMLStreamException + { + AttrName an = new AttrName(nsURI, localName); + if (mAttrSet == null) { + /* 13-Dec-2005, TSa: Should use a more efficient Set/Map value + * for this in future -- specifically one that could use + * ns/local-name pairs without intermediate objects + */ + mAttrSet = new HashSet(); + } + if (!mAttrSet.add(an)) { + throw new XMLStreamException("Duplicate attribute write for attribute '"+an+"'"); + } + } + + /* + /////////////////////////////////////////////////////////////////////// + // Public API, mutators + /////////////////////////////////////////////////////////////////////// + */ + + public void setPrefix(String prefix) { + mPrefix = prefix; + } + + @Override + public void setDefaultNsUri(String uri) { + mDefaultNsURI = uri; + } + + /** + * Note: this method can and will only be called before outputting + * the root element. + */ + @Override + protected final void setRootNsContext(NamespaceContext ctxt) + { + mRootNsContext = ctxt; + // Let's also figure out the default ns binding, if any: + String defURI = ctxt.getNamespaceURI(""); + if (defURI != null && defURI.length() > 0) { + mDefaultNsURI = defURI; + } + } + + /* + /////////////////////////////////////////////////////////////////////// + // Helper classes: + /////////////////////////////////////////////////////////////////////// + */ + + /** + * Simple key class used to represent two-piece (attribute) names; + * first part being optional (URI), and second non-optional (local name). + */ + final static class AttrName + implements Comparable + { + final String mNsURI; + final String mLocalName; + + /** + * Let's cache the hash code, since although hash calculation is + * fast, hash code is needed a lot as this is always used as a + * HashSet/TreeMap key. + */ + final int mHashCode; + + public AttrName(String nsURI, String localName) { + mNsURI = (nsURI == null) ? "" : nsURI; + mLocalName = localName; + mHashCode = mNsURI.hashCode() * 31 ^ mLocalName.hashCode(); + } + + @Override + public boolean equals(Object o) { + if (o == this) { + return true; + } + if (!(o instanceof AttrName)) { + return false; + } + AttrName other = (AttrName) o; + String otherLN = other.mLocalName; + // Local names are shorter, more varying: + if (otherLN != mLocalName && !otherLN.equals(mLocalName)) { + return false; + } + String otherURI = other.mNsURI; + return (otherURI == mNsURI || otherURI.equals(mNsURI)); + } + + @Override + public String toString() { + if (mNsURI.length() > 0) { + return "{"+mNsURI + "} " +mLocalName; + } + return mLocalName; + } + + @Override + public int hashCode() { + return mHashCode; + } + + @Override + public int compareTo(AttrName other) { + // Let's first order by namespace: + int result = mNsURI.compareTo(other.mNsURI); + if (result == 0) { + result = mLocalName.compareTo(other.mLocalName); + } + return result; + } + } +} diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/sw/TypedStreamWriter.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/sw/TypedStreamWriter.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/sw/TypedStreamWriter.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/sw/TypedStreamWriter.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,358 @@ +/* Woodstox XML processor + * + * Copyright (c) 2004- Tatu Saloranta, tatu.saloranta@iki.fi + * + * Licensed under the License specified in file LICENSE, included with + * the source code. + * You may not use this file except in compliance with the License. + * + * 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 com.ctc.wstx.sw; + +import java.io.IOException; +import java.math.BigDecimal; +import java.math.BigInteger; + +import javax.xml.namespace.QName; +import javax.xml.stream.XMLStreamException; + +import org.codehaus.stax2.typed.Base64Variant; +import org.codehaus.stax2.typed.Base64Variants; +import org.codehaus.stax2.ri.typed.AsciiValueEncoder; +import org.codehaus.stax2.ri.typed.ValueEncoderFactory; +import org.codehaus.stax2.validation.XMLValidator; + +import com.ctc.wstx.api.WriterConfig; +import com.ctc.wstx.cfg.ErrorConsts; +import com.ctc.wstx.exc.WstxIOException; + +/** + * Intermediate base class that implements Typed Access API (Stax2 v3) + * for all (repairing, non-repairing, non-namespace) native stream + * writer implementations. + */ +public abstract class TypedStreamWriter + extends BaseStreamWriter +{ + /** + * When outputting using Typed Access API, we will need + * encoders. If so, they will created by lazily-constructed + * factory + */ + protected ValueEncoderFactory mValueEncoderFactory; + + /* + //////////////////////////////////////////////////// + // Life-cycle + //////////////////////////////////////////////////// + */ + + protected TypedStreamWriter(XmlWriter xw, String enc, WriterConfig cfg) + { + super(xw, enc, cfg); + } + + protected final ValueEncoderFactory valueEncoderFactory() + { + if (mValueEncoderFactory == null) { + mValueEncoderFactory = new ValueEncoderFactory(); + } + return mValueEncoderFactory; + } + + /* + ///////////////////////////////////////////////// + // TypedXMLStreamWriter2 implementation + // (Typed Access API, Stax v3.0) + ///////////////////////////////////////////////// + */ + + // // // Typed element content write methods + + @Override + public void writeBoolean(boolean value) + throws XMLStreamException + { + writeTypedElement(valueEncoderFactory().getEncoder(value)); + } + + @Override + public void writeInt(int value) + throws XMLStreamException + { + writeTypedElement(valueEncoderFactory().getEncoder(value)); + } + + @Override + public void writeLong(long value) + throws XMLStreamException + { + writeTypedElement(valueEncoderFactory().getEncoder(value)); + } + + @Override + public void writeFloat(float value) + throws XMLStreamException + { + writeTypedElement(valueEncoderFactory().getEncoder(value)); + } + + @Override + public void writeDouble(double value) + throws XMLStreamException + { + writeTypedElement(valueEncoderFactory().getEncoder(value)); + + } + + @Override + public void writeInteger(BigInteger value) + throws XMLStreamException + { + /* No really efficient method exposed by JDK, keep it simple + * (esp. considering that length is actually not bound) + */ + writeTypedElement(valueEncoderFactory().getScalarEncoder(value.toString())); + } + + @Override + public void writeDecimal(BigDecimal value) + throws XMLStreamException + { + /* No really efficient method exposed by JDK, keep it simple + * (esp. considering that length is actually not bound) + */ + writeTypedElement(valueEncoderFactory().getScalarEncoder(value.toString())); + } + + @Override + public void writeQName(QName name) + throws XMLStreamException + { + /* Can't use AsciiValueEncoder, since QNames can contain + * non-ascii characters + */ + writeCharacters(serializeQName(name)); + } + + @Override + public final void writeIntArray(int[] value, int from, int length) + throws XMLStreamException + { + writeTypedElement(valueEncoderFactory().getEncoder(value, from, length)); + } + + @Override + public void writeLongArray(long[] value, int from, int length) + throws XMLStreamException + { + writeTypedElement(valueEncoderFactory().getEncoder(value, from, length)); + } + + @Override + public void writeFloatArray(float[] value, int from, int length) + throws XMLStreamException + { + writeTypedElement(valueEncoderFactory().getEncoder(value, from, length)); + } + + @Override + public void writeDoubleArray(double[] value, int from, int length) + throws XMLStreamException + { + writeTypedElement(valueEncoderFactory().getEncoder(value, from, length)); + } + + @Override + public void writeBinary(byte[] value, int from, int length) + throws XMLStreamException + { + Base64Variant v = Base64Variants.getDefaultVariant(); + writeTypedElement(valueEncoderFactory().getEncoder(v, value, from, length)); + } + + @Override + public void writeBinary(Base64Variant v, byte[] value, int from, int length) + throws XMLStreamException + { + writeTypedElement(valueEncoderFactory().getEncoder(v, value, from, length)); + } + + protected final void writeTypedElement(AsciiValueEncoder enc) + throws XMLStreamException + { + if (mStartElementOpen) { + closeStartElement(mEmptyElement); + } + // How about well-formedness? + if (mCheckStructure) { + if (inPrologOrEpilog()) { + reportNwfStructure(ErrorConsts.WERR_PROLOG_NONWS_TEXT); + } + } + // Or validity? + if (mVldContent <= XMLValidator.CONTENT_ALLOW_WS) { + reportInvalidContent(CHARACTERS); + } + + // So far so good: let's serialize + try { + XMLValidator vld = (mVldContent == XMLValidator.CONTENT_ALLOW_VALIDATABLE_TEXT) ? + mValidator : null; + if (vld == null) { + mWriter.writeTypedElement(enc); + } else { + mWriter.writeTypedElement(enc, vld, getCopyBuffer()); + } + } catch (IOException ioe) { + throw new WstxIOException(ioe); + } + } + + // // // Typed attribute value write methods + + @Override + public void writeBooleanAttribute(String prefix, String nsURI, String localName, boolean value) + throws XMLStreamException + { + writeTypedAttribute(prefix, nsURI, localName, + valueEncoderFactory().getEncoder(value)); + } + + @Override + public void writeIntAttribute(String prefix, String nsURI, String localName, int value) + throws XMLStreamException + { + writeTypedAttribute(prefix, nsURI, localName, + valueEncoderFactory().getEncoder(value)); + } + + @Override + public void writeLongAttribute(String prefix, String nsURI, String localName, long value) + throws XMLStreamException + { + writeTypedAttribute(prefix, nsURI, localName, + valueEncoderFactory().getEncoder(value)); + } + + @Override + public void writeFloatAttribute(String prefix, String nsURI, String localName, float value) + throws XMLStreamException + { + writeTypedAttribute(prefix, nsURI, localName, + valueEncoderFactory().getEncoder(value)); + } + + @Override + public void writeDoubleAttribute(String prefix, String nsURI, String localName, double value) + throws XMLStreamException + { + writeTypedAttribute(prefix, nsURI, localName, + valueEncoderFactory().getEncoder(value)); + } + + @Override + public void writeIntegerAttribute(String prefix, String nsURI, String localName, BigInteger value) + throws XMLStreamException + { + // not optimal, but has to do: + writeTypedAttribute(prefix, nsURI, localName, + valueEncoderFactory().getScalarEncoder(value.toString())); + } + + @Override + public void writeDecimalAttribute(String prefix, String nsURI, String localName, BigDecimal value) + throws XMLStreamException + { + // not optimal, but has to do: + writeTypedAttribute(prefix, nsURI, localName, + valueEncoderFactory().getScalarEncoder(value.toString())); + } + + @Override + public void writeQNameAttribute(String prefix, String nsURI, String localName, QName name) + throws XMLStreamException + { + /* Can't use AsciiValueEncoder, since QNames can contain + * non-ascii characters + */ + writeAttribute(prefix, nsURI, localName, serializeQName(name)); + } + + @Override + public void writeIntArrayAttribute(String prefix, String nsURI, String localName, int[] value) + throws XMLStreamException + { + writeTypedAttribute(prefix, nsURI, localName, + valueEncoderFactory().getEncoder(value, 0, value.length)); + } + + @Override + public void writeLongArrayAttribute(String prefix, String nsURI, String localName, long[] value) + throws XMLStreamException + { + writeTypedAttribute(prefix, nsURI, localName, + valueEncoderFactory().getEncoder(value, 0, value.length)); + } + + @Override + public void writeFloatArrayAttribute(String prefix, String nsURI, String localName, float[] value) + throws XMLStreamException + { + writeTypedAttribute(prefix, nsURI, localName, + valueEncoderFactory().getEncoder(value, 0, value.length)); + } + + @Override + public void writeDoubleArrayAttribute(String prefix, String nsURI, String localName, double[] value) + throws XMLStreamException + { + writeTypedAttribute(prefix, nsURI, localName, + valueEncoderFactory().getEncoder(value, 0, value.length)); + } + + @Override + public void writeBinaryAttribute(String prefix, String nsURI, String localName, byte[] value) + throws XMLStreamException + { + Base64Variant v = Base64Variants.getDefaultVariant(); + writeTypedAttribute(prefix, nsURI, localName, + valueEncoderFactory().getEncoder(v, value, 0, value.length)); + } + + @Override + public void writeBinaryAttribute(Base64Variant v, String prefix, String nsURI, String localName, byte[] value) + throws XMLStreamException + { + writeTypedAttribute(prefix, nsURI, localName, + valueEncoderFactory().getEncoder(v, value, 0, value.length)); + } + + /** + * Method that will write attribute with value that is known not to + * require additional escaping. + */ + protected abstract void writeTypedAttribute(String prefix, String nsURI, + String localName, + AsciiValueEncoder enc) + throws XMLStreamException; + + private String serializeQName(QName name) + throws XMLStreamException + { + String vp = validateQNamePrefix(name); + String local = name.getLocalPart(); + if (vp == null || vp.length() == 0) { + return local; + } + + // Not efficient... but should be ok + return vp + ":" + local; + } +} diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/sw/XmlWriter.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/sw/XmlWriter.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/sw/XmlWriter.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/sw/XmlWriter.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,631 @@ +/* Woodstox XML processor + * + * Copyright (c) 2004- Tatu Saloranta, tatu.saloranta@iki.fi + * + * Licensed under the License specified in file LICENSE, included with + * the source code. + * You may not use this file except in compliance with the License. + * + * 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 com.ctc.wstx.sw; + +import java.io.IOException; +import java.io.OutputStream; +import java.io.Writer; +import java.text.MessageFormat; + +import javax.xml.stream.XMLStreamException; + +import org.codehaus.stax2.io.EscapingWriterFactory; +import org.codehaus.stax2.ri.typed.AsciiValueEncoder; +import org.codehaus.stax2.validation.XMLValidator; + +import com.ctc.wstx.api.InvalidCharHandler; +import com.ctc.wstx.api.WriterConfig; +import com.ctc.wstx.api.WstxOutputProperties; +import com.ctc.wstx.cfg.ErrorConsts; +import com.ctc.wstx.cfg.OutputConfigFlags; +import com.ctc.wstx.exc.WstxIOException; +import com.ctc.wstx.io.WstxInputData; + +/** + * This is the base class for actual physical xml outputters. These + * instances will only handle actual writing (possibly including + * encoding) of the serialized textual xml, and will in general + * not verify content being output. The exception are the + * character-by-character checks that are most efficiently done + * at encoding level (such as character escaping, and checks for + * illegal character combinations), which are handled at this + * level. + *

+ * Note that implementations can have different operating modes: + * specifically, when dealing with illegal content (such as "--" + * in a comment, "?>" in processing instruction, or "]]>" within + * CDATA section), implementations can do one of 3 things: + *

    + *
  • Fix the problem, by splitting the section (which can be done + * for CDATA sections, and to some degree, comments) + *
  • + *
  • Stop outputting, and return an index to the illegal piece + * of data (if there is no easy way to fix the problem: for + * example, for processing instruction) + *
  • + *
  • Just output content even though it will not result in + * well-formed output. This should only be done if the calling + * application has specifically requested verifications to be + * disabled. + *
  • + *
+ */ +public abstract class XmlWriter +{ + protected final static int SURR1_FIRST = 0xD800; + protected final static int SURR1_LAST = 0xDBFF; + protected final static int SURR2_FIRST = 0xDC00; + protected final static int SURR2_LAST = 0xDFFF; + + protected final static char DEFAULT_QUOTE_CHAR = '"'; + + protected final WriterConfig mConfig; + protected final String mEncoding; + + // // // Operating mode: base class needs to know whether + // // // namespaces are support (for entity/PI target validation) + + protected final boolean mNsAware; + + protected final boolean mCheckStructure; + protected final boolean mCheckContent; + protected final boolean mCheckNames; + protected final boolean mFixContent; + + /** + * Whether to escape CR (\r) character. + */ + final boolean mEscapeCR; + + /** + * Whether to add a space after empty element (before closing "/>") + * or not. + */ + final boolean mAddSpaceAfterEmptyElem; + + /** + * Whether to use double quotes in XML declaration or not. + */ + final boolean mUseDoubleQuotesInXmlDecl; + + /** + * Flag that defines whether close() on this writer should call + * close on the underlying output object (stream, writer) + */ + protected final boolean mAutoCloseOutput; + + /** + * Optional escaping writer used for escaping characters like '<' + * '&' and '>' in textual content. + * Constructed if calling code has + * installed a special escaping writer factory for text content. + * Null if the default escaper is to be used. + */ + protected Writer mTextWriter; + + /** + * Optional escaping writer used for escaping characters like '"' + * '&' and '<' in attribute values. + * Constructed if calling code has + * installed a special escaping writer factory for text content. + * Null if the default escaper is to be used. + */ + protected Writer mAttrValueWriter; + + /** + * Indicates whether output is to be compliant; if false, is to be + * xml 1.0 compliant, if true, xml 1.1 compliant. + */ + protected boolean mXml11 = false; + + /** + * Lazy-constructed wrapper object, which will route all calls to + * Writer API, to matching writeRaw methods of this + * XmlWriter instance. + */ + protected XmlWriterWrapper mRawWrapper = null; + + /** + * Lazy-constructed wrapper object, which will route all calls to + * Writer API, to matching writeCharacters methods of this + * XmlWriter instance. + */ + protected XmlWriterWrapper mTextWrapper = null; + + /* + /////////////////////////////////////////////////////// + // Output location info + /////////////////////////////////////////////////////// + */ + + /** + * Number of characters output prior to currently buffered output + */ + protected int mLocPastChars = 0; + + protected int mLocRowNr = 1; + + /** + * Offset of the first character on this line. May be negative, if + * the offset was in a buffer that has been flushed out. + */ + protected int mLocRowStartOffset = 0; + + /* + /////////////////////////////////////////////////////// + // Life-cycle + /////////////////////////////////////////////////////// + */ + + protected XmlWriter(WriterConfig cfg, String encoding, boolean autoclose) + throws IOException + { + mConfig = cfg; + mEncoding = encoding; + mAutoCloseOutput = autoclose; + int flags = cfg.getConfigFlags(); + mNsAware = (flags & OutputConfigFlags.CFG_ENABLE_NS) != 0; + mCheckStructure = (flags & OutputConfigFlags.CFG_VALIDATE_STRUCTURE) != 0; + mCheckContent = (flags & OutputConfigFlags.CFG_VALIDATE_CONTENT) != 0; + mCheckNames = (flags & OutputConfigFlags.CFG_VALIDATE_NAMES) != 0; + mFixContent = (flags & OutputConfigFlags.CFG_FIX_CONTENT) != 0; + mEscapeCR = (flags & OutputConfigFlags.CFG_ESCAPE_CR) != 0; + mAddSpaceAfterEmptyElem = (flags & OutputConfigFlags.CFG_ADD_SPACE_AFTER_EMPTY_ELEM) != 0; + mUseDoubleQuotesInXmlDecl = (flags & OutputConfigFlags.CFG_USE_DOUBLE_QUOTES_IN_XML_DECL) != 0; + + // Has caller requested any custom text or attr value escaping? + + EscapingWriterFactory f = mConfig.getTextEscaperFactory(); + if (f == null) { + mTextWriter = null; + } else { + String enc = (mEncoding == null || mEncoding.length() == 0) ? + WstxOutputProperties.DEFAULT_OUTPUT_ENCODING : mEncoding; + mTextWriter = f.createEscapingWriterFor(wrapAsRawWriter(), enc); + } + + f = mConfig.getAttrValueEscaperFactory(); + if (f == null) { + mAttrValueWriter = null; + } else { + String enc = (mEncoding == null || mEncoding.length() == 0) ? + WstxOutputProperties.DEFAULT_OUTPUT_ENCODING : mEncoding; + mAttrValueWriter = f.createEscapingWriterFor(wrapAsRawWriter(), enc); + } + } + + /* + //////////////////////////////////////////////////// + // Extra configuration + //////////////////////////////////////////////////// + */ + + public void enableXml11() { + mXml11 = true; + } + + /* + //////////////////////////////////////////////////// + // Access to underlying physical output destinations + //////////////////////////////////////////////////// + */ + + /** + * @return Underlying OutputStream used for physical output, + * if the writer was constructed using one + */ + protected abstract OutputStream getOutputStream(); + + /** + * @return Underlying Writer used for physical output, + * if the writer was constructed with one, or one was + * created to be used with an OutputStream. + */ + protected abstract Writer getWriter(); + + /* + //////////////////////////////////////////////////// + // Basic methods for communicating with underlying + // stream or writer + //////////////////////////////////////////////////// + */ + + /** + * Method called to flush the buffer(s), and close the output + * sink (stream or writer) if enabled (auto-closing) or + * forced. + */ + public abstract void close(boolean forceRealClose) throws IOException; + + public abstract void flush() + throws IOException; + + public abstract void writeRaw(String str, int offset, int len) + throws IOException; + + public void writeRaw(String str) + throws IOException + { + writeRaw(str, 0, str.length()); + } + + public abstract void writeRaw(char[] cbuf, int offset, int len) + throws IOException; + + /** + * Like {@link #writeRaw}, but caller guarantees that the contents + * additionally are known to be in 7-bit ascii range. + */ + public abstract void writeRawAscii(char[] cbuf, int offset, int len) + throws IOException; + + /* + //////////////////////////////////////////////////// + // Raw, non-verifying write methods; used when + // directly copying trusted content + //////////////////////////////////////////////////// + */ + + public abstract void writeCDataStart() + throws IOException; + + public abstract void writeCDataEnd() + throws IOException; + + public abstract void writeCommentStart() + throws IOException; + + public abstract void writeCommentEnd() + throws IOException; + + public abstract void writePIStart(String target, boolean addSpace) + throws IOException; + + public abstract void writePIEnd() + throws IOException; + + /* + //////////////////////////////////////////////////// + // Write methods, textual: + //////////////////////////////////////////////////// + */ + + /** + * @param data Contents of the CDATA section to write out + + * @return offset of the (first) illegal content segment ("]]>") in + * passed content and not in repairing mode; or -1 if none or is + * repairing + */ + public abstract int writeCData(String data) + throws IOException, XMLStreamException; + + public abstract int writeCData(char[] cbuf, int offset, int len) + throws IOException, XMLStreamException; + + public abstract void writeCharacters(String data) + throws IOException; + + public abstract void writeCharacters(char[] cbuf, int offset, int len) + throws IOException; + + /* + //////////////////////////////////////////////////// + // Write methods, non-textual, non-elem/attr: + //////////////////////////////////////////////////// + */ + + /** + * Method that will try to output the content as specified. If + * the content passed in has embedded "--" in it, it will either + * add an intervening space between consequtive hyphens (if content + * fixing is enabled), or return the offset of the first hyphen in + * multi-hyphen sequence. + */ + public abstract int writeComment(String data) + throws IOException, XMLStreamException; + + /** + * Older "legacy" output method for outputting DOCTYPE declaration. + * Assumes that the passed-in String contains a complete DOCTYPE + * declaration properly quoted. + */ + public abstract void writeDTD(String data) + throws IOException, XMLStreamException; + + public abstract void writeDTD(String rootName, + String systemId, String publicId, + String internalSubset) + throws IOException, XMLStreamException; + + public abstract void writeEntityReference(String name) + throws IOException, XMLStreamException; + + public abstract int writePI(String target, String data) + throws IOException, XMLStreamException; + + public abstract void writeXmlDeclaration(String version, String enc, String standalone) + throws IOException; + + /* + //////////////////////////////////////////////////// + // Write methods, elements + //////////////////////////////////////////////////// + */ + + /** + *

+ * Note: can throw XMLStreamException, if name checking is enabled, + * and name is invalid (name check has to be in this writer, not + * caller, since it depends not only on xml limitations, but also + * on encoding limitations) + */ + public abstract void writeStartTagStart(String localName) + throws IOException, XMLStreamException; + + /** + *

+ * Note: can throw XMLStreamException, if name checking is enabled, + * and name is invalid (name check has to be in this writer, not + * caller, since it depends not only on xml limitations, but also + * on encoding limitations) + */ + public abstract void writeStartTagStart(String prefix, String localName) + throws IOException, XMLStreamException; + + public abstract void writeStartTagEnd() + throws IOException; + + public abstract void writeStartTagEmptyEnd() + throws IOException; + + public abstract void writeEndTag(String localName) + throws IOException; + + public abstract void writeEndTag(String prefix, String localName) + throws IOException; + + /* + //////////////////////////////////////////////////// + // Write methods, attributes/ns + //////////////////////////////////////////////////// + */ + + /** + *

+ * Note: can throw XMLStreamException, if name checking is enabled, + * and name is invalid (name check has to be in this writer, not + * caller, since it depends not only on xml limitations, but also + * on encoding limitations) + */ + public abstract void writeAttribute(String localName, String value) + throws IOException, XMLStreamException; + + public abstract void writeAttribute(String localName, char[] value, int offset, int len) + throws IOException, XMLStreamException; + + /** + *

+ * Note: can throw XMLStreamException, if name checking is enabled, + * and name is invalid (name check has to be in this writer, not + * caller, since it depends not only on xml limitations, but also + * on encoding limitations) + */ + public abstract void writeAttribute(String prefix, String localName, String value) + throws IOException, XMLStreamException; + + public abstract void writeAttribute(String prefix, String localName, char[] value, int offset, int len) + throws IOException, XMLStreamException; + + /* + //////////////////////////////////////////////////// + // Write methods, Typed Access API support + //////////////////////////////////////////////////// + */ + + /** + * Like {@link #writeRaw}, but caller guarantees that the contents + * additionally are known to be in 7-bit ascii range, and also + * passes an encoder object that will encode values only when + * being handed a buffer to append to. + * + * @param enc Encoder that will produce content + */ + public abstract void writeTypedElement(AsciiValueEncoder enc) + throws IOException; + + /** + * Like {@link #writeRaw}, but caller guarantees that the contents + * additionally are known to be in 7-bit ascii range, and also + * passes an encoder object that will encode values only when + * being handed a buffer to append to. + * + * @param enc Encoder that will produce content + * @param validator Validator to use for validating serialized textual + * content (can not be null) + * @param copyBuffer Temporary buffer that writer can use for temporary + * copies as necessary + */ + public abstract void writeTypedElement(AsciiValueEncoder enc, + XMLValidator validator, char[] copyBuffer) + throws IOException, XMLStreamException; + + /** + * Method similar to {@link #writeAttribute(String,String,char[],int,int)} + * but where is known not to require escaping. + * No validation needs to be performed. + */ + public abstract void writeTypedAttribute(String localName, AsciiValueEncoder enc) + throws IOException, XMLStreamException; + + /** + * Method similar to {@link #writeAttribute(String,String,char[],int,int)} + * but where is known not to require escaping. + * No validation needs to be performed. + */ + public abstract void writeTypedAttribute(String prefix, String localName, AsciiValueEncoder enc) + throws IOException, XMLStreamException; + + /** + * Method similar to {@link #writeAttribute(String,String,char[],int,int)} + * but where is known not to require escaping. + * Validation of the attribute value must be done by calling given + * validator appropriately. + */ + public abstract void writeTypedAttribute(String prefix, String localName, String nsURI, + AsciiValueEncoder enc, + XMLValidator validator, char[] copyBuffer) + throws IOException, XMLStreamException; + + /* + //////////////////////////////////////////////////// + // Location information + //////////////////////////////////////////////////// + */ + + protected abstract int getOutputPtr(); + + public int getRow() { + return mLocRowNr; + } + + public int getColumn() { + return (getOutputPtr() - mLocRowStartOffset) + 1; + } + + public int getAbsOffset() { + return mLocPastChars +getOutputPtr(); + } + + /* + //////////////////////////////////////////////////// + // Wrapper methods, semi-public + //////////////////////////////////////////////////// + */ + + /** + * Method that can be called to get a wrapper instance that + * can be used to essentially call the writeRaw + * method. + */ + public final Writer wrapAsRawWriter() + { + if (mRawWrapper == null) { + mRawWrapper = XmlWriterWrapper.wrapWriteRaw(this); + } + return mRawWrapper; + } + + public final Writer wrapAsTextWriter() + { + if (mTextWrapper == null) { + mTextWrapper = XmlWriterWrapper.wrapWriteCharacters(this); + } + return mTextWrapper; + } + + /* + //////////////////////////////////////////////////// + // Helper methods for sub-classes + //////////////////////////////////////////////////// + */ + + /** + * Method called to verify that the name is a legal XML name. + */ + public final void verifyNameValidity(String name, boolean checkNs) + throws XMLStreamException + { + /* No empty names... caller must have dealt with optional arguments + * prior to calling this method + */ + if (name == null || name.length() == 0) { + reportNwfName(ErrorConsts.WERR_NAME_EMPTY); + } + int illegalIx = WstxInputData.findIllegalNameChar(name, checkNs, mXml11); + if (illegalIx >= 0) { + if (illegalIx == 0) { + reportNwfName(ErrorConsts.WERR_NAME_ILLEGAL_FIRST_CHAR, + WstxInputData.getCharDesc(name.charAt(0))); + } + reportNwfName(ErrorConsts.WERR_NAME_ILLEGAL_CHAR, + WstxInputData.getCharDesc(name.charAt(illegalIx))); + } + } + + /** + * This is the method called when an output method call violates + * name well-formedness checks + * and {@link WstxOutputProperties#P_OUTPUT_VALIDATE_NAMES} is + * is enabled. + */ + protected void reportNwfName(String msg) + throws XMLStreamException + { + throwOutputError(msg); + } + + protected void reportNwfName(String msg, Object arg) + throws XMLStreamException + { + throwOutputError(msg, arg); + } + + protected void reportNwfContent(String msg) + throws XMLStreamException + { + throwOutputError(msg); + } + + protected void throwOutputError(String msg) + throws XMLStreamException + { + // First, let's flush any output we may have, to make debugging easier + try { + flush(); + } catch (IOException ioe) { + throw new WstxIOException(ioe); + } + + throw new XMLStreamException(msg); + } + + protected void throwOutputError(String format, Object arg) + throws XMLStreamException + { + String msg = MessageFormat.format(format, new Object[] { arg }); + throwOutputError(msg); + } + + /** + * Method called to handle invalid character in textual content requested + * to be output. Content may be part of textual events (CHARACTER, CDATA), + * attribute value, COMMENT content or PROCESSING_INSTRUCTION data. + * The default behavior is to just throw an exception, but this can + * be configured via property {@link WstxOutputProperties#P_OUTPUT_INVALID_CHAR_HANDLER}. + */ + protected char handleInvalidChar(int c) + throws IOException + { + // First, let's flush any output we may have, to make debugging easier + flush(); + InvalidCharHandler h = mConfig.getInvalidCharHandler(); + if (h == null) { + h = InvalidCharHandler.FailingHandler.getInstance(); + } + return h.convertInvalidChar(c); + } +} diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/sw/XmlWriterWrapper.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/sw/XmlWriterWrapper.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/sw/XmlWriterWrapper.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/sw/XmlWriterWrapper.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,167 @@ +/* Woodstox XML processor + * + * Copyright (c) 2004- Tatu Saloranta, tatu.saloranta@iki.fi + * + * Licensed under the License specified in file LICENSE, included with + * the source code. + * You may not use this file except in compliance with the License. + * + * 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 com.ctc.wstx.sw; + +import java.io.*; + +/** + * This is a simple wrapper class, which decorates an {@link XmlWriter} + * to look like a Writer. This is necessary to implement a (legacy) + * character quoting system introduced for Woodstox 2.0, which relies + * on having a Writer to use for outputting. + */ +public abstract class XmlWriterWrapper + extends Writer +{ + protected final XmlWriter mWriter; + + private char[] mBuffer = null; + + public static XmlWriterWrapper wrapWriteRaw(XmlWriter xw) + { + return new RawWrapper(xw); + } + + public static XmlWriterWrapper wrapWriteCharacters(XmlWriter xw) + { + return new TextWrapper(xw); + } + + protected XmlWriterWrapper(XmlWriter writer) + { + mWriter = writer; + } + + @Override + public final void close() throws IOException + { + mWriter.close(false); + } + + @Override + public final void flush() throws IOException + { + mWriter.flush(); + } + + /* !!! 30-Nov-2006, TSa: Due to co-variance between Appendable and + * Writer, this would not compile with javac 1.5, in 1.4 mode + * (source and target set to "1.4". Not a huge deal, but since + * the base impl is just fine, no point in overriding it. + */ + /* + public final Writer append(char c) + throws IOException + { + if (mBuffer == null) { + mBuffer = new char[1]; + } + mBuffer[0] = (char) c; + write(mBuffer, 0, 1); + return this; + } + */ + + @Override + public final void write(char[] cbuf) throws IOException { + write(cbuf, 0, cbuf.length); + } + + @Override + public abstract void write(char[] cbuf, int off, int len) throws IOException; + + @Override + public final void write(int c) throws IOException + { + if (mBuffer == null) { + mBuffer = new char[1]; + } + mBuffer[0] = (char) c; + write(mBuffer, 0, 1); + } + + @Override + public abstract void write(String str) throws IOException; + + @Override + public abstract void write(String str, int off, int len) throws IOException; + + /* + ////////////////////////////////////////////////// + // Implementation classes + ////////////////////////////////////////////////// + */ + + /** + * This wrapper directs calls to writeRaw methods. Thus, + * it is a "vanilla" writer, and no escaping is done. + */ + private final static class RawWrapper + extends XmlWriterWrapper + { + protected RawWrapper(XmlWriter writer) + { + super(writer); + } + + @Override + public void write(char[] cbuf, int off, int len) throws IOException + { + mWriter.writeRaw(cbuf, off, len); + } + + @Override + public void write(String str, int off, int len) throws IOException + { + mWriter.writeRaw(str, off, len); + } + + @Override + public final void write(String str) throws IOException + { + mWriter.writeRaw(str, 0, str.length()); + } + } + + /** + * This wrapper directs calls to writeCharacters methods. + * This means that text content escaping (and, possibly, validation) + * is done, using default or custom escaping code. + */ + private static class TextWrapper + extends XmlWriterWrapper + { + protected TextWrapper(XmlWriter writer) { + super(writer); + } + + @Override + public void write(char[] cbuf, int off, int len) throws IOException { + mWriter.writeCharacters(cbuf, off, len); + } + + @Override + public void write(String str) throws IOException { + mWriter.writeCharacters(str); + } + + @Override + public void write(String str, int off, int len) throws IOException { + mWriter.writeCharacters(str.substring(off, off+len)); + } + } +} + diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/util/ArgUtil.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/util/ArgUtil.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/util/ArgUtil.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/util/ArgUtil.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,83 @@ +package com.ctc.wstx.util; + +/** + * Simple static utility class that contains (static) utility methods useful + * when parsing non-typesafe arguments (String-only configuration, command + * line args). + */ +public final class ArgUtil +{ + private ArgUtil() { } + + public static boolean convertToBoolean(String prop, Object value) + { + if (value == null) { + return false; + } + if (value instanceof Boolean) { + return ((Boolean) value).booleanValue(); + } + if (value instanceof String) { + String str = (String) value; + if (str.equalsIgnoreCase("false")) { + return false; + } + if (str.equalsIgnoreCase("true")) { + return true; + } + throw new IllegalArgumentException("Invalid String value for property '"+prop+"': expected Boolean value."); + } + throw new IllegalArgumentException("Invalid value type ("+value.getClass()+") for property '"+prop+"': expected Boolean value."); + } + + public static int convertToInt(String prop, Object value, int minValue) + { + int i; + + if (value == null) { + i = 0; + } else if (value instanceof Number) { + i = ((Number) value).intValue(); + } else if (value instanceof String) { + try { + i = Integer.parseInt((String) value); + } catch (NumberFormatException nex) { + throw new IllegalArgumentException("Invalid String value for property '"+prop+"': expected a number (Integer)."); + } + } else { + throw new IllegalArgumentException("Invalid value type ("+value.getClass()+") for property '"+prop+"': expected Integer value."); + } + + if (i < minValue) { + throw new IllegalArgumentException("Invalid numeric value ("+i + +") for property '"+prop + +"': minimum is "+minValue+"."); + } + return i; + } + public static long convertToLong(String prop, Object value, long minValue) + { + long i; + + if (value == null) { + i = 0; + } else if (value instanceof Number) { + i = ((Number) value).longValue(); + } else if (value instanceof String) { + try { + i = Long.parseLong((String) value); + } catch (NumberFormatException nex) { + throw new IllegalArgumentException("Invalid String value for property '"+prop+"': expected a number (Long)."); + } + } else { + throw new IllegalArgumentException("Invalid value type ("+value.getClass()+") for property '"+prop+"': expected Long value."); + } + + if (i < minValue) { + throw new IllegalArgumentException("Invalid numeric value ("+i + +") for property '"+prop + +"': minimum is "+minValue+"."); + } + return i; + } +} diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/util/BaseNsContext.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/util/BaseNsContext.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/util/BaseNsContext.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/util/BaseNsContext.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,134 @@ +/* Woodstox XML processor + * + * Copyright (c) 2004 Tatu Saloranta, tatu.saloranta@iki.fi + * + * Licensed under the License specified in file LICENSE, included with + * the source code. + * You may not use this file except in compliance with the License. + * + * 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 com.ctc.wstx.util; + +import java.io.IOException; +import java.io.Writer; +import java.util.Iterator; + +import javax.xml.XMLConstants; +import javax.xml.namespace.NamespaceContext; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamWriter; +import javax.xml.stream.events.Namespace; + +import com.ctc.wstx.cfg.ErrorConsts; + +/** + * Abstract base class that defines extra features defined by most + * NamespaceContext implementations Wodstox uses. + */ +public abstract class BaseNsContext + implements NamespaceContext +{ + /** + * This is the URI returned for default namespace, when it hasn't + * been explicitly declared; could be either "" or null. + */ + protected final static String UNDECLARED_NS_URI = ""; + + /* + ///////////////////////////////////////////// + // NamespaceContext API + ///////////////////////////////////////////// + */ + + @Override + public final String getNamespaceURI(String prefix) + { + /* First the known offenders; invalid args, 2 predefined xml namespace + * prefixes + */ + if (prefix == null) { + throw new IllegalArgumentException(ErrorConsts.ERR_NULL_ARG); + } + if (prefix.length() > 0) { + if (prefix.equals(XMLConstants.XML_NS_PREFIX)) { + return XMLConstants.XML_NS_URI; + } + if (prefix.equals(XMLConstants.XMLNS_ATTRIBUTE)) { + return XMLConstants.XMLNS_ATTRIBUTE_NS_URI; + } + } + return doGetNamespaceURI(prefix); + } + + @Override + public final String getPrefix(String nsURI) + { + /* First the known offenders; invalid args, 2 predefined xml namespace + * prefixes + */ + if (nsURI == null || nsURI.length() == 0) { + throw new IllegalArgumentException("Illegal to pass null/empty prefix as argument."); + } + if (nsURI.equals(XMLConstants.XML_NS_URI)) { + return XMLConstants.XML_NS_PREFIX; + } + if (nsURI.equals(XMLConstants.XMLNS_ATTRIBUTE_NS_URI)) { + return XMLConstants.XMLNS_ATTRIBUTE; + } + return doGetPrefix(nsURI); + } + + @Override + public final Iterator getPrefixes(String nsURI) + { + /* First the known offenders; invalid args, 2 predefined xml namespace + * prefixes + */ + if (nsURI == null || nsURI.length() == 0) { + throw new IllegalArgumentException("Illegal to pass null/empty prefix as argument."); + } + if (nsURI.equals(XMLConstants.XML_NS_URI)) { + return DataUtil.singletonIterator(XMLConstants.XML_NS_PREFIX); + } + if (nsURI.equals(XMLConstants.XMLNS_ATTRIBUTE_NS_URI)) { + return DataUtil.singletonIterator(XMLConstants.XMLNS_ATTRIBUTE); + } + + return doGetPrefixes(nsURI); + } + + /* + ///////////////////////////////////////////// + // Extended API + ///////////////////////////////////////////// + */ + + public abstract Iterator getNamespaces(); + + /** + * Method called by the matching start element class to + * output all namespace declarations active in current namespace + * scope, if any. + */ + public abstract void outputNamespaceDeclarations(Writer w) throws IOException; + + public abstract void outputNamespaceDeclarations(XMLStreamWriter w) throws XMLStreamException; + + /* + ///////////////////////////////////////////////// + // Template methods sub-classes need to implement + ///////////////////////////////////////////////// + */ + + public abstract String doGetNamespaceURI(String prefix); + + public abstract String doGetPrefix(String nsURI); + + public abstract Iterator doGetPrefixes(String nsURI); +} diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/util/BijectiveNsMap.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/util/BijectiveNsMap.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/util/BijectiveNsMap.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/util/BijectiveNsMap.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,320 @@ +/* Woodstox XML processor + * + * Copyright (c) 2005 Tatu Saloranta, tatu.saloranta@iki.fi + * + * Licensed under the License specified in file LICENSE, included with + * the source code. + * You may not use this file except in compliance with the License. + * + * 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 com.ctc.wstx.util; + +import java.util.*; + +import javax.xml.XMLConstants; +import javax.xml.namespace.NamespaceContext; + +import com.ctc.wstx.util.DataUtil; + +/** + * Helper class that implements "bijective map" (Map that allows use of values + * as keys and vice versa, bidirectional access), and is specifically + * used for storing namespace binding information. + * One thing worth noting is that Strings stored are NOT assumed to have + * been unified (interned) -- if they were, different implementation would + * be more optimal. + *

+ * Currently only used by stream writers, but could be more generally useful + * too. + */ + +public final class BijectiveNsMap +{ + /* + /////////////////////////////////////////////// + // Constants + /////////////////////////////////////////////// + */ + + /** + * Let's plan for having up to 14 explicit namespace declarations (2 + * defaults, for 'xml' and 'xmlns', are pre-populated) + */ + final static int DEFAULT_ARRAY_SIZE = 2 * 16; + + /* + /////////////////////////////////////////////// + // Member vars + /////////////////////////////////////////////// + */ + + final int mScopeStart; + + /** + * Array that contains { prefix, ns-uri } pairs, up to (but not including) + * index {@link #mScopeEnd}. + */ + String[] mNsStrings; + + int mScopeEnd; + + /* + /////////////////////////////////////////////// + // Life-cycle + /////////////////////////////////////////////// + */ + + private BijectiveNsMap(int scopeStart, String[] strs) + { + mScopeStart = mScopeEnd = scopeStart; + mNsStrings = strs; + } + + public static BijectiveNsMap createEmpty() + { + String[] strs = new String[DEFAULT_ARRAY_SIZE]; + + strs[0] = XMLConstants.XML_NS_PREFIX; + strs[1] = XMLConstants.XML_NS_URI; + strs[2] = XMLConstants.XMLNS_ATTRIBUTE; + strs[3] = XMLConstants.XMLNS_ATTRIBUTE_NS_URI; + + /* Let's consider pre-defined ones to be 'out of scope', i.e. + * conceptually be part of (missing) parent's mappings. + */ + return new BijectiveNsMap(4, strs); + } + + public BijectiveNsMap createChild() { + return new BijectiveNsMap(mScopeEnd, mNsStrings); + } + + /* + /////////////////////////////////////////////// + // Public API, accessors + /////////////////////////////////////////////// + */ + + public String findUriByPrefix(String prefix) + { + /* This is quite simple: just need to locate the last mapping + * for the prefix, if any: + */ + String[] strs = mNsStrings; + int phash = prefix.hashCode(); + + for (int ix = mScopeEnd - 2; ix >= 0; ix -= 2) { + String thisP = strs[ix]; + if (thisP == prefix || + (thisP.hashCode() == phash && thisP.equals(prefix))) { + return strs[ix+1]; + } + } + return null; + } + + public String findPrefixByUri(String uri) + { + /* Finding a valid binding for the given URI is trickier, since + * mappings can be masked by others... so, we need to first find + * most recent binding, from the freshest one, and then verify + * it's still unmasked; if not, continue with the first loop, + * and so on. + */ + + String[] strs = mNsStrings; + int uhash = uri.hashCode(); + + main_loop: + for (int ix = mScopeEnd - 1; ix > 0; ix -= 2) { + String thisU = strs[ix]; + if (thisU == uri || + (thisU.hashCode() == uhash && thisU.equals(uri))) { + // match, but has it been masked? + String prefix = strs[ix-1]; + /* only need to check, if it wasn't within current scope + * (no masking allowed within scopes) + */ + if (ix < mScopeStart) { + int phash = prefix.hashCode(); + for (int j = ix+1, end = mScopeEnd; j < end; j += 2) { + String thisP = strs[j]; + if (thisP == prefix || + (thisP.hashCode() == phash && thisP.equals(prefix))) { + // Masking... got to continue the main loop: + continue main_loop; + } + } + } + // Ok, unmasked one, can return + return prefix; + } + } + return null; + } + + public List getPrefixesBoundToUri(String uri, List l) + { + /* Same problems (masking) apply here, as well as with + * findPrefixByUri... + */ + String[] strs = mNsStrings; + int uhash = uri.hashCode(); + + main_loop: + for (int ix = mScopeEnd - 1; ix > 0; ix -= 2) { + String thisU = strs[ix]; + if (thisU == uri || + (thisU.hashCode() == uhash && thisU.equals(uri))) { + // match, but has it been masked? + String prefix = strs[ix-1]; + /* only need to check, if it wasn't within current scope + * (no masking allowed within scopes) + */ + if (ix < mScopeStart) { + int phash = prefix.hashCode(); + for (int j = ix+1, end = mScopeEnd; j < end; j += 2) { + String thisP = strs[j]; + if (thisP == prefix || + (thisP.hashCode() == phash && thisP.equals(prefix))) { + // Masking... got to continue the main loop: + continue main_loop; + } + } + } + // Ok, unmasked one, can add + if (l == null) { + l = new ArrayList(); + } + l.add(prefix); + } + } + return l; + } + + public int size() { + return (mScopeEnd >> 1); + } + + public int localSize() { + return ((mScopeEnd - mScopeStart) >> 1); + } + + /* + /////////////////////////////////////////////// + // Public API, mutators + /////////////////////////////////////////////// + */ + + /** + * Method to add a new prefix-to-URI mapping for the current scope. + * Note that it should NOT be used for the default namespace + * declaration + * + * @param prefix Prefix to bind + * @param uri URI to bind to the prefix + * + * @return If the prefix was already bound, the URI it was bound to: + * null if it's a new binding for the current scope. + */ + public String addMapping(String prefix, String uri) + { + String[] strs = mNsStrings; + int phash = prefix.hashCode(); + + for (int ix = mScopeStart, end = mScopeEnd; ix < end; ix += 2) { + String thisP = strs[ix]; + if (thisP == prefix || + (thisP.hashCode() == phash && thisP.equals(prefix))) { + // Overriding an existing mapping + String old = strs[ix+1]; + strs[ix+1] = uri; + return old; + } + } + // no previous binding, let's just add it at the end + if (mScopeEnd >= strs.length) { + // let's just double the array sizes... + strs = DataUtil.growArrayBy(strs, strs.length); + mNsStrings = strs; + } + strs[mScopeEnd++] = prefix; + strs[mScopeEnd++] = uri; + + return null; + } + + /** + * Method used to add a dynamic binding, and return the prefix + * used to bind the specified namespace URI. + */ + public String addGeneratedMapping(String prefixBase, NamespaceContext ctxt, + String uri, int[] seqArr) + { + String[] strs = mNsStrings; + int seqNr = seqArr[0]; + String prefix; + + main_loop: + while (true) { + /* We better intern the resulting prefix? Or not? + * TODO: maybe soft cache these for other docs? + */ + prefix = (prefixBase + seqNr).intern(); + ++seqNr; + + /* Ok, let's see if we have a mapping (masked or not) for + * the prefix. If we do, let's just not use it: we could + * of course mask it (unless it's in current scope), but + * it's easier to just get a "virgin" prefix... + */ + int phash = prefix.hashCode(); + + for (int ix = mScopeEnd - 2; ix >= 0; ix -= 2) { + String thisP = strs[ix]; + if (thisP == prefix || + (thisP.hashCode() == phash && thisP.equals(prefix))) { + continue main_loop; + } + } + /* So far so good... but do we have a root context that might + * have something too? + */ + + if (ctxt != null && ctxt.getNamespaceURI(prefix) != null) { + continue; + } + break; + } + seqArr[0] = seqNr; + + // Ok, good; then let's just add it in... + if (mScopeEnd >= strs.length) { + // let's just double the array sizes... + strs = DataUtil.growArrayBy(strs, strs.length); + mNsStrings = strs; + } + strs[mScopeEnd++] = prefix; + strs[mScopeEnd++] = uri; + + return prefix; + } + + /* + /////////////////////////////////////////////// + // Standard overridden methods + /////////////////////////////////////////////// + */ + + @Override + public String toString() { + return "["+getClass().toString()+"; "+size()+" entries; of which " + +localSize()+" local]"; + } +} diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/util/DataUtil.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/util/DataUtil.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/util/DataUtil.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/util/DataUtil.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,128 @@ +package com.ctc.wstx.util; + +import java.lang.reflect.Array; +import java.util.*; + +import org.codehaus.stax2.ri.EmptyIterator; +import org.codehaus.stax2.ri.SingletonIterator; + +public final class DataUtil +{ + final static char[] EMPTY_CHAR_ARRAY = new char[0]; + + final static Long MAX_LONG = new Long(Long.MAX_VALUE); + + private DataUtil() { } + + /* + //////////////////////////////////////////////////////////// + // Pooling for immutable objects + //////////////////////////////////////////////////////////// + */ + + public static char[] getEmptyCharArray() { + return EMPTY_CHAR_ARRAY; + } + + // TODO: deprecate, not really needed post-JDK-1.4 + public static Integer Integer(int i) { + return Integer.valueOf(i); + } + + /* + //////////////////////////////////////////////////////////// + // Empty/singleton thingies + //////////////////////////////////////////////////////////// + */ + + public static Iterator singletonIterator(T item) { + // TODO: with JDK 1.7, can use method from Collections + // TODO: alternatively, with Woodstox 5.1, can fix deprecation marker + return SingletonIterator.create(item); + } + + public static Iterator emptyIterator() { + // TODO: with JDK 1.7, can use method from Collections + return EmptyIterator.getInstance(); + } + + /* + //////////////////////////////////////////////////////////// + // Methods for common operations on std data structs + //////////////////////////////////////////////////////////// + */ + + /** + * Method that can be used to efficiently check if 2 collections + * share at least one common element. + * + * @return True if there is at least one element that's common + * to both Collections, ie. that is contained in both of them. + */ + public static boolean anyValuesInCommon(Collection c1, Collection c2) + { + // Let's always iterate over smaller collection: + if (c1.size() > c2.size()) { + Collection tmp = c1; + c1 = c2; + c2 = tmp; + } + Iterator it = c1.iterator(); + while (it.hasNext()) { + if (c2.contains(it.next())) { + return true; + } + } + return false; + } + + final static String NO_TYPE = "Illegal to pass null; can not determine component type"; + + public static Object growArrayBy50Pct(Object arr) + { + if (arr == null) { + throw new IllegalArgumentException(NO_TYPE); + } + Object old = arr; + int len = Array.getLength(arr); + arr = Array.newInstance(arr.getClass().getComponentType(), len + (len >> 1)); + System.arraycopy(old, 0, arr, 0, len); + return arr; + } + + /** + * Method similar to {@link #growArrayBy50Pct}, but it also ensures that + * the new size is at least as big as the specified minimum size. + */ + public static Object growArrayToAtLeast(Object arr, int minLen) + { + if (arr == null) { + throw new IllegalArgumentException(NO_TYPE); + } + Object old = arr; + int oldLen = Array.getLength(arr); + int newLen = oldLen + ((oldLen + 1) >> 1); + if (newLen < minLen) { + newLen = minLen; + } + arr = Array.newInstance(arr.getClass().getComponentType(), newLen); + System.arraycopy(old, 0, arr, 0, oldLen); + return arr; + } + + public static String[] growArrayBy(String[] arr, int more) + { + if (arr == null) { + return new String[more]; + } + return Arrays.copyOf(arr, arr.length + more); + } + + public static int[] growArrayBy(int[] arr, int more) + { + if (arr == null) { + return new int[more]; + } + return Arrays.copyOf(arr, arr.length + more); + } +} diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/util/DefaultXmlSymbolTable.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/util/DefaultXmlSymbolTable.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/util/DefaultXmlSymbolTable.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/util/DefaultXmlSymbolTable.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,93 @@ +package com.ctc.wstx.util; + +import com.ctc.wstx.util.SymbolTable; + +/** + * Factory class used for instantiating pre-populated XML symbol + * tables. Such tables already have basic String constants that + * XML standard defines. + */ +public final class DefaultXmlSymbolTable +{ + /** + * Root symbol table from which child instances are derived. + */ + final static SymbolTable sInstance; + + final static String mNsPrefixXml; + final static String mNsPrefixXmlns; + + /* Although theoretically there'd be no strict need to pre-populate + * the default table, if all access was done using suggested usage + * patterns (reuse input factories consistently, esp. for same types + * of documents), it is possible some developers just use each factory + * just once. As such, it does matter how tables are pre-populated. + * Thus, let's use limited sensible set of predefined prefixes and + * names. + */ + static { + /* 128 means it's ok without resize up to ~96 symbols; true that + * default symbols added will be interned. + */ + sInstance = new SymbolTable(true, 128); + + // Let's add default namespace binding prefixes + mNsPrefixXml = sInstance.findSymbol("xml"); + mNsPrefixXmlns = sInstance.findSymbol("xmlns"); + + /* No need to add keywords, as they are checked directly by + * Reader, without constructing Strings. + */ + + // Ok, any common prefixes? + + // or local names (element, attribute)? + sInstance.findSymbol("id"); + sInstance.findSymbol("name"); + + // XML Schema? + // prefixes: + sInstance.findSymbol("xsd"); + sInstance.findSymbol("xsi"); + // local names: + sInstance.findSymbol("type"); + + // How about some common prefixes and names for Soap? + // commonly used prefixes: + sInstance.findSymbol("soap"); + sInstance.findSymbol("SOAP-ENC"); + sInstance.findSymbol("SOAP-ENV"); + // local names: + sInstance.findSymbol("Body"); + sInstance.findSymbol("Envelope"); + } + + /* + /////////////////////////////////////////////////// + // Public API, factory method(s): + /////////////////////////////////////////////////// + */ + + /** + * Method that will return an instance of SymbolTable that has basic + * XML 1.0 constants pre-populated. + */ + public static SymbolTable getInstance() { + return sInstance.makeChild(); + } + + /* + /////////////////////////////////////////////////// + // Public API, efficient access to (shared) + // constants values: + /////////////////////////////////////////////////// + */ + + public static String getXmlSymbol() { + return mNsPrefixXml; + } + + public static String getXmlnsSymbol() { + return mNsPrefixXmlns; + } +} diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/util/ElementId.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/util/ElementId.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/util/ElementId.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/util/ElementId.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,163 @@ +package com.ctc.wstx.util; + +import javax.xml.stream.Location; + +import com.ctc.wstx.cfg.ErrorConsts; + +/** + * Simple container Object used to store information about id attribute + * values, and references to such (as of yet undefined) values. + *

+ * Instances can be in one of 2 modes: either in fully defined mode, + * in which case information refers to location where value was defined + * (ie. we had id as a value of ID type attribute); or in undefined mode, + * in which case information refers to the first reference. + *

+ * Note: this class is designed to be used with {@link ElementIdMap}, + * and as a result has some information specifically needed by the + * map implementation (such as collision links). + */ +public final class ElementId +{ + /** + * Flag that indicates whether this Object presents a defined id + * value (value of an ID attribute) or just a reference to one. + */ + private boolean mDefined; + + /* + ///////////////////////////////////////////////// + // Information about id value or value reference, + // depending on mDefined flag + ///////////////////////////////////////////////// + */ + + /** + * Actual id value + */ + private final String mIdValue; + + /** + * Location of either definition (if {@link #mDefined} is true; or + * first reference (otherwise). Used when reporting errors; either + * a referenced id has not been defined, or there are multiple + * definitions of same id. + */ + private Location mLocation; + + /** + * Name of element for which this id refers. + */ + private PrefixedName mElemName; + + /** + * Name of the attribute that contains this id value (often "id", + * but need not be) + */ + private PrefixedName mAttrName; + + /* + //////////////////////////////////////////////////// + // Linking information, needed by the map to keep + // track of collided ids, as well as undefined ids + //////////////////////////////////////////////////// + */ + + private ElementId mNextUndefined; + + /** + * Pointer to the next element within collision chain. + */ + private ElementId mNextColl; + + /* + ///////////////////////////////////////////////// + // Life cycle + ///////////////////////////////////////////////// + */ + + ElementId(String id, Location loc, boolean defined, + PrefixedName elemName, PrefixedName attrName) + { + mIdValue = id; + mLocation = loc; + mDefined = defined; + mElemName = elemName; + mAttrName = attrName; + } + + protected void linkUndefined(ElementId undefined) + { + if (mNextUndefined != null) { + throw new IllegalStateException("ElementId '"+this+"' already had net undefined set ('"+mNextUndefined+"')"); + } + mNextUndefined = undefined; + } + + protected void setNextColliding(ElementId nextColl) + { + // May add/remove link, no point in checking + mNextColl = nextColl; + } + + /* + ///////////////////////////////////////////////// + // Public API + ///////////////////////////////////////////////// + */ + + public String getId() { return mIdValue; } + public Location getLocation() { return mLocation; } + public PrefixedName getElemName() { return mElemName; } + public PrefixedName getAttrName() { return mAttrName; } + + public boolean isDefined() { return mDefined; } + + public boolean idMatches(char[] buf, int start, int len) + { + if (mIdValue.length() != len) { + return false; + } + // Assumes it's always at least one char long + if (buf[start] != mIdValue.charAt(0)) { + return false; + } + int i = 1; + len += start; + while (++start < len) { + if (buf[start] != mIdValue.charAt(i)) { + return false; + } + ++i; + } + return true; + } + + public boolean idMatches(String idStr) + { + return mIdValue.equals(idStr); + } + + public ElementId nextUndefined() { return mNextUndefined; } + public ElementId nextColliding() { return mNextColl; } + + public void markDefined(Location defLoc) { + if (mDefined) { // sanity check + throw new IllegalStateException(ErrorConsts.ERR_INTERNAL); + } + mDefined = true; + mLocation = defLoc; + } + + /* + ///////////////////////////////////////////////// + // Other methods + ///////////////////////////////////////////////// + */ + + @Override + public String toString() { + return mIdValue; + } +} + diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/util/ElementIdMap.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/util/ElementIdMap.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/util/ElementIdMap.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/util/ElementIdMap.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,427 @@ +/* Woodstox XML processor + * + * Copyright (c) 2004- Tatu Saloranta, tatu.saloranta@iki.fi + * + * Licensed under the License specified in the file LICENSE which is + * included with the source code. + * You may not use this file except in compliance with the License. + * + * 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 com.ctc.wstx.util; + +import javax.xml.stream.Location; + + +/** + * This class is a specialized type-safe linked hash map used for + * storing {@link ElementId} instances. {@link ElementId} instances + * represent both id definitions (values of element attributes that + * have type ID in DTD), and references (values of element attributes + * of type IDREF and IDREFS). These definitions and references are + * stored for the purpose of verifying + * that all referenced id values are defined, and that none are defined + * more than once. + *

+ * Note: there are 2 somewhat distinct usage modes, by DTDValidator and + * by MSV-based validators. + * DTDs pass raw character arrays, whereas + * MSV-based validators operate on Strings. This is the main reason + * for 2 distinct sets of methods. + */ + +public final class ElementIdMap +{ + /** + * Default initial table size; set so that usually it need not + * be expanded. + */ + protected static final int DEFAULT_SIZE = 128; + + protected static final int MIN_SIZE = 16; + + /** + * Let's use 80% fill factor... + */ + protected static final int FILL_PCT = 80; + + /* + //////////////////////////////////////// + // Actual hash table structure + //////////////////////////////////////// + */ + + /** + * Actual hash table area + */ + protected ElementId[] mTable; + + /** + * Current size (number of entries); needed to know if and when + * rehash. + */ + protected int mSize; + + /** + * Limit that indicates maximum size this instance can hold before + * it needs to be expanded and rehashed. Calculated using fill + * factor passed in to constructor. + */ + protected int mSizeThreshold; + + /** + * Mask used to get index from hash values; equal to + * mBuckets.length - 1, when mBuckets.length is + * a power of two. + */ + protected int mIndexMask; + + /* + //////////////////////////////////////// + // Linked list info + //////////////////////////////////////// + */ + + protected ElementId mHead; + + protected ElementId mTail; + + /* + //////////////////////////////////////// + // Life-cycle: + //////////////////////////////////////// + */ + + public ElementIdMap() + { + this(DEFAULT_SIZE); + } + + /** + * This constructor is mainly used for testing, as it can be sized + * appropriately to test rehashing etc. + */ + public ElementIdMap(int initialSize) + { + int actual = MIN_SIZE; + while (actual < initialSize) { + actual += actual; + } + mTable = new ElementId[actual]; + // Mask is easy to calc for powers of two. + mIndexMask = actual - 1; + mSize = 0; + mSizeThreshold = (actual * FILL_PCT) / 100; + mHead = mTail = null; + } + + /* + //////////////////////////////////////////////////// + // Public API + //////////////////////////////////////////////////// + */ + + public ElementId getFirstUndefined() + { + /* Since the linked list is pruned to always start with + * the first (in doc order) undefined id, we can just + * return head: + */ + return mHead; + } + + /** + * Method called when a reference to id is encountered. If so, need + * to check if specified id entry (ref or definiton) exists; and if not, + * to add a reference marker. + */ + public ElementId addReferenced(char[] buffer, int start, int len, int hash, + Location loc, PrefixedName elemName, PrefixedName attrName) + { + int index = (hash & mIndexMask); + ElementId id = mTable[index]; + + while (id != null) { + if (id.idMatches(buffer, start, len)) { // found existing one + return id; + } + id = id.nextColliding(); + } + + // Not found, need to create a placeholder... + + // But first, do we need more room? + if (mSize >= mSizeThreshold) { + rehash(); + // Index changes, for the new entr: + index = (hash & mIndexMask); + } + ++mSize; + + // Ok, then, let's create the entry + String idStr = new String(buffer, start, len); + id = new ElementId(idStr, loc, false, elemName, attrName); + + // First, let's link it to Map; all ids have to be connected + id.setNextColliding(mTable[index]); + mTable[index] = id; + + // And then add the undefined entry at the end of list + if (mHead == null) { + mHead = mTail = id; + } else { + mTail.linkUndefined(id); + mTail = id; + } + return id; + } + + public ElementId addReferenced(String idStr, + Location loc, PrefixedName elemName, PrefixedName attrName) + { + int hash = calcHash(idStr); + int index = (hash & mIndexMask); + ElementId id = mTable[index]; + + while (id != null) { + if (id.idMatches(idStr)) { // found existing one + return id; + } + id = id.nextColliding(); + } + + // Not found, need to create a placeholder... + + // But first, do we need more room? + if (mSize >= mSizeThreshold) { + rehash(); + // Index changes, for the new entr: + index = (hash & mIndexMask); + } + ++mSize; + + // Ok, then, let's create the entry + id = new ElementId(idStr, loc, false, elemName, attrName); + + // First, let's link it to Map; all ids have to be connected + id.setNextColliding(mTable[index]); + mTable[index] = id; + + // And then add the undefined entry at the end of list + if (mHead == null) { + mHead = mTail = id; + } else { + mTail.linkUndefined(id); + mTail = id; + } + return id; + } + + /** + * Method called when an id definition is encountered. If so, need + * to check if specified id entry (ref or definiton) exists. If not, + * need to add the definition marker. If it does exist, need to + * 'upgrade it', if it was a reference marker; otherwise need to + * just return the old entry, and expect caller to check for dups + * and report the error. + */ + public ElementId addDefined(char[] buffer, int start, int len, int hash, + Location loc, PrefixedName elemName, PrefixedName attrName) + { + int index = (hash & mIndexMask); + ElementId id = mTable[index]; + + while (id != null) { + if (id.idMatches(buffer, start, len)) { + break; + } + id = id.nextColliding(); + } + + /* Not found, can just add it to the Map; no need to add to the + * linked list as it's not undefined + */ + if (id == null) { + // First, do we need more room? + if (mSize >= mSizeThreshold) { + rehash(); + index = (hash & mIndexMask); + } + ++mSize; + String idStr = new String(buffer, start, len); + id = new ElementId(idStr, loc, true, elemName, attrName); + id.setNextColliding(mTable[index]); + mTable[index] = id; + } else { + /* If already defined, nothing additional to do (we could + * signal an error here, though... for now, we'll let caller + * do that + */ + if (id.isDefined()) { + ; + } else { + /* Not defined, just need to upgrade, and possibly remove from + * the linked list. + */ + id.markDefined(loc); + + /* Ok; if it was the first undefined, need to unlink it, as + * well as potentially next items. + */ + if (id == mHead) { + do { + mHead = mHead.nextUndefined(); + } while (mHead != null && mHead.isDefined()); + + // Did we clear up all undefined ids? + if (mHead == null) { + mTail = null; + } + } + } + } + + return id; + } + + public ElementId addDefined(String idStr, + Location loc, PrefixedName elemName, PrefixedName attrName) + { + int hash = calcHash(idStr); + int index = (hash & mIndexMask); + ElementId id = mTable[index]; + + while (id != null) { + if (id.idMatches(idStr)) { + break; + } + id = id.nextColliding(); + } + + /* Not found, can just add it to the Map; no need to add to the + * linked list as it's not undefined + */ + if (id == null) { + if (mSize >= mSizeThreshold) { // need more room + rehash(); + index = (hash & mIndexMask); + } + ++mSize; + id = new ElementId(idStr, loc, true, elemName, attrName); + id.setNextColliding(mTable[index]); + mTable[index] = id; + } else { + /* If already defined, nothing additional to do (we could + * signal an error here, though... for now, we'll let caller + * do that + */ + if (id.isDefined()) { + ; + } else { + /* Not defined, just need to upgrade, and possibly remove from + * the linked list. + */ + id.markDefined(loc); + + /* Ok; if it was the first undefined, need to unlink it, as + * well as potentially next items. + */ + if (id == mHead) { + do { + mHead = mHead.nextUndefined(); + } while (mHead != null && mHead.isDefined()); + if (mHead == null) { // cleared up all undefined ids? + mTail = null; + } + } + } + } + + return id; + } + + /** + * Implementation of a hashing method for variable length + * Strings. Most of the time intention is that this calculation + * is done by caller during parsing, not here; however, sometimes + * it needs to be done for parsed "String" too. + *

+ * Note: identical to {@link com.ctc.wstx.util.SymbolTable#calcHash}, + * although not required to be. + * + * @param len Length of String; has to be at least 1 (caller guarantees + * this pre-condition) + */ + @SuppressWarnings("cast") + public static int calcHash(char[] buffer, int start, int len) + { + int hash = (int) buffer[start]; + for (int i = 1; i < len; ++i) { + hash = (hash * 31) + (int) buffer[start+i]; + } + return hash; + } + + @SuppressWarnings("cast") + public static int calcHash(String key) + { + int hash = (int) key.charAt(0); + for (int i = 1, len = key.length(); i < len; ++i) { + hash = (hash * 31) + (int) key.charAt(i); + + } + return hash; + } + + /* + ////////////////////////////////////////////////////////// + // Internal methods + ////////////////////////////////////////////////////////// + */ + + /** + * Method called when size (number of entries) of symbol table grows + * so big that load factor is exceeded. Since size has to remain + * power of two, arrays will then always be doubled. Main work + * is really redistributing old entries into new String/Bucket + * entries. + */ + private void rehash() + { + int size = mTable.length; + /* Let's grow aggressively; this should minimize number of + * resizes, while adding to mem usage. But since these Maps + * are never long-lived (only during parsing and validation of + * a single doc), that shouldn't greatly matter. + */ + int newSize = (size << 2); + ElementId[] oldSyms = mTable; + mTable = new ElementId[newSize]; + + // Let's update index mask, threshold, now (needed for rehashing) + mIndexMask = newSize - 1; + mSizeThreshold <<= 2; + + int count = 0; // let's do sanity check + + for (int i = 0; i < size; ++i) { + for (ElementId id = oldSyms[i]; id != null; ) { + ++count; + int index = calcHash(id.getId()) & mIndexMask; + ElementId nextIn = id.nextColliding(); + id.setNextColliding(mTable[index]); + mTable[index] = id; + id = nextIn; + } + } + + if (count != mSize) { + ExceptionUtil.throwInternal("on rehash(): had "+mSize+" entries; now have "+count+"."); + } + } +} diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/util/EmptyNamespaceContext.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/util/EmptyNamespaceContext.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/util/EmptyNamespaceContext.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/util/EmptyNamespaceContext.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,74 @@ +package com.ctc.wstx.util; + +import java.io.Writer; +import java.util.Iterator; + +import javax.xml.namespace.NamespaceContext; +import javax.xml.stream.XMLStreamWriter; +import javax.xml.stream.events.Namespace; + +/** + * Dummy {@link NamespaceContext} (and {@link BaseNsContext}) + * implementation that is usually used in + * non-namespace-aware mode. + *

+ * Note: differs from Stax2 reference implementation's version + * slightly, since it needs to support Woodstox specific extensions + * for efficient namespace declaration serialization. + */ +public final class EmptyNamespaceContext + extends BaseNsContext +{ + final static EmptyNamespaceContext sInstance = new EmptyNamespaceContext(); + + private EmptyNamespaceContext() { } + + public static EmptyNamespaceContext getInstance() { return sInstance; } + + /* + ///////////////////////////////////////////// + // Extended API + ///////////////////////////////////////////// + */ + + @Override + public Iterator getNamespaces() { + return DataUtil.emptyIterator(); + } + + /** + * Method called by the matching start element class to + * output all namespace declarations active in current namespace + * scope, if any. + */ + @Override + public void outputNamespaceDeclarations(Writer w) { + ; // nothing to output + } + + @Override + public void outputNamespaceDeclarations(XMLStreamWriter w) { + ; // nothing to output + } + + /* + ///////////////////////////////////////////////// + // Template methods sub-classes need to implement + ///////////////////////////////////////////////// + */ + + @Override + public String doGetNamespaceURI(String prefix) { + return null; + } + + @Override + public String doGetPrefix(String nsURI) { + return null; + } + + @Override + public Iterator doGetPrefixes(String nsURI) { + return DataUtil.emptyIterator(); + } +} diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/util/ExceptionUtil.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/util/ExceptionUtil.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/util/ExceptionUtil.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/util/ExceptionUtil.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,82 @@ +package com.ctc.wstx.util; + +import java.io.IOException; + +public final class ExceptionUtil +{ + private ExceptionUtil() { } + + /** + * Method that can be used to convert any Throwable to a RuntimeException; + * conversion is only done for checked exceptions. + */ + public static void throwRuntimeException(Throwable t) + { + // Unchecked? Can re-throw as is + throwIfUnchecked(t); + // Otherwise, let's just change its type: + throw new RuntimeException("[was "+t.getClass()+"] "+t.getMessage(), t); + } + + public static IOException constructIOException(String msg, Throwable src) + { + /* Stupid IOException constructors... only 1.6 has + * what we need. Hence must set root cause explicitly + * as we have to support JDK 1.5. + */ + IOException e = new IOException(msg); + setInitCause(e, src); + return e; + } + + public static void throwAsIllegalArgument(Throwable t) + { + // Unchecked? Can re-throw as is + throwIfUnchecked(t); + // Otherwise, let's just change its type: + IllegalArgumentException rex = new IllegalArgumentException("[was "+t.getClass()+"] "+t.getMessage()); + // And indicate the root cause + setInitCause(rex, t); + throw rex; + } + + public static void throwIfUnchecked(Throwable t) + { + // If it's not checked, let's throw it as is + if (t instanceof RuntimeException) { + throw (RuntimeException) t; + } + if (t instanceof Error) { + throw (Error) t; + } + } + + /** + * This method is just added for convenience, and only to be used for + * assertion style of exceptions. For errors that actually occur, method + * with the string arg should be called instead. + */ + public static void throwGenericInternal() + { + throwInternal(null); + } + + public static void throwInternal(String msg) + { + if (msg == null) { + msg = "[no description]"; + } + throw new RuntimeException("Internal error: "+msg); + } + + public static void setInitCause(Throwable newT, Throwable rootT) + { + /* [WSTX-110]: Better make sure we do not already have + * a chained exception... + */ + if (newT.getCause() == null) { + newT.initCause(rootT); + } + } +} + diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/util/InternCache.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/util/InternCache.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/util/InternCache.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/util/InternCache.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,70 @@ +package com.ctc.wstx.util; + +import java.util.LinkedHashMap; +import java.util.Map; + +/** + * Singleton class that implements "fast intern" functionality, essentially + * adding a layer that caches Strings that have been previously intern()ed, + * but that probably shouldn't be added to symbol tables. + * This is usually used by improving intern()ing of things like namespace + * URIs. + *

+ * Note: that this class extends {@link LinkedHashMap} is an implementation + * detail -- no code should ever directly call Map methods. + */ +@SuppressWarnings("serial") +public final class InternCache extends LinkedHashMap +{ + /** + * Let's create cache big enough to usually have enough space for + * all entries... (assuming NS URIs only) + */ + private final static int DEFAULT_SIZE = 64; + + /** + * Let's limit to hash area size of 1024. + */ + private final static int MAX_SIZE = 660; + + private final static InternCache sInstance = new InternCache(); + + private InternCache() { + /* Let's also try to seriously minimize collisions... since + * collisions are likely to be more costly here, with longer + * Strings; so let's use 2/3 ratio (67%) instead of default + * (75%) + */ + super(DEFAULT_SIZE, 0.6666f, false); + } + + public static InternCache getInstance() { + return sInstance; + } + + public String intern(String input) + { + String result; + + /* Let's split sync block to help in edge cases like + * [WSTX-220] + */ + synchronized (this) { + result = get(input); + } + if (result == null) { + result = input.intern(); + synchronized (this) { + put(result, result); + } + } + return result; + } + + // We will force maximum size here (for [WSTX-237]) + @Override protected boolean removeEldestEntry(Map.Entry eldest) + { + return size() > MAX_SIZE; + } +} + diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/util/package.html libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/util/package.html --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/util/package.html 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/util/package.html 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,7 @@ + +Contains utility classes that are not directly Woodstox specific, but are +for now only used by Woodstox. +

+Note that some of more generic classes may eventually be moved to more +generic packages under com.ctc package. + diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/util/PrefixedName.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/util/PrefixedName.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/util/PrefixedName.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/util/PrefixedName.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,187 @@ +/* Woodstox XML processor + * + * Copyright (c) 2004 Tatu Saloranta, tatu.saloranta@iki.fi + * + * Licensed under the License specified in file LICENSE, included with + * the source code. + * You may not use this file except in compliance with the License. + * + * 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 com.ctc.wstx.util; + +import javax.xml.namespace.QName; + +/** + * Simple key Object to be used for storing/accessing of potentially namespace + * scoped element and attribute names. + *

+ * One important note about usage is that two of the name components (prefix + * and local name) HAVE to have been interned some way, as all comparisons + * are done using identity comparison; whereas URI is NOT necessarily + * interned. + *

+ * Note that the main reason this class is mutable -- unlike most key classes + * -- is that this allows reusing key objects for access, as long as the code + * using it knows ramifications of trying to modify a key that's used + * in a data structure. + *

+ * Note, too, that the hash code is cached as this class is mostly used as + * a Map key, and hash code is used a lot. + */ +public final class PrefixedName + implements Comparable // to allow alphabetic ordering +{ + private String mPrefix, mLocalName; + + volatile int mHash = 0; + + /* + /////////////////////////////////////////////////// + // Life-cycle + /////////////////////////////////////////////////// + */ + + public PrefixedName(String prefix, String localName) + { + mLocalName = localName; + mPrefix = (prefix != null && prefix.length() == 0) ? + null : prefix; + } + + public PrefixedName reset(String prefix, String localName) + { + mLocalName = localName; + mPrefix = (prefix != null && prefix.length() == 0) ? + null : prefix; + mHash = 0; + return this; + } + + public static PrefixedName valueOf(QName n) + { + return new PrefixedName(n.getPrefix(), n.getLocalPart()); + } + + /* + /////////////////////////////////////////////////// + // Accessors: + /////////////////////////////////////////////////// + */ + + public String getPrefix() { return mPrefix; } + + public String getLocalName() { return mLocalName; } + + /** + * @return True, if this attribute name would result in a namespace + * binding (ie. it's "xmlns" or starts with "xmlns:"). + */ + public boolean isaNsDeclaration() + { + if (mPrefix == null) { + return mLocalName == "xmlns"; + } + return mPrefix == "xmlns"; + } + + /** + * Method used to check for xml reserved attribute names, like + * "xml:space" and "xml:id". + *

+ * Note: it is assumed that the passed-in localName is also + * interned. + */ + public boolean isXmlReservedAttr(boolean nsAware, String localName) + { + if (nsAware) { + if ("xml" == mPrefix) { + return mLocalName == localName; + } + } else { + if (mLocalName.length() == (4 + localName.length())) { + return (mLocalName.startsWith("xml:") + && mLocalName.endsWith(localName)); + } + } + return false; + } + + /* + /////////////////////////////////////////////////// + // Overridden standard methods: + /////////////////////////////////////////////////// + */ + + @Override + public String toString() + { + if (mPrefix == null || mPrefix.length() == 0) { + return mLocalName; + } + StringBuilder sb = new StringBuilder(mPrefix.length() + 1 + mLocalName.length()); + sb.append(mPrefix); + sb.append(':'); + sb.append(mLocalName); + return sb.toString(); + } + + @Override + public boolean equals(Object o) + { + if (o == this) { + return true; + } + if (!(o instanceof PrefixedName)) { // also filters out nulls + return false; + } + PrefixedName other = (PrefixedName) o; + + if (mLocalName != other.mLocalName) { // assumes equality + return false; + } + return (mPrefix == other.mPrefix); + } + + @Override + public int hashCode() { + int hash = mHash; + + if (hash == 0) { + hash = mLocalName.hashCode(); + if (mPrefix != null) { + hash ^= mPrefix.hashCode(); + } + mHash = hash; + } + return hash; + } + + @Override + public int compareTo(PrefixedName other) + { + // First, by prefix, then by local name: + String op = other.mPrefix; + + // Missing prefix is ordered before existing prefix + if (op == null || op.length() == 0) { + if (mPrefix != null && mPrefix.length() > 0) { + return 1; + } + } else if (mPrefix == null || mPrefix.length() == 0) { + return -1; + } else { + int result = mPrefix.compareTo(op); + if (result != 0) { + return result; + } + } + + return mLocalName.compareTo(other.mLocalName); + } +} diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/util/SimpleCache.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/util/SimpleCache.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/util/SimpleCache.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/util/SimpleCache.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,60 @@ +package com.ctc.wstx.util; + +import java.util.*; + +/** + * Simple Map implementation usable for caches where contents do not + * expire, but where size needs to remain bounded. + *

+ * Note: we probably should use weak references, or something similar + * to limit maximum memory usage. This could be implemented in many + * ways, perhaps by using two areas: first, smaller one, with strong + * refs, and secondary bigger one that uses soft references. + */ + +public final class SimpleCache +{ + final LimitMap mItems; + + final int mMaxSize; + + public SimpleCache(int maxSize) + { + mItems = new LimitMap(maxSize); + mMaxSize = maxSize; + } + + public V find(K key) { + return mItems.get(key); + } + + public void add(K key, V value) + { + mItems.put(key, value); + } + + /* + ///////////////////////////////////////////// + // Helper classes + ///////////////////////////////////////////// + */ + + @SuppressWarnings("serial") + final static class LimitMap + extends LinkedHashMap + { + final int mMaxSize; + + public LimitMap(int size) + { + super(size, 0.8f, true); + // Let's not allow silly low values... + mMaxSize = size; + } + + @Override + public boolean removeEldestEntry(Map.Entry eldest) { + return (size() >= mMaxSize); + } + } +} diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/util/StringUtil.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/util/StringUtil.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/util/StringUtil.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/util/StringUtil.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,340 @@ +package com.ctc.wstx.util; + +import java.util.Collection; +import java.util.Iterator; + +public final class StringUtil +{ + final static char CHAR_SPACE = ' '; // 0x0020 + private final static char INT_SPACE = 0x0020; + + static String sLF = null; + + public static String getLF() + { + String lf = sLF; + if (lf == null) { + try { + lf = System.getProperty("line.separator"); + sLF = (lf == null) ? "\n" : lf; + } catch (Throwable t) { + // Doh.... whatever; most likely SecurityException + sLF = lf = "\n"; + } + } + return lf; + } + + public static void appendLF(StringBuilder sb) { + sb.append(getLF()); + } + + public static String concatEntries(Collection coll, String sep, String lastSep) { + if (lastSep == null) { + lastSep = sep; + } + int len = coll.size(); + StringBuilder sb = new StringBuilder(16 + (len << 3)); + Iterator it = coll.iterator(); + int i = 0; + while (it.hasNext()) { + if (i == 0) { + ; + } else if (i == (len - 1)) { + sb.append(lastSep); + } else { + sb.append(sep); + } + ++i; + sb.append(it.next()); + } + return sb.toString(); + } + + /** + * Method that will check character array passed, and remove all + * "extra" spaces (leading and trailing space), and normalize + * other white space (more than one consequtive space character + * replaced with a single space). + *

+ * NOTE: we only remove explicit space characters (char code 0x0020); + * the reason being that other white space must have come from + * non-normalizable sources, ie. via entity expansion, and is thus + * not to be normalized + * + * @param buf Buffer that contains the String to check + * @param origStart Offset of the first character of the text to check + * in the buffer + * @param origEnd Offset of the character following the last character + * of the text (as per usual Java API convention) + * + * @return Normalized String, if any white space was removed or + * normalized; null if no changes were necessary. + */ + public static String normalizeSpaces(char[] buf, int origStart, int origEnd) + { + --origEnd; + + int start = origStart; + int end = origEnd; + + // First let's trim start... + while (start <= end && buf[start] == CHAR_SPACE) { + ++start; + } + // Was it all empty? + if (start > end) { + return ""; + } + + /* Nope, need to trim from the end then (note: it's known that char + * at index 'start' is not a space, at this point) + */ + while (end > start && buf[end] == CHAR_SPACE) { + --end; + } + + /* Ok, may have changes or not: now need to normalize + * intermediate duplicate spaces. We also now that the + * first and last characters can not be spaces. + */ + int i = start+1; + + while (i < end) { + if (buf[i] == CHAR_SPACE) { + if (buf[i+1] == CHAR_SPACE) { + break; + } + // Nah; no hole for these 2 chars! + i += 2; + } else { + ++i; + } + } + + // Hit the end? + if (i >= end) { + // Any changes? + if (start == origStart && end == origEnd) { + return null; // none + } + return new String(buf, start, (end-start)+1); + } + + /* Nope, got a hole, need to constuct the damn thing. Shouldn't + * happen too often... so let's just use StringBuilder() + */ + StringBuilder sb = new StringBuilder(end-start); // can't be longer + sb.append(buf, start, i-start); // won't add the starting space + + while (i <= end) { + char c = buf[i++]; + if (c == CHAR_SPACE) { + sb.append(CHAR_SPACE); + // Need to skip dups + while (true) { + c = buf[i++]; + if (c != CHAR_SPACE) { + sb.append(c); + break; + } + } + } else { + sb.append(c); + } + } + + return sb.toString(); + } + + public static boolean isAllWhitespace(String str) + { + for (int i = 0, len = str.length(); i < len; ++i) { + if (str.charAt(i) > CHAR_SPACE) { + return false; + } + } + return true; + } + + public static boolean isAllWhitespace(char[] ch, int start, int len) + { + len += start; + for (; start < len; ++start) { + if (ch[start] > CHAR_SPACE) { + return false; + } + } + return true; + } + + /** + * Internal constant used to denote END-OF-STRING + */ + private final static int EOS = 0x10000; + + /** + * Method that implements a loose String compairon for encoding + * Strings. It will work like {@link String#equalsIgnoreCase}, + * except that it will also ignore all hyphen, underscore and + * space characters. + */ + public static boolean equalEncodings(String str1, String str2) + { + final int len1 = str1.length(); + final int len2 = str2.length(); + + // Need to loop completely over both Strings + for (int i1 = 0, i2 = 0; i1 < len1 || i2 < len2; ) { + int c1 = (i1 >= len1) ? EOS : str1.charAt(i1++); + int c2 = (i2 >= len2) ? EOS : str2.charAt(i2++); + + // Can first do a quick comparison (usually they are equal) + if (c1 == c2) { + continue; + } + + // if not equal, maybe there are WS/hyphen/underscores to skip + while (c1 <= INT_SPACE || c1 == '_' || c1 == '-') { + c1 = (i1 >= len1) ? EOS : str1.charAt(i1++); + } + while (c2 <= INT_SPACE || c2 == '_' || c2 == '-') { + c2 = (i2 >= len2) ? EOS : str2.charAt(i2++); + } + // Ok, how about case differences, then? + if (c1 != c2) { + // If one is EOF, can't match (one is substring of the other) + if (c1 == EOS || c2 == EOS) { + return false; + } + if (c1 < 127) { // ascii is easy... + if (c1 <= 'Z' && c1 >= 'A') { + c1 = c1 + ('a' - 'A'); + } + } else { + c1 = Character.toLowerCase((char)c1); + } + if (c2 < 127) { // ascii is easy... + if (c2 <= 'Z' && c2 >= 'A') { + c2 = c2 + ('a' - 'A'); + } + } else { + c2 = Character.toLowerCase((char)c2); + } + if (c1 != c2) { + return false; + } + } + } + + // If we got this far, we are ok as long as we got through it all + return true; + } + + public static boolean encodingStartsWith(String enc, String prefix) + { + int len1 = enc.length(); + int len2 = prefix.length(); + + int i1 = 0, i2 = 0; + + // Need to loop completely over both Strings + while (i1 < len1 || i2 < len2) { + int c1 = (i1 >= len1) ? EOS : enc.charAt(i1++); + int c2 = (i2 >= len2) ? EOS : prefix.charAt(i2++); + + // Can first do a quick comparison (usually they are equal) + if (c1 == c2) { + continue; + } + + // if not equal, maybe there are WS/hyphen/underscores to skip + while (c1 <= CHAR_SPACE || c1 == '_' || c1 == '-') { + c1 = (i1 >= len1) ? EOS : enc.charAt(i1++); + } + while (c2 <= CHAR_SPACE || c2 == '_' || c2 == '-') { + c2 = (i2 >= len2) ? EOS : prefix.charAt(i2++); + } + // Ok, how about case differences, then? + if (c1 != c2) { + if (c2 == EOS) { // Prefix done, good! + return true; + } + if (c1 == EOS) { // Encoding done, not good + return false; + } + if (Character.toLowerCase((char)c1) != Character.toLowerCase((char)c2)) { + return false; + } + } + } + + // Ok, prefix was exactly the same as encoding... that's fine + return true; + } + + /** + * Method that will remove all non-alphanumeric characters, and optionally + * upper-case included letters, from the given String. + */ + public static String trimEncoding(String str, boolean upperCase) + { + int i = 0; + int len = str.length(); + + // Let's first check if String is fine as is: + for (; i < len; ++i) { + char c = str.charAt(i); + if (c <= CHAR_SPACE || !Character.isLetterOrDigit(c)) { + break; + } + } + + if (i == len) { + return str; + } + + // Nope: have to trim it + StringBuilder sb = new StringBuilder(); + if (i > 0) { + sb.append(str.substring(0, i)); + } + for (; i < len; ++i) { + char c = str.charAt(i); + if (c > CHAR_SPACE && Character.isLetterOrDigit(c)) { + if (upperCase) { + c = Character.toUpperCase(c); + } + sb.append(c); + } + } + + return sb.toString(); + } + + public static boolean matches(String str, char[] cbuf, int offset, int len) + { + if (str.length() != len) { + return false; + } + for (int i = 0; i < len; ++i) { + if (str.charAt(i) != cbuf[offset+i]) { + return false; + } + } + return true; + } + + /** + *

+ * Note that it is assumed that any "weird" white space + * (xml 1.1 LSEP and NEL) have been replaced by canonical + * alternatives (linefeed for element content, regular space + * for attributes) + */ + @SuppressWarnings("cast") + public final static boolean isSpace(char c) + { + return ((int) c) <= 0x0020; + } +} diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/util/StringVector.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/util/StringVector.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/util/StringVector.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/util/StringVector.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,245 @@ +package com.ctc.wstx.util; + +/** + * Data container similar {@link java.util.List} (from storage perspective), + * but that can be used in multiple ways. For some uses it acts more like + * type-safe String list/vector; for others as order associative list of + * String-to-String mappings. + */ +public final class StringVector +{ + private String[] mStrings; + + private int mSize; + + /* + /////////////////////////////////////////////////////// + // Life-cycle: + /////////////////////////////////////////////////////// + */ + + public StringVector(int initialCount) { + mStrings = new String[initialCount]; + } + + /* + /////////////////////////////////////////////////////// + // Basic accessors + /////////////////////////////////////////////////////// + */ + + public int size() { return mSize; } + + public boolean isEmpty() { return mSize == 0; } + + public String getString(int index) { + if (index < 0 || index >= mSize) { + throw new IllegalArgumentException("Index "+index+" out of valid range; current size: "+mSize+"."); + } + return mStrings[index]; + } + + public String getLastString() { + if (mSize < 1) { + throw new IllegalStateException("getLastString() called on empty StringVector."); + } + return mStrings[mSize-1]; + } + + public String[] getInternalArray() { + return mStrings; + } + + public String[] asArray() { + String[] strs = new String[mSize]; + System.arraycopy(mStrings, 0, strs, 0, mSize); + return strs; + } + + public boolean containsInterned(String value) { + String[] str = mStrings; + for (int i = 0, len = mSize; i < len; ++i) { + if (str[i] == value) { + return true; + } + } + return false; + } + + /* + /////////////////////////////////////////////////////// + // Mutators: + /////////////////////////////////////////////////////// + */ + + public void addString(String str) { + if (mSize == mStrings.length) { + String[] old = mStrings; + int oldSize = old.length; + mStrings = new String[oldSize + (oldSize << 1)]; + System.arraycopy(old, 0, mStrings, 0, oldSize); + } + mStrings[mSize++] = str; + } + + public void addStrings(String str1, String str2) { + if ((mSize + 2) > mStrings.length) { + String[] old = mStrings; + int oldSize = old.length; + mStrings = new String[oldSize + (oldSize << 1)]; + System.arraycopy(old, 0, mStrings, 0, oldSize); + } + mStrings[mSize] = str1; + mStrings[mSize+1] = str2; + mSize += 2; + } + + public void setString(int index, String str) { + mStrings[index] = str; + } + + public void clear(boolean removeRefs) { + if (removeRefs) { + for (int i = 0, len = mSize; i < len; ++i) { + mStrings[i] = null; + } + } + mSize = 0; + } + + public String removeLast() { + String result = mStrings[--mSize]; + mStrings[mSize] = null; + return result; + } + + public void removeLast(int count) { + while (--count >= 0) { + mStrings[--mSize] = null; + } + } + + /* + /////////////////////////////////////////////////////// + // Specialized "map accessors": + /////////////////////////////////////////////////////// + */ + + /** + * Specialized access method; treats vector as a Map, with 2 Strings + * per entry; first one being key, second value. Further, keys are + * assumed to be canonicalized with passed in key (ie. either intern()ed, + * or resolved from symbol table). + * Starting from the + * end (assuming even number of entries), tries to find an entry with + * matching key, and if so, returns value. + */ + public String findLastFromMap(String key) { + int index = mSize; + while ((index -= 2) >= 0) { + if (mStrings[index] == key) { + return mStrings[index+1]; + } + } + return null; + } + + public String findLastNonInterned(String key) + { + int index = mSize; + while ((index -= 2) >= 0) { + String curr = mStrings[index]; + if (curr == key || (curr != null && curr.equals(key))) { + return mStrings[index+1]; + } + } + return null; + } + + public int findLastIndexNonInterned(String key) { + int index = mSize; + while ((index -= 2) >= 0) { + String curr = mStrings[index]; + if (curr == key || (curr != null && curr.equals(key))) { + return index; + } + } + return -1; + } + + public String findLastByValueNonInterned(String value) { + for (int index = mSize-1; index > 0; index -= 2) { + String currVal = mStrings[index]; + if (currVal == value || (currVal != null && currVal.equals(value))) { + return mStrings[index-1]; + } + } + return null; + } + + public int findLastIndexByValueNonInterned(String value) { + for (int index = mSize-1; index > 0; index -= 2) { + String currVal = mStrings[index]; + if (currVal == value || (currVal != null && currVal.equals(value))) { + return index-1; + } + } + return -1; + } + + /* + // Not needed any more + public Iterator findAllByValueNonInterned(String value) { + String first = null; + ArrayList all = null; + for (int index = mSize-1; index > 0; index -= 2) { + String currVal = mStrings[index]; + if (currVal == value || (currVal != null && currVal.equals(value))) { + if (first == null) { + first = mStrings[index-1]; + } else { + if (all == null) { + all = new ArrayList(); + all.add(first); + } + all.add(mStrings[index-1]); + } + } + } + if (all != null) { + return all.iterator(); + } + if (first != null) { + return new SingletonIterator(first); + } + return DataUtil.emptyIterator(); + } + */ + + /* + /////////////////////////////////////////////////////// + // Other methods + /////////////////////////////////////////////////////// + */ + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(mSize * 16); + sb.append("[(size = "); + sb.append(mSize); + sb.append(" ) "); + for (int i = 0; i < mSize; ++i) { + if (i > 0) { + sb.append(", "); + } + sb.append('"'); + sb.append(mStrings[i]); + sb.append('"'); + + sb.append(" == "); + sb.append(Integer.toHexString(System.identityHashCode(mStrings[i]))); + } + sb.append(']'); + return sb.toString(); + } +} diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/util/SymbolTable.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/util/SymbolTable.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/util/SymbolTable.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/util/SymbolTable.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,750 @@ +/* Woodstox XML processor + * + * Copyright (c) 2004- Tatu Saloranta, tatu.saloranta@iki.fi + * + * Licensed under the License specified in the file LICENSE which is + * included with the source code. + * You may not use this file except in compliance with the License. + * + * 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 com.ctc.wstx.util; + +/** + * This class is a kind of specialized type-safe Map, from char array to + * String value. Specialization means that in addition to type-safety + * and specific access patterns (key char array, Value optionally interned + * String; values added on access if necessary), and that instances are + * meant to be used concurrently, but by using well-defined mechanisms + * to obtain such concurrently usable instances. Main use for the class + * is to store symbol table information for things like compilers and + * parsers; especially when number of symbols (keywords) is limited. + *

+ * For optimal performance, usage pattern should be one where matches + * should be very common (esp. after "warm-up"), and as with most hash-based + * maps/sets, that hash codes are uniformly distributed. Also, collisions + * are slightly more expensive than with HashMap or HashSet, since hash codes + * are not used in resolving collisions; that is, equals() comparison is + * done with all symbols in same bucket index.
+ * Finally, rehashing is also more expensive, as hash codes are not + * stored; rehashing requires all entries' hash codes to be recalculated. + * Reason for not storing hash codes is reduced memory usage, hoping + * for better memory locality. + *

+ * Usual usage pattern is to create a single "master" instance, and either + * use that instance in sequential fashion, or to create derived "child" + * instances, which after use, are asked to return possible symbol additions + * to master instance. In either case benefit is that symbol table gets + * initialized so that further uses are more efficient, as eventually all + * symbols needed will already be in symbol table. At that point no more + * Symbol String allocations are needed, nor changes to symbol table itself. + *

+ * Note that while individual SymbolTable instances are NOT thread-safe + * (much like generic collection classes), concurrently used "child" + * instances can be freely used without synchronization. However, using + * master table concurrently with child instances can only be done if + * access to master instance is read-only (ie. no modifications done). + */ + +public class SymbolTable { + + /** + * Default initial table size; no need to make it miniscule, due + * to couple of things: first, overhead of array reallocation + * is significant, + * and second, overhead of rehashing is also non-negligible. + *

+ * Let's use 128 as the default; it allows for up to 96 symbols, + * and uses about 512 bytes on 32-bit machines. + */ + protected static final int DEFAULT_TABLE_SIZE = 128; + + protected static final float DEFAULT_FILL_FACTOR = 0.75f; + + protected static final String EMPTY_STRING = ""; + + /* + //////////////////////////////////////// + // Configuration: + //////////////////////////////////////// + */ + + /** + * Flag that determines whether Strings to be added need to be + * interned before being added or not. Forcing intern()ing will add + * some overhead when adding new Strings, but may be beneficial if such + * Strings are generally used by other parts of system. Note that even + * without interning, all returned String instances are guaranteed + * to be comparable with equality (==) operator; it's just that such + * guarantees are not made for Strings other classes return. + */ + protected boolean mInternStrings; + + /* + //////////////////////////////////////// + // Actual symbol table data: + //////////////////////////////////////// + */ + + /** + * Primary matching symbols; it's expected most match occur from + * here. + */ + protected String[] mSymbols; + + /** + * Overflow buckets; if primary doesn't match, lookup is done + * from here. + *

+ * Note: Number of buckets is half of number of symbol entries, on + * assumption there's less need for buckets. + */ + protected Bucket[] mBuckets; + + /** + * Current size (number of entries); needed to know if and when + * rehash. + */ + protected int mSize; + + /** + * Limit that indicates maximum size this instance can hold before + * it needs to be expanded and rehashed. Calculated using fill + * factor passed in to constructor. + */ + protected int mSizeThreshold; + + /** + * Mask used to get index from hash values; equal to + * mBuckets.length - 1, when mBuckets.length is + * a power of two. + */ + protected int mIndexMask; + + /* + //////////////////////////////////////// + // Information about concurrency + //////////////////////////////////////// + */ + + /** + * Version of this table instance; used when deriving new concurrently + * used versions from existing 'master' instance. + */ + protected int mThisVersion; + + /** + * Flag that indicates if any changes have been made to the data; + * used to both determine if bucket array needs to be copied when + * (first) change is made, and potentially if updated bucket list + * is to be resync'ed back to master instance. + */ + protected boolean mDirty; + + /* + //////////////////////////////////////// + // Life-cycle: + //////////////////////////////////////// + */ + + /** + * Method for constructing a master symbol table instance; this one + * will create master instance with default size, and with interning + * enabled. + */ + public SymbolTable() { + this(true); + } + + /** + * Method for constructing a master symbol table instance. + */ + public SymbolTable(boolean internStrings) { + this(internStrings, DEFAULT_TABLE_SIZE); + } + + /** + * Method for constructing a master symbol table instance. + */ + public SymbolTable(boolean internStrings, int initialSize) { + this(internStrings, initialSize, DEFAULT_FILL_FACTOR); + } + + /** + * Main method for constructing a master symbol table instance; will + * be called by other public constructors. + * + * @param internStrings Whether Strings to add are intern()ed or not + * @param initialSize Minimum initial size for bucket array; internally + * will always use a power of two equal to or bigger than this value. + * @param fillFactor Maximum fill factor allowed for bucket table; + * when more entries are added, table will be expanded. + */ + public SymbolTable(boolean internStrings, int initialSize, + float fillFactor) + { + mInternStrings = internStrings; + // Let's start versions from 1 + mThisVersion = 1; + // And we'll also set flags so no copying of buckets is needed: + mDirty = true; + + // No point in requesting funny initial sizes... + if (initialSize < 1) { + throw new IllegalArgumentException("Can not use negative/zero initial size: "+initialSize); + } + /* Initial size has to be a power of two. Also, let's not honour + * sizes that are ridiculously small... + */ + { + int currSize = 4; + while (currSize < initialSize) { + currSize += currSize; + } + initialSize = currSize; + } + + mSymbols = new String[initialSize]; + mBuckets = new Bucket[initialSize >> 1]; + // Mask is easy to calc for powers of two. + mIndexMask = initialSize - 1; + mSize = 0; + + // Sanity check for fill factor: + if (fillFactor < 0.01f) { + throw new IllegalArgumentException("Fill factor can not be lower than 0.01."); + } + if (fillFactor > 10.0f) { // just to catch stupid values, ie. useless from performance perspective + throw new IllegalArgumentException("Fill factor can not be higher than 10.0."); + } + mSizeThreshold = (int) (initialSize * fillFactor + 0.5); + } + + /** + * Internal constructor used when creating child instances. + */ + private SymbolTable(boolean internStrings, String[] symbols, + Bucket[] buckets, int size, int sizeThreshold, + int indexMask, int version) + { + mInternStrings = internStrings; + mSymbols = symbols; + mBuckets = buckets; + mSize = size; + mSizeThreshold = sizeThreshold; + mIndexMask = indexMask; + mThisVersion = version; + + // Need to make copies of arrays, if/when adding new entries + mDirty = false; + } + + /** + * "Factory" method; will create a new child instance of this symbol + * table. It will be a copy-on-write instance, ie. it will only use + * read-only copy of parent's data, but when changes are needed, a + * copy will be created. + *

+ * Note: while data access part of this method is synchronized, it is + * generally not safe to both use makeChild/mergeChild, AND to use instance + * actively. Instead, a separate 'root' instance should be used + * on which only makeChild/mergeChild are called, but instance itself + * is not used as a symbol table. + */ + public SymbolTable makeChild() + { + final boolean internStrings; + final String[] symbols; + final Bucket[] buckets; + final int size; + final int sizeThreshold; + final int indexMask; + final int version; + + synchronized (this) { + internStrings = mInternStrings; + symbols = mSymbols; + buckets = mBuckets; + size = mSize; + sizeThreshold = mSizeThreshold; + indexMask = mIndexMask; + version = mThisVersion+1; + } + return new SymbolTable(internStrings, symbols, buckets, + size, sizeThreshold, indexMask, version); + } + + /** + * Method that allows contents of child table to potentially be + * "merged in" with contents of this symbol table. + *

+ * Note that caller has to make sure symbol table passed in is + * really a child or sibling of this symbol table. + */ + public synchronized void mergeChild(SymbolTable child) + { + // Let's do a basic sanity check first: + if (child.size() <= size()) { // nothing to add + return; + } + + // Okie dokie, let's get the data in! + mSymbols = child.mSymbols; + mBuckets = child.mBuckets; + mSize = child.mSize; + mSizeThreshold = child.mSizeThreshold; + mIndexMask = child.mIndexMask; + mThisVersion++; // to prevent other children from overriding + + // Dirty flag... well, let's just clear it, to force copying just + // in case. Shouldn't really matter, for master tables. + mDirty = false; + + /* However, we have to mark child as dirty, so that it will not + * be modifying arrays we "took over" (since child may have + * returned an updated table before it stopped fully using + * the SymbolTable: for example, it may still use it for + * parsing PI targets in epilog) + */ + child.mDirty = false; + } + + /* + //////////////////////////////////////////////////// + // Public API, configuration + //////////////////////////////////////////////////// + */ + + public void setInternStrings(boolean state) { + mInternStrings = state; + } + + /* + //////////////////////////////////////////////////// + // Public API, generic accessors: + //////////////////////////////////////////////////// + */ + + public int size() { return mSize; } + + public int version() { return mThisVersion; } + + public boolean isDirty() { return mDirty; } + + public boolean isDirectChildOf(SymbolTable t) + { + /* Actually, this doesn't really prove it is a child (would have to + * use sequence number, or identityHash to really prove it), but + * it's good enough if relationship is known to exist. + */ + /* (for real check, one would need to child/descendant stuff; or + * at least an identity hash... or maybe even just a _static_ global + * counter for instances... maybe that would actually be worth + * doing?) + */ + if (mThisVersion == (t.mThisVersion + 1)) { + return true; + } + return false; + } + + /* + //////////////////////////////////////////////////// + // Public API, accessing symbols: + //////////////////////////////////////////////////// + */ + + /** + * Main access method; will check if actual symbol String exists; + * if so, returns it; if not, will create, add and return it. + * + * @return The symbol matching String in input array + */ + /* + public String findSymbol(char[] buffer, int start, int len) + { + return findSymbol(buffer, start, len, calcHash(buffer, start, len)); + } + */ + + public String findSymbol(char[] buffer, int start, int len, int hash) + { + // Sanity check: + if (len < 1) { + return EMPTY_STRING; + } + + hash &= mIndexMask; + + String sym = mSymbols[hash]; + + // Optimal case; checking existing primary symbol for hash index: + if (sym != null) { + // Let's inline primary String equality checking: + if (sym.length() == len) { + int i = 0; + do { + if (sym.charAt(i) != buffer[start+i]) { + break; + } + } while (++i < len); + // Optimal case; primary match found + if (i == len) { + return sym; + } + } + // How about collision bucket? + Bucket b = mBuckets[hash >> 1]; + if (b != null) { + sym = b.find(buffer, start, len); + if (sym != null) { + return sym; + } + } + } + + // Need to expand? + if (mSize >= mSizeThreshold) { + rehash(); + /* Need to recalc hash; rare occurence (index mask has been + * recalculated as part of rehash) + */ + hash = calcHash(buffer, start, len) & mIndexMask; + } else if (!mDirty) { + // Or perhaps we need to do copy-on-write? + copyArrays(); + mDirty = true; + } + ++mSize; + + String newSymbol = new String(buffer, start, len); + if (mInternStrings) { + newSymbol = newSymbol.intern(); + } + // Ok; do we need to add primary entry, or a bucket? + if (mSymbols[hash] == null) { + mSymbols[hash] = newSymbol; + } else { + int bix = hash >> 1; + mBuckets[bix] = new Bucket(newSymbol, mBuckets[bix]); + } + + return newSymbol; + } + + /** + * Similar to {link #findSymbol}, but will not add passed in symbol + * if it is not in symbol table yet. + */ + public String findSymbolIfExists(char[] buffer, int start, int len, int hash) + { + // Sanity check: + if (len < 1) { + return EMPTY_STRING; + } + hash &= mIndexMask; + + String sym = mSymbols[hash]; + // Optimal case; checking existing primary symbol for hash index: + if (sym != null) { + // Let's inline primary String equality checking: + if (sym.length() == len) { + int i = 0; + do { + if (sym.charAt(i) != buffer[start+i]) { + break; + } + } while (++i < len); + // Optimal case; primary match found + if (i == len) { + return sym; + } + } + // How about collision bucket? + Bucket b = mBuckets[hash >> 1]; + if (b != null) { + sym = b.find(buffer, start, len); + if (sym != null) { + return sym; + } + } + } + return null; + } + + /** + * Similar to to {@link #findSymbol(char[],int,int,int)}; used to either + * do potentially cheap intern() (if table already has intern()ed version), + * or to pre-populate symbol table with known values. + */ + public String findSymbol(String str) + { + int len = str.length(); + // Sanity check: + if (len < 1) { + return EMPTY_STRING; + } + + int index = calcHash(str) & mIndexMask; + String sym = mSymbols[index]; + + // Optimal case; checking existing primary symbol for hash index: + if (sym != null) { + // Let's inline primary String equality checking: + if (sym.length() == len) { + int i = 0; + for (; i < len; ++i) { + if (sym.charAt(i) != str.charAt(i)) { + break; + } + } + // Optimal case; primary match found + if (i == len) { + return sym; + } + } + // How about collision bucket? + Bucket b = mBuckets[index >> 1]; + if (b != null) { + sym = b.find(str); + if (sym != null) { + return sym; + } + } + } + + // Need to expand? + if (mSize >= mSizeThreshold) { + rehash(); + /* Need to recalc hash; rare occurence (index mask has been + * recalculated as part of rehash) + */ + index = calcHash(str) & mIndexMask; + } else if (!mDirty) { + // Or perhaps we need to do copy-on-write? + copyArrays(); + mDirty = true; + } + ++mSize; + + if (mInternStrings) { + str = str.intern(); + } + // Ok; do we need to add primary entry, or a bucket? + if (mSymbols[index] == null) { + mSymbols[index] = str; + } else { + int bix = index >> 1; + mBuckets[bix] = new Bucket(str, mBuckets[bix]); + } + + return str; + } + + /** + * Implementation of a hashing method for variable length + * Strings. Most of the time intention is that this calculation + * is done by caller during parsing, not here; however, sometimes + * it needs to be done for parsed "String" too. + * + * @param len Length of String; has to be at least 1 (caller guarantees + * this pre-condition) + */ + @SuppressWarnings("cast") + public static int calcHash(char[] buffer, int start, int len) { + int hash = (int) buffer[start]; + for (int i = 1; i < len; ++i) { + hash = (hash * 31) + (int) buffer[start+i]; + } + return hash; + } + + @SuppressWarnings("cast") + public static int calcHash(String key) { + int hash = (int) key.charAt(0); + for (int i = 1, len = key.length(); i < len; ++i) { + hash = (hash * 31) + (int) key.charAt(i); + + } + return hash; + } + + /* + ////////////////////////////////////////////////////////// + // Internal methods + ////////////////////////////////////////////////////////// + */ + + /** + * Method called when copy-on-write is needed; generally when first + * change is made to a derived symbol table. + */ + private void copyArrays() { + String[] oldSyms = mSymbols; + int size = oldSyms.length; + mSymbols = new String[size]; + System.arraycopy(oldSyms, 0, mSymbols, 0, size); + Bucket[] oldBuckets = mBuckets; + size = oldBuckets.length; + mBuckets = new Bucket[size]; + System.arraycopy(oldBuckets, 0, mBuckets, 0, size); + } + + /** + * Method called when size (number of entries) of symbol table grows + * so big that load factor is exceeded. Since size has to remain + * power of two, arrays will then always be doubled. Main work + * is really redistributing old entries into new String/Bucket + * entries. + */ + private void rehash() + { + int size = mSymbols.length; + int newSize = size + size; + String[] oldSyms = mSymbols; + Bucket[] oldBuckets = mBuckets; + mSymbols = new String[newSize]; + mBuckets = new Bucket[newSize >> 1]; + // Let's update index mask, threshold, now (needed for rehashing) + mIndexMask = newSize - 1; + mSizeThreshold += mSizeThreshold; + + int count = 0; // let's do sanity check + + /* Need to do two loops, unfortunately, since spillover area is + * only half the size: + */ + for (int i = 0; i < size; ++i) { + String symbol = oldSyms[i]; + if (symbol != null) { + ++count; + int index = calcHash(symbol) & mIndexMask; + if (mSymbols[index] == null) { + mSymbols[index] = symbol; + } else { + int bix = index >> 1; + mBuckets[bix] = new Bucket(symbol, mBuckets[bix]); + } + } + } + + size >>= 1; + for (int i = 0; i < size; ++i) { + Bucket b = oldBuckets[i]; + while (b != null) { + ++count; + String symbol = b.getSymbol(); + int index = calcHash(symbol) & mIndexMask; + if (mSymbols[index] == null) { + mSymbols[index] = symbol; + } else { + int bix = index >> 1; + mBuckets[bix] = new Bucket(symbol, mBuckets[bix]); + } + b = b.getNext(); + } + } + + if (count != mSize) { + throw new IllegalStateException("Internal error on SymbolTable.rehash(): had "+mSize+" entries; now have "+count+"."); + } + } + + /* + ////////////////////////////////////////////////////////// + // Test/debug support: + ////////////////////////////////////////////////////////// + */ + + public double calcAvgSeek() { + int count = 0; + + for (int i = 0, len = mSymbols.length; i < len; ++i) { + if (mSymbols[i] != null) { + ++count; + } + } + + for (int i = 0, len = mBuckets.length; i < len; ++i) { + Bucket b = mBuckets[i]; + int cost = 2; + while (b != null) { + count += cost; + ++cost; + b = b.getNext(); + } + } + + return ((double) count) / ((double) mSize); + } + + /* + ////////////////////////////////////////////////////////// + // Bucket class + ////////////////////////////////////////////////////////// + */ + + /** + * This class is a symbol table entry. Each entry acts as a node + * in a linked list. + */ + static final class Bucket { + private final String mSymbol; + private final Bucket mNext; + + public Bucket(String symbol, Bucket next) { + mSymbol = symbol; + mNext = next; + } + + public String getSymbol() { return mSymbol; } + public Bucket getNext() { return mNext; } + + public String find(char[] buf, int start, int len) { + String sym = mSymbol; + Bucket b = mNext; + + while (true) { // Inlined equality comparison: + if (sym.length() == len) { + int i = 0; + do { + if (sym.charAt(i) != buf[start+i]) { + break; + } + } while (++i < len); + if (i == len) { + return sym; + } + } + if (b == null) { + break; + } + sym = b.getSymbol(); + b = b.getNext(); + } + return null; + } + + public String find(String str) { + String sym = mSymbol; + Bucket b = mNext; + + while (true) { + if (sym.equals(str)) { + return sym; + } + if (b == null) { + break; + } + sym = b.getSymbol(); + b = b.getNext(); + } + return null; + } + } +} diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/util/TextAccumulator.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/util/TextAccumulator.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/util/TextAccumulator.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/util/TextAccumulator.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,71 @@ +package com.ctc.wstx.util; + +/** + * Simple utility class used to efficiently accumulate and concatenate + * text passed in various forms + */ +public final class TextAccumulator +{ + private String mText = null; + + private StringBuilder mBuilder = null; + + public TextAccumulator() { } + + public boolean hasText() { + return (mBuilder != null) || (mText != null); + } + + public void addText(String text) + { + int len = text.length(); + if (len > 0) { + // Any prior text? + if (mText != null) { + mBuilder = new StringBuilder(mText.length() + len); + mBuilder.append(mText); + mText = null; + } + if (mBuilder != null) { + mBuilder.append(text); + } else { + mText = text; + } + } + } + + public void addText(char[] buf, int start, int end) + { + int len = end-start; + if (len > 0) { + // Any prior text? + if (mText != null) { + mBuilder = new StringBuilder(mText.length() + len); + mBuilder.append(mText); + mText = null; + } else if (mBuilder == null) { + /* more efficient to use a builder than a string; and although + * could use a char array, StringBuilder has the benefit of + * being able to share the array, eventually. + */ + mBuilder = new StringBuilder(len); + } + mBuilder.append(buf, start, end-start); + } + } + + public String getAndClear() + { + if (mText != null) { + String result = mText; + mText = null; + return result; + } + if (mBuilder != null) { + String result = mBuilder.toString(); + mBuilder = null; + return result; + } + return ""; + } +} diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/util/TextBuffer.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/util/TextBuffer.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/util/TextBuffer.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/util/TextBuffer.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,1410 @@ +package com.ctc.wstx.util; + +import java.io.*; +import java.util.ArrayList; + +import javax.xml.stream.Location; +import javax.xml.stream.XMLStreamException; + +import org.xml.sax.ContentHandler; +import org.xml.sax.SAXException; +import org.xml.sax.ext.LexicalHandler; +import org.codehaus.stax2.typed.Base64Variant; +import org.codehaus.stax2.typed.TypedArrayDecoder; +import org.codehaus.stax2.typed.TypedValueDecoder; +import org.codehaus.stax2.typed.TypedXMLStreamException; +import org.codehaus.stax2.validation.XMLValidator; +import org.codehaus.stax2.ri.typed.CharArrayBase64Decoder; + +import com.ctc.wstx.api.ReaderConfig; +import com.ctc.wstx.dtd.DTDEventListener; +import com.ctc.wstx.sr.InputProblemReporter; +import com.ctc.wstx.util.StringUtil; + +/** + * TextBuffer is a class similar to {@link StringBuilder}, with + * following differences: + *

    + *
  • TextBuffer uses segments character arrays, to avoid having + * to do additional array copies when array is not big enough. This + * means that only reallocating that is necessary is done only once -- + * if and when caller + * wants to access contents in a linear array (char[], String). + *
  • + *
  • TextBuffer is not synchronized. + *
  • + *
+ *

+ * Over time more and more cruft has accumulated here, mostly to + * support efficient access to collected text. Since access is + * easiest to do efficiently using callbacks, this class now needs + * to known interfaces of SAX classes and validators. + *

+ * Notes about usage: for debugging purposes, it's suggested to use + * {@link #toString} method, as opposed to + * {@link #contentsAsArray} or {@link #contentsAsString}. Internally + * resulting code paths may or may not be different, WRT caching. + * + * @author Tatu Saloranta + */ +public final class TextBuffer +{ + /* 23-Mar-2006, TSa: Memory buffer clearing is a significant overhead + * for small documents, no need to use huge buffer -- it will expand + * as necessary for larger docs, but commonly text segments just + * aren't that long. + */ + /** + * Size of the first text segment buffer to allocate; need not contain + * the biggest segment, since new ones will get allocated as needed. + * However, it's sensible to use something that often is big enough + * to contain segments. + */ + final static int DEF_INITIAL_BUFFER_SIZE = 500; // 1k + + /** + * We will also restrict maximum length of individual segments + * to allocate (not including cases where we must return a single + * segment). Value is somewhat arbitrary, let's use it so that + * memory used is no more than 1/2 megabytes. + */ + final static int MAX_SEGMENT_LENGTH = 256 * 1024; + + final static int INT_SPACE = 0x0020; + + // // // Configuration: + + private final ReaderConfig mConfig; + + // // // Shared read-only input buffer: + + /** + * Shared input buffer; stored here in case some input can be returned + * as is, without being copied to collector's own buffers. Note that + * this is read-only for this Objet. + */ + private char[] mInputBuffer; + + /** + * Character offset of first char in input buffer; -1 to indicate + * that input buffer currently does not contain any useful char data + */ + private int mInputStart; + + /** + * When using shared buffer, offset after the last character in + * shared buffer + */ + private int mInputLen; + + // // // Internal non-shared collector buffers: + + private boolean mHasSegments = false; + + /** + * List of segments prior to currently active segment. + */ + private ArrayList mSegments; + + + // // // Currently used segment; not (yet) contained in mSegments + + /** + * Amount of characters in segments in {@link mSegments} + */ + private int mSegmentSize; + + private char[] mCurrentSegment; + + /** + * Number of characters in currently active (last) segment + */ + private int mCurrentSize; + + // // // Temporary caching for Objects to return + + /** + * String that will be constructed when the whole contents are + * needed; will be temporarily stored in case asked for again. + */ + private String mResultString; + + private char[] mResultArray; + + // // // Canonical indentation objects (up to 32 spaces, 8 tabs) + + public final static int MAX_INDENT_SPACES = 32; + public final static int MAX_INDENT_TABS = 8; + + // Let's add one more space at the end, for safety... + private final static String sIndSpaces = + // 123456789012345678901234567890123 + "\n "; + private final static char[] sIndSpacesArray = sIndSpaces.toCharArray(); + private final static String[] sIndSpacesStrings = new String[sIndSpacesArray.length]; + + private final static String sIndTabs = + // 1 2 3 4 5 6 7 8 9 + "\n\t\t\t\t\t\t\t\t\t"; + private final static char[] sIndTabsArray = sIndTabs.toCharArray(); + private final static String[] sIndTabsStrings = new String[sIndTabsArray.length]; + + /* + ////////////////////////////////////////////// + // Life-cycle + ////////////////////////////////////////////// + */ + + private TextBuffer(ReaderConfig cfg) + { + mConfig = cfg; + } + + public static TextBuffer createRecyclableBuffer(ReaderConfig cfg) + { + return new TextBuffer(cfg); + } + + public static TextBuffer createTemporaryBuffer() + { + return new TextBuffer(null); + } + + /** + * Method called to indicate that the underlying buffers should now + * be recycled if they haven't yet been recycled. Although caller + * can still use this text buffer, it is not advisable to call this + * method if that is likely, since next time a buffer is needed, + * buffers need to reallocated. + * Note: calling this method automatically also clears contents + * of the buffer. + */ + public void recycle(boolean force) + { + if (mConfig != null && mCurrentSegment != null) { + if (force) { + /* If we are allowed to wipe out all existing data, it's + * quite easy; we'll just wipe out contents, and return + * biggest buffer: + */ + resetWithEmpty(); + } else { + /* But if there's non-shared data (ie. buffer is still + * in use), can't return it yet: + */ + if (mInputStart < 0 && (mSegmentSize + mCurrentSize) > 0) { + return; + } + // If no data (or only shared data), can continue + if (mSegments != null && mSegments.size() > 0) { + // No need to use anything from list, curr segment not null + mSegments.clear(); + mSegmentSize = 0; + } + } + + char[] buf = mCurrentSegment; + mCurrentSegment = null; + mConfig.freeMediumCBuffer(buf); + } + } + + /** + * Method called to clear out any content text buffer may have, and + * initializes buffer to use non-shared data. + */ + public void resetWithEmpty() + { + mInputBuffer = null; + mInputStart = -1; // indicates shared buffer not used + mInputLen = 0; + + mResultString = null; + mResultArray = null; + + // And then reset internal input buffers, if necessary: + if (mHasSegments) { + clearSegments(); + } + mCurrentSize = 0; + } + + /** + * Similar to {@link #resetWithEmpty}, but actively marks current + * text content to be empty string (whereas former method leaves + * content as undefined). + */ + public void resetWithEmptyString() + { + mInputBuffer = null; + mInputStart = -1; // indicates shared buffer not used + mInputLen = 0; + mResultString = ""; + mResultArray = null; + if (mHasSegments) { + clearSegments(); + } + mCurrentSize = 0; + } + + /** + * Method called to initialize the buffer with a shared copy of data; + * this means that buffer will just have pointers to actual data. It + * also means that if anything is to be appended to the buffer, it + * will first have to unshare it (make a local copy). + */ + public void resetWithShared(char[] buf, int start, int len) + { + // Let's first mark things we need about input buffer + mInputBuffer = buf; + mInputStart = start; + mInputLen = len; + + // Then clear intermediate values, if any: + mResultString = null; + mResultArray = null; + + // And then reset internal input buffers, if necessary: + if (mHasSegments) { + clearSegments(); + } + } + + public void resetWithCopy(char[] buf, int start, int len) + { + mInputBuffer = null; + mInputStart = -1; // indicates shared buffer not used + mInputLen = 0; + + mResultString = null; + mResultArray = null; + + // And then reset internal input buffers, if necessary: + if (mHasSegments) { + clearSegments(); + } else { + if (mCurrentSegment == null) { + mCurrentSegment = allocBuffer(len); + } + mCurrentSize = mSegmentSize = 0; + } + append(buf, start, len); + } + + /** + * Method called to make sure there is a non-shared segment to use, without + * appending any content yet. + */ + public void resetInitialized() + { + resetWithEmpty(); + if (mCurrentSegment == null) { + mCurrentSegment = allocBuffer(0); + } + } + + private final char[] allocBuffer(int needed) + { + int size = Math.max(needed, DEF_INITIAL_BUFFER_SIZE); + char[] buf = null; + if (mConfig != null) { + buf = mConfig.allocMediumCBuffer(size); + if (buf != null) { + return buf; + } + } + return new char[size]; + } + + private final void clearSegments() + { + mHasSegments = false; + /* Since the current segment should be the biggest one + * (as we allocate 50% bigger each time), let's retain it, + * and clear others + */ + mSegments.clear(); + mCurrentSize = mSegmentSize = 0; + } + + public void resetWithIndentation(int indCharCount, char indChar) + { + mInputStart = 0; + mInputLen = indCharCount+1; + String text; + if (indChar == '\t') { // tabs? + mInputBuffer = sIndTabsArray; + text = sIndTabsStrings[indCharCount]; + if (text == null) { + sIndTabsStrings[indCharCount] = text = sIndTabs.substring(0, mInputLen); + } + } else { // nope, spaces (should assert indChar?) + mInputBuffer = sIndSpacesArray; + text = sIndSpacesStrings[indCharCount]; + if (text == null) { + sIndSpacesStrings[indCharCount] = text = sIndSpaces.substring(0, mInputLen); + } + } + mResultString = text; + + /* Should not need the explicit non-shared array; no point in + * pre-populating it (can be changed if this is not true) + */ + mResultArray = null; + + // And then reset internal input buffers, if necessary: + if (mSegments != null && mSegments.size() > 0) { + mSegments.clear(); + mCurrentSize = mSegmentSize = 0; + } + } + + /* + ////////////////////////////////////////////// + // Accessors for implementing StAX interface: + ////////////////////////////////////////////// + */ + + /** + * @return Number of characters currently stored by this collector + */ + public int size() { + if (mInputStart >= 0) { // shared copy from input buf + return mInputLen; + } + // local segmented buffers + return mSegmentSize + mCurrentSize; + } + + public int getTextStart() + { + /* Only shared input buffer can have non-zero offset; buffer + * segments start at 0, and if we have to create a combo buffer, + * that too will start from beginning of the buffer + */ + return (mInputStart >= 0) ? mInputStart : 0; + } + + public char[] getTextBuffer() + { + // Are we just using shared input buffer? + if (mInputStart >= 0) { + return mInputBuffer; + } + // Nope; but does it fit in just one segment? + if (mSegments == null || mSegments.size() == 0) { + return mCurrentSegment; + } + // Nope, need to have/create a non-segmented array and return it + return contentsAsArray(); + } + + /* + ///////////////////////////////////////////////// + // Accessors for implementing StAX2 Typed access + ///////////////////////////////////////////////// + */ + + /** + * Generic pass-through method which call given decoder + * with accumulated data + */ + public void decode(TypedValueDecoder tvd) + throws IllegalArgumentException + { + char[] buf; + int start, end; + + if (mInputStart >= 0) { // shared buffer, common case + buf = mInputBuffer; + start = mInputStart; + end = start + mInputLen; + } else { + buf = getTextBuffer(); + start = 0; + end = mSegmentSize + mCurrentSize; + } + + // Need to trim first + while (true) { + if (start >= end) { + tvd.handleEmptyValue(); + return; + } + if (!StringUtil.isSpace(buf[start])) { + break; + } + ++start; + } + // Trailing space? + while (--end > start && StringUtil.isSpace(buf[end])) { } + tvd.decode(buf, start, end+1); + } + + /** + * Pass-through decode method called to find find the next token, + * decode it, and repeat the process as long as there are more + * tokens and the array decoder accepts more entries. + * All tokens processed will be "consumed", such that they will + * not be visible via buffer. + * + * @return Number of tokens decoded; 0 means that no (more) tokens + * were found from this buffer. + */ + public int decodeElements(TypedArrayDecoder tad, InputProblemReporter rep) + throws TypedXMLStreamException + { + int count = 0; + + /* First: for simplicity, we require a single flat buffer to + * decode from. Second: to be able to update start location + * (to keep track of what's available), we need to fake that + * we are using a shared buffer (since that has offset) + */ + if (mInputStart < 0) { + if (mHasSegments) { + mInputBuffer = buildResultArray(); + mInputLen = mInputBuffer.length; + // let's also clear segments since they are not needed any more + clearSegments(); + } else { + // just current buffer, easier to fake + mInputBuffer = mCurrentSegment; + mInputLen = mCurrentSize; + } + mInputStart = 0; + } + + // And then let's decode + int ptr = mInputStart; + final int end = ptr + mInputLen; + final char[] buf = mInputBuffer; + int start = ptr; + + try { + decode_loop: + while (ptr < end) { + // First, any space to skip? + while (buf[ptr] <= INT_SPACE) { + if (++ptr >= end) { + break decode_loop; + } + } + // Then let's figure out non-space char (token) + start = ptr; + ++ptr; + while (ptr < end && buf[ptr] > INT_SPACE) { + ++ptr; + } + ++count; + int tokenEnd = ptr; + ++ptr; // to skip trailing space (or, beyond end) + // And there we have it + if (tad.decodeValue(buf, start, tokenEnd)) { + break; + } + } + } catch (IllegalArgumentException iae) { + // Need to convert to a checked stream exception + + /* Hmmh. This is probably not an accurate location... but + * we can't do much better as content we have has been + * normalized already. + */ + Location loc = rep.getLocation(); + // -1 to move it back after being advanced earlier (to skip trailing space) + String lexical = new String(buf, start, (ptr-start-1)); + throw new TypedXMLStreamException(lexical, iae.getMessage(), loc, iae); + } finally { + mInputStart = ptr; + mInputLen = end-ptr; + } + return count; + } + + /** + * Method that needs to be called to configure given base64 decoder + * with textual contents collected by this buffer. + * + * @param dec Decoder that will need data + * @param firstChunk Whether this is the first segment fed or not; + * if it is, state needs to be fullt reset; if not, only partially. + */ + public void initBinaryChunks(Base64Variant v, CharArrayBase64Decoder dec, boolean firstChunk) + { + if (mInputStart < 0) { // non-shared + dec.init(v, firstChunk, mCurrentSegment, 0, mCurrentSize, mSegments); + } else { // shared + dec.init(v, firstChunk, mInputBuffer, mInputStart, mInputLen, null); + } + } + + /* + ////////////////////////////////////////////// + // Accessors: + ////////////////////////////////////////////// + */ + + public String contentsAsString() + { + if (mResultString == null) { + // Has array been requested? Can make a shortcut, if so: + if (mResultArray != null) { + mResultString = new String(mResultArray); + } else { + // Do we use shared array? + if (mInputStart >= 0) { + if (mInputLen < 1) { + return (mResultString = ""); + } + mResultString = new String(mInputBuffer, mInputStart, mInputLen); + } else { // nope... need to copy + // But first, let's see if we have just one buffer + int segLen = mSegmentSize; + int currLen = mCurrentSize; + + if (segLen == 0) { // yup + mResultString = (currLen == 0) ? "" : new String(mCurrentSegment, 0, currLen); + } else { // no, need to combine + StringBuilder sb = new StringBuilder(segLen + currLen); + // First stored segments + if (mSegments != null) { + for (int i = 0, len = mSegments.size(); i < len; ++i) { + char[] curr = mSegments.get(i); + sb.append(curr, 0, curr.length); + } + } + // And finally, current segment: + sb.append(mCurrentSegment, 0, mCurrentSize); + mResultString = sb.toString(); + } + } + } + } + return mResultString; + } + + /** + * Similar to {@link #contentsAsString}, but constructs a StringBuilder + * for further appends. + * + * @param extraSpace Number of extra characters to preserve in StringBuilder + * beyond space immediately needed to hold the contents + */ + public StringBuilder contentsAsStringBuilder(int extraSpace) + { + if (mResultString != null) { + return new StringBuilder(mResultString); + } + if (mResultArray != null) { + StringBuilder sb = new StringBuilder(mResultArray.length + extraSpace); + sb.append(mResultArray, 0, mResultArray.length); + return sb; + } + if (mInputStart >= 0) { // shared array + if (mInputLen < 1) { + return new StringBuilder(); + } + StringBuilder sb = new StringBuilder(mInputLen + extraSpace); + sb.append(mInputBuffer, mInputStart, mInputLen); + return sb; + } + int segLen = mSegmentSize; + int currLen = mCurrentSize; + + StringBuilder sb = new StringBuilder(segLen + currLen + extraSpace); + // First stored segments + if (mSegments != null) { + for (int i = 0, len = mSegments.size(); i < len; ++i) { + char[] curr = mSegments.get(i); + sb.append(curr, 0, curr.length); + } + } + // And finally, current segment: + sb.append(mCurrentSegment, 0, currLen); + return sb; + } + + public void contentsToStringBuilder(StringBuilder sb) + { + if (mResultString != null) { + sb.append(mResultString); + } else if (mResultArray != null) { + sb.append(mResultArray); + } else if (mInputStart >= 0) { // shared array + if (mInputLen > 0) { + sb.append(mInputBuffer, mInputStart, mInputLen); + } + } else { + // First stored segments + if (mSegments != null) { + for (int i = 0, len = mSegments.size(); i < len; ++i) { + char[] curr = mSegments.get(i); + sb.append(curr, 0, curr.length); + } + } + // And finally, current segment: + sb.append(mCurrentSegment, 0, mCurrentSize); + } + } + + public char[] contentsAsArray() + { + char[] result = mResultArray; + if (result == null) { + mResultArray = result = buildResultArray(); + } + return result; + } + + public int contentsToArray(int srcStart, char[] dst, int dstStart, int len) { + // Easy to copy from shared buffer: + if (mInputStart >= 0) { + int amount = mInputLen - srcStart; + if (amount > len) { + amount = len; + } else if (amount < 0) { + amount = 0; + } + if (amount > 0) { + System.arraycopy(mInputBuffer, mInputStart+srcStart, + dst, dstStart, amount); + } + return amount; + } + + /* Could also check if we have array, but that'd only help with + * braindead clients that get full array first, then segments... + * which hopefully aren't that common + */ + // Copying from segmented array is bit more involved: + int totalAmount = 0; + if (mSegments != null) { + for (int i = 0, segc = mSegments.size(); i < segc; ++i) { + char[] segment = mSegments.get(i); + int segLen = segment.length; + int amount = segLen - srcStart; + if (amount < 1) { // nothing from this segment? + srcStart -= segLen; + continue; + } + if (amount >= len) { // can get rest from this segment? + System.arraycopy(segment, srcStart, dst, dstStart, len); + return (totalAmount + len); + } + // Can get some from this segment, offset becomes zero: + System.arraycopy(segment, srcStart, dst, dstStart, amount); + totalAmount += amount; + dstStart += amount; + len -= amount; + srcStart = 0; + } + } + + // Need to copy anything from last segment? + if (len > 0) { + int maxAmount = mCurrentSize - srcStart; + if (len > maxAmount) { + len = maxAmount; + } + if (len > 0) { // should always be true + System.arraycopy(mCurrentSegment, srcStart, dst, dstStart, len); + totalAmount += len; + } + } + + return totalAmount; + } + + /** + * Method that will stream contents of this buffer into specified + * Writer. + */ + public int rawContentsTo(Writer w) + throws IOException + { + // Let's first see if we have created helper objects: + if (mResultArray != null) { + w.write(mResultArray); + return mResultArray.length; + } + if (mResultString != null) { + w.write(mResultString); + return mResultString.length(); + } + + // Do we use shared array? + if (mInputStart >= 0) { + if (mInputLen > 0) { + w.write(mInputBuffer, mInputStart, mInputLen); + } + return mInputLen; + } + // Nope, need to do full segmented output + int rlen = 0; + if (mSegments != null) { + for (int i = 0, len = mSegments.size(); i < len; ++i) { + char[] ch = mSegments.get(i); + w.write(ch); + rlen += ch.length; + } + } + if (mCurrentSize > 0) { + w.write(mCurrentSegment, 0, mCurrentSize); + rlen += mCurrentSize; + } + return rlen; + } + + public Reader rawContentsViaReader() + throws IOException + { + // Let's first see if we have created helper objects: + if (mResultArray != null) { + return new CharArrayReader(mResultArray); + } + if (mResultString != null) { + return new StringReader(mResultString); + } + + // Do we use shared array? + if (mInputStart >= 0) { + if (mInputLen > 0) { + return new CharArrayReader(mInputBuffer, mInputStart, mInputLen); + } + return new StringReader(""); + } + // or maybe it's all in the current segment + if (mSegments == null || mSegments.size() == 0) { + return new CharArrayReader(mCurrentSegment, 0, mCurrentSize); + } + // Nope, need to do full segmented output + return new BufferReader(mSegments, mCurrentSegment, mCurrentSize); + } + + public boolean isAllWhitespace() + { + if (mInputStart >= 0) { // using single shared buffer? + char[] buf = mInputBuffer; + int i = mInputStart; + int last = i + mInputLen; + for (; i < last; ++i) { + if (buf[i] > INT_SPACE) { + return false; + } + } + return true; + } + + // Nope, need to do full segmented output + if (mSegments != null) { + for (int i = 0, len = mSegments.size(); i < len; ++i) { + char[] buf = mSegments.get(i); + for (int j = 0, len2 = buf.length; j < len2; ++j) { + if (buf[j] > INT_SPACE) { + return false; + } + } + } + } + + char[] buf = mCurrentSegment; + for (int i = 0, len = mCurrentSize; i < len; ++i) { + if (buf[i] > INT_SPACE) { + return false; + } + } + return true; + } + + /** + * Method that can be used to check if the contents of the buffer end + * in specified String. + * + * @return True if the textual content buffer contains ends with the + * specified String; false otherwise + */ + public boolean endsWith(String str) + { + /* Let's just play this safe; should seldom if ever happen... + * and because of that, can be sub-optimal, performancewise, to + * alternatives. + */ + if (mInputStart >= 0) { + unshare(16); + } + + int segIndex = (mSegments == null) ? 0 : mSegments.size(); + int inIndex = str.length() - 1; + char[] buf = mCurrentSegment; + int bufIndex = mCurrentSize-1; + + while (inIndex >= 0) { + if (str.charAt(inIndex) != buf[bufIndex]) { + return false; + } + if (--inIndex == 0) { + break; + } + if (--bufIndex < 0) { + if (--segIndex < 0) { // no more data? + return false; + } + buf = mSegments.get(segIndex); + bufIndex = buf.length-1; + } + } + + return true; + } + + /** + * Note: it is assumed that this method is not used often enough to + * be a bottleneck, or for long segments. Based on this, it is optimized + * for common simple cases where there is only one single character + * segment to use; fallback for other cases is to create such segment. + */ + public boolean equalsString(String str) + { + int expLen = str.length(); + + // First the easy check; if we have a shared buf: + if (mInputStart >= 0) { + if (mInputLen != expLen) { + return false; + } + for (int i = 0; i < expLen; ++i) { + if (str.charAt(i) != mInputBuffer[mInputStart+i]) { + return false; + } + } + return true; + } + + // Otherwise, segments: + if (expLen != size()) { + return false; + } + char[] seg; + if (mSegments == null || mSegments.size() == 0) { + // just one segment, still easy + seg = mCurrentSegment; + } else { + /* Ok; this is the sub-optimal case. Could obviously juggle through + * segments, but probably not worth the hassle, we seldom if ever + * get here... + */ + seg = contentsAsArray(); + } + + for (int i = 0; i < expLen; ++i) { + if (seg[i] != str.charAt(i)) { + return false; + } + } + return true; + } + + /* + ////////////////////////////////////////////// + // Access using SAX handlers: + ////////////////////////////////////////////// + */ + + public void fireSaxCharacterEvents(ContentHandler h) + throws SAXException + { + if (mResultArray != null) { // already have single array? + h.characters(mResultArray, 0, mResultArray.length); + } else if (mInputStart >= 0) { // sharing input buffer? + h.characters(mInputBuffer, mInputStart, mInputLen); + } else { + if (mSegments != null) { + for (int i = 0, len = mSegments.size(); i < len; ++i) { + char[] ch = mSegments.get(i); + h.characters(ch, 0, ch.length); + } + } + if (mCurrentSize > 0) { + h.characters(mCurrentSegment, 0, mCurrentSize); + } + } + } + + public void fireSaxSpaceEvents(ContentHandler h) + throws SAXException + { + if (mResultArray != null) { // only happens for indentation + h.ignorableWhitespace(mResultArray, 0, mResultArray.length); + } else if (mInputStart >= 0) { // sharing input buffer? + h.ignorableWhitespace(mInputBuffer, mInputStart, mInputLen); + } else { + if (mSegments != null) { + for (int i = 0, len = mSegments.size(); i < len; ++i) { + char[] ch = mSegments.get(i); + h.ignorableWhitespace(ch, 0, ch.length); + } + } + if (mCurrentSize > 0) { + h.ignorableWhitespace(mCurrentSegment, 0, mCurrentSize); + } + } + } + + public void fireSaxCommentEvent(LexicalHandler h) + throws SAXException + { + // Comment can not be split, so may need to combine the array + if (mResultArray != null) { // only happens for indentation + h.comment(mResultArray, 0, mResultArray.length); + } else if (mInputStart >= 0) { // sharing input buffer? + h.comment(mInputBuffer, mInputStart, mInputLen); + } else if (mSegments != null && mSegments.size() > 0) { + char[] ch = contentsAsArray(); + h.comment(ch, 0, ch.length); + } else { + h.comment(mCurrentSegment, 0, mCurrentSize); + } + } + + public void fireDtdCommentEvent(DTDEventListener l) + { + // Comment can not be split, so may need to combine the array + if (mResultArray != null) { // only happens for indentation + l.dtdComment(mResultArray, 0, mResultArray.length); + } else if (mInputStart >= 0) { // sharing input buffer? + l.dtdComment(mInputBuffer, mInputStart, mInputLen); + } else if (mSegments != null && mSegments.size() > 0) { + char[] ch = contentsAsArray(); + l.dtdComment(ch, 0, ch.length); + } else { + l.dtdComment(mCurrentSegment, 0, mCurrentSize); + } + } + + /* + ////////////////////////////////////////////// + // Support for validation + ////////////////////////////////////////////// + */ + + public void validateText(XMLValidator vld, boolean lastSegment) + throws XMLStreamException + { + // Shared buffer? Let's just pass that + if (mInputStart >= 0) { + vld.validateText(mInputBuffer, mInputStart, mInputStart + mInputLen, lastSegment); + } else { + /* Otherwise, can either create a combine buffer, or construct + * a String. While former could be more efficient, let's do latter + * for now since current validator implementations work better + * with Strings. + */ + vld.validateText(contentsAsString(), lastSegment); + } + } + + /* + ////////////////////////////////////////////// + // Public mutators: + ////////////////////////////////////////////// + */ + + /** + * Method called to make sure that buffer is not using shared input + * buffer; if it is, it will copy such contents to private buffer. + */ + public void ensureNotShared() { + if (mInputStart >= 0) { + unshare(16); + } + } + + public void append(char c) { + // Using shared buffer so far? + if (mInputStart >= 0) { + unshare(16); + } + mResultString = null; + mResultArray = null; + // Room in current segment? + char[] curr = mCurrentSegment; + if (mCurrentSize >= curr.length) { + expand(1); + curr = mCurrentSegment; + } + curr[mCurrentSize++] = c; + } + + public void append(char[] c, int start, int len) + { + // Can't append to shared buf (sanity check) + if (mInputStart >= 0) { + unshare(len); + } + mResultString = null; + mResultArray = null; + + // Room in current segment? + char[] curr = mCurrentSegment; + int max = curr.length - mCurrentSize; + + if (max >= len) { + System.arraycopy(c, start, curr, mCurrentSize, len); + mCurrentSize += len; + } else { + // No room for all, need to copy part(s): + if (max > 0) { + System.arraycopy(c, start, curr, mCurrentSize, max); + start += max; + len -= max; + } + /* And then allocate new segment; we are guaranteed to now + * have enough room in segment. + */ + expand(len); // note: curr != mCurrentSegment after this + System.arraycopy(c, start, mCurrentSegment, 0, len); + mCurrentSize = len; + } + } + + public void append(String str) + { + // Can't append to shared buf (sanity check) + int len = str.length(); + if (mInputStart >= 0) { + unshare(len); + } + mResultString = null; + mResultArray = null; + + // Room in current segment? + char[] curr = mCurrentSegment; + int max = curr.length - mCurrentSize; + if (max >= len) { + str.getChars(0, len, curr, mCurrentSize); + mCurrentSize += len; + } else { + // No room for all, need to copy part(s): + if (max > 0) { + str.getChars(0, max, curr, mCurrentSize); + len -= max; + } + /* And then allocate new segment; we are guaranteed to now + * have enough room in segment. + */ + expand(len); + str.getChars(max, max+len, mCurrentSegment, 0); + mCurrentSize = len; + } + } + + /* + ////////////////////////////////////////////// + // Raw access, for high-performance use: + ////////////////////////////////////////////// + */ + + public char[] getCurrentSegment() + { + /* Since the intention of the caller is to directly add stuff into + * buffers, we should NOT have anything in shared buffer... ie. may + * need to unshare contents. + */ + if (mInputStart >= 0) { + unshare(1); + } else { + char[] curr = mCurrentSegment; + if (curr == null) { + mCurrentSegment = allocBuffer(0); + } else if (mCurrentSize >= curr.length) { + // Plus, we better have room for at least one more char + expand(1); + } + } + return mCurrentSegment; + } + + public int getCurrentSegmentSize() { + return mCurrentSize; + } + + public void setCurrentLength(int len) { + mCurrentSize = len; + } + + public char[] finishCurrentSegment() + { + if (mSegments == null) { + mSegments = new ArrayList(); + } + mHasSegments = true; + mSegments.add(mCurrentSegment); + int oldLen = mCurrentSegment.length; + mSegmentSize += oldLen; + char[] curr = new char[calcNewSize(oldLen)]; + mCurrentSize = 0; + mCurrentSegment = curr; + return curr; + } + + /** + * Method used to determine size of the next segment to + * allocate to contain textual content. + */ + private int calcNewSize(int latestSize) + { + // Let's grow segments by 50%, when over 8k + int incr = (latestSize < 8000) ? latestSize : (latestSize >> 1); + int size = latestSize + incr; + // but let's not create too big chunks + return Math.min(size, MAX_SEGMENT_LENGTH); + } + + /* + ////////////////////////////////////////////// + // Standard methods: + ////////////////////////////////////////////// + */ + + /** + * Note: calling this method may not be as efficient as calling + * {@link #contentsAsString}, since it's not guaranteed that resulting + * String is cached. + */ + @Override + public String toString() { + return contentsAsString(); + } + + /* + ////////////////////////////////////////////// + // Internal methods: + ////////////////////////////////////////////// + */ + + /** + * Method called if/when we need to append content when we have been + * initialized to use shared buffer. + */ + public void unshare(int needExtra) + { + int len = mInputLen; + mInputLen = 0; + char[] inputBuf = mInputBuffer; + mInputBuffer = null; + int start = mInputStart; + mInputStart = -1; + + // Is buffer big enough, or do we need to reallocate? + int needed = len+needExtra; + if (mCurrentSegment == null || needed > mCurrentSegment.length) { + mCurrentSegment = allocBuffer(needed); + } + if (len > 0) { + System.arraycopy(inputBuf, start, mCurrentSegment, 0, len); + } + mSegmentSize = 0; + mCurrentSize = len; + } + + /** + * Method called when current segment is full, to allocate new + * segment. + * + * @param roomNeeded Number of characters that the resulting + * new buffer must have + */ + private void expand(int roomNeeded) + { + // First, let's move current segment to segment list: + if (mSegments == null) { + mSegments = new ArrayList(); + } + char[] curr = mCurrentSegment; + mHasSegments = true; + mSegments.add(curr); + int oldLen = curr.length; + mSegmentSize += oldLen; + int newSize = Math.max(roomNeeded, calcNewSize(oldLen)); + curr = new char[newSize]; + mCurrentSize = 0; + mCurrentSegment = curr; + } + + private char[] buildResultArray() + { + if (mResultString != null) { // Can take a shortcut... + return mResultString.toCharArray(); + } + char[] result; + + // Do we use shared array? + if (mInputStart >= 0) { + if (mInputLen < 1) { + return DataUtil.getEmptyCharArray(); + } + result = new char[mInputLen]; + System.arraycopy(mInputBuffer, mInputStart, result, 0, + mInputLen); + } else { // nope + int size = size(); + if (size < 1) { + return DataUtil.getEmptyCharArray(); + } + int offset = 0; + result = new char[size]; + if (mSegments != null) { + for (int i = 0, len = mSegments.size(); i < len; ++i) { + char[] curr = mSegments.get(i); + int currLen = curr.length; + System.arraycopy(curr, 0, result, offset, currLen); + offset += currLen; + } + } + System.arraycopy(mCurrentSegment, 0, result, offset, mCurrentSize); + } + return result; + } + + private final static class BufferReader + extends Reader + { + ArrayList _segments; + char[] _currentSegment; + final int _currentLength; + + int _segmentIndex; + int _segmentOffset; + int _currentOffset; + + public BufferReader(ArrayList segs, char[] currSeg, int currSegLen) + { + _segments = segs; + _currentSegment = currSeg; + _currentLength = currSegLen; + + _segmentIndex = 0; + _segmentOffset = _currentOffset = 0; + } + + @Override + public void close() { + _segments = null; + _currentSegment = null; + } + + @Override + public void mark(int x) throws IOException { + throw new IOException("mark() not supported"); + } + + @Override + public boolean markSupported() { + return false; + } + + @Override + public int read(char[] cbuf, int offset, int len) + { + if (len < 1) { + return 0; + } + + int origOffset = offset; + // First need to copy stuff from previous segments + while (_segments != null) { + char[] curr = _segments.get(_segmentIndex); + int max = curr.length - _segmentOffset; + if (len <= max) { // this is enough + System.arraycopy(curr, _segmentOffset, cbuf, offset, len); + _segmentOffset += len; + offset += len; + return (offset - origOffset); + } + // Not enough, but helps... + if (max > 0) { + System.arraycopy(curr, _segmentOffset, cbuf, offset, max); + offset += max; + } + if (++_segmentIndex >= _segments.size()) { // last one + _segments = null; + } else { + _segmentOffset = 0; + } + } + + // ok, anything to copy from the active segment? + if (len > 0 && _currentSegment != null) { + int max = _currentLength - _currentOffset; + if (len >= max) { // reading it all + len = max; + System.arraycopy(_currentSegment, _currentOffset, + cbuf, offset, len); + _currentSegment = null; + } else { + System.arraycopy(_currentSegment, _currentOffset, + cbuf, offset, len); + _currentOffset += len; + } + offset += len; + } + + return (origOffset == offset) ? -1 : (offset - origOffset); + } + + @Override + public boolean ready() { + return true; + } + + @Override + public void reset() throws IOException + { + throw new IOException("reset() not supported"); + } + + @Override + public long skip(long amount) + { + /* Note: implementation is almost identical to that of read(); + * difference being that no data is copied. + */ + if (amount < 0) { + return 0L; + } + + long origAmount= amount; + + while (_segments != null) { + char[] curr = _segments.get(_segmentIndex); + int max = curr.length - _segmentOffset; + if (max >= amount) { // this is enough + _segmentOffset += (int) amount; + return origAmount; + } + // Not enough, but helps... + amount -= max; + if (++_segmentIndex >= _segments.size()) { // last one + _segments = null; + } else { + _segmentOffset = 0; + } + } + + // ok, anything left in the active segment? + if (amount > 0 && _currentSegment != null) { + int max = _currentLength - _currentOffset; + if (amount >= max) { // reading it all + amount -= max; + _currentSegment = null; + } else { + amount = 0L; + _currentOffset += (int) amount; + } + } + + return (amount == origAmount) ? -1L : (origAmount - amount); + } + } +} diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/util/TextBuilder.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/util/TextBuilder.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/util/TextBuilder.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/util/TextBuilder.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,134 @@ +package com.ctc.wstx.util; + +/** + * Class similar to {@link StringBuilder}, except that it can be used to + * construct multiple Strings, that will share same underlying character + * buffer. This is generally useful for closely related value Strings, + * such as attribute values of a single XML start element. + */ +public final class TextBuilder +{ + private final static int MIN_LEN = 60; + private final static int MAX_LEN = 120; + + private char[] mBuffer; + + private int mBufferLen; + + private String mResultString; + + /* + /////////////////////////////////////////////// + // Life-cycle: + /////////////////////////////////////////////// + */ + + public TextBuilder(int initialSize) + { + int charSize = (initialSize << 4); // multiply by 16 (-> def. 192 chars) + if (charSize < MIN_LEN) { + charSize = MIN_LEN; + } else if (charSize > MAX_LEN) { + charSize = MAX_LEN; + } + mBuffer = new char[charSize]; + } + + /** + * Method called before starting to (re)use the buffer, will discard + * any existing content, and start collecting new set of values. + */ + public void reset() { + mBufferLen = 0; + mResultString = null; + } + + /* + /////////////////////////////////////////////// + // Accesors: + /////////////////////////////////////////////// + */ + + public boolean isEmpty() { + return mBufferLen == 0; + } + + public String getAllValues() + { + if (mResultString == null) { + mResultString = new String(mBuffer, 0, mBufferLen); + } + return mResultString; + } + + /** + * Method that gives access to underlying character buffer + */ + public char[] getCharBuffer() { + return mBuffer; + } + + public int getCharSize() { + return mBufferLen; + } + + /* + /////////////////////////////////////////////// + // Mutators: + /////////////////////////////////////////////// + */ + + public void append(char c) { + if (mBuffer.length == mBufferLen) { + resize(1); + } + mBuffer[mBufferLen++] = c; + } + + public void append(char[] src, int start, int len) { + if (len > (mBuffer.length - mBufferLen)) { + resize(len); + } + System.arraycopy(src, start, mBuffer, mBufferLen, len); + mBufferLen += len; + } + + public void setBufferSize(int newSize) { + mBufferLen = newSize; + } + + public char[] bufferFull(int needSpaceFor) { + mBufferLen = mBuffer.length; + resize(needSpaceFor); + return mBuffer; + } + + /* + /////////////////////////////////////////////// + // Debugging: + /////////////////////////////////////////////// + */ + + @Override + public String toString() { + return new String(mBuffer, 0, mBufferLen); + } + + /* + /////////////////////////////////////////////// + // Internal methods: + /////////////////////////////////////////////// + */ + + private void resize(int needSpaceFor) { + char[] old = mBuffer; + int oldLen = old.length; + int addition = oldLen >> 1; // Grow by 50% + needSpaceFor -= (oldLen - mBufferLen); + if (addition < needSpaceFor) { + addition = needSpaceFor; + } + mBuffer = new char[oldLen+addition]; + System.arraycopy(old, 0, mBuffer, 0, mBufferLen); + } +} diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/util/URLUtil.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/util/URLUtil.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/util/URLUtil.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/util/URLUtil.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,221 @@ +package com.ctc.wstx.util; + +import java.io.*; +import java.net.*; +import java.util.regex.Pattern; + +public final class URLUtil +{ + /** + * While URIs that contain pipe are wrong, we'll work around that + * for [WSTX-275]. + */ + private final static Pattern URI_WINDOWS_FILE_PATTERN = Pattern.compile("^file:///\\p{Alpha}|.*$"); + + private URLUtil() { } + + /** + * Method that tries to figure out how to create valid URL from a system + * id, without additional contextual information. + * If we could use URIs this might be easier to do, but they are part + * of JDK 1.4, and preferably code should only require 1.2 (or maybe 1.3) + */ + public static URL urlFromSystemId(String sysId) throws IOException + { + try { + sysId = cleanSystemId(sysId); + /* Ok, does it look like a full URL? For one, you need a colon. Also, + * to reduce likelihood of collision with Windows paths, let's only + * accept it if there are 3 preceding other chars... + * Not sure if Mac might be a problem? (it uses ':' as file path + * separator, alas, at least prior to MacOS X) + */ + int ix = sysId.indexOf(':', 0); + /* Also, protocols are generally fairly short, usually 3 or 4 + * chars (http, ftp, urn); so let's put upper limit of 8 chars too + */ + if (ix >= 3 && ix <= 8) { + return new URL(sysId); + } + // Ok, let's just assume it's local file reference... + /* 24-May-2006, TSa: Amazingly, this single call does show in + * profiling, for small docs. The problem is that deep down it + * tries to check physical file system, to check if the File + * pointed to is a directory: and that is (relatively speaking) + * a very expensive call. Since in this particular case it + * should never be a dir (and/or doesn't matter), let's just + * implement conversion locally + */ + String absPath = new java.io.File(sysId).getAbsolutePath(); + // Need to convert colons/backslashes to regular slashes? + { + char sep = File.separatorChar; + if (sep != '/') { + absPath = absPath.replace(sep, '/'); + } + } + if (absPath.length() > 0 && absPath.charAt(0) != '/') { + absPath = "/" + absPath; + } + return new URL("file", "", absPath); + } catch (MalformedURLException e) { + throwIOException(e, sysId); + return null; // never gets here + } + } + + /** + * @since 4.1 + */ + public static URI uriFromSystemId(final String sysId) throws IOException + { + // as per [WSTX-275] + // note: mostly a copy of matching method above, but with URI instead of URL + try { + if (sysId.indexOf('|', 0) > 0) { + if (URI_WINDOWS_FILE_PATTERN.matcher(sysId).matches()) { + return new URI(sysId.replace('|', ':')); + } + } + + final int ix = sysId.indexOf(':', 0); + if (ix >= 3 && ix <= 8) { + return new URI(sysId); + } + String absPath = new java.io.File(sysId).getAbsolutePath(); + final char sep = File.separatorChar; + if (sep != '/') { + absPath = absPath.replace(sep, '/'); + } + if (absPath.length() > 0 && absPath.charAt(0) != '/') { + absPath = "/" + absPath; + } + return new URI("file", absPath, null); + } catch (final URISyntaxException e) { + throwIOException(e, sysId); + return null; // never gets here + } + } + + public static URL urlFromSystemId(String sysId, URL ctxt) + throws IOException + { + if (ctxt == null) { + return urlFromSystemId(sysId); + } + try { + sysId = cleanSystemId(sysId); + return new URL(ctxt, sysId); + } catch (MalformedURLException e) { + throwIOException(e, sysId); + return null; // never gets here + } + } + + /** + * Method that tries to create and return URL that denotes current + * working directory. Usually used to create a context, when one is + * not explicitly passed. + */ + public static URL urlFromCurrentDir() + throws IOException /* MalformedURLException or such */ + { + /* This seems to work; independent of whether there happens to + * be such/file dir or not. + */ + File parent = new File("a").getAbsoluteFile().getParentFile(); + return toURL(parent); + } + + /** + * Method that tries to get a stream (ideally, optimal one) to read from + * the specified URL. + * Currently it just means creating a simple file input stream if the + * URL points to a (local) file, and otherwise relying on URL classes + * input stream creation method. + */ + public static InputStream inputStreamFromURL(URL url) throws IOException + { + if ("file".equals(url.getProtocol())) { + /* As per [WSTX-82], can not do this if the path refers + * to a network drive on windows. This fixes the problem; + * might not be needed on all platforms (NFS?), but should not + * matter a lot: performance penalty of extra wrapping is more + * relevant when accessing local file system. + */ + String host = url.getHost(); + if (host == null || host.length() == 0) { + /* One more test: if there are quoted characters, need + * to decoded [WSTX-207]: + */ + String path = url.getPath(); + if (path.indexOf('%') >= 0) { + path = URLDecoder.decode(path, "UTF-8"); + } + return new FileInputStream(path); + } + } + return url.openStream(); + } + + /** + * Method that tries to get a stream (ideally, optimal one) to write to + * the resource specified by given URL. + * Currently it just means creating a simple file output stream if the + * URL points to a (local) file, and otherwise relying on URL classes + * input stream creation method. + */ + public static OutputStream outputStreamFromURL(URL url) + throws IOException + { + if ("file".equals(url.getProtocol())) { + /* As per [WSTX-82], can not do this if the path refers + * to a network drive on windows. + */ + String host = url.getHost(); + if (host == null || host.length() == 0) { + return new FileOutputStream(url.getPath()); + } + } + return url.openConnection().getOutputStream(); + } + + /** + * Helper method that will convert given file into equivalent URL. + * Encapsulated as a separate method to allow for working around + * problems with deprecation of {@link File#toURL} method. + */ + public static URL toURL(File f) throws IOException { + return f.toURI().toURL(); + } + + /* + /////////////////////////////////////////// + // Private helper methods + /////////////////////////////////////////// + */ + + private static String cleanSystemId(final String sysId) + { + int ix = sysId.indexOf('|'); + if (ix > 0 && URI_WINDOWS_FILE_PATTERN.matcher(sysId).matches()) { + StringBuilder sb = new StringBuilder(sysId); + sb.setCharAt(ix, ':'); + return sb.toString(); + } + return sysId; + } + + /** + * Helper method that tries to fully convert strange URL-specific exception + * to more general IO exception. Also, to try to use JDK 1.4 feature without + * creating requirement, uses reflection to try to set the root cause, if + * we are running on JDK1.4 + */ + private static void throwIOException(Exception mex, String sysId) + throws IOException + { + String msg = "[resolving systemId '"+sysId+"']: "+mex.toString(); + throw ExceptionUtil.constructIOException(msg, mex); + } +} diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/util/WordResolver.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/util/WordResolver.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/util/WordResolver.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/util/WordResolver.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,578 @@ +package com.ctc.wstx.util; + +import java.util.*; + +/** + * A specialized Map/Symbol table - like data structure that can be used + * for both checking whether a word (passed in as a char array) exists + * in certain set of words AND getting that word as a String. + * It is reasonably efficient both time and speed-wise, at least for + * certain use cases; specifically, if there is no existing key to use, + * it is more efficient way to get to a shared copy of that String + * The general usage pattern is expected + * to be such that most checks are positive, ie. that the word indeed + * is contained in the structure. + *

+ * Although this is an efficient data struct for specific set of usage + * patterns, one restriction is that the full set of words to include has to + * be known before constructing the instnace. Also, the size of the set is + * limited to total word content of about 20k characters. + *

+ * TODO: Should document the internal data structure... + */ +public final class WordResolver +{ + /** + * Maximum number of words (Strings) an instance can contain + */ + public final static int MAX_WORDS = 0x2000; + + final static char CHAR_NULL = (char) 0; + + /** + * Offset added to numbers to mark 'negative' numbers. Asymmetric, + * since range of negative markers needed is smaller than positive + * numbers... + */ + final static int NEGATIVE_OFFSET = 0x10000 - MAX_WORDS; + + /** + * This is actually just a guess; but in general linear search should + * be faster for short sequences (definitely for 4 or less; maybe up + * to 8 or less?) + */ + final static int MIN_BINARY_SEARCH = 7; + + /** + * Compressed presentation of the word set. + */ + final char[] mData; + + /** + * Array of actual words returned resolved for matches. + */ + final String[] mWords; + + /* + //////////////////////////////////////////////// + // Life-cycle + //////////////////////////////////////////////// + */ + + private WordResolver(String[] words, char[] index) { + mWords = words; + mData = index; + } + + /** + * Tries to construct an instance given ordered set of words. + *

+ * Note: currently maximum number of words that can be contained + * is limited to {@link #MAX_WORDS}; additionally, maximum length + * of all such words can not exceed roughly 28000 characters. + * + * @return WordResolver constructed for given set of words, if + * the word set size is not too big; null to indicate "too big" + * instance. + */ + public static WordResolver constructInstance(TreeSet wordSet) + { + if (wordSet.size() > MAX_WORDS) { + return null; + } + return new Builder(wordSet).construct(); + } + + /* + //////////////////////////////////////////////// + // Public API + //////////////////////////////////////////////// + */ + + /** + * @return Number of words contained + */ + public int size() { + return mWords.length; + } + + /* + public int indexSize() { + return mData.length; + } + */ + + /** + * @param str Character array that contains the word to find + * @param start Index of the first character of the word + * @param end Index following the last character of the word, + * so that end - start equals word length (similar + * to the way String.substring() has). + * + * @return (Shared) string instance of the word, if it exists in + * the word set; null if not. + */ + @SuppressWarnings("cast") + public String find(char[] str, final int start, final int end) + { + char[] data = mData; + + // 03-Jan-2006, TSa: Special case; one entry + if (data == null) { + return findFromOne(str, start, end); + } + + int ptr = 0; // pointer to compressed set data + int offset = start; + + while (true) { + // End of input String? Need to match the runt entry! + if (offset == end) { + if (data[ptr+1] == CHAR_NULL) { + return mWords[data[ptr+2] - NEGATIVE_OFFSET]; + } + return null; + } + + int count = data[ptr++]; + // Need to find the branch to follow, if any + char c = str[offset++]; + + inner_block: + do { // dummy loop, need to have break + // Linear or binary search? + if (count < MIN_BINARY_SEARCH) { + // always at least two branches; never less + if (data[ptr] == c) { + ptr = (int) data[ptr+1]; + break inner_block; + } + if (data[ptr+2] == c) { + ptr = (int) data[ptr+3]; + break inner_block; + } + int branchEnd = ptr + (count << 1); + // Starts from entry #3, if such exists + for (ptr += 4; ptr < branchEnd; ptr += 2) { + if (data[ptr] == c) { + ptr = (int) data[ptr+1]; + break inner_block; + } + } + return null; // No match! + } else { // Ok, binary search: + int low = 0; + int high = count-1; + int mid; + + while (low <= high) { + mid = (low + high) >> 1; + int ix = ptr + (mid << 1); + int diff = data[ix] - c; + if (diff > 0) { // char was 'higher', need to go down + high = mid-1; + } else if (diff < 0) { // lower, need to go up + low = mid+1; + } else { // match (so far) + ptr = (int) data[ix+1]; + break inner_block; + } + } + return null; // No match! + } + } while (false); + + // Ok; now, is it the end? + if (ptr >= NEGATIVE_OFFSET) { + String word = mWords[ptr - NEGATIVE_OFFSET]; + int expLen = (end - start); + if (word.length() != expLen) { + return null; + } + for (int i = offset - start; offset < end; ++i, ++offset) { + if (word.charAt(i) != str[offset]) { + return null; + } + } + return word; + } + } + // never gets here + } + + private String findFromOne(char[] str, final int start, final int end) + { + String word = mWords[0]; + int len = end-start; + if (word.length() != len) { + return null; + } + for (int i = 0; i < len; ++i) { + if (word.charAt(i) != str[start+i]) { + return null; + } + } + return word; + } + + /** + * @return (Shared) string instance of the word, if it exists in + * the word set; null if not. + */ + @SuppressWarnings("cast") + public String find(String str) + { + char[] data = mData; + + // 03-Jan-2006, TSa: Special case; one entry + if (data == null) { + String word = mWords[0]; + return word.equals(str) ? word : null; + } + + int ptr = 0; // pointer to compressed set data + int offset = 0; + int end = str.length(); + + while (true) { + // End of input String? Need to match the runt entry! + if (offset == end) { + if (data[ptr+1] == CHAR_NULL) { + return mWords[data[ptr+2] - NEGATIVE_OFFSET]; + } + return null; + } + + int count = data[ptr++]; + // Need to find the branch to follow, if any + char c = str.charAt(offset++); + + inner_block: + do { // dummy loop, need to have break + // Linear or binary search? + if (count < MIN_BINARY_SEARCH) { + // always at least two branches; never less + if (data[ptr] == c) { + ptr = (int) data[ptr+1]; + break inner_block; + } + if (data[ptr+2] == c) { + ptr = (int) data[ptr+3]; + break inner_block; + } + int branchEnd = ptr + (count << 1); + // Starts from entry #3, if such exists + for (ptr += 4; ptr < branchEnd; ptr += 2) { + if (data[ptr] == c) { + ptr = (int) data[ptr+1]; + break inner_block; + } + } + return null; // No match! + } else { // Ok, binary search: + int low = 0; + int high = count-1; + int mid; + + while (low <= high) { + mid = (low + high) >> 1; + int ix = ptr + (mid << 1); + int diff = data[ix] - c; + if (diff > 0) { // char was 'higher', need to go down + high = mid-1; + } else if (diff < 0) { // lower, need to go up + low = mid+1; + } else { // match (so far) + ptr = (int) data[ix+1]; + break inner_block; + } + } + return null; // No match! + } + } while (false); + + // Ok; now, is it the end? + if (ptr >= NEGATIVE_OFFSET) { + String word = mWords[ptr - NEGATIVE_OFFSET]; + if (word.length() != str.length()) { + return null; + } + for (; offset < end; ++offset) { + if (word.charAt(offset) != str.charAt(offset)) { + return null; + } + } + return word; + } + } + // never gets here + } + + /* + //////////////////////////////////////////////// + // Re-defined public methods + //////////////////////////////////////////////// + */ + + @Override + public String toString() + { + StringBuilder sb = new StringBuilder(16 + (mWords.length << 3)); + for (int i = 0, len = mWords.length; i < len; ++i) { + if (i > 0) { + sb.append(", "); + } + sb.append(mWords[i]); + } + return sb.toString(); + } + + /* + //////////////////////////////////////////////// + // Helper classes + //////////////////////////////////////////////// + */ + + private final static class Builder + { + final String[] mWords; + + char[] mData; + + /** + * Number of characters currently used from mData + */ + int mSize; + + public Builder(TreeSet wordSet) + { + int wordCount = wordSet.size(); + + mWords = new String[wordCount]; + wordSet.toArray(mWords); + + /* 03-Jan-2006, TSa: Special case: just one entry; if so, + * let's leave char array null, and just have the String + * array with one entry. + */ + if (wordCount < 2) { + if (wordCount == 0) { + throw new IllegalArgumentException(); // not legal + } + mData = null; + } else { + /* Let's guess approximate size we should need, assuming + * average word length of 6 characters, overhead matching + * compression (ie. about 1-to-1 ratio overall) + */ + int size = wordCount * 6; + if (size < 256) { + size = 256; + } + mData = new char[size]; + } + } + + /** + * @return Raw character data that contains compressed structure + * of the word set + */ + public WordResolver construct() + { + char[] result; + + /* 03-Jan-2006, TSa: Special case: just one entry; if so, + * let's leave char array null, and just have the String + * array with one entry. + */ + if (mData == null) { + result = null; + } else { + constructBranch(0, 0, mWords.length); + + // Too big? + if (mSize > NEGATIVE_OFFSET) { + return null; + } + + result = new char[mSize]; + System.arraycopy(mData, 0, result, 0, mSize); + } + + return new WordResolver(mWords, result); + } + + /** + * Method that is called recursively to build the data + * representation for a branch, ie. part of word set tree + * that still has more than one ending + * + * @param charIndex Index of the character in words to consider + * for this round + * @param start Index of the first word to be processed + * @param end Index of the word after last word to be processed + * (so that number of words is end - start - 1 + */ + @SuppressWarnings("cast") + private void constructBranch(int charIndex, int start, int end) + { + // If more than one entry, need to divide into groups + + // First, need to add placeholder for branch count: + if (mSize >= mData.length) { + expand(1); + } + mData[mSize++] = 0; // placeholder! + /* structStart will point to second char of first entry + * (which will temporarily have entry count, eventually 'link' + * to continuation) + */ + int structStart = mSize + 1; + int groupCount = 0; + int groupStart = start; + String[] words = mWords; + boolean gotRunt; + + /* First thing we need to do is a special check for the + * first entry -- it may be "runt" word, one that has no + * more chars but also has a longer version ("id" vs. + * "identifier"). If so, it needs to be marked; this is done + * by adding a special entry before other entries (since such + * entry would always be ordered first alphabetically) + */ + if (words[groupStart].length() == charIndex) { // yup, got one: + if ((mSize + 2) > mData.length) { + expand(2); + } + /* First null marks the "missing" char (or, end-of-word); + * and then we need the index + */ + mData[mSize++] = CHAR_NULL; + mData[mSize++] = (char) (NEGATIVE_OFFSET + groupStart); + + // Ok, let's then ignore that entry + ++groupStart; + ++groupCount; + gotRunt = true; + } else { + gotRunt = false; + } + + // Ok, then, let's find the ('real') groupings: + while (groupStart < end) { + // Inner loop, let's find the group: + char c = words[groupStart].charAt(charIndex); + int j = groupStart+1; + while (j < end && words[j].charAt(charIndex) == c) { + ++j; + } + /* Ok, let's store the char in there, along with count; + * count will be needed in second, and will then get + * overwritten with actual data later on + */ + if ((mSize + 2) > mData.length) { + expand(2); + } + mData[mSize++] = c; + mData[mSize++] = (char) (j - groupStart); // entries in group + groupStart = j; + ++groupCount; + } + + /* Ok, groups found; need to loop through them, recursively + * calling branch and/or leaf methods + */ + // first let's output the header, ie. group count: + mData[structStart-2] = (char) groupCount; + groupStart = start; + + // Do we have the "runt" to skip? + if (gotRunt) { + structStart += 2; + ++groupStart; + } + + int structEnd = mSize; + ++charIndex; + for (; structStart < structEnd; structStart += 2) { + groupCount = (int) mData[structStart]; // no sign expansion, is ok + /* Ok, count gotten, can either create a branch (if more than + * one entry) or leaf (just one entry) + */ + if (groupCount == 1) { + mData[structStart] = (char) (NEGATIVE_OFFSET + groupStart); + } else { + mData[structStart] = (char) mSize; + constructBranch(charIndex, groupStart, + groupStart + groupCount); + } + groupStart += groupCount; + } + + // done! + } + + private char[] expand(int needSpace) + { + char[] old = mData; + int len = old.length; + int newSize = len + ((len < 4096) ? len : (len >> 1)); + + /* Let's verify we get enough; should always be true but + * better safe than sorry + */ + if (newSize < (mSize + needSpace)) { + newSize = mSize + needSpace + 64; + } + mData = new char[newSize]; + System.arraycopy(old, 0, mData, 0, len); + return mData; + } + } + + /* + //////////////////////////////////////////////////// + // Simple test driver, useful for debugging + // (uncomment if needed -- commented out so it won't + // affect coverage testing) + //////////////////////////////////////////////////// + */ + + /* + public static void main(String[] args) + { + if (args.length < 2) { + System.err.println("Usage: "+WordResolver.class+" word1 [word2] ... [wordN] keyword"); + System.exit(1); + } + String key = args[args.length-1]; + TreeSet words = new TreeSet(); + for (int i = 0; i < args.length-1; ++i) { + words.add(args[i]); + } + + WordResolver set = WordResolver.constructInstance(words); + +//outputData(set.mData); + + // Ok, and then the test! + char[] keyA = new char[key.length() + 4]; + key.getChars(0, key.length(), keyA, 2); + //System.out.println("Word '"+key+"' found via array search: "+WordResolver.find(data, keyA, 2, key.length() + 2)); + System.out.println("Word '"+key+"' found via array search: "+set.find(keyA, 2, key.length() + 2)); + } + + static void outputData(char[] data) + { + for (int i = 0; i < data.length; ++i) { + char c = data[i]; + System.out.print(Integer.toHexString(i)+" ["+Integer.toHexString(c)+"]"); + if (c > 32 && c <= 127) { // printable char (letter) + System.out.println(" -> '"+c+"'"); + } else { + System.out.println(); + } + } + } + */ +} diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/util/WordSet.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/util/WordSet.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/util/WordSet.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/util/WordSet.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,479 @@ +package com.ctc.wstx.util; + +import java.util.*; + +/** + * An efficient (both memory and time) implementation of a Set used to + * verify that a given + * word is contained within the set. The general usage pattern is expected + * to be such that most checks are positive, ie. that the word indeed + * is contained in the set. + *

+ * Performance of the set is comparable to that of {@link java.util.TreeSet} + * for Strings, ie. 2-3x slower than {@link java.util.HashSet} when + * using pre-constructed Strings. This is generally result of algorithmic + * complexity of structures; Word and Tree sets are roughly logarithmic + * to the whole data, whereas Hash set is linear to the length of key. + * However: + *

    + *
  • WordSet can use char arrays as keys, without constructing Strings. + * In cases where there is no (need for) Strings, WordSet seems to be + * about twice as fast, even without considering additional GC caused + * by temporary String instances. + *
  • + *
  • WordSet is more compact in its memory presentation; if Strings are + * shared its size is comparable to optimally filled HashSet, and if + * no such Strings exists, its much more compact (relatively speaking) + *
  • + *
+ *

+ * Although this is an efficient set for specific set of usage patterns, + * one restriction is that the full set of words to include has to be + * known before constructing the set. Also, the size of the set is + * limited to total word content of about 20k characters; factory method + * does verify the limit and indicates if an instance can not be created. + */ +public final class WordSet +{ + final static char CHAR_NULL = (char) 0; + + /** + * Offset added to numbers to mark 'negative' numbers. Asymmetric, + * since range of negative markers needed is smaller than positive + * numbers... + */ + final static int NEGATIVE_OFFSET = 0xC000; + + /** + * This is actually just a guess; but in general linear search should + * be faster for short sequences (definitely for 4 or less; maybe up + * to 8 or less?) + */ + final static int MIN_BINARY_SEARCH = 7; + + /** + * Compressed presentation of the word set. + */ + final char[] mData; + + /* + //////////////////////////////////////////////// + // Life-cycle + //////////////////////////////////////////////// + */ + + private WordSet(char[] data) { + mData = data; + } + + public static WordSet constructSet(TreeSet wordSet) + { + return new WordSet(new Builder(wordSet).construct()); + } + + public static char[] constructRaw(TreeSet wordSet) + { + return new Builder(wordSet).construct(); + } + + /* + //////////////////////////////////////////////// + // Public API + //////////////////////////////////////////////// + */ + + public boolean contains(char[] buf, int start, int end) { + return contains(mData, buf, start, end); + } + + @SuppressWarnings("cast") + public static boolean contains(char[] data, char[] str, int start, int end) + { + int ptr = 0; // pointer to compressed set data + + main_loop: + do { + int left = end-start; + + // End of input String? Need to have the run entry: + if (left == 0) { + return (data[ptr+1] == CHAR_NULL); + } + + int count = data[ptr++]; + + // Nope, but do we have an end marker? + if (count >= NEGATIVE_OFFSET) { + // How many chars do we need to have left to match? + int expCount = count - NEGATIVE_OFFSET; + if (left != expCount) { + return false; + } + while (start < end) { + if (data[ptr] != str[start]) { + return false; + } + ++ptr; + ++start; + } + return true; + } + + // No, need to find the branch to follow, if any + char c = str[start++]; + + // Linear or binary search? + if (count < MIN_BINARY_SEARCH) { + // always at least two branches; never less + if (data[ptr] == c) { + ptr = (int) data[ptr+1]; + continue main_loop; + } + if (data[ptr+2] == c) { + ptr = (int) data[ptr+3]; + continue main_loop; + } + int branchEnd = ptr + (count << 1); + // Starts from entry #3, if such exists + for (ptr += 4; ptr < branchEnd; ptr += 2) { + if (data[ptr] == c) { + ptr = (int) data[ptr+1]; + continue main_loop; + } + } + return false; // No match! + } + + { // Ok, binary search: + int low = 0; + int high = count-1; + int mid; + + while (low <= high) { + mid = (low + high) >> 1; + int ix = ptr + (mid << 1); + int diff = data[ix] - c; + if (diff > 0) { // char was 'higher', need to go down + high = mid-1; + } else if (diff < 0) { // lower, need to go up + low = mid+1; + } else { // match + ptr = (int) data[ix+1]; + continue main_loop; + } + } + } + + // If we fall here, no match! + return false; + + } while (ptr != 0); + + // If we reached an end state, must match the length + return (start == end); + } + + public boolean contains(String str) { + return contains(mData, str); + } + + @SuppressWarnings("cast") + public static boolean contains(char[] data, String str) + { + // Let's use same vars as array-based code, to allow cut'n pasting + int ptr = 0; // pointer to compressed set data + int start = 0; + int end = str.length(); + + main_loop: + do { + int left = end-start; + + // End of input String? Need to have the run entry: + if (left == 0) { + return (data[ptr+1] == CHAR_NULL); + } + + int count = data[ptr++]; + + // Nope, but do we have an end marker? + if (count >= NEGATIVE_OFFSET) { + // How many chars do we need to have left to match? + int expCount = count - NEGATIVE_OFFSET; + if (left != expCount) { + return false; + } + while (start < end) { + if (data[ptr] != str.charAt(start)) { + return false; + } + ++ptr; + ++start; + } + return true; + } + + // No, need to find the branch to follow, if any + char c = str.charAt(start++); + + // Linear or binary search? + if (count < MIN_BINARY_SEARCH) { + // always at least two branches; never less + if (data[ptr] == c) { + ptr = (int) data[ptr+1]; + continue main_loop; + } + if (data[ptr+2] == c) { + ptr = (int) data[ptr+3]; + continue main_loop; + } + int branchEnd = ptr + (count << 1); + // Starts from entry #3, if such exists + for (ptr += 4; ptr < branchEnd; ptr += 2) { + if (data[ptr] == c) { + ptr = (int) data[ptr+1]; + continue main_loop; + } + } + return false; // No match! + } + + { // Ok, binary search: + int low = 0; + int high = count-1; + int mid; + + while (low <= high) { + mid = (low + high) >> 1; + int ix = ptr + (mid << 1); + int diff = data[ix] - c; + if (diff > 0) { // char was 'higher', need to go down + high = mid-1; + } else if (diff < 0) { // lower, need to go up + low = mid+1; + } else { // match + ptr = (int) data[ix+1]; + continue main_loop; + } + } + } + + // If we fall here, no match! + return false; + + } while (ptr != 0); + + // If we reached an end state, must match the length + return (start == end); + } + + /* + //////////////////////////////////////////////// + // Private methods + //////////////////////////////////////////////// + */ + + /* + //////////////////////////////////////////////// + // Helper classes + //////////////////////////////////////////////// + */ + + private final static class Builder + { + final String[] mWords; + + char[] mData; + + /** + * Number of characters currently used from mData + */ + int mSize; + + public Builder(TreeSet wordSet) { + int wordCount = wordSet.size(); + mWords = new String[wordCount]; + wordSet.toArray(mWords); + + /* Let's guess approximate size we should need, assuming + * average word length of 6 characters, and 100% overhead + * in structure: + */ + int size = wordCount * 12; + if (size < 256) { + size = 256; + } + mData = new char[size]; + } + + /** + * @return Raw character data that contains compressed structure + * of the word set + */ + public char[] construct() + { +// Uncomment if you need to debug array-out-of-bound probs +//try { + // Let's check degenerate case of 1 word: + if (mWords.length == 1) { + constructLeaf(0, 0); + } else { + constructBranch(0, 0, mWords.length); + } +//} catch (Throwable t) { System.err.println("Error: "+t); } + + char[] result = new char[mSize]; + System.arraycopy(mData, 0, result, 0, mSize); + return result; + } + + /** + * Method that is called recursively to build the data + * representation for a branch, ie. part of word set tree + * that still has more than one ending + * + * @param charIndex Index of the character in words to consider + * for this round + * @param start Index of the first word to be processed + * @param end Index of the word after last word to be processed + * (so that number of words is end - start - 1 + */ + @SuppressWarnings("cast") + private void constructBranch(int charIndex, int start, int end) + { + // If more than one entry, need to divide into groups + + // First, need to add placeholder for branch count: + if (mSize >= mData.length) { + expand(1); + } + mData[mSize++] = 0; // placeholder! + /* structStart will point to second char of first entry + * (which will temporarily have entry count, eventually 'link' + * to continuation) + */ + int structStart = mSize + 1; + int groupCount = 0; + int groupStart = start; + String[] words = mWords; + + /* First thing we need to do is a special check for the + * first entry -- it may be "runt" word, one that has no + * more chars but also has a longer version ("id" vs. + * "identifier"). If there is such a word, it'll always + * be first in alphabetic ordering: + */ + if (words[groupStart].length() == charIndex) { // yup, got one: + if ((mSize + 2) > mData.length) { + expand(2); + } + /* Nulls mark both imaginary branching null char and + * "missing link" to the rest + */ + mData[mSize++] = CHAR_NULL; + mData[mSize++] = CHAR_NULL; + + // Ok, let's then ignore that entry + ++groupStart; + ++groupCount; + } + + // Ok, then, let's find the ('real') groupings: + while (groupStart < end) { + // Inner loop, let's find the group: + char c = words[groupStart].charAt(charIndex); + int j = groupStart+1; + while (j < end && words[j].charAt(charIndex) == c) { + ++j; + } + /* Ok, let's store the char in there, along with count; + * count will be needed in second, and will then get + * overwritten with actual data later on + */ + if ((mSize + 2) > mData.length) { + expand(2); + } + mData[mSize++] = c; + mData[mSize++] = (char) (j - groupStart); // entries in group + groupStart = j; + ++groupCount; + } + + /* Ok, groups found; need to loop through them, recursively + * calling branch and/or leaf methods + */ + // first let's output the header, ie. group count: + mData[structStart-2] = (char) groupCount; + groupStart = start; + + // Do we have the "runt" to skip? + if (mData[structStart] == CHAR_NULL) { + structStart += 2; + ++groupStart; + } + + int structEnd = mSize; + ++charIndex; + for (; structStart < structEnd; structStart += 2) { + groupCount = (int) mData[structStart]; // no sign expansion, is ok + // Ok, count gotten, can now put the 'link' (pointer) in there + mData[structStart] = (char) mSize; + if (groupCount == 1) { + /* One optimization; if it'd lead to a single runt + * entry, we can just add 'null' link: + */ + String word = words[groupStart]; + if (word.length() == charIndex) { + mData[structStart] = CHAR_NULL; + } else { // otherwise, let's just create end state: + constructLeaf(charIndex, groupStart); + } + } else { + constructBranch(charIndex, groupStart, + groupStart + groupCount); + } + groupStart += groupCount; + } + + // done! + } + + /** + * Method called to add leaf entry to word set; basically + * "here is the rest of the only matching word" + */ + private void constructLeaf(int charIndex, int wordIndex) + { + String word = mWords[wordIndex]; + int len = word.length(); + char[] data = mData; + + // need room for 1 header char, rest of the word + if ((mSize + len + 1) >= data.length) { + data = expand(len+1); + } + + data[mSize++] = (char) (NEGATIVE_OFFSET + (len - charIndex)); + for (; charIndex < len; ++charIndex) { + data[mSize++] = word.charAt(charIndex); + } + } + + private char[] expand(int needSpace) + { + char[] old = mData; + int len = old.length; + int newSize = len + ((len < 4096) ? len : (len >> 1)); + + /* Let's verify we get enough; should always be true but + * better safe than sorry + */ + if (newSize < (mSize + needSpace)) { + newSize = mSize + needSpace + 64; + } + mData = new char[newSize]; + System.arraycopy(old, 0, mData, 0, len); + return mData; + } + } +} diff -Nru libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/util/XmlChars.java libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/util/XmlChars.java --- libwoodstox-java-4.1.3/src/main/java/com/ctc/wstx/util/XmlChars.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/java/com/ctc/wstx/util/XmlChars.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,533 @@ +package com.ctc.wstx.util; + +/** + * Simple utility class that encapsulates logic of determining validity + * of characters outside basic 7-bit range of Unicode, for XML 1.0 + */ +public final class XmlChars +{ + // We don't need full 64k bits... (0x80 - 0x312C) / 32. But to + // simplify things, let's just include first 0x80 entries in there etc + final static int SIZE = (0x3140 >> 5); // 32 bits per int + + final static int[] sXml10StartChars = new int[SIZE]; + static { + SETBITS(sXml10StartChars, 0xC0, 0xD6); + SETBITS(sXml10StartChars, 0xD8, 0xF6); + SETBITS(sXml10StartChars, 0xF8, 0xFF); + SETBITS(sXml10StartChars, 0x100, 0x131); + SETBITS(sXml10StartChars, 0x134, 0x13e); + SETBITS(sXml10StartChars, 0x141, 0x148); + SETBITS(sXml10StartChars, 0x14a, 0x17e); + SETBITS(sXml10StartChars, 0x180, 0x1c3); + SETBITS(sXml10StartChars, 0x1cd, 0x1f0); + SETBITS(sXml10StartChars, 0x1f4, 0x1f5); + SETBITS(sXml10StartChars, 0x1fa, 0x217); + SETBITS(sXml10StartChars, 0x250, 0x2a8); + SETBITS(sXml10StartChars, 0x2bb, 0x2c1); + SETBITS(sXml10StartChars, 0x386); + SETBITS(sXml10StartChars, 0x388, 0x38a); + SETBITS(sXml10StartChars, 0x38c); + SETBITS(sXml10StartChars, 0x38e, 0x3a1); + SETBITS(sXml10StartChars, 0x3a3, 0x3ce); + SETBITS(sXml10StartChars, 0x3d0, 0x3d6); + SETBITS(sXml10StartChars, 0x3da); + SETBITS(sXml10StartChars, 0x3dc); + SETBITS(sXml10StartChars, 0x3de); + SETBITS(sXml10StartChars, 0x3e0); + SETBITS(sXml10StartChars, 0x3e2, 0x3f3); + SETBITS(sXml10StartChars, 0x401, 0x40c); + SETBITS(sXml10StartChars, 0x40e, 0x44f); + SETBITS(sXml10StartChars, 0x451, 0x45c); + SETBITS(sXml10StartChars, 0x45e, 0x481); + SETBITS(sXml10StartChars, 0x490, 0x4c4); + SETBITS(sXml10StartChars, 0x4c7, 0x4c8); + SETBITS(sXml10StartChars, 0x4cb, 0x4cc); + SETBITS(sXml10StartChars, 0x4d0, 0x4eb); + SETBITS(sXml10StartChars, 0x4ee, 0x4f5); + SETBITS(sXml10StartChars, 0x4f8, 0x4f9); + + SETBITS(sXml10StartChars, 0x531, 0x556); + SETBITS(sXml10StartChars, 0x559); + SETBITS(sXml10StartChars, 0x561, 0x586); + SETBITS(sXml10StartChars, 0x5d0, 0x5ea); + SETBITS(sXml10StartChars, 0x5f0, 0x5f2); + SETBITS(sXml10StartChars, 0x621, 0x63a); + SETBITS(sXml10StartChars, 0x641, 0x64a); + SETBITS(sXml10StartChars, 0x671, 0x6b7); + SETBITS(sXml10StartChars, 0x6ba, 0x6be); + SETBITS(sXml10StartChars, 0x6c0, 0x6ce); + SETBITS(sXml10StartChars, 0x6d0, 0x6d3); + SETBITS(sXml10StartChars, 0x6d5); + + SETBITS(sXml10StartChars, 0x6e5, 0x6e6); + SETBITS(sXml10StartChars, 0x905, 0x939); + SETBITS(sXml10StartChars, 0x93d); + SETBITS(sXml10StartChars, 0x958, 0x961); + SETBITS(sXml10StartChars, 0x985, 0x98c); + SETBITS(sXml10StartChars, 0x98f, 0x990); + SETBITS(sXml10StartChars, 0x993, 0x9a8); + SETBITS(sXml10StartChars, 0x9aa, 0x9b0); + SETBITS(sXml10StartChars, 0x9b2); + SETBITS(sXml10StartChars, 0x9b6, 0x9b9); + SETBITS(sXml10StartChars, 0x9dc); + SETBITS(sXml10StartChars, 0x9dd); + SETBITS(sXml10StartChars, 0x9df, 0x9e1); + SETBITS(sXml10StartChars, 0x9f0); SETBITS(sXml10StartChars, 0x9f1); + SETBITS(sXml10StartChars, 0xA05, 0xA0A); + SETBITS(sXml10StartChars, 0xA0F); SETBITS(sXml10StartChars, 0xA10); + SETBITS(sXml10StartChars, 0xA13, 0xA28); + SETBITS(sXml10StartChars, 0xA2A, 0xA30); + SETBITS(sXml10StartChars, 0xA32); SETBITS(sXml10StartChars, 0xA33); + SETBITS(sXml10StartChars, 0xA35); SETBITS(sXml10StartChars, 0xA36); + SETBITS(sXml10StartChars, 0xA38); SETBITS(sXml10StartChars, 0xA39); + SETBITS(sXml10StartChars, 0xA59, 0xA5C); + SETBITS(sXml10StartChars, 0xA5E); + SETBITS(sXml10StartChars, 0xA72, 0xA74); + SETBITS(sXml10StartChars, 0xA85, 0xA8B); + SETBITS(sXml10StartChars, 0xA8D); + SETBITS(sXml10StartChars, 0xA8F, 0xA91); + SETBITS(sXml10StartChars, 0xA93, 0xAA8); + SETBITS(sXml10StartChars, 0xAAA, 0xAB0); + SETBITS(sXml10StartChars, 0xAB2, 0xAB3); + SETBITS(sXml10StartChars, 0xAB5, 0xAB9); + SETBITS(sXml10StartChars, 0xABD); + SETBITS(sXml10StartChars, 0xAE0); + SETBITS(sXml10StartChars, 0xB05, 0xB0C); + SETBITS(sXml10StartChars, 0xB0F); SETBITS(sXml10StartChars, 0xB10); + SETBITS(sXml10StartChars, 0xB13, 0xB28); + + SETBITS(sXml10StartChars, 0xB2A, 0xB30); + SETBITS(sXml10StartChars, 0xB32); SETBITS(sXml10StartChars, 0xB33); + SETBITS(sXml10StartChars, 0xB36, 0xB39); + SETBITS(sXml10StartChars, 0xB3D); + SETBITS(sXml10StartChars, 0xB5C); SETBITS(sXml10StartChars, 0xB5D); + SETBITS(sXml10StartChars, 0xB5F, 0xB61); + SETBITS(sXml10StartChars, 0xB85, 0xB8A); + SETBITS(sXml10StartChars, 0xB8E, 0xB90); + + SETBITS(sXml10StartChars, 0xB92, 0xB95); + SETBITS(sXml10StartChars, 0xB99, 0xB9A); + SETBITS(sXml10StartChars, 0xB9C); + SETBITS(sXml10StartChars, 0xB9E); SETBITS(sXml10StartChars, 0xB9F); + SETBITS(sXml10StartChars, 0xBA3); SETBITS(sXml10StartChars, 0xBA4); + SETBITS(sXml10StartChars, 0xBA8, 0xBAA); + SETBITS(sXml10StartChars, 0xBAE, 0xBB5); + SETBITS(sXml10StartChars, 0xBB7, 0xBB9); + SETBITS(sXml10StartChars, 0xC05, 0xC0C); + SETBITS(sXml10StartChars, 0xC0E, 0xC10); + + SETBITS(sXml10StartChars, 0xC12, 0xC28); + SETBITS(sXml10StartChars, 0xC2A, 0xC33); + SETBITS(sXml10StartChars, 0xC35, 0xC39); + SETBITS(sXml10StartChars, 0xC60); SETBITS(sXml10StartChars, 0xC61); + SETBITS(sXml10StartChars, 0xC85, 0xC8C); + SETBITS(sXml10StartChars, 0xC8E, 0xC90); + SETBITS(sXml10StartChars, 0xC92, 0xCA8); + SETBITS(sXml10StartChars, 0xCAA, 0xCB3); + SETBITS(sXml10StartChars, 0xCB5, 0xCB9); + SETBITS(sXml10StartChars, 0xCDE); + SETBITS(sXml10StartChars, 0xCE0); SETBITS(sXml10StartChars, 0xCE1); + SETBITS(sXml10StartChars, 0xD05, 0xD0C); + SETBITS(sXml10StartChars, 0xD0E, 0xD10); + SETBITS(sXml10StartChars, 0xD12, 0xD28); + SETBITS(sXml10StartChars, 0xD2A, 0xD39); + SETBITS(sXml10StartChars, 0xD60); SETBITS(sXml10StartChars, 0xD61); + SETBITS(sXml10StartChars, 0xE01, 0xE2E); + SETBITS(sXml10StartChars, 0xE30); + SETBITS(sXml10StartChars, 0xE32); SETBITS(sXml10StartChars, 0xE33); + SETBITS(sXml10StartChars, 0xE40, 0xE45); + SETBITS(sXml10StartChars, 0xE81); SETBITS(sXml10StartChars, 0xE82); + SETBITS(sXml10StartChars, 0xE84); + SETBITS(sXml10StartChars, 0xE87); SETBITS(sXml10StartChars, 0xE88); + SETBITS(sXml10StartChars, 0xE8A); SETBITS(sXml10StartChars, 0xE8D); + SETBITS(sXml10StartChars, 0xE94, 0xE97); + SETBITS(sXml10StartChars, 0xE99, 0xE9F); + SETBITS(sXml10StartChars, 0xEA1, 0xEA3); + SETBITS(sXml10StartChars, 0xEA5); SETBITS(sXml10StartChars, 0xEA7); + SETBITS(sXml10StartChars, 0xEAA); SETBITS(sXml10StartChars, 0xEAB); + SETBITS(sXml10StartChars, 0xEAD); SETBITS(sXml10StartChars, 0xEAE); + SETBITS(sXml10StartChars, 0xEB0); + SETBITS(sXml10StartChars, 0xEB2); SETBITS(sXml10StartChars, 0xEB3); + SETBITS(sXml10StartChars, 0xEBD); + + SETBITS(sXml10StartChars, 0xEC0, 0xEC4); + SETBITS(sXml10StartChars, 0xF40, 0xF47); + SETBITS(sXml10StartChars, 0xF49, 0xF69); + SETBITS(sXml10StartChars, 0x10a0, 0x10c5); + SETBITS(sXml10StartChars, 0x10d0, 0x10f6); + SETBITS(sXml10StartChars, 0x1100); + SETBITS(sXml10StartChars, 0x1102, 0x1103); + SETBITS(sXml10StartChars, 0x1105, 0x1107); + SETBITS(sXml10StartChars, 0x1109); + SETBITS(sXml10StartChars, 0x110b, 0x110c); + SETBITS(sXml10StartChars, 0x110e, 0x1112); + SETBITS(sXml10StartChars, 0x113c); + SETBITS(sXml10StartChars, 0x113e); + SETBITS(sXml10StartChars, 0x1140); + SETBITS(sXml10StartChars, 0x114c); + SETBITS(sXml10StartChars, 0x114e); + SETBITS(sXml10StartChars, 0x1150); + SETBITS(sXml10StartChars, 0x1154, 0x1155); + SETBITS(sXml10StartChars, 0x1159); + SETBITS(sXml10StartChars, 0x115f, 0x1161); + SETBITS(sXml10StartChars, 0x1163); + SETBITS(sXml10StartChars, 0x1165); + SETBITS(sXml10StartChars, 0x1167); + SETBITS(sXml10StartChars, 0x1169); + SETBITS(sXml10StartChars, 0x116d, 0x116e); + SETBITS(sXml10StartChars, 0x1172, 0x1173); + SETBITS(sXml10StartChars, 0x1175); + SETBITS(sXml10StartChars, 0x119e); + SETBITS(sXml10StartChars, 0x11a8); + SETBITS(sXml10StartChars, 0x11ab); + SETBITS(sXml10StartChars, 0x11ae, 0x11af); + SETBITS(sXml10StartChars, 0x11b7, 0x11b8); + SETBITS(sXml10StartChars, 0x11ba); + SETBITS(sXml10StartChars, 0x11bc, 0x11c2); + SETBITS(sXml10StartChars, 0x11eb); + SETBITS(sXml10StartChars, 0x11f0); + SETBITS(sXml10StartChars, 0x11f9); + SETBITS(sXml10StartChars, 0x1e00, 0x1e9b); + SETBITS(sXml10StartChars, 0x1ea0, 0x1ef9); + SETBITS(sXml10StartChars, 0x1f00, 0x1f15); + SETBITS(sXml10StartChars, 0x1f18, 0x1f1d); + SETBITS(sXml10StartChars, 0x1f20, 0x1f45); + SETBITS(sXml10StartChars, 0x1f48, 0x1f4d); + SETBITS(sXml10StartChars, 0x1f50, 0x1f57); + SETBITS(sXml10StartChars, 0x1f59); + SETBITS(sXml10StartChars, 0x1f5b); + SETBITS(sXml10StartChars, 0x1f5d); + SETBITS(sXml10StartChars, 0x1f5f, 0x1f7d); + SETBITS(sXml10StartChars, 0x1f80, 0x1fb4); + SETBITS(sXml10StartChars, 0x1fb6, 0x1fbc); + SETBITS(sXml10StartChars, 0x1fbe); + SETBITS(sXml10StartChars, 0x1fc2, 0x1fc4); + SETBITS(sXml10StartChars, 0x1fc6, 0x1fcc); + SETBITS(sXml10StartChars, 0x1fd0, 0x1fd3); + SETBITS(sXml10StartChars, 0x1fd6, 0x1fdb); + SETBITS(sXml10StartChars, 0x1fe0, 0x1fec); + SETBITS(sXml10StartChars, 0x1ff2, 0x1ff4); + SETBITS(sXml10StartChars, 0x1ff6, 0x1ffc); + SETBITS(sXml10StartChars, 0x2126); + SETBITS(sXml10StartChars, 0x212a, 0x212b); + SETBITS(sXml10StartChars, 0x212e); + SETBITS(sXml10StartChars, 0x2180, 0x2182); + SETBITS(sXml10StartChars, 0x3041, 0x3094); + SETBITS(sXml10StartChars, 0x30a1, 0x30fa); + SETBITS(sXml10StartChars, 0x3105, 0x312c); + // note: AC00 - D7A3 handled separately + + // [86] Ideographic (but note: > 0x312c handled separately) + SETBITS(sXml10StartChars, 0x3007); + SETBITS(sXml10StartChars, 0x3021, 0x3029); + } + + final static int[] sXml10Chars = new int[SIZE]; + static { + // Let's start with all valid start chars: + System.arraycopy(sXml10StartChars, 0, sXml10Chars, 0, SIZE); + + // [87] CombiningChar ::= + SETBITS(sXml10Chars, 0x300, 0x345); + SETBITS(sXml10Chars, 0x360, 0x361); + SETBITS(sXml10Chars, 0x483, 0x486); + SETBITS(sXml10Chars, 0x591, 0x5a1); + SETBITS(sXml10Chars, 0x5a3, 0x5b9); + SETBITS(sXml10Chars, 0x5bb, 0x5bd); + SETBITS(sXml10Chars, 0x5bf); + + SETBITS(sXml10Chars, 0x5c1, 0x5c2); + SETBITS(sXml10Chars, 0x5c4); + SETBITS(sXml10Chars, 0x64b, 0x652); + SETBITS(sXml10Chars, 0x670); + SETBITS(sXml10Chars, 0x6d6, 0x6dc); + SETBITS(sXml10Chars, 0x6dd, 0x6df); + SETBITS(sXml10Chars, 0x6e0, 0x6e4); + SETBITS(sXml10Chars, 0x6e7, 0x6e8); + SETBITS(sXml10Chars, 0x6ea, 0x6ed); + + SETBITS(sXml10Chars, 0x901, 0x903); + SETBITS(sXml10Chars, 0x93c); + SETBITS(sXml10Chars, 0x93e, 0x94c); + SETBITS(sXml10Chars, 0x94d); + SETBITS(sXml10Chars, 0x951, 0x954); + SETBITS(sXml10Chars, 0x962); SETBITS(sXml10Chars, 0x963); + SETBITS(sXml10Chars, 0x981, 0x983); + SETBITS(sXml10Chars, 0x9bc); + SETBITS(sXml10Chars, 0x9be); SETBITS(sXml10Chars, 0x9bf); + SETBITS(sXml10Chars, 0x9c0, 0x9c4); + SETBITS(sXml10Chars, 0x9c7); SETBITS(sXml10Chars, 0x9c8); + SETBITS(sXml10Chars, 0x9cb, 0x9cd); + SETBITS(sXml10Chars, 0x9d7); + SETBITS(sXml10Chars, 0x9e2); SETBITS(sXml10Chars, 0x9e3); + SETBITS(sXml10Chars, 0xA02); + SETBITS(sXml10Chars, 0xA3C); + SETBITS(sXml10Chars, 0xA3E); SETBITS(sXml10Chars, 0xA3F); + SETBITS(sXml10Chars, 0xA40, 0xA42); + SETBITS(sXml10Chars, 0xA47); SETBITS(sXml10Chars, 0xA48); + SETBITS(sXml10Chars, 0xA4B, 0xA4D); + SETBITS(sXml10Chars, 0xA70); SETBITS(sXml10Chars, 0xA71); + SETBITS(sXml10Chars, 0xA81, 0xA83); + SETBITS(sXml10Chars, 0xABC); + SETBITS(sXml10Chars, 0xABE, 0xAC5); + SETBITS(sXml10Chars, 0xAC7, 0xAC9); + SETBITS(sXml10Chars, 0xACB, 0xACD); + SETBITS(sXml10Chars, 0xB01, 0xB03); + SETBITS(sXml10Chars, 0xB3C); + SETBITS(sXml10Chars, 0xB3E, 0xB43); + SETBITS(sXml10Chars, 0xB47); SETBITS(sXml10Chars, 0xB48); + SETBITS(sXml10Chars, 0xB4B, 0xB4D); + SETBITS(sXml10Chars, 0xB56); SETBITS(sXml10Chars, 0xB57); + SETBITS(sXml10Chars, 0xB82); SETBITS(sXml10Chars, 0xB83); + SETBITS(sXml10Chars, 0xBBE, 0xBC2); + SETBITS(sXml10Chars, 0xBC6, 0xBC8); + SETBITS(sXml10Chars, 0xBCA, 0xBCD); + SETBITS(sXml10Chars, 0xBD7); + SETBITS(sXml10Chars, 0xC01, 0xC03); + SETBITS(sXml10Chars, 0xC3E, 0xC44); + SETBITS(sXml10Chars, 0xC46, 0xC48); + SETBITS(sXml10Chars, 0xC4A, 0xC4D); + SETBITS(sXml10Chars, 0xC55, 0xC56); + SETBITS(sXml10Chars, 0xC82, 0xC83); + SETBITS(sXml10Chars, 0xCBE, 0xCC4); + SETBITS(sXml10Chars, 0xCC6, 0xCC8); + SETBITS(sXml10Chars, 0xCCA, 0xCCD); + SETBITS(sXml10Chars, 0xCD5, 0xCD6); + SETBITS(sXml10Chars, 0xD02, 0xD03); + SETBITS(sXml10Chars, 0xD3E, 0xD43); + SETBITS(sXml10Chars, 0xD46, 0xD48); + SETBITS(sXml10Chars, 0xD4A, 0xD4D); + SETBITS(sXml10Chars, 0xD57); + SETBITS(sXml10Chars, 0xE31); + SETBITS(sXml10Chars, 0xE34, 0xE3A); + SETBITS(sXml10Chars, 0xE47, 0xE4E); + SETBITS(sXml10Chars, 0xEB1); + SETBITS(sXml10Chars, 0xEB4, 0xEB9); + SETBITS(sXml10Chars, 0xEBB, 0xEBC); + SETBITS(sXml10Chars, 0xEC8, 0xECD); + SETBITS(sXml10Chars, 0xF18, 0xF19); + SETBITS(sXml10Chars, 0xF35); SETBITS(sXml10Chars, 0xF37); + SETBITS(sXml10Chars, 0xF39); + SETBITS(sXml10Chars, 0xF3E); SETBITS(sXml10Chars, 0xF3F); + SETBITS(sXml10Chars, 0xF71, 0xF84); + SETBITS(sXml10Chars, 0xF86, 0xF8B); + SETBITS(sXml10Chars, 0xF90, 0xF95); + SETBITS(sXml10Chars, 0xF97); + SETBITS(sXml10Chars, 0xF99, 0xFAD); + SETBITS(sXml10Chars, 0xFB1, 0xFB7); + SETBITS(sXml10Chars, 0xFB9); + SETBITS(sXml10Chars, 0x20D0, 0x20DC); + SETBITS(sXml10Chars, 0x20E1); + SETBITS(sXml10Chars, 0x302A, 0x302F); + SETBITS(sXml10Chars, 0x3099); SETBITS(sXml10Chars, 0x309A); + // [88] Digit: + SETBITS(sXml10Chars, 0x660, 0x669); + SETBITS(sXml10Chars, 0x6f0, 0x6f9); + SETBITS(sXml10Chars, 0x966, 0x96f); + SETBITS(sXml10Chars, 0x9e6, 0x9ef); + SETBITS(sXml10Chars, 0xa66, 0xa6f); + SETBITS(sXml10Chars, 0xae6, 0xaef); + SETBITS(sXml10Chars, 0xb66, 0xb6f); + SETBITS(sXml10Chars, 0xbe7, 0xbef); + SETBITS(sXml10Chars, 0xc66, 0xc6f); + SETBITS(sXml10Chars, 0xce6, 0xcef); + SETBITS(sXml10Chars, 0xd66, 0xd6f); + SETBITS(sXml10Chars, 0xe50, 0xe59); + SETBITS(sXml10Chars, 0xed0, 0xed9); + SETBITS(sXml10Chars, 0xf20, 0xf29); + + // [89] Extender: + SETBITS(sXml10Chars, 0xb7); + SETBITS(sXml10Chars, 0x2d0); + SETBITS(sXml10Chars, 0x2d1); + SETBITS(sXml10Chars, 0x387); + SETBITS(sXml10Chars, 0x640); + SETBITS(sXml10Chars, 0xE46); + SETBITS(sXml10Chars, 0xEC6); + SETBITS(sXml10Chars, 0x3005); + SETBITS(sXml10Chars, 0x3031, 0x3035); + SETBITS(sXml10Chars, 0x309d, 0x309e); + SETBITS(sXml10Chars, 0x30fc, 0x30fe); + } + + private XmlChars() { } + + public final static boolean is10NameStartChar(char c) + { + // First, let's deal with outliers + if (c > 0x312C) { // Most valid chars are below this.. + if (c < 0xAC00) { + return (c >= 0x4E00 && c <= 0x9FA5); // valid ideograms + } + if (c <= 0xD7A3) { // 0xAC00 - 0xD7A3, valid base chars + return true; + } + /* As to surrogate pairs... let's do the bare minimum; + * 0xD800 - 0xDBFF (high surrogate) are ok; low surrogates + * can only follow high one + */ + return (c <= 0xDBFF && c >= 0xD800); + } + // but then we'll just need to use the table... + @SuppressWarnings("cast") + int ix = (int) c; + return (sXml10StartChars[ix >> 5] & (1 << (ix & 31))) != 0; + } + + public final static boolean is10NameChar(char c) + { + // First, let's deal with outliers + if (c > 0x312C) { // Most valid chars are below this.. + if (c < 0xAC00) { + return (c >= 0x4E00 && c <= 0x9FA5); // valid ideograms + } + if (c <= 0xD7A3) { // 0xAC00 - 0xD7A3, valid base chars + return true; + } + /* As to surrogate pairs... let's do the bare minimum; + * 0xD800 - 0xDFFF (high, low surrogate) are ok (need to + * check pairing in future) + */ + return (c >= 0xD800 && c <= 0xDFFF); + } + // but then we'll just need to use the table... + @SuppressWarnings("cast") + int ix = (int) c; + return (sXml10Chars[ix >> 5] & (1 << (ix & 31))) != 0; + } + + public final static boolean is11NameStartChar(char c) + { + // Others are checked block-by-block: + if (c <= 0x2FEF) { + if (c < 0x300) { + if (c < 0x00C0) { // 8-bit ctrl chars + return false; + } + // most of the rest are fine... + return (c != 0xD7 && c != 0xF7); + } + if (c >= 0x2C00) { + // 0x2C00 - 0x2FEF are ok + return true; + } + if (c < 0x370 || c > 0x218F) { + // 0x300 - 0x36F, 0x2190 - 0x2BFF invalid + return false; + } + if (c < 0x2000) { + // 0x370 - 0x37D, 0x37F - 0x1FFF are ok + return (c != 0x37E); + } + if (c >= 0x2070) { + // 0x2070 - 0x218F are ok + return (c <= 0x218F); + } + // And finally, 0x200C - 0x200D + return (c == 0x200C || c == 0x200D); + } + + // 0x3000 and above: + if (c >= 0x3001) { + /* Hmmh, let's allow high surrogates here, without checking + * that they are properly followed... crude basic support, + * I know, but allows valid combinations, just doesn't catch + * invalid ones + */ + if (c <= 0xDBFF) { // 0x3001 - 0xD7FF (chars), + // 0xD800 - 0xDBFF (high surrogate) are ok (unlike DC00-DFFF) + return true; + } + if (c >= 0xF900 && c <= 0xFFFD) { + /* Check above removes low surrogate (since one can not + * START an identifier), and byte-order markers.. + */ + return (c <= 0xFDCF || c >= 0xFDF0); + } + } + + return false; + } + + public final static boolean is11NameChar(char c) + { + // Others are checked block-by-block: + if (c <= 0x2FEF) { + if (c < 0x2000) { // only 8-bit ctrl chars and 0x37E to filter out + return (c >= 0x00C0 && c != 0x37E) || (c == 0xB7); + } + if (c >= 0x2C00) { + // 0x100 - 0x1FFF, 0x2C00 - 0x2FEF are ok + return true; + } + if (c < 0x200C || c > 0x218F) { + // 0x2000 - 0x200B, 0x2190 - 0x2BFF invalid + return false; + } + if (c >= 0x2070) { + // 0x2070 - 0x218F are ok + return true; + } + // And finally, 0x200C - 0x200D, 0x203F - 0x2040 are ok + return (c == 0x200C || c == 0x200D + || c == 0x203F || c == 0x2040); + } + + // 0x3000 and above: + if (c >= 0x3001) { + /* Hmmh, let's allow surrogate heres, without checking that + * they have proper ordering. For non-first name chars, both are + * ok, for valid names. Crude basic support, + * I know, but allows valid combinations, just doesn't catch + * invalid ones + */ + if (c <= 0xDFFF) { // 0x3001 - 0xD7FF (chars), + // 0xD800 - 0xDFFF (high, low surrogate) are ok: + return true; + } + if (c >= 0xF900 && c <= 0xFFFD) { + /* Check above removes other invalid chars (below valid + * range), and byte-order markers (0xFFFE, 0xFFFF). + */ + return (c <= 0xFDCF || c >= 0xFDF0); + } + } + + return false; + } + + private static void SETBITS(int[] array, int start, int end) + { + int bit1 = (start & 31); + int bit2 = (end & 31); + start >>= 5; + end >>= 5; + + /* Ok; this is not perfectly optimal, but should be good enough... + * we'll only do one-by-one at the ends. + */ + if (start == end) { + for (; bit1 <= bit2; ++bit1) { + array[start] |= (1 << bit1); + } + } else { + for (int bit = bit1; bit <= 31; ++bit) { + array[start] |= (1 << bit); + } + while (++start < end) { + array[start] = -1; + } + for (int bit = 0; bit <= bit2; ++bit) { + array[end] |= (1 << bit); + } + } + } + + private static void SETBITS(int[] array, int point) { + int ix = (point >> 5); + int bit = (point & 31); + + array[ix] |= (1 << bit); + } +} diff -Nru libwoodstox-java-4.1.3/src/main/resources/META-INF/LICENSE libwoodstox-java-5.1.0/src/main/resources/META-INF/LICENSE --- libwoodstox-java-4.1.3/src/main/resources/META-INF/LICENSE 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/resources/META-INF/LICENSE 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,8 @@ +This copy of Jackson JSON processor databind module is licensed under the +Apache (Software) License, version 2.0 ("the License"). +See the License for details about distribution rights, and the +specific rights regarding derivate works. + +You may obtain a copy of the License at: + +http://www.apache.org/licenses/LICENSE-2.0 diff -Nru libwoodstox-java-4.1.3/src/main/resources/META-INF/services/javax.xml.stream.XMLEventFactory libwoodstox-java-5.1.0/src/main/resources/META-INF/services/javax.xml.stream.XMLEventFactory --- libwoodstox-java-4.1.3/src/main/resources/META-INF/services/javax.xml.stream.XMLEventFactory 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/resources/META-INF/services/javax.xml.stream.XMLEventFactory 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1 @@ +com.ctc.wstx.stax.WstxEventFactory diff -Nru libwoodstox-java-4.1.3/src/main/resources/META-INF/services/javax.xml.stream.XMLInputFactory libwoodstox-java-5.1.0/src/main/resources/META-INF/services/javax.xml.stream.XMLInputFactory --- libwoodstox-java-4.1.3/src/main/resources/META-INF/services/javax.xml.stream.XMLInputFactory 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/resources/META-INF/services/javax.xml.stream.XMLInputFactory 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1 @@ +com.ctc.wstx.stax.WstxInputFactory \ No newline at end of file diff -Nru libwoodstox-java-4.1.3/src/main/resources/META-INF/services/javax.xml.stream.XMLOutputFactory libwoodstox-java-5.1.0/src/main/resources/META-INF/services/javax.xml.stream.XMLOutputFactory --- libwoodstox-java-4.1.3/src/main/resources/META-INF/services/javax.xml.stream.XMLOutputFactory 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/resources/META-INF/services/javax.xml.stream.XMLOutputFactory 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1 @@ +com.ctc.wstx.stax.WstxOutputFactory \ No newline at end of file diff -Nru libwoodstox-java-4.1.3/src/main/resources/META-INF/services/org.codehaus.stax2.validation.XMLValidationSchemaFactory.dtd libwoodstox-java-5.1.0/src/main/resources/META-INF/services/org.codehaus.stax2.validation.XMLValidationSchemaFactory.dtd --- libwoodstox-java-4.1.3/src/main/resources/META-INF/services/org.codehaus.stax2.validation.XMLValidationSchemaFactory.dtd 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/resources/META-INF/services/org.codehaus.stax2.validation.XMLValidationSchemaFactory.dtd 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1 @@ +com.ctc.wstx.dtd.DTDSchemaFactory diff -Nru libwoodstox-java-4.1.3/src/main/resources/META-INF/services/org.codehaus.stax2.validation.XMLValidationSchemaFactory.relaxng libwoodstox-java-5.1.0/src/main/resources/META-INF/services/org.codehaus.stax2.validation.XMLValidationSchemaFactory.relaxng --- libwoodstox-java-4.1.3/src/main/resources/META-INF/services/org.codehaus.stax2.validation.XMLValidationSchemaFactory.relaxng 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/resources/META-INF/services/org.codehaus.stax2.validation.XMLValidationSchemaFactory.relaxng 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1 @@ +com.ctc.wstx.msv.RelaxNGSchemaFactory diff -Nru libwoodstox-java-4.1.3/src/main/resources/META-INF/services/org.codehaus.stax2.validation.XMLValidationSchemaFactory.w3c libwoodstox-java-5.1.0/src/main/resources/META-INF/services/org.codehaus.stax2.validation.XMLValidationSchemaFactory.w3c --- libwoodstox-java-4.1.3/src/main/resources/META-INF/services/org.codehaus.stax2.validation.XMLValidationSchemaFactory.w3c 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/main/resources/META-INF/services/org.codehaus.stax2.validation.XMLValidationSchemaFactory.w3c 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1 @@ +com.ctc.wstx.msv.W3CSchemaFactory diff -Nru libwoodstox-java-4.1.3/src/maven/stax2-api.pom libwoodstox-java-5.1.0/src/maven/stax2-api.pom --- libwoodstox-java-4.1.3/src/maven/stax2-api.pom 2012-04-24 04:38:21.000000000 +0000 +++ libwoodstox-java-5.1.0/src/maven/stax2-api.pom 1970-01-01 00:00:00.000000000 +0000 @@ -1,50 +0,0 @@ - - - - - - 4.0.0 - org.codehaus.woodstox - stax2-api - jar - Stax2 API - @VERSION@ - Stax2 API is an extension to basic Stax 1.0 API that adds significant new functionality, such as full-featured bi-direction validation interface and high-performance Typed Access API. - - - - - - http://woodstox.codehaus.org/StAX2 - - http://jira.codehaus.org/browse/WSTX - - - - - - - - javax.xml.stream - stax-api - 1.0-2 - - - - - - - The BSD License - http://www.opensource.org/licenses/bsd-license.php - repo - - - - - Codehaus - http://www.codehaus.org/ - - - diff -Nru libwoodstox-java-4.1.3/src/maven/woodstox-core-asl.pom libwoodstox-java-5.1.0/src/maven/woodstox-core-asl.pom --- libwoodstox-java-4.1.3/src/maven/woodstox-core-asl.pom 2012-04-24 04:38:21.000000000 +0000 +++ libwoodstox-java-5.1.0/src/maven/woodstox-core-asl.pom 1970-01-01 00:00:00.000000000 +0000 @@ -1,51 +0,0 @@ - - - - 4.0.0 - org.codehaus.woodstox - woodstox-core-asl - jar - Woodstox - @VERSION@ - Woodstox is a high-performance XML processor that -implements Stax (JSR-173) and SAX2 APIs - - - http://woodstox.codehaus.org - http://jira.codehaus.org/browse/WSTX - - - - - - javax.xml.stream - stax-api - 1.0-2 - - - - org.codehaus.woodstox - stax2-api - @REQ_STAX2_VERSION@ - - - - - - - The Apache Software License, Version 2.0 - http://www.apache.org/licenses/LICENSE-2.0.txt - repo - - - - - Codehaus - http://www.codehaus.org/ - - - diff -Nru libwoodstox-java-4.1.3/src/maven/woodstox-core-lgpl.pom libwoodstox-java-5.1.0/src/maven/woodstox-core-lgpl.pom --- libwoodstox-java-4.1.3/src/maven/woodstox-core-lgpl.pom 2012-04-24 04:38:21.000000000 +0000 +++ libwoodstox-java-5.1.0/src/maven/woodstox-core-lgpl.pom 1970-01-01 00:00:00.000000000 +0000 @@ -1,50 +0,0 @@ - - - - 4.0.0 - org.codehaus.woodstox - woodstox-core-lgpl - jar - Woodstox - @VERSION@ - Woodstox is a high-performance XML processor that -implements Stax (JSR-173) and SAX2 APIs - - - http://woodstox.codehaus.org - http://jira.codehaus.org/browse/WSTX - - - - - - javax.xml.stream - stax-api - 1.0-2 - - - - org.codehaus.woodstox - stax2-api - @REQ_STAX2_VERSION@ - - - - - - - GNU Lesser General Public License (LGPL), Version 2.1 - http://www.fsf.org/licensing/licenses/lgpl.txt - repo - - - - - Codehaus - http://www.codehaus.org/ - - diff -Nru libwoodstox-java-4.1.3/src/resources/javax.xml.stream.XMLEventFactory libwoodstox-java-5.1.0/src/resources/javax.xml.stream.XMLEventFactory --- libwoodstox-java-4.1.3/src/resources/javax.xml.stream.XMLEventFactory 2012-04-24 04:38:21.000000000 +0000 +++ libwoodstox-java-5.1.0/src/resources/javax.xml.stream.XMLEventFactory 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -com.ctc.wstx.stax.WstxEventFactory diff -Nru libwoodstox-java-4.1.3/src/resources/javax.xml.stream.XMLInputFactory libwoodstox-java-5.1.0/src/resources/javax.xml.stream.XMLInputFactory --- libwoodstox-java-4.1.3/src/resources/javax.xml.stream.XMLInputFactory 2012-04-24 04:38:21.000000000 +0000 +++ libwoodstox-java-5.1.0/src/resources/javax.xml.stream.XMLInputFactory 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -com.ctc.wstx.stax.WstxInputFactory \ No newline at end of file diff -Nru libwoodstox-java-4.1.3/src/resources/javax.xml.stream.XMLOutputFactory libwoodstox-java-5.1.0/src/resources/javax.xml.stream.XMLOutputFactory --- libwoodstox-java-4.1.3/src/resources/javax.xml.stream.XMLOutputFactory 2012-04-24 04:38:21.000000000 +0000 +++ libwoodstox-java-5.1.0/src/resources/javax.xml.stream.XMLOutputFactory 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -com.ctc.wstx.stax.WstxOutputFactory \ No newline at end of file diff -Nru libwoodstox-java-4.1.3/src/resources/org.codehaus.stax2.validation.XMLValidationSchemaFactory.dtd libwoodstox-java-5.1.0/src/resources/org.codehaus.stax2.validation.XMLValidationSchemaFactory.dtd --- libwoodstox-java-4.1.3/src/resources/org.codehaus.stax2.validation.XMLValidationSchemaFactory.dtd 2012-04-24 04:38:21.000000000 +0000 +++ libwoodstox-java-5.1.0/src/resources/org.codehaus.stax2.validation.XMLValidationSchemaFactory.dtd 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -com.ctc.wstx.dtd.DTDSchemaFactory diff -Nru libwoodstox-java-4.1.3/src/resources/org.codehaus.stax2.validation.XMLValidationSchemaFactory.relaxng libwoodstox-java-5.1.0/src/resources/org.codehaus.stax2.validation.XMLValidationSchemaFactory.relaxng --- libwoodstox-java-4.1.3/src/resources/org.codehaus.stax2.validation.XMLValidationSchemaFactory.relaxng 2012-04-24 04:38:21.000000000 +0000 +++ libwoodstox-java-5.1.0/src/resources/org.codehaus.stax2.validation.XMLValidationSchemaFactory.relaxng 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -com.ctc.wstx.msv.RelaxNGSchemaFactory diff -Nru libwoodstox-java-4.1.3/src/resources/org.codehaus.stax2.validation.XMLValidationSchemaFactory.w3c libwoodstox-java-5.1.0/src/resources/org.codehaus.stax2.validation.XMLValidationSchemaFactory.w3c --- libwoodstox-java-4.1.3/src/resources/org.codehaus.stax2.validation.XMLValidationSchemaFactory.w3c 2012-04-24 04:38:21.000000000 +0000 +++ libwoodstox-java-5.1.0/src/resources/org.codehaus.stax2.validation.XMLValidationSchemaFactory.w3c 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -com.ctc.wstx.msv.W3CSchemaFactory diff -Nru libwoodstox-java-4.1.3/src/samples/ValidateOutputWithDtd.java libwoodstox-java-5.1.0/src/samples/ValidateOutputWithDtd.java --- libwoodstox-java-4.1.3/src/samples/ValidateOutputWithDtd.java 2012-04-24 04:38:21.000000000 +0000 +++ libwoodstox-java-5.1.0/src/samples/ValidateOutputWithDtd.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,63 +0,0 @@ -package samples; - -import java.io.*; - -import javax.xml.stream.*; - -import org.codehaus.stax2.*; -import org.codehaus.stax2.validation.*; - -/** - * This is a simple example/sample class that shows how to - * use the new Stax2 validation API to validate XML output written - * using XMLStreamWriter, against an DTD instance. - */ -public class ValidateOutputWithDtd -{ - public static void main(String[] args) - { - if (args.length > 0) { - System.err.println("Usage: java ValidateOutputWithDtd"); - System.exit(1); - } - - final String DTD_STR = - "\n" - +"" - +"" - +"\n"; - StringWriter strw = new StringWriter(); - try { - // First, let's parse DTD schema object - XMLValidationSchemaFactory sf = XMLValidationSchemaFactory.newInstance(XMLValidationSchema.SCHEMA_ID_DTD); - XMLValidationSchema dtd = sf.createSchema(new StringReader(DTD_STR)); - XMLOutputFactory ofact = XMLOutputFactory.newInstance(); - XMLStreamWriter2 sw = (XMLStreamWriter2) ofact.createXMLStreamWriter(strw); - - try { - sw.validateAgainst(dtd); // this starts validation - // Document validation is done as output is written - sw.writeStartDocument(); - sw.writeStartElement("root"); - sw.writeStartElement("branch"); - sw.writeStartElement("leaf"); - sw.writeEndElement(); - // We'll get exception -- branch not legal in branch - sw.writeStartElement("branch"); - sw.writeEndElement(); - sw.writeEndElement(); - sw.writeEndElement(); - sw.writeEndDocument(); - sw.close(); - } catch (XMLValidationException vex) { - System.err.println("Document failed validation: "+vex); - System.exit(1); - } - } catch (XMLStreamException xse) { - System.err.println("Failed output the document: "+xse); - System.exit(1); - } - // If we got this far, we are all good - System.out.println("Document succesfully validated and written. Content: '"+strw.toString()+"'"); - } -} diff -Nru libwoodstox-java-4.1.3/src/samples/ValidateWithDtd.java libwoodstox-java-5.1.0/src/samples/ValidateWithDtd.java --- libwoodstox-java-4.1.3/src/samples/ValidateWithDtd.java 2012-04-24 04:38:21.000000000 +0000 +++ libwoodstox-java-5.1.0/src/samples/ValidateWithDtd.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,60 +0,0 @@ -package samples; - -import java.io.File; - -import javax.xml.stream.*; - -import org.codehaus.stax2.*; -import org.codehaus.stax2.validation.*; - -/** - * This is a simple example command line utility, that shows how to - * use the new Stax2 validation API to validate input documents against - * specific DTD instance. - */ -public class ValidateWithDtd -{ - public static void main(String[] args) - { - if (args.length != 2) { - System.err.println("Usage: java ValidateWithDtd [input-file] [dtd-file]"); - System.exit(1); - } - // First, let's parse DTD schema object - XMLValidationSchemaFactory sf = XMLValidationSchemaFactory.newInstance(XMLValidationSchema.SCHEMA_ID_DTD); - File schemaFile = new File(args[1]); - XMLValidationSchema dtd = null; - - try { - dtd = sf.createSchema(schemaFile); - } catch (XMLStreamException xe) { - System.err.println("Failed to process the DTD file ('"+schemaFile+"'): "+xe); - System.exit(1); - } - - // And then validate a document: - File inputFile = new File(args[0]); - try { - XMLInputFactory2 ifact = (XMLInputFactory2)XMLInputFactory.newInstance(); - XMLStreamReader2 sr = ifact.createXMLStreamReader(inputFile); - - try { - sr.validateAgainst(dtd); - /* Document validation is done as document is read through (ie. - * it's fully streaming as well as parsing), so just need to - * traverse the contents. - */ - while (sr.hasNext()) { - sr.next(); - } - } catch (XMLValidationException vex) { - System.err.println("Document '"+inputFile+"' failed validation: "+vex); - System.exit(1); - } - } catch (XMLStreamException xse) { - System.err.println("Failed parse the input document ('"+inputFile+"'): "+xse); - System.exit(1); - } - System.out.println("Document '"+inputFile+"' succesfully validated."); - } -} diff -Nru libwoodstox-java-4.1.3/src/samples/ValidateWithRelaxNg.java libwoodstox-java-5.1.0/src/samples/ValidateWithRelaxNg.java --- libwoodstox-java-4.1.3/src/samples/ValidateWithRelaxNg.java 2012-04-24 04:38:21.000000000 +0000 +++ libwoodstox-java-5.1.0/src/samples/ValidateWithRelaxNg.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,60 +0,0 @@ -package samples; - -import java.io.File; - -import javax.xml.stream.*; - -import org.codehaus.stax2.*; -import org.codehaus.stax2.validation.*; - -/** - * This is a simple example command line utility, that shows how to - * use the new Stax2 validation API to validate input documents against - * specific Relax NG schema instance. - */ -public class ValidateWithRelaxNg -{ - public static void main(String[] args) - { - if (args.length != 2) { - System.err.println("Usage: java ValidateWithRelaxNg [input-file] [rng-file]"); - System.exit(1); - } - // First, let's parse RNG schema object - XMLValidationSchemaFactory sf = XMLValidationSchemaFactory.newInstance(XMLValidationSchema.SCHEMA_ID_RELAXNG); - File schemaFile = new File(args[1]); - XMLValidationSchema rng = null; - - try { - rng = sf.createSchema(schemaFile); - } catch (XMLStreamException xe) { - System.err.println("Failed to process the RNG file ('"+schemaFile+"'): "+xe); - System.exit(1); - } - - // And then validate a document: - File inputFile = new File(args[0]); - try { - XMLInputFactory2 ifact = (XMLInputFactory2)XMLInputFactory.newInstance(); - XMLStreamReader2 sr = ifact.createXMLStreamReader(inputFile); - - try { - sr.validateAgainst(rng); - /* Document validation is done as document is read through (ie. - * it's fully streaming as well as parsing), so just need to - * traverse the contents. - */ - while (sr.hasNext()) { - sr.next(); - } - } catch (XMLValidationException vex) { - System.err.println("Document '"+inputFile+"' failed validation: "+vex); - System.exit(1); - } - } catch (XMLStreamException xse) { - System.err.println("Failed parse the input document ('"+inputFile+"'): "+xse); - System.exit(1); - } - System.out.println("Document '"+inputFile+"' succesfully validated."); - } -} diff -Nru libwoodstox-java-4.1.3/src/test/java/failing/TestBasicSax.java libwoodstox-java-5.1.0/src/test/java/failing/TestBasicSax.java --- libwoodstox-java-4.1.3/src/test/java/failing/TestBasicSax.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/failing/TestBasicSax.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,71 @@ +package failing; + +import java.io.*; + +import javax.xml.parsers.SAXParser; + +import org.xml.sax.*; +import org.xml.sax.ext.DefaultHandler2; + +import com.ctc.wstx.sax.*; + +import wstxtest.BaseWstxTest; + +/** + * Simple unit tests to verify that most fundamental parsing functionality + * works via Woodstox SAX implementation. + */ +public class TestBasicSax + extends BaseWstxTest +{ + /** + * Test for [WSTX_227] + */ + public void testCData() throws Exception + { + SAXParser parser = new WstxSAXParser(); + StringBuffer buffer = new StringBuffer(""); + CDATASectionCounter handler = new CDATASectionCounter(); + parser.setProperty("http://xml.org/sax/properties/lexical-handler", handler); + parser.parse(new InputSource(new StringReader(buffer.toString())), handler); + // Should get as many cdata sections as text segments + int cdatas = handler.getCDATASectionCount(); + int segments = handler.getSegmentCount(); + + assertEquals("Should only get a single CDATA segments, got "+cdatas+" (for "+segments+" text segments)", + 1, cdatas); + } + + /* + //////////////////////////////////////////////////// + // Helper methods + //////////////////////////////////////////////////// + */ + + private static class CDATASectionCounter extends DefaultHandler2 { + private int cdataSectionCount; + private int segmentCount; + + @Override + public void startCDATA() throws SAXException { + cdataSectionCount++; + } + + @Override + public void characters(char[] ch, int start, int length) throws SAXException { + segmentCount++; + } + + public int getCDATASectionCount() { + return cdataSectionCount; + } + + public int getSegmentCount() { + return segmentCount; + } + } +} diff -Nru libwoodstox-java-4.1.3/src/test/java/failing/TestParsingModeForEvents.java libwoodstox-java-5.1.0/src/test/java/failing/TestParsingModeForEvents.java --- libwoodstox-java-4.1.3/src/test/java/failing/TestParsingModeForEvents.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/failing/TestParsingModeForEvents.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,68 @@ +package failing; + +import javax.xml.stream.XMLInputFactory; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.events.XMLEvent; + +import org.codehaus.stax2.XMLEventReader2; + +import com.ctc.wstx.api.WstxInputProperties; + +import wstxtest.stream.BaseStreamTest; + +public class TestParsingModeForEvents + extends BaseStreamTest +{ + final static String XML_MULTI_DOC = + "text\n" + +"text\n" + +"text" + +"text" + ; + + // [woodstox-core#42] + public void testMultiDocumentWithEventReader() throws XMLStreamException + { + XMLInputFactory f = getInputFactory(); + setCoalescing(f, true); + f.setProperty(WstxInputProperties.P_INPUT_PARSING_MODE, WstxInputProperties.PARSING_MODE_DOCUMENTS); + XMLEventReader2 er = constructEventReader(f, XML_MULTI_DOC); + + _checkEventDoc(er, 0); + _checkEventDoc(er, 1); + _checkEventDoc(er, 2); + _checkEventDoc(er, 3); + + // and then the end + assertFalse(er.hasNextEvent()); + } + + private void _checkEventDoc(XMLEventReader2 er, int seq) throws XMLStreamException + { + if (!er.hasNextEvent()) { + fail("No more events: should start document #"+seq+" in multi-doc mode"); + } + XMLEvent event; + assertTokenType(START_DOCUMENT, er.nextEvent()); + assertTokenType(START_ELEMENT, (event = er.nextEvent())); + assertEquals("root", event.asStartElement().getName().getLocalPart()); + assertTokenType(CHARACTERS, (event = er.nextEvent())); + assertEquals("text", event.asCharacters().getData()); + assertTokenType(END_ELEMENT, (event = er.nextEvent())); + assertEquals("root", event.asEndElement().getName().getLocalPart()); + + // may get other types + while (true) { + event = er.nextEvent(); + switch (event.getEventType()) { + case END_DOCUMENT: + return; + case PROCESSING_INSTRUCTION: + case COMMENT: + break; + default: + fail("Unexpected XMLEvent after document: "+event); + } + } + } +} diff -Nru libwoodstox-java-4.1.3/src/test/java/failing/TestRelaxNG.java libwoodstox-java-5.1.0/src/test/java/failing/TestRelaxNG.java --- libwoodstox-java-4.1.3/src/test/java/failing/TestRelaxNG.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/failing/TestRelaxNG.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,135 @@ +package failing; + +import javax.xml.stream.*; + +import org.codehaus.stax2.*; +import org.codehaus.stax2.validation.*; + +import wstxtest.vstream.BaseValidationTest; + +/** + * This is a simple base-line "smoke test" that checks that RelaxNG + * validation works at least minimally. + */ +public class TestRelaxNG + extends BaseValidationTest +{ + final static String SIMPLE_RNG_SCHEMA = + "\n" + +" \n" + +" \n" + +" \n" + +" \n" + +" \n" + +" \n" + +" \n" + +" \n" + +" \n" + +" \n" + +" \n" + +" \n" + +"" + ; + + /** + * Similar schema, but one that uses namespaces + */ + final static String SIMPLE_RNG_NS_SCHEMA = + "\n" + +" \n" + +" \n" + +" \n" + +" \n" + +" \n" + +" \n" + +" \n" + +" \n" + +" \n" + +" \n" + +" \n" + +"" + ; + + public void testSimpleBooleanElem() throws XMLStreamException + { + final String schemaDef = + "\n" + +" \n" + +" \n" + +" \n" + +"" + ; + + XMLValidationSchema schema = parseRngSchema(schemaDef); + + // First, a simple valid document + XMLStreamReader2 sr = getReader("true"); + sr.validateAgainst(schema); + while (sr.next() != END_DOCUMENT) { } + sr.close(); + + // Then one with invalid element value + verifyRngFailure("foobar", + schema, "invalid boolean element value", + "does not satisfy the \"boolean\" type"); + + // And one with empty value + // 12-Nov-2008, TSa: still having MSV bug here, need to suppress failure + verifyRngFailure(" ", + schema, "missing boolean element value", + "does not satisfy the \"boolean\" type", true); + + // And then 2 variations of completely missing value + // 12-Nov-2008, TSa: still having MSV bug here, need to suppress failure + verifyRngFailure("", + schema, "missing boolean element value", + "does not satisfy the \"boolean\" type", true); + + // 12-Nov-2008, TSa: still having MSV bug here, need to suppress failure + verifyRngFailure("", + schema, "missing boolean element value", + "does not satisfy the \"boolean\" type", true); + } + + private void verifyRngFailure(String xml, XMLValidationSchema schema, String failMsg, String failPhrase) + throws XMLStreamException + { + // By default, yes we are strict... + verifyRngFailure(xml, schema, failMsg, failPhrase, true); + } + + private void verifyRngFailure(String xml, XMLValidationSchema schema, String failMsg, String failPhrase, + boolean strict) throws XMLStreamException + { + XMLStreamReader2 sr = getReader(xml); + sr.validateAgainst(schema); + try { + while (sr.hasNext()) { + /*int type =*/ sr.next(); + } + fail("Expected validity exception for "+failMsg); + } catch (XMLValidationException vex) { + String origMsg = vex.getMessage(); + String msg = (origMsg == null) ? "" : origMsg.toLowerCase(); + if (msg.indexOf(failPhrase.toLowerCase()) < 0) { + String actualMsg = "Expected validation exception for "+failMsg+", containing phrase '"+failPhrase+"': got '"+origMsg+"'"; + if (strict) { + fail(actualMsg); + } + warn("suppressing failure due to MSV bug, failure: '"+actualMsg+"'"); + } + // should get this specific type; not basic stream exception + } catch (XMLStreamException sex) { + fail("Expected XMLValidationException for "+failMsg); + } + } + + + private XMLStreamReader2 getReader(String contents) throws XMLStreamException + { + XMLInputFactory2 f = getInputFactory(); + setValidating(f, false); + return constructStreamReader(f, contents); + } +} diff -Nru libwoodstox-java-4.1.3/src/test/java/failing/TestW3CDefaultValues.java libwoodstox-java-5.1.0/src/test/java/failing/TestW3CDefaultValues.java --- libwoodstox-java-4.1.3/src/test/java/failing/TestW3CDefaultValues.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/failing/TestW3CDefaultValues.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,92 @@ +package failing; + +import javax.xml.stream.*; + +import org.codehaus.stax2.*; +import org.codehaus.stax2.validation.*; + +import wstxtest.vstream.BaseValidationTest; + +/** + * Test for XML Schema value constraints (default, required) for + * elements and attributes. + */ +public class TestW3CDefaultValues + extends BaseValidationTest +{ + final static String SCHEMA_WITH_DEFAULTS = + "\n" + + "\n" + + " \n" + + " \n" + + " " + + " " + + " " + + " \n" + + " \n" + + "\n" + +"" + ; + + final static String SCHEMA_WITH_REQUIRED = ""; + + public void testAttributeDefault() throws Exception + { + XMLValidationSchema schema = parseW3CSchema(SCHEMA_WITH_DEFAULTS); + XMLStreamReader2 sr = getReader("129"); + sr.validateAgainst(schema); + // first: if explicitly defined, should show that value + assertTokenType(START_ELEMENT, sr.next()); + assertEquals("price", sr.getLocalName()); + assertEquals(1, sr.getAttributeCount()); + assertEquals("FIM", sr.getAttributeValue(null, "currency")); + sr.close(); + + // then, if missing, default to given default + sr = getReader("129"); + sr.validateAgainst(schema); + // first: if explicitly defined, should show that value + assertTokenType(START_ELEMENT, sr.next()); + assertEquals("price", sr.getLocalName()); + assertEquals(1, sr.getAttributeCount()); + assertEquals("USD", sr.getAttributeValue(null, "currency")); + sr.close(); + } + + public void testElementDefault() throws Exception + { + XMLValidationSchema schema = parseW3CSchema(SCHEMA_WITH_DEFAULTS); + XMLStreamReader2 sr = getReader("129"); + sr.validateAgainst(schema); + // first: if explicitly defined, should show that value + assertTokenType(START_ELEMENT, sr.next()); + assertEquals("price", sr.getLocalName()); + assertEquals("129", sr.getElementText()); + assertTokenType(END_ELEMENT, sr.getEventType()); + sr.close(); + + // then, if missing, default to given default + sr = getReader(""); + sr.validateAgainst(schema); + // first: if explicitly defined, should show that value + assertTokenType(START_ELEMENT, sr.next()); + assertEquals("price", sr.getLocalName()); + assertEquals("10", sr.getElementText()); + assertTokenType(END_ELEMENT, sr.getEventType()); + sr.close(); + } + + /* + /////////////////////////////////////////////////////////////////////// + // Helper methods + /////////////////////////////////////////////////////////////////////// + */ + + XMLStreamReader2 getReader(String contents) throws XMLStreamException + { + XMLInputFactory2 f = getInputFactory(); + setValidating(f, false); + return constructStreamReader(f, contents); + } + +} diff -Nru libwoodstox-java-4.1.3/src/test/java/failing/TestW3CSchemaComplexTypes.java libwoodstox-java-5.1.0/src/test/java/failing/TestW3CSchemaComplexTypes.java --- libwoodstox-java-4.1.3/src/test/java/failing/TestW3CSchemaComplexTypes.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/failing/TestW3CSchemaComplexTypes.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,81 @@ +package failing; + +import javax.xml.stream.XMLStreamException; + +import org.codehaus.stax2.XMLInputFactory2; +import org.codehaus.stax2.XMLStreamReader2; +import org.codehaus.stax2.validation.XMLValidationException; +import org.codehaus.stax2.validation.XMLValidationSchema; + +import wstxtest.vstream.BaseValidationTest; + +public class TestW3CSchemaComplexTypes + extends BaseValidationTest +{ + /** + * For problem with MSV: https://github.com/kohsuke/msv/issues/2 + * + * 29-Mar-2018, tatu: Oddly enough, problem itself allegedly resolved... + */ + public void testMSVGithubIssue2() throws Exception + { + XMLValidationSchema schema = parseW3CSchema( +"" ++"" ++"" ++" " ++" " ++" " ++"" ++"" ++"" ++" " ++" " ++" " ++"" ++"" ++"" ++"" ++"" ++"" ++"" ++" " ++" " ++" " ++" " ++"" ++"" ++""); + XMLStreamReader2 sr = getReader("" + +"" + +"" + +""); + sr.validateAgainst(schema); + + try { + assertTokenType(START_ELEMENT, sr.next()); + assertEquals("Root", sr.getLocalName()); + assertTokenType(START_ELEMENT, sr.next()); + assertEquals("Child", sr.getLocalName()); + assertTokenType(END_ELEMENT, sr.next()); + assertTokenType(END_ELEMENT, sr.next()); + assertTokenType(END_DOCUMENT, sr.next()); + } catch (XMLValidationException vex) { + fail("Did not expect validation exception, got: " + vex); + } + assertTokenType(END_DOCUMENT, sr.getEventType()); + } + + /* + /////////////////////////////////////////////////////////////////////// + // Helper methods + /////////////////////////////////////////////////////////////////////// + */ + + XMLStreamReader2 getReader(String contents) throws XMLStreamException + { + XMLInputFactory2 f = getInputFactory(); + setValidating(f, false); + return constructStreamReader(f, contents); + } +} diff -Nru libwoodstox-java-4.1.3/src/test/java/failing/TestW3CSchemaTypes.java libwoodstox-java-5.1.0/src/test/java/failing/TestW3CSchemaTypes.java --- libwoodstox-java-4.1.3/src/test/java/failing/TestW3CSchemaTypes.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/failing/TestW3CSchemaTypes.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,43 @@ +package failing; + +import org.codehaus.stax2.validation.*; + +import wstxtest.vstream.BaseValidationTest; + +/** + * Simple testing of W3C Schema datatypes. + * Added to test [WSTX-210]. + * + * @author Tatu Saloranta + */ +public class TestW3CSchemaTypes + extends BaseValidationTest +{ + private final static String SCHEMA_INT = + "\n" + +"" + +"\n" + ; + + private final static String SCHEMA_FLOAT = + "\n" + +"" + +"\n" + ; + + // // // First 'int' datatype + + public void testSimpleMissingInt() throws Exception + { + XMLValidationSchema schema = parseW3CSchema(SCHEMA_INT); + verifyFailure("", schema, "missing 'int' value", + "does not satisfy the \"int\" type"); + } + + public void testSimpleMissingFloat() throws Exception + { + XMLValidationSchema schema = parseW3CSchema(SCHEMA_FLOAT); + verifyFailure("", schema, "missing 'float' value", + "Undefined ID 'm3'"); + } +} diff -Nru libwoodstox-java-4.1.3/src/test/java/org/codehaus/stax/test/BaseStaxTest.java libwoodstox-java-5.1.0/src/test/java/org/codehaus/stax/test/BaseStaxTest.java --- libwoodstox-java-4.1.3/src/test/java/org/codehaus/stax/test/BaseStaxTest.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/org/codehaus/stax/test/BaseStaxTest.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,659 @@ +package org.codehaus.stax.test; + +import java.io.*; +import java.util.HashMap; + +import junit.framework.TestCase; + +import javax.xml.stream.*; +import javax.xml.stream.events.XMLEvent; + +/* Latest updates: + * + * - 07-Sep-2007, TSa: Updating based on latest understanding of + * the proper use of null and Empty String wrt. "no prefix" and + * "no namespace" cases. + */ + +/** + * Base class for all StaxTest unit test classes. Contains shared + * functionality for many common set up tasks, as well as for + * outputting diagnostics. + * + * @author Tatu Saloranta + */ +public abstract class BaseStaxTest + extends TestCase + implements XMLStreamConstants +{ + /** + * This is the de facto standard property that enables accurate reporting + * of CDATA events. + */ + final static String PROP_REPORT_CDATA = "http://java.sun.com/xml/stream/properties/report-cdata-event"; + + final static HashMap mTokenTypes = new HashMap(); + static { + mTokenTypes.put(new Integer(START_ELEMENT), "START_ELEMENT"); + mTokenTypes.put(new Integer(END_ELEMENT), "END_ELEMENT"); + mTokenTypes.put(new Integer(START_DOCUMENT), "START_DOCUMENT"); + mTokenTypes.put(new Integer(END_DOCUMENT), "END_DOCUMENT"); + mTokenTypes.put(new Integer(CHARACTERS), "CHARACTERS"); + mTokenTypes.put(new Integer(CDATA), "CDATA"); + mTokenTypes.put(new Integer(COMMENT), "COMMENT"); + mTokenTypes.put(new Integer(PROCESSING_INSTRUCTION), "PROCESSING_INSTRUCTION"); + mTokenTypes.put(new Integer(DTD), "DTD"); + mTokenTypes.put(new Integer(SPACE), "SPACE"); + mTokenTypes.put(new Integer(ENTITY_REFERENCE), "ENTITY_REFERENCE"); + mTokenTypes.put(new Integer(NAMESPACE), "NAMESPACE_DECLARATION"); + mTokenTypes.put(new Integer(NOTATION_DECLARATION), "NOTATION_DECLARATION"); + mTokenTypes.put(new Integer(ENTITY_DECLARATION), "ENTITY_DECLARATION"); + } + + /* + /////////////////////////////////////////////////////////// + // Consts for expected values + /////////////////////////////////////////////////////////// + */ + + /** + * Expected return value for streamReader.getNamespaceURI() in + * non-namespace-aware mode. + */ + protected final String DEFAULT_URI_NON_NS = ""; + + protected final String DEFAULT_URI_NS = ""; + + /* + /////////////////////////////////////////////////////////// + // Cached instances + /////////////////////////////////////////////////////////// + */ + + XMLInputFactory mInputFactory; + XMLOutputFactory mOutputFactory; + XMLEventFactory mEventFactory; + + /* + /////////////////////////////////////////////////////////// + // Factory methods + /////////////////////////////////////////////////////////// + */ + + protected XMLInputFactory getInputFactory() + { + if (mInputFactory == null) { + mInputFactory = getNewInputFactory(); + } + return mInputFactory; + } + + protected static XMLInputFactory getNewInputFactory() + { + return XMLInputFactory.newInstance(); + } + + protected XMLOutputFactory getOutputFactory() + { + if (mOutputFactory == null) { + mOutputFactory = getNewOutputFactory(); + } + return mOutputFactory; + } + + protected static XMLOutputFactory getNewOutputFactory() + { + return XMLOutputFactory.newInstance(); + } + + protected XMLEventFactory getEventFactory() + { + if (mEventFactory == null) { + mEventFactory = XMLEventFactory.newInstance(); + } + return mEventFactory; + } + + protected static XMLStreamReader constructUtf8StreamReader(XMLInputFactory f, String content) + throws XMLStreamException + { + try { + return f.createXMLStreamReader(new ByteArrayInputStream(content.getBytes("UTF-8"))); + } catch (UnsupportedEncodingException e) { + throw new RuntimeException(e); + } + } + + protected static XMLStreamReader constructCharStreamReader(XMLInputFactory f, String content) + throws XMLStreamException + { + return f.createXMLStreamReader(new StringReader(content)); + } + + protected static XMLStreamReader constructStreamReader(XMLInputFactory f, String content) + throws XMLStreamException + { + /* Can either create a simple reader from String, or go with + * input stream & decoding? + */ + //return constructCharStreamReader(f, content); + return constructUtf8StreamReader(f, content); + } + + protected static XMLStreamReader constructStreamReader(XMLInputFactory f, byte[] b) + throws XMLStreamException + { + return f.createXMLStreamReader(new ByteArrayInputStream(b)); + } + + @SuppressWarnings("resource") + protected static XMLStreamReader constructStreamReaderForFile(XMLInputFactory f, String filename) + throws IOException, XMLStreamException + { + File inf = new File(filename); + XMLStreamReader sr = f.createXMLStreamReader(inf.toURL().toString(), + new FileReader(inf)); + assertEquals(START_DOCUMENT, sr.getEventType()); + return sr; + } + + protected XMLStreamReader constructNsStreamReader(String content) + throws XMLStreamException + { + XMLInputFactory f = getInputFactory(); + setNamespaceAware(f, true); + return f.createXMLStreamReader(new StringReader(content)); + } + + protected XMLStreamReader constructNsStreamReader(String content, boolean coal) + throws XMLStreamException + { + XMLInputFactory f = getInputFactory(); + setNamespaceAware(f, true); + setCoalescing(f, coal); + return f.createXMLStreamReader(new StringReader(content)); + } + + /* + /////////////////////////////////////////////////////////// + // Configuring input factory + /////////////////////////////////////////////////////////// + */ + + protected static boolean isCoalescing(XMLInputFactory f) + throws XMLStreamException + { + return ((Boolean) f.getProperty(XMLInputFactory.IS_COALESCING)).booleanValue(); + } + + protected static void setCoalescing(XMLInputFactory f, boolean state) + throws XMLStreamException + { + Boolean b = state ? Boolean.TRUE : Boolean.FALSE; + f.setProperty(XMLInputFactory.IS_COALESCING, b); + // Let's just double-check it... + assertEquals(state, isCoalescing(f)); + } + + protected static boolean isValidating(XMLInputFactory f) + throws XMLStreamException + { + return ((Boolean) f.getProperty(XMLInputFactory.IS_VALIDATING)).booleanValue(); + } + + protected static void setValidating(XMLInputFactory f, boolean state) + throws XMLStreamException + { + try { + Boolean b = state ? Boolean.TRUE : Boolean.FALSE; + f.setProperty(XMLInputFactory.IS_VALIDATING, b); + } catch (IllegalArgumentException iae) { + fail("Could not set DTD validating mode to "+state+": "+iae); + //throw new XMLStreamException(iae.getMessage(), iae); + } + assertEquals(state, isValidating(f)); + } + + protected static boolean isNamespaceAware(XMLInputFactory f) + throws XMLStreamException + { + return ((Boolean) f.getProperty(XMLInputFactory.IS_NAMESPACE_AWARE)).booleanValue(); + } + + /** + * @return True if setting succeeded, and property supposedly was + * succesfully set to the value specified; false if there was a problem. + */ + protected static boolean setNamespaceAware(XMLInputFactory f, boolean state) + throws XMLStreamException + { + try { + f.setProperty(XMLInputFactory.IS_NAMESPACE_AWARE, + state ? Boolean.TRUE : Boolean.FALSE); + + /* 07-Sep-2005, TSa: Let's not assert, but instead let's see if + * it sticks. Some implementations might choose to silently + * ignore setting, at least for 'false'? + */ + return (isNamespaceAware(f) == state); + } catch (IllegalArgumentException e) { + /* Let's assume, then, that the property (or specific value for it) + * is NOT supported... + */ + return false; + } + } + + protected static void setReplaceEntities(XMLInputFactory f, boolean state) + throws XMLStreamException + { + Boolean b = state ? Boolean.TRUE : Boolean.FALSE; + f.setProperty(XMLInputFactory.IS_REPLACING_ENTITY_REFERENCES, b); + assertEquals(b, f.getProperty(XMLInputFactory.IS_REPLACING_ENTITY_REFERENCES)); + } + + protected static void setSupportDTD(XMLInputFactory f, boolean state) + throws XMLStreamException + { + Boolean b = state ? Boolean.TRUE : Boolean.FALSE; + f.setProperty(XMLInputFactory.SUPPORT_DTD, b); + assertEquals(b, f.getProperty(XMLInputFactory.SUPPORT_DTD)); + } + + protected static boolean setSupportExternalEntities(XMLInputFactory f, boolean state) + throws XMLStreamException + { + Boolean b = state ? Boolean.TRUE : Boolean.FALSE; + try { + f.setProperty(XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES, b); + Object act = f.getProperty(XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES); + return (act instanceof Boolean) && ((Boolean) act).booleanValue() == state; + } catch (IllegalArgumentException e) { + /* Let's assume, then, that the property (or specific value for it) + * is NOT supported... + */ + return false; + } + } + + protected static void setResolver(XMLInputFactory f, XMLResolver resolver) + throws XMLStreamException + { + f.setProperty(XMLInputFactory.RESOLVER, resolver); + } + + protected static boolean setReportCData(XMLInputFactory f, boolean state) + throws XMLStreamException + { + + Boolean b = state ? Boolean.TRUE : Boolean.FALSE; + if (f.isPropertySupported(PROP_REPORT_CDATA)) { + f.setProperty(PROP_REPORT_CDATA, b); + return true; + } + return false; + } + + /* + /////////////////////////////////////////////////////////// + // Stream reader accessors + /////////////////////////////////////////////////////////// + */ + + /** + * Method that not only gets currently available text from the + * reader, but also checks that its consistenly accessible using + * different StAX methods. + */ + protected static String getAndVerifyText(XMLStreamReader sr) + throws XMLStreamException + { + String text = sr.getText(); + + /* 05-Apr-2006, TSa: Although getText() is available for DTD + * and ENTITY_REFERENCE, getTextXxx() are not. Thus, can not + * do more checks for those types. + */ + int type = sr.getEventType(); + if (type != ENTITY_REFERENCE && type != DTD) { + assertNotNull("getText() should never return null.", text); + int expLen = sr.getTextLength(); + /* Hmmh. Can only return empty text for CDATA (since empty + * blocks are legal). + */ + /* !!! 01-Sep-2004, TSa: + * note: theoretically, in coalescing mode, it could be possible + * to have empty CDATA section(s) get converted to CHARACTERS, + * which would be empty... may need to enhance this to check that + * mode is not coalescing? Or something + */ + if (sr.getEventType() == CHARACTERS) { + if (expLen == 0) { + fail("Stream reader should never return empty Strings (type: "+sr.getClass().getName()+")"); + } + } + assertEquals("Expected text length of "+expLen+", got "+text.length(), + expLen, text.length()); + char[] textChars = sr.getTextCharacters(); + int start = sr.getTextStart(); + String text2 = new String(textChars, start, expLen); + assertEquals("Expected getText() and getTextCharacters() to return same value for event of type ("+tokenTypeDesc(sr.getEventType())+")", text, text2); + } else { // DTD or ENTITY_REFERENCE + // not sure if null is legal for these either, but... + if (text == null) { // let's prevent an NPE at caller + text = ""; + } + } + return text; + } + + protected static String getAllText(XMLStreamReader sr) + throws XMLStreamException + { + StringBuffer sb = new StringBuffer(); + while (true) { + int tt = sr.getEventType(); + if (tt != CHARACTERS && tt != SPACE && tt != CDATA) { + break; + } + sb.append(getAndVerifyText(sr)); + sr.next(); + } + return sb.toString(); + } + + protected static String getAllCData(XMLStreamReader sr) + throws XMLStreamException + { + StringBuffer sb = new StringBuffer(); + while (true) { + /* Note: CDATA sections CAN be reported as CHARACTERS, but + * not as SPACE + */ + int tt = sr.getEventType(); + if (tt != CHARACTERS && tt != CDATA) { + break; + } + sb.append(getAndVerifyText(sr)); + sr.next(); + } + return sb.toString(); + } + + /* + /////////////////////////////////////////////////////////// + // Derived assert/fail methods + /////////////////////////////////////////////////////////// + */ + + protected static void assertTokenType(int expType, int actType) + { + if (expType == actType) { + return; + } + fail("Expected token "+tokenTypeDesc(expType) + +"; got "+tokenTypeDesc(actType)+"."); + } + + protected static void assertTokenType(int expType, int actType, + XMLStreamReader sr) + { + if (expType == actType) { + return; + } + fail("Expected token "+tokenTypeDesc(expType) + +"; got "+tokenTypeDesc(actType, sr)+"."); + } + + protected static void assertTextualTokenType(int actType) + { + if (actType != CHARACTERS && actType != SPACE + && actType != CDATA) { + fail("Expected textual token (CHARACTERS, SPACE or CDATA)" + +"; got "+tokenTypeDesc(actType)+"."); + } + } + + protected static void failStrings(String msg, String exp, String act) + { + // !!! TODO: Indicate position where Strings differ + fail(msg+": expected "+quotedPrintable(exp)+", got " + +quotedPrintable(act)); + } + + /** + * Helper method for ensuring that the current element + * (START_ELEMENT, END_ELEMENT) has no prefix + *

+ * Specific method makes sense, since earlier it was not clear + * whether null or empty string (or perhaps both) would be the + * right answer when there is no prefix. + *

+ * Current thinking (early 2008) is that empty string is the + * expected value + */ + protected static void assertNoPrefix(XMLStreamReader sr) + throws XMLStreamException + { + String prefix = sr.getPrefix(); + if (prefix == null) { + fail("Expected \"\" to signify missing prefix (see XMLStreamReader#getPrefix() JavaDocs): got null"); + } else { + if (prefix.length() > 0) { + fail("Current element should not have a prefix: got '"+prefix+"'"); + } + } + } + + /** + * Helper method for ensuring that the given return value for + * attribute prefix accessor has returned a value that + * represents "no prefix" value. + *

+ * Current thinking (early 2008) is that empty string is the + * expected value here. + */ + protected static void assertNoAttrPrefix(String attrPrefix) + throws XMLStreamException + { + if (attrPrefix == null) { + fail("Attribute that does not have a prefix should be indicated with \"\", not null"); + } else { + if (attrPrefix.length() > 0) { + fail("Attribute should not have prefix (had '"+attrPrefix+"')"); + } + } + } + + /** + * Similar to {@link #assertNoPrefix}, but here we do know that unbound + * namespace URI should be indicated as empty String. + */ + protected static void assertNoNsURI(XMLStreamReader sr) + throws XMLStreamException + { + String uri = sr.getNamespaceURI(); + if (uri == null) { + fail("Expected empty String to indicate \"no namespace\": got null"); + } else if (uri.length() != 0) { + fail("Expected empty String to indicate \"no namespace\": got '"+uri+"'"); + } + } + + protected static void assertNoAttrNamespace(String attrNsURI) + throws XMLStreamException + { + if (attrNsURI == null) { + fail("Expected empty String to indicate \"no namespace\" (for attribute): got null"); + } else if (attrNsURI.length() != 0) { + fail("Expected empty String to indicate \"no namespace\" (for attribute): got '"+attrNsURI+"'"); + } + } + + protected static void assertNoPrefixOrNs(XMLStreamReader sr) + throws XMLStreamException + { + assertNoPrefix(sr); + assertNoNsURI(sr); + } + + /** + * Helper assertion that assert that the String is either null or + * empty (""). + */ + protected static void assertNullOrEmpty(String str) + { + if (str != null && str.length() > 0) { + fail("Expected String to be empty or null; was '"+str+"' (length " + +str.length()+")"); + } + } + + /* + /////////////////////////////////////////////////////////// + // Cleansing + /////////////////////////////////////////////////////////// + */ + + protected static String stripXmlDecl(String xml) { + if (xml.startsWith("") + 2); + } + return xml; + } + + /* + /////////////////////////////////////////////////////////// + // Debug/output helpers + /////////////////////////////////////////////////////////// + */ + + protected static String tokenTypeDesc(int tt) + { + String desc = (String) mTokenTypes.get(new Integer(tt)); + if (desc == null) { + return "["+tt+"]"; + } + return desc; + } + + protected static String tokenTypeDesc(XMLEvent evt) + { + return tokenTypeDesc(evt.getEventType()); + } + + final static int MAX_DESC_TEXT_CHARS = 8; + + protected static String tokenTypeDesc(int tt, XMLStreamReader sr) + { + String desc = tokenTypeDesc(tt); + // Let's show first 8 chars or so... + if (tt == CHARACTERS || tt == SPACE || tt == CDATA) { + String str = sr.getText(); + if (str.length() > MAX_DESC_TEXT_CHARS) { + desc = "\""+str.substring(0, MAX_DESC_TEXT_CHARS) + "\"[...]"; + } else { + desc = "\"" + desc + "\""; + } + desc = " ("+desc+")"; + } + return desc; + } + + protected static String valueDesc(String value) + { + if (value == null) { + return "[NULL]"; + } + return "\"" + value + "\""; + } + + protected static String printable(char ch) + { + if (ch == '\n') { + return "\\n"; + } + if (ch == '\r') { + return "\\r"; + } + if (ch == '\t') { + return "\\t"; + } + if (ch == ' ') { + return "_"; + } + if (ch > 127 || ch < 32) { + StringBuffer sb = new StringBuffer(6); + sb.append("\\u"); + String hex = Integer.toHexString((int)ch); + for (int i = 0, len = 4 - hex.length(); i < len; i++) { + sb.append('0'); + } + sb.append(hex); + return sb.toString(); + } + return null; + } + + protected static String printable(String str) + { + if (str == null || str.length() == 0) { + return str; + } + + int len = str.length(); + StringBuffer sb = new StringBuffer(len + 64); + for (int i = 0; i < len; ++i) { + char c = str.charAt(i); + String res = printable(c); + if (res == null) { + sb.append(c); + } else { + sb.append(res); + } + } + return sb.toString(); + } + + protected static String quotedPrintable(String str) + { + if (str == null || str.length() == 0) { + return "[0]''"; + } + return "[len: "+str.length()+"] '"+printable(str)+"'"; + } + + protected void reportNADueToProperty(String method, String prop) + { + String clsName = getClass().getName(); + /* 27-Sep-2005, TSa: Should probably use some other mechanism for + * reporting this. Does JUnit have something applicable? + */ + System.err.println("Skipping "+clsName+"#"+method+": property '" + +prop+"' (or one of its values) not supported."); + } + + protected void reportNADueToNS(String method) + { + reportNADueToProperty(method, "IS_NAMESPACE_AWARE"); + } + + protected void reportNADueToExtEnt(String method) + { + reportNADueToProperty(method, "IS_SUPPORTING_EXTERNAL_ENTITIES"); + } + + protected void reportNADueToEntityExpansion(String method, int type) + { + String clsName = getClass().getName(); + String msg = (type > 0) ? " (next event: "+tokenTypeDesc(type)+")" : ""; + System.err.println("Skipping "+clsName+"#"+method+": entity expansion does not seem to be functioning properly"+msg+"."); + } + + protected void warn(String msg) + { + // Hmmh. Should we add a dependency to log4j or j.u.l? + // For now let's just dump to console. + System.err.println("WARN: "+msg); + } +} diff -Nru libwoodstox-java-4.1.3/src/test/java/org/codehaus/stax/test/dtd/BaseTestForDTD.java libwoodstox-java-5.1.0/src/test/java/org/codehaus/stax/test/dtd/BaseTestForDTD.java --- libwoodstox-java-4.1.3/src/test/java/org/codehaus/stax/test/dtd/BaseTestForDTD.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/org/codehaus/stax/test/dtd/BaseTestForDTD.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,22 @@ +package org.codehaus.stax.test.dtd; + +import javax.xml.stream.XMLInputFactory; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; + +import org.codehaus.stax.test.stream.BaseStreamTest; + +abstract class BaseTestForDTD extends BaseStreamTest +{ + protected XMLStreamReader getDTDAwareReader(String contents, boolean validate) + throws XMLStreamException + { + XMLInputFactory f = getInputFactory(); + setCoalescing(f, false); + setNamespaceAware(f, true); + setSupportDTD(f, true); + // Let's make sure DTD is really parsed? + setValidating(f, validate); + return constructStreamReader(f, contents); + } +} diff -Nru libwoodstox-java-4.1.3/src/test/java/org/codehaus/stax/test/dtd/TestDtdWithUnicodeEntities.java libwoodstox-java-5.1.0/src/test/java/org/codehaus/stax/test/dtd/TestDtdWithUnicodeEntities.java --- libwoodstox-java-4.1.3/src/test/java/org/codehaus/stax/test/dtd/TestDtdWithUnicodeEntities.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/org/codehaus/stax/test/dtd/TestDtdWithUnicodeEntities.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,32 @@ +package org.codehaus.stax.test.dtd; + +import javax.xml.stream.XMLStreamReader; + +public class TestDtdWithUnicodeEntities extends BaseTestForDTD +{ + /** + * Test to verify [WSTX-256], issues with character entities for DTD-declared + * entities. + */ + public void testEntitiesEmbedded() throws Exception + { + final String XML = "" + +"]>\n" + +"&Abc;\n&Abc;" + ; + XMLStreamReader sr = getDTDAwareReader(XML, false); + assertTokenType(DTD, sr.next()); + assertTokenType(START_ELEMENT, sr.next()); + assertEquals("root", sr.getLocalName()); + assertTokenType(CHARACTERS, sr.next()); + String text = getAllText(sr); + // we should have two surrogate pairs in there... + assertEquals(5, text.length()); + assertEquals(0x1D504, Character.codePointAt(text, 0)); + assertEquals(0x1D504, Character.codePointAt(text, 3)); + assertTokenType(END_ELEMENT, sr.getEventType()); + assertEquals("root", sr.getLocalName()); + assertTokenType(END_DOCUMENT, sr.next()); + } +} diff -Nru libwoodstox-java-4.1.3/src/test/java/org/codehaus/stax/test/evt/BaseEventTest.java libwoodstox-java-5.1.0/src/test/java/org/codehaus/stax/test/evt/BaseEventTest.java --- libwoodstox-java-4.1.3/src/test/java/org/codehaus/stax/test/evt/BaseEventTest.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/org/codehaus/stax/test/evt/BaseEventTest.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,149 @@ +package org.codehaus.stax.test.evt; + +import java.io.*; +import java.util.Iterator; + +import javax.xml.stream.*; +import javax.xml.stream.events.*; + +import org.codehaus.stax.test.BaseStaxTest; + +/** + * Base class for all StaxTest unit tests that test Event API + * functionality. + * + * @author Tatu Saloranta + */ +public abstract class BaseEventTest + extends BaseStaxTest +{ + protected BaseEventTest() { super(); } + + /* + /////////////////////////////////////////////////// + // Utility methods + /////////////////////////////////////////////////// + */ + + @Override + protected XMLEventFactory getEventFactory() + throws FactoryConfigurationError + { + return XMLEventFactory.newInstance(); + } + + protected static XMLEventReader constructEventReader(XMLInputFactory f, String content) + throws XMLStreamException + { + return f.createXMLEventReader(new StringReader(content)); + } + + @SuppressWarnings("resource") + protected static XMLEventReader constructEventReaderForFile(XMLInputFactory f, String filename) + throws IOException, XMLStreamException + { + File inf = new File(filename); + XMLEventReader er = f.createXMLEventReader(inf.toURL().toString(), + new FileReader(inf)); + return er; + } + + /** + * Method that will iterate through contents of an XML document + * using specified event reader; will also access some of data + * to make sure reader reads most of lazy-loadable data. + * Method is usually called to try to get an exception for invalid + * content. + * + * @return Dummy value calculated on contents; used to make sure + * no dead code is eliminated + */ + protected int streamThrough(XMLEventReader er) + throws XMLStreamException + { + int result = 0; + + while (er.hasNext()) { + XMLEvent evt = er.nextEvent(); + int type = evt.getEventType(); + result += type; + if (evt.isCharacters()) { + result += evt.asCharacters().getData().hashCode(); + } + } + + return result; + } + + protected int calcAttrCount(StartElement elem) + throws XMLStreamException + { + int count = 0; + Iterator it = elem.getAttributes(); + if (it != null) { + while (it.hasNext()) { + /*Attribute attr = (Attribute)*/ it.next(); + ++count; + } + } + return count; + } + + public static void checkEventIsMethods(int type, XMLEvent evt) + { + int actualType = evt.getEventType(); + if (actualType != type) { + /* Minor deviation; should Characters objects that are constructed + * for CDATA and SPACE return true type or CHARACTERS? + */ + if (type == CHARACTERS && + (actualType == SPACE || actualType == CDATA)) { + // for now let's let this pass... + } else { + assertTokenType(type, actualType); // this'll fail and output descs for types + } + } + + /* Hmmh. Whether Namespace object should return true or false + * is an open question. So let's accept both + */ + if (type == NAMESPACE) { + /* for now let's just ask for it (to make sure it won't throw + * exceptions), but not verify the value + */ + /*boolean isAttr =*/ evt.isAttribute(); + } else { + assertEquals((type == ATTRIBUTE), evt.isAttribute()); + } + + assertEquals((type == CHARACTERS), evt.isCharacters()); + assertEquals((type == START_DOCUMENT), evt.isStartDocument()); + assertEquals((type == END_DOCUMENT), evt.isEndDocument()); + assertEquals((type == START_ELEMENT), evt.isStartElement()); + assertEquals((type == END_ELEMENT), evt.isEndElement()); + assertEquals((type == ENTITY_REFERENCE), evt.isEntityReference()); + assertEquals((type == NAMESPACE), evt.isNamespace()); + assertEquals((type == PROCESSING_INSTRUCTION), evt.isProcessingInstruction()); + } + + /** + * Simple test utility method that just calls output method, to verify + * it does not throw anything nasty, and does output something. + * Not enough to verify actual working, but should exercise code path + * to check for fatal problems. + */ + public void testEventWritability(XMLEvent evt) + throws XMLStreamException + { + StringWriter sw = new StringWriter(); + evt.writeAsEncodedUnicode(sw); + + // Some events do not (have to) output anything: + switch (evt.getEventType()) { + case END_DOCUMENT: // nothing to output, usually + return; + } + + assertTrue(sw.toString().length() > 0); + } +} diff -Nru libwoodstox-java-4.1.3/src/test/java/org/codehaus/stax/test/evt/TestEventCopy.java libwoodstox-java-5.1.0/src/test/java/org/codehaus/stax/test/evt/TestEventCopy.java --- libwoodstox-java-4.1.3/src/test/java/org/codehaus/stax/test/evt/TestEventCopy.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/org/codehaus/stax/test/evt/TestEventCopy.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,144 @@ +package org.codehaus.stax.test.evt; + +import javax.xml.namespace.QName; +import javax.xml.stream.*; +import javax.xml.stream.events.*; + +import java.io.*; + +/** + * This test tries to verify that events can be copied from event reader + * to event writer, and result in well-formed output + * + * @author Tatu Saloranta + */ +public class TestEventCopy + extends BaseEventTest +{ + public void testCopy() + throws XMLStreamException + { + final String XML = + "\n" + +" \n" + +" " + +" \n" + +" " + +"" + ; + XMLEventReader er = getEventReader(XML, true, true); + StringWriter strw = new StringWriter(); + XMLOutputFactory f = getOutputFactory(); + XMLEventWriter ew = f.createXMLEventWriter(strw); + + while (er.hasNext()) { + ew.add(er.nextEvent()); + } + ew.close(); + + // And let's then just verify it's well-formed still + String results = strw.toString(); + er = getEventReader(results, true, true); + XMLEvent evt; + + // Plus that events are the way they ought to be + assertNotNull((evt = er.nextEvent())); + assertTrue(evt.isStartDocument()); + + evt = er.nextEvent(); + assertEquals(new QName("root"), evt.asStartElement().getName()); + + evt = er.nextEvent(); + assertTrue(evt.isCharacters()); + assertTrue(evt.asCharacters().isWhiteSpace()); + + evt = er.nextEvent(); + assertTrue(evt.isStartElement()); + assertEquals(new QName("branch"), evt.asStartElement().getName()); + + evt = er.nextEvent(); + assertTrue(evt.isCharacters()); + assertTrue(evt.asCharacters().isWhiteSpace()); + + evt = er.nextEvent(); + assertTrue(evt.isStartElement()); + assertEquals(new QName("leaf"), evt.asStartElement().getName()); + evt = er.nextEvent(); + assertTrue(evt.isEndElement()); + assertEquals(new QName("leaf"), evt.asEndElement().getName()); + + evt = er.nextEvent(); + assertTrue(evt.isCharacters()); + assertTrue(evt.asCharacters().isWhiteSpace()); + + evt = er.nextEvent(); + assertTrue(evt.isEndElement()); + assertEquals(new QName("branch"), evt.asEndElement().getName()); + + evt = er.nextEvent(); + assertTrue(evt.isCharacters()); + assertTrue(evt.asCharacters().isWhiteSpace()); + + evt = er.nextEvent(); + assertTrue(evt.isStartElement()); + assertEquals(new QName("leaf"), evt.asStartElement().getName()); + evt = er.nextEvent(); + assertTrue(evt.isEndElement()); + assertEquals(new QName("leaf"), evt.asEndElement().getName()); + + evt = er.nextEvent(); + assertTrue(evt.isEndElement()); + assertEquals(new QName("root"), evt.asEndElement().getName()); + } + + public void testCopyWithCData() + throws XMLStreamException + { + final String XML = + ""; + + XMLEventReader er = getEventReader(XML, true, false); + StringWriter strw = new StringWriter(); + XMLOutputFactory f = getOutputFactory(); + XMLEventWriter ew = f.createXMLEventWriter(strw); + + while (er.hasNext()) { + ew.add(er.nextEvent()); + } + ew.close(); + + // And then test what it looks like + String results = strw.toString(); + er = getEventReader(results, true, false); + XMLEvent evt; + + // Plus that events are the way they ought to be + assertNotNull((evt = er.nextEvent())); + assertTrue(evt.isStartDocument()); + + evt = er.nextEvent(); + assertTrue(evt.isStartElement()); + assertEquals(new QName("root"), evt.asStartElement().getName()); + + evt = er.nextEvent(); + assertTrue(evt.isCharacters()); + assertTrue("Expected CDATA block to generate a Characters event for which isCData() returns true", evt.asCharacters().isCData()); + assertEquals("a&b", evt.asCharacters().getData()); + + evt = er.nextEvent(); + assertTrue(evt.isEndElement()); + assertEquals(new QName("root"), evt.asEndElement().getName()); + + } + + private XMLEventReader getEventReader(String contents, boolean nsAware, boolean coal) + throws XMLStreamException + { + XMLInputFactory f = getInputFactory(); + setNamespaceAware(f, nsAware); + setCoalescing(f, coal); + setSupportDTD(f, true); + setValidating(f, false); + return constructEventReader(f, contents); + } +} diff -Nru libwoodstox-java-4.1.3/src/test/java/org/codehaus/stax/test/evt/TestEventDTD.java libwoodstox-java-5.1.0/src/test/java/org/codehaus/stax/test/evt/TestEventDTD.java --- libwoodstox-java-4.1.3/src/test/java/org/codehaus/stax/test/evt/TestEventDTD.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/org/codehaus/stax/test/evt/TestEventDTD.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,185 @@ +package org.codehaus.stax.test.evt; + +import javax.xml.stream.*; +import javax.xml.stream.events.*; + +import java.util.*; + +/** + * Tests for verifying behavior of Event API implementation with events + * that depend on (internal) DTD subset(s). + * + * @author Tatu Saloranta + */ +public class TestEventDTD + extends BaseEventTest +{ + /** + * Test that checks that entity objects are properly returned in + * non-expanding mode. + */ + public void testNonExpandingEntities() + throws XMLStreamException + { + // Let's test all entity types + final String URL1 = "nosuchdir/dummyent.xml"; + String XML = "" + +"\n" + +"\n" + +"\n" + // Hmmh: can't test this, but let's declare it anyway + +"\n" + +"]>" + //+"&intEnt;&extParsedEnt;&extUnparsedEnt;" + +"&intEnt;&extParsedEnt;" + ; + + for (int i = 0; i < 2; ++i) { + boolean ns = (i & 1) != 0; + /* 08-Sep-2007, TSa: Alas, not all impls (like sjsxp) support + * combination of non-expanding and coalescing; thus, + * can only test non-coalescing mode here. + */ + //boolean coal = (i & 2) != 0; + boolean coal = false; + // false -> do not expand entities + XMLEventReader er = getReader(XML, ns, coal, false); + + assertTokenType(START_DOCUMENT, er.nextEvent().getEventType()); + assertTokenType(DTD, er.nextEvent().getEventType()); + XMLEvent evt = er.nextEvent(); + assertTrue(evt.isStartElement()); + + evt = er.nextEvent(); + assertTokenType(ENTITY_REFERENCE, evt.getEventType()); + EntityReference ref = (EntityReference) evt; + assertNotNull(ref); + assertTrue(ref.isEntityReference()); + assertEquals("intEnt", ref.getName()); + EntityDeclaration ed = ref.getDeclaration(); + assertNotNull("Declaration of internal entity 'intEnt' should not be null", ed); + assertEquals("intEnt", ed.getName()); + assertEquals("internal", ed.getReplacementText()); + assertNullOrEmpty(ed.getNotationName()); + assertNullOrEmpty(ed.getPublicId()); + assertNullOrEmpty(ed.getSystemId()); + + evt = er.nextEvent(); + assertTokenType(ENTITY_REFERENCE, evt.getEventType()); + ref = (EntityReference) evt; + assertNotNull(ref); + assertTrue(ref.isEntityReference()); + assertEquals("extParsedEnt", ref.getName()); + ed = ref.getDeclaration(); + assertNotNull("Declaration of external entity 'extParsedEnt' should not be null", ed); + assertEquals("extParsedEnt", ed.getName()); + assertNullOrEmpty(ed.getNotationName()); + assertNullOrEmpty(ed.getPublicId()); + assertEquals(URL1, ed.getSystemId()); + + /* + evt = er.nextEvent(); + assertTokenType(ENTITY_REFERENCE, evt.getEventType()); + ref = (EntityReference) evt; + assertEquals("extUnparsedEnt", ref.getName()); + assertNotNull(ref); + assertTrue(ref.isEntityReference()); + ed = ref.getDeclaration(); + assertNotNull(ed); + assertEquals("notation", ed.getNotationName()); + */ + + evt = er.nextEvent(); + assertTrue(evt.isEndElement()); + assertTokenType(END_DOCUMENT, er.nextEvent().getEventType()); + assertFalse(er.hasNext()); + } + } + + /** + * This unit test checks that a DTD event that results from parsing + * a valid document, to the degree it is done without having to + * validate anything + */ + public void testValidDtdEvent() + throws XMLStreamException + { + String XML = "" + +"\n" + +"\n" + +"\n" + +"\n" + +"\n" + +"]>" + +"" + ; + for (int i = 0; i < 4; ++i) { + boolean ns = (i & 1) != 0; + boolean coal = (i & 2) != 0; + XMLEventReader er = getReader(XML, ns, coal); + + assertTokenType(START_DOCUMENT, er.nextEvent().getEventType()); + XMLEvent evt = er.nextEvent(); + assertTokenType(DTD, evt.getEventType()); + DTD dtd = (DTD) evt; + /* isXxx() methods and writability are tested by a different + * unit test (in TestEventTypes()); here let's just check for + * entities and notations + */ + List entities = dtd.getEntities(); + assertNotNull("Entity list for a DTD declaration with entities should not be null", entities); + assertEquals(3, entities.size()); + + // Let's also verify they are all of right type... + testListElems(entities, EntityDeclaration.class); + + List notations = dtd.getNotations(); + + // Let's also verify they are all of right type... + testListElems(notations, NotationDeclaration.class); + + assertNotNull("Notation list for a DTD declaration with notations should not be null", entities); + assertNotNull(notations); + assertEquals(2, notations.size()); + } + } + + /* + /////////////////////////////////////////////////////////// + // Internal methods: + /////////////////////////////////////////////////////////// + */ + + private XMLEventReader getReader(String contents, boolean nsAware, + boolean coalesce) + throws XMLStreamException + { + return getReader(contents, nsAware, coalesce, true); + } + + private XMLEventReader getReader(String contents, boolean nsAware, + boolean coalesce, boolean expandEnt) + throws XMLStreamException + { + //XMLInputFactory f = getInputFactory(); + XMLInputFactory f = getNewInputFactory(); + setNamespaceAware(f, nsAware); + setCoalescing(f, coalesce); + setSupportDTD(f, true); + setValidating(f, false); + setReplaceEntities(f, expandEnt); + return constructEventReader(f, contents); + } + + private void testListElems(List l, Class expType) + { + Iterator it = l.iterator(); + while (it.hasNext()) { + Object o = it.next(); + assertNotNull(o); + assertTrue(expType.isAssignableFrom(o.getClass())); + } + } +} diff -Nru libwoodstox-java-4.1.3/src/test/java/org/codehaus/stax/test/evt/TestEventFactory.java libwoodstox-java-5.1.0/src/test/java/org/codehaus/stax/test/evt/TestEventFactory.java --- libwoodstox-java-4.1.3/src/test/java/org/codehaus/stax/test/evt/TestEventFactory.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/org/codehaus/stax/test/evt/TestEventFactory.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,342 @@ +package org.codehaus.stax.test.evt; + +import java.util.*; + +import javax.xml.namespace.QName; +import javax.xml.stream.*; +import javax.xml.stream.events.*; + +/** + * Class that contains simple tests for making sure that event objets + * created by the {@link XMLEventFactory} have expected properties. + * + * @author Tatu Saloranta + */ +public class TestEventFactory + extends BaseEventTest +{ + public void testAttribute() + throws XMLStreamException + { + XMLEventFactory f = getEventFactory(); + final String URI = "http://foo.com"; + + QName attrName = new QName(URI, "attr", "ns"); + Attribute attr = f.createAttribute(attrName, "value"); + + checkEventIsMethods(ATTRIBUTE, attr); + testEventWritability(attr); + + Attribute attr2 = f.createAttribute("ns", URI, "attr", "value'2'"); + Attribute attr3 = f.createAttribute("attr", "this&more"); + + /* No way to associate with a DTD, should have fairly basic + * settings: + */ + assertEquals("CDATA", attr.getDTDType()); + assertEquals("CDATA", attr2.getDTDType()); + assertEquals("CDATA", attr3.getDTDType()); + + /* 26-Jan-2008, TSa: Hmmh. Should these be constructed as + * defined/specified or not? + */ + if (!attr.isSpecified()) { + /* + assertTrue("Attribute 'ns:attr' should be created as 'defined'", + attr.isSpecified()); + assertTrue("Attribute 'ns:attr' should be created as 'defined'", + attr2.isSpecified()); + assertTrue("Attribute 'attr' should be created as 'defined'", + attr3.isSpecified()); + */ + warn("Attribute.isSpecified() returns false for XMLEventFactory generated Attribute events -- does that make sense?"); + } + assertEquals("value", attr.getValue()); + assertEquals("value'2'", attr2.getValue()); + assertEquals("this&more", attr3.getValue()); + + // Ok, then names... + assertEquals(attrName, attr.getName()); + assertEquals(attrName, attr2.getName()); + + QName name3 = attr3.getName(); + /* Alas, QName doesn't seem to retain nulls... so let's + * be bit more lenient here: + */ + assertEquals("attr", name3.getLocalPart()); + String str = name3.getPrefix(); + assertTrue(str == null || str.length() == 0); + str = name3.getNamespaceURI(); + assertTrue(str == null || str.length() == 0); + } + + public void testCData() + throws XMLStreamException + { + final String contents = "test text & more! [[]] --"; + XMLEventFactory f = getEventFactory(); + Characters c = f.createCData(contents); + checkEventIsMethods(CHARACTERS, c); + testEventWritability(c); + + assertEquals(contents, c.getData()); + assertTrue(c.isCData()); + assertFalse(c.isIgnorableWhiteSpace()); + assertFalse(c.isWhiteSpace()); + } + + public void testCharacters() + throws XMLStreamException + { + final String contents = "test text & more! [[]] --"; + XMLEventFactory f = getEventFactory(); + Characters c = f.createCharacters(contents); + + checkEventIsMethods(CHARACTERS, c); + testEventWritability(c); + + assertEquals(contents, c.getData()); + assertFalse(c.isCData()); + assertFalse(c.isIgnorableWhiteSpace()); + assertFalse(c.isWhiteSpace()); + } + + public void testComment() + throws XMLStreamException + { + final String content = "Comment - how interesting!"; + + XMLEventFactory f = getEventFactory(); + Comment c = f.createComment(content); + + checkEventIsMethods(COMMENT, c); + testEventWritability(c); + + assertEquals(content, c.getText()); + } + + public void testDTD() + throws XMLStreamException + { + XMLEventFactory f = getEventFactory(); + DTD d = f.createDTD(""); + + checkEventIsMethods(DTD, d); + testEventWritability(d); + + // !!! TBI + } + + public void testEndDocument() + throws XMLStreamException + { + XMLEventFactory f = getEventFactory(); + EndDocument ed = f.createEndDocument(); + + // No properties -- as long as we got instance of right type, it's ok + checkEventIsMethods(END_DOCUMENT, ed); + testEventWritability(ed); + } + + public void testEndElement() + throws XMLStreamException + { + XMLEventFactory f = getEventFactory(); + final String LOCALNAME = "elem"; + + // prefix, uri, localName + EndElement ee = f.createEndElement("", "", LOCALNAME); + checkEventIsMethods(END_ELEMENT, ee); + testEventWritability(ee); + + QName n = ee.getName(); + assertNotNull(n); + assertEquals(LOCALNAME, n.getLocalPart()); + } + + public void testEntityReference() + throws XMLStreamException + { +// XMLEventFactory f = getEventFactory(); + + /* 22-Dec-2005, TSa: ... but how can we create the entity declaration + * that is needed? Should null be ok? For now, can't really test... + */ + //EntityReference ref = f.createEntityReference("ref", decl); + //checkEventIsMethods(ENTITY_REFERENCE, ref); + //testEventWritability(ref); + } + + public void testIgnorableSpace() + throws XMLStreamException + { + final String contents = " \t \n "; + XMLEventFactory f = getEventFactory(); + Characters c = f.createIgnorableSpace(contents); + + checkEventIsMethods(CHARACTERS, c); + testEventWritability(c); + + assertEquals(contents, c.getData()); + assertFalse(c.isCData()); + assertTrue(c.isIgnorableWhiteSpace()); + assertTrue(c.isWhiteSpace()); + } + + public void testNamespace() + throws XMLStreamException + { + XMLEventFactory f = getEventFactory(); + final String PREFIX = "prefix"; + final String URI = "http://foo"; + + // First default: + Namespace ns = f.createNamespace(URI); + + checkEventIsMethods(NAMESPACE, ns); + testEventWritability(ns); + + String prefix = ns.getPrefix(); + // Both null and empty are ok? + if (prefix != null && prefix.length() > 0) { + fail("Expected prefix to be null or empty for default namespace event object"); + } + assertEquals(URI, ns.getNamespaceURI()); + assertTrue(ns.isDefaultNamespaceDeclaration()); + + // Then non-default: + ns = f.createNamespace(PREFIX, URI); + checkEventIsMethods(NAMESPACE, ns); + assertEquals(PREFIX, ns.getPrefix()); + assertEquals(URI, ns.getNamespaceURI()); + assertFalse(ns.isDefaultNamespaceDeclaration()); + } + + public void testProcInstr() + throws XMLStreamException + { + XMLEventFactory f = getEventFactory(); + ProcessingInstruction pi = f.createProcessingInstruction("target", "data"); + checkEventIsMethods(PROCESSING_INSTRUCTION, pi); + testEventWritability(pi); + + assertEquals("target", pi.getTarget()); + assertEquals("data", pi.getData()); + + } + + public void testSpace() + throws XMLStreamException + { + final String contents = " \t \n "; + XMLEventFactory f = getEventFactory(); + Characters c = f.createSpace(contents); + assertEquals(contents, c.getData()); + + checkEventIsMethods(CHARACTERS, c); + testEventWritability(c); + + assertFalse(c.isCData()); + assertFalse(c.isIgnorableWhiteSpace()); + assertTrue(c.isWhiteSpace()); + } + + public void testStartDocument() + throws XMLStreamException + { + XMLEventFactory f = getEventFactory(); + StartDocument sd = f.createStartDocument(); + checkEventIsMethods(START_DOCUMENT, sd); + testEventWritability(sd); + + assertFalse(sd.encodingSet()); + assertFalse(sd.standaloneSet()); + + final String ENCODING = "ISO-8859-1"; + final String VERSION = "1.0"; + sd = f.createStartDocument(ENCODING, VERSION, true); + checkEventIsMethods(START_DOCUMENT, sd); + assertTrue("Expected StartDocument.encodingSet() to be true when constructing via factory method that passes in non-empty encoding value", sd.encodingSet()); + assertTrue(sd.standaloneSet()); + assertEquals(ENCODING, sd.getCharacterEncodingScheme()); + assertEquals(VERSION, sd.getVersion()); + } + + public void testStartElement() + throws XMLStreamException + { + final String LOCALNAME = "root"; + final String PREFIX = "ns"; + final String URI = "urn:whatever"; + + XMLEventFactory f = getEventFactory(); + // prefix, uri, localname + StartElement se = f.createStartElement("", "", LOCALNAME); + testEventWritability(se); + + checkEventIsMethods(START_ELEMENT, se); + QName n = se.getName(); + assertNotNull(n); + assertEquals(LOCALNAME, n.getLocalPart()); + + se = f.createStartElement(PREFIX, URI, LOCALNAME); + checkEventIsMethods(START_ELEMENT, se); + n = se.getName(); + assertNotNull(n); + assertEquals(LOCALNAME, n.getLocalPart()); + assertEquals(PREFIX, n.getPrefix()); + assertEquals(URI, n.getNamespaceURI()); + } + + public void testStartElementWithAttrs() + throws XMLStreamException + { + final String NS_URI = "http://foo"; + + XMLEventFactory f = getEventFactory(); + ArrayList attrs = new ArrayList(); + Attribute attr1 = f.createAttribute(new QName("attr1"), "value"); + testEventWritability(attr1); + attrs.add(attr1); + checkEventIsMethods(ATTRIBUTE, attr1); + attrs.add(f.createAttribute(new QName(NS_URI, "attr2"), "value2")); + + // Ok, so let's create the start element, and check it's ok: + StartElement se = f.createStartElement(new QName("root"), + attrs.iterator(), null); + testEventWritability(se); + checkEventIsMethods(START_ELEMENT, se); + QName n = se.getName(); + assertNotNull(n); + assertEquals("root", n.getLocalPart()); + + // Then let's check both existing attrs: + Attribute resultAttr = se.getAttributeByName(new QName("attr1")); + assertNotNull(resultAttr); + n = resultAttr.getName(); + assertEquals("attr1", n.getLocalPart()); + assertEquals("value", resultAttr.getValue()); + + resultAttr = se.getAttributeByName(new QName(NS_URI, "attr2")); + assertNotNull(resultAttr); + n = resultAttr.getName(); + assertEquals("attr2", n.getLocalPart()); + assertEquals("value2", resultAttr.getValue()); + + // Then non-existing ones (switch ns URIs around) + assertNull(se.getAttributeByName(new QName(NS_URI, "attr1"))); + assertNull(se.getAttributeByName(new QName("attr2"))); + + // and finally raw count + Iterator it = se.getAttributes(); + assertNotNull(it); + int count = 0; + + while (it.hasNext()) { + it.next(); + ++count; + } + assertEquals(2, count); + } +} + diff -Nru libwoodstox-java-4.1.3/src/test/java/org/codehaus/stax/test/evt/TestEventReader.java libwoodstox-java-5.1.0/src/test/java/org/codehaus/stax/test/evt/TestEventReader.java --- libwoodstox-java-4.1.3/src/test/java/org/codehaus/stax/test/evt/TestEventReader.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/org/codehaus/stax/test/evt/TestEventReader.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,372 @@ +package org.codehaus.stax.test.evt; + +import java.util.NoSuchElementException; + +import javax.xml.stream.*; +import javax.xml.stream.events.*; + +/** + * Class that contains simple tests for making sure that event objects + * created by the {@link XMLEventFactory} have expected properties. + * + * @author Tatu Saloranta + */ +public class TestEventReader + extends BaseEventTest +{ + public void testSimpleValid() + throws XMLStreamException + { + /* Whether prolog/epilog white space is reported is not defined + * by StAX specs, thus, let's not add any + */ + String XML = "" + +"" + +"\n" + +""; + + for (int i = 0; i < 4; ++i) { + boolean ns = (i & 1) != 0; + boolean coal = (i & 2) != 0; + XMLEventReader er = getReader(XML, ns, coal); + + assertTokenType(START_DOCUMENT, er.nextEvent().getEventType()); + assertTokenType(DTD, er.nextEvent().getEventType()); + assertTokenType(START_ELEMENT, er.nextEvent().getEventType()); + assertTokenType(COMMENT, er.nextEvent().getEventType()); + // for fun, let's just use next() instead of nextEvent() + XMLEvent evt = (XMLEvent) er.next(); + assertTokenType(CHARACTERS, evt.getEventType()); + assertTokenType(END_ELEMENT, er.nextEvent().getEventType()); + assertTokenType(END_DOCUMENT, er.nextEvent().getEventType()); + assertFalse(er.hasNext()); + er.close(); + } + } + + public void testInvalidUsage() + throws XMLStreamException + { + String XML = ""; + for (int i = 0; i < 4; ++i) { + boolean ns = (i & 1) != 0; + boolean coal = (i & 2) != 0; + XMLEventReader er = getReader(XML, ns, coal); + + @SuppressWarnings("unused") + XMLEvent evt = (XMLEvent) er.nextEvent(); + + // Let's try removal: + String msg = null; + try { + er.remove(); + msg = "Was expecting UnsupportedOperationException for XMLEventReader.remove()"; + } catch (UnsupportedOperationException e) { + ; // good + } catch (Throwable t) { + msg = "Was expecting UnsupportedOperationException for XMLEventReader.remove(); instead got: "+t; + } + if (msg != null) { + fail(msg); + } + } + } + + /** + * The main purpose of this test is to ensure that an exception + * is thrown at the end. + */ + public void testIterationEndException() + throws XMLStreamException + { + String XML = ""; + + for (int i = 0; i < 4; ++i) { + boolean coal = (i & 1) != 0; + boolean checkHasNext = (i & 2) != 0; + XMLEventReader er = getReader(XML, true, coal); + + assertTokenType(START_DOCUMENT, er.nextEvent().getEventType()); + assertTokenType(START_ELEMENT, er.nextEvent().getEventType()); + assertTokenType(END_ELEMENT, er.nextEvent().getEventType()); + assertTokenType(END_DOCUMENT, er.nextEvent().getEventType()); + + if (checkHasNext) { + assertFalse(er.hasNext()); + } + + XMLEvent ev = null; + try { + ev = er.nextEvent(); + } catch (NoSuchElementException nex) { + continue; // good + } catch (Throwable t) { + fail("Expected a NoSuchElementException after iterating through the document; got "+t); + } + + // Shouldn't get this far... + fail("Expected a NoSuchElementException after iterating through the document; got event: "+ev); + } + } + + public void testNextTagOk() + throws XMLStreamException + { + String XML = "\n" + +" " + +""; + + for (int i = 0; i < 4; ++i) { + boolean ns = (i & 1) != 0; + boolean coal = (i & 2) != 0; + XMLEventReader er = getReader(XML, ns, coal); + + assertTokenType(START_DOCUMENT, er.nextEvent().getEventType()); + + assertTokenType(START_ELEMENT, er.nextTag().getEventType()); + assertTokenType(START_ELEMENT, er.nextTag().getEventType()); + /* Ok, let's mix in bit of peeking to ensure reader won't + * be confused too badly... + */ + // This should be space between and ... + assertTokenType(CHARACTERS, er.peek().getEventType()); + + // And then the leaf + assertTokenType(START_ELEMENT, er.nextTag().getEventType()); + + assertTokenType(END_ELEMENT, er.nextTag().getEventType()); + assertTokenType(END_ELEMENT, er.nextTag().getEventType()); + assertTokenType(END_ELEMENT, er.nextTag().getEventType()); + + assertTokenType(END_DOCUMENT, er.nextEvent().getEventType()); + assertFalse(er.hasNext()); + } + } + + public void testNextTagInvalid() + throws XMLStreamException + { + String XML = " non-empty"; + String XML2 = "text "; + + for (int i = 0; i < 4; ++i) { + boolean ns = (i & 1) != 0; + boolean coal = (i & 2) != 0; + XMLEventReader er = getReader(XML, ns, coal); + assertTokenType(START_DOCUMENT, er.nextEvent().getEventType()); + assertTokenType(START_ELEMENT, er.nextEvent().getEventType()); + String msg = null; + try { + /*XMLEvent evt =*/ er.nextTag(); + msg = "Expected a XMLStreamException when trying to call XMLEventReader.nextTag() on non-empty CHARACTERS"; + } catch (XMLStreamException sex) { + // fine! + } catch (Throwable t) { + msg = "Expected a XMLStreamException when trying to call XMLEventReader.nextTag() on non-empty CHARACTERS; got ("+t.getClass()+"): "+t; + } + if (msg != null) { + fail(msg); + } + er.close(); + + /* any other easily failing cases? Maybe if we are on top of + * END_ELEMENT, and will hit another one? + */ + er = getReader(XML2, ns, coal); + assertTokenType(START_DOCUMENT, er.nextEvent().getEventType()); + assertTokenType(START_ELEMENT, er.nextEvent().getEventType()); + assertTokenType(START_ELEMENT, er.nextEvent().getEventType()); + assertTokenType(END_ELEMENT, er.nextEvent().getEventType()); + + try { + XMLEvent evt = er.nextTag(); + msg = "Expected a XMLStreamException when trying to call XMLEventReader.nextTag() on END_ELEMENT and hitting non-ws text; got event "+tokenTypeDesc(evt); + } catch (XMLStreamException sex) { + msg = null; // fine! + } catch (Throwable t) { + msg = "Expected a XMLStreamException when trying to call XMLEventReader.nextTag() on END_ELEMENT and hitting non-ws text; got: "+t; + } + if (msg != null) { + fail(msg); + } + er.close(); + } + } + + public void testSkip() + throws XMLStreamException + { + String XML = "\n" + +" " + +""; + + for (int i = 0; i < 4; ++i) { + boolean ns = (i & 1) != 0; + boolean coal = (i & 2) != 0; + XMLEventReader er = getReader(XML, ns, coal); + + assertTokenType(START_DOCUMENT, er.peek().getEventType()); + assertTokenType(START_DOCUMENT, er.nextEvent().getEventType()); + assertTokenType(DTD, er.peek().getEventType()); + assertTokenType(DTD, er.nextEvent().getEventType()); + assertTokenType(START_ELEMENT, er.peek().getEventType()); + assertTokenType(START_ELEMENT, er.nextEvent().getEventType()); + + assertTokenType(CHARACTERS, er.peek().getEventType()); + assertTokenType(CHARACTERS, er.nextEvent().getEventType()); + + // branch + assertTokenType(START_ELEMENT, er.peek().getEventType()); + assertTokenType(START_ELEMENT, er.nextEvent().getEventType()); + assertTokenType(CHARACTERS, er.peek().getEventType()); + assertTokenType(CHARACTERS, er.nextEvent().getEventType()); + + // leaf + assertTokenType(START_ELEMENT, er.peek().getEventType()); + assertTokenType(START_ELEMENT, er.nextEvent().getEventType()); + assertTokenType(CHARACTERS, er.peek().getEventType()); + assertTokenType(CHARACTERS, er.nextEvent().getEventType()); + assertTokenType(END_ELEMENT, er.peek().getEventType()); + assertTokenType(END_ELEMENT, er.nextEvent().getEventType()); + + assertTokenType(END_ELEMENT, er.peek().getEventType()); + assertTokenType(END_ELEMENT, er.nextEvent().getEventType()); + + assertTokenType(COMMENT, er.peek().getEventType()); + assertTokenType(COMMENT, er.nextEvent().getEventType()); + assertTokenType(END_ELEMENT, er.peek().getEventType()); + assertTokenType(END_ELEMENT, er.nextEvent().getEventType()); + + assertTokenType(END_DOCUMENT, er.peek().getEventType()); + assertTokenType(END_DOCUMENT, er.nextEvent().getEventType()); + assertFalse(er.hasNext()); + } + } + + /** + * This test was inspired by an actual bug in one of implementations: + * initial state was not properly set if nextTag() was called (instead + * of nextEvent()), and subsequent peek() failed. + */ + public void testPeek() + throws XMLStreamException + { + String XML = "text"; + + for (int i = 0; i < 4; ++i) { + boolean ns = (i & 1) != 0; + boolean coal = (i & 2) != 0; + XMLEventReader er = getReader(XML, ns, coal); + assertTokenType(START_DOCUMENT, er.nextEvent().getEventType()); + + XMLEvent tag = er.nextTag(); + assertTokenType(START_ELEMENT, tag.getEventType()); + + // Now, peek() should produce text.. + XMLEvent text = er.peek(); + assertTokenType(CHARACTERS, text.getEventType()); + Characters chars = text.asCharacters(); + assertNotNull(chars); + assertEquals("text", chars.getData()); + + // and need nextEvent() to get rid of it, too: + text = er.nextEvent(); + // Let's verify it again: + assertTokenType(CHARACTERS, text.getEventType()); + chars = text.asCharacters(); + assertNotNull(chars); + assertEquals("text", chars.getData()); + assertTokenType(END_ELEMENT, er.nextTag().getEventType()); + assertTokenType(END_DOCUMENT, er.nextEvent().getEventType()); + + // And at the end, peek() should return null + assertNull(er.peek()); + } + } + + public void testElementText() + throws XMLStreamException + { + String TEXT1 = "some\ntest"; + String TEXT2 = "inside CDATA too!"; + + String XML = ""+TEXT1+""; + + // First, let's see how things work without peeking: + for (int i = 0; i < 4; ++i) { + boolean ns = (i & 1) != 0; + boolean coal = (i & 2) != 0; + XMLEventReader er = getReader(XML, ns, coal); + assertTokenType(START_DOCUMENT, er.nextEvent().getEventType()); + XMLEvent elem = er.nextEvent(); + assertTokenType(START_ELEMENT, elem.getEventType()); + + try { + assertEquals(TEXT1+TEXT2, er.getElementText()); + } catch (XMLStreamException sex) { + fail("Failed on XMLEventReader.getElementText(): "+sex); + } + + /* 06-Jan-2006, TSa: I'm really not sure whether to expect + * END_ELEMENT, or END_DOCUMENT here... maybe the latter + * makes more sense? For now let's accept both, however. + */ + elem = er.nextEvent(); + if (elem.getEventType() != END_DOCUMENT + && elem.getEventType() != END_ELEMENT) { + fail("Expected END_DOCUMENT or END_ELEMENT, got "+tokenTypeDesc(elem.getEventType())); + } + } + + // and then with peeking: + for (int i = 0; i < 4; ++i) { + boolean ns = (i & 1) != 0; + boolean coal = (i & 2) != 0; + XMLEventReader er = getReader(XML, ns, coal); + assertTokenType(START_DOCUMENT, er.nextEvent().getEventType()); + XMLEvent elem = er.nextEvent(); + assertTokenType(START_ELEMENT, elem.getEventType()); + XMLEvent peeked = er.peek(); + assertTokenType(CHARACTERS, peeked.getEventType()); + assertEquals(TEXT1+TEXT2, er.getElementText()); + + /* 06-Jan-2006, TSa: I'm really not sure whether to expect + * END_ELEMENT, or END_DOCUMENT here... maybe the latter + * makes more sense? For now let's accept both, however. + */ + elem = er.nextEvent(); + + if (elem.getEventType() != END_DOCUMENT + && elem.getEventType() != END_ELEMENT) { + fail("Expected END_DOCUMENT or END_ELEMENT, got "+tokenTypeDesc(elem.getEventType())); + } + } + } + + /* + ///////////////////////////////////////////////// + // Internal methods: + ///////////////////////////////////////////////// + */ + + private XMLEventReader getReader(String contents, boolean nsAware, + boolean coalesce) + throws XMLStreamException + { + return getReader(contents, nsAware, coalesce, true); + } + + private XMLEventReader getReader(String contents, boolean nsAware, + boolean coalesce, boolean expandEnt) + throws XMLStreamException + { + //XMLInputFactory f = getInputFactory(); + XMLInputFactory f = getNewInputFactory(); + setNamespaceAware(f, nsAware); + setCoalescing(f, coalesce); + setSupportDTD(f, true); + setValidating(f, false); + setReplaceEntities(f, expandEnt); + return constructEventReader(f, contents); + } +} diff -Nru libwoodstox-java-4.1.3/src/test/java/org/codehaus/stax/test/evt/TestEventTypes.java libwoodstox-java-5.1.0/src/test/java/org/codehaus/stax/test/evt/TestEventTypes.java --- libwoodstox-java-4.1.3/src/test/java/org/codehaus/stax/test/evt/TestEventTypes.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/org/codehaus/stax/test/evt/TestEventTypes.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,172 @@ +package org.codehaus.stax.test.evt; + +import javax.xml.namespace.QName; +import javax.xml.stream.*; +import javax.xml.stream.events.*; + +/** + * Class that contains simple tests for making sure that event types + * produced have expected settings. + * + * @author Tatu Saloranta + */ +public class TestEventTypes + extends BaseEventTest +{ + public void testTypes() + throws XMLStreamException + { + doTestTypes(false); // non-namespace + doTestTypes(true); // namespace-aware + } + + /* + //////////////////////////////////////// + // Private methods, tests + //////////////////////////////////////// + */ + + private void doTestTypes(boolean useNs) + throws XMLStreamException + { + String INPUT = + "" + +"" + +"" + +"" + +"some text" + +""; + + XMLEventReader er = getReader(INPUT, useNs); + + // First, should get START_DOCUMENT: + XMLEvent evt = er.nextEvent(); + assertEquals(START_DOCUMENT, evt.getEventType()); + assertTrue(evt.isStartDocument()); + { + StartDocument doc = (StartDocument) evt; + assertFalse(doc.encodingSet()); + /* Not sure how to test getCharacterEncodingScheme(); problem + * is, XML parser are allowed to auto-detect things... but don't + * have to. + */ + // ... same is true about system id too + + if (doc.standaloneSet()) { + fail("Reporting stand-alone as set, even though xml declaration has no value (should assume 'false')"); + } + + // I guess parser should NOT think it is stand-alone without decl? + assertFalse("Should assume 'no' as stand-alone value if no extra information", doc.isStandalone()); + } + + // Then, proc. instr: + evt = er.nextEvent(); + assertEquals(PROCESSING_INSTRUCTION, evt.getEventType()); + assertTrue(evt.isProcessingInstruction()); + { + ProcessingInstruction pi = (ProcessingInstruction) evt; + assertEquals("proc", pi.getTarget()); + // data may or may not contain the space between target and data... + String data = pi.getData().trim(); + assertEquals("instr", data); + } + + // Then COMMENT + evt = er.nextEvent(); + assertEquals(COMMENT, evt.getEventType()); + { + Comment c = (Comment) evt; + assertEquals("comment - - contents", c.getText()); + } + + // Then DTD + evt = er.nextEvent(); + assertEquals(DTD, evt.getEventType()); + { + DTD dtd = (DTD) evt; + checkEventIsMethods(DTD, dtd); + testEventWritability(dtd); + assertNotNull(dtd.getDocumentTypeDeclaration()); + } + + // Then START_ELEMENT + evt = er.nextEvent(); + assertEquals(START_ELEMENT, evt.getEventType()); + assertTrue(evt.isStartElement()); + QName elemName; + + { + StartElement elem = evt.asStartElement(); + elemName = elem.getName(); + assertEquals("root", elemName.getLocalPart()); + + assertEquals(1, calcAttrCount(elem)); + + Attribute noSuchAttr = elem.getAttributeByName(new QName("foobar")); + assertNull("Should not have found attribute 'foobar' from the element", noSuchAttr); + + Attribute attr = elem.getAttributeByName(new QName("attr")); + assertNotNull("Should have found attribute 'attr' from the element", attr); + assertTrue(attr.isAttribute()); + assertEquals("value", attr.getValue()); + assertEquals("CDATA", attr.getDTDType()); + assertTrue(attr.isSpecified()); + QName an = attr.getName(); + assertEquals("attr", an.getLocalPart()); + } + + // Then CHARACTERS + evt = er.nextEvent(); + assertEquals(CHARACTERS, evt.getEventType()); + assertTrue(evt.isCharacters()); + { + Characters ch = evt.asCharacters(); + assertFalse(ch.isCData()); + assertFalse(ch.isIgnorableWhiteSpace()); + assertFalse(ch.isWhiteSpace()); + assertEquals("some text", ch.getData()); + } + + // Then END_ELEMENT + evt = er.nextEvent(); + assertEquals(END_ELEMENT, evt.getEventType()); + assertTrue(evt.isEndElement()); + { + EndElement elem = evt.asEndElement(); + QName endName = elem.getName(); + assertEquals("root", endName.getLocalPart()); + // Let's also verify it's equal to the start element name... + assertEquals(elemName, endName); + } + + // And finally END_DOCUMENT + evt = er.nextEvent(); + assertEquals(END_DOCUMENT, evt.getEventType()); + assertTrue(evt.isEndDocument()); + // Nothing to test, but let's case to ensure it's of right type + { + @SuppressWarnings("unused") + EndDocument doc = (EndDocument) evt; + } + } + + /* + //////////////////////////////////////// + // Private methods, other + //////////////////////////////////////// + */ + + private XMLEventReader getReader(String contents, boolean nsAware) + throws XMLStreamException + { + XMLInputFactory f = getInputFactory(); + setCoalescing(f, true); + setNamespaceAware(f, nsAware); + setValidating(f, false); + setSupportDTD(f, true); + return constructEventReader(f, contents); + } + +} + diff -Nru libwoodstox-java-4.1.3/src/test/java/org/codehaus/stax/test/evt/TestEventWriter.java libwoodstox-java-5.1.0/src/test/java/org/codehaus/stax/test/evt/TestEventWriter.java --- libwoodstox-java-4.1.3/src/test/java/org/codehaus/stax/test/evt/TestEventWriter.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/org/codehaus/stax/test/evt/TestEventWriter.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,187 @@ +package org.codehaus.stax.test.evt; + +import java.io.StringWriter; +import java.util.*; + +import javax.xml.stream.*; +import javax.xml.stream.events.*; + +/** + * Class that contains simple tests for making sure that event objects + * get serialized properly when using {@link XMLEventWriter}. + * + * @author Tatu Saloranta + */ +public class TestEventWriter + extends BaseEventTest +{ + public void testNonRepairingNsWrite() + throws XMLStreamException + { + XMLOutputFactory f = getOutputFactory(); + StringWriter strw = new StringWriter(); + XMLEventWriter w = f.createXMLEventWriter(strw); + + XMLEventFactory evtf = getEventFactory(); + + ArrayList attrs = new ArrayList(); + attrs.add(evtf.createAttribute("attr", "value")); + attrs.add(evtf.createAttribute("ns", "uri", "attr2", "value2")); + ArrayList ns = new ArrayList(); + ns.add(evtf.createNamespace("ns", "uri")); + StartElement elem = evtf.createStartElement("", "", "root", attrs.iterator(), ns.iterator()); + + w.add(elem); + w.add(evtf.createEndElement("", "", "root")); + w.close(); + + // Ok, let's read it back: + String contents = strw.toString(); + + XMLStreamReader sr = getReader(contents, true, true); + + assertTokenType(START_DOCUMENT, sr.getEventType()); + assertTokenType(START_ELEMENT, sr.next()); + + assertEquals("root", sr.getLocalName()); + assertEquals(2, sr.getAttributeCount()); + + // Ordering of attrs is not guaranteed... + String ln = sr.getAttributeLocalName(0); + if (ln.equals("attr")) { + assertEquals("attr2", sr.getAttributeLocalName(1)); + assertEquals("ns", sr.getAttributePrefix(1)); + assertEquals("uri", sr.getAttributeNamespace(1)); + } else if (ln.equals("attr2")) { + assertEquals("attr", sr.getAttributeLocalName(1)); + assertEquals("ns", sr.getAttributePrefix(0)); + assertEquals("uri", sr.getAttributeNamespace(0)); + } else { + fail("Unexpected attr local name '"+ln+"' for attribute #0; expected 'attr' or 'attr2'"); + } + + assertTokenType(END_ELEMENT, sr.next()); + } + + /** + * The idea of this test is to basically verify that given a simplish + * input document, we can parse, output and re-parse it; and second + * time around still get the same events (at least by type, and maybe + * doing some simple sanity checks). + */ + @SuppressWarnings("unchecked") + public void testPassThrough() + throws XMLStreamException + { + final String INPUT = + "" + +"\n" + +"\n" + +" \n" + +" \n" + +" \n" + +" ]]>\n" + +" \n" + +" " + +""; + ; + XMLEventReader er = getEventReader(INPUT, true, true); + List list1 = collectEvents(er); + + StringWriter strw = new StringWriter(); + XMLOutputFactory f = getOutputFactory(); + XMLEventWriter ew = f.createXMLEventWriter(strw); + Iterator it = list1.iterator(); + while (it.hasNext()) { + ew.add(it.next()); + } + + // And re-parse... + er = getEventReader(INPUT, true, true); + List list2 = collectEvents(er); + + assertEquals("Should have gotten same number of events", + list1.size(), list2.size()); + + // And finally, let's at least compare types we have: + it = list1.iterator(); + Iterator it2 = list2.iterator(); + + for (int ix = 0; it.hasNext(); ++ix) { + XMLEvent evt1 = it.next(); + XMLEvent evt2 = it2.next(); + + if (evt1.getEventType() != evt2.getEventType()) { + fail("Event #"+ix+"; first time got event "+evt1.getEventType() + +", second time "+evt2.getEventType()); + } + + if (evt1.isStartElement()) { + /* ok, should have same attrs and ns decls. For now, let's + * just verify raw counts; can/should test contents too + * in future. + */ + StartElement se1 = evt1.asStartElement(); + StartElement se2 = evt2.asStartElement(); + List attrs1 = fetchElems((Iterator)se1.getAttributes()); + List attrs2 = fetchElems((Iterator)se2.getAttributes()); + assertEquals(attrs1.size(), attrs2.size()); + + List ns1 = fetchElems((Iterator)se1.getNamespaces()); + List ns2 = fetchElems((Iterator)se2.getNamespaces()); + assertEquals(ns1.size(), ns2.size()); + } + } + } + + private List fetchElems(Iterator it) + { + ArrayList l = new ArrayList(); + while (it.hasNext()) { + l.add(it.next()); + } + return l; + } + + /* + /////////////////////////////////////////////////////////// + // Private methods, other + /////////////////////////////////////////////////////////// + */ + + private XMLStreamReader getReader(String contents, boolean nsAware, + boolean coalesce) + throws XMLStreamException + { + XMLInputFactory f = getInputFactory(); + setNamespaceAware(f, nsAware); + setCoalescing(f, coalesce); + setSupportDTD(f, true); + setValidating(f, false); + return constructStreamReader(f, contents); + } + + private XMLEventReader getEventReader(String contents, boolean nsAware, + boolean coalesce) + throws XMLStreamException + { + XMLInputFactory f = getInputFactory(); + setNamespaceAware(f, nsAware); + setCoalescing(f, coalesce); + setSupportDTD(f, true); + setValidating(f, false); + XMLStreamReader sr = constructStreamReader(f, contents); + return f.createXMLEventReader(sr); + } + + private List collectEvents(XMLEventReader er) + throws XMLStreamException + { + ArrayList events = new ArrayList(); + while (er.hasNext()) { + events.add(er.nextEvent()); + } + return events; + } +} diff -Nru libwoodstox-java-4.1.3/src/test/java/org/codehaus/stax/test/evt/TestFilteredReader.java libwoodstox-java-5.1.0/src/test/java/org/codehaus/stax/test/evt/TestFilteredReader.java --- libwoodstox-java-4.1.3/src/test/java/org/codehaus/stax/test/evt/TestFilteredReader.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/org/codehaus/stax/test/evt/TestFilteredReader.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,63 @@ +package org.codehaus.stax.test.evt; + +import javax.xml.stream.*; +import javax.xml.stream.events.*; + +/** + * Simple unit test suite that tries to if filtered stream readers are + * constructed and can be used. + *

+ * One thing to note, though, is that the StAX specs do not tell much + * anything about expected ways that the implementation is to deal with + * problems resulting from filtering END_DOCUMENT event and so forth. + * + * @author Tatu Saloranta + */ +public class TestFilteredReader + extends BaseEventTest +{ + /** + * Simplest possible test: let's only check that we can actually + * construct an instance with dummy filter that accepts everything, + * and that we can traverse through all the events as usual. + */ + public void testCreation() + throws XMLStreamException + { + XMLEventReader er = createFilteredReader(new MyFilter(), "text", true); + + assertTokenType(START_DOCUMENT, er.nextEvent().getEventType()); + XMLEvent evt = er.nextEvent(); + assertTokenType(START_ELEMENT, evt.getEventType()); + assertNotNull(evt.asStartElement().getName()); + assertTokenType(CHARACTERS, er.nextEvent().getEventType()); + assertTokenType(END_ELEMENT, er.nextEvent().getEventType()); + assertTokenType(END_DOCUMENT, er.nextEvent().getEventType()); + } + + /* + //////////////////////////////////////// + // Non-test methods + //////////////////////////////////////// + */ + + private XMLEventReader createFilteredReader(EventFilter filter, String content, + boolean nsAware) + throws XMLStreamException + { + XMLInputFactory f = getInputFactory(); + setNamespaceAware(f, nsAware); + XMLEventReader base = constructEventReader(f, content); + return f.createFilteredReader(base, filter); + } + + final static class MyFilter + implements EventFilter + { + @Override + public boolean accept(XMLEvent event) { + return true; + } + } +} + diff -Nru libwoodstox-java-4.1.3/src/test/java/org/codehaus/stax/test/evt/TestStartDocument.java libwoodstox-java-5.1.0/src/test/java/org/codehaus/stax/test/evt/TestStartDocument.java --- libwoodstox-java-4.1.3/src/test/java/org/codehaus/stax/test/evt/TestStartDocument.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/org/codehaus/stax/test/evt/TestStartDocument.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,175 @@ +package org.codehaus.stax.test.evt; + +import javax.xml.namespace.QName; +import javax.xml.stream.*; +import javax.xml.stream.events.*; + +/** + * Class that tests basic dealing of the StartDocument event (skipping, + * accessing) + * + * @author Tatu Saloranta + */ +public class TestStartDocument + extends BaseEventTest +{ + /** + * First, let's see what happens when there's no decl + */ + public void testTrivialValid() + throws XMLStreamException + { + String XML = ""; + for (int i = 0; i < 4; ++i) { + boolean ns = (i & 1) != 0; + boolean coal = (i & 2) != 0; + XMLEventReader er = getReader(XML, ns, coal); + + // First, explicit access without peek + XMLEvent evt = er.nextEvent(); + assertTrue(evt.isStartDocument()); + StartDocument devt = (StartDocument) evt; + assertFalse(devt.encodingSet()); + assertFalse("Stand-alone should not be assumed true if not included in xml declaration", devt.standaloneSet()); + // Version is to default to "1.0", as per stax 1.0 javadocs + assertEquals("1.0", devt.getVersion()); + er.close(); + } + + // And then let's check with peeking: + for (int i = 0; i < 4; ++i) { + boolean ns = (i & 1) != 0; + boolean coal = (i & 2) != 0; + XMLEventReader er = getReader(XML, ns, coal); + XMLEvent evt = er.peek(); + assertTrue(evt.isStartDocument()); + StartDocument devt = (StartDocument) evt; + assertFalse(devt.encodingSet()); + assertFalse(devt.standaloneSet()); + // Version is to default to "1.0", as per stax 1.0 javadocs + assertEquals("1.0", devt.getVersion()); + er.close(); + + // And then let's see that we can still access it normally too + evt = er.peek(); + assertTrue(evt.isStartDocument()); + // and cast just for fun (to check it really is startdoc event) + devt = (StartDocument) evt; + } + } + + public void testNormalValid() + throws XMLStreamException + { + String XML = "" + +""; + for (int i = 0; i < 4; ++i) { + boolean ns = (i & 1) != 0; + boolean coal = (i & 2) != 0; + XMLEventReader er = getReader(XML, ns, coal); + + // First, explicit access without peek + XMLEvent evt = er.nextEvent(); + assertTrue(evt.isStartDocument()); + StartDocument devt = (StartDocument) evt; + assertEquals("1.0", devt.getVersion()); + assertTrue(devt.encodingSet()); + assertEquals("UTF-8", devt.getCharacterEncodingScheme()); + assertTrue(devt.standaloneSet()); + assertTrue(devt.isStandalone()); + er.close(); + } + + // And then let's check with peeking: + for (int i = 0; i < 4; ++i) { + boolean ns = (i & 1) != 0; + boolean coal = (i & 2) != 0; + XMLEventReader er = getReader(XML, ns, coal); + + XMLEvent evt = er.peek(); + assertTrue(evt.isStartDocument()); + StartDocument devt = (StartDocument) evt; + assertEquals("1.0", devt.getVersion()); + assertTrue(devt.encodingSet()); + assertEquals("UTF-8", devt.getCharacterEncodingScheme()); + assertTrue(devt.standaloneSet()); + assertTrue(devt.isStandalone()); + er.close(); + + // And then let's see that we can still access it normally too + evt = er.peek(); + assertTrue(evt.isStartDocument()); + // and cast just for fun (to check it really is startdoc event) + devt = (StartDocument) evt; + } + } + + /** + * Let's also quickly verify that we can skip xml declaration (actual + * or virtual) to the root element -- should work ok. + */ + public void testNextEvent() + throws XMLStreamException + { + String XML = ""; + for (int i = 0; i < 4; ++i) { + boolean ns = (i & 1) != 0; + boolean coal = (i & 2) != 0; + XMLEventReader er = getReader(XML, ns, coal); + + XMLEvent evt = er.nextTag(); + assertNotNull(evt); + assertTrue(evt.isStartElement()); + StartElement elem = evt.asStartElement(); + QName n = elem.getName(); + assertNotNull(n); + assertEquals("root", n.getLocalPart()); + } + + XML = "" + +""; + for (int i = 0; i < 4; ++i) { + boolean ns = (i & 1) != 0; + boolean coal = (i & 2) != 0; + XMLEventReader er = getReader(XML, ns, coal); + XMLEvent evt = er.peek(); + + assertTrue(evt.isStartDocument()); + + // Fine, and then should get the start elem anyways + evt = er.nextTag(); + assertNotNull(evt); + assertTrue(evt.isStartElement()); + StartElement elem = evt.asStartElement(); + QName n = elem.getName(); + assertNotNull(n); + assertEquals("root", n.getLocalPart()); + } + } + + /* + ///////////////////////////////////////////////// + // Internal methods: + ///////////////////////////////////////////////// + */ + + private XMLEventReader getReader(String contents, boolean nsAware, + boolean coalesce) + throws XMLStreamException + { + return getReader(contents, nsAware, coalesce, true); + } + + private XMLEventReader getReader(String contents, boolean nsAware, + boolean coalesce, boolean expandEnt) + throws XMLStreamException + { + XMLInputFactory f = getInputFactory(); + setNamespaceAware(f, nsAware); + setCoalescing(f, coalesce); + setSupportDTD(f, true); + setValidating(f, false); + setReplaceEntities(f, expandEnt); + return constructEventReader(f, contents); + } +} diff -Nru libwoodstox-java-4.1.3/src/test/java/org/codehaus/stax/test/evt/TestStartElem.java libwoodstox-java-5.1.0/src/test/java/org/codehaus/stax/test/evt/TestStartElem.java --- libwoodstox-java-4.1.3/src/test/java/org/codehaus/stax/test/evt/TestStartElem.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/org/codehaus/stax/test/evt/TestStartElem.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,388 @@ +package org.codehaus.stax.test.evt; + +import java.util.*; + +import javax.xml.namespace.NamespaceContext; +import javax.xml.namespace.QName; +import javax.xml.stream.*; +import javax.xml.stream.events.*; + +/** + * Unit tests for testing that START_ELEMENT event object behaves + * as expected + * + * @author Tatu Saloranta + */ +public class TestStartElem + extends BaseEventTest +{ + /** + * Simple tests to ensure that the namespace declarations are properly + * parsed and accessible via {@link StartElement}. + */ + public void testStartElemNs() + throws XMLStreamException + { + String XML = ""; + + XMLEventReader er = getReader(XML, true, false); + assertTokenType(START_DOCUMENT, er.nextEvent().getEventType()); + XMLEvent evt = er.nextEvent(); + assertTokenType(START_ELEMENT, evt.getEventType()); + // Ok, got the start element... is it ok? + assertTrue(evt.isStartElement()); + StartElement se = evt.asStartElement(); + testEventWritability(se); + + NamespaceContext nsCtxt = se.getNamespaceContext(); + + assertNotNull("StartElement.getNamespaceContext() should never return null", nsCtxt); + // First, ones we shouldn't get: + assertNull(nsCtxt.getPrefix("a")); + assertNull(nsCtxt.getPrefix("http://foobar")); + assertNull(nsCtxt.getNamespaceURI("b")); + assertNull(nsCtxt.getNamespaceURI("http://my")); + + { + Iterator it = nsCtxt.getPrefixes("http://foobar"); + // Specs don't specify if we should get null, or empty iterator + assertTrue((it == null) || !it.hasNext()); + it = nsCtxt.getPrefixes("a"); + assertTrue((it == null) || !it.hasNext()); + } + // Then ones we should: + + assertEquals("a", nsCtxt.getPrefix("ns:attrs")); + assertEquals("", nsCtxt.getPrefix("http://my")); + assertEquals("http://my", nsCtxt.getNamespaceURI("")); + assertEquals("ns:attrs", nsCtxt.getNamespaceURI("a")); + + // Plus, let's check the other namespace access: + Iterator it = se.getNamespaces(); + assertEquals(2, countElements(it)); + + assertTokenType(END_ELEMENT, er.nextEvent().getEventType()); + assertTokenType(END_DOCUMENT, er.nextEvent().getEventType()); + assertFalse(er.hasNext()); + } + + public void testNestedStartElemNs() + throws XMLStreamException + { + String XML = "" + +"" + +"" + +""; + + XMLEventReader er = getReader(XML, true, false); + assertTokenType(START_DOCUMENT, er.nextEvent().getEventType()); + XMLEvent evt = er.nextEvent(); + assertTokenType(START_ELEMENT, evt.getEventType()); + StartElement se = evt.asStartElement(); + testEventWritability(se); + + // Let's first check that it has 1 declaration: + assertEquals(0, countElements(se.getNamespaces())); + NamespaceContext nsCtxt = se.getNamespaceContext(); + assertNotNull("StartElement.getNamespaceContext() should never return null", nsCtxt); + assertNull(nsCtxt.getPrefix("a")); + assertNull(nsCtxt.getNamespaceURI("b")); + + // then first leaf: + evt = er.nextEvent(); + assertTrue(evt.isStartElement()); + se = evt.asStartElement(); + assertEquals("leaf", se.getName().getLocalPart()); + assertEquals(1, countElements(se.getNamespaces())); + assertEquals("x", se.getName().getNamespaceURI()); + nsCtxt = se.getNamespaceContext(); + assertEquals("x", nsCtxt.getNamespaceURI("")); + assertEquals("", nsCtxt.getPrefix("x")); + testEventWritability(se); + + evt = er.nextEvent(); + assertTrue(evt.isEndElement()); + testEventWritability(evt); + + // Ok, branch: + evt = er.nextEvent(); + assertTrue(evt.isStartElement()); + se = evt.asStartElement(); + assertEquals("branch", se.getName().getLocalPart()); + assertEquals(2, countElements(se.getNamespaces())); + nsCtxt = se.getNamespaceContext(); + assertEquals("a", nsCtxt.getPrefix("b")); + assertEquals("b", nsCtxt.getNamespaceURI("a")); + assertEquals("x", nsCtxt.getPrefix("url")); + assertEquals("url", nsCtxt.getNamespaceURI("x")); + testEventWritability(se); + + // second leaf + evt = er.nextEvent(); + assertTrue(evt.isStartElement()); + se = evt.asStartElement(); + nsCtxt = se.getNamespaceContext(); + assertEquals("leaf", se.getName().getLocalPart()); + // only one declared in this particular element + assertEquals(1, countElements(se.getNamespaces())); + // but should still show the other bound ns from parent + nsCtxt = se.getNamespaceContext(); + assertEquals("a", nsCtxt.getPrefix("c")); + assertEquals("c", nsCtxt.getNamespaceURI("a")); + assertEquals("x", nsCtxt.getPrefix("url")); + assertEquals("url", nsCtxt.getNamespaceURI("x")); + // ok, but how about masking: + assertNull(nsCtxt.getPrefix("b")); + + // Ok, fine... others we don't care about: + assertTrue(er.nextEvent().isEndElement()); + } + + /** + * Another unit test, one that checks a special case of namespace + * enclosures and namespace context objects. + */ + public void testNestedStartElemNs2() + throws XMLStreamException + { + String XML = ""; + + XMLEventReader er = getReader(XML, true, false); + assertTokenType(START_DOCUMENT, er.nextEvent().getEventType()); + + XMLEvent evt = er.nextEvent(); // root + assertTokenType(START_ELEMENT, evt.getEventType()); + StartElement se = evt.asStartElement(); + assertEquals("root", se.getName().getLocalPart()); + assertEquals(0, countElements(se.getNamespaces())); + + evt = er.nextEvent(); // branch + assertTokenType(START_ELEMENT, evt.getEventType()); + se = evt.asStartElement(); + assertEquals("branch", se.getName().getLocalPart()); + assertEquals(1, countElements(se.getNamespaces())); + NamespaceContext nsCtxt = se.getNamespaceContext(); + assertNotNull("StartElement.getNamespaceContext() should never return null", nsCtxt); + assertEquals("url", nsCtxt.getNamespaceURI("a")); + assertEquals("a", nsCtxt.getPrefix("url")); + + evt = er.nextEvent(); // leaf + assertTokenType(START_ELEMENT, evt.getEventType()); + se = evt.asStartElement(); + assertEquals("leaf", se.getName().getLocalPart()); + assertEquals(0, countElements(se.getNamespaces())); + nsCtxt = se.getNamespaceContext(); + assertEquals("url", nsCtxt.getNamespaceURI("a")); + assertEquals("a", nsCtxt.getPrefix("url")); + + assertTrue(er.nextEvent().isEndElement()); // /leaf + assertTrue(er.nextEvent().isEndElement()); // /branch + assertTrue(er.nextEvent().isEndElement()); // /root + } + + + /** + * Test to check that attributes can be accessed normally via + * {@link StartElement} instances. + */ + public void testStartElemAttrs() + throws XMLStreamException + { + String XML = ""; + + XMLEventReader er = getReader(XML, true, false); + assertTokenType(START_DOCUMENT, er.nextEvent().getEventType()); + + XMLEvent evt = er.nextEvent(); + assertTokenType(START_ELEMENT, evt.getEventType()); + StartElement se = evt.asStartElement(); + + assertAttr(se, "", "attr1", "value1"); + // ... and same without ns uri being passed + assertNqAttr(se, "attr1", "value1"); + assertAttr(se, "ns:attrs", "attr2", "value2"); + assertAttr(se, "", "attr2", null); + assertNqAttr(se, "attr2", null); + assertAttr(se, "ns:attrs", "attr1", null); + + evt = er.nextEvent(); + assertTokenType(START_ELEMENT, evt.getEventType()); + se = evt.asStartElement(); + + // One we should find (note: def. ns is not used!) + assertAttr(se, "", "attr", "x"); + assertNqAttr(se, "attr", "x"); + + // and then ones that aren't there... + assertAttr(se, "url:ns2", "attr", null); + assertAttr(se, "url:ns2", "x", null); + assertAttr(se, "ns:foo", "foobar", null); + assertAttr(se, "", "attr1", null); + assertNqAttr(se, "attr1", null); + + assertTokenType(END_ELEMENT, er.nextEvent().getEventType()); + assertTokenType(END_ELEMENT, er.nextEvent().getEventType()); + assertTokenType(END_DOCUMENT, er.nextEvent().getEventType()); + } + + public void testStartElemManyAttrsNs() + throws XMLStreamException + { + XMLEventReader er = getReader(get11AttrDoc(), true, false); + assertTokenType(START_DOCUMENT, er.nextEvent().getEventType()); + XMLEvent evt = er.nextEvent(); + assertTokenType(START_ELEMENT, evt.getEventType()); + StartElement se = evt.asStartElement(); + assertEquals(11, countElements(se.getAttributes())); + + // Let's verify we can find all attrs: + for (int i = ATTR11_NAMES.length; --i >= 0; ) { + String name = ATTR11_NAMES[i]; + String value = ATTR11_VALUES[i]; + // First, via string constant: + assertAttr11Value(se, name, value); + // Then using non-interned: + assertAttr11Value(se, ""+name, value); + + // Then that non-existing ones are not found: + String start = name.substring(0, 1); + assertAttr11Value(se, name+start, null); + assertAttr11Value(se, start+name, null); + } + assertTokenType(END_ELEMENT, er.nextEvent().getEventType()); + er.close(); + } + + /* + ///////////////////////////////////////////////// + // Internal methods: + ///////////////////////////////////////////////// + */ + + final static String[] ATTR11_NAMES = new String[] { + "method", "activeShell", "source", "data", + "widget", "length", "start", "styledTextNewValue", + "replacedText", "styledTextFunction", "raw" + }; + final static String[] ATTR11_VALUES = new String[] { + "a", "x", "y", "z", + "a", "1", "2", "t", + "", "f", "b" + }; + + private void assertAttr11Value(StartElement elem, String localName, String expValue) + { + String msg = "Wrong value for attribute '"+localName+"'; "; + + Attribute attr = elem.getAttributeByName(new QName(localName)); + String actValue = (attr == null) ? null : attr.getValue(); + if (expValue == null) { + assertNull(msg, actValue); + } else { + assertEquals(msg, expValue, actValue); + } + + // Let's also try with the other qname constructors, just to be sure + attr = elem.getAttributeByName(new QName("", localName)); + actValue = (attr == null) ? null : attr.getValue(); + if (expValue == null) { + assertNull(msg, actValue); + } else { + assertEquals(msg, expValue, actValue); + } + + attr = elem.getAttributeByName(new QName("", localName, "")); + actValue = (attr == null) ? null : attr.getValue(); + if (expValue == null) { + assertNull(msg, actValue); + } else { + assertEquals(msg, expValue, actValue); + } + } + + private String get11AttrDoc() + { + StringBuffer sb = new StringBuffer(); + sb.append(""); + return sb.toString(); + } + + private int countElements(Iterator it) { + int count = 0; + if (it != null) { + while (it.hasNext()) { + ++count; + it.next(); + } + } + return count; + } + + private void assertAttr(StartElement se, String nsURI, String localName, + String expValue) + { + QName qn = new QName(nsURI, localName); + Attribute attr = se.getAttributeByName(qn); + + if (expValue == null) { + assertNull("Should not find attribute '"+qn+"'", attr); + } else { + assertNotNull("Should find attribute '"+qn+"' but got null", attr); + assertEquals("Attribute '"+qn+"' has unexpected value", + expValue, attr.getValue()); + } + } + + private void assertNqAttr(StartElement se, String localName, String expValue) + { + QName qn = new QName(localName); + Attribute attr = se.getAttributeByName(qn); + + if (expValue == null) { + assertNull("Should not find attribute '"+qn+"'", attr); + } else { + assertNotNull("Should find attribute '"+qn+"' but got null", attr); + assertEquals("Attribute '"+qn+"' has unexpected value", + expValue, attr.getValue()); + } + + /* 21-Sep-2006, TSa: Let's also try it with different QName + * constructor, just to be sure + */ + qn = new QName("", localName); + attr = se.getAttributeByName(qn); + if (expValue == null) { + assertNull("Should not find attribute '"+qn+"'", attr); + } else { + assertNotNull("Should find attribute '"+qn+"' but got null", attr); + assertEquals("Attribute '"+qn+"' has unexpected value", + expValue, attr.getValue()); + } + } + + private XMLEventReader getReader(String contents, boolean nsAware, + boolean coalesce) + throws XMLStreamException + { + XMLInputFactory f = getInputFactory(); + setNamespaceAware(f, nsAware); + setCoalescing(f, coalesce); + setSupportDTD(f, true); + setValidating(f, false); + return constructEventReader(f, contents); + } +} diff -Nru libwoodstox-java-4.1.3/src/test/java/org/codehaus/stax/test/evt/TestSurrogatePairs.java libwoodstox-java-5.1.0/src/test/java/org/codehaus/stax/test/evt/TestSurrogatePairs.java --- libwoodstox-java-4.1.3/src/test/java/org/codehaus/stax/test/evt/TestSurrogatePairs.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/org/codehaus/stax/test/evt/TestSurrogatePairs.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,21 @@ +package org.codehaus.stax.test.evt; + +import java.io.*; + +import javax.xml.stream.XMLEventReader; +import javax.xml.stream.XMLInputFactory; + +public class TestSurrogatePairs + extends wstxtest.BaseWstxTest +{ + public void testIssue280() throws Exception + { + XMLInputFactory xif = getInputFactory(); + InputStream inputStream = getClass().getResourceAsStream("surrogate-pairs.xml"); + XMLEventReader eventReader = xif.createXMLEventReader(inputStream); + + while (eventReader.hasNext()) { + eventReader.next(); + } + } +} diff -Nru libwoodstox-java-4.1.3/src/test/java/org/codehaus/stax/test/SimpleResolver.java libwoodstox-java-5.1.0/src/test/java/org/codehaus/stax/test/SimpleResolver.java --- libwoodstox-java-4.1.3/src/test/java/org/codehaus/stax/test/SimpleResolver.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/org/codehaus/stax/test/SimpleResolver.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,32 @@ +package org.codehaus.stax.test; + +import javax.xml.stream.XMLResolver; + +/** + * This is a simple and stupid resolver, that does not check what is + * being resolved; and thus it should only be used if only one thing + * (a single external entity; a single external subset) is to + * be expanded (although that single entity can be repeated multiple + * times). + */ +public class SimpleResolver + implements XMLResolver +{ + final String ENC = "UTF-8"; + final byte[] mData; + + public SimpleResolver(String content) + { + try { + mData = content.getBytes(ENC); + } catch (java.io.IOException ioe) { + throw new Error(ioe.toString()); + } + } + + @Override + public Object resolveEntity(String publicID, String systemID, String baseURI, String namespace) + { + return new java.io.ByteArrayInputStream(mData); + } +} diff -Nru libwoodstox-java-4.1.3/src/test/java/org/codehaus/stax/test/stream/BaseStreamTest.java libwoodstox-java-5.1.0/src/test/java/org/codehaus/stax/test/stream/BaseStreamTest.java --- libwoodstox-java-4.1.3/src/test/java/org/codehaus/stax/test/stream/BaseStreamTest.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/org/codehaus/stax/test/stream/BaseStreamTest.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,153 @@ +package org.codehaus.stax.test.stream; + +import javax.xml.namespace.QName; +import javax.xml.stream.XMLInputFactory; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; + +import org.codehaus.stax.test.BaseStaxTest; + +/** + * Base class for all StaxTest unit tests that test basic non-validating + * stream (cursor) API functionality. + * + * @author Tatu Saloranta + */ +public abstract class BaseStreamTest + extends BaseStaxTest +{ + /** + * Switch that can be turned on to verify to display ALL exact Exceptions + * thrown when Exceptions are expected. This is sometimes necessary + * when debugging, since it's impossible to automatically verify + * that Exception is exactly the right one, since there is no + * strict Exception type hierarchy for StAX problems. + *

+ * Note: Not made 'final static', so that compiler won't inline + * it. Makes possible to do partial re-compilations. + * Note: Since it's only used as the default value, sub-classes + * can separately turn it off as necessary + */ + //protected static boolean DEF_PRINT_EXP_EXCEPTION = true; + protected static boolean DEF_PRINT_EXP_EXCEPTION = false; + + protected boolean PRINT_EXP_EXCEPTION = DEF_PRINT_EXP_EXCEPTION; + + /* + /////////////////////////////////////////////////////////// + // Higher-level test methods + /////////////////////////////////////////////////////////// + */ + + /** + * Method that will iterate through contents of an XML document + * using specified stream reader; will also access some of data + * to make sure reader reads most of lazy-loadable data. + * Method is usually called to try to get an exception for invalid + * content. + * + * @return Dummy value calculated on contents; used to make sure + * no dead code is eliminated + */ + protected int streamThrough(XMLStreamReader sr) + throws XMLStreamException + { + int result = 0; + + assertNotNull(sr); + try { + while (sr.hasNext()) { + int type = sr.next(); + result += type; + if (sr.hasText()) { + /* will also do basic verification for text content, to + * see that all text accessor methods return same content + */ + result += getAndVerifyText(sr).hashCode(); + } + if (sr.hasName()) { + QName n = sr.getName(); + assertNotNull(n); + result += n.hashCode(); + } + } + } catch (RuntimeException rex) { + // Let's try to find a nested XMLStreamException, if possible + Throwable t = rex; + while (t != null) { + t = t.getCause(); + if (t instanceof XMLStreamException) { + throw (XMLStreamException) t; + } + } + // Nope, just a runtime exception + throw rex; + } + + return result; + } + + protected int streamThroughFailing(XMLInputFactory f, String contents, + String msg) + { + int result = 0; + try { + XMLStreamReader sr = constructStreamReader(f, contents); + result = streamThrough(sr); + } catch (XMLStreamException ex) { // good + if (PRINT_EXP_EXCEPTION) { + System.out.println("Expected failure: '"+ex.getMessage()+"' " + +"(matching message: '"+msg+"')"); + } + return 0; + } catch (Exception ex2) { // may still be ok: + if (ex2.getCause() instanceof XMLStreamException) { + if (PRINT_EXP_EXCEPTION) { + System.out.println("Expected failure: '"+ex2.getMessage()+"' " + +"(matching message: '"+msg+"')"); + } + return 0; + } + fail("Expected an XMLStreamException (either direct, or getCause() of a primary exception) for "+msg + +", got: "+ex2); + } + + fail("Expected an exception for "+msg); + return result; // never gets here + } + + protected int streamThroughFailing(XMLStreamReader sr, String msg) + { + int result = 0; + try { + result = streamThrough(sr); + } catch (XMLStreamException ex) { // good + if (PRINT_EXP_EXCEPTION) { + System.out.println("Expected failure: '"+ex.getMessage()+"' " + +"(matching message: '"+msg+"')"); + } + return 0; + } catch (Exception ex2) { // ok; iff links to XMLStreamException + Throwable t = ex2; + while (t.getCause() != null && !(t instanceof XMLStreamException)) { + t = t.getCause(); + } + if (t instanceof XMLStreamException) { + if (PRINT_EXP_EXCEPTION) { + System.out.println("Expected failure: '"+ex2.getMessage()+"' " + +"(matching message: '"+msg+"')"); + } + return 0; + } + if (t == ex2) { + fail("Expected an XMLStreamException (either direct, or getCause() of a primary exception) for "+msg + +", got: "+ex2); + } + fail("Expected an XMLStreamException (either direct, or getCause() of a primary exception) for "+msg + +", got: "+ex2+" (root: "+t+")"); + } + + fail("Expected an exception for "+msg); + return result; // never gets here + } +} diff -Nru libwoodstox-java-4.1.3/src/test/java/org/codehaus/stax/test/stream/BlockingStream.java libwoodstox-java-5.1.0/src/test/java/org/codehaus/stax/test/stream/BlockingStream.java --- libwoodstox-java-4.1.3/src/test/java/org/codehaus/stax/test/stream/BlockingStream.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/org/codehaus/stax/test/stream/BlockingStream.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,46 @@ +package org.codehaus.stax.test.stream; + +import java.io.*; + +/** + * Test stream used to test whether Reader using this stream would + * 'accidentally' cause blocking. Used by {@link TestStreaming} + * unit test suite. + */ +class BlockingStream + extends FilterInputStream +{ + public boolean mBlocked = false; + + // dummy ctor to keep JUnit happy + public BlockingStream() { super(null); } + + public BlockingStream(InputStream is) + { + super(is); + } + + public boolean hasBlocked() { + return mBlocked; + } + + @Override + public int read() throws IOException + { + int r = super.read(); + if (r < 0) { + mBlocked = true; + } + return r; + } + + @Override + public int read(byte[] b, int off, int len) throws IOException + { + int r = super.read(b, off, len); + if (r < 0) { + mBlocked = true; + } + return r; + } +} diff -Nru libwoodstox-java-4.1.3/src/test/java/org/codehaus/stax/test/stream/TestAttributeDTD.java libwoodstox-java-5.1.0/src/test/java/org/codehaus/stax/test/stream/TestAttributeDTD.java --- libwoodstox-java-4.1.3/src/test/java/org/codehaus/stax/test/stream/TestAttributeDTD.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/org/codehaus/stax/test/stream/TestAttributeDTD.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,43 @@ +package org.codehaus.stax.test.stream; + +import javax.xml.stream.*; + +/** + * Unit tests related to handling of attributes that depend on DTD subsets. + * + * @author Tatu Saloranta + */ +public class TestAttributeDTD + extends BaseStreamTest +{ + + /** + * Test to make sure that quotes can be used in attribute values + * via entity expansion + */ + final String VALID_ATTRS_WITH_QUOTES + = "\n" + + " ]>\n" + + ""; + + public void testQuotesViaEntities() + throws XMLStreamException + { + XMLInputFactory ifact = getNewInputFactory(); + setNamespaceAware(ifact, false); // shouldn't matter + // These are needed to get entities read and expanded: + setSupportDTD(ifact, true); + setReplaceEntities(ifact, true); + + XMLStreamReader sr = constructStreamReader(ifact, VALID_ATTRS_WITH_QUOTES); + // Shouldn't get exceptions... + + try { + streamThrough(sr); + } catch (XMLStreamException ex) { + fail("Failed to parse attributes with quotes expanded from entities: "+ex); + } + } +} diff -Nru libwoodstox-java-4.1.3/src/test/java/org/codehaus/stax/test/stream/TestAttributeRead.java libwoodstox-java-5.1.0/src/test/java/org/codehaus/stax/test/stream/TestAttributeRead.java --- libwoodstox-java-4.1.3/src/test/java/org/codehaus/stax/test/stream/TestAttributeRead.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/org/codehaus/stax/test/stream/TestAttributeRead.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,517 @@ +package org.codehaus.stax.test.stream; + +import javax.xml.namespace.QName; +import javax.xml.stream.*; + +/** + * Unit test suite that tests handling of the XML attributes, both + * in namespace aware and non-namespace modes, including ensuring + * that values are properly normalized with regards to white space. + * There are tests for both well-formed and non-wellformed cases. + * + * @author Tatu Saloranta + */ +public class TestAttributeRead + extends BaseStreamTest +{ + final String VALID_XML1 + = ""; + + final String VALID_XML2 + = ""; + + final String VALID_XML3 + = ""; + + public void testValidNsAttrsByName() + throws XMLStreamException + { + XMLStreamReader sr = getReader(VALID_XML1, true); + assertEquals(START_ELEMENT, sr.next()); + assertEquals(1, sr.getNamespaceCount()); + assertEquals(2, sr.getAttributeCount()); + + assertEquals("r&b", sr.getAttributeValue(null, "a")); + assertEquals("\"", sr.getAttributeValue("url", "b")); + + // Shoulnd't allow using prefix instead of URI + String val = sr.getAttributeValue("a", "b"); + assertNull("Should get null, not '"+val+"'", val); + val = sr.getAttributeValue("", "b"); + assertNull("Should get null, not '"+val+"'", val); + + assertEquals(END_ELEMENT, sr.next()); + assertEquals(END_DOCUMENT, sr.next()); + } + + /** + * Additional unit test that verifies that empty namespace URI + * can be used as expected + */ + public void testValidNsAttrsByName2() + throws XMLStreamException + { + XMLStreamReader sr = getReader("", true); + assertEquals(START_ELEMENT, sr.next()); + assertEquals(0, sr.getNamespaceCount()); + assertEquals(1, sr.getAttributeCount()); + + /* Both null and "" should work as well + * (note: specs are bit confusing and contradictory wrt + * how null is to be handled, but in this case all interpretations + * would produce same result) + */ + assertEquals("1", sr.getAttributeValue(null, "attr")); + assertEquals("1", sr.getAttributeValue("", "attr")); + + assertNull(sr.getAttributeValue(null, "b")); + assertNull(sr.getAttributeValue("", "b")); + + assertEquals(END_ELEMENT, sr.next()); + assertEquals(END_DOCUMENT, sr.next()); + } + + public void testValidNsAttrsByIndex() + throws XMLStreamException + { + XMLStreamReader sr = getReader(VALID_XML1, true); + assertEquals(START_ELEMENT, sr.next()); + assertEquals(1, sr.getNamespaceCount()); + assertEquals(2, sr.getAttributeCount()); + + /* Note: we can not assume on stream reader returning attributes + * in document order... most will do that, but it's not a + * strict StAX requirement. + */ + + String ln1 = sr.getAttributeLocalName(0); + + int index1 = 0; + int index2 = 1; + + if (ln1.equals("a")) { + ; + } else if (ln1.equals("b")) { + index1 = 1; + index2 = 0; + } else { + fail("Unexpected local name for attribute #0; expected either 'a' or 'b'; got '"+ln1+"'."); + } + + assertEquals("a", sr.getAttributeLocalName(index1)); + assertEquals("b", sr.getAttributeLocalName(index2)); + + assertEquals("r&b", sr.getAttributeValue(index1)); + assertEquals("\"", sr.getAttributeValue(index2)); + + assertNoAttrPrefix(sr.getAttributePrefix(index1)); + assertEquals("a", sr.getAttributePrefix(index2)); + assertNoAttrNamespace(sr.getAttributeNamespace(index1)); + assertEquals("url", sr.getAttributeNamespace(index2)); + } + + public void testValidNsAttrs2() + throws XMLStreamException + { + XMLStreamReader sr = getReader(VALID_XML3, true); + assertEquals(START_ELEMENT, sr.next()); + assertEquals("root", sr.getLocalName()); + + assertEquals(START_ELEMENT, sr.next()); + assertEquals("e1", sr.getLocalName()); + assertEquals(1, sr.getAttributeCount()); + assertEquals("a", sr.getAttributeLocalName(0)); + assertEquals("123", sr.getAttributeValue(0)); + assertEquals("123", sr.getAttributeValue(null, "a")); + assertEquals(END_ELEMENT, sr.next()); + assertEquals("e1", sr.getLocalName()); + + assertEquals(START_ELEMENT, sr.next()); + assertEquals("e2", sr.getLocalName()); + assertEquals(0, sr.getAttributeCount()); + String val = sr.getAttributeValue(null, "a"); + if (val != null) { + fail("Should not find a value for attribute 'a', found '"+val+"'"); + } + + assertEquals(END_ELEMENT, sr.next()); + assertEquals("e2", sr.getLocalName()); + + assertEquals(END_ELEMENT, sr.next()); + assertEquals("root", sr.getLocalName()); + sr.close(); + } + + public void testValidNsAttrNsInfo() + throws XMLStreamException + { + XMLStreamReader sr = getReader + ("", + true); + + assertEquals(START_ELEMENT, sr.next()); + assertEquals("root", sr.getLocalName()); + assertEquals(1, sr.getNamespaceCount()); + assertEquals(1, sr.getAttributeCount()); + assertNoAttrPrefix(sr.getAttributePrefix(0)); + assertNoAttrNamespace(sr.getAttributeNamespace(0)); + assertEquals("xyz", sr.getAttributeValue(0)); + + assertEquals(START_ELEMENT, sr.next()); + assertEquals("leaf", sr.getLocalName()); + assertEquals(0, sr.getNamespaceCount()); + assertEquals(1, sr.getAttributeCount()); + assertEquals("b", sr.getAttributePrefix(0)); + assertEquals("http://foo", sr.getAttributeNamespace(0)); + assertEquals("1", sr.getAttributeValue(0)); + + assertEquals(END_ELEMENT, sr.next()); + assertEquals("leaf", sr.getLocalName()); + assertEquals(END_ELEMENT, sr.next()); + assertEquals("root", sr.getLocalName()); + + assertEquals(END_DOCUMENT, sr.next()); + } + + public void testValidNonNsAttrs() + throws XMLStreamException + { + XMLStreamReader sr = getReader(VALID_XML1, false); + + // Does the impl support non-ns mode? + if (sr == null) { // nope! + return; + } + + assertEquals(START_ELEMENT, sr.next()); + assertEquals(0, sr.getNamespaceCount()); + assertEquals(3, sr.getAttributeCount()); + + assertEquals("r&b", sr.getAttributeValue(null, "a")); + assertEquals("\"", sr.getAttributeValue(null, "a:b")); + + assertEquals(END_ELEMENT, sr.next()); + assertEquals(END_DOCUMENT, sr.next()); + } + + public void testValidNonNsAttrsByIndex() + throws XMLStreamException + { + // = ""; + XMLStreamReader sr = getReader(VALID_XML2, false); + + // Does the impl support non-ns mode? + if (sr == null) { // nope! + return; + } + + assertEquals(START_ELEMENT, sr.next()); + assertEquals(0, sr.getNamespaceCount()); + assertEquals(2, sr.getAttributeCount()); + + /* Note: we can not assume on stream reader returning attributes + * in document order... most will do that, but it's not a + * strict StAX requirement. + */ + + String ln1 = sr.getAttributeLocalName(0); + + int index1 = 0; + int index2 = 1; + + if (ln1.equals("a:b")) { + ; + } else if (ln1.equals("xmlns:a")) { + index1 = 1; + index2 = 0; + } else { + fail("Unexpected local name for attribute #0; expected either 'a:b' or 'xmlns:a'; got '"+ln1+"'."); + } + + assertEquals("a:b", sr.getAttributeLocalName(index1)); + assertEquals("xmlns:a", sr.getAttributeLocalName(index2)); + + assertEquals("\"", sr.getAttributeValue(index1)); + assertEquals("url", sr.getAttributeValue(index2)); + assertNoAttrPrefix(sr.getAttributePrefix(index1)); + assertNoAttrPrefix(sr.getAttributePrefix(index2)); + + assertNoAttrNamespace(sr.getAttributeNamespace(index1)); + assertNoAttrNamespace(sr.getAttributeNamespace(index2)); + } + + public void testInvalidAttrNames() + throws XMLStreamException + { + // First NS-aware, then non-NS: + XMLStreamReader sr = getReader("", true); + if (sr != null) { + streamThroughFailing(sr, "invalid attribute name; can not start with '.'"); + } + sr = getReader("", false); + if (sr != null) { + streamThroughFailing(sr, "invalid attribute name; can not start with '.'"); + } + sr = getReader("", false); + if (sr != null) { + streamThroughFailing(sr, "invalid attribute name can not contain '?'"); + } + sr = getReader("", true); + if (sr != null) { + streamThroughFailing(sr, "invalid attribute name can not contain '?'"); + } + } + + public void testInvalidAttrValue() + throws XMLStreamException + { + for (int i = 0; i < 2; ++i) { + boolean ns = (i > 0); + // Invalid, '<' not allowed in attribute value + String XML = ""; + + XMLStreamReader sr = getReader(XML, ns); + // Does the impl support non-ns mode? + if (sr == null) { // nope! shouldn't test... + continue; + } + streamThroughFailing(sr, "unquoted '<' in attribute value"); + + XML = ""; + streamThroughFailing(getReader(XML, ns), + "missing value for attribute"); + } + } + + /** + * This tests that spaces are actually needed between attributes... + */ + public void testInvalidAttrSpaces() + throws XMLStreamException + { + for (int i = 0; i < 2; ++i) { + boolean ns = (i > 0); + String XML = ""; + XMLStreamReader sr = getReader(XML, ns); + // Does the impl support non-ns mode? + if (sr == null) { // nope! shouldn't test... + continue; + } + streamThroughFailing(sr, "missing space between attributes"); + XML = ""; + streamThroughFailing(getReader(XML, ns), + "missing space between attributes"); + } + } + + public void testInvalidNsAttrDup() + throws XMLStreamException + { + // Invalid; straight duplicate attrs: + String XML = ""; + streamThroughFailing(getReader(XML, true), "duplicate attributes"); + // Invalid; sneakier duplicate attrs: + XML = ""; + streamThroughFailing(getReader(XML, true), + "duplicate attributes (same URI, different prefix)"); + + /* Also, let's add some more, in case parser just checks for adjacent + * ones, or has special cases for small number of attrs... + */ + XML = ""; + streamThroughFailing(getReader(XML, true), "duplicate attributes"); + + XML = ""; + streamThroughFailing(getReader(XML, true), + "duplicate attributes (same URI, different prefix)"); + } + + public void testInvalidNonNsAttrDup() + throws XMLStreamException + { + // Invalid; duplicate attrs even without namespaces + String XML = ""; + XMLStreamReader sr = getReader(XML, false); + if (sr != null) { + streamThroughFailing(sr, "duplicate attributes"); + } + + // Valid when namespaces not enabled: + XML = ""; + try { + sr = getReader(XML, false); + // Does the impl support non-ns mode? + if (sr == null) { // nope! shouldn't test... + return; + } + streamThrough(sr); + } catch (Exception e) { + fail("Didn't expect an exception when namespace support not enabled: "+e); + } + } + + /** + * This test verifies that handling of multiple attributes should + * work as expected + */ + public void testManyAttrsNs() + throws Exception + { + doTestManyAttrs(true); + } + + public void testManyAttrsNonNs() + throws Exception + { + doTestManyAttrs(false); + } + + /** + * Unit test that verifies that by-index attribute accessors + * will throw proper exception when using invalid index to + * access data (value, name, uri/prefix). + */ + public void testInvalidAccessByIndex() + throws Exception + { + String XML = ""; + + XMLStreamReader sr = getReader(XML, true); + assertTokenType(START_ELEMENT, sr.next()); + assertEquals(2, sr.getAttributeCount()); + assertTokenType(START_ELEMENT, sr.next()); + assertEquals(1, sr.getAttributeCount()); + + try { + String str = sr.getAttributeValue(1); + fail("Expected IllegalArgumentException for sr.getAttributeValue() with illegal index, no exception, value = ["+str+"]"); + } catch (IllegalArgumentException iae) { + ; // good + } catch (Exception e) { + // almost ok + fail("Expected IllegalArgumentException for sr.getAttributeValue() with illegal index, got: "+e); + } + + try { + QName n = sr.getAttributeName(1); + fail("Expected IllegalArgumentException for sr.getAttributeName() with illegal index, no exception, name = ["+n+"]"); + } catch (IllegalArgumentException iae) { + ; // good + } catch (Exception e) { + // almost ok + fail("Expected IllegalArgumentException for sr.getAttributeName() with illegal index, got: "+e); + } + + try { + String n = sr.getAttributeLocalName(1); + fail("Expected IllegalArgumentException for sr.getAttributeLocalName() with illegal index, no exception, got = ["+n+"]"); + } catch (IllegalArgumentException iae) { + ; // good + } catch (Exception e) { + // almost ok + fail("Expected IllegalArgumentException for sr.getAttributeLocalName() with illegal index, got: "+e); + } + + try { + String n = sr.getAttributeNamespace(1); + fail("Expected IllegalArgumentException for sr.getAttributeNamespace() with illegal index, no exception, got = ["+n+"]"); + } catch (IllegalArgumentException iae) { + ; // good + } catch (Exception e) { + // almost ok + fail("Expected IllegalArgumentException for sr.getAttributeNamespace() with illegal index, got: "+e); + } + + try { + String n = sr.getAttributePrefix(1); + fail("Expected IllegalArgumentException for sr.getAttributePrefix() with illegal index, no exception, got = ["+n+"]"); + } catch (IllegalArgumentException iae) { + ; // good + } catch (Exception e) { + // almost ok + fail("Expected IllegalArgumentException for sr.getAttributePrefix() with illegal index, got: "+e); + } + + sr.close(); + } + + /* + //////////////////////////////////////// + // Private methods, other + //////////////////////////////////////// + */ + + final static String[] ATTR11_NAMES = new String[] { + "method", "activeShell", "source", "data", + "widget", "length", "start", "styledTextNewValue", + "replacedText", "styledTextFunction", "raw" + }; + final static String[] ATTR11_VALUES = new String[] { + "a", "x", "y", "z", + "a", "1", "2", "t", + "", "f", "b" + }; + + private String get11AttrDoc() + { + StringBuffer sb = new StringBuffer(); + sb.append(""); + return sb.toString(); + } + + private void doTestManyAttrs(boolean ns) + throws XMLStreamException + { + XMLStreamReader sr = getReader(get11AttrDoc(), ns); + // If non-ns mode not available, that's ok; we'll skip the test + if (sr == null) { + return; + } + assertTokenType(START_ELEMENT, sr.next()); + assertEquals(11, sr.getAttributeCount()); + /* Let's verify we can find them all + */ + for (int i = ATTR11_NAMES.length; --i >= 0; ) { + String name = ATTR11_NAMES[i]; + String value = ATTR11_VALUES[i]; + // First, via string constant: + assertEquals(value, sr.getAttributeValue(null, name)); + // Then via new String (non-interned) + assertEquals(value, sr.getAttributeValue(null, ""+name)); + + // Then that non-existing ones are not found: + String start = name.substring(0, 1); + assertNull(value, sr.getAttributeValue(null, name+start)); + assertNull(value, sr.getAttributeValue(null, start+name)); + } + assertTokenType(END_ELEMENT, sr.next()); + } + + /** + * @return Stream reader constructed if initialization succeeded (all + * setting supported by the impl); null if some settings (namespace + * awareness) not supported. + */ + private XMLStreamReader getReader(String contents, boolean nsAware) + throws XMLStreamException + { + XMLInputFactory f = getInputFactory(); + if (!setNamespaceAware(f, nsAware)) { + return null; + } + + setCoalescing(f, true); // shouldn't matter + setValidating(f, false); + return constructStreamReader(f, contents); + } +} diff -Nru libwoodstox-java-4.1.3/src/test/java/org/codehaus/stax/test/stream/TestCDataRead.java libwoodstox-java-5.1.0/src/test/java/org/codehaus/stax/test/stream/TestCDataRead.java --- libwoodstox-java-4.1.3/src/test/java/org/codehaus/stax/test/stream/TestCDataRead.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/org/codehaus/stax/test/stream/TestCDataRead.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,317 @@ +package org.codehaus.stax.test.stream; + +import java.io.*; + +import javax.xml.stream.*; + +/** + * Unit test suite that tests that the stream reader does in fact + * coalesce adjacent text/CDATA segments when told to do so. + */ +public class TestCDataRead + extends BaseStreamTest +{ + final static String CDATA1; + final static String CDATA2; + static { + StringBuffer sb1 = new StringBuffer(8000); + StringBuffer sb2 = new StringBuffer(8000); + + sb1.append("..."); + sb2.append("\n \n\n "); + + /* Let's add enough stuff to probably cause segmentation... + */ + for (int i = 0; i < 200; ++i) { + String txt = "Round #"+i+"; & that's fun: &x"+i+"; <> %xx; &ent <<< %%% ]> "; + sb1.append(txt); + sb1.append(" "); + sb2.append("\n"); + sb2.append(txt); + } + + CDATA1 = sb1.toString(); + CDATA2 = sb2.toString(); + } + + final static String CDATA3 = " ]] "; + + final static String EXP_CDATA = CDATA1 + CDATA2 + CDATA3; + + final static String VALID_XML = + "" + +"" + +"" + +"" + +"" + +""; + + /** + * This test verifies that no character quoting need (or can) be + * done within CDATA section. + */ + public void testCDataSimple() + throws XMLStreamException + { + String XML = "]]]>"; + String EXP = "<&]>]"; + XMLStreamReader sr = getReader(XML, true); + assertTokenType(START_ELEMENT, sr.next()); + // In coalescing mode, all CDATA are reported as CHARACTERS + assertTokenType(CHARACTERS, sr.next()); + String act = getAndVerifyText(sr); + assertEquals(EXP, act); + assertTokenType(END_ELEMENT, sr.next()); + } + + public void testCDataCoalescing() + throws XMLStreamException + { + XMLStreamReader sr = getReader(VALID_XML, true); + assertTokenType(START_ELEMENT, sr.next()); + // In coalescing mode, all CDATA are reported as CHARACTERS + assertTokenType(CHARACTERS, sr.next()); + String act = getAndVerifyText(sr); + assertEquals(EXP_CDATA, act); + assertTokenType(END_ELEMENT, sr.next()); + } + + public void testCDataNonCoalescing() + throws XMLStreamException + { + XMLStreamReader sr = getReader(VALID_XML, false); + assertTokenType(START_ELEMENT, sr.next()); + int type = sr.next(); + /* 07-Dec-2004, TSa: StAX specs actually allow returning + * CHARACTERS too... + */ + if (type != CHARACTERS) { + assertEquals("Unexpected token type (" + +tokenTypeDesc(type) + +") returned; expected CDATA or CHARACTERS", + CDATA, type); + } + + StringBuffer sb = new StringBuffer(16000); + do { + sb.append(getAndVerifyText(sr)); + type = sr.next(); + } while (type == CDATA || type == CHARACTERS); + assertEquals(EXP_CDATA, sb.toString()); + assertTokenType(END_ELEMENT, sr.getEventType()); + } + + public void testInvalidCData() + throws XMLStreamException + { + String XML = ""; + String MSG = "unfinished CDATA section"; + streamThroughFailing(getReader(XML, false), MSG); + streamThroughFailing(getReader(XML, true), MSG); + + XML = " "; + MSG = "malformed CDATA section"; + streamThroughFailing(getReader(XML, false), MSG); + streamThroughFailing(getReader(XML, true), MSG); + + XML = " "; + streamThroughFailing(getReader(XML, false), MSG); + streamThroughFailing(getReader(XML, true), MSG); + + XML = " "; + streamThroughFailing(getReader(XML, false), MSG); + streamThroughFailing(getReader(XML, true), MSG); + } + + /** + * This unit test verifies that nested CData sections cause + * an error. It is related to another test, which just checks + * that ]]> (with no quoting) is illegal, but parsers may deal + * with them differently. + *

+ * Note: this is directly based on XMLTest/SAXTest #735. + */ + public void testInvalidNestedCData() + throws XMLStreamException + { + String XML = "\n\n" + +"\n]]>\n"; + + main_loop: + for (int i = 0; i < 2; ++i) { + boolean coal = (i > 0); + XMLStreamReader sr = getReader(XML, coal); + assertTokenType(START_ELEMENT, sr.next()); + // Ok, now should get an exception... + StringBuffer sb = new StringBuffer(); + int type = -1; + try { + while (true) { + type = sr.next(); + if (type != CDATA && type != CHARACTERS) { + break; + } + sb.append(getAndVerifyText(sr)); + } + } catch (XMLStreamException sex) { + // good + continue; + } catch (RuntimeException rex) { + /* Hmmh. Some implementations may throw a runtime exception, + * if things are lazily parsed (for example, Woodstox). + * But let's allow this only if a nested exception is + * of proper type + */ + Throwable t = rex; + while (t != null) { + if (t instanceof XMLStreamException) { + continue main_loop; + } + t = t.getCause(); + } + fail("Expected an XMLStreamException for nested CDATA section (coalescing: "+coal+"); instead got exception ("+rex.getClass()+"): "+rex.getMessage()); + } + fail("Expected an exception for nested CDATA section (coalescing: "+coal+"); instead got text \""+sb.toString()+"\" (next event "+tokenTypeDesc(type)+")"); + } + } + + // [WSTX-294]: Incorrect coalescing in some cases + public void testIssue294() throws Exception + { + XMLInputFactory f = getInputFactory(); + setCoalescing(f, true); + + InputStream in = getClass().getResource("issue294.xml").openStream(); + + // Important: only occurs when we construct a Reader -- not with InputStream + // (different offsets, perhaps?) + XMLStreamReader sr = f.createXMLStreamReader(new InputStreamReader(in, "UTF-8")); + + assertTokenType(START_ELEMENT, sr.next()); + assertEquals("Envelope", sr.getLocalName()); + assertTokenType(CHARACTERS, sr.next()); // white space + assertTokenType(START_ELEMENT, sr.next()); + assertEquals("Body", sr.getLocalName()); + assertTokenType(CHARACTERS, sr.next()); // white space + assertTokenType(START_ELEMENT, sr.next()); + assertEquals("helloResponse", sr.getLocalName()); + assertTokenType(CHARACTERS, sr.next()); // white space + assertTokenType(START_ELEMENT, sr.next()); + assertEquals("return", sr.getLocalName()); + + assertTokenType(CHARACTERS, sr.next()); + + String text = getAndVerifyText(sr); + + // Should start with "abcde" + if (!text.startsWith("abcde")) { + if (text.length() > 5) { + text = text.substring(0, 5); + } + fail("Expected cdata in 'return' element to start with 'abcde': instead got: '"+text+"'"); + } + + assertTokenType(END_ELEMENT, sr.next()); + assertEquals("return", sr.getLocalName()); + assertTokenType(CHARACTERS, sr.next()); + assertTokenType(END_ELEMENT, sr.next()); + assertEquals("helloResponse", sr.getLocalName()); + assertTokenType(CHARACTERS, sr.next()); + assertTokenType(END_ELEMENT, sr.next()); + assertEquals("Body", sr.getLocalName()); + assertTokenType(CHARACTERS, sr.next()); + assertTokenType(END_ELEMENT, sr.next()); + assertEquals("Envelope", sr.getLocalName()); + + sr.close(); + in.close(); + } + + // [woodstox-core#21]: CDATA contents truncated to buffer size (500 initially) + public void testLongerCData2() throws Exception + { + String SRC_TEXT = + "\r\n123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678\r\n" + + "Woodstox 4.0.5 does not like this embedded element. However, if you take\r\n" + + "out one or more characters from the really long line (so that less than 500 characters come between\r\n" + + "'CDATA[' and the opening of the embeddedElement tag (including LF), then Woodstox will instead\r\n" + + "complain that the CDATA section wasn't ended."; + String DST_TEXT = SRC_TEXT.replace("\r\n", "\n"); + String XML = "\r\n" + + ""; + XMLInputFactory f = getInputFactory(); + // important: don't force coalescing, that'll convert CDATA to CHARACTERS + f.setProperty(XMLInputFactory.IS_COALESCING, Boolean.FALSE); + + XMLStreamReader sr = f.createXMLStreamReader(new StringReader(XML)); + assertTokenType(START_DOCUMENT, sr.getEventType()); + assertTokenType(START_ELEMENT, sr.next()); + assertEquals("test", sr.getLocalName()); + assertTokenType(CDATA, sr.next()); + // This should still work, although with linefeed replacements + final String text = sr.getText(); + if (text.length() != DST_TEXT.length()) { + fail("Length expected as "+DST_TEXT.length()+", was "+text.length()); + } + if (!text.equals(DST_TEXT)) { + fail("Length as expected ("+DST_TEXT.length()+"), contents differ:\n"+text); + } + assertTokenType(END_ELEMENT, sr.next()); + sr.close(); + } + + // [woodstox-core#22]: and some CDATA contents truncation via different codepath + public void testLongerCData3() throws Exception { + String SRC_TEXT = + "123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678\r\n" + + "Woodstox 4.0.5 does not like this embedded element. However, if you take\r\n" + + "out one or more characters from the really long line (so that less than 500 characters come between\r\n" + + "'CDATA[' and the opening of the embeddedElement tag (including LF), then Woodstox will instead\r\n" + + "complain that the CDATA section wasn't ended."; + String DST_TEXT = SRC_TEXT.replace("\r\n", "\n"); + String XML = "\r\n" + + ""; + XMLInputFactory f = getInputFactory(); + // important: don't force coalescing, that'll convert CDATA to CHARACTERS + f.setProperty(XMLInputFactory.IS_COALESCING, Boolean.FALSE); + + XMLStreamReader sr = f.createXMLStreamReader(new StringReader(XML)); + assertTokenType(START_DOCUMENT, sr.getEventType()); + assertTokenType(START_ELEMENT, sr.next()); + assertEquals("test", sr.getLocalName()); + assertTokenType(CDATA, sr.next()); + // This should still work, although with linefeed replacements + String text = sr.getText(); + if (text.length() != DST_TEXT.length()) { + System.err.println("DEBUG: initial length = "+text.length()); + while (sr.next() == CDATA) { + text += sr.getText(); + System.err.println("DEBUG: another CDATA, len now: "+text.length()); + } +// fail("Length expected as " + DST_TEXT.length() + ", was " + text.length()); + } + if (!text.equals(DST_TEXT)) { + fail("Length as expected (" + DST_TEXT.length() + "), contents differ:\n" + text); + } +// assertTokenType(END_ELEMENT, sr.next()); + sr.close(); + } + + /* + /////////////////////////////////////////////////////////////////////// + // Private methods, other + /////////////////////////////////////////////////////////////////////// + */ + + private XMLStreamReader getReader(String contents, boolean coalescing) + throws XMLStreamException + { + XMLInputFactory f = getInputFactory(); + setCoalescing(f, coalescing); + setReplaceEntities(f, true); + setValidating(f, false); + return constructStreamReader(f, contents); + } + +} diff -Nru libwoodstox-java-4.1.3/src/test/java/org/codehaus/stax/test/stream/TestCommentRead.java libwoodstox-java-5.1.0/src/test/java/org/codehaus/stax/test/stream/TestCommentRead.java --- libwoodstox-java-4.1.3/src/test/java/org/codehaus/stax/test/stream/TestCommentRead.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/org/codehaus/stax/test/stream/TestCommentRead.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,236 @@ +package org.codehaus.stax.test.stream; + +import javax.xml.stream.*; + +/** + * Unit test suite that tests handling of XML comments (except for the + * linefeed normalization which is tested elsewhere); mostly just what + * properties is the stream reader returning when pointing to a comment. + * + * @author Tatu Saloranta + */ +public class TestCommentRead + extends BaseStreamTest +{ + public void testValidComments() + throws XMLStreamException + { + String XML = " "; + streamThrough(getReader(XML, true)); + streamThrough(getReader(XML, false)); + XML = " "; + streamThrough(getReader(XML, true)); + streamThrough(getReader(XML, false)); + } + + /** + * Method that checks properties of COMMENT + * returned by the stream reader are correct according to StAX specs. + */ + public void testCommentProperties() + throws XMLStreamException + { + /* Neither ns-awareness nor dtd-support should make any difference, + * but let's double check them... + */ + doTestProperties(true, true); + doTestProperties(true, false); + doTestProperties(false, true); + doTestProperties(false, false); + } + + public void testInvalidComment() + throws XMLStreamException + { + String XML = " "; + String XML2 = ""; + String XML3 = ""; + + for (int i = 0; i < 1; ++i) { + boolean ns = (i & 1) != 0; + + streamThroughFailing(getReader(XML, ns), + "invalid comment content (embedded \"--\")"); + streamThroughFailing(getReader(XML2, ns), + "malformed comment (extra space)"); + streamThroughFailing(getReader(XML3, ns), + "malformed comment (extra space)"); + } + } + + public void testUnfinishedComment() + throws XMLStreamException + { + String XML = ""; + + XMLStreamReader sr = getReader(XML, true); + try { + // May get an exception when parsing entity declaration... ? + // (since it contains partial token) + assertTokenType(DTD, sr.next()); + assertTokenType(START_ELEMENT, sr.next()); + int type = sr.next(); + if (type != COMMENT) { + reportNADueToEntityExpansion("testRunawayComment", type); + return; + } + type = sr.next(); + fail("Expected an exception for split/runaway comment (instead got event "+tokenTypeDesc(type)+")"); + } catch (XMLStreamException sex) { + // good + } catch (RuntimeException rex) { + // some impls. throw lazy exceptions, too... + } + } + + public void testLongComments() + throws XMLStreamException + { + final String COMMENT1 = + "Some longish comment to see if the input buffer size restrictions might apply here: the reference\nimplementation had problems beyond 256 characters\n" + +" so let's add at least that much, and preferably quite a bit more\n" + +"too... Blah blah yadda yadda: also, unquoted '&' and '<' are kosher here" + +"\nwithout any specific problems or issues." + +" Is this long enough now? :-)" + ; + + String XML = "" ++"" ++"" ++" \n" ++"]>" + ; + XMLStreamReader sr = getReader(XML, true); + assertTokenType(COMMENT, sr.next()); + assertEquals(COMMENT1, getAndVerifyText(sr)); + assertTokenType(PROCESSING_INSTRUCTION, sr.next()); + assertTokenType(DTD, sr.next()); + assertTokenType(START_ELEMENT, sr.next()); + assertEquals("root", sr.getLocalName()); + assertTokenType(COMMENT, sr.next()); + assertEquals(COMMENT1, getAndVerifyText(sr)); + assertTokenType(END_ELEMENT, sr.next()); + } + + /* + //////////////////////////////////////// + // Private methods, shared test code + //////////////////////////////////////// + */ + + private void doTestProperties(boolean nsAware, boolean dtd) + throws XMLStreamException + { + XMLStreamReader sr = getReader("", + nsAware); + assertEquals(COMMENT, sr.next()); + + // Type info + assertEquals(false, sr.isStartElement()); + assertEquals(false, sr.isEndElement()); + assertEquals(false, sr.isCharacters()); + assertEquals(false, sr.isWhiteSpace()); + + // indirect type info + assertEquals(false, sr.hasName()); + assertEquals(true, sr.hasText()); + + assertNotNull(sr.getLocation()); + if (nsAware) { + assertNotNull(sr.getNamespaceContext()); + } + + // And then let's check methods that should throw specific exception + for (int i = 0; i < 8; ++i) { + String method = ""; + + try { + @SuppressWarnings("unused") + Object result = null; + switch (i) { + case 0: + method = "getName"; + result = sr.getName(); + break; + case 1: + method = "getPrefix"; + result = sr.getPrefix(); + break; + case 2: + method = "getLocalName"; + result = sr.getLocalName(); + break; + case 3: + method = "getNamespaceURI"; + result = sr.getNamespaceURI(); + break; + case 4: + method = "getNamespaceCount"; + result = new Integer(sr.getNamespaceCount()); + break; + case 5: + method = "getAttributeCount"; + result = new Integer(sr.getAttributeCount()); + break; + case 6: + method = "getPITarget"; + result = sr.getPITarget(); + break; + case 7: + method = "getPIData"; + result = sr.getPIData(); + break; + } + fail("Expected IllegalStateException, when calling " + +method+"() for COMMENT"); + } catch (IllegalStateException iae) { + ; // good + } + } + + String content = getAndVerifyText(sr); + assertEquals("comment & ", content); + } + + /* + //////////////////////////////////////// + // Private methods, other + //////////////////////////////////////// + */ + + private XMLStreamReader getReader(String contents, boolean nsAware) + throws XMLStreamException + { + XMLInputFactory f = getInputFactory(); + setCoalescing(f, false); // shouldn't really matter + setNamespaceAware(f, nsAware); + setValidating(f, false); + return constructStreamReader(f, contents); + } +} diff -Nru libwoodstox-java-4.1.3/src/test/java/org/codehaus/stax/test/stream/TestDoctypeDecl.java libwoodstox-java-5.1.0/src/test/java/org/codehaus/stax/test/stream/TestDoctypeDecl.java --- libwoodstox-java-4.1.3/src/test/java/org/codehaus/stax/test/stream/TestDoctypeDecl.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/org/codehaus/stax/test/stream/TestDoctypeDecl.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,363 @@ +package org.codehaus.stax.test.stream; + +import java.util.List; + +import javax.xml.stream.*; +import javax.xml.stream.events.EntityDeclaration; +import javax.xml.stream.events.NotationDeclaration; + +/** + * Unit test suite that tests handling of the DOCTYPE declaration event + * (XMLStreamConstants.DTD). + * Note that these tests are all related to the non-validating DTD-aware + * mode: actual validation tests are in separate package. Some of the + * tests are complementary to the validating mode, however, often testing + * explicitly that validity violations are not to be reported as exceptions + * in non-validating mode. + * + * @author Tatu Saloranta + */ +public class TestDoctypeDecl + extends BaseStreamTest +{ + /** + * Method that verifies properties that should be active when + * DTD is the current event. + */ + public void testProperties() + throws XMLStreamException + { + doTestProperties(false); + doTestProperties(true); + } + + public void testMinimalValidDecl() + throws XMLStreamException + { + doTestMinimalValid(false); + doTestMinimalValid(true); + } + + public void testSimpleValidDecl() + throws XMLStreamException + { + doTestSimpleValid(false); + doTestSimpleValid(true); + } + + public void testTypicalValid() + throws XMLStreamException + { + doTestTypicalValid(false); + doTestTypicalValid(true); + } + + public void testSimpleInvalidDecl() + throws XMLStreamException + { + doTestSimpleInvalid(false); + doTestSimpleInvalid(true); + } + + final static String UNPARSED_ENTITY_XML = + "\n" + +"\n" + +"]>"; + + + public void testSimpleEntity() + throws XMLStreamException + { + XMLStreamReader sr = getReader(UNPARSED_ENTITY_XML, true); + assertTokenType(DTD, sr.next()); + List l = (List) sr.getProperty("javax.xml.stream.entities"); + assertNotNull(l); + assertEquals(1, l.size()); + EntityDeclaration ed = (EntityDeclaration) l.get(0); + assertEquals("unp", ed.getName()); + assertEquals("mynot", ed.getNotationName()); + + sr.close(); + } + + public void testSimpleNotation() + throws XMLStreamException + { + XMLStreamReader sr = getReader(UNPARSED_ENTITY_XML, true); + assertTokenType(DTD, sr.next()); + List l = (List) sr.getProperty("javax.xml.stream.notations"); + assertNotNull(l); + assertEquals(1, l.size()); + NotationDeclaration nd = (NotationDeclaration) l.get(0); + assertEquals("mynot", nd.getName()); + } + + /** + * This test specifically checks to see that xml validation is + * only to be done when enabled; not just because DTD-awareness + * is enabled. + */ + public void testNonVldWithEmptyContentModel() + throws XMLStreamException + { + final boolean NS = true; + final String XML1 = + "\n" + +"\n" + +"]>" + +""; + final String XML2 = ""; + + // First, let's verify regular text is ok + XMLStreamReader sr = getReader(XML1 + "some text" + XML2, NS); + assertTokenType(DTD, sr.next()); + assertTokenType(START_ELEMENT, sr.next()); + assertTokenType(CHARACTERS, sr.next()); + streamThrough(sr); + sr.close(); + + // Then that char/general entities are + sr = getReader(XML1 + "&" + XML2, NS); + assertTokenType(DTD, sr.next()); + streamThrough(sr); + sr.close(); + + /* And then that a (declared) element is fine too + * (undeclared should be, too, but there's separate test + * elsewhere for that) + */ + sr = getReader(XML1 + "" + XML2, NS); + assertTokenType(DTD, sr.next()); + streamThrough(sr); + sr.close(); + } + + public void testNonVldWithNonMixedContentModel() + throws XMLStreamException + { + final boolean NS = true; + final String XML1 = + "\n" + +"\n" + +"]>" + +""; + final String XML2 = ""; + + XMLStreamReader sr = getReader(XML1 + "some text" + XML2, NS); + assertTokenType(DTD, sr.next()); + assertTokenType(START_ELEMENT, sr.next()); + assertTokenType(CHARACTERS, sr.next()); + streamThrough(sr); + sr.close(); + + // Then that entities are ok too + sr = getReader(XML1 + "& xxx" + XML2, NS); + assertTokenType(DTD, sr.next()); + streamThrough(sr); + sr.close(); + } + + /* + //////////////////////////////////////// + // Private methods, shared test code + //////////////////////////////////////// + */ + + private void doTestProperties(boolean nsAware) + throws XMLStreamException + { + final String PROP_TEST = + " ]>"; + + XMLStreamReader sr = getReader(PROP_TEST, nsAware); + assertEquals(DTD, sr.next()); + // Type info + assertEquals(false, sr.isStartElement()); + assertEquals(false, sr.isEndElement()); + assertEquals(false, sr.isCharacters()); + assertEquals(false, sr.isWhiteSpace()); + + // indirect type info + assertEquals(false, sr.hasName()); + assertEquals(true, sr.hasText()); + + // And then let's check methods that should throw specific exception + for (int i = 0; i <= 10; ++i) { + String method = ""; + + try { + @SuppressWarnings("unused") + Object result = null; + switch (i) { + case 0: + method = "getName"; + result = sr.getName(); + break; + case 1: + method = "getPrefix"; + result = sr.getPrefix(); + break; + case 2: + method = "getLocalName"; + result = sr.getLocalName(); + break; + case 3: + method = "getNamespaceURI"; + result = sr.getNamespaceURI(); + break; + case 4: + method = "getNamespaceCount"; + result = new Integer(sr.getNamespaceCount()); + break; + case 5: + method = "getAttributeCount"; + result = new Integer(sr.getAttributeCount()); + break; + case 6: + method = "getPITarget"; + result = sr.getPITarget(); + break; + case 7: + method = "getPIData"; + result = sr.getPIData(); + break; + case 8: + method = "getTextCharacters"; + result = sr.getTextCharacters(); + break; + case 9: + method = "getTextStart"; + result = new Integer(sr.getTextStart()); + break; + case 10: + method = "getTextLength"; + result = new Integer(sr.getTextLength()); + break; + } + fail("Expected IllegalStateException, when calling " + +method+"() for DTD"); + } catch (IllegalStateException iae) { + ; // good + } + } + + /* Here let's only check it's not null or empty, not exact contents + * (there are other tests for checking contents) + */ + String str = sr.getText(); + if (str == null || str.trim().length() == 0) { + fail("Internal subset not available; StreamReader.getText() returned an empty String (after trim())"); + } + } + + private void doTestMinimalValid(boolean nsAware) + throws XMLStreamException + { + final String VALID_TEST = ""; + + XMLStreamReader sr = getReader(VALID_TEST, nsAware); + + assertEquals(DTD, sr.next()); + assertEquals(START_ELEMENT, sr.next()); + } + + private void doTestSimpleValid(boolean nsAware) + throws XMLStreamException + { + final String INT_SUBSET = ""; + final String VALID_TEST = + ""; + + XMLStreamReader sr = getReader(VALID_TEST, nsAware); + assertTokenType(DTD, sr.next()); + + /* Now... exactly what should be returned is not quite clear. + * Let's assume that leading/trailing white space may be truncated, + * but that otherwise we'll get stuff back, with linefeeds + * normalized? + */ + String str = getAndVerifyText(sr).trim(); + + /* 16-Aug-2004, TSa: Hmmh. Specs are bit confusing; in some places + * claiming it should be only the internal subset, in others that + * it should be the full DOCTYPE declaration production... + */ + assertEquals(INT_SUBSET, str); + + sr.close(); + + /* 05-Apr-2006, TSa: Following is actually invalid, but + * well-formed. And as such, it should not throw an exception + * in non-validating mode (but should in validating mode). + */ + final String VALID_TEST2 = ""; + sr = getReader(VALID_TEST2, nsAware); + assertTokenType(DTD, sr.next()); + assertTokenType(START_ELEMENT, sr.next()); + assertEquals("fubar", sr.getLocalName()); + assertTokenType(END_ELEMENT, sr.next()); + assertTokenType(END_DOCUMENT, sr.next()); + + + } + + private void doTestTypicalValid(boolean nsAware) + throws XMLStreamException + { + final String VALID_TEST = "\n" + +"\n" + +"]>\n" + +""; + + XMLStreamReader sr = getReader(VALID_TEST, nsAware); + + assertTokenType(DTD, sr.next()); + // May or may not get SPACE... if we get it, will skip + int type; + while ((type = sr.next()) == SPACE) { + ; + } + assertTokenType(START_ELEMENT, type); + } + + private void doTestSimpleInvalid(boolean nsAware) + throws XMLStreamException + { + final String INVALID1 = " "; + streamThroughFailing(getReader(INVALID1, nsAware), + "invalid DOCTYPE declaration (missing root element)"); + + final String INVALID3 = ""; + streamThroughFailing(getReader(INVALID3, nsAware), + "invalid DOCTYPE declaration (missing SYSTEM identifier for DTD)"); + + final String INVALID4 = ""; + streamThroughFailing(getReader(INVALID4, nsAware), + "invalid DOCTYPE declaration (missing PUBLIC identifier for DTD)"); + + final String INVALID5 = ""; + streamThroughFailing(getReader(INVALID5, nsAware), + "invalid DOCTYPE declaration (unexpected ampersand character)"); + } + + /* + //////////////////////////////////////// + // Private methods, other + //////////////////////////////////////// + */ + + private XMLStreamReader getReader(String contents, boolean nsAware) + throws XMLStreamException + { + XMLInputFactory f = getInputFactory(); + setCoalescing(f, false); // shouldn't matter + setNamespaceAware(f, nsAware); + setValidating(f, false); + setSupportDTD(f, true); + return constructStreamReader(f, contents); + } +} diff -Nru libwoodstox-java-4.1.3/src/test/java/org/codehaus/stax/test/stream/TestElements.java libwoodstox-java-5.1.0/src/test/java/org/codehaus/stax/test/stream/TestElements.java --- libwoodstox-java-4.1.3/src/test/java/org/codehaus/stax/test/stream/TestElements.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/org/codehaus/stax/test/stream/TestElements.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,367 @@ +package org.codehaus.stax.test.stream; + +import javax.xml.namespace.*; +import javax.xml.stream.*; + +/** + * Unit test suite that tests handling of XML elements, both in namespace + * aware and non-namespace modes. + * + * @author Tatu Saloranta + */ +public class TestElements + extends BaseStreamTest +{ + /** + * Method that checks properties of START_ELEMENT and END_ELEMENT + * returned by the stream reader are correct according to StAX specs. + */ + public void testNsProperties() + throws XMLStreamException + { + testProperties(true, "testNsProperties"); + } + + public void testNonNsProperties() + throws XMLStreamException + { + testProperties(false, "testNonNsProperties"); + } + + /** + * Does test for simple element structure in namespace aware mode + */ + public void testValidNsElems() + throws XMLStreamException + { + testValid(true, "testValidNsElems"); + } + + public void testValidNonNsElems() + throws XMLStreamException + { + testValid(false, "testValidNonNsElems"); + } + + public void testInvalidNsElems() + throws XMLStreamException + { + testInvalid(true, "testInvalidNsElems"); + } + + public void testInvalidNonNsElems() + throws XMLStreamException + { + testInvalid(false, "testInvalidNonNsElems"); + } + + public void testEmptyDocument() + throws XMLStreamException + { + String EMPTY_XML = " "; + + // Empty documents are not valid (missing root element) + + streamThroughFailing(getElemReader(EMPTY_XML, true), + "empty document (not valid, missing root element)"); + + XMLStreamReader sr = getElemReader(EMPTY_XML, false); + if (sr != null) { // only if non-ns-aware mode supported + streamThroughFailing(sr, + "empty document (not valid, missing root element)"); + } + } + + public void testNoRootDocument() + throws XMLStreamException + { + String NOROOT_XML = "\n" + +" "; + + // Documents without root are not valid + streamThroughFailing(getElemReader(NOROOT_XML, true), + "document without root element"); + + XMLStreamReader sr = getElemReader(NOROOT_XML, false); + if (sr != null) { // only if non-ns-aware mode supported + streamThroughFailing(sr, "document without root element"); + } + } + + public void testInvalidEmptyElem() + throws XMLStreamException + { + String XML = " "; + String MSG = "malformed empty element (space between '/' and '>')"; + + streamThroughFailing(getElemReader(XML, true), MSG); + + XMLStreamReader sr = getElemReader(XML, false); + if (sr != null) { // only if non-ns-aware mode supported + streamThroughFailing(sr, MSG); + } + } + + /* + /////////////////////////////////////////////////////////// + // Private methods, shared test code + /////////////////////////////////////////////////////////// + */ + + private void testProperties(boolean nsAware, String method) + throws XMLStreamException + { + XMLStreamReader sr = getElemReader("", nsAware); + if (sr == null) { + reportNADueToNS(method); + return; + } + + assertEquals(START_ELEMENT, sr.next()); + testStartOrEnd(nsAware, sr, true); + + assertEquals(END_ELEMENT, sr.next()); + testStartOrEnd(nsAware, sr, false); + } + + private void testStartOrEnd(boolean nsAware, XMLStreamReader sr, + boolean isStart) + throws XMLStreamException + { + int evtType = isStart ? START_ELEMENT : END_ELEMENT; + assertEquals(evtType, sr.getEventType()); + String eventStr = tokenTypeDesc(evtType); + + // simple type info + assertEquals(isStart, sr.isStartElement()); + assertEquals(!isStart, sr.isEndElement()); + assertEquals(false, sr.isCharacters()); + assertEquals(false, sr.isWhiteSpace()); + + // indirect type info + assertEquals(true, sr.hasName()); + assertEquals(false, sr.hasText()); + + assertNotNull(sr.getLocation()); + QName n = sr.getName(); + assertNotNull(n); + assertEquals("root", n.getLocalPart()); + /* 07-Sep-2007, TSa: The current thinking within Stax community + * is that empty String is the right answer for all unbound + * prefixes and namespace URIs, unless explicitly defined + * that null is to be used for individual methods. + */ + assertEquals("", n.getPrefix()); + assertNoNsURI(sr); + + if (isStart) { + assertEquals(0, sr.getAttributeCount()); + } else { + try { + /*int count =*/ sr.getAttributeCount(); + fail("Expected an IllegalStateException when trying to call getAttributeCount() for "+eventStr); + } catch (IllegalStateException e) { + // good + } + } + assertEquals(0, sr.getNamespaceCount()); + if (nsAware) { + /* but how about if namespaces are not supported? Can/should + * it return null? + */ + assertNotNull(sr.getNamespaceContext()); + } + + for (int i = 0; i < 4; ++i) { + String method = ""; + + try { + @SuppressWarnings("unused") + Object result = null; + switch (i) { + case 0: + method = "getText"; + result = sr.getText(); + break; + case 1: + method = "getTextCharacters"; + result = sr.getTextCharacters(); + break; + case 2: + method = "getPITarget"; + result = sr.getPITarget(); + break; + case 3: + method = "getPIData"; + result = sr.getPIData(); + break; + } + fail("Expected IllegalStateException, when calling "+method+"() for "+eventStr); + } catch (IllegalStateException iae) { + ; // good + } + } + } + + private void testValid(boolean nsAware, String method) + throws XMLStreamException + { + final String NS_URL1 = "http://www.stax.org"; + final String NS_PREFIX1 = "prefix1"; + + final String NS_URL2 = "urn://mydummyid"; +// final String NS_PREFIX2 = "prefix2"; + + final String VALID_CONTENT + = "<"+NS_PREFIX1+":elem xmlns:"+NS_PREFIX1 + +"='"+NS_URL1+"' "+NS_PREFIX1+":attr='value'>Text" + +"" + +""; + + /* First of all, let's check that it can be completely + * parsed: + */ + XMLStreamReader sr = getElemReader(VALID_CONTENT, nsAware); + if (sr == null) { + reportNADueToNS(method); + return; + } + + streamThrough(sr); + + // And then let's do it step by step + sr = getElemReader(VALID_CONTENT, nsAware); + + // First, need to get + assertTokenType(START_ELEMENT, sr.next()); + assertEquals("root", sr.getLocalName()); + assertNoPrefix(sr); + assertNoNsURI(sr); + + // Let's also check QName seems valid: + QName name = sr.getName(); + assertNotNull("Shouldn't get null QName for any start element", name); + assertEquals(name, new QName("root")); + assertNoNsURI(sr); + assertEquals(0, sr.getAttributeCount()); + assertEquals(0, sr.getNamespaceCount()); + + // And then + assertEquals(START_ELEMENT, sr.next()); + if (nsAware) { + assertEquals("elem", sr.getLocalName()); + assertEquals(NS_PREFIX1, sr.getPrefix()); + assertEquals(NS_URL1, sr.getNamespaceURI()); + } else { + assertEquals(NS_PREFIX1+":elem", sr.getLocalName()); + assertNoPrefix(sr); + assertNoNsURI(sr); + } + + int expNs = nsAware ? 1 : 0; + int expAttr = nsAware ? 1 : 2; + + /* Let's just check counts, not values; attribute test can + * do thorough tests for values and access + */ + assertEquals(expAttr, sr.getAttributeCount()); + assertEquals(expNs, sr.getNamespaceCount()); + + assertEquals(CHARACTERS, sr.next()); + assertEquals("Text", getAndVerifyText(sr)); + + assertEquals(END_ELEMENT, sr.next()); + if (nsAware) { + assertEquals("elem", sr.getLocalName()); + assertEquals(NS_PREFIX1, sr.getPrefix()); + assertEquals(NS_URL1, sr.getNamespaceURI()); + } else { + assertEquals(NS_PREFIX1+":elem", sr.getLocalName()); + assertNoPrefix(sr); + assertNoNsURI(sr); + } + assertEquals(expNs, sr.getNamespaceCount()); + + assertEquals(START_ELEMENT, sr.next()); + assertEquals("elem2", sr.getLocalName()); + + assertNoPrefix(sr); + if (nsAware) { + assertEquals(NS_URL2, sr.getNamespaceURI()); + } else { + assertNoNsURI(sr); + } + assertEquals(expAttr, sr.getAttributeCount()); + assertEquals(expNs, sr.getNamespaceCount()); + + assertEquals(END_ELEMENT, sr.next()); + assertEquals("elem2", sr.getLocalName()); + + assertNoPrefix(sr); + if (nsAware) { + assertEquals(NS_URL2, sr.getNamespaceURI()); + } else { + assertNoNsURI(sr); + } + assertEquals(expNs, sr.getNamespaceCount()); + + assertEquals(END_ELEMENT, sr.next()); + assertEquals("root", sr.getLocalName()); + assertNoNsURI(sr); + assertNoPrefix(sr); + assertEquals(0, sr.getNamespaceCount()); + } + + /** + * Simple tests to check for incorrect nesting + */ + private void testInvalid(boolean nsAware, String method) + throws XMLStreamException + { + // Wrong end element: + String XML = " text "; + + XMLStreamReader sr = getElemReader(XML, nsAware); + if (sr == null) { + reportNADueToNS(method); + return; + } + + streamThroughFailing(sr, "incorrect nesting (wrong end element name)"); + + // For namespace mode, has to be same prefix (not just same URI) + if (nsAware) { + XML = " text "; + sr = getElemReader(XML, nsAware); + streamThroughFailing(sr, "incorrect nesting (namespace prefix in close element not the same as in start element)"); + } + + // Missing end element: + XML = " text "; + streamThroughFailing(getElemReader(XML, nsAware), + "incorrect nesting (missing end element)"); + + // More than one root: + XML = ""; + streamThroughFailing(getElemReader(XML, nsAware), + "more than one root element"); + } + + /* + /////////////////////////////////////////////////////////// + // Private methods, other + /////////////////////////////////////////////////////////// + */ + + private XMLStreamReader getElemReader(String contents, boolean nsAware) + throws XMLStreamException + { + XMLInputFactory f = getInputFactory(); + if (!setNamespaceAware(f, nsAware)) { + return null; + } + setCoalescing(f, true); + setValidating(f, false); + return constructStreamReader(f, contents); + } +} diff -Nru libwoodstox-java-4.1.3/src/test/java/org/codehaus/stax/test/stream/TestEncodingRead.java libwoodstox-java-5.1.0/src/test/java/org/codehaus/stax/test/stream/TestEncodingRead.java --- libwoodstox-java-4.1.3/src/test/java/org/codehaus/stax/test/stream/TestEncodingRead.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/org/codehaus/stax/test/stream/TestEncodingRead.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,208 @@ +package org.codehaus.stax.test.stream; + +import java.io.*; + +import javax.xml.stream.*; + +/** + * Unit test suite that tests handling of text encoding, as specified + * by XML declaration and/or specific byte-order markers. + */ +public class TestEncodingRead + extends BaseStreamTest +{ + final String UTF_1 = String.valueOf((char) 0x41); // 'A' + final String UTF_2 = String.valueOf((char) 0xA0); // nbsp + final String UTF_3 = String.valueOf((char) 0xB61); // some char that needs 3-byte encoding + + final String UTF_CONTENT = "" + +UTF_1 + UTF_2 + UTF_3 + +UTF_1 + UTF_1 + UTF_2 + UTF_2 + UTF_3 + UTF_3 + +UTF_3 + UTF_3 + UTF_2 + UTF_2 + UTF_1 + UTF_1 + +UTF_1 + UTF_3 + UTF_2 + +UTF_2 + UTF_1 + UTF_3 + +UTF_2 + UTF_3 + UTF_1 + +UTF_3 + UTF_1 + UTF_2 + +UTF_3 + UTF_2 + UTF_1 + ; + + final static byte[] BE_BOM = new byte[] { (byte) 0xFE, (byte) 0xFF }; + final static byte[] LE_BOM = new byte[] { (byte) 0xFF, (byte) 0xFE }; + final static byte[] UTF8_BOM = new byte[] { (byte) 0xEF, (byte) 0xBB, (byte) 0xBF }; + + /** + * Test to check that UTF-8 stream with no leading BOM is succesfully + * handled by parser. + */ + public void testUTF8() + throws Exception + { + doTestEncoding("UTF-8", "UTF-8", null); + doTestEncoding("UTF-8", null, null); + } + + /** + * Test to check that UTF-8 stream with leading BOM is succesfully + * handled by parser. + */ + public void testUTF8WithBOM() + throws Exception + { + doTestEncoding("UTF-8", "UTF-8", UTF8_BOM); + doTestEncoding("UTF-8", null, UTF8_BOM); + } + + public void testUTF8Surrogates() + throws XMLStreamException, IOException + { + String XML = "XXXX"; + int ix = XML.indexOf('X'); + byte[] src = XML.getBytes("UTF-8"); + + // A somewhat random high-order Unicode char: + src[ix] = (byte)0xF1; + src[ix+1] = (byte)0x90; + src[ix+2] = (byte)0x88; + src[ix+3] = (byte)0x88; + + InputStream in = new ByteArrayInputStream(src); + XMLInputFactory f = getInputFactory(); + XMLStreamReader sr = f.createXMLStreamReader(in); + + assertTokenType(START_ELEMENT, sr.next()); + assertEquals("root", sr.getLocalName()); + assertTokenType(CHARACTERS, sr.next()); + String str = getAndVerifyText(sr); + // Should result in a surrogate pair... + assertEquals(2, str.length()); + assertEquals((char) 0xd900, str.charAt(0)); + assertEquals((char) 0xde08, str.charAt(1)); + assertTokenType(END_ELEMENT, sr.next()); + } + + public void testUTF16BEWithBOM() + throws XMLStreamException, + UnsupportedEncodingException + { + doTestEncoding("UTF-16BE", "UTF-16", BE_BOM); + doTestEncoding("UTF-16BE", null, BE_BOM); + + doTestEncoding2(true); + } + + public void testUTF16LEWithBOM() + throws XMLStreamException, + UnsupportedEncodingException + { + doTestEncoding("UTF-16LE", "UTF-16", LE_BOM); + doTestEncoding("UTF-16LE", null, LE_BOM); + + doTestEncoding2(false); + } + + /* + //////////////////////////////////////// + // Private methods, shared test code + //////////////////////////////////////// + */ + + /** + * @param javaEnc Name of encoding as understood by JDK; used to + * instantiate JDK encoder/decoder to use for test + * @param xmlEnc Name of encoding as included in xml declaration; + * null to indicate nothing should be added + * @param bom Pre-defined bom bytes to prepend to input, if any. + */ + public void doTestEncoding(String javaEnc, String xmlEnc, + byte[] bom) + throws XMLStreamException, + UnsupportedEncodingException + { + String XML = ""+UTF_CONTENT+""; + + byte[] b = XML.getBytes(javaEnc); + if (bom != null) { + byte[] orig = b; + b = new byte[b.length + bom.length]; + System.arraycopy(bom, 0, b, 0, bom.length); + System.arraycopy(orig, 0, b, bom.length, orig.length); + } + + XMLStreamReader sr = getReader(b); + + if (xmlEnc != null) { + assertEquals(xmlEnc, sr.getCharacterEncodingScheme()); + } else { + /* otherwise... should we get some info? Preferably yes; + * (getEncoding() should return auto-detected encoding) + * but this is not strictly mandated by the specs? + */ + } + + assertEquals(START_ELEMENT, sr.next()); + assertEquals(CHARACTERS, sr.next()); + + assertEquals(UTF_CONTENT, getAllText(sr)); + + assertEquals(END_ELEMENT, sr.getEventType()); + assertEquals(END_DOCUMENT, sr.next()); + } + + private void doTestEncoding2(boolean bigEndian) + throws XMLStreamException + { + + /* 20-Jan-2006, TSa: Ok, let's try another variation that may + * causes problem; UTF-16 is vague, and if using JDK provided + * readers, parser has to indicate endianness. + */ + final String XML = "\n" + +"text"; + int len = XML.length(); + byte[] b = new byte[2 + len + len]; + + if (bigEndian) { + b[0] = (byte) 0xFE; + b[1] = (byte) 0xFF; + } else { + b[0] = (byte) 0xFF; + b[1] = (byte) 0xFE; + } + + int offset = bigEndian ? 3 : 2; + for (int i = 0; i < len; ++i) { + b[offset + i + i] = (byte) XML.charAt(i); + } + XMLStreamReader sr = getReader(b); + // may get white space... + int type = sr.next(); + if (type == SPACE) { + type = sr.next(); + } + assertTokenType(COMMENT, type); + assertTokenType(START_ELEMENT, sr.next()); + assertTokenType(CHARACTERS, sr.next()); + assertEquals("text", getAndVerifyText(sr)); + assertTokenType(END_ELEMENT, sr.next()); + sr.close(); + } + + /* + //////////////////////////////////////// + // Private methods, other + //////////////////////////////////////// + */ + + private XMLStreamReader getReader(byte[] contents) + throws XMLStreamException + { + XMLInputFactory f = getInputFactory(); + setValidating(f, false); + return constructStreamReader(f, contents); + } +} diff -Nru libwoodstox-java-4.1.3/src/test/java/org/codehaus/stax/test/stream/TestEntityRead.java libwoodstox-java-5.1.0/src/test/java/org/codehaus/stax/test/stream/TestEntityRead.java --- libwoodstox-java-4.1.3/src/test/java/org/codehaus/stax/test/stream/TestEntityRead.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/org/codehaus/stax/test/stream/TestEntityRead.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,634 @@ +package org.codehaus.stax.test.stream; + +import javax.xml.stream.*; + +import org.codehaus.stax.test.SimpleResolver; + +/** + * Unit test suite that tests handling of various kinds of entities. + */ +public class TestEntityRead + extends BaseStreamTest +{ + /** + * Method that tests properties of unresolved DTD event. + */ + public void testEntityProperties() + throws XMLStreamException + { + // Ns-awareness should make no different, but let's double-check it: + doTestProperties(true); + doTestProperties(false); + } + + public void testValidPredefdEntities() + throws XMLStreamException + { + String EXP = "Testing \"this\" & 'that' !? !"; + String XML = "Testing "this" & 'that' !? !"; + + XMLStreamReader sr = getReader(XML, false, true, true); + + assertTokenType(START_ELEMENT, sr.next()); + assertTokenType(CHARACTERS, sr.next()); + + // Let's not count on coalescing working, though... + StringBuffer sb = new StringBuffer(getAndVerifyText(sr)); + int type; + + while ((type = sr.next()) == CHARACTERS) { + sb.append(getAndVerifyText(sr)); + } + assertEquals(EXP, sb.toString()); + assertTokenType(END_ELEMENT, type); + } + + /** + * This unit test checks that handling of character entities works + * as expected, including corner cases like characters that expand + * to surrogate pairs in Java. + */ + public void testValidCharEntities() + throws XMLStreamException + { + String XML = "surrogates: 񐀀."; + XMLStreamReader sr = getReader(XML, true, true, true); + + assertTokenType(START_ELEMENT, sr.next()); + assertTokenType(CHARACTERS, sr.next()); + // may still be split, though (buggy coalescing) + StringBuffer sb = new StringBuffer(getAndVerifyText(sr)); + int type; + + while ((type = sr.next()) == CHARACTERS) { + sb.append(getAndVerifyText(sr)); + } + String result = sb.toString(); + String exp = "surrogates: \uD900\uDC00."; + + if (!exp.equals(result)) { + failStrings("Expected character entity &x#50000 to expand to surrogate pair with chars 0xD900 and 0xDC00", exp, result); + } + + assertTokenType(END_ELEMENT, type); + sr.close(); + } + + public void testValidGeneralEntities() + throws XMLStreamException + { + String EXP = "y yabc abc&"; + String XML = "\n" + +"" + +"" + +"]>\n" + +"&x; &both; &aa;&myAmp;"; + + XMLStreamReader sr = getReader(XML, false, true, true); + + assertTokenType(DTD, sr.next()); + int type = sr.next(); + if (type == SPACE) { + type = sr.next(); + } + assertTokenType(START_ELEMENT, type); + try { + assertTokenType(CHARACTERS, sr.next()); + } catch (XMLStreamException xse) { + fail("Expected succesful entity expansion, got: "+xse); + } + + String actual = getAndVerifyText(sr); + assertEquals(EXP, actual); + + /* !!! TBI: test things like: + * + * - Allow using single and double quotes in entity expansion value + * via param entity expansion (see next entry) + * - Rules for expanding char entities vs. generic entities (esp. + * regarding parameter entities) + */ + } + + /** + * Test that checks that generic parsed entities are returned as + * entity reference events, when automatic entity expansion is disabled. + */ + public void testUnexpandedEntities() + throws XMLStreamException + { + /* + String TEXT1 = ""Start""; + String TEXT2 = "&End..."; + */ + String XML = "]>\n" + +"&Start"&myent;End!"; + + XMLStreamReader sr = getReader(XML, false, true, false); + + assertTokenType(DTD, sr.next()); + int type = sr.next(); + + // May or may not get SPACE events in epilog (before root) + while (type == SPACE) { + type = sr.next(); + } + + assertTokenType(START_ELEMENT, type); + + assertTokenType(CHARACTERS, sr.next()); + assertEquals("&Start\"", getAndVerifyText(sr)); + + assertTokenType(ENTITY_REFERENCE, sr.next()); + assertEquals("myent", sr.getLocalName()); + assertEquals("data", getAndVerifyText(sr)); + + assertTokenType(CHARACTERS, sr.next()); + assertEquals("End!", getAndVerifyText(sr)); + + assertTokenType(END_ELEMENT, sr.next()); + assertTokenType(END_DOCUMENT, sr.next()); + + /* And then, for good measure, let's just do a longer + * one, but without exact type checks, and both with and + * without coalescing: + */ + + XML = "]>\n" + +"&Start"&myent;End!\n" + +" !&myent;&myent;&myent;&" + +""; + + // First, no coalescing + sr = getReader(XML, false, false, false); + streamThrough(sr); + + // then with coalescing + sr = getReader(XML, false, true, false); + streamThrough(sr); + } + + public void testUnexpandedEntities2() + throws XMLStreamException + { + /* Note: as per XML 1.0 specs, non-char entities (including pre-defined + * entities like 'amp' and 'lt'!) are not to be expanded before entity + * that contains them is expanded... so they are returned unexpanded. + * Char entities, however, are to be expanded. + */ + String ENTITY_VALUE = "Something slightly longer & challenging\nwhich may or may not work"; + String XML = "]>" + +"&myent;"; + + XMLStreamReader sr = getReader(XML, false, true, false); + + assertTokenType(DTD, sr.next()); + assertTokenType(START_ELEMENT, sr.next()); + assertTokenType(ENTITY_REFERENCE, sr.next()); + assertEquals("myent", sr.getLocalName()); + + // Ok, let's try the other access method: + /* 05-Apr-2006, TSa: Actually, getTextXxx() methods are not + * legal for ENTITY_REFERENCEs, can't check: + */ + /* + int len = sr.getTextLength(); + assertEquals(ENTITY_VALUE.length(), len); + int start = sr.getTextStart(); + char[] ch = new char[len]; + sr.getTextCharacters(0, ch, 0, len); + assertEquals(ENTITY_VALUE, new String(ch)); + */ + assertEquals(ENTITY_VALUE, sr.getText()); + + assertTokenType(END_ELEMENT, sr.next()); + assertTokenType(END_DOCUMENT, sr.next()); + } + + /** + * Test that checks that entities that expand to elements, comments + * and processing instructions are properly handled. + */ + public void testElementEntities() + throws XMLStreamException + { + String XML = "text'>\n" + +" '>\n" + +" '>\n" + +" \n" + +" \n" + +"]>\n" + +"&ent1;&ent2;&ent3;&ent4a;"; + + XMLStreamReader sr = getReader(XML, true, true, true); + + assertTokenType(DTD, sr.next()); + // May or may not get whitespace + int type = sr.next(); + if (type == SPACE) { + type = sr.next(); + } + assertTokenType(START_ELEMENT, type); + assertEquals("root", sr.getLocalName()); + + // First, entity that expands to element + try { + type = sr.next(); + } catch (XMLStreamException xse) { + fail("Expected succesful entity expansion, got: "+xse); + } + if (type != START_ELEMENT) { // failure + if (type == ENTITY_REFERENCE) { // most likely failure? + fail("Implementation fails to re-parse general entity expansion text: instead of element , received entity reference &"+sr.getLocalName()+";"); + } + if (type == CHARACTERS) { + String text = sr.getText(); + fail("Implementation fails to re-parse general entity expansion text: instead of element , received text ["+text.length()+"]: '"+text+"'"); + } + assertTokenType(START_ELEMENT, type); + } + assertEquals("tag", sr.getLocalName()); + assertTokenType(CHARACTERS, sr.next()); + assertEquals("text", sr.getText()); + assertTokenType(END_ELEMENT, sr.next()); + assertEquals("tag", sr.getLocalName()); + + // Then one that expands to comment + assertTokenType(COMMENT, sr.next()); + assertEquals("comment", sr.getText()); + + // Then one that expands to a PI + assertTokenType(PROCESSING_INSTRUCTION, sr.next()); + assertEquals("proc", sr.getPITarget()); + assertEquals("instr", sr.getPIData().trim()); + + // Then one that expands to text (single char) + assertTokenType(CHARACTERS, sr.next()); + assertEquals("A", sr.getText()); + + assertTokenType(END_ELEMENT, sr.next()); + assertEquals("root", sr.getLocalName()); + } + + /** + * Test that verifies that it is possible to quote CDATA end marker + * ("]]>") using character and general entities. + */ + public void testQuotedCDataEndMarker() + throws XMLStreamException + { + try { + // First, using pre-defined/char entities + String XML = "" + +"Ok the usual one: ]]>" + +" and then alternatives: ]]>" + +", ]]>" + +""; + XMLStreamReader sr = getReader(XML, true, false, true); + streamThrough(sr); + } catch (Exception e) { + fail("Didn't except problems with pre-def/char entity quoted ']]>'; got: "+e); + } + + try { + // Then using general entities: + String XML = "\n" + +"]>\n" + +"" + +" &doubleBracket;> and &doubleBracket;>" + +""; + XMLStreamReader sr = getReader(XML, true, false, true); + streamThrough(sr); + } catch (Exception e) { + fail("Didn't except problems with general entity quoted ']]>'; got: "+e); + } + } + + /** + * Test that ensures that entities can have quotes in them, if quotes + * are expanded from (parameter) entities. For that need to use + * external entities, or at least ext. subset. + */ + /* + public void testValidEntityWithQuotes() + throws XMLStreamException + { + } + */ + + public void testInvalidEntityUndeclared() + throws XMLStreamException + { + XMLStreamReader sr = getReader("&myent;", + true, false, true); + try { + streamThrough(sr); + fail("Expected an exception for invalid comment content"); + } catch (Exception e) { } + } + + public void testInvalidEntityRecursive() + throws XMLStreamException + { + XMLStreamReader sr = getReader + ("\n" + +"\n" + +"]> &ent1;", + false, true, true); + + streamThroughFailing(sr, "recursive general entity/ies"); + + /* !!! TBI: test things like: + * + * - Incorrectly nested entities (only start element, no end etc) + */ + } + + public void testInvalidEntityPEInIntSubset() + throws XMLStreamException + { + /* Although PEs are allowed in int. subset, they can only be + * used to replace whole declarations; not in entity value + * expansions. + */ + XMLStreamReader sr = getReader + ("\n" + +"\n" + +"]> ", + false, true, true); + + streamThroughFailing(sr, "declaring a parameter entity in the internal DTD subset"); + } + + /** + * Test that ensures that an invalid 'partial' entity is caught; + * partial meaning that only beginning part of an entity (ie ampersand + * and zero or more of the first characters of entity id) come from + * another expanded entity, and rest comes from content following. + * Such partial entities are not legal according to XML specs. + */ + public void testInvalidEntityPartial() + throws XMLStreamException + { + XMLStreamReader sr = getReader + ("\n" + +"]>&partial;;", + false, false, true); + + /* Hmmh. Actually, fully conforming implementations should throw + * an exception when parsing internal DTD subset. But better + * late than never; it's ok to fail on expansion too, as far as + * this test is concerned. + */ + int type1, type2; + int lastType; + + try { + type1 = sr.next(); + type2 = sr.next(); + while ((lastType = sr.next()) == CHARACTERS) { + ; + } + } catch (XMLStreamException e) { + return; // ok + } catch (RuntimeException e) { // some impls throw lazy exceptions + return; // ok + } + assertTokenType(DTD, type1); + assertTokenType(START_ELEMENT, type2); + fail("Expected an exception for partial entity reference: current token after text: "+tokenTypeDesc(lastType)); + } + + /** + * This unit test checks that external entities can be resolved; and + * to do that without requiring external files, will use a simple + * helper resolver + */ + public void testExternalEntityWithResolver() + throws XMLStreamException + { + String ENTITY_VALUE1 = "some text from the external entity"; + String ACTUAL_VALUE1 = "ent='"+ENTITY_VALUE1+"'"; + String XML = + "\n" + +"]>ent='&extEnt;'"; + + // ns-aware, coalescing (to simplify verifying), entity expanding + XMLInputFactory f = doGetFactory(true, true, true); + + if (!setSupportExternalEntities(f, true)) { + reportNADueToExtEnt("testExternalEntityWithResolver"); + return; + } + + setResolver(f, new SimpleResolver(ENTITY_VALUE1)); + + // First, simple content without further expansion etc + XMLStreamReader sr = constructStreamReader(f, XML); + assertTokenType(DTD, sr.next()); + assertTokenType(START_ELEMENT, sr.next()); + assertTokenType(CHARACTERS, sr.next()); + assertEquals(ACTUAL_VALUE1, getAndVerifyText(sr)); + assertTokenType(END_ELEMENT, sr.next()); + sr.close(); + + // Then bit more complicated one: + + String ENTITY_VALUE2 = "external entity: this & that &intEnt;"; + String ACTUAL_VALUE2a = "ent='external entity: "; + String ACTUAL_VALUE2b = " this & that & more!'"; + String XML2 = + "\n" + +"\n" + +"]>ent='&extEnt;'"; + setResolver(f, new SimpleResolver(ENTITY_VALUE2)); + + sr = constructStreamReader(f, XML2); + assertTokenType(DTD, sr.next()); + assertTokenType(START_ELEMENT, sr.next()); + assertTokenType(CHARACTERS, sr.next()); + assertEquals(ACTUAL_VALUE2a, getAndVerifyText(sr)); + assertTokenType(START_ELEMENT, sr.next()); + assertEquals("leaf", sr.getLocalName()); + assertTokenType(END_ELEMENT, sr.next()); + assertTokenType(CHARACTERS, sr.next()); + assertEquals(ACTUAL_VALUE2b, getAndVerifyText(sr)); + assertTokenType(END_ELEMENT, sr.next()); + sr.close(); + } + + /* + /////////////////////////////////////////////////////////// + // Private methods, shared test code + /////////////////////////////////////////////////////////// + */ + + private void doTestProperties(boolean nsAware) + throws XMLStreamException + { + XMLStreamReader sr = getReader + ("\n" + +"\n" + +"]>&myent;&ent2;", + nsAware, false, false); + + assertTokenType(DTD, sr.next()); + assertTokenType(START_ELEMENT, sr.next()); + assertTokenType(ENTITY_REFERENCE, sr.next()); + + /* Ok, now we can test actual properties we + * are interested in: + */ + + // Type info + assertEquals(false, sr.isStartElement()); + assertEquals(false, sr.isEndElement()); + assertEquals(false, sr.isCharacters()); + assertEquals(false, sr.isWhiteSpace()); + + // indirect type info + /* 29-Jul-2004: It's kind of unintuitive, but API says hasName() + * is only true for start/end elements... + */ + assertEquals(false, sr.hasName()); + + /* And this returns true at least for internal entities, like the one + * we hit first + */ + assertEquals(true, sr.hasText()); + + // Now, local name is accessible, still: + assertEquals("myent", sr.getLocalName()); + + // And replacement text too: + assertEquals("value", getAndVerifyText(sr)); + + assertNotNull(sr.getLocation()); + if (nsAware) { + assertNotNull(sr.getNamespaceContext()); + } + + // And then let's check methods that should throw specific exception + for (int i = 0; i <= 9; ++i) { + String method = ""; + + try { + @SuppressWarnings("unused") + Object result = null; + switch (i) { + case 0: + method = "getName"; + result = sr.getName(); + break; + case 1: + method = "getPrefix"; + result = sr.getPrefix(); + break; + case 2: + method = "getNamespaceURI"; + result = sr.getNamespaceURI(); + break; + case 3: + method = "getNamespaceCount"; + result = new Integer(sr.getNamespaceCount()); + break; + case 4: + method = "getAttributeCount"; + result = new Integer(sr.getAttributeCount()); + break; + case 5: + method = "getPITarget"; + result = sr.getPITarget(); + break; + case 6: + method = "getPIData"; + result = sr.getPIData(); + break; + case 7: + method = "getTextCharacters"; + result = sr.getTextCharacters(); + break; + case 8: + method = "getTextStart"; + result = new Integer(sr.getTextStart()); + break; + case 9: + method = "getTextLength"; + result = new Integer(sr.getTextLength()); + break; + } + fail("Expected IllegalArgumentException, when calling " + +method+"() for ENTITY_REFERENCE"); + } catch (IllegalStateException iae) { + ; // good + } + } + + + // // Ok, and the second entity; an external one + + assertTokenType(ENTITY_REFERENCE, sr.next()); + + assertEquals("ent2", sr.getLocalName()); + + /* Now, text replacement... it seems like hasText() should still + * return true, by default, but getText() (etc) should return + * null? + */ + String text = sr.getText(); + + if (text != null && text.length() > 0) { + fail("Expected getText() for external entity 'ent2' to return null or empty String; instead got '"+text+"'"); + } + + // // ok, should be good: + assertTokenType(END_ELEMENT, sr.next()); + assertTokenType(END_DOCUMENT, sr.next()); + + } + + /* + /////////////////////////////////////////////////////////// + // Private methods, other + /////////////////////////////////////////////////////////// + */ + + /** + * Note: all readers for this set of unit tests enable DTD handling; + * otherwise entity definitions wouldn't be read. Validation shouldn't + * need to be enabled just for that purpose. + */ + private XMLStreamReader getReader(String contents, boolean nsAware, + boolean coalescing, boolean replEntities) + throws XMLStreamException + { + XMLInputFactory f = doGetFactory(nsAware, coalescing, replEntities); + return constructStreamReader(f, contents); + } + + private XMLInputFactory doGetFactory(boolean nsAware, + boolean coalescing, boolean replEntities) + throws XMLStreamException + { + XMLInputFactory f = getInputFactory(); + setNamespaceAware(f, nsAware); + setSupportDTD(f, true); + setCoalescing(f, coalescing); + setSupportExternalEntities(f, true); + setReplaceEntities(f, replEntities); + setValidating(f, false); + return f; + } +} diff -Nru libwoodstox-java-4.1.3/src/test/java/org/codehaus/stax/test/stream/TestEpilog.java libwoodstox-java-5.1.0/src/test/java/org/codehaus/stax/test/stream/TestEpilog.java --- libwoodstox-java-4.1.3/src/test/java/org/codehaus/stax/test/stream/TestEpilog.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/org/codehaus/stax/test/stream/TestEpilog.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,105 @@ +package org.codehaus.stax.test.stream; + +import javax.xml.stream.*; + +/** + * Unit test suite that tests that events from prolog and epilog are + * correctly reported (and normalized if need be) by the stream reader. + */ +public class TestEpilog + extends BaseStreamTest +{ + public void testValidEpilog() + throws XMLStreamException + { + String XML = " "; + + XMLStreamReader sr = getReader(XML, true); + assertTokenType(COMMENT, sr.next()); + assertEquals(" test comment ", getAndVerifyText(sr)); + + // May or may not get white space in epilog... + int type; + while ((type = sr.next()) == SPACE) { + ; + } + assertTokenType(START_ELEMENT, type); + assertTokenType(END_ELEMENT, sr.next()); + + while ((type = sr.next()) == SPACE) { + ; + } + assertTokenType(PROCESSING_INSTRUCTION, type); + assertEquals("some", sr.getPITarget()); + // Not sure if the white space between target and data is included... + assertEquals("processing instruction", sr.getPIData().trim()); + + while ((type = sr.next()) == SPACE) { + ; + } + + assertTokenType(COMMENT, type); + assertEquals(" another comment! ", getAndVerifyText(sr)); + + while ((type = sr.next()) == SPACE) { + ; + } + assertTokenType(END_DOCUMENT, type); + } + + public void testInvalidEpilog() + throws XMLStreamException + { + /* Once again, ns/non-ns shouldn't matter... but you + * never know + */ + doTestInvalid(false); + doTestInvalid(true); + } + + /* + //////////////////////////////////////// + // Private methods, shared test code + //////////////////////////////////////// + */ + + private void doTestInvalid(boolean nsAware) + throws XMLStreamException + { + // Text before the root element: + String XML = " yeehaw! "; + try { + streamThrough(getReader(XML, nsAware)); + fail("Expected an exception for text in prolog"); + } catch (Exception e) { + ; // good + } + + // Text after the root element: + XML = " foobar"; + try { + streamThrough(getReader(XML, nsAware)); + fail("Expected an exception for text in epilog"); + } catch (Exception e) { + ; // good + } + + } + + /* + //////////////////////////////////////// + // Private methods, other + //////////////////////////////////////// + */ + + private XMLStreamReader getReader(String contents, boolean nsAware) + throws XMLStreamException + { + XMLInputFactory f = getInputFactory(); + // Let's coalesce, makes it easier to skip white space + setCoalescing(f, true); + setNamespaceAware(f, nsAware); + setValidating(f, false); + return constructStreamReader(f, contents); + } +} diff -Nru libwoodstox-java-4.1.3/src/test/java/org/codehaus/stax/test/stream/TestFilteredReader.java libwoodstox-java-5.1.0/src/test/java/org/codehaus/stax/test/stream/TestFilteredReader.java --- libwoodstox-java-4.1.3/src/test/java/org/codehaus/stax/test/stream/TestFilteredReader.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/org/codehaus/stax/test/stream/TestFilteredReader.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,96 @@ +package org.codehaus.stax.test.stream; + +import javax.xml.stream.*; + +/** + * Simple unit test suite that tries to if filtered stream readers are + * constructed and can be used. + *

+ * One thing to note, though, is that the StAX specs do not tell much + * anything about expected ways that the implementation is to deal with + * problems resulting from filtering END_DOCUMENT event and so forth. + * + * @author Tatu Saloranta + */ +public class TestFilteredReader + extends BaseStreamTest +{ + /** + * Simplest possible test: let's only check that we can actually + * construct an instance with dummy filter that accepts everything, + * and that we can traverse through all the events as usual. + */ + public void testCreation() + throws XMLStreamException + { + XMLStreamReader sr = createFilteredReader(new MyFilter(), "text", true); + + assertTokenType(START_DOCUMENT, sr.getEventType()); + assertTokenType(START_ELEMENT, sr.next()); + assertEquals("root", sr.getLocalName()); + assertEquals(0, sr.getAttributeCount()); + assertNotNull(sr.getName()); + assertTokenType(CHARACTERS, sr.next()); + assertEquals("text", getAndVerifyText(sr)); + assertTokenType(END_ELEMENT, sr.next()); + assertEquals("root", sr.getLocalName()); + assertTokenType(END_DOCUMENT, sr.next()); + } + + public void testStartElemFilter1() + throws XMLStreamException + { + XMLStreamReader sr = createFilteredReader + (getElementFilter("elem"), + "text", true); + // Should skip the START_DOCUMENT due to filter + assertTokenType(START_ELEMENT, sr.getEventType()); + } + + public void testStartElemFilter2() + throws XMLStreamException + { + XMLStreamReader sr = createFilteredReader + (getElementFilter("elem"), + "...text", true); + // Should skip START_DOCUMENT, START_ELEMENT and CHARACTERS + assertTokenType(START_ELEMENT, sr.getEventType()); + assertEquals("elem", sr.getLocalName()); + } + + /* + //////////////////////////////////////// + // Non-test methods + //////////////////////////////////////// + */ + + private StreamFilter getElementFilter(final String localName) + { + return new StreamFilter() { + @Override + public boolean accept(XMLStreamReader r) { + return r.getEventType() == XMLStreamConstants.START_ELEMENT && + r.getLocalName().equals(localName); + } + }; + } + + private XMLStreamReader createFilteredReader(StreamFilter filter, String content, + boolean nsAware) + throws XMLStreamException + { + XMLInputFactory f = getInputFactory(); + setNamespaceAware(f, nsAware); + XMLStreamReader base = constructStreamReader(f, content); + return f.createFilteredReader(base, filter); + } + + final static class MyFilter + implements StreamFilter + { + @Override + public boolean accept(XMLStreamReader reader) { + return true; + } + } +} diff -Nru libwoodstox-java-4.1.3/src/test/java/org/codehaus/stax/test/stream/TestGetSegmentedText.java libwoodstox-java-5.1.0/src/test/java/org/codehaus/stax/test/stream/TestGetSegmentedText.java --- libwoodstox-java-4.1.3/src/test/java/org/codehaus/stax/test/stream/TestGetSegmentedText.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/org/codehaus/stax/test/stream/TestGetSegmentedText.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,284 @@ +package org.codehaus.stax.test.stream; + +import java.io.*; + +import javax.xml.stream.*; + +/** + * Unit test suite that ensures that the 'segmented' text accessors + * (multi-argument getTextCharacters) works as expected, with various + * combinations of access lengths, and orderings. + * + * @author Tatu Saloranta + */ +public class TestGetSegmentedText + extends BaseStreamTest +{ + static String sXmlInput = null; + static String sExpResult = null; + + public void testCoalescingAutoEntity() + throws Exception + { + doTest(false, true, true); // non-ns + doTest(true, true, true); // ns-aware + } + + public void testNonCoalescingAutoEntity() + throws Exception + { + doTest(false, false, true); // non-ns + doTest(true, false, true); // ns-aware + } + + public void testCoalescingNonAutoEntity() + throws Exception + { + doTest(false, true, false); // non-ns + doTest(true, true, false); // ns-aware + } + + public void testNonCoalescingNonAutoEntity() + throws Exception + { + doTest(false, false, false); // non-ns + doTest(true, false, false); // ns-aware + } + + public void testSegmentedGetCharacters() + throws XMLStreamException + { + final String TEXT = "Let's just add some content in here ('') to fill some of the parser buffers, to test multi-argument getTextCharacters() method"; + final String XML = ""+TEXT+""; + + XMLInputFactory f = getFactory(true, false, true); + XMLStreamReader sr = constructStreamReader(f, XML); + + // May or may not get the prolog comment + int type = sr.next(); + if (type == COMMENT) { + type = sr.next(); + } + assertTokenType(START_ELEMENT, type); + assertTokenType(PROCESSING_INSTRUCTION, sr.next()); + type = sr.next(); + assertTokenType(CHARACTERS, type); + + /* Ok... let's just access all the text, by one char reads, from + * possibly multiple events: + */ + StringBuffer sb = new StringBuffer(); + while (type == CHARACTERS) { + char[] buf = new char[5]; + int offset = 0; + int count; + + while (true) { // let's use 2 different size of requests... + int start, len; + + if ((offset & 1) == 0) { + start = 2; + len = 1; + } else { + start = 0; + len = buf.length; + } + count = sr.getTextCharacters(offset, buf, start, len); + if (count > 0) { + sb.append(buf, start, count); + offset += count; + } + if (count < len) { + break; + } + } + + type = sr.next(); + } + + assertEquals(TEXT, sb.toString()); + assertTokenType(END_ELEMENT, type); + } + + /* + //////////////////////////////////////// + // Private methods, common test code + //////////////////////////////////////// + */ + + private void doTest(boolean ns, boolean coalescing, boolean autoEntity) + throws Exception + { + // This is bit hacky, but speeds up testing... + if (sXmlInput == null) { + initData(); + } + + // And let's also check using different buffer sizes: + for (int sz = 0; sz < 3; ++sz) { + // Let's test different input methods too: + for (int j = 0; j < 3; ++j) { + + XMLInputFactory f = getFactory(ns, coalescing, autoEntity); + XMLStreamReader sr; + + switch (j) { + case 0: // simple StringReader: + sr = constructStreamReader(f, sXmlInput); + break; + case 1: // via InputStream and auto-detection + /* It shouldn't really contain anything outside ISO-Latin; + * however, detection may be tricky.. so let's just + * test with UTF-8, for now? + */ + { + ByteArrayInputStream bin = new ByteArrayInputStream + (sXmlInput.getBytes("UTF-8")); + sr = f.createXMLStreamReader(bin); + } + break; + case 2: // explicit UTF-8 stream + { + ByteArrayInputStream bin = new ByteArrayInputStream + (sXmlInput.getBytes("UTF-8")); + Reader br = new InputStreamReader(bin, "UTF-8"); + sr = f.createXMLStreamReader(br); + } + break; + default: throw new Error("Internal error"); + } + + char[] cbuf; + + if (sz == 0) { + cbuf = new char[23]; + } else if (sz == 1) { + cbuf = new char[384]; + } else { + cbuf = new char[4005]; + } + + assertTokenType(START_ELEMENT, sr.next()); + int segCount = 0; + int totalLen = sExpResult.length(); + StringBuffer totalBuf = new StringBuffer(totalLen); + + /* Ok; for each segment let's test separately first, + * and then combine all the results together as well + */ + while (sr.next() == CHARACTERS) { + // Where are we within the whole String? + int segOffset = totalBuf.length(); + + ++segCount; + // Should not get multiple when coalescing... + if (coalescing && segCount > 1) { + fail("Didn't expect multiple CHARACTERS segments when coalescing: first segment contained "+segOffset+" chars from the whole expected "+totalLen+" chars"); + } + StringBuffer sb = new StringBuffer(); + int count; + int offset = 0; + int readCount = 0; + + while ((count = sr.getTextCharacters(offset, cbuf, 0, cbuf.length)) > 0) { + ++readCount; + sb.append(cbuf, 0, count); + offset += count; + } + int expLen = sr.getTextLength(); + + // Sanity check #1: should get matching totals + assertEquals + ("Expected segment #"+segOffset+" (one-based; read with "+readCount+" reads) to have length of " + +expLen+"; reported to have gotten just "+offset+" chars", + expLen, offset); + + // Sanity check #2: and string buf should have it too + assertEquals + ("Expected segment #"+segOffset+" (one-based; read with "+readCount+" reads) to get " + +expLen+" chars; StringBuffer only has "+sb.length(), + expLen, sb.length()); + + totalBuf.append(sb); + } + assertTokenType(END_ELEMENT, sr.getEventType()); + + // Ok; all gotten, does it match? + assertEquals("Expected total of "+totalLen+" chars, got "+totalBuf.length(), + sExpResult.length(), totalBuf.length()); + + // Lengths are ok, but how about content? + if (!sExpResult.equals(totalBuf.toString())) { + // TODO: indicate where they differ? + String str1 = sExpResult; + String str2 = totalBuf.toString(); + int len = str1.length(); + int i = 0; + char c1 = 'x', c2 = 'x'; + + for (; i < len; ++i) { + c1 = str1.charAt(i); + c2 = str2.charAt(i); + if (c1 != c2) { + break; + } + } + fail("Expected Strings to equal; differed at character #"+i+" (length "+len+" was correct); expected '"+c1+"' ("+((int) c1)+"), got '"+c2+"' ("+((int) c2)+")"); + + sr.close(); + } + } + } + } + + /* + //////////////////////////////////////// + // Private methods, other + //////////////////////////////////////// + */ + + private XMLInputFactory getFactory(boolean nsAware, + boolean coalescing, boolean autoEntity) + throws XMLStreamException + { + XMLInputFactory f = getInputFactory(); + setNamespaceAware(f, nsAware); + setCoalescing(f, coalescing); + setReplaceEntities(f, autoEntity); + + setSupportDTD(f, true); + setValidating(f, false); + return f; + } + + private void initData() + throws XMLStreamException + { + StringBuffer sb = new StringBuffer(""); + sb.append(""); + + /* Let's create a ~64kchar text segment for testing, first; and one + * including stuff like linefeeds and (pre-defined) entities. + */ + while (sb.length() < 65000) { + sb.append("abcd efgh\r\nijkl & mnop < > qrst\n uvwx\r yz A"); + } + + sb.append(""); + final String XML = sb.toString(); + + /* But more than that, let's also see what we should get + * as a result... + */ + XMLInputFactory f = getFactory(true, false, true); + XMLStreamReader sr = constructStreamReader(f, XML); + assertTokenType(START_ELEMENT, sr.next()); + StringBuffer sb2 = new StringBuffer(XML.length()); + while (sr.next() == CHARACTERS) { + sb2.append(sr.getText()); + } + + sXmlInput = XML; + sExpResult = sb2.toString(); + } +} diff -Nru libwoodstox-java-4.1.3/src/test/java/org/codehaus/stax/test/stream/TestLinefeeds.java libwoodstox-java-5.1.0/src/test/java/org/codehaus/stax/test/stream/TestLinefeeds.java --- libwoodstox-java-4.1.3/src/test/java/org/codehaus/stax/test/stream/TestLinefeeds.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/org/codehaus/stax/test/stream/TestLinefeeds.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,294 @@ +package org.codehaus.stax.test.stream; + +import javax.xml.stream.*; + +/** + * Unit test suite that tests linefeed normalization features of parsers. + */ +public class TestLinefeeds + extends BaseStreamTest +{ + final String IN_SPACES1 = " \r \n \r\n "; + final String OUT_SPACES1 = " \n \n \n "; + + final String IN_SPACES2 = "\r\r \n \r"; + final String OUT_SPACES2 = "\n\n \n \n"; + + final String IN_SPACES3 = " \r\n \r\n \r\n"; + final String OUT_SPACES3 = " \n \n \n"; + + final String IN_MIXED1 = "Something\nwonderful (?)\rhas...\r\r\n happened "; + final String OUT_MIXED1 = "Something\nwonderful (?)\nhas...\n\n happened "; + + /** + * Test that checks that if ignorable whitespace is reported from + * epilog and/or prolog, it will be properly normalized. + */ + public void testLfInEpilog() + throws XMLStreamException + { + final String contents = IN_SPACES1+""+IN_SPACES2; + + for (int i = 0; i < 4; ++i) { + XMLInputFactory f = getInputFactory(); + boolean coal = ((i & 1) == 0); + boolean ns = ((i & 2) == 0); + setCoalescing(f, coal); + setNamespaceAware(f, ns); + XMLStreamReader sr = constructStreamReader(f, contents); + + /* Since reporting (ignorable) white space is optional, have to + * be careful... + */ + int type = sr.next(); + if (type == SPACE) { // ok + String str = getAndVerifyText(sr); + while ((type = sr.next()) == SPACE) { + str += getAndVerifyText(sr); + } + assertEquals(printable(OUT_SPACES1), printable(str)); + } + + // Either way, needs to have the root element now + assertEquals(START_ELEMENT, type); + assertEquals("root", sr.getLocalName()); + assertNoPrefix(sr); + + // And then matching virtual close + assertEquals(END_ELEMENT, sr.next()); + assertEquals("root", sr.getLocalName()); + assertNoPrefix(sr); + + // And then we may get more whitespace: + type = sr.next(); + if (type == SPACE) { // ok + String str = getAndVerifyText(sr); + while ((type = sr.next()) == SPACE) { + str += getAndVerifyText(sr); + } + if (!str.equals(OUT_SPACES2)) { + String exp = printable(OUT_SPACES2); + String act = printable(str); + fail("Failed (coalesce: "+coal+", ns-aware: "+ns+"); expected '"+exp+"', got '"+act+"'."); + } + } + + assertEquals(END_DOCUMENT, type); + } + } + + public void testLfInCData() + throws XMLStreamException + { + /* Split into separate calls, to make it easier to see which + * combination failed (from stack trace) + */ + doTestLfInCData(false, false); + doTestLfInCData(false, true); + doTestLfInCData(true, false); + doTestLfInCData(true, true); + } + + private void doTestLfInCData(boolean ns, boolean coalescing) + throws XMLStreamException + { + final String contents = ""; + + XMLInputFactory f = getInputFactory(); + setCoalescing(f, coalescing); + setNamespaceAware(f, ns); + XMLStreamReader sr = constructStreamReader(f, contents); + + // Then should get the root element: + // Either way, needs to have the root element now + assertEquals(START_ELEMENT, sr.next()); + assertEquals("root", sr.getLocalName()); + assertNoPrefix(sr); + + /* Then we will get either CDATA or CHARACTERS type; let's + * NOT do thorough check here -- that'll be up to specific + * CDATA unit tests on a separate suite. + */ + int type = sr.next(); + + assertTrue("Expected either CDATA or CHARACTERS event, got "+type, + (type == CDATA || type == CHARACTERS)); + + String str = getAndVerifyText(sr); + /* If we are not coalescing, data can (in theory) be split + * up... + */ + if (coalescing) { + type = sr.next(); + } else { + while (true) { + type = sr.next(); + if (type != CDATA && type != CHARACTERS) { + break; + } + str += getAndVerifyText(sr); + } + } + + String exp = OUT_SPACES1+OUT_SPACES2; + if (!str.equals(exp)) { + fail("Failed (coalesce: "+coalescing+", ns-aware: "+ns+"); expected '" + +printable(exp)+"', got '"+printable(str)+"'."); + } + + // Plus, should get the close element too + assertEquals(END_ELEMENT, type); + assertEquals("root", sr.getLocalName()); + assertNoPrefix(sr); + + // And then the end doc + assertEquals(END_DOCUMENT, sr.next()); + } + + public void testLfInProcInstr() + throws XMLStreamException + { + /* Since exact handling of the white space between target and + * data is not well-defined by the specs, let's just add markers + * and trim such white space out... + */ + final String contents = "" + +""; + + /* There really shouldn't be any difference between coalescing/non + * or namespace aware/non-ns modes, let's try out the combinations + * just in case + */ + for (int i = 0; i < 4; ++i) { + XMLInputFactory f = getInputFactory(); + setCoalescing(f, ((i & 1) == 0)); + setNamespaceAware(f, ((i & 2) == 0)); + + XMLStreamReader sr = constructStreamReader(f, contents); + + // Then should get the root element: + // Either way, needs to have the root element now + assertEquals(START_ELEMENT, sr.next()); + assertEquals("root", sr.getLocalName()); + assertNoPrefix(sr); + + assertEquals(PROCESSING_INSTRUCTION, sr.next()); + assertEquals("target", sr.getPITarget()); + + // Ok, how about the contents: + String data = sr.getPIData(); + String exp = "["+OUT_SPACES1+OUT_SPACES2+"]"; + + assertEquals(printable(exp), printable(data)); + + // And some more white space + lf handling: + assertEquals(PROCESSING_INSTRUCTION, sr.next()); + assertEquals("target", sr.getPITarget()); + + data = sr.getPIData(); + exp = "["+OUT_SPACES3+"]"; + assertEquals(printable(exp), printable(data)); + + // Plus, should get the close element too + assertEquals(END_ELEMENT, sr.next()); + assertEquals("root", sr.getLocalName()); + assertNoPrefix(sr); + + // And then the end doc + assertEquals(END_DOCUMENT, sr.next()); + } + } + + public void testLfInComment() + throws XMLStreamException + { + final String contents = "" + +"" + +"" + +"" + +"" + +""; + + /* There really shouldn't be any difference between coalescing/non + * or namespace aware/non-ns modes, but let's try out the combinations + * just in case (some implementations may internally have differing + * handling) + */ + for (int i = 0; i < 4; ++i) { + XMLInputFactory f = getInputFactory(); + setCoalescing(f, ((i & 1) == 0)); + setNamespaceAware(f, ((i & 2) == 0)); + + XMLStreamReader sr = constructStreamReader(f, contents); + + // Then should get the root element: + // Either way, needs to have the root element now + assertEquals(START_ELEMENT, sr.next()); + assertEquals("root", sr.getLocalName()); + assertNoPrefix(sr); + + assertEquals(COMMENT, sr.next()); + assertEquals(printable(OUT_SPACES1), printable(sr.getText())); + assertEquals(COMMENT, sr.next()); + assertEquals(printable(OUT_SPACES2), printable(sr.getText())); + assertEquals(COMMENT, sr.next()); + assertEquals(printable(OUT_SPACES3), printable(sr.getText())); + assertEquals(COMMENT, sr.next()); + assertEquals(printable(OUT_MIXED1), printable(sr.getText())); + + // Plus, should get the close element too + assertEquals(END_ELEMENT, sr.next()); + assertEquals("root", sr.getLocalName()); + assertNoPrefix(sr); + + // And then the end doc + assertEquals(END_DOCUMENT, sr.next()); + } + } + + public void testLfInText() + throws XMLStreamException + { + final String contents = ""+IN_SPACES1+IN_SPACES2+""; + + for (int i = 0; i < 4; ++i) { // to test coalescing and non-coalescing + XMLInputFactory f = getInputFactory(); + boolean coalescing = ((i & 1) == 0); + setCoalescing(f, coalescing); + setNamespaceAware(f, ((i & 2) == 0)); + XMLStreamReader sr = constructStreamReader(f, contents); + + assertEquals(START_ELEMENT, sr.next()); + assertEquals(CHARACTERS, sr.next()); + + int type; + String str = getAndVerifyText(sr); + + /* If we are not coalescing, data can be split + * up... (but in practice would probably need longer input + * text?) + */ + if (coalescing) { + type = sr.next(); + } else { + while (true) { + type = sr.next(); + if (type != CDATA && type != CHARACTERS) { + break; + } + str += getAndVerifyText(sr); + } + } + + assertEquals(printable(OUT_SPACES1+OUT_SPACES2), + printable(str)); + + // Plus, should get the close element too + assertEquals(END_ELEMENT, type); + // And then the end doc + assertEquals(END_DOCUMENT, sr.next()); + } + } +} diff -Nru libwoodstox-java-4.1.3/src/test/java/org/codehaus/stax/test/stream/TestMisc.java libwoodstox-java-5.1.0/src/test/java/org/codehaus/stax/test/stream/TestMisc.java --- libwoodstox-java-4.1.3/src/test/java/org/codehaus/stax/test/stream/TestMisc.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/org/codehaus/stax/test/stream/TestMisc.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,426 @@ +package org.codehaus.stax.test.stream; + +import java.util.Random; + +import javax.xml.stream.*; + +/** + * Unit test suite that tests miscellaneous stream reader methods, such + * as require(), getElementText() and nextTag() + * @author Tatu Saloranta + */ +public class TestMisc + extends BaseStreamTest +{ + public void testRequire() + throws XMLStreamException + { + String XML = + "" + +"" + +"Text" + +"" + +"" + +"" + ; + + XMLStreamReader sr = getReader(XML, true, true); + + sr.require(START_DOCUMENT, null, null); + + assertTokenType(START_ELEMENT, sr.next()); + + assertTokenType(COMMENT, sr.next()); + sr.require(COMMENT, null, null); + try { // should get an exception due to comments not having names + sr.require(COMMENT, null, "tag"); + fail("Should have thrown an exception when checking local name of a COMMENT"); + } catch (XMLStreamException e) { + ; // good + } catch (IllegalStateException ise) { + ; // likewise this is ok, as getName() can throw it + } + + assertTokenType(PROCESSING_INSTRUCTION, sr.next()); + sr.require(PROCESSING_INSTRUCTION, null, null); + + assertTokenType(START_ELEMENT, sr.next()); + sr.require(START_ELEMENT, null, "tag"); + + String nsURI = sr.getNamespaceURI(); + try { + sr.require(START_ELEMENT, "", "tag"); + } catch (XMLStreamException e) { + fail("Did not expect problems with match (current ns URI as reported by stream reader = '"+nsURI+"'), got: "+e.getMessage()); + } + + try { // should get an exception due to incorrect ns URI + sr.require(START_ELEMENT, "http://foo", "tag"); + fail("Should have thrown an exception for incorrect NS URI"); + } catch (XMLStreamException e) { + ; // good + } + + assertTokenType(CHARACTERS, sr.next()); + sr.require(CHARACTERS, null, null); + + assertTokenType(END_ELEMENT, sr.next()); + sr.require(END_ELEMENT, null, "tag"); + sr.require(END_ELEMENT, "", "tag"); + + assertTokenType(START_ELEMENT, sr.next()); + + /* Will get CHARACTERS instead of CDATA, because it's a + * coalescing reader... + */ + assertTokenType(CHARACTERS, sr.next()); + sr.require(CHARACTERS, null, null); + + assertTokenType(END_ELEMENT, sr.next()); + + assertTokenType(START_ELEMENT, sr.next()); // empty + sr.require(START_ELEMENT, "http://foo", "empty"); + assertTokenType(END_ELEMENT, sr.next()); + sr.require(END_ELEMENT, "http://foo", "empty"); + sr.require(END_ELEMENT, "http://foo", null); + sr.require(END_ELEMENT, null, "empty"); + + assertTokenType(END_ELEMENT, sr.next()); + sr.require(END_ELEMENT, "", "root"); + + assertTokenType(END_DOCUMENT, sr.next()); + sr.require(END_DOCUMENT, null, null); + } + + public void testGetElementText() + throws XMLStreamException + { + _testGetElementText(false); + _testGetElementText(true); + } + + private void _testGetElementText(boolean textual) + throws XMLStreamException + { + String XML = "" + +"Got some text 'n stuff!" + +"more " + +"abcde" + +"" + ; + // Special: let's verify using both utf-8 and text-based readers + XMLInputFactory f = getInputFactory(); + setNamespaceAware(f, true); + + XMLStreamReader sr = textual ? constructCharStreamReader(f, XML) + : constructUtf8StreamReader(f, XML); + + // First 2 valid cases: + assertTokenType(START_ELEMENT, sr.next()); + assertTokenType(START_ELEMENT, sr.next()); + assertEquals("Got some text 'n stuff!", sr.getElementText()); + assertTokenType(END_ELEMENT, sr.getEventType()); + assertTokenType(START_ELEMENT, sr.next()); + assertEquals("more stuff ", sr.getElementText()); + assertTokenType(END_ELEMENT, sr.getEventType()); + assertTokenType(START_ELEMENT, sr.next()); + assertEquals("abcde", sr.getElementText()); + assertTokenType(END_ELEMENT, sr.getEventType()); + + assertTokenType(END_ELEMENT, sr.next()); + sr.close(); + } + + public void testGetElementTextInvalid() + throws XMLStreamException + { + String XML = "Invalid: (no kids allowed!)"; + XMLStreamReader sr = getReader(XML, true, false); + assertTokenType(START_ELEMENT, sr.next()); + + // And then should get proper exception + try { + @SuppressWarnings("unused") + String str = sr.getElementText(); + fail("Expected an exception for nested start element"); + } catch (XMLStreamException ex) { + ; // ok! (would be nice to check error message but...) + } + } + + /** + * Alternative test that tries to verify that handling of long + * and non-contiguous text segment also works acceptably. + */ + public void testGetElementTextLong() + throws XMLStreamException + { + /* Let's do multiple passes, starting with shorter Strings; + * easier to troubleshoot with shorter, better coverage with + * longer + */ + + int[] lengths = new int[] { 50, 190, 2400, 9300, 42000 }; + + for (int i = 0; i < lengths.length; ++i) { + int len = lengths[i]; + StringBuffer input = new StringBuffer(len * 3 / 2); + StringBuffer output = new StringBuffer(len + 100); + + Random r = new Random(i); + + while (output.length() < len) { + String str = null; + switch (Math.abs(r.nextInt()) % 7) { + case 0: + { + int nr = r.nextInt(); + // note: linefeed normalization + input.append(" ").append(nr).append("\r\n"); + output.append(" ").append(nr).append("\n"); + } + break; + case 1: + input.append("&"); + output.append("&"); + break; + case 2: + input.append(""); + break; + case 3: + input.append(""); + break; + case 4: + str = "abc "+((char) ('A' + i))+" xyz"; + break; + case 5: + str = ">>> "; + break; + case 6: + str = "; ?? (\u00A0, \u1123)"; + break; + } + if (str != null) { + if ((r.nextInt() & 0x3) == 1) { + input.append(""); + } else { + input.append(str); + } + output.append(str); + } + } + + final String XML = ""+input.toString()+""; + XMLStreamReader sr = getReader(XML, true, false); + + assertTokenType(START_ELEMENT, sr.next()); + String act = sr.getElementText(); + String exp = output.toString(); + assertEquals(exp, act); + sr.close(); + } + } + + /** + * Additional simple test that verifies that element text for + * an empty element is returned as empty String. + */ + public void testGetElementTextEmpty() + throws XMLStreamException + { + // First simple case + + String XML = ""; + XMLStreamReader sr = getReader(XML, true, false); + + assertTokenType(START_ELEMENT, sr.next()); + assertEquals("", sr.getElementText()); + // and then invalid + assertTokenType(END_ELEMENT, sr.getEventType()); + assertEquals("root", sr.getLocalName()); + assertTokenType(END_DOCUMENT, sr.next()); + sr.close(); + + // Then similar but longer + XML = ""; + sr = getReader(XML, true, false); + + assertTokenType(START_ELEMENT, sr.next()); // root + + assertTokenType(START_ELEMENT, sr.next()); + assertEquals("a", sr.getLocalName()); + assertEquals("", sr.getElementText()); + // and then invalid + assertTokenType(END_ELEMENT, sr.getEventType()); + + assertTokenType(START_ELEMENT, sr.next()); + assertEquals("b", sr.getLocalName()); + assertEquals("", sr.getElementText()); + // and then invalid + assertTokenType(END_ELEMENT, sr.getEventType()); + + assertTokenType(END_ELEMENT, sr.next()); + assertEquals("root", sr.getLocalName()); + assertTokenType(END_DOCUMENT, sr.next()); + } + + public void testNextTag() + throws XMLStreamException + { + String XML = + " " + +" " + +" " + +"text" + ; + XMLStreamReader sr = getReader(XML, true, false); + // First valid cases: + assertTokenType(START_ELEMENT, sr.nextTag()); + assertEquals("root", sr.getLocalName()); + assertTokenType(START_ELEMENT, sr.nextTag()); + assertTokenType(END_ELEMENT, sr.nextTag()); + assertEquals("tag", sr.getLocalName()); + + assertTokenType(START_ELEMENT, sr.nextTag()); + assertEquals("tag", sr.getLocalName()); + + assertTokenType(START_ELEMENT, sr.nextTag()); + assertEquals("leaf", sr.getLocalName()); + + assertTokenType(END_ELEMENT, sr.nextTag()); + assertEquals("leaf", sr.getLocalName()); + + assertTokenType(END_ELEMENT, sr.nextTag()); + assertEquals("tag", sr.getLocalName()); + + // And then invalid: + assertTokenType(START_ELEMENT, sr.nextTag()); + assertEquals("tag", sr.getLocalName()); + try { + @SuppressWarnings("unused") + int type = sr.nextTag(); + fail("Expected an exception for non-whitespace text"); + } catch (XMLStreamException ex) { + ; // ok! + } + } + + public void testNextTagWithCommentsAndPIs() + throws XMLStreamException + { + String XML = + " \n" + +"\n" + +" \n" + +"\n" + +"" + ; + XMLStreamReader sr = getReader(XML, true, false); + + assertTokenType(START_ELEMENT, sr.nextTag()); + assertEquals("root", sr.getLocalName()); + + // First, an empty 'leaf' element + assertTokenType(START_ELEMENT, sr.nextTag()); + assertEquals("leaf", sr.getLocalName()); + assertTokenType(END_ELEMENT, sr.nextTag()); + assertEquals("leaf", sr.getLocalName()); + + // Then one with a single PI in it + assertTokenType(START_ELEMENT, sr.nextTag()); + assertEquals("leaf", sr.getLocalName()); + assertTokenType(END_ELEMENT, sr.nextTag()); + assertEquals("leaf", sr.getLocalName()); + + // Then one with multiple comments + assertTokenType(START_ELEMENT, sr.nextTag()); + assertEquals("leaf", sr.getLocalName()); + assertTokenType(END_ELEMENT, sr.nextTag()); + assertEquals("leaf", sr.getLocalName()); + + // Then one with a mix: + assertTokenType(START_ELEMENT, sr.nextTag()); + assertEquals("leaf", sr.getLocalName()); + assertTokenType(END_ELEMENT, sr.nextTag()); + assertEquals("leaf", sr.getLocalName()); + + // And then the closing root tag + assertTokenType(END_ELEMENT, sr.nextTag()); + assertEquals("root", sr.getLocalName()); + } + + /** + * Test that checks that stream reader's behavior at the end of + * input is compliant. Specifically, an exception should be thrown + * if one tries to access events beyond END_DOCUMENT. + */ + public void testEndOfStream() + throws XMLStreamException + { + String XML = "x"; + XMLStreamReader sr = getReader(XML, true, true); + + assertTokenType(START_DOCUMENT, sr.getEventType()); + assertTokenType(START_ELEMENT, sr.next()); + assertTokenType(CHARACTERS, sr.next()); + assertTokenType(END_ELEMENT, sr.next()); + assertTokenType(END_DOCUMENT, sr.next()); + assertFalse(sr.hasNext()); + + try { + int type = sr.next(); + fail("Expected NoSuchElementException when trying to access events after END_DOCUMENT returned (but received event "+tokenTypeDesc(type)+")"); + } catch (java.util.NoSuchElementException ne) { + // good + } catch (XMLStreamException e) { // wrong exception + fail("Expected NoSuchElementException; received (type "+e.getClass()+"): "+e); + } + } + + /** + * Simple test case to verify an edge case with isWhiteSpace(). + */ + public void testIsWhiteSpace() + throws XMLStreamException + { + // First, simplest possible + XMLStreamReader sr = getReader("A?", true, true); + assertTokenType(START_DOCUMENT, sr.getEventType()); + assertTokenType(START_ELEMENT, sr.next()); + assertTokenType(CHARACTERS, sr.next()); + if (sr.isWhiteSpace()) { + fail("XMLStreamReader.isWhiteSpace() should return false, text = '"+sr.getText()+"'"); + } + sr.close(); + + // Then just bit more complex + sr = getReader("\nA?", true, true); + assertTokenType(START_DOCUMENT, sr.getEventType()); + assertTokenType(START_ELEMENT, sr.nextTag()); + assertTokenType(START_ELEMENT, sr.nextTag()); + assertTokenType(CHARACTERS, sr.next()); + if (sr.isWhiteSpace()) { + fail("XMLStreamReader.isWhiteSpace() should return false, text = '"+sr.getText()+"'"); + } + sr.close(); + } + + /* + //////////////////////////////////////// + // Private methods, other + //////////////////////////////////////// + */ + + private XMLStreamReader getReader(String contents, boolean nsAware, + boolean coalescing) + throws XMLStreamException + { + XMLInputFactory f = getInputFactory(); + setNamespaceAware(f, nsAware); + setSupportDTD(f, true); + setCoalescing(f, coalescing); + setReplaceEntities(f, true); + setValidating(f, false); + return constructStreamReader(f, contents); + } +} diff -Nru libwoodstox-java-4.1.3/src/test/java/org/codehaus/stax/test/stream/TestNamespaces.java libwoodstox-java-5.1.0/src/test/java/org/codehaus/stax/test/stream/TestNamespaces.java --- libwoodstox-java-4.1.3/src/test/java/org/codehaus/stax/test/stream/TestNamespaces.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/org/codehaus/stax/test/stream/TestNamespaces.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,693 @@ +package org.codehaus.stax.test.stream; + +import java.util.Iterator; + +import javax.xml.XMLConstants; +import javax.xml.namespace.*; +import javax.xml.stream.*; + +/** + * Unit test suite that tests handling of the namespace declarations, + * both in namespace aware and non-namespace modes. + * + * @author Tatu Saloranta + */ +public class TestNamespaces + extends BaseStreamTest +{ + final String VALID_NS_XML + = "" + +"" + +"" + +"" + +""; + + public void testValidNs() + throws XMLStreamException + { + XMLStreamReader sr = getNsReader(VALID_NS_XML, true); + assertEquals(START_ELEMENT, sr.next()); + assertEquals(1, sr.getNamespaceCount()); + assertEquals(2, sr.getAttributeCount()); + // element properties: + assertNoPrefix(sr); + assertEquals("root", sr.getLocalName()); + assertNoNsURI(sr); + // ns/attr properties: + assertEquals("value", sr.getAttributeValue(null, "attr1")); + assertEquals("", sr.getAttributeValue("myurl", "attr1")); + + checkIllegalAttributeIndexes(sr); + + // Shouldn't be able to use prefix, just URI: + assertNull(sr.getAttributeValue("xmlns", "a")); + assertEquals("myurl", sr.getNamespaceURI("a")); + assertNull(sr.getNamespaceURI("myurl")); + /* 07-Sep-2007, TSa: This is a tough call, but I do believe + * we should expect "no namespace" as the answer (== ""), not + * "unbound" (null). + */ + //assertNull(sr.getNamespaceURI("")); + assertEquals("", sr.getNamespaceURI("")); + + assertNull(sr.getNamespaceURI("nosuchurl")); + + NamespaceContext nc = sr.getNamespaceContext(); + assertNotNull(nc); + assertEquals(XMLConstants.XML_NS_URI, nc.getNamespaceURI(XMLConstants.XML_NS_PREFIX)); + assertEquals(XMLConstants.XML_NS_PREFIX, nc.getPrefix(XMLConstants.XML_NS_URI)); + assertEquals(XMLConstants.XMLNS_ATTRIBUTE_NS_URI, nc.getNamespaceURI(XMLConstants.XMLNS_ATTRIBUTE)); + assertEquals(XMLConstants.XMLNS_ATTRIBUTE, nc.getPrefix(XMLConstants.XMLNS_ATTRIBUTE_NS_URI)); + + assertEquals("myurl", nc.getNamespaceURI("a")); + assertEquals("a", nc.getPrefix("myurl")); + Iterator it = nc.getPrefixes("foobar"); + // Hmmmh. Can it be null or not? For now let's allow null too + if (it == null) { + ; + } else { + assertFalse(it.hasNext()); + } + it = nc.getPrefixes("myurl"); + assertNotNull(it); + assertTrue(it.hasNext()); + assertEquals("a", (String) it.next()); + assertFalse(it.hasNext()); + + // // Ok, then the second element: + + assertEquals(START_ELEMENT, sr.next()); + assertEquals(2, sr.getNamespaceCount()); + assertEquals(1, sr.getAttributeCount()); + assertEquals("a", sr.getPrefix()); + assertEquals("branch", sr.getLocalName()); + + assertEquals("whatever", sr.getNamespaceURI()); + assertEquals("value", sr.getAttributeValue(null, "attr")); + assertEquals("value", sr.getAttributeValue(0)); + + assertEquals("someurl", sr.getNamespaceURI("")); + + // // And finally the third + + assertEquals(START_ELEMENT, sr.next()); + assertEquals(0, sr.getNamespaceCount()); + assertEquals(2, sr.getAttributeCount()); + assertEquals("leaf", sr.getLocalName()); + assertNoPrefix(sr); + assertEquals("yyy", sr.getAttributeValue("whatever", "a")); + assertEquals("xxx", sr.getAttributeValue(null, "a")); + + assertEquals(END_ELEMENT, sr.next()); + assertEquals(0, sr.getNamespaceCount()); + assertEquals("leaf", sr.getLocalName()); + assertNoPrefix(sr); + + assertEquals(END_ELEMENT, sr.next()); + assertEquals(2, sr.getNamespaceCount()); + assertEquals("a", sr.getPrefix()); + assertEquals("branch", sr.getLocalName()); + + assertEquals(END_ELEMENT, sr.next()); + assertEquals(1, sr.getNamespaceCount()); + assertNoNsURI(sr); + assertEquals("root", sr.getLocalName()); + + assertEquals(END_DOCUMENT, sr.next()); + assertFalse(sr.hasNext()); + } + + final String VALID_NS_XML2 + ="" + +"text" + +""; + + /** + * Another unit test that checks that valid namespace declarations + * are handled properly. + */ + public void testMultipleValidNs() + throws XMLStreamException + { + XMLStreamReader sr = getNsReader(VALID_NS_XML2, true); + assertEquals(START_ELEMENT, sr.next()); + + // Let's thoroughly check the root elem + assertEquals(2, sr.getNamespaceCount()); + assertEquals(0, sr.getAttributeCount()); + assertNoPrefix(sr); + assertEquals("root", sr.getLocalName()); + assertEquals("http://foo", sr.getNamespaceURI()); + assertEquals("myurl", sr.getNamespaceURI("a")); + + // first empty elem + while (sr.next() == CHARACTERS) { } + assertTokenType(START_ELEMENT, sr.getEventType()); + assertEquals(0, sr.getNamespaceCount()); + assertEquals(1, sr.getAttributeCount()); + assertNoPrefix(sr); + assertEquals("empty", sr.getLocalName()); + assertEquals("http://foo", sr.getNamespaceURI()); + assertEquals("myurl", sr.getNamespaceURI("a")); + assertNoAttrNamespace(sr.getAttributeNamespace(0)); + assertNoAttrPrefix(sr.getAttributePrefix(0)); + assertEquals("&", sr.getAttributeValue(0)); + assertTokenType(END_ELEMENT, sr.next()); + + // second empty elem + assertTokenType(START_ELEMENT, sr.next()); + assertEquals(0, sr.getNamespaceCount()); + assertEquals(0, sr.getAttributeCount()); + assertEquals("empty", sr.getLocalName()); + assertEquals("a", sr.getPrefix()); + assertEquals("myurl", sr.getNamespaceURI()); + assertEquals("myurl", sr.getNamespaceURI("a")); + assertEquals("http://foo", sr.getNamespaceURI("")); + assertTokenType(END_ELEMENT, sr.next()); + + // And closing 'root' + assertTokenType(END_ELEMENT, sr.next()); + assertEquals("root", sr.getLocalName()); + assertEquals("http://foo", sr.getNamespaceURI()); + + assertTokenType(END_DOCUMENT, sr.next()); + } + + /** + * Test proper handling of valid xml content in non-namespace aware mode. + * Since not all implementations (like the ref. impl.) support non-ns + * aware mode, this unit test is skipped if not applicable. + */ + public void testValidNonNs() + throws XMLStreamException + { + XMLStreamReader sr = getNsReader(VALID_NS_XML, false); + if (sr == null) { + reportNADueToNS("testValidNonNs"); + return; + } + + assertEquals(START_ELEMENT, sr.next()); + assertEquals(0, sr.getNamespaceCount()); + assertEquals(3, sr.getAttributeCount()); + // element properties: + assertNoPrefix(sr); + assertEquals("root", sr.getLocalName()); + + assertNoNsURI(sr); + // ns/attr properties: + + assertEquals("value", sr.getAttributeValue(null, "attr1")); + assertEquals(null, sr.getAttributeValue(null, "foobar")); + + checkIllegalAttributeIndexes(sr); + + /* ... not sure if how namespace access should work, ie. is it ok + * to throw an exception, return null or what + */ + + // // Ok, then the second element: + + assertEquals(START_ELEMENT, sr.next()); + assertEquals(0, sr.getNamespaceCount()); + assertEquals(3, sr.getAttributeCount()); + assertEquals("a:branch", sr.getLocalName()); + assertNoPrefix(sr); + + // // And finally the third + + assertEquals(START_ELEMENT, sr.next()); + assertEquals(0, sr.getNamespaceCount()); + assertEquals(2, sr.getAttributeCount()); + assertEquals("leaf", sr.getLocalName()); + assertNoPrefix(sr); + assertEquals("xxx", sr.getAttributeValue(null, "a")); + assertEquals("yyy", sr.getAttributeValue(null, "a:a")); + + // // And then the end elements + + assertEquals(END_ELEMENT, sr.next()); + assertEquals(0, sr.getNamespaceCount()); + assertEquals("leaf", sr.getLocalName()); + assertNoPrefix(sr); + + assertEquals(END_ELEMENT, sr.next()); + assertEquals(0, sr.getNamespaceCount()); + assertEquals("a:branch", sr.getLocalName()); + assertNoPrefix(sr); + + assertEquals(END_ELEMENT, sr.next()); + assertEquals(0, sr.getNamespaceCount()); + assertNoPrefix(sr); + assertEquals("root", sr.getLocalName()); + + assertEquals(END_DOCUMENT, sr.next()); + assertFalse(sr.hasNext()); + } + + public void testInvalidNs() + throws XMLStreamException + { + testPotentiallyInvalid(true, "testInvalidNs"); + } + + public void testInvalidNonNs() + throws XMLStreamException + { + // Some things are ok, some not, when namespace support is not enabled: + testPotentiallyInvalid(false, "testInvalidNonNs"); + } + + public void testInvalidStandardBindings() + throws XMLStreamException + { + doTestXmlBinding(true, "testInvalidStandardBindings"); + doTestXmlnsBinding(true, "testInvalidStandardBindings"); + } + + public void testInvalidStandardBindingsNonNs() + throws XMLStreamException + { + doTestXmlBinding(false, "testInvalidStandardBindingsNonNs"); + doTestXmlnsBinding(false, "testInvalidStandardBindingsNonNs"); + } + + public void testDefaultNs() + throws XMLStreamException + { + String XML = ""; + + XMLStreamReader sr = getNsReader(XML, true); + assertEquals(START_ELEMENT, sr.next()); + assertEquals("root", sr.getLocalName()); + assertEquals("url", sr.getNamespaceURI()); + assertNoPrefix(sr); + NamespaceContext ctxt = sr.getNamespaceContext(); + assertEquals(1, sr.getNamespaceCount()); + assertEquals("url", sr.getNamespaceURI(0)); + assertNoAttrPrefix(sr.getNamespacePrefix(0)); + + assertEquals("url", ctxt.getNamespaceURI("")); + assertEquals("", ctxt.getPrefix("url")); + assertNull(ctxt.getNamespaceURI("b")); + assertNull(ctxt.getPrefix("ns:b")); + + + XML = ""; + + sr = getNsReader(XML, true); + assertEquals(START_ELEMENT, sr.next()); + assertEquals("root", sr.getLocalName()); + assertNoPrefix(sr); + assertNoNsURI(sr); + assertEquals(1, sr.getNamespaceCount()); + assertEquals("url", sr.getNamespaceURI(0)); + assertEquals("a", sr.getNamespacePrefix(0)); + } + + /** + * Test case that verifies that namespaces properly nest, and + * inner definitions (ns in child element) can mask outer + * definitions (ns in parent element) + */ + public void testMaskingNs() + throws XMLStreamException + { + final String XML = + ""; + + XMLStreamReader sr = getNsReader(XML, true); + assertEquals(START_ELEMENT, sr.next()); + assertEquals("root", sr.getLocalName()); + assertEquals("a", sr.getPrefix()); + assertEquals("ns:a", sr.getNamespaceURI()); + NamespaceContext ctxt = sr.getNamespaceContext(); + assertEquals("ns:a", ctxt.getNamespaceURI("a")); + assertNull(ctxt.getNamespaceURI("b")); + assertEquals("a", ctxt.getPrefix("ns:a")); + assertNull(ctxt.getPrefix("ns:b")); + + assertEquals(START_ELEMENT, sr.next()); + assertEquals("child", sr.getLocalName()); + assertEquals("a", sr.getPrefix()); + assertEquals("ns:b", sr.getNamespaceURI()); + + ctxt = sr.getNamespaceContext(); + assertEquals("ns:b", ctxt.getNamespaceURI("a")); + assertEquals("a", ctxt.getPrefix("ns:b")); + assertNull(ctxt.getNamespaceURI("b")); + + // This is testing of actual masking, using NamespaceContext + { + // Previous binding should be masked by now! + String prefix = ctxt.getPrefix("ns:a"); + if (prefix != null) { + fail("Failed: second declaration for prefix 'a' should have masked previous one; and there should not be a prefix for 'ns:a'. Instead, prefix '"+prefix+"' was considered to (still) be bound"); + } + } + } + + /** + * Unit test that verifies that the default namespace masking works + * as expected. + */ + public void testMaskingDefaultNs() + throws XMLStreamException + { + final String XML = + "" + +"" + +"" + ; + + XMLStreamReader sr = getNsReader(XML, true); + assertEquals(START_ELEMENT, sr.next()); + assertEquals("root", sr.getLocalName()); + assertNoPrefix(sr); + assertEquals("someurl", sr.getNamespaceURI()); + assertEquals(1, sr.getNamespaceCount()); + + assertEquals(START_ELEMENT, sr.next()); + assertEquals("branch", sr.getLocalName()); + assertNoPrefix(sr); + assertNoNsURI(sr); + assertEquals(1, sr.getNamespaceCount()); + + assertEquals(START_ELEMENT, sr.next()); + assertEquals("leaf", sr.getLocalName()); + assertNoPrefix(sr); + assertNoNsURI(sr); + assertEquals(0, sr.getNamespaceCount()); + assertEquals(END_ELEMENT, sr.next()); // leaf + assertEquals(0, sr.getNamespaceCount()); + + assertEquals(START_ELEMENT, sr.next()); + assertEquals("leaf", sr.getLocalName()); + assertNoPrefix(sr); + assertEquals("anotherurl", sr.getNamespaceURI()); + assertEquals(1, sr.getNamespaceCount()); + assertEquals(END_ELEMENT, sr.next()); // leaf + assertEquals(1, sr.getNamespaceCount()); + + assertEquals(END_ELEMENT, sr.next()); // branch + assertEquals(1, sr.getNamespaceCount()); + + assertEquals(END_ELEMENT, sr.next()); // root + assertEquals(1, sr.getNamespaceCount()); + } + + /** + * This specialized test case verifies that there are no + * unbinding of explict namespace prefixes in xml 1.0 + * documents. While namespaces 1.1 (and hence, xml 1.0) + * makes such use legal, xml 1.0 does not allow it. + */ + public void testUnbindingInvalindInXml10() + throws XMLStreamException + { + final String XML = + ""; + + XMLStreamReader sr = getNsReader(XML, true); + assertEquals(START_ELEMENT, sr.next()); + assertEquals("root", sr.getLocalName()); + assertNoPrefix(sr); + + try { + sr.next(); // start_element, usually throws exc her + sr.next(); // but if not, at least should do it before end element + fail("Expected an exception when trying to unbind namespace mapping for prefix 'ns': not legal in xml 1.0 documents"); + } catch (XMLStreamException e) { + // good + } + sr.close(); + } + + /** + * Unit test that verifies that the namespace with prefix 'xml' is + * always predefined without further work. + */ + public void testPredefinedXmlNs() + throws XMLStreamException + { + final String XML = ""; + + XMLStreamReader sr = getNsReader(XML, true); + assertEquals(START_ELEMENT, sr.next()); + assertEquals("xml", sr.getAttributePrefix(0)); + assertEquals("lang", sr.getAttributeLocalName(0)); + assertEquals(XMLConstants.XML_NS_URI, sr.getAttributeNamespace(0)); + assertEquals(START_ELEMENT, sr.next()); + assertEquals("xml", sr.getPrefix()); + assertEquals("a", sr.getLocalName()); + assertEquals(XMLConstants.XML_NS_URI, sr.getNamespaceURI()); + assertEquals(END_ELEMENT, sr.next()); + assertEquals(END_ELEMENT, sr.next()); + } + + /** + * This test verifies that "no namespace" is correctly reported. At + * this point definition of correct handling is not complete, so + * it'll only test cases for which there is clear consensus. + */ + public void testNoNamespace() + throws XMLStreamException + { + String XML = "xyz"; + XMLStreamReader sr = getNsReader(XML, true); + assertEquals(START_ELEMENT, sr.next()); + assertEquals(1, sr.getNamespaceCount()); + + /* 21-Jul-2006, TSa: + * URI returned for namespace declarations (different from URI + * of the element, or attributes) should be the lexical value, + * that is, for "no namespace" it should be "", not null. + */ + assertEquals("", sr.getNamespaceURI(0)); + + /* Too bad there's no consensus on what actual element URI + * should be: both null and "" have their supporters... ;-) + */ + sr.close(); + } + + /* + //////////////////////////////////////// + // Private methods, shared test code + //////////////////////////////////////// + */ + + private void checkIllegalAttributeIndexes(XMLStreamReader sr) + throws XMLStreamException + { + /* 26-Jan-2008, TSa: Javadocs/stax specs do not actually specify + * what should happen if an illegal index is given. + * So while it seems logical that we'd throw an exception, + * we can not count on that. Let's rather just check that + * we either get an exception, or empty (null or "") value; + * and if latter, just warn. + */ + try { + String str = sr.getAttributeValue(-1); + if (str != null) { + if (str.length() > 0) { + fail("Did not expect to find a non-empty value when trying to access attribute #-1, got '"+str+"'"); + } + } + warn("Did not get an exception when calling sr.getAttributeValue(-1): seems odd, but legal?"); + } catch (Exception e) { } + + int count = sr.getAttributeCount(); + try { + String str = sr.getAttributeValue(count); + if (str != null) { + if (str.length() > 0) { + fail("Did not expect to find a non-empty value when trying to access attribute #"+count+" [with element only having "+count+" attribute(s)], got '"+str+"'"); + } + } + warn("Did not get an exception when calling sr.getAttributeValue("+count+"): [with element only having "+count+" attribute(s)] seems odd, but legal?"); + } catch (Exception e) { } + } + + private void testPotentiallyInvalid(boolean nsAware, String method) + throws XMLStreamException + { + // First, check that undeclared namespace prefixes are not kosher + try { + XMLStreamReader sr = getNsReader("", nsAware); + if (sr == null) { + reportNADueToNS(method); + return; + } + + streamThrough(sr); + if (nsAware) { + fail("Was expecting an exception for content that uses undeclared namespace prefix."); + } + } catch (Exception e) { + if (!nsAware) { + fail("Was not expecting an exception for undeclared namespace when namespaces support not enabled: "+e); + } + } + + // Plus, can't redeclare default namespace + try { + XMLStreamReader sr = getNsReader("", + nsAware); + streamThrough(sr); + fail("Was expecting an exception for content that has duplicate declaration of the default namespace."); + } catch (Exception e) { + ; // both should get here + } + + // Nor other prefixes + try { + XMLStreamReader sr = getNsReader("", + nsAware); + streamThrough(sr); + fail("Was expecting an exception for content that has duplicate declaration for a prefix."); + } catch (Exception e) { + ; // both should get here + } + + /* And then, two attribute names may be equivalent if prefixes + * point to same URI; but only in namespace-aware mode + */ + try { + XMLStreamReader sr = getNsReader + ("", + nsAware); + streamThrough(sr); + if (nsAware) { + fail("Was expecting an exception for content that has duplicate attribute (even though prefixes differ, they point to the same URI)"); + } + } catch (Exception e) { + if (!nsAware) { + fail("Was NOT expecting an exception since in non-namespace mode attributes 'a:attr1' and 'b:attr1' are not equivalent: "+e); + } + } + } + + private void doTestXmlBinding(boolean nsAware, String method) + throws XMLStreamException + { + // And 'xml' can only be bound to its correct URI + { // this should be fine + XMLStreamReader sr = getNsReader("", nsAware); + if (sr == null) { + reportNADueToNS(method); + return; + } + streamThrough(sr); + } + + // But not to anything else: + try { + XMLStreamReader sr = getNsReader("", nsAware); + streamThrough(sr); + if (nsAware) { + fail("Was expecting an exception for content that tries to redeclare 'xml' to different URI."); + } + } catch (Exception e) { + if (!nsAware) { + fail("Was not expecting an exception for redeclaration of 'xml' when namespace support not enabled: "+e); + } + } + + // Also, nothing else can bind to that URI, neither explicit prefix + try { + XMLStreamReader sr = getNsReader("", nsAware); + streamThrough(sr); + if (nsAware) { + fail("Was expecting an exception for content that tries to bind prefix other than 'xml' to URI '"+XMLConstants.XML_NS_URI+"'"); + } + } catch (Exception e) { + if (!nsAware) { + fail("Was not expecting an exception for binding 'xml' URI"); + } + } + + // Nor default namespace + try { + XMLStreamReader sr = getNsReader("", nsAware); + streamThrough(sr); + if (nsAware) { + fail("Was expecting an exception for content that tries to bind the default namespace to 'xml' URI '"+XMLConstants.XML_NS_URI+"'"); + } + } catch (Exception e) { + if (!nsAware) { + fail("Was not expecting an exception for binding default namespace to 'xml' URI"); + } + } + } + + private void doTestXmlnsBinding(boolean nsAware, String method) + throws XMLStreamException + { + // Illegal to try to (re)declare 'xmlns' in any way + try { + XMLStreamReader sr = getNsReader("", nsAware); + if (sr == null) { + reportNADueToNS(method); + return; + } + streamThrough(sr); + if (nsAware) { + fail("Was expecting an exception for content that tries to redeclare 'xml' or 'xmlns' to different URI."); + } + } catch (Exception e) { + if (!nsAware) { + fail("Was not expecting an exception for redeclaration of 'xmlns' when namespace support not enabled: "+e); + } + } + + // Also, nothing else can bind to that URI, neither explicit prefix + try { + XMLStreamReader sr = getNsReader("", nsAware); + streamThrough(sr); + if (nsAware) { + fail("Was expecting an exception for content that tries to bind prefix other than 'xml' to URI '"+XMLConstants.XMLNS_ATTRIBUTE_NS_URI+"'"); + } + } catch (Exception e) { + if (!nsAware) { + fail("Was not expecting an exception for binding 'xml' URI"); + } + } + + // Nor default namespace + try { + XMLStreamReader sr = getNsReader("", nsAware); + streamThrough(sr); + if (nsAware) { + fail("Was expecting an exception for content that tries to bind the default namespace to 'xml' URI '"+XMLConstants.XMLNS_ATTRIBUTE_NS_URI+"'"); + } + } catch (Exception e) { + if (!nsAware) { + fail("Was not expecting an exception for binding default namespace to 'xml' URI"); + } + } + } + + /* + //////////////////////////////////////// + // Private methods, other + //////////////////////////////////////// + */ + + /** + * @return Stream reader constructed if initialization succeeded (all + * setting supported by the impl); null if some settings (namespace + * awareness) not supported. + */ + private XMLStreamReader getNsReader(String contents, boolean nsAware) + throws XMLStreamException + { + XMLInputFactory f = getInputFactory(); + if (!setNamespaceAware(f, nsAware)) { + return null; + } + setCoalescing(f, true); + setValidating(f, false); + return constructStreamReader(f, contents); + } +} diff -Nru libwoodstox-java-4.1.3/src/test/java/org/codehaus/stax/test/stream/TestProcInstrRead.java libwoodstox-java-5.1.0/src/test/java/org/codehaus/stax/test/stream/TestProcInstrRead.java --- libwoodstox-java-4.1.3/src/test/java/org/codehaus/stax/test/stream/TestProcInstrRead.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/org/codehaus/stax/test/stream/TestProcInstrRead.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,280 @@ +package org.codehaus.stax.test.stream; + +import javax.xml.stream.*; + +/** + * Unit test suite that tests handling of XML processing instructions (except + * for the linefeed normalization which is tested elsewhere); mostly just what + * properties is the stream reader returning when pointing to a comment. + */ +public class TestProcInstrRead + extends BaseStreamTest +{ + /** + * Method that checks properties of PROCESSING_INSTRUCTION + * returned by the stream reader are correct according to StAX specs. + */ + public void testProcInstrProperties() + throws XMLStreamException + { + /* Neither ns-awareness nor dtd-support should make any differnece, + * but let's double check them... + */ + doTestProperties(true, true); + doTestProperties(true, false); + doTestProperties(false, true); + doTestProperties(false, false); + } + + public void testSpaceHandling() + throws XMLStreamException + { + String CONTENT_TEXT = "some data "; + String CONTENT = " "+CONTENT_TEXT; + String XML = ""; + + for (int i = 0; i < 3; ++i) { + boolean ns = (i & 1) != 0; + boolean dtd = (i & 2) != 0; + XMLStreamReader sr = getReader(XML, ns, dtd); + assertTokenType(PROCESSING_INSTRUCTION, sr.next()); + assertEquals("target", sr.getPITarget()); + + String content = sr.getPIData(); + assertNotNull(content); + // Is content exactly as expected? + if (!content.equals(CONTENT_TEXT)) { + // Nope... but would it be without white space? + if (CONTENT_TEXT.trim().equals(content.trim())) { + fail("Proc. instr. white space handling not correct: expected data '" + +CONTENT_TEXT+"', got '"+content+"'"); + } + // Nah, totally wrong: + fail("Processing instruction data incorrect: expected '" + +CONTENT_TEXT+"', got '"+content+"'"); + } + } + } + + public void testInvalidProcInstr() + throws XMLStreamException + { + String XML = ""; + String XML2 = " "; + String XML3 = ""; + + for (int i = 0; i < 3; ++i) { + boolean ns = (i & 1) != 0; + boolean dtd = (i & 2) != 0; + + streamThroughFailing(getReader(XML, ns, dtd), + "invalid processing instruction target ('xml' [case-insensitive] not legal) [ns: "+ns+", dtd: "+dtd+"]"); + + streamThroughFailing(getReader(XML2, ns, dtd), + "invalid processing instruction; empty proc. instr (missing target)"); + + streamThroughFailing(getReader(XML3, ns, dtd), + "invalid processing instruction; ends with '?', not \"?>\""); + } + } + + public void testUnfinishedPI() + throws XMLStreamException + { + String XML = ""; + + for (int i = 0; i < 3; ++i) { + boolean ns = (i & 1) != 0; + streamThroughFailing(getReader(XML, ns, true), + "invalid proc. instr. (unfinished)"); + } + } + + /** + * This unit test checks that the parser does not allow split processing + * instructions; ones that start from within an entity expansion, but do + * not completely finish within entity expansion, but in the original + * input source that referenced the entity. + * Such markup is illegal according to XML specs. + */ + public void testRunawayProcInstr() + throws XMLStreamException + { + String XML = "\n" + +"]>" + + "π?>"; + + XMLStreamReader sr = getReader(XML, true, true); + + try { + // May get an exception when parsing entity declaration... ? + // (since it contains partial token) + assertTokenType(DTD, sr.next()); + assertTokenType(START_ELEMENT, sr.next()); + int type = sr.next(); + if (type != PROCESSING_INSTRUCTION) { + reportNADueToEntityExpansion("testRunawayProcInstr", type); + return; + } + type = sr.next(); + fail("Expected an exception for split/runaway processing instruction (instead got event "+tokenTypeDesc(type)+")"); + } catch (XMLStreamException sex) { + // good + } catch (RuntimeException rex) { + // some impls. throw lazy exceptions, too... + } + } + + /** + * Unit test based on a bug found in the Stax reference implementation. + */ + public void testLongerProcInstr() + throws XMLStreamException + { + String XML = "\n\n" ++"\n\n" ++"\n\n" ++"\n" ++"]>\n\n" ++"\n" ++" &eduni-errata2e;\n" + +"\n"; + + XMLStreamReader sr = getReader(XML, true, true); + + // May get an exception when parsing entity declaration... ? + // (since it contains partial token) + int type; + + while ((type = sr.next()) == SPACE) { } + assertTokenType(COMMENT, type); + while ((type = sr.next()) == SPACE) { } + assertTokenType(PROCESSING_INSTRUCTION, type); + assertEquals("xml-stylesheet", sr.getPITarget()); + while ((type = sr.next()) == SPACE) { } + assertTokenType(DTD, type); + while ((type = sr.next()) == SPACE) { } + assertTokenType(START_ELEMENT, type); + } + + /* + //////////////////////////////////////// + // Private methods, shared test code + //////////////////////////////////////// + */ + + private void doTestProperties(boolean ns, boolean dtd) + throws XMLStreamException + { + final String DATA = "data & more data (???) <>"; + XMLStreamReader sr = getReader("", ns, dtd); + + assertEquals(PROCESSING_INSTRUCTION, sr.next()); + + // Type info + assertEquals(false, sr.isStartElement()); + assertEquals(false, sr.isEndElement()); + assertEquals(false, sr.isCharacters()); + assertEquals(false, sr.isWhiteSpace()); + + // indirect type info + assertFalse("Processing instructions have no names; XMLStreamReader.hasName() should return false", sr.hasName()); + assertEquals(false, sr.hasText()); + + assertNotNull(sr.getLocation()); + if (ns) { + assertNotNull(sr.getNamespaceContext()); + } + + // And then let's check methods that should throw specific exception + for (int i = 0; i < 10; ++i) { + String method = ""; + + try { + @SuppressWarnings("unused") + Object result = null; + switch (i) { + case 0: + method = "getName"; + result = sr.getName(); + break; + case 1: + method = "getPrefix"; + result = sr.getPrefix(); + break; + case 2: + method = "getLocalName"; + result = sr.getLocalName(); + break; + case 3: + method = "getNamespaceURI"; + result = sr.getNamespaceURI(); + break; + case 4: + method = "getNamespaceCount"; + result = new Integer(sr.getNamespaceCount()); + break; + case 5: + method = "getAttributeCount"; + result = new Integer(sr.getAttributeCount()); + break; + case 6: + method = "getText"; + result = sr.getText(); + break; + case 7: + method = "getTextCharacters"; + result = sr.getTextCharacters(); + break; + case 8: + method = "getTextStart"; + result = new Integer(sr.getTextStart()); + break; + case 9: + method = "getTextLength"; + result = new Integer(sr.getTextLength()); + break; + } + fail("Expected IllegalStateException, when calling " + +method+"() for PROCESSING_INSTRUCTION"); + } catch (IllegalStateException iae) { + ; // good + } + } + + assertEquals("target", sr.getPITarget()); + + /* Now; specs are bit vague WRT white space handling between target + * and data; thus, let's just trim trailing/leading white space + */ + /* 13-Nov-2004, TSa: Actually, handling is to get rid + * of leading but not trailing white space, as per XML specs. + * StAX API is not clear, but another test will verify proper + * behaviour. + */ + assertEquals(DATA.trim(), sr.getPIData().trim()); + } + + /* + //////////////////////////////////////// + // Private methods, other + //////////////////////////////////////// + */ + + private XMLStreamReader getReader(String contents, boolean nsAware, + boolean supportDTD) + throws XMLStreamException + { + XMLInputFactory f = getInputFactory(); + setCoalescing(f, false); // shouldn't really matter + setNamespaceAware(f, nsAware); + setSupportDTD(f, supportDTD); + setValidating(f, false); + return constructStreamReader(f, contents); + } +} diff -Nru libwoodstox-java-4.1.3/src/test/java/org/codehaus/stax/test/stream/TestProperties.java libwoodstox-java-5.1.0/src/test/java/org/codehaus/stax/test/stream/TestProperties.java --- libwoodstox-java-4.1.3/src/test/java/org/codehaus/stax/test/stream/TestProperties.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/org/codehaus/stax/test/stream/TestProperties.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,50 @@ +package org.codehaus.stax.test.stream; + +import javax.xml.stream.*; + +/** + * Unit tests that verify handling of XMLInputFactory properties. + * This includes: + *

    + *
  • Property defaults as defined by Stax specs (see class javadocs for + * {@link javax.xml.stream.XMLInputFactory} + *
  • + *
+ * + * @author Tatu Saloranta + */ +public class TestProperties + extends BaseStreamTest +{ + public void testDefaultEntitySettings() + { + XMLInputFactory f = getNewInputFactory(); + assertEquals(Boolean.TRUE, f.getProperty(XMLInputFactory.IS_REPLACING_ENTITY_REFERENCES)); + Object o = f.getProperty(XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES); + if (!(o instanceof Boolean)) { + fail("Property value for XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES not of type Boolean, but "+((o == null) ? "[null]" : o.getClass().getName())); + } + } + + public void testDefaultValidationSettings() + { + XMLInputFactory f = getNewInputFactory(); + assertEquals(Boolean.FALSE, f.getProperty(XMLInputFactory.IS_VALIDATING)); + // A few impls might not support this, but it is the default... + assertEquals(Boolean.TRUE, f.getProperty(XMLInputFactory.SUPPORT_DTD)); + } + + public void testDefaultMiscSettings() + { + XMLInputFactory f = getNewInputFactory(); + + assertEquals(Boolean.TRUE, f.getProperty(XMLInputFactory.IS_NAMESPACE_AWARE)); + assertEquals(Boolean.FALSE, f.getProperty(XMLInputFactory.IS_COALESCING)); + // Shouldn't have default handlero objects either + assertNull(f.getProperty(XMLInputFactory.REPORTER)); + assertNull(f.getProperty(XMLInputFactory.RESOLVER)); + assertNull(f.getProperty(XMLInputFactory.ALLOCATOR)); + } + +} + diff -Nru libwoodstox-java-4.1.3/src/test/java/org/codehaus/stax/test/stream/TestRandomStream.java libwoodstox-java-5.1.0/src/test/java/org/codehaus/stax/test/stream/TestRandomStream.java --- libwoodstox-java-4.1.3/src/test/java/org/codehaus/stax/test/stream/TestRandomStream.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/org/codehaus/stax/test/stream/TestRandomStream.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,372 @@ +package org.codehaus.stax.test.stream; + +import java.io.*; +import java.util.Random; + +import javax.xml.stream.*; + +/** + * Unit test suite that ensures that independent of combinations of settings + * such as namespace-awareness, coalescing, automatic entity replacement, + * parsing results remain the same when they should. + */ +public class TestRandomStream + extends BaseStreamTest +{ + public void testCoalescingAutoEntity() + throws Exception + { + doTest(false, true, true); // non-ns + doTest(true, true, true); // ns-aware + } + + public void testNonCoalescingAutoEntity() + throws Exception + { + doTest(false, false, true); // non-ns + doTest(true, false, true); // ns-aware + } + + public void testCoalescingNonAutoEntity() + throws Exception + { + doTest(false, true, false); // non-ns + doTest(true, true, false); // ns-aware + } + + public void testNonCoalescingNonAutoEntity() + throws Exception + { + doTest(false, false, false); // non-ns + doTest(true, false, false); // ns-aware + } + + /* + //////////////////////////////////////// + // Private methods, common test code + //////////////////////////////////////// + */ + + private void doTest(boolean ns, boolean coalescing, boolean autoEntity) + throws Exception + { +//System.err.println("Ns: "+ns+", coal "+coalescing+" ent "+autoEntity); + // Let's generate seed from args so it's reproducible + long seed = 123457; + if (ns) { + seed ^= "ns".hashCode(); + } + if (coalescing) { + seed ^= "coalescing".hashCode(); + } + if (autoEntity) { + seed ^= "autoEntity".hashCode(); + } + Random r = new Random(seed); + + /* We can do multiple rounds, too, too get even wider coverage... + */ + final int ROUNDS = 5; + + for (int i = 0; i < ROUNDS; ++i) { + StringBuffer inputBuf = new StringBuffer(1000); + StringBuffer expOutBuf = new StringBuffer(1000); + generateData(r, inputBuf, expOutBuf, autoEntity); + String input = inputBuf.toString(); + String expOutput = expOutBuf.toString(); + + // Let's test different input methods too: + for (int j = 0; j < 3; ++j) { + XMLInputFactory f = getFactory(ns, coalescing, autoEntity); + XMLStreamReader sr; + + switch (j) { + case 0: // simple StringReader: + sr = constructStreamReader(f, input); + break; + case 1: // via InputStream and auto-detection + /* It shouldn't really contain anything outside ISO-Latin; + * however, detection may be tricky.. so let's just + * test with UTF-8, for now? + */ + { + ByteArrayInputStream bin = new ByteArrayInputStream + (input.getBytes("UTF-8")); + sr = f.createXMLStreamReader(bin); + } + break; + case 2: // explicit UTF-8 stream + { + ByteArrayInputStream bin = new ByteArrayInputStream + (input.getBytes("UTF-8")); + Reader br = new InputStreamReader(bin, "UTF-8"); + sr = f.createXMLStreamReader(br); + } + break; + default: throw new Error("Internal error"); + } + + String actual = null; + + try { + actual = runTest(sr); + } catch (Exception e) { + // For debugging uncomment: + /* + System.err.println("Error: "+e); + System.err.println("Ns: "+ns+", coalescing: "+coalescing+", auto-ent: "+autoEntity); + System.err.println("Input was '"+input+"'"); + */ + + throw e; + } + + // uncomment for debugging: + /* + if (!expOutput.equals(actual)) { + System.err.println("Input: '"+input+"'"); + System.err.println("Exp: '"+expOutput+"'"); + System.err.println("Actual: '"+actual+"'"); + } + */ + assertEquals(expOutput, actual); + } + } + } + + private String runTest(XMLStreamReader sr) + throws Exception + { + assertEquals(DTD, sr.next()); + + int type; + + while ((type = sr.next()) == SPACE) { + ; + } + assertEquals(START_ELEMENT, type); + + StringBuffer act = new StringBuffer(1000); + + do { + if (type == START_ELEMENT || type == END_ELEMENT) { + act.append('<'); + if (type == END_ELEMENT) { + act.append('/'); + } + String prefix = sr.getPrefix(); + if (prefix != null && prefix.length() > 0) { + act.append(prefix); + act.append(':'); + } + act.append(sr.getLocalName()); + act.append('>'); + } else if (type == CHARACTERS || type == SPACE || type == CDATA) { + // No quoting, doesn't have to result in legal XML + try { // note: entity expansion may fail... + act.append(getAndVerifyText(sr)); + } catch (XMLStreamException xse) { + fail("Expected succesful entity expansion, got: "+xse); + } catch (RuntimeException rex) { + /* 28-Oct-2006, TSa: since getText() may not be able + * to throw XMLStreamException, let's see if we got + * a runtime excpetion with root cause of stream exc + */ + if (rex.getCause() instanceof XMLStreamException) { + fail("Expected succesful entity expansion, got: "+rex); + } else { + throw rex; + } + } + } else if (type == COMMENT) { + act.append(""); + } else if (type == ENTITY_REFERENCE) { + act.append(sr.getText()); + } else { + fail("Unexpected event type "+type); + } + try { + type = sr.next(); + } catch (XMLStreamException xse) { + fail("Parse problem: "+xse); + } + } while (type != END_DOCUMENT); + + return act.toString(); + } + + private void generateData(Random r, StringBuffer input, + StringBuffer output, boolean autoEnt) + { + final String PREAMBLE = + "" + +"\n" + +" \n" + +" \n" + +"]>"; + + /* Ok; template will use '*' chars as placeholders, to be replaced + * by pseudo-randomly selected choices. + */ + final String TEMPLATE = + "" + + // Short one for trouble shooting: + /* + +" * Text ****\n" + */ + + // Real one for regression testing: + +" * Text ****\n" + +"** * xx\n" + +"Text ******\n" + +"*......**" + +"******" + +"***" + +"***" + +"a*b*c*d*e*f*g*h*i*j*k" + +"" + + ; + + input.append(TEMPLATE); + output.append(TEMPLATE); + + for (int i = TEMPLATE.length(); --i >= 0; ) { + char c = TEMPLATE.charAt(i); + + if (c == '*') { + replaceEntity(input, output, autoEnt, r, i); + } + } + + // Let's also insert preamble into input now + input.insert(0, PREAMBLE); + } + + private void replaceEntity(StringBuffer input, StringBuffer output, + boolean autoEnt, + Random r, int index) + { + String in, out; + + switch (Math.abs(r.nextInt()) % 5) { + case 0: // Let's use one of pre-def'd entities: + switch (Math.abs(r.nextInt()) % 5) { + case 0: + in = "&"; + out = "&"; + break; + case 1: + in = "'"; + out = "'"; + break; + case 2: + in = "<"; + out = "<"; + break; + case 3: + in = ">"; + out = ">"; + break; + case 4: + in = """; + out = "\""; + break; + default: throw new Error("Internal error!"); + } + break; + case 1: // How about some CDATA? + switch (Math.abs(r.nextInt()) % 4) { + case 0: + in = "]]>"; + out = "]] >"; + break; + case 1: + in = ""; + out = "xyz&abc"; + break; + case 2: + in = ""; + out = ""; + break; + case 3: + in = ""; + out = " "; + break; + default: throw new Error("Internal error!"); + } + break; + case 2: // Char entities? + switch (Math.abs(r.nextInt()) % 4) { + case 0: + in = "#"; + out = "#"; + break; + case 1: + in = "$"; + out = "$"; + break; + case 2: + in = "©"; // above US-Ascii, copyright symbol + out = "\u00A9"; + break; + case 3: + in = "Ä"; // Upper-case a with umlauts + out = "\u00C4"; + break; + default: throw new Error("Internal error!"); + } + break; + case 3: // Full entities + switch (Math.abs(r.nextInt()) % 3) { + case 0: + in = "&ent1;"; + out = "ent1Value"; + break; + case 1: + in = "&x;"; + out = "Y"; + break; + case 2: + in = "&both;"; + out = autoEnt ? "ent1ValueY" : "&ent1;&x;"; + break; + default: throw new Error("Internal error!"); + } + break; + + case 4: // Plain text, ISO-Latin chars: + in = out = "(\u00A9)"; // copyright symbol + break; + + default: + throw new Error("Internal error!"); + } + input.replace(index, index+1, in); + output.replace(index, index+1, out); + } + + /* + //////////////////////////////////////// + // Private methods, other + //////////////////////////////////////// + */ + + private XMLInputFactory getFactory(boolean nsAware, + boolean coalescing, boolean autoEntity) + throws XMLStreamException + { + XMLInputFactory f = getInputFactory(); + setNamespaceAware(f, nsAware); + setCoalescing(f, coalescing); + setReplaceEntities(f, autoEntity); + + setSupportDTD(f, true); + setValidating(f, false); + return f; + } +} diff -Nru libwoodstox-java-4.1.3/src/test/java/org/codehaus/stax/test/stream/TestStreaming.java libwoodstox-java-5.1.0/src/test/java/org/codehaus/stax/test/stream/TestStreaming.java --- libwoodstox-java-4.1.3/src/test/java/org/codehaus/stax/test/stream/TestStreaming.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/org/codehaus/stax/test/stream/TestStreaming.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,80 @@ +package org.codehaus.stax.test.stream; + +import java.io.*; + +import javax.xml.stream.*; + +/** + * Unit test suite that tests that the stream is really fully streaming: + * that is, it doesn't need to fill buffers completely before being + * able to return events for things for which it has already read + * text. Tests were added after reports that some implementations did + * in fact have problems with such buffering, and as a result using + * such readers on network (http, tcp) streams wasn't working as well + * as it should. + *

+ * Note: should we test Ascii or ISO-Latin, or only UTF-8 (since that's + * the only encoding XML parsers HAVE to understand)? Most parsers handle + * them all. Also; is sub-optimal behaviour (blocking too early) really + * a bug, or just sub-standard implementation? + */ +public class TestStreaming + extends BaseStreamTest +{ + public void testAscii() + throws XMLStreamException, UnsupportedEncodingException + { + testWith("US-ASCII"); + } + + public void testISOLatin() + throws XMLStreamException, UnsupportedEncodingException + { + testWith("ISO-8859-1"); + } + + public void testUTF8() + throws XMLStreamException, UnsupportedEncodingException + { + testWith("UTF-8"); + } + + /* + //////////////////////////////////////// + // Private methods, tests + //////////////////////////////////////// + */ + + private void testWith(String enc) + throws XMLStreamException, UnsupportedEncodingException + { + BlockingStream bs = getStream(enc); + XMLStreamReader sr = getReader(bs); + assertTokenType(START_ELEMENT, sr.next()); + if (bs.hasBlocked()) { + fail("Stream reader causes blocking before returning START_ELEMENT event that should be parsed before blocking"); + } + } + + /* + //////////////////////////////////////// + // Private methods, other + //////////////////////////////////////// + */ + + private BlockingStream getStream(String enc) + throws XMLStreamException, UnsupportedEncodingException + { + String contents = "Some test"; + byte[] data = contents.getBytes(enc); + return new BlockingStream(new ByteArrayInputStream(data)); + } + + private XMLStreamReader getReader(BlockingStream in) + throws XMLStreamException + { + XMLInputFactory f = getInputFactory(); + setValidating(f, false); + return f.createXMLStreamReader((InputStream) in); + } +} diff -Nru libwoodstox-java-4.1.3/src/test/java/org/codehaus/stax/test/stream/TestTextCoalescing.java libwoodstox-java-5.1.0/src/test/java/org/codehaus/stax/test/stream/TestTextCoalescing.java --- libwoodstox-java-4.1.3/src/test/java/org/codehaus/stax/test/stream/TestTextCoalescing.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/org/codehaus/stax/test/stream/TestTextCoalescing.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,158 @@ +package org.codehaus.stax.test.stream; + +import javax.xml.stream.*; + +/** + * Unit test suite that tests that the stream reader does in fact + * coalesce adjacent text/CDATA segments when told to do so. + */ +public class TestTextCoalescing + extends BaseStreamTest +{ + final static String VALID_XML = "Text /that's all!"; + + public void testCoalescing() + throws XMLStreamException + { + XMLStreamReader sr = getReader(VALID_XML, true, true); + assertTokenType(START_ELEMENT, sr.next()); + assertTokenType(CHARACTERS, sr.next()); + + String act = getAndVerifyText(sr); + String exp = "Text cdata\nin two lines!/that's all!"; + + if (!exp.equals(act)) { + failStrings("Coalescing failed", exp, act); + } + + assertTokenType(END_ELEMENT, sr.next()); + assertTokenType(END_DOCUMENT, sr.next()); + } + + /** + * Test that ensures that even when just skipping (ie not accessing + * any data), we'll still see just one event for the whole text + */ + public void testCoalescingSkipping() + throws XMLStreamException + { + XMLStreamReader sr = getReader(VALID_XML, true, true); + assertTokenType(START_ELEMENT, sr.next()); + assertTokenType(CHARACTERS, sr.next()); + assertTokenType(END_ELEMENT, sr.next()); + assertTokenType(END_DOCUMENT, sr.next()); + } + + public void testNonCoalescing() + throws XMLStreamException + { + // VALID_XML = "Text /that's all!"; + + XMLStreamReader sr = getReader(VALID_XML, true, false); + assertTokenType(START_ELEMENT, sr.next()); + + /* Can not assume that all events are returned in one call... + * so let's play it safe: + */ + sr.next(); + checkText(sr, CHARACTERS, "Text "); + int count = checkText(sr, CDATA, "cdata\nin two lines!"); + if (count < 2) { + // Can't easily check boundaries... well, could but... + fail("Expected at least two CDATA events; parser coalesced them"); + } + checkText(sr, CHARACTERS, "/that's all!"); + + assertTokenType(END_ELEMENT, sr.getEventType()); + assertTokenType(END_DOCUMENT, sr.next()); + } + + public void testNonCoalescingSkipping() + throws XMLStreamException + { + // VALID_XML = "Text /that's all!"; + + XMLStreamReader sr = getReader(VALID_XML, true, false); + assertTokenType(START_ELEMENT, sr.next()); + + assertTokenType(CHARACTERS, sr.next()); + + /* ugh. Since implementations are allowed to return CHARACTERS, + * instead of CDATA, we can only check that we get at least + * 4 segments of any type... + */ + // Now, we may get more than one CHARACTERS + int count = 1; + StringBuffer sb = new StringBuffer(); + sb.append('['); + sb.append(sr.getText()); + sb.append(']'); + int type; + + while (true) { + type = sr.next(); + if (type != CHARACTERS && type != CDATA) { + break; + } + ++count; + sb.append('['); + sb.append(sr.getText()); + sb.append(']'); + } + if (count < 4) { + fail("Expected at least 4 separate segments (CDATA/CHARACTERS), in non-coalescing mode, got "+count+" (text: "+sb+")"); + } + + assertTokenType(END_ELEMENT, type); + assertTokenType(END_DOCUMENT, sr.next()); + } + + public void testInvalidTextWithCDataEndMarker() + throws XMLStreamException + { + String XML = " ]]> "; + + streamThroughFailing(getReader(XML, true, true), + "text content that has ']]>' in it."); + } + + /* + //////////////////////////////////////// + // Private methods, other + //////////////////////////////////////// + */ + + private XMLStreamReader getReader(String contents, boolean nsAware, + boolean coalescing) + throws XMLStreamException + { + XMLInputFactory f = getInputFactory(); + setNamespaceAware(f, nsAware); + setSupportDTD(f, true); + setCoalescing(f, coalescing); + setReplaceEntities(f, true); + setValidating(f, false); + // 13-Mar-2006, TSa: Let's try to get accurate CDATA reporting... + setReportCData(f, true); + return constructStreamReader(f, contents); + } + + private int checkText(XMLStreamReader sr, int expType, String exp) + throws XMLStreamException + { + assertTokenType(expType, sr.getEventType()); + //if (expType != sr.getEventType()) System.err.println("WARN: expected "+tokenTypeDesc(expType)+", got "+tokenTypeDesc(sr.getEventType())); + StringBuffer sb = new StringBuffer(getAndVerifyText(sr)); + int count = 1; + while ((sr.next()) == expType) { + ++count; + sb.append(getAndVerifyText(sr)); + } + String act = sb.toString(); + if (!exp.equals(act)) { + failStrings("Incorrect text contents", act, exp); + } + return count; + } +} diff -Nru libwoodstox-java-4.1.3/src/test/java/org/codehaus/stax/test/stream/TestXmlDecl.java libwoodstox-java-5.1.0/src/test/java/org/codehaus/stax/test/stream/TestXmlDecl.java --- libwoodstox-java-4.1.3/src/test/java/org/codehaus/stax/test/stream/TestXmlDecl.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/org/codehaus/stax/test/stream/TestXmlDecl.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,218 @@ +package org.codehaus.stax.test.stream; + +import java.io.*; + +import javax.xml.stream.*; + +/** + * Unit test suite that tests handling of the xml declaration. + */ +public class TestXmlDecl + extends BaseStreamTest +{ + final String VALID_XML1 + = ""; + + final String VALID_XML_UTF8 + = ""; + + /** + * Method that verifies properties that should be active when + * START_DOCUMENT is the current event (ie before iterating), ie. + * right after xml declaration has been read + */ + public void testProperties() + throws XMLStreamException + { + doTestProperties(false); + doTestProperties(true); + } + + public void testValidDecl() + throws XMLStreamException, IOException + { + doTestValid(false); + doTestValid(true); + } + + public void testValidStandaloneDecls() + throws XMLStreamException, IOException + { + String XML = ""; + XMLStreamReader sr = getReader(XML, true); + + assertEquals("1.0", sr.getVersion()); + assertTrue("XMLStreamReader.standalonSet() should be true", sr.standaloneSet()); + assertTrue("XMLStreamReader.isStandalone() should be true", sr.isStandalone()); + + + XML = ""; + sr = getReader(XML, true); + + assertEquals("1.0", sr.getVersion()); + assertTrue("XMLStreamReader.standalonSet() should be true", sr.standaloneSet()); + assertFalse("XMLStreamReader.isStandalone() should be false", sr.isStandalone()); + + // And then all of it: + + XML = ""; + sr = getReader(XML, true); + + assertEquals("1.0", sr.getVersion()); + assertTrue("XMLStreamReader.standalonSet() should be true", sr.standaloneSet()); + assertTrue("XMLStreamReader.isStandalone() should be true", sr.isStandalone()); + assertEquals("US-ASCII", sr.getCharacterEncodingScheme()); + } + + public void testInvalidDecl() + throws XMLStreamException + { + doTestInvalid(false); + doTestInvalid(true); + } + + /* + //////////////////////////////////////// + // Private methods, shared test code + //////////////////////////////////////// + */ + + private void doTestProperties(boolean nsAware) + throws XMLStreamException + { + XMLStreamReader sr = getReader(VALID_XML1, nsAware); + assertEquals(START_DOCUMENT, sr.getEventType()); + // Type info + assertEquals(false, sr.isStartElement()); + assertEquals(false, sr.isEndElement()); + assertEquals(false, sr.isCharacters()); + assertEquals(false, sr.isWhiteSpace()); + + // indirect type info + assertEquals(false, sr.hasName()); + assertEquals(false, sr.hasText()); + + /* Now... how about location and namespace context? Are they really + * guaranteed to exist at this point? Since API doesn't indicate + * otherwise, let's assume this is the case, for now. + */ + assertNotNull(sr.getLocation()); + if (nsAware) { + assertNotNull(sr.getNamespaceContext()); + } + + // And then let's check methods that should throw specific exception + for (int i = 0; i < 8; ++i) { + String method = ""; + + try { + @SuppressWarnings("unused") + Object result = null; + switch (i) { + case 0: + method = "getName"; + result = sr.getName(); + break; + case 1: + method = "getPrefix"; + result = sr.getPrefix(); + break; + case 2: + method = "getLocalName"; + result = sr.getLocalName(); + break; + case 3: + method = "getNamespaceURI"; + result = sr.getNamespaceURI(); + break; + case 4: + method = "getNamespaceCount"; + result = new Integer(sr.getNamespaceCount()); + break; + case 5: + method = "getAttributeCount"; + result = new Integer(sr.getAttributeCount()); + break; + case 6: + method = "getPITarget"; + result = sr.getPITarget(); + break; + case 7: + method = "getPIData"; + result = sr.getPIData(); + break; + } + fail("Expected IllegalStateException, when calling " + +method+"() for XML declaration (START_DOCUMENT)"); + } catch (IllegalStateException iae) { + ; // good + } + } + } + + private void doTestValid(boolean nsAware) + throws XMLStreamException, IOException + { + XMLStreamReader sr = getReader(VALID_XML1, nsAware); + + /* First, let's ensure that version is ok, and whether + * stand-alone pseudo-attr was set: + */ + assertEquals("1.0", sr.getVersion()); + assertFalse(sr.standaloneSet()); + + // Then, encoding passed via factory method: + sr = getUTF8StreamReader(VALID_XML1, nsAware); + assertEquals("UTF-8", sr.getEncoding()); + + // Then, automatic detection of encoding: + sr = getReader(VALID_XML_UTF8, nsAware); + assertEquals("1.0", sr.getVersion()); + assertEquals("UTF-8", sr.getCharacterEncodingScheme()); + } + + private void doTestInvalid(boolean nsAware) + throws XMLStreamException + { + String XML = ""; + streamThroughFailing(getFactory(nsAware), XML, + "invalid XML declaration (missing version)"); + + XML = ""; + streamThroughFailing(getFactory(nsAware), XML, + "invalid XML declaration (mismatch of quotes)"); + } + + /* + //////////////////////////////////////// + // Private methods, other + //////////////////////////////////////// + */ + + private XMLInputFactory getFactory(boolean nsAware) + throws XMLStreamException + { + XMLInputFactory f = getInputFactory(); + setCoalescing(f, false); // shouldn't matter + setNamespaceAware(f, nsAware); + setValidating(f, false); + return f; + } + + private XMLStreamReader getReader(String contents, boolean nsAware) + throws XMLStreamException + { + return constructStreamReader(getFactory(nsAware), contents); + } + + private XMLStreamReader getUTF8StreamReader(String contents, boolean nsAware) + throws XMLStreamException, UnsupportedEncodingException + { + XMLInputFactory f = getInputFactory(); + setCoalescing(f, false); // shouldn't matter + setNamespaceAware(f, nsAware); + setValidating(f, false); + InputStream in = new ByteArrayInputStream(contents.getBytes("UTF-8")); + return f.createXMLStreamReader(in, "UTF-8"); + } +} diff -Nru libwoodstox-java-4.1.3/src/test/java/org/codehaus/stax/test/vstream/BaseVStreamTest.java libwoodstox-java-5.1.0/src/test/java/org/codehaus/stax/test/vstream/BaseVStreamTest.java --- libwoodstox-java-4.1.3/src/test/java/org/codehaus/stax/test/vstream/BaseVStreamTest.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/org/codehaus/stax/test/vstream/BaseVStreamTest.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,42 @@ +package org.codehaus.stax.test.vstream; + +import javax.xml.stream.XMLInputFactory; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; + +import org.codehaus.stax.test.stream.BaseStreamTest; + +/** + * Base class for all StaxTest unit tests that test validation-dependant + * parts of stream (cursor) API functionality. + * + * @author Tatu Saloranta + */ +abstract class BaseVStreamTest + extends BaseStreamTest +{ + protected XMLStreamReader getValidatingReader(String contents) + throws XMLStreamException + { + return getValidatingReader(contents, true); + } + + protected XMLStreamReader getValidatingReader(String contents, boolean nsAware) + throws XMLStreamException + { + XMLInputFactory f = getValidatingFactory(nsAware); + return constructStreamReader(f, contents); + } + + protected XMLInputFactory getValidatingFactory(boolean nsAware) + throws XMLStreamException + { + XMLInputFactory f = getInputFactory(); + setCoalescing(f, false); // shouldn't really matter + setNamespaceAware(f, nsAware); + setSupportDTD(f, true); + // Let's make sure DTD is really parsed? + setValidating(f, true); + return f; + } +} diff -Nru libwoodstox-java-4.1.3/src/test/java/org/codehaus/stax/test/vstream/TestAttrRead.java libwoodstox-java-5.1.0/src/test/java/org/codehaus/stax/test/vstream/TestAttrRead.java --- libwoodstox-java-4.1.3/src/test/java/org/codehaus/stax/test/vstream/TestAttrRead.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/org/codehaus/stax/test/vstream/TestAttrRead.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,233 @@ +package org.codehaus.stax.test.vstream; + +import javax.xml.stream.*; + +/** + * Unit test suite that tests basic handling of attributes; aspects + * that do not depend on actual concrete type. + */ +public class TestAttrRead + extends BaseVStreamTest +{ + /* + /////////////////////////////////////////////////////////// + // Attribute declaration tests: + /////////////////////////////////////////////////////////// + */ + + /** + * Simple tests for generic valid attribute declarations; using + * some constructs that can be warned about, but that are not + * erroneous. + */ + public void testValidAttrDecl() + throws XMLStreamException + { + /* First; declaring attributes for non-declared elements is + * not an error + */ + String XML = "\n" + +"\n" + +"]>\n"; + streamThrough(getValidatingReader(XML, true)); + + /* Then, declaring same attribute more than once is not an + * error; first one is binding (note: should test that this + * indeed happens, via attribute property inspection?) + */ + XML = "\n" + +"\n" + +"\n" + +"\n" + +"]>\n"; + streamThrough(getValidatingReader(XML, true)); + } + + /** + * Unit test that verifies that the attribute type declaration information + * is properly parsed and accessible via stream reader. + */ + public void testAttributeTypes() + throws XMLStreamException + { + String XML = "\n" + +"\n" + +"\n" + +"\n" + +"\n" + +"]>" + +""; + /* Could/should extend to cover all types... but this should be + * enough to at least determined reader does pass through the + * type info (instead of always returning CDATA) + */ + XMLStreamReader sr = getValidatingReader(XML, true); + + assertTokenType(DTD, sr.next()); + assertTokenType(START_ELEMENT, sr.next()); + + assertEquals(4, sr.getAttributeCount()); + for (int i = 0; i < 4; ++i) { + String ln = sr.getAttributeLocalName(i); + String type = sr.getAttributeType(i); + String expType = ln.toUpperCase(); + assertNotNull("Attribute type should never be null; CDATA should be returned if information not known/available"); + assertEquals("Incorrect attribute type for attribute '"+ln+"'", + expType, type); + } + assertTokenType(END_ELEMENT, sr.next()); + } + + public void testValidRequiredAttr() + throws XMLStreamException + { + // this should be valid: + String XML = "\n" + +"\n" + +"]>"; + XMLStreamReader sr = getValidatingReader(XML, true); + assertTokenType(DTD, sr.next()); + assertTokenType(START_ELEMENT, sr.next()); + + assertEquals(1, sr.getAttributeCount()); + assertEquals("attr", sr.getAttributeLocalName(0)); + assertEquals("value", sr.getAttributeValue(0)); + } + + public void testInvalidRequiredAttr() + throws XMLStreamException + { + // Invalid as it's missing the required attribute + String XML = "\n" + +"\n" + +"]>\n"; + streamThroughFailing(getValidatingReader(XML, true), + "Missing required attribute value"); + } + + public void testOkFixedAttr() + throws XMLStreamException + { + // Ok to omit altogether + String XML = "\n" + +"\n" + +"]>"; + // But if so, should get the default value + XMLStreamReader sr = getValidatingReader(XML, true); + assertTokenType(DTD, sr.next()); + assertTokenType(START_ELEMENT, sr.next()); + assertEquals("Should have 1 attribute; 'elem' had #FIXED default value", 1, sr.getAttributeCount()); + assertEquals("attr", sr.getAttributeLocalName(0)); + assertEquals("fixed", sr.getAttributeValue(0)); + assertTokenType(END_ELEMENT, sr.next()); + sr.close(); + + // Or to use fixed value + XML = "\n" + +"\n" + +"]>"; + sr = getValidatingReader(XML, true); + assertTokenType(DTD, sr.next()); + assertTokenType(START_ELEMENT, sr.next()); + assertEquals(1, sr.getAttributeCount()); + assertEquals("attr", sr.getAttributeLocalName(0)); + assertEquals("fixed", sr.getAttributeValue(0)); + assertTokenType(END_ELEMENT, sr.next()); + } + + public void testInvalidFixedAttr() + throws XMLStreamException + { + // Not ok to have any other value, either completely different + String XML = "\n" + +"\n" + +"]>\n"; + streamThroughFailing(getValidatingReader(XML), + "fixed attribute value not matching declaration"); + + // Or one with extra white space (CDATA won't get fully normalized) + XML = "\n" + +"\n" + +"]>\n"; + streamThroughFailing(getValidatingReader(XML), + "fixed attribute value not matching declaration"); + } + + /** + * Unit test that verifies that the default attribute values are properly + * used on validating mode. + */ + public void testDefaultAttr() + throws XMLStreamException + { + // Let's verify we get default value + String XML = "\n" + +"\n" + +"]>"; + XMLStreamReader sr = getValidatingReader(XML, true); + assertTokenType(DTD, sr.next()); + assertTokenType(START_ELEMENT, sr.next()); + + assertEquals(1, sr.getAttributeCount()); + assertEquals("attr", sr.getAttributeLocalName(0)); + assertEquals("default", sr.getAttributeValue(0)); + } + + /** + * Test for proper handling for multiple attribute declarations for + * a single attribute. This is legal, although discouraged (ie. parser + * can issue a non-fatal warning): but if used, the first definition + * should stick. Let's test for both default values and types. + */ + public void testMultipleDeclForSingleAttr() + throws XMLStreamException + { + // Let's verify we get the right default value + String XML = "\n" + +"\n" + +"\n" + +"]>"; + XMLStreamReader sr = getValidatingReader(XML, true); + assertTokenType(DTD, sr.next()); + assertTokenType(START_ELEMENT, sr.next()); + assertEquals(1, sr.getAttributeCount()); + assertEquals("attr", sr.getAttributeLocalName(0)); + assertEquals("val1", sr.getAttributeValue(0)); + + // And then let's test that the type is correct as well + XML = "\n" + +"\n" + +"\n" + +"]>"; + sr = getValidatingReader(XML, true); + assertTokenType(DTD, sr.next()); + assertTokenType(START_ELEMENT, sr.next()); + assertEquals(1, sr.getAttributeCount()); + assertEquals("attr", sr.getAttributeLocalName(0)); + assertEquals("valX", sr.getAttributeValue(0)); + assertEquals("NMTOKEN", sr.getAttributeType(0)); + } + + /* + //////////////////////////////////////// + // Private methods + //////////////////////////////////////// + */ +} diff -Nru libwoodstox-java-4.1.3/src/test/java/org/codehaus/stax/test/vstream/TestAttrTypes.java libwoodstox-java-5.1.0/src/test/java/org/codehaus/stax/test/vstream/TestAttrTypes.java --- libwoodstox-java-4.1.3/src/test/java/org/codehaus/stax/test/vstream/TestAttrTypes.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/org/codehaus/stax/test/vstream/TestAttrTypes.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,78 @@ +package org.codehaus.stax.test.vstream; + +import java.util.HashMap; + +import javax.xml.stream.*; + +/** + * Unit test suite that tests that attribute type information returned + * for all recognized types is as expected + */ +public class TestAttrTypes + extends BaseVStreamTest +{ + public void testAttrTypes() + throws XMLStreamException + { + // Let's verify we get default value + String XML = "\n" + +"\n" + +"]>" + +""; + XMLStreamReader sr = getValidatingReader(XML, true); + assertTokenType(DTD, sr.next()); + assertTokenType(START_ELEMENT, sr.next()); + int count = sr.getAttributeCount(); + assertEquals(7, count); + + HashMap seen = new HashMap(); + for (int i = 0; i < count; ++i) { + String name = sr.getAttributeLocalName(i); + String value = sr.getAttributeValue(i); + String old = (String) seen.put(name, value); + if (old != null) { + fail("Duplicate attribute '"+name+"': previous value: '"+value+"'"); + } + String type = sr.getAttributeType(i); + if (name.equals("attrCData")) { + assertEquals("CDATA", type); + } else if (name.equals("attrId")) { + assertEquals("ID", type); + } else if (name.equals("attrIdref")) { + assertEquals("IDREF", type); + } else if (name.equals("attrIdrefs")) { + assertEquals("IDREFS", type); + } else if (name.equals("attrEnum")) { + /* 25-Apr-2005, TSa: Not quite sure what would be the + * "official" name for the enumerated type? + */ + assertEquals("ENUMERATED", type); + } else if (name.equals("attrName")) { + assertEquals("NMTOKEN", type); + } else if (name.equals("attrNames")) { + assertEquals("NMTOKENS", type); + } else { + fail("Unexpected attribute '"+name+"'"); + } + } + } +} diff -Nru libwoodstox-java-4.1.3/src/test/java/org/codehaus/stax/test/vstream/TestDTDElemRead.java libwoodstox-java-5.1.0/src/test/java/org/codehaus/stax/test/vstream/TestDTDElemRead.java --- libwoodstox-java-4.1.3/src/test/java/org/codehaus/stax/test/vstream/TestDTDElemRead.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/org/codehaus/stax/test/vstream/TestDTDElemRead.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,108 @@ +package org.codehaus.stax.test.vstream; + +import javax.xml.stream.*; + +/** + * Unit test suite that tests handling of DTD element declarations. + */ +public class TestDTDElemRead + extends BaseVStreamTest +{ + /* + /////////////////////////////////////////////////////////// + // Element declaration tests: + /////////////////////////////////////////////////////////// + */ + + public void testValidElementDecl() + throws XMLStreamException + { + /* Following should be ok; it is not an error to refer to + * undeclared elements... although it is to encounter such + * undeclared elements in content. + */ + String XML = "\n" + +"]>\n"; + streamThrough(getVReader(XML)); + } + + public void testInvalidElementDecl() + throws XMLStreamException + { + /* Then let's make sure that duplicate element declarations + * are caught (as they are errors): + */ + String XML = "\n" + +"\n" + +"\n" + +"]>\n"; + try { + streamThrough(getVReader(XML)); + fail("Expected an exception for duplicate ELEMENT declaration."); + } catch (XMLStreamException ex) { // good + } catch (RuntimeException ex2) { // ok + } catch (Throwable t) { // not so good + fail("Expected an XMLStreamException or RuntimeException for duplicate ELEMENT declaration, not: "+t); + } + } + + /** + * Let's ensure basic simple notation declarations are parsed + * succesfully. + */ + public void testValidNotationDecl() + throws XMLStreamException + { + // Will need a simple content model, too, since we are validating... + String XML = "\n" + +"\n" + +"\n" + +"]>"; + streamThrough(getVReader(XML)); + } + + /** + * This unit test checks that there are no duplicate notation declarations + */ + public void testInvalidDupNotationDecl() + throws XMLStreamException + { + /* Then let's make sure that duplicate element declarations + * are caught (as they are errors): + */ + String XML = "\n" + +"\n" + +"\n" + +"]>"; + try { + streamThrough(getVReader(XML)); + fail("Expected an exception for duplicate NOTATION declaration."); + } catch (XMLStreamException ex) { // good + } catch (RuntimeException ex2) { // ok + } catch (Throwable t) { // not so good + fail("Expected an XMLStreamException or RuntimeException for duplicate NOTATION declaration, not: "+t); + } + } + + /* + //////////////////////////////////////// + // Private methods + //////////////////////////////////////// + */ + + private XMLStreamReader getVReader(String contents) + throws XMLStreamException + { + XMLInputFactory f = getInputFactory(); + setCoalescing(f, false); // shouldn't really matter + //setNamespaceAware(f, nsAware); + setSupportDTD(f, true); + // Let's make sure DTD is really parsed? + setValidating(f, true); + return constructStreamReader(f, contents); + } +} diff -Nru libwoodstox-java-4.1.3/src/test/java/org/codehaus/stax/test/vstream/TestEntityAttrRead.java libwoodstox-java-5.1.0/src/test/java/org/codehaus/stax/test/vstream/TestEntityAttrRead.java --- libwoodstox-java-4.1.3/src/test/java/org/codehaus/stax/test/vstream/TestEntityAttrRead.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/org/codehaus/stax/test/vstream/TestEntityAttrRead.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,200 @@ +package org.codehaus.stax.test.vstream; + +import javax.xml.stream.*; + +/** + * Unit test suite that tests handling of attributes that are declared + * by DTD to be of type NOTATION. + * + * @author Tatu Saloranta + */ +public class TestEntityAttrRead + extends BaseVStreamTest +{ + /* + /////////////////////////////////////// + // Test cases + /////////////////////////////////////// + */ + + public void testValidEntityAttrDecl() + throws XMLStreamException + { + // Following should be ok; notations have been declared ok + String XML = "\n" + +"\n" + +"\n" + +"\n" + +"]>\n"; + streamThrough(getValidatingReader(XML)); + + // Likewise for default values + XML = "\n" + +"\n" + +"\n" + +"\n" + +"]>\n"; + streamThrough(getValidatingReader(XML)); + } + + public void testValidUnorderedEntityAttrDecl() + throws XMLStreamException + { + // Following should be ok even though ordering is reversed + String XML = "\n" + +"\n" + +"\n" + +"\n" + +"]>\n"; + try { + streamThrough(getValidatingReader(XML)); + } catch (XMLStreamException e) { + fail("Entity declaration order should not matter, but failed due to: "+e.getMessage()); + } + } + + public void testValidEntitiesAttrDecl() + throws XMLStreamException + { + // Following should be ok; notations have been declared ok + String XML = "\n" + +"\n" + +"\n" + +"\n" + +"]>\n"; + streamThrough(getValidatingReader(XML)); + + // and for default values + XML = "\n" + +"\n" + +"\n" + +"\n" + +"\n" + +"\n" + +"\n" + +"]>\n"; + streamThrough(getValidatingReader(XML)); + } + + public void testInvalidEntityAttrDecl() + throws XMLStreamException + { + // First, let's check that undeclared notation throws an exception + String XML = "\n" + +"\n" + +"\n" + +"\n" + +"]>\n"; + streamThroughFailing(getValidatingReader(XML), + "undeclared notation for ENTITY attribute"); + + // Similarly, undeclared entity via default value + XML = "\n" + +"\n" + +"\n" + +"\n" + +"]>\n"; + streamThroughFailing(getValidatingReader(XML), + "undeclared entity for ENTITY default value"); + } + + public void testInvalidEntitiesAttrDecl() + throws XMLStreamException + { + // First, let's check that undeclared notation throws an exception + String XML = "\n" + +"\n" + +"\n" + +"\n" + +"]>\n"; + streamThroughFailing(getValidatingReader(XML), + "undeclared notation for ENTITIES attribute"); + + // Similarly, undeclared entity via default value + XML = "\n" + +"\n" + +"\n" + +"\n" + +"]>\n"; + streamThroughFailing(getValidatingReader(XML), + "undeclared entity for ENTITIES default value"); + + XML = "\n" + +"\n" + +"\n" + +"\n" + +"]>\n"; + streamThroughFailing(getValidatingReader(XML), + "undeclared entity for ENTITIES default value"); + } + + public void testValidEntityAttrUse() + throws XMLStreamException + { + // Following should be ok; notations have been declared ok + String XML = "\n" + +"\n" + +"\n" + +"\n" + +"\n" + +"\n" + +"]>"; + + XMLStreamReader sr = getValidatingReader(XML); + // Let's ensure white space normalization too: + assertTokenType(DTD, sr.next()); + assertTokenType(START_ELEMENT, sr.next()); + assertEquals(1, sr.getAttributeCount()); + assertEquals("unpEnt2", sr.getAttributeValue(0)); + } + + public void testValidEntitiesAttrUse() + throws XMLStreamException + { + // Following should be ok; notations have been declared ok + String XML = "\n" + +"\n" + +"\n" + +"\n" + +"\n" + +"\n" + +"\n" + +"\n" + +"]>"; + streamThrough(getValidatingReader(XML)); + + XMLStreamReader sr = getValidatingReader(XML); + // Let's ensure white space normalization too: + assertTokenType(DTD, sr.next()); + assertTokenType(START_ELEMENT, sr.next()); + assertEquals(1, sr.getAttributeCount()); + assertEquals("unpEnt2 unpEnt3 unpEnt1", sr.getAttributeValue(0)); + } + + /* + public void testInvalidEntityAttrUse() + throws XMLStreamException + { + } + */ + + /* + public void testInvalidEntitiesAttrUse() + throws XMLStreamException + { + } + */ + +} diff -Nru libwoodstox-java-4.1.3/src/test/java/org/codehaus/stax/test/vstream/TestEnumAttrRead.java libwoodstox-java-5.1.0/src/test/java/org/codehaus/stax/test/vstream/TestEnumAttrRead.java --- libwoodstox-java-4.1.3/src/test/java/org/codehaus/stax/test/vstream/TestEnumAttrRead.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/org/codehaus/stax/test/vstream/TestEnumAttrRead.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,119 @@ +package org.codehaus.stax.test.vstream; + +import javax.xml.stream.*; + +/** + * Unit test suite that tests handling of attributes that are declared + * by DTD to be of type NOTATION. + */ +public class TestEnumAttrRead + extends BaseVStreamTest +{ + public void testValidAttrDecl() + throws XMLStreamException + { + // Ok, just a simple declaration... + String XML = "\n" + +"\n" + +"]>\n"; + streamThrough(getValidatingReader(XML, true)); + } + + + public void testValidAttrDecl2() + throws XMLStreamException + { + /* Following should be ok, only problematic if DTD parser is + * either trying to match SGML comments, or otherwise unhappy + * about hyphen starting an NMTOKEN. + */ + String XML = "\n" + +"\n" + +"]>\n"; + streamThrough(getReader(XML)); + } + + public void testInvalidAttrDecl() + throws XMLStreamException + { + // Duplicates are not allowed + String XML = "\n" + +"\n" + +"]>\n"; + streamThroughFailing(getValidatingReader(XML, true), + "duplicate enumeration in attribute declaration"); + } + + public void testValidAttrUse() + throws XMLStreamException + { + // Ok, just a simple declaration... + String XML = "\n" + +"\n" + +"]>"; + + XMLStreamReader sr = getValidatingReader(XML, true); + assertTokenType(DTD, sr.next()); + assertTokenType(START_ELEMENT, sr.next()); + + assertEquals(1, sr.getAttributeCount()); + assertEquals("attr2", sr.getAttributeLocalName(0)); + assertEquals("enum2", sr.getAttributeValue(0)); + } + + /** + * Unit test that verifies that values of attributes of type ID + * will get properly normalized. + */ + public void testEnumAttrNormalization() + throws XMLStreamException + { + String XML = "\n" + +"\n" + +"]>" + +"" + +"" + +"" + +""; + ; + XMLStreamReader sr = getValidatingReader(XML); + assertTokenType(DTD, sr.next()); + assertTokenType(START_ELEMENT, sr.next()); + assertEquals(1, sr.getAttributeCount()); + assertEquals("enum2", sr.getAttributeValue(0)); + assertTokenType(START_ELEMENT, sr.next()); + assertEquals(1, sr.getAttributeCount()); + assertEquals("enum", sr.getAttributeValue(0)); + assertTokenType(END_ELEMENT, sr.next()); + assertTokenType(START_ELEMENT, sr.next()); + assertEquals(1, sr.getAttributeCount()); + assertEquals("last", sr.getAttributeValue(0)); + assertTokenType(END_ELEMENT, sr.next()); + assertTokenType(END_ELEMENT, sr.next()); + } + + /* + //////////////////////////////////////// + // Private methods + //////////////////////////////////////// + */ + + private XMLStreamReader getReader(String contents) + throws XMLStreamException + { + XMLInputFactory f = getInputFactory(); + setCoalescing(f, false); // shouldn't really matter + //setNamespaceAware(f, nsAware); + setSupportDTD(f, true); + // Let's make sure DTD is really parsed? + setValidating(f, true); + return constructStreamReader(f, contents); + } +} diff -Nru libwoodstox-java-4.1.3/src/test/java/org/codehaus/stax/test/vstream/TestExternalSubset.java libwoodstox-java-5.1.0/src/test/java/org/codehaus/stax/test/vstream/TestExternalSubset.java --- libwoodstox-java-4.1.3/src/test/java/org/codehaus/stax/test/vstream/TestExternalSubset.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/org/codehaus/stax/test/vstream/TestExternalSubset.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,80 @@ +package org.codehaus.stax.test.vstream; + +import javax.xml.stream.*; + +import org.codehaus.stax.test.SimpleResolver; + +/** + * Unit test suite that verifies that external subsets can be used, and + * also tests some of features only legal in there (include/exclude, + * parameter entities within declarations) + * + * @author Tatu Saloranta + */ +public class TestExternalSubset + extends BaseVStreamTest +{ + public void testSimpleValidExternalSubset() + throws XMLStreamException + { + String XML = "" + +"text"; +// String EXT_ENTITY_VALUE = "just testing"; + String EXT_SUBSET = + "\n" + +""; + + XMLStreamReader sr = getReader(XML, true, + new SimpleResolver(EXT_SUBSET)); + assertTokenType(DTD, sr.next()); + assertTokenType(START_ELEMENT, sr.next()); + assertEquals("root", sr.getLocalName()); + assertTokenType(CHARACTERS, sr.next()); + assertEquals("text", getAndVerifyText(sr)); + assertTokenType(END_ELEMENT, sr.next()); + sr.close(); + } + + public void testEntityInExternalSubset() + throws XMLStreamException + { + String XML = "" + +"&extEnt;"; + String EXT_ENTITY_VALUE = "just testing"; + String EXT_SUBSET = + "\n" + +"\n"; + + XMLStreamReader sr = getReader(XML, true, + new SimpleResolver(EXT_SUBSET)); + assertTokenType(DTD, sr.next()); + assertTokenType(START_ELEMENT, sr.next()); + assertEquals("root", sr.getLocalName()); + assertTokenType(CHARACTERS, sr.next()); + assertEquals(EXT_ENTITY_VALUE, getAndVerifyText(sr)); + assertTokenType(END_ELEMENT, sr.next()); + sr.close(); + } + + /* + //////////////////////////////////////// + // Private methods, other + //////////////////////////////////////// + */ + + private XMLStreamReader getReader(String contents, boolean nsAware, + XMLResolver resolver) + throws XMLStreamException + { + XMLInputFactory f = getInputFactory(); + setCoalescing(f, false); // shouldn't really matter + setNamespaceAware(f, nsAware); + setSupportDTD(f, true); + setValidating(f, true); + // This shouldn't be required but let's play it safe: + setSupportExternalEntities(f, true); + setResolver(f, resolver); + return constructStreamReader(f, contents); + } +} + diff -Nru libwoodstox-java-4.1.3/src/test/java/org/codehaus/stax/test/vstream/TestIdAttrRead.java libwoodstox-java-5.1.0/src/test/java/org/codehaus/stax/test/vstream/TestIdAttrRead.java --- libwoodstox-java-4.1.3/src/test/java/org/codehaus/stax/test/vstream/TestIdAttrRead.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/org/codehaus/stax/test/vstream/TestIdAttrRead.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,224 @@ +package org.codehaus.stax.test.vstream; + +import javax.xml.stream.*; + +/** + * Unit test suite that tests handling of attributes that are declared + * by DTD to be of type ID, IDREF or IDREFS; such information is only + * guranteed to be available in validation mode. + */ +public class TestIdAttrRead + extends BaseVStreamTest +{ + /** + * Test case that verifies behaviour of valid ID/IDREF/IDREF + * attribute declarations. + */ + public void testValidIdAttrDecl() + throws XMLStreamException + { + // Following should be ok + String XML = "\n" + +"\n" + +"\n" + +"]>\n"; + streamThrough(getValidatingReader(XML)); + } + + /** + * Test case that verifies behaviour of invalid ID/IDREF/IDREF + * attribute declarations. + */ + public void testInvalidIdAttrDecl() + throws XMLStreamException + { + /* First, let's check couple of invalid id attr declarations + */ + + // Can not have default value for id attr + String XML = "\n" + +"\n" + +"]>\n"; + XMLStreamReader sr = getValidatingReader(XML); + streamThroughFailing(sr, "invalid attribute id (default value not allowed)"); + + // Nor require fixed value + sr = getValidatingReader("\n" + +"\n" + +"]>\n"); + streamThroughFailing(sr, "invalid id attribute (fixed value not allowed)"); + + // Only one attr id per element + sr = getValidatingReader("\n" + +"\n" + +"]>\n"); + streamThroughFailing(sr, "more than one attribute id per element"); + } + + public void testInvalidIdRefAttrDecl() + throws XMLStreamException + { + // IDREF default value needs to be valid id + XMLStreamReader sr = getValidatingReader("\n" + +"\n" + +"]>\n"); + streamThroughFailing(sr, "invalid IDREF default value ('#' not allowed)"); + sr = getValidatingReader("\n" + +"\n" + +"]>\n"); + streamThroughFailing(sr, "invalid (missing) IDREF default value"); + + // IDREFS default value needs to be non-empty set of valid ids + sr = getValidatingReader("\n" + +"\n" + +"]>\n"); + streamThroughFailing(sr, "invalid IDREFS default value ('?' not allowed)"); + sr = getValidatingReader("\n" + +"\n" + +"]>\n"); + streamThroughFailing(sr, "invalid (missing) IDREFS default value"); + } + + public void testValidIdAttrUse() + throws XMLStreamException + { + // Following should be ok; all ids are defined + String XML = "\n" + +"\n" + +"\n" + +"]>\n "; + streamThrough(getValidatingReader(XML)); + } + + public void testInvalidIdAttrUse() + throws XMLStreamException + { + // Error: undefined id 'someId' + String XML = "\n" + +"\n" + +"\n" + +"]>\n"; + streamThroughFailing(getValidatingReader(XML), + "undefined id reference for 'someId'"); + + // Error: empty idref value + XML = "\n" + +"\n" + +"\n" + +"]>\n"; + streamThroughFailing(getValidatingReader(XML), + "empty IDREF value"); + } + + public void testValidIdAttrsUse() + throws XMLStreamException + { + // Following should be ok; all ids are defined + String XML = "\n" + +"\n" + +"\n" + +"]>\n\n" + +"\n" + +""; + streamThrough(getValidatingReader(XML)); + } + + public void testInvalidIdAttrsUse() + throws XMLStreamException + { + // Error: undefined id 'someId' + String XML = "\n" + +"\n" + +"\n" + +"]>\n"; + streamThroughFailing(getValidatingReader(XML), + "undefined id reference for 'someId'"); + + // Error: empty idrefs value + XML = "\n" + +"\n" + +"\n" + +"]>\n"; + streamThroughFailing(getValidatingReader(XML), + "empty IDREFS value"); + } + + /** + * Unit test that verifies that values of attributes of type ID + * will get properly normalized. + */ + public void testIdAttrNormalization() + throws XMLStreamException + { + String XML = "\n" + +"\n" + +"\n" + +"]>" + +"" + +"" + +""; + ; + XMLStreamReader sr = getValidatingReader(XML); + assertTokenType(DTD, sr.next()); + assertTokenType(START_ELEMENT, sr.next()); + assertEquals(1, sr.getAttributeCount()); + assertEquals("someId", sr.getAttributeValue(0)); + assertTokenType(START_ELEMENT, sr.next()); + assertEquals(1, sr.getAttributeCount()); + assertEquals("otherId", sr.getAttributeValue(0)); + assertTokenType(END_ELEMENT, sr.next()); + assertTokenType(END_ELEMENT, sr.next()); + } + + public void testIdRefAttrNormalization() + throws XMLStreamException + { + String XML = "\n" + +"\n" + +"\n" + +"\n" + +"]>" + +"" + +"" + +"" + +""; + ; + + XMLStreamReader sr = getValidatingReader(XML); + assertTokenType(DTD, sr.next()); + assertTokenType(START_ELEMENT, sr.next()); + assertTokenType(START_ELEMENT, sr.next()); + assertEquals(2, sr.getAttributeCount()); + assertEquals("id2", sr.getAttributeValue(0)); + assertEquals("someId", sr.getAttributeValue(1)); + assertTokenType(END_ELEMENT, sr.next()); + assertTokenType(START_ELEMENT, sr.next()); + assertEquals(1, sr.getAttributeCount()); + assertEquals("id2 someId", sr.getAttributeValue(0)); + assertTokenType(END_ELEMENT, sr.next()); + assertTokenType(END_ELEMENT, sr.next()); + } + + /* + //////////////////////////////////////// + // Private methods + //////////////////////////////////////// + */ +} diff -Nru libwoodstox-java-4.1.3/src/test/java/org/codehaus/stax/test/vstream/TestIncludes.java libwoodstox-java-5.1.0/src/test/java/org/codehaus/stax/test/vstream/TestIncludes.java --- libwoodstox-java-4.1.3/src/test/java/org/codehaus/stax/test/vstream/TestIncludes.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/org/codehaus/stax/test/vstream/TestIncludes.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,133 @@ +package org.codehaus.stax.test.vstream; + +import java.io.StringReader; + +import javax.xml.stream.*; + +import org.codehaus.stax.test.SimpleResolver; + +/** + * Simple unit tests to check and verify that DTD handler properly deals + * with conditional sections. + * + * @author Tatu Saloranta + */ +public class TestIncludes + extends BaseVStreamTest +{ + public void testSimpleInclude() + throws XMLStreamException + { + final String XML = + "&myent;"; + ; + final String EXT_DTD = + "\n" + +"" + +"]]>\n" + ; + + XMLInputFactory f = getValidatingFactory(true); + setResolver(f, new SimpleResolver(EXT_DTD)); + XMLStreamReader sr = f.createXMLStreamReader(new StringReader(XML)); + assertTokenType(DTD, sr.next()); + assertTokenType(START_ELEMENT, sr.next()); + assertTokenType(CHARACTERS, sr.next()); + assertEquals("value", getAndVerifyText(sr)); + assertTokenType(END_ELEMENT, sr.next()); + } + + public void testSimpleIgnore() + throws XMLStreamException + { + final String XML = + "&myent;"; + ; + + /* Let's add something that'd be invalid in there... + */ + final String EXT_DTD = + "\n" + +" " + +"]]>\n" + +"" + ; + + XMLInputFactory f = getValidatingFactory(true); + setResolver(f, new SimpleResolver(EXT_DTD)); + XMLStreamReader sr = f.createXMLStreamReader(new StringReader(XML)); + assertTokenType(DTD, sr.next()); + assertTokenType(START_ELEMENT, sr.next()); + assertTokenType(CHARACTERS, sr.next()); + assertEquals("value", getAndVerifyText(sr)); + assertTokenType(END_ELEMENT, sr.next()); + } + + /** + * Conditional sections can NOT be used in the internal subset -- + * let's quickly verify this. + */ + public void testFailingInIntSubset() + throws XMLStreamException + { + // first inclusion: + String XML = + "" + +"]]>" + +"]>\n" + ; + streamThroughFailing(getValidatingReader(XML), + "Condition INCLUDE not allowed in internal DTD subset"); + + // Then IGNORE: + XML = + "" + +"]]>" + +" " + +"]>\n" + ; + streamThroughFailing(getValidatingReader(XML), + "Condition INCLUDE not allowed in internal DTD subset"); + } + + /** + * Ok, and then we better consider parameter entity expanded variations + * of INCLUDE/IGNORE directives (see example under XML 1.0.3 section 3.4 + * for a sample) + */ + public void testPEIncludeAndIgnore() + throws XMLStreamException + { + final String XML = "&myent;"; + ; + final String EXT_DTD = + "\n" + +"\n" + +"\n" + +"]]>\n" + +"\n" + +"]]>\n" + +"\n" + ; + + XMLInputFactory f = getValidatingFactory(true); + setResolver(f, new SimpleResolver(EXT_DTD)); + XMLStreamReader sr = f.createXMLStreamReader(new StringReader(XML)); + assertTokenType(DTD, sr.next()); + assertTokenType(START_ELEMENT, sr.next()); + assertTokenType(CHARACTERS, sr.next()); + String text = getAndVerifyText(sr); + if (!text.equals("include")) { + fail("Expected 'myent' to expand to 'include', not '"+text+"'"); + } + assertTokenType(END_ELEMENT, sr.next()); + } +} diff -Nru libwoodstox-java-4.1.3/src/test/java/org/codehaus/stax/test/vstream/TestInvalidDTD.java libwoodstox-java-5.1.0/src/test/java/org/codehaus/stax/test/vstream/TestInvalidDTD.java --- libwoodstox-java-4.1.3/src/test/java/org/codehaus/stax/test/vstream/TestInvalidDTD.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/org/codehaus/stax/test/vstream/TestInvalidDTD.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,103 @@ +package org.codehaus.stax.test.vstream; + +import javax.xml.stream.*; + +/** + * Simple unit test suite that checks for set of well-formedness problems + * with DTDs + * + * @author Tatu Saloranta + */ +public class TestInvalidDTD + extends BaseVStreamTest +{ + public void testInvalidDirectives() + throws XMLStreamException + { + String XML = "\n" + +"]>\n"; + streamThroughFailing(getValidatingReader(XML), "invalid directive ''"); + + XML = "\n" + +"\n" + +"]>\n"; + streamThroughFailing(getValidatingReader(XML), "invalid directive ''"); + } + + public void testInvalidGE() + throws XMLStreamException + { + // Need space between name, content + String XML = "\n" + +"]>\n"; + streamThroughFailing(getValidatingReader(XML), + "missing space between general entity name and value"); + } + + public void testInvalidPE() + throws XMLStreamException + { + // Need space between name, content + String XML = "\n" + +"\n" + +"]>\n"; + streamThroughFailing(getValidatingReader(XML), "missing space between parameter entity name and value"); + + // As well as before and after percent sign + XML = "\n" + +"\n" + +"]>\n"; + streamThroughFailing(getValidatingReader(XML), "missing space between parameter entity percent sign and name"); + XML = "\n" + +"\n" + +"]>"; + streamThroughFailing(getValidatingReader(XML), "missing space between ENTITY and parameter entity percent sign"); + + // and finally, no NDATA allowed for PEs + XML = "\n" + +"\n" + +"\n" + +"]>\n"; + streamThroughFailing(getValidatingReader(XML), "PEs can not be unparsed external (ie. have NDATA reference)"); + } + + public void testInvalidComment() + throws XMLStreamException + { + String XML = "\n" + +"\n" + +"]>"; + streamThroughFailing(getValidatingReader(XML), "invalid directive ''"); + } + + public void testInvalidPI() + throws XMLStreamException + { + String XML = "\n" + +"\n" + +"]>"; + streamThroughFailing(getValidatingReader(XML), "invalid processing instruction in DTD; can not have target 'xml'"); + } + + /** + * CDATA directive not allowed in DTD subsets. + */ + public void testInvalidCData() + throws XMLStreamException + { + String XML = "\n" + +"\n" + +"]>"; + streamThroughFailing(getValidatingReader(XML), "invalid CDATA directive in int. DTD subset"); + } +} diff -Nru libwoodstox-java-4.1.3/src/test/java/org/codehaus/stax/test/vstream/TestNmTokenAttrRead.java libwoodstox-java-5.1.0/src/test/java/org/codehaus/stax/test/vstream/TestNmTokenAttrRead.java --- libwoodstox-java-4.1.3/src/test/java/org/codehaus/stax/test/vstream/TestNmTokenAttrRead.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/org/codehaus/stax/test/vstream/TestNmTokenAttrRead.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,136 @@ +package org.codehaus.stax.test.vstream; + +import javax.xml.stream.*; + +/** + * Unit test suite that tests handling of attributes that are declared + * by DTD to be of type NMTOKEN or NMTOKENS; such information is only + * guranteed to be available in validation mode. + */ +public class TestNmTokenAttrRead + extends BaseVStreamTest +{ + /* + /////////////////////////////////////// + // Test cases + /////////////////////////////////////// + */ + + /** + * Test case that verifies behaviour of valid NMTOKEN/NMTOKENS + * attribute declarations. + */ + public void testValidNmTokenAttrDecl() + throws XMLStreamException + { + // Following should be ok + String XML = "\n" + +"\n" + +"]>\n"; + streamThrough(getValidatingReader(XML)); + } + + /** + * Test case that verifies behaviour of invalid NMTOKEN/NMTOKENS + * attribute declarations. + */ + public void testInvalidNmTokenAttrDecl() + throws XMLStreamException + { + // ??? Are there any such cases? + } + + public void testValidNmTokenAttrUse() + throws XMLStreamException + { + String XML = "\n" + +"\n" + +"\n" + +"]>\n "; + streamThrough(getValidatingReader(XML)); + } + + public void testInvalidNmTokenAttrUse() + throws XMLStreamException + { + // Error: invalid NMTOKEN, ? not valid + String XML = "\n" + +"\n" + +"]>\n"; + streamThroughFailing(getValidatingReader(XML), + "invalid char ('?') in NMTOKEN"); + + // Error: invalid NMTOKENS, / not valid + XML = "\n" + +"\n" + +"]>\n"; + streamThroughFailing(getValidatingReader(XML), + "invalid char ('/') in NMTOKENS"); + } + + /** + * Unit test that verifies that values of attributes of type NMTOKEN and + * NMTOKENS will get properly normalized. + */ + public void testNmTokenAttrNormalization() + throws XMLStreamException + { + String XML = "\n" + +"\n" + +"\n" + +"\n" + +"\n" + +"\n" + +"\n" + +"]>" + +"" + +"" + +"" + +"" + +""; + ; + XMLStreamReader sr = getValidatingReader(XML); + assertTokenType(DTD, sr.next()); + assertTokenType(START_ELEMENT, sr.next()); + assertEquals("elem", sr.getLocalName()); + assertEquals(1, sr.getAttributeCount()); + assertEquals("nmToken", sr.getAttributeValue(0)); + assertTokenType(START_ELEMENT, sr.next()); + assertEquals(1, sr.getAttributeCount()); + assertEquals("name", sr.getAttributeValue(0)); + assertTokenType(END_ELEMENT, sr.next()); + assertTokenType(START_ELEMENT, sr.next()); + assertEquals(1, sr.getAttributeCount()); + assertEquals("first_name second last", sr.getAttributeValue(0)); + assertTokenType(END_ELEMENT, sr.next()); + + // then the defaults + assertTokenType(START_ELEMENT, sr.next()); + assertEquals("elem2", sr.getLocalName()); + assertEquals(1, sr.getAttributeCount()); + assertEquals("name", sr.getAttributeLocalName(0)); + assertEquals("somename", sr.getAttributeValue(0)); + assertTokenType(END_ELEMENT, sr.next()); + + assertTokenType(START_ELEMENT, sr.next()); + assertEquals("elem3", sr.getLocalName()); + assertEquals(1, sr.getAttributeCount()); + assertEquals("names", sr.getAttributeLocalName(0)); + assertEquals("name1 name2 name3", sr.getAttributeValue(0)); + assertTokenType(END_ELEMENT, sr.next()); + + assertTokenType(END_ELEMENT, sr.next()); + } + + /* + //////////////////////////////////////// + // Private methods + //////////////////////////////////////// + */ +} diff -Nru libwoodstox-java-4.1.3/src/test/java/org/codehaus/stax/test/vstream/TestNotationAttrRead.java libwoodstox-java-5.1.0/src/test/java/org/codehaus/stax/test/vstream/TestNotationAttrRead.java --- libwoodstox-java-4.1.3/src/test/java/org/codehaus/stax/test/vstream/TestNotationAttrRead.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/org/codehaus/stax/test/vstream/TestNotationAttrRead.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,163 @@ +package org.codehaus.stax.test.vstream; + +import javax.xml.stream.*; + +/** + * Unit test suite that tests handling of attributes that are declared + * by DTD to be of type NOTATION. + * + * @author Tatu Saloranta + */ +public class TestNotationAttrRead + extends BaseVStreamTest +{ + /* + /////////////////////////////////////// + // Test cases + /////////////////////////////////////// + */ + + public void testValidAttrDecl() + throws XMLStreamException + { + // Following should be ok; notations have been declared ok + String XML = "\n" + +"\n" + +"\n" + +"" + +"]>\n"; + streamThrough(getValidatingReader(XML)); + + // Likewise for default values + XML = "\n" + +"\n" + +"\n" + +"" + +"]>\n"; + streamThrough(getValidatingReader(XML)); + } + + /** + * This unit test verifies that the ordering of ATTLIST declaration + * and NOTATION(s) it refers to need not be done in a specific + * order. + */ + public void testValidUnorderedAttrDecl() + throws XMLStreamException + { + String XML = "\n" + +"" + +"\n" + +"]>\n"; + try { + streamThrough(getValidatingReader(XML)); + } catch (XMLStreamException e) { + fail("Notation declaration order should not matter, but failed due to: "+e.getMessage()); + } + + // Likewise for default values + XML = "\n" + +"" + +"\n" + +"]>\n"; + try { + streamThrough(getValidatingReader(XML)); + } catch (XMLStreamException e) { + fail("Notation declaration order should not matter, but failed due to: "+e.getMessage()); + } + } + + public void testInvalidAttrDecl() + throws XMLStreamException + { + // First, let's check that undeclared notation throws an exception + String XML = "\n" + +"" + +"]>\n"; + + XMLStreamReader sr = getValidatingReader(XML); + streamThroughFailing(sr, "undeclared notation"); + + // And then that only one attribute of type NOTATION is allowed per element + XML = "\n" + +"\n" + +"\n" + +"]>\n"; + + sr = getValidatingReader(XML); + streamThroughFailing(sr, "more than one notation attribute per element"); + + // Also, notation ids can not be duplicates + XML = "\n" + +"\n" + +"\n" + +"\n" + +"]>\n"; + + sr = getValidatingReader(XML); + streamThroughFailing(sr, "duplicate notation values enumerated for attribute"); + } + + public void testValidAttrUse() + throws XMLStreamException + { + // Following should be ok, everything defined as required... + String XML = "\n" + +"\n" + +"\n" + +"\n" + +"]>\n"; + streamThrough(getReader(XML)); + } + + public void testInvalidAttrUse() + throws XMLStreamException + { + // Shouldn't work, undefined notation... + String XML = "\n" + +"\n" + +"\n" + +"]>\n"; + + XMLStreamReader sr = getValidatingReader(XML); + streamThroughFailing(sr, "reference to notation that is not enumerated"); + + // and same using default values + XML = "\n" + +"\n" + +"\n" + +"]>\n"; + + sr = getValidatingReader(XML); + streamThroughFailing(sr, "reference to notation (via default value) that is not enumerated"); + } + + /* + //////////////////////////////////////// + // Private methods + //////////////////////////////////////// + */ + + private XMLStreamReader getReader(String contents) + throws XMLStreamException + { + XMLInputFactory f = getInputFactory(); + setCoalescing(f, false); // shouldn't really matter + //setNamespaceAware(f, nsAware); + setSupportDTD(f, true); + // Let's make sure DTD is really parsed? + setValidating(f, true); + return constructStreamReader(f, contents); + } +} diff -Nru libwoodstox-java-4.1.3/src/test/java/org/codehaus/stax/test/vstream/TestParamEntities.java libwoodstox-java-5.1.0/src/test/java/org/codehaus/stax/test/vstream/TestParamEntities.java --- libwoodstox-java-4.1.3/src/test/java/org/codehaus/stax/test/vstream/TestParamEntities.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/org/codehaus/stax/test/vstream/TestParamEntities.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,56 @@ +package org.codehaus.stax.test.vstream; + +import java.io.StringReader; +import java.util.*; + +import javax.xml.stream.*; + +/** + * Unit test suite that tests various aspects of parameter entity resolution + * in the external DTD subset. + * + * @author Tatu Saloranta + */ +public class TestParamEntities + extends BaseVStreamTest +{ + /** + * Test similar to one in xmltest (valid/not-sa/003.xml, specifically) + */ + public void testExternalParamDeclViaPE() + throws XMLStreamException + { + HashMap m = new HashMap(); + m.put("ent1", "\n" + +"\n" + +""); + m.put("ent2", ""); + + // Following should be ok; notations have been declared ok + String XML = ""; + + XMLInputFactory f = getValidatingFactory(true); + setResolver(f, new MyResolver(m)); + streamThrough(getValidatingReader(XML)); + } + + final static class MyResolver + implements XMLResolver + { + final Map mEntities; + + public MyResolver(Map entities) { + mEntities = entities; + } + + @Override + public Object resolveEntity(String publicID, String systemID, String baseURI, String namespace) + { + String str = (String) mEntities.get(publicID); + if (str == null) { + str = (String) mEntities.get(systemID); + } + return (str == null) ? null : new StringReader(str); + } + } +} diff -Nru libwoodstox-java-4.1.3/src/test/java/org/codehaus/stax/test/vstream/TestStructuralValidation.java libwoodstox-java-5.1.0/src/test/java/org/codehaus/stax/test/vstream/TestStructuralValidation.java --- libwoodstox-java-4.1.3/src/test/java/org/codehaus/stax/test/vstream/TestStructuralValidation.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/org/codehaus/stax/test/vstream/TestStructuralValidation.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,448 @@ +package org.codehaus.stax.test.vstream; + +import javax.xml.stream.*; + +/** + * Unit test suite that tests structural validation using DTD. + */ +public class TestStructuralValidation + extends BaseVStreamTest +{ + public TestStructuralValidation() { + super(); + // Uncomment to see if we get exceptions we should be getting: + //PRINT_EXP_EXCEPTION = true; + } + + public void testValidStructure() + throws XMLStreamException + { + for (int i = 0; i < 2; ++i) { + boolean nsAware = (i > 0); + String XML = "\n" + +"\n" + +"\n" + +"]>\n Text "; + streamThrough(getReader(XML, nsAware)); + } + } + + public void testValidStructure2() + throws XMLStreamException + { + for (int i = 0; i < 2; ++i) { + boolean nsAware = (i > 0); + String XML = "\n" + +"\n" + +"\n" + +"]>\n text"; + streamThrough(getReader(XML, nsAware)); + + // Ok, as leaf is optional... + XML = "\n" + +"\n" + +"]>\n"; + streamThrough(getReader(XML, nsAware)); + + XML = "\n" + +"\n" + +"]>\n text & and more"; + streamThrough(getReader(XML, nsAware)); + } + } + + public void testValidSimpleSeqStructure() + throws XMLStreamException + { + for (int i = 0; i < 2; ++i) { + boolean nsAware = (i > 0); + String XML = "\n" + +"\n" + +"\n" + +"\n" + +"\n" + +"]>\n" + +"\n" + +"" + +""; + streamThrough(getReader(XML, nsAware)); + } + } + + public void testInvalidSimpleSeqStructure() + throws XMLStreamException + { + for (int i = 0; i < 2; ++i) { + boolean nsAware = (i > 0); + String XML = "\n" + +"\n" + +"\n" + +"\n" + +"\n" + +"]>\n" + +"\n" + +"" + +""; + streamThroughFailing(getReader(XML, nsAware), + "invalid simple content sequence: missing 'a3' element"); + + XML = "\n" + +"\n" + +"\n" + +"\n" + +"\n" + +"]>\n" + +"\n" + +"" + +""; + streamThroughFailing(getReader(XML, nsAware), + "invalid simple content sequence: missing 'a4' element"); + } + } + + public void testValidSimpleChoiceStructure() + throws XMLStreamException + { + for (int i = 0; i < 2; ++i) { + boolean nsAware = (i > 0); + String XML = "\n" + +"\n" + +"\n" + +"\n" + +"\n" + +"\n" + +"\n" + +"\n" + +"\n" + +"\n" + +"]>\n" + +"\n" + +"" + +""; + streamThrough(getReader(XML, nsAware)); + } + } + + public void testInvalidSimpleChoiceStructure() + throws XMLStreamException + { + for (int i = 0; i < 2; ++i) { + boolean nsAware = (i > 0); + String XML = "\n" + +"\n" + +"\n" + +"\n" + +"\n" + +"]>\n" + +"\n" + +""; + streamThroughFailing(getReader(XML, nsAware), + "invalid choice content sequence: no children for root"); + + XML = "\n" + +"\n" + +"\n" + +"\n" + +"\n" + +"]>\n" + +"" + +""; + streamThroughFailing(getReader(XML, nsAware), + "invalid choice content sequence: more than one child"); + + XML = "\n" + +"\n" + +"\n" + +"\n" + +"]>\n" + +"" + +""; + streamThroughFailing(getReader(XML, nsAware), + "invalid choice content sequence: c1 not one of legal children for root"); + } + } + + public void testValidFullChoiceStructure() + throws XMLStreamException + { + for (int i = 0; i < 2; ++i) { + boolean nsAware = (i > 0); + String XML = "\n" + +"\n" + +"\n" + +"\n" + +"\n" + +"]>\n" + +"\n" + +"" + +""; + streamThrough(getReader(XML, nsAware)); + } + } + + public void testValidMixed() + throws XMLStreamException + { + for (int i = 0; i < 2; ++i) { + boolean nsAware = (i > 0); + String XML = "\n" + +"\n" + +"]>Text "; + streamThrough(getReader(XML, nsAware)); + } + } + + public void testInvalidWrongRoot() + throws XMLStreamException + { + for (int i = 0; i < 2; ++i) { + boolean nsAware = (i > 0); + String XML = " "; + streamThroughFailing(getReader(XML, nsAware), "wrong root element"); + } + } + + public void testInvalidMixed() + throws XMLStreamException + { + for (int i = 0; i < 2; ++i) { + boolean nsAware = (i > 0); + String XML = "\n" + +"\n" + +"]>Text "; + streamThroughFailing(getReader(XML, nsAware), + "invalid mixed content"); + + // same, but after a child elem... + XML = "\n" + +"\n" + +"]> x "; + streamThroughFailing(getReader(XML, nsAware), + "invalid mixed content"); + } + } + + public void testInvalidStructureRoot() + throws XMLStreamException + { + for (int i = 0; i < 2; ++i) { + boolean nsAware = (i > 0); + + // First, wrong root element + String XML = "\n" + +"\n" + +"\n" + +"]>\n"; + streamThroughFailing(getReader(XML, nsAware), + "wrong root element"); + + // Then undeclared (root) element + XML = "\n" + +"]>\n "; + streamThroughFailing(getReader(XML, nsAware), + "undeclared element"); + + // Then one wrong element content for root + XML = "\n" + +"\n" + +"\n" + +"]>\n "; + streamThroughFailing(getReader(XML, nsAware), + "wrong element content (expected branch+, end; got nothing) for root"); + } + } + + public void testInvalidStructure() + throws XMLStreamException + { + for (int i = 0; i < 2; ++i) { + boolean nsAware = (i > 0); + + // And then just wrong ordering of child elements + String XML = "\n" + +"\n" + +"\n" + +"]>\n "; + streamThroughFailing(getReader(XML, nsAware), + "wrong element content (ordering) for root"); + + XML = "\n" + +"\n" + +"\n" + +"]>\n xyz"; + streamThroughFailing(getReader(XML, nsAware), + "wrong element content (missing 'end' element) for root"); + + XML = "\n" + +"\n" + +"\n" + +"]>\n "; + streamThroughFailing(getReader(XML, nsAware), + "missing children for root"); + + XML = "\n" + +"\n" + +"\n" + +"\n" + +"]>\n "; + streamThroughFailing(getReader(XML, nsAware), + "wrong child element for branch"); + } + } + + final static String COMPLEX_DTD = + "\n" + +"\n" + +"\n" + +"\n" + +"\n" + +"\n" + +"\n" + +"\n" + +"\n" + +"\n" + ; + + public void testValidStructureComplex() + throws XMLStreamException + { + for (int i = 0; i < 2; ++i) { + boolean nsAware = (i > 0); + + // And then just wrong ordering of child elements + String XML = "" + +"" + +" " + +" " + +" " + +" " + +"" + ; + streamThrough(getReader(XML, nsAware)); + } + } + + public void testInvalidStructureComplex() + throws XMLStreamException + { + for (int i = 0; i < 2; ++i) { + boolean nsAware = (i > 0); + + // And then just wrong ordering of child elements + String XML = "" + +"" + +" " + +" " + // b is missing: + +" " + +" " + +"" + ; + streamThroughFailing(getReader(XML, nsAware), + "wrong element structure; missing element "); + } + } + + /** + * Unit test that checks that it's illegal to add any content (including + * comment, processing instructions or white space) within an element that has + * content declaration of EMPTY. + */ + public void testInvalidEmpty() + throws XMLStreamException + { + for (int i = 0; i < 2; ++i) { + boolean nsAware = (i > 0); + String XML = "\n" + +"]>"; + streamThroughFailing(getReader(XML, nsAware), + "comment within element that has EMPTY content type declaration"); + + XML = "\n" + +"]>"; + streamThroughFailing(getReader(XML, nsAware), + "processing instruction within element that has EMPTY content type declaration"); + + XML = "\n" + +"]> "; + streamThroughFailing(getReader(XML, nsAware), + "white space within element that has EMPTY content type declaration"); + + XML = "\n" + +"\n" + +"]>"; + streamThroughFailing(getReader(XML, nsAware), + "element within element that has EMPTY content type declaration"); + } + } + + public void testValidAny() + throws XMLStreamException + { + for (int i = 0; i < 2; ++i) { + boolean nsAware = (i > 0); + String XML = "\n" + +"\n" + +"\n" + +"]> "; + streamThrough(getReader(XML, nsAware)); + } + } + + public void testInvalidAny() + throws XMLStreamException + { + for (int i = 0; i < 2; ++i) { + boolean nsAware = (i > 0); + String XML = "\n" + +"]>"; + streamThroughFailing(getReader(XML, nsAware), + "undeclared element in element with ANY content type"); + } + } + + /* + //////////////////////////////////////// + // Private methods, other + //////////////////////////////////////// + */ + + private XMLStreamReader getReader(String contents, boolean nsAware) + throws XMLStreamException + { + XMLInputFactory f = getInputFactory(); + setCoalescing(f, false); // shouldn't really matter + setNamespaceAware(f, nsAware); + setSupportDTD(f, true); + setValidating(f, true); + return constructStreamReader(f, contents); + } +} diff -Nru libwoodstox-java-4.1.3/src/test/java/org/codehaus/stax/test/vstream/TestSubsetCombination.java libwoodstox-java-5.1.0/src/test/java/org/codehaus/stax/test/vstream/TestSubsetCombination.java --- libwoodstox-java-4.1.3/src/test/java/org/codehaus/stax/test/vstream/TestSubsetCombination.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/org/codehaus/stax/test/vstream/TestSubsetCombination.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,96 @@ +package org.codehaus.stax.test.vstream; + +import javax.xml.stream.*; + +import org.codehaus.stax.test.SimpleResolver; + +/** + * Unit test suite that tests how implementation handles combining of + * internal and external DTD subsets. + * + * @author Tatu Saloranta + */ +public class TestSubsetCombination + extends BaseVStreamTest +{ + /** + * This unit test checks that a DTD definition that is evenly split + * between subsets will be properly combined, and results in a usable + * definition for validation. + */ + public void testValidSubsets() + throws XMLStreamException + { + // Note: need to resolve using a custom resolver + String XML = + "\n" + +"\n" + +"\n" + +"]> Test entities: &ent1;, &ent2;" + +"..." + +""; + String EXT_DTD = + "\n" + +"\n" + +"\n" + ; + streamThrough(getReader(XML, true, EXT_DTD)); + // Let's also test that non-ns works, just in case it's different + streamThrough(getReader(XML, false, EXT_DTD)); + } + + /** + * This unit test checks that the internal subset has precedence + * for attribute definitions -- it's ok to declare attributes multiple + * times, but the first one sticks, and internal subset is considered + * to come before external subset + */ + public void testAttributePrecedence() + throws XMLStreamException + { + String XML = + "\n" + +"\n" + +"\n" + +"]>" + ; + String EXT_DTD = + "\n" + +"\n" + ; + XMLStreamReader sr = getReader(XML, true, EXT_DTD); + assertTokenType(DTD, sr.next()); + assertTokenType(START_ELEMENT, sr.next()); + assertEquals(1, sr.getAttributeCount()); + assertEquals("attr2", sr.getAttributeLocalName(0)); + assertEquals("intValue", sr.getAttributeValue(0)); + assertFalse(sr.isAttributeSpecified(0)); + } + + /* + //////////////////////////////////////// + // Non-test methods + //////////////////////////////////////// + */ + + private XMLStreamReader getReader(String contents, boolean nsAware, + String extSubset) + throws XMLStreamException + { + XMLInputFactory f = getInputFactory(); + setNamespaceAware(f, nsAware); + setSupportDTD(f, true); + setCoalescing(f, false); + setReplaceEntities(f, true); + setValidating(f, true); + if (extSubset != null) { + setResolver(f, new SimpleResolver(extSubset)); + } else { + setResolver(f, null); + } + return constructStreamReader(f, contents); + } +} + diff -Nru libwoodstox-java-4.1.3/src/test/java/org/codehaus/stax/test/wstream/BaseWriterTest.java libwoodstox-java-5.1.0/src/test/java/org/codehaus/stax/test/wstream/BaseWriterTest.java --- libwoodstox-java-4.1.3/src/test/java/org/codehaus/stax/test/wstream/BaseWriterTest.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/org/codehaus/stax/test/wstream/BaseWriterTest.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,35 @@ +package org.codehaus.stax.test.wstream; + +import java.io.*; + +import javax.xml.stream.*; + +import org.codehaus.stax.test.BaseStaxTest; + +/** + * Base class for all StaxTest unit tests that test basic + * stream (cursor) writer API functionality. + * + * @author Tatu Saloranta + */ +public abstract class BaseWriterTest + extends BaseStaxTest +{ + public XMLStreamWriter getRepairingWriter(Writer w) + throws XMLStreamException + { + XMLOutputFactory f = getOutputFactory(); + f.setProperty(XMLOutputFactory.IS_REPAIRING_NAMESPACES, + Boolean.TRUE); + return f.createXMLStreamWriter(w); + } + + public XMLStreamWriter getNonRepairingWriter(Writer w) + throws XMLStreamException + { + XMLOutputFactory f = getOutputFactory(); + f.setProperty(XMLOutputFactory.IS_REPAIRING_NAMESPACES, + Boolean.FALSE); + return f.createXMLStreamWriter(w); + } +} diff -Nru libwoodstox-java-4.1.3/src/test/java/org/codehaus/stax/test/wstream/CharacterEscapingTest.java libwoodstox-java-5.1.0/src/test/java/org/codehaus/stax/test/wstream/CharacterEscapingTest.java --- libwoodstox-java-4.1.3/src/test/java/org/codehaus/stax/test/wstream/CharacterEscapingTest.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/org/codehaus/stax/test/wstream/CharacterEscapingTest.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,129 @@ +package org.codehaus.stax.test.wstream; + +import java.io.*; + +import javax.xml.stream.*; + +import org.codehaus.stax2.XMLOutputFactory2; +import org.codehaus.stax2.io.EscapingWriterFactory; + +public class CharacterEscapingTest + extends BaseWriterTest +{ + public void testSimpleCdataEscaping() throws Exception + { + XMLOutputFactory outF = getNewOutputFactory(); + outF.setProperty(XMLOutputFactory2.P_TEXT_ESCAPER, new Escapers()); + + _testSimpleEscaping(outF, "", "", + "\">[tag]"); + _testSimpleEscaping(outF, "r&d", "b&w", + "b&w"); + _testSimpleEscaping(outF, "'donald'", "\"duck\"", + "'duck'"); + } + + public void testSimpleAttributeEscaping() throws Exception + { + XMLOutputFactory outF = getNewOutputFactory(); + outF.setProperty(XMLOutputFactory2.P_ATTR_VALUE_ESCAPER, new Escapers()); + + _testSimpleEscaping(outF, "", "", + "<tag>"); + _testSimpleEscaping(outF, "r&d", "b&w", + "b&w"); + _testSimpleEscaping(outF, "'donald'", "\"duck\"", + "\"duck\""); + } + + protected void _testSimpleEscaping(XMLOutputFactory outF, + String attrValue, String elemValue, String expDoc) throws Exception + { + // First using Writer + StringWriter strW = new StringWriter(); + XMLStreamWriter w = outF.createXMLStreamWriter(strW); + _writeSimpleCData(w, attrValue, elemValue); + w.close(); + assertEquals(expDoc, stripXmlDecl(strW.toString()).trim()); + + // then OutputStream + ByteArrayOutputStream bytes = new ByteArrayOutputStream(); + w = outF.createXMLStreamWriter(bytes, "UTF-8"); + _writeSimpleCData(w, attrValue, elemValue); + w.close(); + assertEquals(expDoc, stripXmlDecl(bytes.toString("UTF-8")).trim()); + } + + protected void _writeSimpleCData(XMLStreamWriter w, String attrValue, String elemValue) throws Exception + { + w.writeStartDocument(); + w.writeStartElement("root"); + w.writeAttribute("attr", attrValue); + w.writeCharacters(elemValue); + w.writeEndElement(); + w.writeEndDocument(); + } + + static class Escapers implements EscapingWriterFactory + { + @Override + public Writer createEscapingWriterFor(Writer w, String enc) throws UnsupportedEncodingException { + return new JsonValueWriter(w); + } + + @Override + public Writer createEscapingWriterFor(OutputStream out, String enc) throws UnsupportedEncodingException { + return new JsonValueWriter(new OutputStreamWriter(out, enc)); + } + } + + static class JsonValueWriter extends Writer { + protected final Writer _out; + + public JsonValueWriter(Writer out) { + _out = out; + } + + @Override + public void write(char[] cbuf, int off, int len) throws IOException { + for (int i = off, end = off+len; i < end; ++i) { + write(cbuf[i]); + } + } + + @Override + public void write(int ch) throws IOException + { + switch (ch) { + case '<': + _out.write("["); + break; + case '>': + _out.write("]"); + break; + case '&': + _out.write("&"); + break; + case '"': // replace with apostrophes for funsies + _out.write("'"); + break; + case '\'': // replace with XML escape for apostrophes + _out.write("'"); + break; + default: + _out.write(ch); + } + } +// w.writeCharacters("' & \"b\"'"); + + @Override + public void flush() throws IOException { + _out.flush(); + } + + @Override + public void close() throws IOException { + _out.close(); + } + } +} diff -Nru libwoodstox-java-4.1.3/src/test/java/org/codehaus/stax/test/wstream/TestOutputEncoding.java libwoodstox-java-5.1.0/src/test/java/org/codehaus/stax/test/wstream/TestOutputEncoding.java --- libwoodstox-java-4.1.3/src/test/java/org/codehaus/stax/test/wstream/TestOutputEncoding.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/org/codehaus/stax/test/wstream/TestOutputEncoding.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,151 @@ +package org.codehaus.stax.test.wstream; + +import javax.xml.stream.*; + +import java.io.*; + +/** + * Set of unit tests for verifying operation of {@link XMLStreamWriter} + * when outputting text nodes that contain characters that should + * be quoted. + * + * @author Tatu Saloranta + */ +public class TestOutputEncoding + extends BaseWriterTest +{ + final String ISO_LATIN_ENCODING = "ISO-8859-1"; + final String UTF8_ENCODING = "UTF-8"; + + public void testSimpleContentQuoting() + throws IOException, XMLStreamException + { + String TEXT = "&"; + _testSimpleQuoting(ISO_LATIN_ENCODING, TEXT); + _testSimpleQuoting(UTF8_ENCODING, TEXT); + + TEXT = "Need to quote this too: ]]>"; + _testSimpleQuoting(ISO_LATIN_ENCODING, TEXT); + _testSimpleQuoting(UTF8_ENCODING, TEXT); + + TEXT = "And nbsp: \u00A0."; + _testSimpleQuoting(ISO_LATIN_ENCODING, TEXT); + _testSimpleQuoting(UTF8_ENCODING, TEXT); + } + + public void testSimpleAttrQuoting() + throws IOException, XMLStreamException + { + String TEXT = "&"; + doTestSimpleAttr(ISO_LATIN_ENCODING, TEXT); + doTestSimpleAttr(UTF8_ENCODING, TEXT); + + // Plus, need to quote single/double quotes properly + TEXT = "'\"fab\"'"; + doTestSimpleAttr(ISO_LATIN_ENCODING, TEXT); + doTestSimpleAttr(UTF8_ENCODING, TEXT); + + // And let's test non-ascii char too: + TEXT = "Nbsp -> \u00A0."; + doTestSimpleAttr(ISO_LATIN_ENCODING, TEXT); + doTestSimpleAttr(UTF8_ENCODING, TEXT); + } + + public void testXml11CharQuoting() + throws IOException, XMLStreamException + { + String TEXT = "First: (\u0007)"; + _testXml11CharQuoting(ISO_LATIN_ENCODING, TEXT); + _testXml11CharQuoting(UTF8_ENCODING, TEXT); + + TEXT = "Second: (\u009F)"; + _testXml11CharQuoting(ISO_LATIN_ENCODING, TEXT); + _testXml11CharQuoting(UTF8_ENCODING, TEXT); + + TEXT = "Third: (\u007F)"; + _testXml11CharQuoting(ISO_LATIN_ENCODING, TEXT); + _testXml11CharQuoting(UTF8_ENCODING, TEXT); + } + + /* + /////////////////////////////////////////////////////////// + // Helper methods + /////////////////////////////////////////////////////////// + */ + + private void _testSimpleQuoting(String encoding, String content) + throws IOException, XMLStreamException + { + StringWriter strw = new StringWriter(); + XMLStreamWriter w = getNonRepairingWriter(strw); + + w.writeStartDocument(encoding, "1.0"); + w.writeStartElement("root"); + w.writeCharacters(content); + w.writeEndElement(); + w.writeEndDocument(); + w.close(); + + // And then let's parse and verify it all: + XMLStreamReader sr = constructNsStreamReader(strw.toString(), true); + assertTokenType(START_DOCUMENT, sr.getEventType()); + assertEquals(encoding, sr.getCharacterEncodingScheme()); + assertTokenType(START_ELEMENT, sr.next()); + + // May get multiple segments.. + assertTokenType(CHARACTERS, sr.next()); + assertEquals(content, getAllText(sr)); + assertTokenType(END_ELEMENT, sr.getEventType()); + assertTokenType(END_DOCUMENT, sr.next()); + } + + private void doTestSimpleAttr(String encoding, String attrValue) + throws IOException, XMLStreamException + { + StringWriter strw = new StringWriter(); + XMLStreamWriter w = getNonRepairingWriter(strw); + + w.writeStartDocument(encoding, "1.0"); + w.writeStartElement("root"); + w.writeAttribute("attr", attrValue); + w.writeEndElement(); + w.writeEndDocument(); + w.close(); + + // And then let's parse and verify it all: + XMLStreamReader sr = constructNsStreamReader(strw.toString(), true); + assertTokenType(START_DOCUMENT, sr.getEventType()); + assertEquals(encoding, sr.getCharacterEncodingScheme()); + assertTokenType(START_ELEMENT, sr.next()); + assertEquals(1, sr.getAttributeCount()); + assertEquals(attrValue, sr.getAttributeValue(0)); + assertTokenType(END_ELEMENT, sr.next()); + assertTokenType(END_DOCUMENT, sr.next()); + } + + private void _testXml11CharQuoting(String encoding, String content) + throws IOException, XMLStreamException + { + StringWriter strw = new StringWriter(); + XMLStreamWriter w = getNonRepairingWriter(strw); + + w.writeStartDocument(encoding, "1.1"); + w.writeStartElement("root"); + w.writeCharacters(content); + w.writeEndElement(); + w.writeEndDocument(); + w.close(); + + // And then let's parse and verify it all: + XMLStreamReader sr = constructUtf8StreamReader(getInputFactory(), strw.toString()); + assertTokenType(START_DOCUMENT, sr.getEventType()); + assertEquals(encoding, sr.getCharacterEncodingScheme()); + assertTokenType(START_ELEMENT, sr.next()); + + // May get multiple segments.. + assertTokenType(CHARACTERS, sr.next()); + assertEquals(content, getAllText(sr)); + assertTokenType(END_ELEMENT, sr.getEventType()); + assertTokenType(END_DOCUMENT, sr.next()); + } +} diff -Nru libwoodstox-java-4.1.3/src/test/java/org/codehaus/stax/test/wstream/TestProperties.java libwoodstox-java-5.1.0/src/test/java/org/codehaus/stax/test/wstream/TestProperties.java --- libwoodstox-java-4.1.3/src/test/java/org/codehaus/stax/test/wstream/TestProperties.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/org/codehaus/stax/test/wstream/TestProperties.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,21 @@ +package org.codehaus.stax.test.wstream; + +import javax.xml.stream.*; + +/** + * Unit tests that verify handling of XMLOutputFactory properties. + * This includes: + *

+ */ +public class TestProperties extends BaseWriterTest +{ + public void testDefaultSettings() + { + XMLOutputFactory f = getNewOutputFactory(); + assertEquals(Boolean.FALSE, f.getProperty(XMLOutputFactory.IS_REPAIRING_NAMESPACES)); + } +} diff -Nru libwoodstox-java-4.1.3/src/test/java/org/codehaus/stax/test/wstream/TestRepairingWriter.java libwoodstox-java-5.1.0/src/test/java/org/codehaus/stax/test/wstream/TestRepairingWriter.java --- libwoodstox-java-4.1.3/src/test/java/org/codehaus/stax/test/wstream/TestRepairingWriter.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/org/codehaus/stax/test/wstream/TestRepairingWriter.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,444 @@ +package org.codehaus.stax.test.wstream; + +import java.io.*; + +import javax.xml.stream.*; + +/** + * Set of unit tests for verifying operation of {@link XMLStreamWriter} + * in "repairing" mode. + * + * @author Tatu Saloranta + */ +public class TestRepairingWriter + extends BaseWriterTest +{ + /** + * Test similar to the one in {@link TestSimpleWriter}. + */ + public void testElements() + throws IOException, XMLStreamException + { + StringWriter strw = new StringWriter(); + XMLStreamWriter w = getRepairingWriter(strw); + final String URL_P1 = "http://p1.org"; + final String URL_P2 = "http://ns.p2.net/yeehaw.html"; + final String URL_DEF = "urn:default"; + + final String TEXT = " some text\n"; + + w.writeStartDocument(); + + /* Calling setPrefix() should be optional; but if we call it, + * exceptation is that it does properly cause URL to be bound. + */ + w.setPrefix("p1", URL_P1); + w.writeStartElement(URL_P1, "test"); + + w.writeStartElement("p2", "branch", URL_P2); + + // And then a dynamically created prefix... + w.writeStartElement(URL_DEF, "leaf"); + + w.writeCharacters(TEXT); + + w.writeEndElement(); // first leaf + + w.writeEmptyElement(URL_P1, "leaf"); // second leaf + + w.writeStartElement("", "third"); // may need dynamic NS too + w.writeEndElement(); + + w.writeEndElement(); // branch + w.writeEndElement(); // root elem + w.writeEndDocument(); + w.close(); + + // And then let's parse and verify it all: + XMLStreamReader sr = constructNsStreamReader(strw.toString()); + assertTokenType(START_DOCUMENT, sr.getEventType(), sr); + + // root element + assertTokenType(START_ELEMENT, sr.next(), sr); + assertEquals("test", sr.getLocalName()); + // ??? is writer obligated to honor the prefix suggestion + assertEquals(URL_P1, sr.getNamespaceURI()); + /* note: can not really verify number of namespace bindings, since + * writer should be in charge... and it may output extra bindings, + * too (and use default ns or explicit ones etc) + */ + + // first branch: + assertTokenType(START_ELEMENT, sr.next(), sr); + assertEquals("branch", sr.getLocalName()); + assertEquals(URL_P2, sr.getNamespaceURI()); + + // first leaf + assertTokenType(START_ELEMENT, sr.next(), sr); + assertEquals("leaf", sr.getLocalName()); + assertEquals(URL_DEF, sr.getNamespaceURI()); + + assertTokenType(CHARACTERS, sr.next(), sr); + assertEquals(TEXT, getAllText(sr)); + // not: getAllText ^^^ moves cursor! + + assertTokenType(END_ELEMENT, sr.getEventType(), sr); + assertEquals("leaf", sr.getLocalName()); + assertEquals(URL_DEF, sr.getNamespaceURI()); + + // another leaf: + assertTokenType(START_ELEMENT, sr.next(), sr); + assertEquals("leaf", sr.getLocalName()); + assertEquals(URL_P1, sr.getNamespaceURI()); + + assertTokenType(END_ELEMENT, sr.next(), sr); + assertEquals("leaf", sr.getLocalName()); + assertEquals(URL_P1, sr.getNamespaceURI()); + + // "third" + /* Adding explicit catching to print more diagnostics, as one + * of the tested impls did fail here: + */ + try { + assertTokenType(START_ELEMENT, sr.next(), sr); + } catch (XMLStreamException e) { + fail("Unexpected problems when parsing document [\""+strw.toString()+"\"], expecting element 'third': "+e.getMessage()); + throw e; + } + assertEquals("third", sr.getLocalName()); + assertNoNsURI(sr); + assertTokenType(END_ELEMENT, sr.next(), sr); + assertEquals("third", sr.getLocalName()); + assertNoNsURI(sr); + + // (close) branch + assertTokenType(END_ELEMENT, sr.next(), sr); + assertEquals("branch", sr.getLocalName()); + assertEquals(URL_P2, sr.getNamespaceURI()); + + // closing root element + assertTokenType(END_ELEMENT, sr.next(), sr); + assertEquals("test", sr.getLocalName()); + assertEquals(URL_P1, sr.getNamespaceURI()); + + assertTokenType(END_DOCUMENT, sr.next(), sr); + } + + public void testAttributeSimple() + throws IOException, XMLStreamException + { + StringWriter strw = new StringWriter(); + XMLStreamWriter w = getRepairingWriter(strw); + final String URL_P1 = "http://p1.org"; + final String ATTR_VALUE = "'value'&\"another\""; + + w.writeStartDocument(); + w.writeStartElement("", "test"); + w.writeAttribute(URL_P1, "attr", ATTR_VALUE); + w.writeEndElement(); + w.writeEndDocument(); + w.close(); + +//System.err.println("testAttributeSimple: doc = '"+strw+"'"); + + // And then let's parse and verify it all: + XMLStreamReader sr = constructNsStreamReader(strw.toString()); + assertTokenType(START_DOCUMENT, sr.getEventType(), sr); + + // root element + assertTokenType(START_ELEMENT, sr.next(), sr); + assertEquals("test", sr.getLocalName()); + assertNoNsURI(sr); + + assertEquals(1, sr.getAttributeCount()); + assertEquals("attr", sr.getAttributeLocalName(0)); + assertEquals(URL_P1, sr.getAttributeNamespace(0)); + assertEquals(ATTR_VALUE, sr.getAttributeValue(0)); + + assertTokenType(END_ELEMENT, sr.next(), sr); + assertEquals("test", sr.getLocalName()); + assertNoNsURI(sr); + + assertTokenType(END_DOCUMENT, sr.next(), sr); + } + + public void testAttributes() + throws IOException, XMLStreamException + { + StringWriter strw = new StringWriter(); + XMLStreamWriter w = getRepairingWriter(strw); +// final String URL_P1 = "http://p1.org"; + final String URL_DEF = "urn:default"; + final String ATTR_VALUE = "'value\""; + final String ATTR_VALUE2 = ""; + + w.writeStartDocument(); + + /* Calling this method should be optional; but if we call it, + * exceptation is that it does properly bind the prefix and URL + * as the 'preferred' combination. In this case we'll just try + * to make URL bound as the default namespace + */ + w.setDefaultNamespace(URL_DEF); + w.writeStartElement(URL_DEF, "test"); + + /* And let's further make element and attribute(s) belong to that + * same namespace + */ + w.writeStartElement("", "leaf", URL_DEF); + w.writeAttribute(URL_DEF, "attr", ATTR_VALUE); + w.writeEndElement(); + + w.writeEmptyElement("", "leaf"); // in empty/no namespace! + + w.writeStartElement(URL_DEF, "leaf"); + w.writeAttribute("", "attr2", ATTR_VALUE2); // in empty/no namespace + w.writeEndElement(); + + w.writeEndElement(); // root elem + w.writeEndDocument(); + w.close(); + + // And then let's parse and verify it all: + //System.err.println("testAttributes: doc = '"+strw+"'"); + + XMLStreamReader sr = constructNsStreamReader(strw.toString()); + assertTokenType(START_DOCUMENT, sr.getEventType(), sr); + + // root element + assertTokenType(START_ELEMENT, sr.next(), sr); + assertEquals("test", sr.getLocalName()); + assertEquals(URL_DEF, sr.getNamespaceURI()); + + // first leaf: + assertTokenType(START_ELEMENT, sr.next(), sr); + assertEquals("leaf", sr.getLocalName()); + assertEquals(URL_DEF, sr.getNamespaceURI()); + assertEquals(1, sr.getAttributeCount()); + assertEquals("attr", sr.getAttributeLocalName(0)); + + String uri = sr.getAttributeNamespace(0); + if (!URL_DEF.equals(uri)) { + fail("Expected attribute 'attr' to have NS '"+URL_DEF+"', was "+valueDesc(uri)+"; input = '"+strw+"'"); + } + assertEquals(ATTR_VALUE, sr.getAttributeValue(0)); + assertTokenType(END_ELEMENT, sr.next(), sr); + assertEquals("leaf", sr.getLocalName()); + assertEquals(URL_DEF, sr.getNamespaceURI()); + + // empty leaf + assertTokenType(START_ELEMENT, sr.next(), sr); + assertEquals("leaf", sr.getLocalName()); + assertNoNsURI(sr); + assertTokenType(END_ELEMENT, sr.next(), sr); + assertEquals("leaf", sr.getLocalName()); + assertNoNsURI(sr); + + // third leaf + assertTokenType(START_ELEMENT, sr.next(), sr); + assertEquals("leaf", sr.getLocalName()); + assertEquals(URL_DEF, sr.getNamespaceURI()); + + assertEquals(1, sr.getAttributeCount()); + assertEquals("attr2", sr.getAttributeLocalName(0)); + assertNoAttrNamespace(sr.getAttributeNamespace(0)); + assertEquals(ATTR_VALUE2, sr.getAttributeValue(0)); + + assertTokenType(END_ELEMENT, sr.next(), sr); + assertEquals("leaf", sr.getLocalName()); + assertEquals(URL_DEF, sr.getNamespaceURI()); + + // closing root element + assertTokenType(END_ELEMENT, sr.next(), sr); + assertEquals("test", sr.getLocalName()); + assertEquals(URL_DEF, sr.getNamespaceURI()); + + assertTokenType(END_DOCUMENT, sr.next(), sr); + } + + /** + * This test specifically checks that namespace bindings for + * sub-trees do not "leak" into following sibling elements or + * trees. + */ + public void testSiblingNsBinding() + throws IOException, XMLStreamException + { + StringWriter strw = new StringWriter(); + XMLStreamWriter w = getRepairingWriter(strw); + final String URL_P1 = "http://p1.org"; + + w.writeStartDocument(); + w.writeStartElement("root"); + + // First leaf: + w.writeStartElement("leaf1"); + w.writeAttribute(URL_P1, "attr1", "1"); + w.writeEndElement(); + + // Second leaf: + w.writeStartElement("leaf2"); + w.writeAttribute(URL_P1, "attr2", "2"); + w.writeEndElement(); + + w.writeEndDocument(); + w.close(); + +//System.err.println("doc = '"+strw+"'"); + + XMLStreamReader sr = constructNsStreamReader(strw.toString()); + // root element + assertTokenType(START_ELEMENT, sr.next(), sr); + assertEquals("root", sr.getLocalName()); + + // First leaf: + assertTokenType(START_ELEMENT, sr.next(), sr); + assertEquals("leaf1", sr.getLocalName()); + assertEquals(1, sr.getAttributeCount()); + assertEquals("attr1", sr.getAttributeLocalName(0)); + assertEquals("1", sr.getAttributeValue(0)); + assertEquals(URL_P1, sr.getAttributeNamespace(0)); + assertEquals(1, sr.getNamespaceCount()); + assertTokenType(END_ELEMENT, sr.next(), sr); + assertEquals(URL_P1, sr.getNamespaceURI(0)); + + // Second leaf: + assertTokenType(START_ELEMENT, sr.next(), sr); + assertEquals("leaf2", sr.getLocalName()); + assertEquals(1, sr.getAttributeCount()); + assertEquals("attr2", sr.getAttributeLocalName(0)); + assertEquals("2", sr.getAttributeValue(0)); + assertEquals(URL_P1, sr.getAttributeNamespace(0)); + assertEquals(1, sr.getNamespaceCount()); + assertTokenType(END_ELEMENT, sr.next(), sr); + assertEquals(URL_P1, sr.getNamespaceURI(0)); + + assertTokenType(END_ELEMENT, sr.next(), sr); + assertTokenType(END_DOCUMENT, sr.next(), sr); + } + + public void testSiblingNs2() + throws IOException, XMLStreamException + { + StringWriter strw = new StringWriter(); + XMLStreamWriter w = getRepairingWriter(strw); + + String ns1 = "urn://namespace1"; + String ns2 = "urn://namespace2"; + w.writeStartDocument(); + w.writeStartElement(ns1, "root"); + w.writeStartElement(ns2, "first"); + w.writeEndElement(); + w.writeStartElement(ns2, "second"); + w.writeEndElement(); + w.writeEndElement(); + w.writeEndDocument(); + w.close(); + + // And then let's parse and verify it all: + XMLStreamReader sr = constructNsStreamReader(strw.toString()); + assertTokenType(START_DOCUMENT, sr.getEventType(), sr); + + assertTokenType(START_ELEMENT, sr.next(), sr); + assertEquals("root", sr.getLocalName()); + // Can't assume anything about prefix assigned (if any), just ns uri + assertEquals(ns1, sr.getNamespaceURI()); + assertEquals(0, sr.getAttributeCount()); + + assertTokenType(START_ELEMENT, sr.next(), sr); + assertEquals("first", sr.getLocalName()); + assertEquals(ns2, sr.getNamespaceURI()); + assertEquals(0, sr.getAttributeCount()); + assertTokenType(END_ELEMENT, sr.next(), sr); + assertEquals("first", sr.getLocalName()); + + assertTokenType(START_ELEMENT, sr.next(), sr); + assertEquals("second", sr.getLocalName()); + assertEquals(ns2, sr.getNamespaceURI()); + assertEquals(0, sr.getAttributeCount()); + assertTokenType(END_ELEMENT, sr.next(), sr); + assertEquals("second", sr.getLocalName()); + assertTokenType(END_ELEMENT, sr.next(), sr); + assertEquals("root", sr.getLocalName()); + } + + /** + * Although repairing writers are allowed to output any number of + * namespace declarations they want to, let's still check that + * unnecessary ones are not output in simple cases. While doing + * that is not strictly an error, it seems reasonable fail the + * test, to let implementors know about sub-optimal behavior. + */ + public void testOptimalDefaultNsDecls() + throws IOException, XMLStreamException + { + StringWriter strw = new StringWriter(); + XMLStreamWriter w = getRepairingWriter(strw); + final String URL_P1 = "http://p1.org"; + + w.writeStartDocument(); + // Let's try to enforce using of the default ns by passing empty prefix + // (writer is not required to honor that request though) + w.writeStartElement("", "test", URL_P1); + w.writeStartElement("", "leaf", URL_P1); + w.writeEndElement(); + w.writeEndElement(); + w.writeEndDocument(); + w.close(); + +//System.err.println("DEBUG: doc = '"+strw+"'"); + // And then let's parse and verify it all: + XMLStreamReader sr = constructNsStreamReader(strw.toString()); + assertTokenType(START_DOCUMENT, sr.getEventType(), sr); + + // root element + assertTokenType(START_ELEMENT, sr.next(), sr); + assertEquals("test", sr.getLocalName()); + assertEquals(URL_P1, sr.getNamespaceURI()); + assertEquals(1, sr.getNamespaceCount()); + assertEquals(URL_P1, sr.getNamespaceURI(0)); + + // leaf: should be able to use parent's namespace decl + assertTokenType(START_ELEMENT, sr.next(), sr); + assertEquals("leaf", sr.getLocalName()); + assertEquals(URL_P1, sr.getNamespaceURI()); + assertEquals(0, sr.getNamespaceCount()); + + sr.close(); + } + + public void testOptimalNonDefaultNsDecls() + throws IOException, XMLStreamException + { + StringWriter strw = new StringWriter(); + XMLStreamWriter w = getRepairingWriter(strw); + final String URL_P1 = "http://p1.org"; + + w.writeStartDocument(); + w.writeStartElement(URL_P1, "test"); + w.writeStartElement(URL_P1, "leaf"); + w.writeEndElement(); + w.writeEndElement(); + w.writeEndDocument(); + w.close(); + + // And then let's parse and verify it all: + XMLStreamReader sr = constructNsStreamReader(strw.toString()); + assertTokenType(START_DOCUMENT, sr.getEventType(), sr); + + // root element + assertTokenType(START_ELEMENT, sr.next(), sr); + assertEquals("test", sr.getLocalName()); + assertEquals(URL_P1, sr.getNamespaceURI()); + assertEquals(1, sr.getNamespaceCount()); + assertEquals(URL_P1, sr.getNamespaceURI(0)); + + // leaf: should be able to use parent's namespace decl + assertTokenType(START_ELEMENT, sr.next(), sr); + assertEquals("leaf", sr.getLocalName()); + assertEquals(URL_P1, sr.getNamespaceURI()); + assertEquals(0, sr.getNamespaceCount()); + + sr.close(); + } +} diff -Nru libwoodstox-java-4.1.3/src/test/java/org/codehaus/stax/test/wstream/TestSimpleWriter.java libwoodstox-java-5.1.0/src/test/java/org/codehaus/stax/test/wstream/TestSimpleWriter.java --- libwoodstox-java-4.1.3/src/test/java/org/codehaus/stax/test/wstream/TestSimpleWriter.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/org/codehaus/stax/test/wstream/TestSimpleWriter.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,724 @@ +package org.codehaus.stax.test.wstream; + +import javax.xml.stream.*; + +import java.io.*; + +/** + * Set of unit tests for verifying operation of {@link XMLStreamWriter} + * in "non-repairing" mode. It also includes writer tests for things + * for which repair/non-repair modes should not matter (comments, PIs + * etc). + * + * @author Tatu Saloranta + */ +public class TestSimpleWriter + extends BaseWriterTest +{ + final String ISO_LATIN_ENCODING = "ISO-8859-1"; + + public void testProlog() + throws IOException, XMLStreamException + { + StringWriter strw = new StringWriter(); + XMLStreamWriter w = getNonRepairingWriter(strw); + + w.writeStartDocument(); + w.writeCharacters("\r\n "); + w.writeEmptyElement("test"); + w.writeCharacters(" \r"); + w.writeEndDocument(); + w.close(); + + /* And then let's parse and verify it all. But are we guaranteed + * to get SPACE? Let's not assume that + */ + XMLStreamReader sr = constructNsStreamReader(strw.toString(), true); + assertTokenType(START_DOCUMENT, sr.getEventType()); + + int type = sr.next(); + if (type != START_ELEMENT) { + assertTokenType(SPACE, type); + assertEquals("\n ", getAndVerifyText(sr)); + assertTokenType(START_ELEMENT, sr.next()); + } + assertEquals("test", sr.getLocalName()); + assertTokenType(END_ELEMENT, sr.next()); + assertEquals("test", sr.getLocalName()); + // Another SPACE? + type = sr.next(); + if (type != END_DOCUMENT) { + assertTokenType(SPACE, type); + assertEquals(" \n", getAndVerifyText(sr)); + assertTokenType(END_DOCUMENT, sr.next()); + } + } + + public void testCData() + throws IOException, XMLStreamException + { + StringWriter strw = new StringWriter(); + XMLStreamWriter w = getNonRepairingWriter(strw); + + final String CDATA_TEXT = "Let's test it with some ]] ]> data; s and && chars and all!"; + + w.writeStartDocument(); + w.writeStartElement("test"); + w.writeCData(CDATA_TEXT); + w.writeEndElement(); + w.writeEndDocument(); + w.close(); + + // And then let's parse and verify it all: + + XMLStreamReader sr = constructNsStreamReader(strw.toString(), true); + assertTokenType(START_DOCUMENT, sr.getEventType()); + assertTokenType(START_ELEMENT, sr.next()); + + // Now, parsers are allowed to report CHARACTERS or CDATA + int tt = sr.next(); + if (tt != CHARACTERS && tt != CDATA) { + assertTokenType(CDATA, tt); // to cause failure + } + assertFalse(sr.isWhiteSpace()); + assertEquals(CDATA_TEXT, getAndVerifyText(sr)); + assertTokenType(END_ELEMENT, sr.next()); + assertTokenType(END_DOCUMENT, sr.next()); + } + + public void testCharacters() + throws IOException, XMLStreamException + { + StringWriter strw = new StringWriter(); + XMLStreamWriter w = getNonRepairingWriter(strw); + + final String TEXT = "Ok; some content\nwith linefeeds and stuff (let's leave encoding as is though, no entities)\n"; + + w.writeStartDocument(); + w.writeStartElement("test"); + w.writeCharacters(TEXT); + w.writeStartElement("leaf"); + // Let's also test the other method... + char[] tmp = new char[TEXT.length() + 4]; + TEXT.getChars(0, TEXT.length(), tmp, 2); + w.writeCharacters(tmp, 2, TEXT.length()); + w.writeEndElement(); + w.writeEndElement(); + w.writeEndDocument(); + w.close(); + + // And then let's parse and verify it all: + + XMLStreamReader sr = constructNsStreamReader(strw.toString(), true); + assertTokenType(START_DOCUMENT, sr.getEventType()); + assertTokenType(START_ELEMENT, sr.next()); + assertTokenType(CHARACTERS, sr.next()); + assertFalse(sr.isWhiteSpace()); + assertEquals(TEXT, getAndVerifyText(sr)); + assertTokenType(START_ELEMENT, sr.next()); + assertTokenType(CHARACTERS, sr.next()); + assertFalse(sr.isWhiteSpace()); + assertEquals(TEXT, getAndVerifyText(sr)); + assertTokenType(END_ELEMENT, sr.next()); + assertTokenType(END_ELEMENT, sr.next()); + assertTokenType(END_DOCUMENT, sr.next()); + } + + public void testComment() + throws IOException, XMLStreamException + { + StringWriter strw = new StringWriter(); + XMLStreamWriter w = getNonRepairingWriter(strw); + final String COMMENT1 = "comments are cool"; + final String COMMENT2 = " some more\ncomments & other stuff"; + final String COMMENT3 = "Hah: "; + final String COMMENT4 = " - - - \t - - \t"; + + w.writeStartDocument(); + + // Let's start with a comment + w.writeComment(COMMENT1); + + w.writeStartElement("root"); + w.writeCharacters(" "); + w.writeComment(COMMENT2); + + w.writeStartElement("branch"); + w.writeEndElement(); + w.writeStartElement("branch"); + w.writeComment(COMMENT3); + w.writeEndElement(); + + w.writeEndElement(); + // and trailing comment too + w.writeComment(COMMENT4); + + w.writeEndDocument(); + w.close(); + + // And then let's parse and verify it all: + XMLStreamReader sr = constructNsStreamReader(strw.toString()); + assertTokenType(START_DOCUMENT, sr.getEventType()); + + // First, PI with just target: + assertTokenType(COMMENT, sr.next()); + assertEquals(COMMENT1, sr.getText()); + + // start root element: + assertTokenType(START_ELEMENT, sr.next()); + assertEquals("root", sr.getLocalName()); + + int tt = sr.next(); + if (tt != CHARACTERS && tt != SPACE) { + fail("Expected a single space (CHARACTERS or SPACE), got " + +tokenTypeDesc(tt)); + } + + assertTokenType(COMMENT, sr.next()); + assertEquals(COMMENT2, sr.getText()); + + // empty element ('branch') + assertTokenType(START_ELEMENT, sr.next()); + assertEquals("branch", sr.getLocalName()); + assertTokenType(END_ELEMENT, sr.next()); + assertEquals("branch", sr.getLocalName()); + + // another 'branch' element: + assertTokenType(START_ELEMENT, sr.next()); + assertEquals("branch", sr.getLocalName()); + assertTokenType(COMMENT, sr.next()); + assertEquals(COMMENT3, sr.getText()); + assertTokenType(END_ELEMENT, sr.next()); + assertEquals("branch", sr.getLocalName()); + + // closing root element + assertTokenType(END_ELEMENT, sr.next()); + assertEquals("root", sr.getLocalName()); + + // trailing (prolog) comment: + assertTokenType(COMMENT, sr.next()); + assertEquals(COMMENT4, sr.getText()); + + assertTokenType(END_DOCUMENT, sr.next()); + } + + public void testDTD() + throws IOException, XMLStreamException + { + // !!! TBI + } + + /** + * Unit test that tests how element writing works, including + * checks for the namespace output. + */ + public void testElements() + throws IOException, XMLStreamException + { + StringWriter strw = new StringWriter(); + XMLStreamWriter w = getNonRepairingWriter(strw); + final String URL_P1 = "http://p1.org"; + final String URL_P2 = "http://ns.p2.net/yeehaw.html"; + final String URL_DEF = "urn:default"; + + final String TEXT = " some text\n"; + + w.writeStartDocument(); + + w.setPrefix("p1", URL_P1); + w.writeStartElement("test"); + w.writeNamespace("p1", URL_P1); + + w.setDefaultNamespace(URL_DEF); + w.setPrefix("p2", URL_P2); + w.writeStartElement("", "branch", URL_DEF); + w.writeDefaultNamespace(URL_DEF); + w.writeNamespace("p2", URL_P2); + + // Ok, let's see that we can also clear out the def ns: + w.setDefaultNamespace(""); + w.writeStartElement("", "leaf", ""); + w.writeDefaultNamespace(""); + + w.writeCharacters(TEXT); + + w.writeEndElement(); // first leaf + + w.writeEmptyElement(URL_P1, "leaf"); // second leaf + + w.writeEndElement(); // branch + w.writeEndElement(); // root elem + w.writeEndDocument(); + w.close(); + + // And then let's parse and verify it all: + XMLStreamReader sr = constructNsStreamReader(strw.toString()); + assertTokenType(START_DOCUMENT, sr.getEventType()); + + // root element + assertTokenType(START_ELEMENT, sr.next()); + assertEquals("test", sr.getLocalName()); + assertNoPrefixOrNs(sr); + assertEquals(1, sr.getNamespaceCount()); + assertEquals("p1", sr.getNamespacePrefix(0)); + assertEquals(URL_P1, sr.getNamespaceURI(0)); + + // first branch: + assertTokenType(START_ELEMENT, sr.next()); + assertEquals("branch", sr.getLocalName()); + assertEquals(2, sr.getNamespaceCount()); + assertNoPrefix(sr); + assertEquals(URL_DEF, sr.getNamespaceURI()); + + // leaf + assertTokenType(START_ELEMENT, sr.next()); + assertEquals("leaf", sr.getLocalName()); + assertEquals(1, sr.getNamespaceCount()); + assertNoPrefix(sr); + + assertTokenType(CHARACTERS, sr.next()); + assertEquals(TEXT, getAllText(sr)); + // not: getAllText ^^^ moves cursor! + + assertTokenType(END_ELEMENT, sr.getEventType()); + assertEquals("leaf", sr.getLocalName()); + assertNoPrefixOrNs(sr); + + // another leaf: + assertTokenType(START_ELEMENT, sr.next()); + assertEquals("leaf", sr.getLocalName()); + assertEquals(0, sr.getNamespaceCount()); + assertEquals("p1", sr.getPrefix()); + assertEquals(URL_P1, sr.getNamespaceURI()); + + assertTokenType(END_ELEMENT, sr.next()); + assertEquals("leaf", sr.getLocalName()); + assertEquals("p1", sr.getPrefix()); + assertEquals(URL_P1, sr.getNamespaceURI()); + + // (close) branch + try { // catching exception to add more info to failure msg... + assertTokenType(END_ELEMENT, sr.next()); + } catch (XMLStreamException sex) { + fail("Failed when trying to match (input '"+strw+"'): "+sex); + } + assertEquals("branch", sr.getLocalName()); + assertNoPrefix(sr); + + // closing root element + assertTokenType(END_ELEMENT, sr.next()); + assertEquals("test", sr.getLocalName()); + assertNoPrefixOrNs(sr); + + assertTokenType(END_DOCUMENT, sr.next()); + } + + /** + * Unit tests for documents that just do not use namespaces (independent + * of whether namespace support is enabled for the writer or not) + */ + public void testNonNsElements() + throws IOException, XMLStreamException + { + StringWriter strw = new StringWriter(); + XMLStreamWriter w = getNonRepairingWriter(strw); + final String TEXT = "Just some text..."; + final String TEXT_SPACE = "\n "; + + w.writeStartDocument(); + + w.writeStartElement("doc"); + w.writeCharacters(TEXT); + + w.writeStartElement("branch"); + w.writeEndElement(); + w.writeCharacters(TEXT_SPACE); + w.writeStartElement("branch.2"); + w.writeCData(TEXT); + w.writeEndElement(); + w.writeEmptyElement("_empty"); + + w.writeEndElement(); + w.writeEndDocument(); + w.close(); + + // And then let's parse and verify it all: + XMLStreamReader sr = constructNsStreamReader(strw.toString()); + assertTokenType(START_DOCUMENT, sr.getEventType()); + + // opening doc element + assertTokenType(START_ELEMENT, sr.next()); + assertEquals("doc", sr.getLocalName()); + assertNoPrefixOrNs(sr); + + assertTokenType(CHARACTERS, sr.next()); + assertEquals(TEXT, getAllText(sr)); + // not: getAllText ^^^ moves cursor! + + // branch elements: + assertTokenType(START_ELEMENT, sr.getEventType()); + assertEquals("branch", sr.getLocalName()); + assertNoPrefixOrNs(sr); + assertTokenType(END_ELEMENT, sr.next()); + assertEquals("branch", sr.getLocalName()); + assertNoPrefixOrNs(sr); + + assertTokenType(CHARACTERS, sr.next()); + assertEquals(TEXT_SPACE, getAllText(sr)); + + assertTokenType(START_ELEMENT, sr.getEventType()); + assertEquals("branch.2", sr.getLocalName()); + assertNoPrefixOrNs(sr); + assertTextualTokenType(sr.next()); + assertEquals(TEXT, getAllText(sr)); + assertTokenType(END_ELEMENT, sr.getEventType()); + assertEquals("branch.2", sr.getLocalName()); + assertNoPrefixOrNs(sr); + + assertTokenType(START_ELEMENT, sr.next()); + assertEquals("_empty", sr.getLocalName()); + assertNoPrefixOrNs(sr); + assertTokenType(END_ELEMENT, sr.next()); + assertEquals("_empty", sr.getLocalName()); + assertNoPrefixOrNs(sr); + + // closing doc element + try { + assertTokenType(END_ELEMENT, sr.next()); + } catch (XMLStreamException sex) { + fail("Failed when trying to match (input '"+strw+"'): "+sex); + } + assertEquals("doc", sr.getLocalName()); + assertNoPrefixOrNs(sr); + + assertTokenType(END_DOCUMENT, sr.next()); + } + + public void testEmptyElements() + throws IOException, XMLStreamException + { + StringWriter strw = new StringWriter(); + XMLStreamWriter w = getNonRepairingWriter(strw); + + w.writeStartDocument(); + + w.writeStartElement("root"); + w.writeStartElement("branch"); + w.writeEmptyElement("leaf"); + + w.writeEndElement(); // branch + w.writeComment("comment"); // should be at same level as branch + w.writeEndElement(); // root elem + w.writeEndDocument(); + w.close(); + + // And then let's parse and verify it all: + XMLStreamReader sr = constructNsStreamReader(strw.toString()); + assertTokenType(START_DOCUMENT, sr.getEventType()); + + // root element + assertTokenType(START_ELEMENT, sr.next()); + assertEquals("root", sr.getLocalName()); + // branch: + assertTokenType(START_ELEMENT, sr.next()); + assertEquals("branch", sr.getLocalName()); + // leaf + assertTokenType(START_ELEMENT, sr.next()); + assertEquals("leaf", sr.getLocalName()); + assertTokenType(END_ELEMENT, sr.next()); + assertEquals("leaf", sr.getLocalName()); + assertTokenType(END_ELEMENT, sr.next()); + assertEquals("branch", sr.getLocalName()); + + assertTokenType(COMMENT, sr.next()); + assertEquals("comment", getAndVerifyText(sr)); + + assertTokenType(END_ELEMENT, sr.next()); + assertEquals("root", sr.getLocalName()); + + assertTokenType(END_DOCUMENT, sr.next()); + } + + public void testEntityRef() + throws IOException, XMLStreamException + { + // !!! TBI + } + + public void testProcInstr() + throws IOException, XMLStreamException + { + StringWriter strw = new StringWriter(); + XMLStreamWriter w = getNonRepairingWriter(strw); + final String LONG_DATA = "content & spaces ... \t "; + final String LONG_DATA2 = "? >? ? > "; + + w.writeStartDocument(); + + // Let's start with a proc instr: + w.writeProcessingInstruction("my_target"); + + w.writeStartElement("root"); + w.writeCharacters("x"); + w.writeProcessingInstruction("target", "data"); + + w.writeStartElement("branch"); + w.writeEndElement(); + w.writeStartElement("branch"); + w.writeProcessingInstruction("t", LONG_DATA); + w.writeEndElement(); + + w.writeEndElement(); + // and trailing proc instr too + w.writeProcessingInstruction("xxx", LONG_DATA2); + + w.writeEndDocument(); + w.close(); + + // And then let's parse and verify it all: + XMLStreamReader sr = constructNsStreamReader(strw.toString()); + assertTokenType(START_DOCUMENT, sr.getEventType()); + + // First, PI with just target: + assertTokenType(PROCESSING_INSTRUCTION, sr.next()); + assertEquals("my_target", sr.getPITarget()); + String data = sr.getPIData(); + if (data != null && data.length() > 0) { + fail("Expected empty (or null) data; got '"+data+"'"); + } + // start root element: + assertTokenType(START_ELEMENT, sr.next()); + assertEquals("root", sr.getLocalName()); + + assertTokenType(CHARACTERS, sr.next()); + assertEquals("x", sr.getText()); + + // 'full' PI: + assertTokenType(PROCESSING_INSTRUCTION, sr.next()); + assertEquals("target", sr.getPITarget()); + assertEquals("data", sr.getPIData()); + + // empty element ('branch') + assertTokenType(START_ELEMENT, sr.next()); + assertEquals("branch", sr.getLocalName()); + assertTokenType(END_ELEMENT, sr.next()); + assertEquals("branch", sr.getLocalName()); + + // another 'branch' element: + assertTokenType(START_ELEMENT, sr.next()); + assertEquals("branch", sr.getLocalName()); + assertTokenType(PROCESSING_INSTRUCTION, sr.next()); + assertEquals("t", sr.getPITarget()); + assertEquals(LONG_DATA, sr.getPIData()); + assertTokenType(END_ELEMENT, sr.next()); + assertEquals("branch", sr.getLocalName()); + + // closing root element + assertTokenType(END_ELEMENT, sr.next()); + assertEquals("root", sr.getLocalName()); + + // trailing (prolog) PI: + assertTokenType(PROCESSING_INSTRUCTION, sr.next()); + assertEquals("xxx", sr.getPITarget()); + assertEquals(LONG_DATA2, sr.getPIData()); + + assertTokenType(END_DOCUMENT, sr.next()); + } + + + public void testXmlDeclImplicit() + throws IOException, XMLStreamException + { + doTextXmlDecl(3); + } + + public void testXmlDecl0args() + throws IOException, XMLStreamException + { + doTextXmlDecl(0); + } + + public void testXmlDecl1arg() + throws IOException, XMLStreamException + { + doTextXmlDecl(1); + } + + public void testXmlDecl2args() + throws IOException, XMLStreamException + { + doTextXmlDecl(2); + } + + /** + * This simple unit tests checks handling of namespace prefix + * information in non-repairing mode, wrt explictly defined + * bindings. + */ + public void testExplicitNsPrefixes() + throws XMLStreamException + { + XMLStreamWriter writer = getNonRepairingWriter(new StringWriter()); + final String NS1 = "http://foo.com"; + final String NS2 = "http://bar.com"; + + writer.writeStartDocument(); + writer.writeStartElement("root"); + + // First, explicit binding: + writer.writeStartElement("branch1"); + writer.setPrefix("ns", NS1); + writer.setDefaultNamespace(NS2); + assertEquals("ns", writer.getPrefix(NS1)); + assertEquals("", writer.getPrefix(NS2)); + // and just for fun, let's check they are not mixed up + assertNull(writer.getPrefix("ns")); + assertNull(writer.getPrefix("nosuchPrefix")); + writer.writeEndElement(); + + // these should be element scoped, and not exist any more + assertNull(writer.getPrefix(NS1)); + assertNull(writer.getPrefix(NS2)); + + // Next: should we check NamespaceContext? + /* For now, let's not: it's unclear if that should + * be unmodified "root" context, or live version + */ + + writer.writeEndElement(); // root + writer.writeEndDocument(); + } + + /** + * This simple unit tests checks handling of namespace prefix + * information in non-repairing mode, wrt implied + * bindings, generated by namespace output method. + * Since information in 1.0 + * specs and associated Javadocs are sparse, these are based + * on consensus on stax_builders list, as well as information + * from Stax TCK unit tests. + */ + public void testImplicitNsPrefixes() + throws XMLStreamException + { + XMLStreamWriter writer = getNonRepairingWriter(new StringWriter()); + final String NS1 = "http://foo.com"; + final String NS2 = "http://bar.com"; + + writer.writeStartDocument(); + writer.writeStartElement("root"); + + /* And then, implicit binding(s). It is not obvious + * whether such should be generated, from the specs, + * but TCK indicates they should. + */ + writer.writeNamespace("ns", NS2); + writer.writeDefaultNamespace(NS1); + + assertEquals("", writer.getPrefix(NS1)); + assertEquals("ns", writer.getPrefix(NS2)); + + /* Not quite sure if these should/need be scoped? + * Probably? + */ + writer.writeEndElement(); + assertNull(writer.getPrefix(NS1)); + assertNull(writer.getPrefix(NS2)); + + writer.writeEndDocument(); + } + + /* + /////////////////////////////////////////////////////////// + // Private methods + /////////////////////////////////////////////////////////// + */ + + private void doTextXmlDecl(int i) + throws IOException, XMLStreamException + { + /* 4 modes: writeStartDocument with 0 args, 1 arg, 2 args, + * and without a call + */ + StringWriter strw = new StringWriter(); + XMLStreamWriter w = getNonRepairingWriter(strw); + + switch (i) { + case 0: + w.writeStartDocument(); + break; + case 1: + /* Might well be ok to output other than 1.0, but the + * reader may choke on others (like 1.1)? + */ + w.writeStartDocument("1.0"); + break; + case 2: + w.writeStartDocument(ISO_LATIN_ENCODING, "1.0"); + break; + case 3: + // No output (shouldn't print out xml decl) + break; + } + w.writeEmptyElement("root"); + w.writeEndDocument(); + w.close(); + + XMLStreamReader sr = constructNsStreamReader(strw.toString()); + assertTokenType(START_DOCUMENT, sr.getEventType()); + + // correct version? + if (i == 3) { + // Shouldn't have output anything: + String ver = sr.getVersion(); + if (ver != null && ver.length() > 0) { + fail("Non-null/empty version ('"+ver+"') when no START_DOCUMENT written explicitly"); + } + } else { + assertEquals("1.0", sr.getVersion()); + } + + // encoding? + String enc = sr.getCharacterEncodingScheme(); + switch (i) { + case 0: + /* Not sure why the encoding has to default to utf-8... would + * make sense to rather leave it out + */ + /* quick note: the proper usage (as per xml specs) would be to + * use UTF-8; Stax 1.0 mentions "utf-8", so let's accept + * both for now (but let's not accept mixed cases) + */ + if (!"utf-8".equals(enc) && !"UTF-8".equals(enc)) { + fail("Expected either 'UTF-8' (xml specs) or 'utf-8' (stax specs) as the encoding output with no-arg 'writeStartDocument()' call (result doc = '"+strw.toString()+"')"); + } + break; + case 1: + /* Interestingly enough, API comments do not indicate an encoding + * default for 1-arg method! + */ + assertNull(enc); + break; + case 2: + assertEquals(ISO_LATIN_ENCODING, enc); + break; + case 3: + assertNull(enc); + break; + } + + // What should sr.getEncoding() return? null? can't check... + + /* but stand-alone we can check; specifically: + */ + assertFalse("XMLStreamReader.standalonSet() should return false if pseudo-attr not found", + sr.standaloneSet()); + + /* now... it's too bad there's no way to explicitly specify + * stand-alone value... so probably can not really test the + * other method + */ + //assertFalse("XMLStreamReader.isStandalone() should return false if pseudo-attr not found", sr.isStandalone()); + sr.close(); + } +} diff -Nru libwoodstox-java-4.1.3/src/test/java/org/codehaus/stax/test/wstream/TestWriterClosing.java libwoodstox-java-5.1.0/src/test/java/org/codehaus/stax/test/wstream/TestWriterClosing.java --- libwoodstox-java-4.1.3/src/test/java/org/codehaus/stax/test/wstream/TestWriterClosing.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/org/codehaus/stax/test/wstream/TestWriterClosing.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,42 @@ +package org.codehaus.stax.test.wstream; + +import javax.xml.stream.*; + +import java.io.*; + +/** + * Simple unit tests for ensuring that the Stax implementation does not + * close the underlying output stream when XMLStreamWriter.close() is + * called. + * + * @author Tatu Saloranta + * @author Matt Solnit + */ +public class TestWriterClosing + extends BaseWriterTest +{ + public void testClosing() + throws IOException, XMLStreamException + { + File f = File.createTempFile("wstxtest", null); + f.deleteOnExit(); + OutputStream stream = new FileOutputStream(f); + OutputStreamWriter strw = new OutputStreamWriter(stream, "UTF-8"); + XMLStreamWriter xsw = getNonRepairingWriter(strw); + xsw.writeStartDocument(); + xsw.writeStartElement("root"); + xsw.writeEndElement(); + xsw.writeEndDocument(); + xsw.close(); + + /* If impl called stream.close() above, we'll get an IOEXception + * here... + */ + try { + strw.write(""); + } catch (IOException ioe) { + fail("Should not have gotten IOException, impl. probably called stream.close(): "+ioe); + } + stream.close(); + } +} diff -Nru libwoodstox-java-4.1.3/src/test/java/org/codehaus/stax2/ri/TestStax2ReaderAdapter.java libwoodstox-java-5.1.0/src/test/java/org/codehaus/stax2/ri/TestStax2ReaderAdapter.java --- libwoodstox-java-4.1.3/src/test/java/org/codehaus/stax2/ri/TestStax2ReaderAdapter.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/org/codehaus/stax2/ri/TestStax2ReaderAdapter.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,141 @@ +package org.codehaus.stax2.ri; + +import java.io.*; + +import javax.xml.stream.*; + +import stax2.BaseStax2Test; + +/** + * @author tsaloranta + * + * @since 4.1 + */ +public class TestStax2ReaderAdapter extends BaseStax2Test +{ + public void testSimple() throws Exception + { + final String XML = "xyzabc"; + XMLInputFactory f = getInputFactory(); + XMLStreamReader reader1 = f.createXMLStreamReader(new StringReader(XML)); + Stax2ReaderAdapter adapter = new Stax2ReaderAdapter(reader1); + assertTokenType(START_DOCUMENT, adapter.getEventType()); + assertEquals(0, adapter.getDepth()); + + assertTokenType(START_ELEMENT, adapter.next()); + assertEquals("root", adapter.getLocalName()); + assertEquals(1, adapter.getDepth()); + + assertTokenType(START_ELEMENT, adapter.next()); + assertEquals(2, adapter.getDepth()); + assertEquals("a", adapter.getLocalName()); + assertTokenType(CHARACTERS, adapter.next()); + assertEquals(2, adapter.getDepth()); + assertEquals("xyz", adapter.getText()); + assertTokenType(END_ELEMENT, adapter.next()); + assertEquals(2, adapter.getDepth()); + assertEquals("a", adapter.getLocalName()); + + assertTokenType(START_ELEMENT, adapter.next()); + assertEquals(2, adapter.getDepth()); + assertEquals("b", adapter.getLocalName()); + assertTokenType(CHARACTERS, adapter.next()); + assertEquals(2, adapter.getDepth()); + assertEquals("abc", adapter.getText()); + assertTokenType(END_ELEMENT, adapter.next()); + assertEquals(2, adapter.getDepth()); + assertEquals("b", adapter.getLocalName()); + + assertTokenType(END_ELEMENT, adapter.next()); + assertEquals("root", adapter.getLocalName()); + assertEquals(1, adapter.getDepth()); + + assertTokenType(END_DOCUMENT, adapter.next()); + assertEquals(0, adapter.getDepth()); + } + + public void testSimpleWithTypedText() throws Exception + { + final String XML = "xyzabc"; + XMLInputFactory f = getInputFactory(); + XMLStreamReader reader1 = f.createXMLStreamReader(new StringReader(XML)); + Stax2ReaderAdapter adapter = new Stax2ReaderAdapter(reader1); + assertTokenType(START_DOCUMENT, adapter.getEventType()); + assertEquals(0, adapter.getDepth()); + + assertTokenType(START_ELEMENT, adapter.next()); + assertEquals("root", adapter.getLocalName()); + assertEquals(1, adapter.getDepth()); + + assertTokenType(START_ELEMENT, adapter.next()); + assertEquals(2, adapter.getDepth()); + assertEquals("a", adapter.getLocalName()); + assertEquals("xyz", adapter.getElementText()); + assertTokenType(END_ELEMENT, adapter.getEventType()); + assertEquals(2, adapter.getDepth()); + assertEquals("a", adapter.getLocalName()); + + assertTokenType(START_ELEMENT, adapter.next()); + assertEquals(2, adapter.getDepth()); + assertEquals("b", adapter.getLocalName()); + assertEquals("abc", adapter.getElementText()); + assertTokenType(END_ELEMENT, adapter.getEventType()); + assertEquals(2, adapter.getDepth()); + assertEquals("b", adapter.getLocalName()); + + assertTokenType(END_ELEMENT, adapter.next()); + assertEquals(1, adapter.getDepth()); + assertEquals("root", adapter.getLocalName()); + + assertTokenType(END_DOCUMENT, adapter.next()); + assertEquals(0, adapter.getDepth()); + } + + /** + * Test actually copied from 'stax2.stream.TestXMLStreamReader2' + */ + public void testWithDepthAndStuff() throws Exception + { + final String XML = "xxx"; + XMLInputFactory f = getInputFactory(); + XMLStreamReader reader1 = f.createXMLStreamReader(new StringReader(XML)); + Stax2ReaderAdapter sr = new Stax2ReaderAdapter(reader1); + + assertTokenType(START_DOCUMENT, sr.getEventType()); + assertEquals(0, sr.getDepth()); + assertFalse(sr.isEmptyElement()); + + assertTokenType(START_ELEMENT, sr.next()); + assertEquals("root", sr.getLocalName()); + assertEquals(1, sr.getDepth()); + assertFalse(sr.isEmptyElement()); + + assertTokenType(START_ELEMENT, sr.next()); + assertEquals("child", sr.getLocalName()); + assertEquals(2, sr.getDepth()); + + assertTokenType(END_ELEMENT, sr.next()); + assertEquals("child", sr.getLocalName()); + assertEquals(2, sr.getDepth()); + + assertTokenType(START_ELEMENT, sr.next()); + assertEquals("child2", sr.getLocalName()); + assertEquals(2, sr.getDepth()); + + assertTokenType(CHARACTERS, sr.next()); + assertEquals("xxx", getAndVerifyText(sr)); + assertEquals(2, sr.getDepth()); + + assertTokenType(END_ELEMENT, sr.next()); + assertEquals("child2", sr.getLocalName()); + assertEquals(2, sr.getDepth()); + + assertTokenType(END_ELEMENT, sr.next()); + assertEquals("root", sr.getLocalName()); + assertEquals(1, sr.getDepth()); + + assertTokenType(END_DOCUMENT, sr.next()); + assertEquals(0, sr.getDepth()); + } + +} diff -Nru libwoodstox-java-4.1.3/src/test/java/stax2/BaseStax2Test.java libwoodstox-java-5.1.0/src/test/java/stax2/BaseStax2Test.java --- libwoodstox-java-4.1.3/src/test/java/stax2/BaseStax2Test.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/stax2/BaseStax2Test.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,703 @@ +package stax2; + +import java.io.*; +import java.util.HashMap; + +import junit.framework.TestCase; + +import javax.xml.stream.*; +import javax.xml.stream.events.XMLEvent; + +import org.codehaus.stax2.*; +import org.codehaus.stax2.evt.*; + +import org.codehaus.stax2.ri.Stax2ReaderAdapter; + +/** + * Base unit test class to be inherited by all unit tests that test + * StAX2 API compatibility. + */ +public abstract class BaseStax2Test + extends TestCase + implements XMLStreamConstants +{ + /** + * Value that should be reported by stax(2) impl to denote "no prefix" + * for elements + */ + final static String ELEM_NO_PREFIX = ""; + + /** + * Value that should be reported by stax(2) impl to denote "no prefix" + * for attributes + */ + final static String ATTR_NO_PREFIX = ""; + + final static HashMap mTokenTypes = new HashMap(); + static { + mTokenTypes.put(new Integer(START_ELEMENT), "START_ELEMENT"); + mTokenTypes.put(new Integer(END_ELEMENT), "END_ELEMENT"); + mTokenTypes.put(new Integer(START_DOCUMENT), "START_DOCUMENT"); + mTokenTypes.put(new Integer(END_DOCUMENT), "END_DOCUMENT"); + mTokenTypes.put(new Integer(CHARACTERS), "CHARACTERS"); + mTokenTypes.put(new Integer(CDATA), "CDATA"); + mTokenTypes.put(new Integer(COMMENT), "COMMENT"); + mTokenTypes.put(new Integer(PROCESSING_INSTRUCTION), "PROCESSING_INSTRUCTION"); + mTokenTypes.put(new Integer(DTD), "DTD"); + mTokenTypes.put(new Integer(SPACE), "SPACE"); + mTokenTypes.put(new Integer(ENTITY_REFERENCE), "ENTITY_REFERENCE"); + } + + /** + * Switch that can be turned on to verify to display ALL exact Exceptions + * thrown when Exceptions are expected. This is sometimes necessary + * when debugging, since it's impossible to automatically verify + * that Exception is exactly the right one, since there is no + * strict Exception type hierarchy for StAX problems. + *

+ * Note: Not made 'final static', so that compiler won't inline + * it. Makes possible to do partial re-compilations. + * Note: Since it's only used as the default value, sub-classes + * can separately turn it off as necessary + */ + //protected static boolean DEF_PRINT_EXP_EXCEPTION = true; + protected static boolean DEF_PRINT_EXP_EXCEPTION = false; + + protected boolean PRINT_EXP_EXCEPTION = DEF_PRINT_EXP_EXCEPTION; + + /* + /////////////////////////////////////////////////////////// + // Lazy-loaded thingies + /////////////////////////////////////////////////////////// + */ + + XMLInputFactory2 mInputFactory = null; + XMLOutputFactory2 mOutputFactory = null; + XMLEventFactory2 mEventFactory = null; + + /* + /////////////////////////////////////////////////////////// + // Factory methods + /////////////////////////////////////////////////////////// + */ + + protected XMLInputFactory2 getInputFactory() + { + if (mInputFactory == null) { + /* Shouldn't try to set these here, if these tests are + * to be reusable. Rather, junit (ant) task should + * define system properties if necessary. + */ + //System.setProperty("javax.xml.stream.XMLInputFactory", "..."); + mInputFactory = getNewInputFactory(); + } + return mInputFactory; + } + + protected XMLStreamReader2 constructNsStreamReader(String content, boolean coal) + throws XMLStreamException + { + XMLInputFactory f = getInputFactory(); + setNamespaceAware(f, true); + setCoalescing(f, coal); + return (XMLStreamReader2) f.createXMLStreamReader(new StringReader(content)); + } + + protected XMLStreamReader2 constructNsStreamReader(InputStream in, boolean coal) + throws XMLStreamException + { + XMLInputFactory f = getInputFactory(); + setNamespaceAware(f, true); + setCoalescing(f, coal); + return (XMLStreamReader2) f.createXMLStreamReader(in); + } + + protected XMLEventFactory2 getEventFactory() + { + if (mEventFactory == null) { + /* Shouldn't try to set these here, if these tests are + * to be reusable. Rather, junit (ant) task should + * define system properties if necessary. + */ + //System.setProperty("javax.xml.stream.XMLEventFactory", "..."); + mEventFactory = (XMLEventFactory2) XMLEventFactory.newInstance(); + } + return mEventFactory; + } + + protected static XMLInputFactory2 getNewInputFactory() + { + return (XMLInputFactory2) XMLInputFactory.newInstance(); + } + + protected XMLOutputFactory2 getOutputFactory() + { + if (mOutputFactory == null) { + //System.setProperty("javax.xml.stream.XMLOutputFactory", "..."); + mOutputFactory = getNewOutputFactory(); + } + return mOutputFactory; + } + + protected static XMLOutputFactory2 getNewOutputFactory() + { + return (XMLOutputFactory2) XMLOutputFactory.newInstance(); + } + + protected XMLEventFactory getNewEventFactory() { + return XMLEventFactory.newFactory(); + } + + protected static XMLStreamReader2 constructStreamReader(XMLInputFactory f, String content) + throws XMLStreamException + { + return (XMLStreamReader2) f.createXMLStreamReader(new StringReader(content)); + } + + protected static XMLStreamReader2 constructStreamReader(XMLInputFactory f, byte[] data) + throws XMLStreamException + { + return (XMLStreamReader2) f.createXMLStreamReader(new ByteArrayInputStream(data)); + } + + @SuppressWarnings({ "deprecation", "resource" }) + protected static XMLStreamReader2 constructStreamReaderForFile(XMLInputFactory f, String filename) + throws IOException, XMLStreamException + { + File inf = new File(filename); + XMLStreamReader sr = f.createXMLStreamReader(inf.toURL().toString(), + new FileReader(inf)); + assertEquals(sr.getEventType(), START_DOCUMENT); + return (XMLStreamReader2) sr; + } + + protected static XMLEventReader2 constructEventReader(XMLInputFactory f, String content) + throws XMLStreamException + { + return (XMLEventReader2) f.createXMLEventReader(new StringReader(content)); + } + + protected XMLStreamReader2 constructNonNsStreamReader(String content, boolean coal) + throws XMLStreamException + { + XMLInputFactory f = getInputFactory(); + setNamespaceAware(f, false); + setCoalescing(f, coal); + return (XMLStreamReader2) f.createXMLStreamReader(new StringReader(content)); + } + + /** + * Method to force constructing a wrapper for given stream reader. + * Have to use this method to work around natural resistance by + * the wrapper to apply itself on what it considered "unnecessary" + * target. + */ + protected XMLStreamReader2 wrapWithAdapter(XMLStreamReader sr) + { + return new ForcedAdapter(sr); + } + + /* + /////////////////////////////////////////////////////////// + // Configuring input factory + /////////////////////////////////////////////////////////// + */ + + protected static boolean setNamespaceAware(XMLInputFactory f, boolean state) + throws XMLStreamException + { + /* Let's not assert, but see if it sticks. Some implementations + * might choose to silently ignore setting, at least for 'false'? + */ + try { + f.setProperty(XMLInputFactory.IS_NAMESPACE_AWARE, state ? Boolean.TRUE : Boolean.FALSE); + return (isNamespaceAware(f) == state); + } catch (IllegalArgumentException e) { + /* Let's assume, then, that the property (or specific value for it) + * is NOT supported... + */ + return false; + } + } + + protected static boolean isNamespaceAware(XMLInputFactory f) + throws XMLStreamException + { + return ((Boolean) f.getProperty(XMLInputFactory.IS_NAMESPACE_AWARE)).booleanValue(); + } + + protected static void setCoalescing(XMLInputFactory f, boolean state) + throws XMLStreamException + { + f.setProperty(XMLInputFactory.IS_COALESCING, Boolean.valueOf(state)); + } + + protected static void setValidating(XMLInputFactory f, boolean state) + throws XMLStreamException + { + f.setProperty(XMLInputFactory.IS_VALIDATING, Boolean.valueOf(state)); + } + + protected static boolean setSupportDTD(XMLInputFactory f, boolean state) + throws XMLStreamException + { + try { + f.setProperty(XMLInputFactory.SUPPORT_DTD, Boolean.valueOf(state)); + return (willSupportDTD(f) == state); + } catch (IllegalArgumentException e) { + // Let's assume that the property (or specific value) is NOT supported... + return false; + } + } + + protected static boolean willSupportDTD(XMLInputFactory f) + throws XMLStreamException + { + return ((Boolean) f.getProperty(XMLInputFactory.SUPPORT_DTD)).booleanValue(); + } + + protected static void setReplaceEntities(XMLInputFactory f, boolean state) + throws XMLStreamException + { + f.setProperty(XMLInputFactory.IS_REPLACING_ENTITY_REFERENCES, + state ? Boolean.TRUE : Boolean.FALSE); + } + + protected static void setSupportExternalEntities(XMLInputFactory f, boolean state) + throws XMLStreamException + { + f.setProperty(XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES, + state ? Boolean.TRUE : Boolean.FALSE); + } + + protected static void setLazyParsing(XMLInputFactory f, boolean state) + throws XMLStreamException + { + f.setProperty(XMLInputFactory2.P_LAZY_PARSING, + state ? Boolean.TRUE : Boolean.FALSE); + } + + /* + /////////////////////////////////////////////////////////// + // Configuring output factory + /////////////////////////////////////////////////////////// + */ + + protected static void setRepairing(XMLOutputFactory f, boolean state) + { + f.setProperty(XMLOutputFactory.IS_REPAIRING_NAMESPACES, + Boolean.valueOf(state)); + } + + protected static boolean setNamespaceAware(XMLOutputFactory f, boolean state) + throws XMLStreamException + { + /* Let's not assert, but see if it sticks. Some implementations + * might choose to silently ignore setting, at least for 'false'? + */ + try { + f.setProperty(XMLStreamProperties.XSP_NAMESPACE_AWARE, state ? Boolean.TRUE : Boolean.FALSE); + return (isNamespaceAware(f) == state); + } catch (IllegalArgumentException e) { + /* Let's assume, then, that the property (or specific value for it) + * is NOT supported... + */ + return false; + } + } + + protected static boolean isNamespaceAware(XMLOutputFactory f) + throws XMLStreamException + { + return ((Boolean) f.getProperty(XMLStreamProperties.XSP_NAMESPACE_AWARE)).booleanValue(); + } + + /* + /////////////////////////////////////////////////////////// + // Higher-level test methods + /////////////////////////////////////////////////////////// + */ + + /** + * Method that will iterate through contents of an XML document + * using specified stream reader; will also access some of data + * to make sure reader reads most of lazy-loadable data. + * Method is usually called to try to get an exception for invalid + * content. + * + * @return Dummy value calculated on contents; used to make sure + * no dead code is eliminated + */ + protected int streamThrough(XMLStreamReader sr) + throws XMLStreamException + { + int result = 0; + + while (sr.hasNext()) { + int type = sr.next(); + result += type; + if (sr.hasText()) { + /* will also do basic verification for text content, to + * see that all text accessor methods return same content + */ + result += getAndVerifyText(sr).hashCode(); + } + if (sr.hasName()) { + result += sr.getName().hashCode(); + } + } + + return result; + } + + protected int streamThroughFailing(XMLInputFactory f, String contents, + String msg) + throws XMLStreamException + { + int result = 0; + try { + XMLStreamReader sr = constructStreamReader(f, contents); + result = streamThrough(sr); + } catch (XMLStreamException ex) { // good + if (PRINT_EXP_EXCEPTION) { + System.out.println("Expected failure: '"+ex.getMessage()+"' " + +"(matching message: '"+msg+"')"); + } + return 0; + } catch (RuntimeException ex2) { // ok + if (PRINT_EXP_EXCEPTION) { + System.out.println("Expected failure: '"+ex2.getMessage()+"' " + +"(matching message: '"+msg+"')"); + } + return 0; + } catch (Throwable t) { // not so good + fail("Expected an XMLStreamException or RuntimeException for "+msg + +", got: "+t); + } + + fail("Expected an exception for "+msg); + return result; // never gets here + } + + protected int streamThroughFailing(XMLStreamReader sr, String msg) + throws XMLStreamException + { + int result = 0; + try { + result = streamThrough(sr); + } catch (XMLStreamException ex) { // good + if (PRINT_EXP_EXCEPTION) { + System.out.println("Expected failure: '"+ex.getMessage()+"' " + +"(matching message: '"+msg+"')"); + } + return 0; + } catch (RuntimeException ex2) { // ok + if (PRINT_EXP_EXCEPTION) { + System.out.println("Expected failure: '"+ex2.getMessage()+"' " + +"(matching message: '"+msg+"')"); + } + return 0; + } catch (Throwable t) { // not so good + fail("Expected an XMLStreamException or RuntimeException for "+msg + +", got: "+t); + } + + fail("Expected an exception for "+msg); + return result; // never gets here + } + + /* + /////////////////////////////////////////////////////////// + // Assertions + /////////////////////////////////////////////////////////// + */ + + protected static String tokenTypeDesc(int tt) + { + String desc = mTokenTypes.get(new Integer(tt)); + return (desc == null) ? ("["+tt+"]") : desc; + } + + protected static void assertTokenType(int expType, XMLEvent evt) + { + assertTokenType(expType, evt.getEventType()); + } + + protected static void assertTokenType(int expType, int actType) + { + if (expType != actType) { + String expStr = tokenTypeDesc(expType); + String actStr = tokenTypeDesc(actType); + + if (expStr == null) { + expStr = ""+expType; + } + if (actStr == null) { + actStr = ""+actType; + } + fail("Expected token "+expStr+"; got "+actStr+"."); + } + } + + /** + * Helper assertion that assert that the String is either null or + * empty (""). + */ + protected static void assertNullOrEmpty(String str) + { + if (str != null && str.length() > 0) { + fail("Expected String to be empty or null; was '"+str+"' (length " + +str.length()+")"); + } + } + + protected static void assertNotNullOrEmpty(String str) + { + if (str == null || str.length() == 0) { + fail("Expected String to be non-empty; got " + +((str == null) ? "NULL" : "\"\"")); + } + } + + /** + * Method that can be used to verify that the current element + * pointed to by the stream reader has no prefix. + */ + protected static void assertNoElemPrefix(XMLStreamReader sr) + throws XMLStreamException + { + String prefix = sr.getPrefix(); + if (prefix != ELEM_NO_PREFIX) { + fail("Element that does not have a prefix should be indicated with <"+ELEM_NO_PREFIX+">, not <"+prefix+">"); + } + } + + /** + * Helper method for ensuring that the given return value for + * attribute prefix accessor has returned a value that + * represents "no prefix" value. + *

+ * Current thinking (early 2008) is that empty string is the + * expected value here. + */ + protected static void assertNoAttrPrefix(String attrPrefix) + throws XMLStreamException + { + if (attrPrefix != ATTR_NO_PREFIX) { + fail("Attribute that does not have a prefix should be indicated with <"+ATTR_NO_PREFIX+">, not <"+attrPrefix+">"); + } + } + + /** + * Method that can be used to verify that the current element + * pointed to by the stream reader does not belong to a namespace. + */ + protected static void assertElemNotInNamespace(XMLStreamReader sr) + throws XMLStreamException + { + String uri = sr.getNamespaceURI(); + if (uri == null) { + fail("Excepted empty String to indicate \"no namespace\": got null"); + } else if (uri.length() != 0) { + fail("Excepted no (null) namespace URI: got '"+uri+"'"); + } + } + + protected static void assertNoAttrNamespace(String attrNsURI) + throws XMLStreamException + { + if (attrNsURI == null) { + fail("Expected empty String to indicate \"no namespace\" (for attribute): got null"); + } else if (attrNsURI.length() != 0) { + fail("Expected empty String to indicate \"no namespace\" (for attribute): got '"+attrNsURI+"'"); + } + } + + protected static void failStrings(String msg, String exp, String act) + { + // !!! TODO: Indicate position where Strings differ + fail(msg+": expected "+quotedPrintable(exp)+", got " + +quotedPrintable(act)); + } + + /** + * Method that not only gets currently available text from the + * reader, but also checks that its consistenly accessible using + * different (basic) StAX methods. + */ + protected static String getAndVerifyText(XMLStreamReader sr) + throws XMLStreamException + { + /* 05-Apr-2006, TSa: Although getText() is available for DTD + * and ENTITY_REFERENCE, getTextXxx() are not. Thus, can not + * do more checks for those types. + */ + int type = sr.getEventType(); + if (type == ENTITY_REFERENCE || type == DTD) { + return sr.getText(); + } + + int expLen = sr.getTextLength(); + /* Hmmh. It's only ok to return empty text for DTD event... well, + * maybe also for CDATA, since empty CDATA blocks are legal? + */ + /* !!! 01-Sep-2004, TSa: + * note: theoretically, in coalescing mode, it could be possible + * to have empty CDATA section(s) get converted to CHARACTERS, + * which would be empty... may need to enhance this to check that + * mode is not coalescing? Or something + */ + if (type == CHARACTERS) { + assertTrue("Stream reader should never return empty Strings.", (expLen > 0)); + } + String text = sr.getText(); + assertNotNull("getText() should never return null.", text); + assertEquals("Expected text length of "+expLen+", got "+text.length(), + expLen, text.length()); + char[] textChars = sr.getTextCharacters(); + int start = sr.getTextStart(); + String text2 = new String(textChars, start, expLen); + assertEquals(text, text2); + return text; + } + + protected void verifyException(Throwable e, String match) + { + String msg = e.getMessage(); + String lmsg = msg.toLowerCase(); + String lmatch = match.toLowerCase(); + if (lmsg.indexOf(lmatch) < 0) { + fail("Expected an exception with sub-string \""+match+"\": got one with message \""+msg+"\""); + } + } + + /* + /////////////////////////////////////////////////////////// + // Debug/output helpers + /////////////////////////////////////////////////////////// + */ + + public static void warn(String msg) + { + System.err.println("WARN: "+msg); + } + + public static String printable(char ch) + { + if (ch == '\n') { + return "\\n"; + } + if (ch == '\r') { + return "\\r"; + } + if (ch == '\t') { + return "\\t"; + } + if (ch == ' ') { + return "_"; + } + if (ch > 127 || ch < 32) { + StringBuffer sb = new StringBuffer(6); + sb.append("\\u"); + String hex = Integer.toHexString(ch); + for (int i = 0, len = 4 - hex.length(); i < len; i++) { + sb.append('0'); + } + sb.append(hex); + return sb.toString(); + } + return null; + } + + public static String printableWithSpaces(char ch) + { + if (ch == '\n') { + return "\\n"; + } + if (ch == '\r') { + return "\\r"; + } + if (ch == '\t') { + return "\\t"; + } + if (ch > 127 || ch < 32) { + StringBuffer sb = new StringBuffer(6); + sb.append("\\u"); + String hex = Integer.toHexString(ch); + for (int i = 0, len = 4 - hex.length(); i < len; i++) { + sb.append('0'); + } + sb.append(hex); + return sb.toString(); + } + return null; + } + + public static String printable(String str) + { + if (str == null || str.length() == 0) { + return str; + } + + int len = str.length(); + StringBuffer sb = new StringBuffer(len + 64); + for (int i = 0; i < len; ++i) { + char c = str.charAt(i); + String res = printable(c); + if (res == null) { + sb.append(c); + } else { + sb.append(res); + } + } + return sb.toString(); + } + + public static String printableWithSpaces(String str) + { + if (str == null || str.length() == 0) { + return str; + } + + int len = str.length(); + StringBuffer sb = new StringBuffer(len + 64); + for (int i = 0; i < len; ++i) { + char c = str.charAt(i); + String res = printableWithSpaces(c); + if (res == null) { + sb.append(c); + } else { + sb.append(res); + } + } + return sb.toString(); + } + + protected static String quotedPrintable(String str) + { + if (str == null || str.length() == 0) { + return "[0]''"; + } + return "[len: "+str.length()+"] '"+printable(str)+"'"; + } + + /* + /////////////////////////////////////////////////////////// + // Helper classes + /////////////////////////////////////////////////////////// + */ + + /** + * Need a dummy base class to be able to access protected + * constructor for testing purposes. + */ + final static class ForcedAdapter + extends Stax2ReaderAdapter + { + public ForcedAdapter(XMLStreamReader sr) + { + super(sr); + } + } +} + diff -Nru libwoodstox-java-4.1.3/src/test/java/stax2/dom/TestDomCompat.java libwoodstox-java-5.1.0/src/test/java/stax2/dom/TestDomCompat.java --- libwoodstox-java-4.1.3/src/test/java/stax2/dom/TestDomCompat.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/stax2/dom/TestDomCompat.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,388 @@ +package stax2.dom; + +import java.io.*; + +import javax.xml.parsers.*; +import javax.xml.namespace.NamespaceContext; +import javax.xml.namespace.QName; +import javax.xml.stream.*; +import javax.xml.transform.dom.DOMSource; + +import org.xml.sax.InputSource; +import org.w3c.dom.Document; +import org.w3c.dom.DocumentFragment; + +import org.codehaus.stax2.*; + +import stax2.BaseStax2Test; + +/** + * Unit test suite that checks that input-side DOM-compatibility + * features (DOMSource as input) are implemented as expected. + *

+ * This test is part of stax2test suite because a reference implementation + * of DOM-wrapping/adapting reader is included, and hence it is + * reasonable to expect that Stax2 implementations would implement + * this part of DOM interoperability support. + */ +public class TestDomCompat + extends BaseStax2Test +{ + public void testSimpleDomInput() throws Exception + { + final String XML = + "" + +"" + +"" + +"" + +"\nAnd some text" + +"" + ; + + XMLStreamReader sr = createDomBasedReader(XML, true); + + assertTokenType(COMMENT, sr.next()); + assertEquals("prolog", getAndVerifyText(sr)); + + // 10-Sep-2010, tatu: Verify [WSTX-246] + assertNotNull(sr.getLocation()); + + assertTokenType(START_ELEMENT, sr.next()); + assertEquals("root", sr.getLocalName()); + assertEquals("ns", sr.getPrefix()); + assertEquals("http://foo", sr.getNamespaceURI()); + QName n = sr.getName(); + assertNotNull(n); + assertEquals("root", n.getLocalPart()); + + assertEquals(1, sr.getAttributeCount()); + assertEquals("attr", sr.getAttributeLocalName(0)); + assertEquals("", sr.getAttributePrefix(0)); + assertEquals("", sr.getAttributeNamespace(0)); + n = sr.getAttributeName(0); + assertNotNull(n); + assertEquals("attr", n.getLocalPart()); + assertEquals("value", sr.getAttributeValue(0)); + + assertEquals(1, sr.getNamespaceCount()); + assertEquals("ns", sr.getNamespacePrefix(0)); + assertEquals("http://foo", sr.getNamespaceURI(0)); + + NamespaceContext nsCtxt = sr.getNamespaceContext(); + assertNotNull(nsCtxt); + /* 28-Apr-2006, TSa: Alas, namespace access is only fully + * implemented in DOM Level 3 (JDK 1.5+)... thus, can't check: + */ + /* + assertEquals("ns", nsCtxt.getPrefix("http://foo")); + assertEquals("http://foo", nsCtxt.getNamespaceURI("ns")); + assertNull(nsCtxt.getPrefix("http://whatever")); + assertNull(nsCtxt.getNamespaceURI("nsX")); + */ + + assertTokenType(START_ELEMENT, sr.next()); + assertEquals("leaf", sr.getLocalName()); + assertEquals("", sr.getPrefix()); + assertEquals("", sr.getNamespaceURI()); + assertEquals(1, sr.getAttributeCount()); + assertEquals("attr", sr.getAttributeLocalName(0)); + assertEquals("ns", sr.getAttributePrefix(0)); + assertEquals("http://foo", sr.getAttributeNamespace(0)); + assertEquals(0, sr.getNamespaceCount()); + + assertTokenType(END_ELEMENT, sr.next()); + assertEquals("leaf", sr.getLocalName()); + assertEquals("", sr.getPrefix()); + assertEquals("", sr.getNamespaceURI()); + assertEquals(0, sr.getNamespaceCount()); + + assertTokenType(PROCESSING_INSTRUCTION, sr.next()); + assertEquals("proc", sr.getPITarget()); + assertEquals("instr", sr.getPIData()); + + assertTokenType(COMMENT, sr.next()); + assertEquals("comment", getAndVerifyText(sr)); + + assertTokenType(CHARACTERS, sr.next()); + // yeah yeah, could be split... + assertEquals("\nAnd some text", getAndVerifyText(sr)); + + assertTokenType(END_ELEMENT, sr.next()); + assertEquals("root", sr.getLocalName()); + assertEquals("ns", sr.getPrefix()); + assertEquals("http://foo", sr.getNamespaceURI()); + + assertEquals(1, sr.getNamespaceCount()); + assertEquals("ns", sr.getNamespacePrefix(0)); + assertEquals("http://foo", sr.getNamespaceURI(0)); + + assertTokenType(PROCESSING_INSTRUCTION, sr.next()); + assertEquals("pi-in", sr.getPITarget()); + assertEquals("epilog", sr.getPIData()); + + assertTokenType(END_DOCUMENT, sr.next()); + + assertFalse(sr.hasNext()); + sr.close(); + } + + /** + * Test added to verify that [WSTX-134] is fixed properly + */ + public void testDomWhitespace() + throws Exception + { + final String XML = + " \n\t x "; + XMLStreamReader sr = createDomBasedReader(XML, true); + + assertTokenType(START_ELEMENT, sr.next()); + assertEquals("root", sr.getLocalName()); + assertTokenType(CHARACTERS, sr.next()); + assertTrue(sr.isWhiteSpace()); + assertEquals(" \n", getAndVerifyText(sr)); + assertTokenType(START_ELEMENT, sr.next()); + assertEquals("leaf", sr.getLocalName()); + assertTokenType(CHARACTERS, sr.next()); + assertTrue(sr.isWhiteSpace()); + assertEquals("\t", getAndVerifyText(sr)); + assertTokenType(END_ELEMENT, sr.next()); + assertEquals("leaf", sr.getLocalName()); + assertTokenType(CHARACTERS, sr.next()); + assertFalse(sr.isWhiteSpace()); + assertEquals(" x ", getAndVerifyText(sr)); + assertTokenType(END_ELEMENT, sr.next()); + assertEquals("root", sr.getLocalName()); + assertTokenType(END_DOCUMENT, sr.next()); + sr.close(); + } + + /** + * Test to verify that [WSTX-145] is properly fixed + */ + public void testDomCoalescingText() + throws Exception + { + final String XML = + "Some in cdata"; + + Document doc = parseDomDoc(XML, true); + XMLInputFactory2 ifact = getInputFactory(); + setCoalescing(ifact, true); + XMLStreamReader sr = ifact.createXMLStreamReader(new DOMSource(doc)); + assertTokenType(START_DOCUMENT, sr.getEventType()); + assertTokenType(START_ELEMENT, sr.next()); + assertEquals("root", sr.getLocalName()); + assertTokenType(CHARACTERS, sr.next()); + assertEquals("Some content in cdata", getAndVerifyText(sr)); + + assertTokenType(END_ELEMENT, sr.next()); + assertTokenType(END_DOCUMENT, sr.next()); + } + + public void testDomCoalescingType() + throws Exception + { + final String XML = + ""; + + Document doc = parseDomDoc(XML, true); + XMLInputFactory2 ifact = getInputFactory(); + setCoalescing(ifact, true); + XMLStreamReader sr = ifact.createXMLStreamReader(new DOMSource(doc)); + assertTokenType(START_ELEMENT, sr.next()); + assertEquals("root", sr.getLocalName()); + // Should always be of type CHARACTERS, even if underlying event is CDATA + assertTokenType(CHARACTERS, sr.next()); + assertEquals("...", getAndVerifyText(sr)); + + assertTokenType(END_ELEMENT, sr.next()); + assertTokenType(END_DOCUMENT, sr.next()); + } + + /** + * First test regarding [WSTX-162], let's check that we can + * actually enable/disable interning on reader instances + * (independent of whether settings take effect or not) + */ + public void testDomInternProperties() + throws Exception + { + Document doc = parseDomDoc("", true); + XMLInputFactory2 ifact = getInputFactory(); + XMLStreamReader2 sr = (XMLStreamReader2) ifact.createXMLStreamReader(new DOMSource(doc)); + + boolean okSet = sr.setProperty(XMLInputFactory2.P_INTERN_NAMES, Boolean.TRUE); + assertTrue(okSet); + assertEquals(Boolean.TRUE, sr.getProperty(XMLInputFactory2.P_INTERN_NAMES)); + okSet = sr.setProperty(XMLInputFactory2.P_INTERN_NAMES, Boolean.FALSE); + assertTrue(okSet); + assertEquals(Boolean.FALSE, sr.getProperty(XMLInputFactory2.P_INTERN_NAMES)); + + okSet = sr.setProperty(XMLInputFactory2.P_INTERN_NS_URIS, Boolean.TRUE); + assertTrue(okSet); + assertEquals(Boolean.TRUE, sr.getProperty(XMLInputFactory2.P_INTERN_NS_URIS)); + okSet = sr.setProperty(XMLInputFactory2.P_INTERN_NS_URIS, Boolean.FALSE); + assertTrue(okSet); + assertEquals(Boolean.FALSE, sr.getProperty(XMLInputFactory2.P_INTERN_NS_URIS)); + } + + /** + * Test for checking that [WSTX-162] has been addressed, + * regarding names. + */ + public void testDomInternNames() + throws Exception + { + final String ELEM = "root"; + final String PREFIX = "ns"; + final String ATTR = "attr"; + final String URI = "http://foo"; + final String XML = "<"+PREFIX+":"+ELEM+" attr='1' xmlns:"+PREFIX+"='"+URI+"' />"; + Document doc = parseDomDoc(XML, true); + XMLInputFactory2 ifact = getInputFactory(); + + /* Ok, so: let's first ensure that local names ARE intern()ed + * when we request them to be: + */ + ifact.setProperty(XMLInputFactory2.P_INTERN_NAMES, Boolean.TRUE); + XMLStreamReader sr = ifact.createXMLStreamReader(new DOMSource(doc)); + assertTokenType(START_ELEMENT, sr.next()); + assertEquals(ELEM, sr.getLocalName()); + assertSame(ELEM, sr.getLocalName()); + + assertEquals(ATTR, sr.getAttributeLocalName(0)); + assertSame(ATTR, sr.getAttributeLocalName(0)); + + assertEquals(PREFIX, sr.getPrefix()); + assertSame(PREFIX, sr.getPrefix()); + sr.close(); + + /* And then also that the impl does honor disabling of + * the feature: while optional, ref. impl. makes this + * easy so there's no excuse not to. + */ + ifact.setProperty(XMLInputFactory2.P_INTERN_NAMES, Boolean.FALSE); + sr = ifact.createXMLStreamReader(new DOMSource(doc)); + assertTokenType(START_ELEMENT, sr.next()); + assertEquals(ELEM, sr.getLocalName()); + // Xerces won't force intern() of element names + assertNotSame(ELEM, sr.getLocalName()); + + // But does intern attribute names + /* + assertEquals(ATTR, sr.getAttributeLocalName(0)); + assertNotSame(ATTR, sr.getAttributeLocalName(0)); + */ + + assertEquals(PREFIX, sr.getPrefix()); + assertNotSame(PREFIX, sr.getPrefix()); + sr.close(); + } + + /** + * Test for checking that [WSTX-162] has been addressed, + * regarding names. + */ + public void testDomInternNsURIs() + throws Exception + { + final String ELEM = "root"; + final String URI = "http://foo"; + final String XML = "<"+ELEM+" xmlns='"+URI+"' />"; + Document doc = parseDomDoc(XML, true); + XMLInputFactory2 ifact = getInputFactory(); + + /* Ok, so: let's first ensure that URIs are intern()ed + * when we request them to be: + */ + ifact.setProperty(XMLInputFactory2.P_INTERN_NS_URIS, Boolean.TRUE); + XMLStreamReader sr = ifact.createXMLStreamReader(new DOMSource(doc)); + assertTokenType(START_ELEMENT, sr.next()); + assertEquals(ELEM, sr.getLocalName()); + assertEquals(URI, sr.getNamespaceURI()); + assertSame(URI, sr.getNamespaceURI()); + sr.close(); + + /* Beyond this we can't say much: it all depends on whether + * the backing DOM impl uses intern() or not. + */ + ifact.setProperty(XMLInputFactory2.P_INTERN_NS_URIS, Boolean.FALSE); + sr = ifact.createXMLStreamReader(new DOMSource(doc)); + assertTokenType(START_ELEMENT, sr.next()); + assertEquals(ELEM, sr.getLocalName()); + assertEquals(URI, sr.getNamespaceURI()); + + // Ok, looks like Xerces does intern namespace URIs? Weird... + /* + assertNotSame(URI, sr.getNamespaceURI()); + */ + + sr.close(); + } + + // [WSTX-244] + public void testGetElementText() throws Exception + { + final String XML = + "Sometext"; + + XMLInputFactory2 ifact = getInputFactory(); + XMLStreamReader sr; + + // First, non-coalescing: + setCoalescing(ifact, false); + sr = ifact.createXMLStreamReader(new DOMSource(parseDomDoc(XML, true))); + assertTokenType(START_ELEMENT, sr.next()); + assertEquals("Some text", sr.getElementText()); + assertTokenType(END_ELEMENT, sr.getEventType()); + assertTokenType(END_DOCUMENT, sr.next()); + sr.close(); + + // then coalescing + setCoalescing(ifact, true); + sr = ifact.createXMLStreamReader(new DOMSource(parseDomDoc(XML, true))); + assertTokenType(START_ELEMENT, sr.next()); + assertEquals("Some text", sr.getElementText()); + assertTokenType(END_ELEMENT, sr.getEventType()); + assertTokenType(END_DOCUMENT, sr.next()); + sr.close(); + } + + // [WSTX-259] + public void testEmptyFragment() throws Exception + { + DocumentFragment fragment = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument().createDocumentFragment(); + + XMLStreamReader sr = XMLInputFactory.newInstance().createXMLStreamReader(new DOMSource(fragment)); + assertTokenType(START_DOCUMENT, sr.getEventType()); + assertTokenType(END_DOCUMENT, sr.next()); + assertFalse(sr.hasNext()); + } + + /* + /////////////////////////////////////////////////////////// + // Helper methods + /////////////////////////////////////////////////////////// + */ + + private XMLStreamReader2 createDomBasedReader(String content, boolean nsAware) + throws Exception + { + XMLInputFactory2 ifact = getInputFactory(); + XMLStreamReader2 sr = (XMLStreamReader2) ifact.createXMLStreamReader(new DOMSource(parseDomDoc(content, nsAware))); + // Let's also check it's properly initialized + assertTokenType(START_DOCUMENT, sr.getEventType()); + return sr; + } + + private Document parseDomDoc(String content, boolean nsAware) + throws Exception + { + // First, need to parse using JAXP DOM: + DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); + dbf.setNamespaceAware(nsAware); + DocumentBuilder db = dbf.newDocumentBuilder(); + return db.parse(new InputSource(new StringReader(content))); + } +} diff -Nru libwoodstox-java-4.1.3/src/test/java/stax2/dom/TestDomNamespaces.java libwoodstox-java-5.1.0/src/test/java/stax2/dom/TestDomNamespaces.java --- libwoodstox-java-4.1.3/src/test/java/stax2/dom/TestDomNamespaces.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/stax2/dom/TestDomNamespaces.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,58 @@ +package stax2.dom; + +import java.io.StringReader; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.stream.*; +import javax.xml.transform.dom.DOMSource; + +import org.w3c.dom.Document; +import org.xml.sax.InputSource; + +import stax2.BaseStax2Test; + +/** + * Additional reader-side tests for namespace handling with DOM input + */ +public class TestDomNamespaces + extends BaseStax2Test +{ + private String xml = "" + +"" + +"" + +"321" + +"" + +"" + +""; + + public void testDOMSource() throws Exception + { + DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); + factory.setNamespaceAware(true); + DocumentBuilder builder = factory.newDocumentBuilder(); + + InputSource source = new InputSource(new StringReader(xml)); + Document doc = builder.parse(source); + + //Fails when using DOMWrappingReader + XMLStreamReader reader = getInputFactory().createXMLStreamReader(new DOMSource(doc)); + + reader.next(); //root + assertEquals(0, reader.getAttributeCount()); + assertEquals(1, reader.getNamespaceCount()); + assertEquals("http://testnamespace/", reader.getNamespaceURI()); + assertEquals("ns2", reader.getPrefix()); + assertEquals("root", reader.getLocalName()); + + reader.next(); //arg0 + reader.next(); //obj + + assertEquals("obj", reader.getLocalName()); + assertEquals("ns2:mycomplextype", reader.getAttributeValue("http://www.w3.org/2001/XMLSchema-instance", "type")); + assertEquals("http://testnamespace/", reader.getNamespaceURI("ns2")); + assertEquals("http://testnamespace/", reader.getNamespaceContext().getNamespaceURI("ns2")); + + assertEquals("ns2", reader.getNamespaceContext().getPrefix("http://testnamespace/")); + } +} diff -Nru libwoodstox-java-4.1.3/src/test/java/stax2/dom/TestDomResultHandling.java libwoodstox-java-5.1.0/src/test/java/stax2/dom/TestDomResultHandling.java --- libwoodstox-java-4.1.3/src/test/java/stax2/dom/TestDomResultHandling.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/stax2/dom/TestDomResultHandling.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,88 @@ +package stax2.dom; + +import javax.xml.parsers.*; +import javax.xml.stream.*; +import javax.xml.transform.dom.DOMResult; + +import org.w3c.dom.*; + +import stax2.wstream.BaseWriterTest; + +/** + * Unit tests initially written to verify [WSTX-183], problems with + * using DOM Element for DOMResult (instead of DOM Document). + * + * @author Christopher Paul Simmons (original tests) + * @author Tatu Saloranta (slight modifications) + */ +public class TestDomResultHandling + extends BaseWriterTest +{ + public void testWriteToDocument() throws Exception + { + // First: write to a regular DOM document + createXMLEventWriter(createDomDoc(true)); + } + + public void testWriteToRootElementNotInDOM() throws Exception + { + // let's try outputting under specified element + Document doc = createDomDoc(true); + Element root = doc.createElementNS("ns", "my:root"); + createXMLEventWriter(root); + /* Should not (try to) attach the element to creating document; + * that is up to caller to do + */ + assertNull(doc.getDocumentElement()); + } + + public void testWriteToRootElementInDOM() throws Exception + { + Document doc = createDomDoc(true); + Element root = doc.createElementNS("ns", "my:root"); + doc.appendChild(root); + createXMLEventWriter(root); + } + + public void testWriteBeforeSibling() throws Exception + { + Document doc = createDomDoc(true); + Element root = doc.createElementNS("ns", "my:root"); + doc.appendChild(root); + Element insertBefore = doc.createElementNS("ns", "my:beforeMe"); + root.appendChild(insertBefore); + createXMLEventWriter(root, insertBefore); + } + + /* + /////////////////////////////////////////////////////////// + // Helper methods + /////////////////////////////////////////////////////////// + */ + + private XMLEventWriter createXMLEventWriter(final Node parent, final Node insertBefore) + throws XMLStreamException + { + XMLOutputFactory f = getOutputFactory(); + return f.createXMLEventWriter(new DOMResult(parent, insertBefore)); + } + + /** + * @param resultNode The node to write to. + * @return The result. + * @throws XMLStreamException On error. + */ + private XMLEventWriter createXMLEventWriter(final Node resultNode) + throws XMLStreamException + { + return createXMLEventWriter(resultNode, null); + } + + private Document createDomDoc(boolean nsAware) + throws Exception + { + DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); + dbf.setNamespaceAware(nsAware); + return dbf.newDocumentBuilder().newDocument(); + } +} diff -Nru libwoodstox-java-4.1.3/src/test/java/stax2/dom/TestDomWrite.java libwoodstox-java-5.1.0/src/test/java/stax2/dom/TestDomWrite.java --- libwoodstox-java-4.1.3/src/test/java/stax2/dom/TestDomWrite.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/stax2/dom/TestDomWrite.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,263 @@ +package stax2.dom; + +import javax.xml.parsers.*; +import javax.xml.stream.*; +import javax.xml.transform.dom.DOMResult; + +import org.w3c.dom.*; + +import org.codehaus.stax2.typed.TypedXMLStreamWriter; + +import stax2.wstream.BaseWriterTest; + +/** + * Unit test suite that checks that output-side DOM-compatibility + * features (DOMResult for output) are implemented as expected. + */ +public class TestDomWrite + extends BaseWriterTest +{ + final static int TYPE_NON_NS = 0; + final static int TYPE_NS = 1; + final static int TYPE_NS_REPAIRING = 2; + + public void testNonNsOutput() throws Exception + { + /* 23-Dec-2008, TSa: Not all Stax2 impls support non-namespace-aware + * modes: need to first ensure one tested does... + */ + XMLOutputFactory of = getFactory(TYPE_NON_NS); + if (of == null) { + System.err.println("Skipping "+getClass().getName()+"#testNonNsOutput: non-namespace-aware mode not supported"); + return; + } + + Document doc = createDomDoc(false); + XMLStreamWriter sw = of.createXMLStreamWriter(new DOMResult(doc)); + + sw.writeStartDocument(); + sw.writeStartElement("root"); + sw.writeAttribute("attr", "value"); + sw.writeAttribute("ns:attr2", "value2"); + sw.writeEmptyElement("leaf"); + sw.writeCharacters("text?"); + sw.writeEndElement(); + sw.writeEndDocument(); + sw.close(); + + Element root = doc.getDocumentElement(); + + assertNotNull(root); + assertEquals("root", root.getTagName()); + NamedNodeMap attrs = root.getAttributes(); + assertEquals(2, attrs.getLength()); + assertEquals("value", root.getAttribute("attr")); + assertEquals("value2", root.getAttribute("ns:attr2")); + + Node child = root.getFirstChild(); + assertNotNull(child); + assertEquals(Node.ELEMENT_NODE, child.getNodeType()); + Element elem = (Element) child; + assertEquals("leaf", elem.getTagName()); + attrs = elem.getAttributes(); + assertEquals(0, attrs.getLength()); + + child = child.getNextSibling(); + assertNotNull(child); + assertEquals(Node.TEXT_NODE, child.getNodeType()); + // Alas, getTextContent() is DOM 3 (Jdk 1.5+) + //assertEquals("text?", child.getTextContent()); + // ... so we'll use less refined method + assertEquals("text?", child.getNodeValue()); + } + + public void testMiscOutput() throws Exception + { + XMLOutputFactory of = getFactory(TYPE_NON_NS); + if (of == null) { + System.err.println("Skipping "+getClass().getName()+"#testNonNsOutput: non-namespace-aware mode not supported"); + return; + } + Document doc = createDomDoc(false); + XMLStreamWriter sw = of.createXMLStreamWriter(new DOMResult(doc)); + + sw.writeStartDocument(); + sw.writeStartElement("root"); + sw.writeComment("comment!"); + sw.writeCData("cdata!"); + sw.writeEndElement(); + sw.writeEndDocument(); + sw.close(); + + Element root = doc.getDocumentElement(); + + assertNotNull(root); + assertEquals("root", root.getTagName()); + + Node child = root.getFirstChild(); + assertNotNull(child); + assertEquals(Node.COMMENT_NODE, child.getNodeType()); + assertEquals("comment!", child.getNodeValue()); + + child = child.getNextSibling(); + assertNotNull(child); + assertEquals(Node.CDATA_SECTION_NODE, child.getNodeType()); + assertEquals("cdata!", child.getNodeValue()); + assertNull(child.getNextSibling()); + } + + public void testNsOutput() + throws Exception + { + Document doc = createDomDoc(false); + XMLOutputFactory of = getFactory(TYPE_NS); + XMLStreamWriter sw = of.createXMLStreamWriter(new DOMResult(doc)); + final String NS_URI = "http://foo"; + + sw.writeStartDocument(); + sw.writeStartElement("ns", "root", NS_URI); + sw.writeNamespace("ns", NS_URI); + sw.writeAttribute("ns", NS_URI, "attr", "value"); + sw.writeCharacters("..."); + sw.writeEndElement(); + sw.writeEndDocument(); + sw.close(); + + Element root = doc.getDocumentElement(); + + assertNotNull(root); + assertEquals("ns:root", root.getTagName()); + NamedNodeMap attrs = root.getAttributes(); + // DOM includes ns decls as attributes, hence 2: + assertEquals(2, attrs.getLength()); + assertEquals(NS_URI, root.getAttribute("xmlns:ns")); + assertEquals("value", root.getAttribute("ns:attr")); + + Node child = root.getFirstChild(); + assertNotNull(child); + assertEquals(Node.TEXT_NODE, child.getNodeType()); + // Alas, getTextContent() is DOM 3 (Jdk 1.5+) + //assertEquals("text?", child.getTextContent()); + // ... so we'll use less refined method + assertEquals("...", child.getNodeValue()); + } + + public void testRepairingNsOutput() + throws Exception + { + final String URI1 = "urn:1"; + final String URI2 = "urn:2"; + + Document doc = createDomDoc(false); + XMLOutputFactory of = getFactory(TYPE_NS_REPAIRING); + XMLStreamWriter sw = of.createXMLStreamWriter(new DOMResult(doc)); + + sw.writeStartDocument(); + sw.writeStartElement(URI1, "root"); + sw.writeAttribute("attr", "x"); + sw.writeEmptyElement(URI2, "leaf"); + sw.writeStartElement(URI2, "leaf2"); + sw.writeAttribute(URI2, "attr2", ""); + sw.writeEndElement(); + sw.writeEndElement(); + sw.writeEndDocument(); + sw.close(); + + Element root = doc.getDocumentElement(); + + //System.err.println("DOC -> "+((org.w3c.dom.ls.DOMImplementationLS) doc.getImplementation()).createLSSerializer().writeToString(doc)); + + assertNotNull(root); + assertEquals("root", root.getLocalName()); + assertEquals(URI1, root.getNamespaceURI()); + NamedNodeMap attrs = root.getAttributes(); + // 1 attribute, 1 ns decl: + assertEquals(2, attrs.getLength()); + // interesting -- as per javadocs, must pass null for "no namespace" + assertEquals("x", root.getAttributeNS(null, "attr")); + + Node child = root.getFirstChild(); + assertNotNull(child); + assertEquals(Node.ELEMENT_NODE, child.getNodeType()); + Element elem = (Element) child; + assertEquals("leaf", elem.getLocalName()); + attrs = elem.getAttributes(); + // 1 ns decl: + assertEquals(1, attrs.getLength()); + + child = child.getNextSibling(); + assertNotNull(child); + assertEquals(Node.ELEMENT_NODE, child.getNodeType()); + elem = (Element) child; + assertEquals("leaf2", elem.getLocalName()); + attrs = elem.getAttributes(); + /* At least 1 attribute, 1 ns decl; but depending on + * how writer chooses to do it, may be 2 ns decls. So... + */ + int count = attrs.getLength(); + if (count < 2 || count > 3) { + fail("Expected 2 or 3 attributes (including namespace declarations), got "+count); + } + assertEquals("", elem.getAttributeNS(URI2, "attr2")); + } + + public void testTypedOutputInt() + throws Exception + { + Document doc = createDomDoc(false); + // let's use namespace-aware just because some impls might not support non-ns + XMLOutputFactory of = getFactory(TYPE_NS); + TypedXMLStreamWriter sw = (TypedXMLStreamWriter) of.createXMLStreamWriter(new DOMResult(doc)); + + sw.writeStartDocument(); + sw.writeStartElement("root"); + sw.writeIntAttribute(null, null, "attr", -900); + sw.writeInt(123); + sw.writeEndElement(); + sw.writeEndDocument(); + sw.close(); + + Element root = doc.getDocumentElement(); + + assertNotNull(root); + assertEquals("root", root.getTagName()); + NamedNodeMap attrs = root.getAttributes(); + assertEquals(1, attrs.getLength()); + assertEquals("-900", root.getAttribute("attr")); + + Node child = root.getFirstChild(); + assertNotNull(child); + assertEquals(Node.TEXT_NODE, child.getNodeType()); + assertEquals("123", child.getNodeValue()); + } + + /* + /////////////////////////////////////////////////////////// + // Helper methods + /////////////////////////////////////////////////////////// + */ + + private Document createDomDoc(boolean nsAware) + throws Exception + { + DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); + dbf.setNamespaceAware(nsAware); + return dbf.newDocumentBuilder().newDocument(); + } + + private XMLOutputFactory getFactory(int type) + throws Exception + { + XMLOutputFactory f = getOutputFactory(); + // type 0 -> non-ns, 1 -> ns, non-repairing, 2 -> ns, repairing + boolean ns = (type > 0); + /* 23-Dec-2008, TSa: Not all Stax2 impls support non-namespace-aware + * modes: need to first ensure one tested does... + */ + if (!setNamespaceAware(f, ns) && !ns) { + return null; + } + setRepairing(f, type > 1); + return f; + } +} diff -Nru libwoodstox-java-4.1.3/src/test/java/stax2/dom/TestFragments.java libwoodstox-java-5.1.0/src/test/java/stax2/dom/TestFragments.java --- libwoodstox-java-4.1.3/src/test/java/stax2/dom/TestFragments.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/stax2/dom/TestFragments.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,49 @@ +package stax2.dom; + +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.stream.*; +import javax.xml.transform.dom.DOMResult; +import javax.xml.transform.dom.DOMSource; + +import org.w3c.dom.DocumentFragment; + +import stax2.BaseStax2Test; + +public class TestFragments extends BaseStax2Test +{ + // [WSTX-257] + public void testFragmentIssue257() throws Exception + { + DocumentFragment fragment = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument().createDocumentFragment(); + XMLStreamWriter xmlWriter = getOutputFactory().createXMLStreamWriter(new DOMResult(fragment)); + // create equivalent of "value1value2" + xmlWriter.writeStartElement("a"); + xmlWriter.writeCharacters("value1"); + xmlWriter.writeEndElement(); + xmlWriter.writeStartElement("b"); + xmlWriter.writeCharacters("value2"); + xmlWriter.writeEndElement(); + xmlWriter.close(); + + XMLStreamReader sr = getInputFactory().createXMLStreamReader(new DOMSource(fragment)); + assertTokenType(START_DOCUMENT, sr.getEventType()); + + assertTokenType(START_ELEMENT, sr.next()); + assertEquals("a", sr.getLocalName()); + assertTokenType(CHARACTERS, sr.next()); + assertEquals("value1", sr.getText()); + assertTokenType(END_ELEMENT, sr.next()); + assertEquals("a", sr.getLocalName()); + + assertTokenType(START_ELEMENT, sr.next()); + assertEquals("b", sr.getLocalName()); + assertTokenType(CHARACTERS, sr.next()); + assertEquals("value2", sr.getText()); + assertTokenType(END_ELEMENT, sr.next()); + assertEquals("b", sr.getLocalName()); + + assertTokenType(END_DOCUMENT, sr.next()); + assertFalse(sr.hasNext()); + } + +} diff -Nru libwoodstox-java-4.1.3/src/test/java/stax2/dtd/TestDefaultAttrs.java libwoodstox-java-5.1.0/src/test/java/stax2/dtd/TestDefaultAttrs.java --- libwoodstox-java-4.1.3/src/test/java/stax2/dtd/TestDefaultAttrs.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/stax2/dtd/TestDefaultAttrs.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,59 @@ +package stax2.dtd; + +import javax.xml.stream.XMLStreamException; + +import org.codehaus.stax2.*; + +import stax2.BaseStax2Test; + +/** + * Test class that checks whether namespace declarations gained via + * attribute defaulting work. + */ +public class TestDefaultAttrs + extends BaseStax2Test +{ + public void testValidNsFromDefaultAttrs() + throws XMLStreamException + { + final String XML = + "\n" + +"\n" + +"\n" + +"\n" + +"]>" + ; + + XMLStreamReader2 sr = getReader(XML, true); + assertTokenType(DTD, sr.next()); + assertTokenType(START_ELEMENT, sr.next()); + assertEquals("node", sr.getLocalName()); + assertEquals(3, sr.getAttributeCount()); + assertEquals("xyz", sr.getAttributeValue("", "attr1")); + assertEquals("xyz", sr.getAttributeValue(null, "attr1")); + assertEquals("123", sr.getAttributeValue("", "attr3")); + assertEquals("123", sr.getAttributeValue(null, "attr3")); + assertEquals("abc", sr.getAttributeValue("", "attr2")); + assertEquals("abc", sr.getAttributeValue(null, "attr2")); + + // and non existing... + assertNull(sr.getAttributeValue("http://foo", "attr1")); + } + + /* + //////////////////////////////////////// + // Private methods + //////////////////////////////////////// + */ + + private XMLStreamReader2 getReader(String contents, boolean nsAware) + throws XMLStreamException + { + XMLInputFactory2 f = getInputFactory(); + setNamespaceAware(f, nsAware); + setSupportDTD(f, true); + setValidating(f, true); + return constructStreamReader(f, contents); + } +} diff -Nru libwoodstox-java-4.1.3/src/test/java/stax2/dtd/TestDTDInfo.java libwoodstox-java-5.1.0/src/test/java/stax2/dtd/TestDTDInfo.java --- libwoodstox-java-4.1.3/src/test/java/stax2/dtd/TestDTDInfo.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/stax2/dtd/TestDTDInfo.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,68 @@ +package stax2.dtd; + +import javax.xml.stream.*; + +import org.codehaus.stax2.*; +import org.codehaus.stax2.validation.DTDValidationSchema; + +import stax2.BaseStax2Test; + +/** + * Set of unit tests that checks that the {@link AttributeInfo} implementation + * works as expected. + */ +public class TestDTDInfo + extends BaseStax2Test +{ + final static String TEST_DOC = + "" + +"\n" + +"\n" // param entity + +"\n" // general internal parsed entity + +"\n" // gen. ext. parsed entity + +"\n" + +"\n" + +"\n" // gen. ext. unparsed + +"]>" + +"" + ; + + public void testDTDInfo() + throws XMLStreamException + { + XMLStreamReader2 sr = getReader(TEST_DOC); + + assertTokenType(DTD, sr.next()); + + DTDInfo info = sr.getDTDInfo(); + assertNotNull(info); + DTDValidationSchema dtd = info.getProcessedDTDSchema(); + assertNotNull(dtd); + + // 4 entities, but one is parameter entity... + assertEquals(3, dtd.getEntityCount()); + + // 2 notations: + assertEquals(2, dtd.getNotationCount()); + + // Also, don't want a creepy exception afterwards... + assertTokenType(START_ELEMENT, sr.next()); + } + + /* + //////////////////////////////////////// + // Private methods + //////////////////////////////////////// + */ + + private XMLStreamReader2 getReader(String contents) + throws XMLStreamException + { + XMLInputFactory f = getInputFactory(); + // Need dtd support, may need validation... + setSupportDTD(f, true); + setValidating(f, true); + return constructStreamReader(f, contents); + } +} diff -Nru libwoodstox-java-4.1.3/src/test/java/stax2/dtd/TestExternalDTD.java libwoodstox-java-5.1.0/src/test/java/stax2/dtd/TestExternalDTD.java --- libwoodstox-java-4.1.3/src/test/java/stax2/dtd/TestExternalDTD.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/stax2/dtd/TestExternalDTD.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,261 @@ +package stax2.dtd; + +import java.io.*; +import java.net.URL; + +import javax.xml.stream.*; +import javax.xml.transform.stream.StreamSource; + +import org.codehaus.stax2.*; + +import stax2.BaseStax2Test; + +/** + * Unit tests that verify that external DTD subsets are properly + * referenced and accessed when using various input factory methods + * that give enough information to reference relative paths (or explicitly + * pass the whole path) + */ +public class TestExternalDTD + extends BaseStax2Test +{ + final String EXTERNAL_FILENAME1 = "external1.xml"; + final String EXTERNAL_FILENAME2 = "external2.xml"; + + final static String DTD1 = "external.dtd"; + + final String EXTERNAL_XML1 = + "" + +"&simpleEntity;" + ; + + final String EXTERNAL_XML2 = + "" + +"&simpleEntity;" + ; + + final String SIMPLE_EXT_ENTITY_TEXT = "simple textual content"; + + /** + * This tests the basic dereferencing when giving an input stream + * and system id (to use for figuring out the base); basic Stax 1.0 + * feature + */ + public void testStreamWithSystemId() + throws IOException, XMLStreamException + { + for (int i = 0; i < 2; ++i) { + String filename = (i == 0) ? EXTERNAL_FILENAME1 : EXTERNAL_FILENAME2; + String sysId = constructSystemId(resolveFile(filename)); + String XML = (i == 0) ? EXTERNAL_XML1 : EXTERNAL_XML2; + XMLInputFactory2 f = getFactory(); + XMLStreamReader sr; + try { + sr = f.createXMLStreamReader(sysId, utf8StreamFromString(XML)); + } catch (XMLStreamException xse) { + fail("Failed to construct a SystemID-based stream reader: "+xse); + return; // never gets here + } + try { + assertTokenType(DTD, sr.next()); + assertTokenType(START_ELEMENT, sr.next()); + assertTokenType(CHARACTERS, sr.next()); + assertEquals(SIMPLE_EXT_ENTITY_TEXT, getAndVerifyText(sr)); + assertTokenType(END_ELEMENT, sr.next()); + } catch (XMLStreamException xse) { + fail("Failed to process content using SystemID-based stream reader: "+xse); + } + } + } + + /** + * This tests the basic dereferencing when giving a Reader + * and system id (to use for figuring out the base); basic Stax 1.0 + * feature + */ + public void testReaderWithSystemId() + throws IOException, XMLStreamException + { + for (int i = 0; i < 2; ++i) { + String filename = (i == 0) ? EXTERNAL_FILENAME1 : EXTERNAL_FILENAME2; + String sysId = constructSystemId(resolveFile(filename)); + String XML = (i == 0) ? EXTERNAL_XML1 : EXTERNAL_XML2; + XMLInputFactory2 f = getFactory(); + XMLStreamReader sr; + try { + sr = f.createXMLStreamReader(sysId, new StringReader(XML)); + } catch (XMLStreamException xse) { + fail("Failed to construct a SystemID-based String reader: "+xse); + return; // never gets here + } + try { + assertTokenType(DTD, sr.next()); + assertTokenType(START_ELEMENT, sr.next()); + assertTokenType(CHARACTERS, sr.next()); + assertEquals(SIMPLE_EXT_ENTITY_TEXT, getAndVerifyText(sr)); + assertTokenType(END_ELEMENT, sr.next()); + } catch (XMLStreamException xse) { + fail("Failed to process content using SystemID-based String reader: "+xse); + } + } + } + + /** + * This tests the basic dereferencing when giving an stream source + * with both system id and input source; Stax 1.0 feature. + */ + public void testStreamWithStreamSource() + throws IOException, XMLStreamException + { + // First, using input source + sys id: + for (int i = 0; i < 2; ++i) { + String filename = (i == 0) ? EXTERNAL_FILENAME1 : EXTERNAL_FILENAME2; + String sysId = constructSystemId(resolveFile(filename)); + String XML = (i == 0) ? EXTERNAL_XML1 : EXTERNAL_XML2; + StreamSource src = new StreamSource(utf8StreamFromString(XML), sysId); + XMLInputFactory2 f = getFactory(); + XMLStreamReader sr; + try { + sr = f.createXMLStreamReader(src); + } catch (XMLStreamException xse) { + fail("Failed to construct a StreamSource-based stream reader: "+xse); + return; // never gets here + } + try { + assertTokenType(DTD, sr.next()); + assertTokenType(START_ELEMENT, sr.next()); + assertTokenType(CHARACTERS, sr.next()); + assertEquals(SIMPLE_EXT_ENTITY_TEXT, getAndVerifyText(sr)); + assertTokenType(END_ELEMENT, sr.next()); + } catch (XMLStreamException xse) { + fail("Failed to process content using StreamSource-based stream reader: "+xse); + } + } + + // Then just passing File: + for (int i = 0; i < 2; ++i) { + String filename = (i == 0) ? EXTERNAL_FILENAME1 : EXTERNAL_FILENAME2; + File file = resolveFile(filename); + StreamSource src = new StreamSource(file); + XMLInputFactory2 f = getFactory(); + XMLStreamReader sr; + try { + sr = f.createXMLStreamReader(src); + } catch (XMLStreamException xse) { + fail("Failed to construct a StreamSource/file-based stream reader: "+xse); + return; // never gets here + } + try { + assertTokenType(DTD, sr.next()); + assertTokenType(START_ELEMENT, sr.next()); + assertTokenType(CHARACTERS, sr.next()); + assertEquals(SIMPLE_EXT_ENTITY_TEXT, getAndVerifyText(sr)); + assertTokenType(END_ELEMENT, sr.next()); + } catch (XMLStreamException xse) { + fail("Failed to process content using StreamSource/file-based stream reader: "+xse); + } + } + } + + /** + * Deref'ing with Stax2 factory method that takes a {@link java.net.URL}. + */ + public void testURL() + throws IOException, XMLStreamException + { + for (int i = 0; i < 2; ++i) { + String filename = (i == 0) ? EXTERNAL_FILENAME1 : EXTERNAL_FILENAME2; + URL src = resolveFile(filename).toURI().toURL(); + XMLInputFactory2 f = getFactory(); + XMLStreamReader sr; + + try { + sr = f.createXMLStreamReader(src); + } catch (XMLStreamException xse) { + fail("Failed to construct an URL-based stream reader: "+xse); + return; // never gets here + } + assertTokenType(DTD, sr.next()); + assertTokenType(START_ELEMENT, sr.next()); + assertTokenType(CHARACTERS, sr.next()); + assertEquals(SIMPLE_EXT_ENTITY_TEXT, getAndVerifyText(sr)); + assertTokenType(END_ELEMENT, sr.next()); + } + } + + /** + * Deref'ing with Stax2 factory method that takes a {@link java.io.File} + */ + public void testFile() + throws IOException, XMLStreamException + { + for (int i = 0; i < 2; ++i) { + String filename = (i == 0) ? EXTERNAL_FILENAME1 : EXTERNAL_FILENAME2; + File file = resolveFile(filename); + XMLInputFactory2 f = getFactory(); + XMLStreamReader sr; + try { + sr = f.createXMLStreamReader(file); + } catch (XMLStreamException xse) { + fail("Failed to construct a file-based stream reader: "+xse); + return; // never gets here + } + assertTokenType(DTD, sr.next()); + assertTokenType(START_ELEMENT, sr.next()); + assertTokenType(CHARACTERS, sr.next()); + assertEquals(SIMPLE_EXT_ENTITY_TEXT, getAndVerifyText(sr)); + assertTokenType(END_ELEMENT, sr.next()); + } + } + + /* + //////////////////////////////////////// + // Private methods + //////////////////////////////////////// + */ + + private XMLInputFactory2 getFactory() + throws XMLStreamException + { + // Let's prevent DTD caching... + XMLInputFactory2 f = getNewInputFactory(); + // Need to support all entities + setReplaceEntities(f, true); + setSupportExternalEntities(f, true); + // Need dtd support but not validation + setSupportDTD(f, true); + setValidating(f, false); + // And to make test robust, coalescing + setCoalescing(f, true); + return f; + } + + /** + * Could/should make this more robust (refer as a resource via + * class loader or such), but for now this should work: + */ + private File resolveFile(String relName) + throws IOException + { + // not good -- fragile... but has to do for now + File f = new File("src"); + f = new File(f, "test"); + f = new File(f, "java"); + f = new File(f, "stax2"); + f = new File(f, "stream"); + f = new File(f, relName); + return f.getAbsoluteFile(); + } + + private String constructSystemId(File f) + { + return f.getAbsolutePath(); + } + + private InputStream utf8StreamFromString(String str) + throws java.io.UnsupportedEncodingException + { + byte[] bytes = str.getBytes("UTF-8"); + return new ByteArrayInputStream(bytes); + } +} diff -Nru libwoodstox-java-4.1.3/src/test/java/stax2/dtd/TestNonValidatingDtdAware.java libwoodstox-java-5.1.0/src/test/java/stax2/dtd/TestNonValidatingDtdAware.java --- libwoodstox-java-4.1.3/src/test/java/stax2/dtd/TestNonValidatingDtdAware.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/stax2/dtd/TestNonValidatingDtdAware.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,136 @@ +package stax2.dtd; + +import javax.xml.stream.XMLStreamException; + +import org.codehaus.stax2.*; + +import stax2.BaseStax2Test; + +public class TestNonValidatingDtdAware + extends BaseStax2Test +{ + public void testSpaceNs() + throws XMLStreamException + { + doTestWS(true, false); + doTestWS(true, true); + } + + public void testSpaceNonNs() + throws XMLStreamException + { + doTestWS(false, false); + doTestWS(false, true); + } + + public void testFalseSpace() + throws XMLStreamException + { + doTestFalseWS(true, false); + doTestFalseWS(true, true); + doTestFalseWS(false, false); + doTestFalseWS(false, true); + } + + /* + //////////////////////////////////////// + // Private methods, shared test code + //////////////////////////////////////// + */ + + public void doTestWS(boolean ns, boolean coalesce) + throws XMLStreamException + { + final String XML = "\n" + +"\n" + +"]>" + +"\n" + +" \n" + +""; + XMLStreamReader2 sr = getReader(XML, ns, coalesce); + + assertTokenType(START_DOCUMENT, sr.getEventType()); + assertTokenType(DTD, sr.next()); + + assertTokenType(START_ELEMENT, sr.next()); + assertEquals("root", sr.getLocalName()); + + assertTokenType(SPACE, sr.next()); + assertEquals("\n ", getAndVerifyText(sr)); + + assertTokenType(START_ELEMENT, sr.next()); + assertEquals("leaf", sr.getLocalName()); + assertTokenType(END_ELEMENT, sr.next()); + assertEquals("leaf", sr.getLocalName()); + + assertTokenType(SPACE, sr.next()); + assertEquals("\n", getAndVerifyText(sr)); + + assertTokenType(END_ELEMENT, sr.next()); + assertEquals("root", sr.getLocalName()); + + assertTokenType(END_DOCUMENT, sr.next()); + } + + public void doTestFalseWS(boolean ns, boolean coalesce) + throws XMLStreamException + { + final String XML = "\n" + +"\n" + +"]>" + +"\n" + +" Foobar" + +""; + XMLStreamReader2 sr = getReader(XML, ns, coalesce); + + assertTokenType(START_DOCUMENT, sr.getEventType()); + assertTokenType(DTD, sr.next()); + + assertTokenType(START_ELEMENT, sr.next()); + assertEquals("root", sr.getLocalName()); + + /* not 100% if this is expected in coalescing mode too, + * but it is the way it's implemented, and kind of makes + * sense even though there are alternatives + */ + assertTokenType(SPACE, sr.next()); + assertEquals("\n ", getAndVerifyText(sr)); + assertTokenType(CHARACTERS, sr.next()); + assertEquals("Foo", getAndVerifyText(sr)); + + assertTokenType(START_ELEMENT, sr.next()); + assertEquals("leaf", sr.getLocalName()); + assertTokenType(END_ELEMENT, sr.next()); + assertEquals("leaf", sr.getLocalName()); + + assertTokenType(CHARACTERS, sr.next()); + assertEquals("bar", getAndVerifyText(sr)); + + assertTokenType(END_ELEMENT, sr.next()); + assertEquals("root", sr.getLocalName()); + + assertTokenType(END_DOCUMENT, sr.next()); + } + + + /* + //////////////////////////////////////// + // Private methods, other + //////////////////////////////////////// + */ + + private XMLStreamReader2 getReader(String contents, boolean nsAware, + boolean coal) + throws XMLStreamException + { + XMLInputFactory2 f = getInputFactory(); + setNamespaceAware(f, nsAware); + setCoalescing(f, coal); + setSupportDTD(f, true); + setValidating(f, false); + return constructStreamReader(f, contents); + } +} + diff -Nru libwoodstox-java-4.1.3/src/test/java/stax2/dtd/TestNsDefaults.java libwoodstox-java-5.1.0/src/test/java/stax2/dtd/TestNsDefaults.java --- libwoodstox-java-4.1.3/src/test/java/stax2/dtd/TestNsDefaults.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/stax2/dtd/TestNsDefaults.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,83 @@ +package stax2.dtd; + +import javax.xml.stream.XMLStreamException; + +import org.codehaus.stax2.*; + +import stax2.BaseStax2Test; + +/** + * Test class that checks whether namespace declarations gained via + * attribute defaulting work. + */ +public class TestNsDefaults + extends BaseStax2Test +{ + public void testValidNsFromDefaultAttrs() + throws XMLStreamException + { + final String XML = + "\n" + +"\n" + +"]>" + +"" + ; + + XMLStreamReader2 sr = getReader(XML, true); + assertTokenType(DTD, sr.next()); + assertTokenType(START_ELEMENT, sr.next()); + assertEquals("node", sr.getLocalName()); + assertElemNotInNamespace(sr); + assertNoElemPrefix(sr); + assertEquals(1, sr.getAttributeCount()); + assertEquals(1, sr.getNamespaceCount()); + + assertEquals("ns", sr.getNamespacePrefix(0)); + assertEquals("http://expl", sr.getNamespaceURI(0)); + + assertEquals("attr", sr.getAttributeLocalName(0)); + assertEquals("ns", sr.getAttributePrefix(0)); + assertEquals("http://expl", sr.getAttributeNamespace(0)); + assertEquals("123", sr.getAttributeValue(0)); + + assertTokenType(START_ELEMENT, sr.next()); + assertEquals("node", sr.getLocalName()); + assertElemNotInNamespace(sr); + assertNoElemPrefix(sr); + + assertEquals(1, sr.getAttributeCount()); + assertEquals(1, sr.getNamespaceCount()); + + assertEquals("ns", sr.getNamespacePrefix(0)); + assertEquals("http://default", sr.getNamespaceURI(0)); + + assertEquals("attr", sr.getAttributeLocalName(0)); + assertNoAttrPrefix(sr.getAttributePrefix(0)); + assertNoAttrNamespace(sr.getAttributeNamespace(0)); + assertEquals("456", sr.getAttributeValue(0)); + + assertTokenType(END_ELEMENT, sr.next()); + assertEquals("node", sr.getLocalName()); + + assertTokenType(END_ELEMENT, sr.next()); + assertEquals("node", sr.getLocalName()); + } + + /* + //////////////////////////////////////// + // Private methods + //////////////////////////////////////// + */ + + private XMLStreamReader2 getReader(String contents, boolean nsAware) + throws XMLStreamException + { + XMLInputFactory2 f = getInputFactory(); + setNamespaceAware(f, nsAware); + setCoalescing(f, false); + setSupportDTD(f, true); + setValidating(f, false); + return constructStreamReader(f, contents); + } +} diff -Nru libwoodstox-java-4.1.3/src/test/java/stax2/dtd/TestReaderWithDTD.java libwoodstox-java-5.1.0/src/test/java/stax2/dtd/TestReaderWithDTD.java --- libwoodstox-java-4.1.3/src/test/java/stax2/dtd/TestReaderWithDTD.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/stax2/dtd/TestReaderWithDTD.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,74 @@ +package stax2.dtd; + +import javax.xml.stream.XMLStreamException; + +import org.codehaus.stax2.XMLInputFactory2; +import org.codehaus.stax2.XMLStreamReader2; + +import stax2.BaseStax2Test; + +public class TestReaderWithDTD extends BaseStax2Test +{ + public void testGetPrefixedName() throws XMLStreamException + { + doTestGetPrefixedName(false); + doTestGetPrefixedName(true); + } + + /* + /////////////////////////////////////////////////////////////////////// + // Helper methods + /////////////////////////////////////////////////////////////////////// + */ + + public void doTestGetPrefixedName(boolean ns) + throws XMLStreamException + { + final String XML = + "'>\n" + +"]>" + +"" + +"" + +"&intEnt;" + +"" + ; + XMLStreamReader2 sr = getReader(XML, ns); + try { + assertTokenType(DTD, sr.next()); + assertEquals("root", sr.getPrefixedName()); + assertTokenType(START_ELEMENT, sr.next()); + assertEquals("root", sr.getPrefixedName()); + assertTokenType(START_ELEMENT, sr.next()); + assertEquals("xy:elem", sr.getPrefixedName()); + assertTokenType(PROCESSING_INSTRUCTION, sr.next()); + assertEquals("proc", sr.getPrefixedName()); + assertTokenType(START_ELEMENT, sr.next()); + assertEquals("leaf", sr.getPrefixedName()); + assertTokenType(END_ELEMENT, sr.next()); + assertEquals("leaf", sr.getPrefixedName()); + assertTokenType(START_ELEMENT, sr.next()); + assertEquals("another:x", sr.getPrefixedName()); + assertTokenType(END_ELEMENT, sr.next()); + assertEquals("another:x", sr.getPrefixedName()); + assertTokenType(END_ELEMENT, sr.next()); + assertEquals("xy:elem", sr.getPrefixedName()); + assertTokenType(END_ELEMENT, sr.next()); + assertEquals("root", sr.getPrefixedName()); + assertTokenType(END_DOCUMENT, sr.next()); + } catch (XMLStreamException xse) { + fail("Did not expect any problems during parsing, but got: "+xse); + } + } + + private XMLStreamReader2 getReader(String contents, boolean nsAware) + throws XMLStreamException + { + XMLInputFactory2 f = getInputFactory(); + setCoalescing(f, true); + setSupportDTD(f, true); + setNamespaceAware(f, nsAware); + setValidating(f, false); + return constructStreamReader(f, contents); + } +} diff -Nru libwoodstox-java-4.1.3/src/test/java/stax2/evt/TestDTDEvent.java libwoodstox-java-5.1.0/src/test/java/stax2/evt/TestDTDEvent.java --- libwoodstox-java-4.1.3/src/test/java/stax2/evt/TestDTDEvent.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/stax2/evt/TestDTDEvent.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,75 @@ +package stax2.evt; + +import java.io.StringWriter; + +import javax.xml.namespace.QName; +import javax.xml.stream.*; +import javax.xml.stream.events.*; + +import org.codehaus.stax2.*; +import org.codehaus.stax2.evt.*; + +import stax2.BaseStax2Test; + +/** + * Set of unit tests that checks that {@linkAttributeInfo} + * implementation works as expected. + */ +public class TestDTDEvent + extends BaseStax2Test +{ + public void testDTDCreation() + throws XMLStreamException + { + final String COMMENT_STR = ""; + + XMLOutputFactory f = getOutputFactory(); + StringWriter strw = new StringWriter(); + XMLEventWriter w = f.createXMLEventWriter(strw); + + XMLEventFactory2 evtf = getEventFactory(); + + w.add(evtf.createStartDocument()); + w.add(evtf.createDTD("root", "sysid", "pubid", COMMENT_STR)); + w.add(evtf.createStartElement("", "", "root")); + w.add(evtf.createEndElement("", "", "root")); + w.add(evtf.createEndDocument()); + + w.close(); + + String xmlContent = strw.toString(); + XMLInputFactory f2 = getInputFactory(); + + /* Hmmh. This is bit problematic: we don't want to read an + * external subset... yet it'd be good to test that system + * and public ids are properly parsed. For now, let's see if + * this works: + */ + setSupportDTD(f2, false); + XMLEventReader2 er = constructEventReader(f2, xmlContent); + + assertTokenType(START_DOCUMENT, er.nextEvent().getEventType()); + XMLEvent evt = er.nextEvent(); + assertTokenType(DTD, evt.getEventType()); + + // Check that all properties are correct: + DTD2 dtd = (DTD2) evt; + assertEquals("root", dtd.getRootName()); + assertEquals("pubid", dtd.getPublicId()); + assertEquals("sysid", dtd.getSystemId()); + String intss = dtd.getInternalSubset().trim(); + assertEquals(COMMENT_STR, intss); + + evt = er.nextEvent(); + assertTokenType(START_ELEMENT, evt.getEventType()); + StartElement start = evt.asStartElement(); + QName name = start.getName(); + assertEquals("root", name.getLocalPart()); + + // just to test hasNextEvent()... + assertTrue(er.hasNextEvent()); + + assertTokenType(END_ELEMENT, er.nextEvent().getEventType()); + assertTokenType(END_DOCUMENT, er.nextEvent().getEventType()); + } +} diff -Nru libwoodstox-java-4.1.3/src/test/java/stax2/evt/TestEventEquality.java libwoodstox-java-5.1.0/src/test/java/stax2/evt/TestEventEquality.java --- libwoodstox-java-4.1.3/src/test/java/stax2/evt/TestEventEquality.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/stax2/evt/TestEventEquality.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,44 @@ +package stax2.evt; + +import javax.xml.stream.*; +import javax.xml.stream.events.XMLEvent; + +import stax2.BaseStax2Test; + +/** + * As of Stax2 v3 (~= Woodstox 4.0), XMLEvent instances are expected + * to implement simple equality comparison. Stax2 reference implementation + * implements this for all event types. This test suite verifies that + * equality checks work for simple cases. + */ +public class TestEventEquality + extends BaseStax2Test +{ + public void testSimple() + throws XMLStreamException + { + XMLInputFactory f = getInputFactory(); + setNamespaceAware(f, true); + String XML = + "Text..." + +"\r\n" + +"\n" + +"" + ; + + XMLEventReader er1 = constructEventReader(f, XML); + XMLEventReader er2 = constructEventReader(f, XML); + + while (er1.hasNext()) { + XMLEvent e1 = er1.nextEvent(); + XMLEvent e2 = er2.nextEvent(); + + if (!e1.equals(e2) || !e2.equals(e1)) { + fail("Event 1 (type "+e1.getEventType()+") differs from Event2 (type "+e2.getEventType()+"), location "+e1.getLocation()); + } + if (e1.hashCode() != e2.hashCode()) { + fail("Hash codes differ for events (type: "+e2.getEventType()+"), location "+e1.getLocation()); + } + } + } +} diff -Nru libwoodstox-java-4.1.3/src/test/java/stax2/evt/TestEventTypes.java libwoodstox-java-5.1.0/src/test/java/stax2/evt/TestEventTypes.java --- libwoodstox-java-4.1.3/src/test/java/stax2/evt/TestEventTypes.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/stax2/evt/TestEventTypes.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,52 @@ +package stax2.evt; + +import java.io.*; + +import javax.xml.stream.*; + +import org.codehaus.stax2.*; +import org.codehaus.stax2.evt.*; + +import stax2.BaseStax2Test; + +/** + * Set of unit tests that checks that new Stax2 features work (generically) + * for event instances. + */ +public class TestEventTypes + extends BaseStax2Test +{ + /** + * This unit test does some crude checking to ensure that the usual + * events can be output to the specified writer. Events are here + * constructed using event factory. + */ + public void testEventObjectOutput() + throws XMLStreamException + { + XMLEventFactory2 evtf = getEventFactory(); + XMLOutputFactory2 f = getOutputFactory(); + StringWriter strw = new StringWriter(); + XMLStreamWriter2 sw = f.createXMLStreamWriter(strw, "UTF-8"); + + XMLEvent2 evt = (XMLEvent2) evtf.createStartDocument(); + evt.writeUsing(sw); + + // Let's output root element with no attrs + ((XMLEvent2) evtf.createStartElement("", "", "root")).writeUsing(sw); + ((XMLEvent2) evtf.createEndElement("", "", "root")).writeUsing(sw); + + ((XMLEvent2) evtf.createEndDocument()).writeUsing(sw); + + sw.close(); + + // Ok, parsing: + XMLInputFactory f2 = getInputFactory(); + XMLStreamReader sr = f2.createXMLStreamReader(new StringReader(strw.toString())); + assertTokenType(START_DOCUMENT, sr.getEventType()); + assertTokenType(START_ELEMENT, sr.next()); + assertTokenType(END_ELEMENT, sr.next()); + assertTokenType(END_DOCUMENT, sr.next()); + sr.close(); + } +} diff -Nru libwoodstox-java-4.1.3/src/test/java/stax2/evt/TestStartElementEvent.java libwoodstox-java-5.1.0/src/test/java/stax2/evt/TestStartElementEvent.java --- libwoodstox-java-4.1.3/src/test/java/stax2/evt/TestStartElementEvent.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/stax2/evt/TestStartElementEvent.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,129 @@ +package stax2.evt; + +import java.io.*; +import java.util.*; + +import javax.xml.namespace.QName; +import javax.xml.stream.*; +import javax.xml.stream.events.*; + +import com.ctc.wstx.evt.DefaultEventAllocator; + +import stax2.BaseStax2Test; + +/** + * Set of unit tests that checks that {@link StartElement} + * implementation works as expected. + */ +public class TestStartElementEvent + extends BaseStax2Test +{ + private final XMLInputFactory XML_F = getNewInputFactory(); + + public void testStartEventAttrs() throws Exception + { + final String DOC = "" + +"some content" + +"some content" + +""; + XMLEventReader er = XML_F.createXMLEventReader(new StringReader(DOC)); + + ArrayList elemEvents = new ArrayList(); + + assertTokenType(START_DOCUMENT, er.nextEvent()); + XMLEvent evt = er.nextEvent(); + assertTokenType(START_ELEMENT, evt); + elemEvents.add(evt.asStartElement()); + evt = er.nextEvent(); + assertTokenType(START_ELEMENT, evt); + elemEvents.add(evt.asStartElement()); + + assertTokenType(CHARACTERS, er.nextEvent()); + assertTokenType(END_ELEMENT, er.nextEvent()); + evt = er.nextEvent(); + assertTokenType(START_ELEMENT, evt); + elemEvents.add(evt.asStartElement()); + + assertTokenType(CHARACTERS, er.nextEvent()); + assertTokenType(END_ELEMENT, er.nextEvent()); + assertTokenType(END_ELEMENT, er.nextEvent()); + er.close(); + + // Ok, got 3 start elements, and accessing the SECOND one triggers + // the problem + _verifyAttrCount(elemEvents.get(1), 4, true); + } + + // From [woodstox-core#43] + public void testIsDefaultAttr() throws Exception + { + String DOC = ""; + XMLStreamReader stream = XML_F.createXMLStreamReader(new StringReader(DOC)); + DefaultEventAllocator allocator = DefaultEventAllocator.getDefaultInstance(); + XMLEventFactory eventFactory = getNewEventFactory(); + + assertTokenType(START_ELEMENT, stream.next()); + XMLEvent event = allocator.allocate(stream); + assertTrue(event.isStartElement()); + + StartElement startOrig = event.asStartElement(); + Attribute attr = startOrig.getAttributeByName(new QName("b")); + assertNotNull(attr); + assertTrue(attr.isSpecified()); + StartElement startAlloc = eventFactory.createStartElement(startOrig.getName(), + startOrig.getAttributes(), startOrig.getNamespaces()); + + attr = startAlloc.getAttributeByName(new QName("b")); + assertNotNull(attr); + assertTrue(attr.isSpecified()); + } + + /* + ///////////////////////////////////////////////// + // Helper methods + ///////////////////////////////////////////////// + */ + + private void _verifyAttrCount(StartElement start, int expCount, boolean hasProb) + { + // First things first: do we have the 'problem' attribute? + Attribute probAttr = start.getAttributeByName(new QName("problem")); + if (hasProb) { + assertNotNull(probAttr); + } else { + assertNull(probAttr); + } + + Iterator it = start.getAttributes(); + @SuppressWarnings("unused") + int count = 0; + Map attrs = new HashMap(); + + // First, collect the attributes + while (it.hasNext()) { + ++count; + Attribute attr = (Attribute) it.next(); + attrs.put(attr.getName(), attr.getValue()); + } + + assertEquals(expCount, attrs.size()); + + // Then verify we can access them ok + //for (Map.Entry en : attrs) { + + Iterator> it2 = attrs.entrySet().iterator(); + while (it2.hasNext()) { + Map.Entry en = it2.next(); + QName key = en.getKey(); + String value = en.getValue(); + + // should find it via StartElement too + Attribute attr = start.getAttributeByName(key); + assertNotNull(attr); + assertEquals(value, attr.getValue()); + + // .. how about a bogus name? + assertNull(start.getAttributeByName(new QName("bogus+"+key.getLocalPart()))); + } + } +} diff -Nru libwoodstox-java-4.1.3/src/test/java/stax2/stream/entity-from-ext.xml libwoodstox-java-5.1.0/src/test/java/stax2/stream/entity-from-ext.xml --- libwoodstox-java-4.1.3/src/test/java/stax2/stream/entity-from-ext.xml 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/stax2/stream/entity-from-ext.xml 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,3 @@ + + + diff -Nru libwoodstox-java-4.1.3/src/test/java/stax2/stream/external1.xml libwoodstox-java-5.1.0/src/test/java/stax2/stream/external1.xml --- libwoodstox-java-4.1.3/src/test/java/stax2/stream/external1.xml 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/stax2/stream/external1.xml 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1 @@ +&simpleEntity; \ No newline at end of file diff -Nru libwoodstox-java-4.1.3/src/test/java/stax2/stream/external2.xml libwoodstox-java-5.1.0/src/test/java/stax2/stream/external2.xml --- libwoodstox-java-4.1.3/src/test/java/stax2/stream/external2.xml 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/stax2/stream/external2.xml 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1 @@ +&simpleEntity; \ No newline at end of file diff -Nru libwoodstox-java-4.1.3/src/test/java/stax2/stream/external.dtd libwoodstox-java-5.1.0/src/test/java/stax2/stream/external.dtd --- libwoodstox-java-4.1.3/src/test/java/stax2/stream/external.dtd 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/stax2/stream/external.dtd 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,11 @@ + + + + + + + + + + + diff -Nru libwoodstox-java-4.1.3/src/test/java/stax2/stream/TestAttrBasic.java libwoodstox-java-5.1.0/src/test/java/stax2/stream/TestAttrBasic.java --- libwoodstox-java-4.1.3/src/test/java/stax2/stream/TestAttrBasic.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/stax2/stream/TestAttrBasic.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,31 @@ +package stax2.stream; + +import javax.xml.stream.*; + +import stax2.BaseStax2Test; + +public class TestAttrBasic + extends BaseStax2Test +{ + public void testNormalization() + throws XMLStreamException + { + String[] LFs = new String[] { "\n", "\r", "\r\n" }; + for (int i = 0; i < LFs.length; ++i) { + XMLStreamReader sr = constructNsStreamReader("", true); + assertTokenType(START_DOCUMENT, sr.getEventType()); + assertTokenType(START_ELEMENT, sr.next()); + assertEquals(1, sr.getAttributeCount()); + // line feeds to be normalized into space + assertEquals(" ", sr.getAttributeValue(0)); + assertTokenType(END_ELEMENT, sr.next()); + assertTokenType(END_DOCUMENT, sr.next()); + } + + XMLStreamReader sr = constructNsStreamReader("", true); + assertTokenType(START_ELEMENT, sr.next()); + assertEquals(1, sr.getAttributeCount()); + // entity as is, \n as space + assertEquals("\r ", sr.getAttributeValue(0)); + } +} diff -Nru libwoodstox-java-4.1.3/src/test/java/stax2/stream/TestAttrInfo.java libwoodstox-java-5.1.0/src/test/java/stax2/stream/TestAttrInfo.java --- libwoodstox-java-4.1.3/src/test/java/stax2/stream/TestAttrInfo.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/stax2/stream/TestAttrInfo.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,233 @@ +package stax2.stream; + +import javax.xml.stream.*; + +import org.codehaus.stax2.*; + +import stax2.BaseStax2Test; + +/** + * Set of unit tests that checks that the {@link AttributeInfo} implementation + * works as expected. + * + * @author Tatu Saloranta + */ +public class TestAttrInfo + extends BaseStax2Test +{ + final static String DEFAULT_VALUE = "default value"; + + final static String TEST_DOC_BASIC = + "" + +"" + +""; + + final static String TEST_DOC_DTD = + "" + +"\n" + +"\n" + +"\n" + +"\n" + +"\n" + +"\n" + +"\n" + +"\n" + +"\n" + +"\n" + +"\n" + +"]>" + +"" + +""; + + /** + * Baseline test case that does not use any information originating + * from DTDs. + */ + public void testAttrFindBasic() + throws XMLStreamException + { + XMLStreamReader2 sr = getAttrReader(TEST_DOC_BASIC); + + // Let's verify basic facts... + assertEquals(4, sr.getAttributeCount()); + + AttributeInfo info = sr.getAttributeInfo(); + assertNotNull(info); + + // And then see if we can find the attributes + { + int ix = info.findAttributeIndex(null, "textAttr"); + if (ix < 0) { + fail("Failed to find index of attribute 'textAttr'"); + } + assertEquals("value", sr.getAttributeValue(ix)); + + ix = info.findAttributeIndex(null, "textAttr2"); + if (ix >= 0) { + fail("Found a phantom index for (missing) attribute 'textAttr2'"); + } + + ix = info.findAttributeIndex(null, "textAttr3"); + if (ix < 0) { + fail("Failed to find index of attribute 'textAttr3'"); + } + assertEquals("1", sr.getAttributeValue(ix)); + } + + // Notation attr? + { + int ix = info.findAttributeIndex(null, "notation"); + if (ix < 0) { + fail("Failed to find index of attribute 'notation'"); + } + assertEquals("not2", sr.getAttributeValue(ix)); + // No DTD info available, should NOT find via this: + + int notIx = info.getNotationAttributeIndex(); + if (notIx >= 0) { + fail("Found a bogus notation attribute index ("+notIx+")"); + } + } + + // Ok, how about the id attr? + { + int ix = info.findAttributeIndex(null, "idAttr"); + if (ix < 0) { + fail("Failed to find index of attribute 'id'"); + } + assertEquals("idValue", sr.getAttributeValue(ix)); + + // .. but not by type, as that depends on DTD or Xml:id + } + + // Ok; but how about of non-existing ones? + assertEquals(-1, info.findAttributeIndex(null, "foo")); + assertEquals(-1, info.findAttributeIndex("http://foo", "id")); + + // and then the other (empty) element: + assertTokenType(START_ELEMENT, sr.next()); + assertEquals(0, sr.getAttributeCount()); + assertEquals(-1, info.findAttributeIndex(null, "dummyAttr")); + + finishAttrReader(sr); + } + + /** + * More complex test case, in which information from DTD + * (like attribute default values, notations) are needed. + */ + public void testAttrFindDTD() + throws XMLStreamException + { + XMLStreamReader2 sr = getAttrReader(TEST_DOC_DTD); + + // Let's verify basic facts... + assertEquals(5, sr.getAttributeCount()); + + AttributeInfo info = sr.getAttributeInfo(); + assertNotNull(info); + + // And then see if we can find the attributes + { + int ix = info.findAttributeIndex(null, "textAttr"); + if (ix < 0) { + fail("Failed to find index of attribute 'textAttr'"); + } + assertEquals("value", sr.getAttributeValue(ix)); + + ix = info.findAttributeIndex(null, "textAttr2"); + if (ix >= 0) { + fail("Found a phantom index for (missing) attribute 'textAttr2'"); + } + + ix = info.findAttributeIndex(null, "textAttr3"); + if (ix < 0) { + fail("Failed to find index of attribute 'textAttr3'"); + } + assertEquals("1", sr.getAttributeValue(ix)); + } + + // Notation attr? + { + int ix = info.findAttributeIndex(null, "notation"); + if (ix < 0) { + fail("Failed to find index of attribute 'notation'"); + } + int notIx = info.getNotationAttributeIndex(); + if (notIx < 0) { + fail("Failed to find index of the notation attribute"); + } + assertEquals(ix, notIx); + assertEquals("not2", sr.getAttributeValue(notIx)); + } + + // Ok, how about the id attr? + { + int ix = info.findAttributeIndex(null, "idAttr"); + if (ix < 0) { + fail("Failed to find index of attribute 'id'"); + } + int idIx = info.getIdAttributeIndex(); + if (idIx < 0) { + fail("Failed to find index of the id attribute"); + } + assertEquals(ix, idIx); + assertEquals("idValue", sr.getAttributeValue(idIx)); + } + + // Ok; but how about of non-existing ones? + assertEquals(-1, info.findAttributeIndex(null, "foo")); + assertEquals(-1, info.findAttributeIndex("http://foo", "id")); + + // and then the other (empty) element: + assertTokenType(START_ELEMENT, sr.next()); + assertEquals(0, sr.getAttributeCount()); + assertEquals(-1, info.findAttributeIndex(null, "dummyAttr")); + + finishAttrReader(sr); + } + + /* + //////////////////////////////////////// + // Private methods + //////////////////////////////////////// + */ + + private XMLStreamReader2 getAttrReader(String str) + throws XMLStreamException + { + XMLStreamReader2 sr = getReader(str); + assertTokenType(START_DOCUMENT, sr.getEventType()); + int type = sr.next(); + if (type == DTD) { + type = sr.next(); + } + assertTokenType(START_ELEMENT, type); + return sr; + } + + private void finishAttrReader(XMLStreamReader sr) + throws XMLStreamException + { + while (sr.getEventType() != END_DOCUMENT) { + sr.next(); + } + } + + private XMLStreamReader2 getReader(String contents) + throws XMLStreamException + { + XMLInputFactory f = getInputFactory(); + setCoalescing(f, false); // shouldn't really matter + setNamespaceAware(f, true); + setSupportDTD(f, true); + /* Probably need to enable validation, to get all the attribute + * type info processed and accessible? + */ + setValidating(f, true); + return constructStreamReader(f, contents); + } +} diff -Nru libwoodstox-java-4.1.3/src/test/java/stax2/stream/TestClosing.java libwoodstox-java-5.1.0/src/test/java/stax2/stream/TestClosing.java --- libwoodstox-java-4.1.3/src/test/java/stax2/stream/TestClosing.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/stax2/stream/TestClosing.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,283 @@ +package stax2.stream; + +import java.io.*; + +import javax.xml.stream.*; +import javax.xml.transform.stream.StreamSource; + +import org.codehaus.stax2.*; +import org.codehaus.stax2.io.Stax2StringSource; + +import stax2.BaseStax2Test; + +/** + * This unit test suite verifies that the auto-closing feature works + * as expected (both explicitly, and via Source object being passed). + * + * @author Tatu Saloranta + * + * @since 3.0 + */ +@SuppressWarnings("resource") +public class TestClosing + extends BaseStax2Test +{ + /** + * This unit test checks the default behaviour; with no auto-close, no + * automatic closing should occur, nor explicit one unless specific + * forcing method is used. + */ + public void testNoAutoCloseReader() + throws XMLStreamException + { + final String XML = "..."; + + XMLInputFactory2 f = getFactory(false); + MyReader input = new MyReader(XML); + XMLStreamReader2 sr = (XMLStreamReader2) f.createXMLStreamReader(input); + // shouldn't be closed to begin with... + assertFalse(input.isClosed()); + assertTokenType(START_ELEMENT, sr.next()); + assertFalse(input.isClosed()); + + // nor closed half-way through with basic close() + sr.close(); + assertFalse(input.isClosed()); + + // ok, let's finish it up: + streamThrough(sr); + // still not closed + assertFalse(input.isClosed()); + + // except when forced to: + sr.closeCompletely(); + assertTrue(input.isClosed()); + + // ... and should be ok to call it multiple times: + sr.closeCompletely(); + sr.closeCompletely(); + assertTrue(input.isClosed()); + } + + public void testNoAutoCloseStream() + throws XMLStreamException, IOException + { + final String XML = "..."; + + XMLInputFactory2 f = getFactory(false); + MyStream input = new MyStream(XML.getBytes("UTF-8")); + XMLStreamReader2 sr = (XMLStreamReader2) f.createXMLStreamReader(input); + // shouldn't be closed to begin with... + assertFalse(input.isClosed()); + assertTokenType(START_ELEMENT, sr.next()); + assertFalse(input.isClosed()); + + // nor closed half-way through with basic close() + sr.close(); + assertFalse(input.isClosed()); + + // ok, let's finish it up: + streamThrough(sr); + // still not closed + assertFalse(input.isClosed()); + + // except when forced to: + sr.closeCompletely(); + assertTrue(input.isClosed()); + + // ... and should be ok to call it multiple times: + sr.closeCompletely(); + assertTrue(input.isClosed()); + } + + /** + * This unit test checks that when auto-closing option is set, the + * passed in input stream does get properly closed both when EOF + * is hit, and when we call close() prior to EOF. + */ + public void testAutoCloseEnabled() + throws XMLStreamException + { + final String XML = "..."; + + // First, explicit close: + XMLInputFactory2 f = getFactory(true); + MyReader input = new MyReader(XML); + XMLStreamReader2 sr = (XMLStreamReader2) f.createXMLStreamReader(input); + assertFalse(input.isClosed()); + assertTokenType(START_ELEMENT, sr.next()); + assertFalse(input.isClosed()); + sr.close(); + assertTrue(input.isClosed()); + // also, let's verify we can call more than once: + sr.close(); + sr.close(); + assertTrue(input.isClosed()); + + // Then implicit close (real auto-close): + input = new MyReader(XML); + sr = (XMLStreamReader2) f.createXMLStreamReader(input); + assertFalse(input.isClosed()); + streamThrough(sr); + assertTrue(input.isClosed()); + + // And then similarly for Source abstraction for streams + MySource src = MySource.createFor(XML); + sr = (XMLStreamReader2) f.createXMLStreamReader(src); + assertFalse(src.isClosed()); + assertTokenType(START_ELEMENT, sr.next()); + streamThrough(sr); + assertTrue(input.isClosed()); + } + + /** + * This unit test checks what happens when we use Result abstraction + * for passing in result stream/writer. Their handling differs depending + * on whether caller is considered to have access to the underlying + * physical object or not. + */ + public void testAutoCloseImplicit() + throws XMLStreamException + { + final String XML = "..."; + + // Factory with auto-close disabled: + XMLInputFactory2 f = getFactory(false); + + /* Ok, first: with regular (InputStream, Reader) streams no auto-closing + * because caller does have access: StreamSource retains given + * stream/reader as is. + */ + MySource input = MySource.createFor(XML); + XMLStreamReader2 sr = (XMLStreamReader2) f.createXMLStreamReader(input); + + assertFalse(input.isClosed()); + assertTokenType(START_ELEMENT, sr.next()); + assertFalse(input.isClosed()); + sr.close(); + assertFalse(input.isClosed()); + // also, let's verify we can call more than once: + sr.close(); + sr.close(); + assertFalse(input.isClosed()); + + /* And then more interesting case; verifying that Stax2Source + * sub-classes are implicitly auto-closed: they need to be, because + * they do not (necessarily) expose underlying physical stream. + * We can test this by using any Stax2Source impl. + */ + MyStringSource src = new MyStringSource(XML); + sr = (XMLStreamReader2) f.createXMLStreamReader(src); + + assertFalse(src.isClosed()); + assertTokenType(START_ELEMENT, sr.next()); + assertFalse(src.isClosed()); + streamThrough(sr); + assertTrue(src.isClosed()); + + // similarly, let's verify plain old close would do it + src = new MyStringSource(XML); + sr = (XMLStreamReader2) f.createXMLStreamReader(src); + assertFalse(src.isClosed()); + assertTokenType(START_ELEMENT, sr.next()); + assertFalse(src.isClosed()); + sr.close(); + assertTrue(src.isClosed()); + } + + /* + //////////////////////////////////////// + // Non-test methods + //////////////////////////////////////// + */ + + XMLInputFactory2 getFactory(boolean autoClose) + { + XMLInputFactory2 f = getInputFactory(); + f.setProperty(XMLInputFactory2.P_AUTO_CLOSE_INPUT, + Boolean.valueOf(autoClose)); + return f; + } + + /* + //////////////////////////////////////// + // Helper mock classes + //////////////////////////////////////// + */ + + final static class MyReader extends StringReader + { + boolean mIsClosed = false; + + public MyReader(String contents) { + super(contents); + } + + @Override + public void close() { + mIsClosed = true; + super.close(); + } + + public boolean isClosed() { return mIsClosed; } + } + + final static class MyStream extends ByteArrayInputStream + { + boolean mIsClosed = false; + + public MyStream(byte[] data) { + super(data); + } + + @Override + public void close() throws IOException { + mIsClosed = true; + super.close(); + } + + public boolean isClosed() { return mIsClosed; } + } + + final static class MySource + extends StreamSource + { + final MyReader mReader; + + private MySource(MyReader reader) { + super(reader); + mReader = reader; + } + + @SuppressWarnings("resource") + public static MySource createFor(String content) { + MyReader r = new MyReader(content); + return new MySource(r); + } + + public boolean isClosed() { + return mReader.isClosed(); + } + + @Override + public Reader getReader() { + return mReader; + } + } + + private final static class MyStringSource + extends Stax2StringSource + { + MyReader mReader; + + public MyStringSource(String s) { super(s); } + + @Override + public Reader constructReader() { + mReader = new MyReader(getText()); + return mReader; + } + + public boolean isClosed() { return mReader.isClosed(); } + } +} diff -Nru libwoodstox-java-4.1.3/src/test/java/stax2/stream/TestConfig.java libwoodstox-java-5.1.0/src/test/java/stax2/stream/TestConfig.java --- libwoodstox-java-4.1.3/src/test/java/stax2/stream/TestConfig.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/stax2/stream/TestConfig.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,75 @@ +package stax2.stream; + +import javax.xml.stream.*; + +import org.codehaus.stax2.*; + +import stax2.BaseStax2Test; + +/** + * Set of unit tests that checks that configuring of + * {@link XMLInputFactory2} works ok. + */ +public class TestConfig + extends BaseStax2Test +{ + public void testForXmlConformanceProfile() + throws XMLStreamException + { + // configureForXmlConformance + XMLInputFactory2 ifact = getNewInputFactory(); + ifact.configureForXmlConformance(); + assertEquals(Boolean.TRUE, ifact.getProperty(XMLInputFactory.SUPPORT_DTD)); + assertEquals(Boolean.TRUE, ifact.getProperty(XMLInputFactory.IS_NAMESPACE_AWARE)); + assertEquals(Boolean.TRUE, ifact.getProperty(XMLInputFactory.IS_REPLACING_ENTITY_REFERENCES)); + assertEquals(Boolean.TRUE, ifact.getProperty(XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES)); + } + + public void testForConvenienceProfile() + throws XMLStreamException + { + // configureForConvenience + XMLInputFactory2 ifact = getNewInputFactory(); + ifact.configureForConvenience(); + assertEquals(Boolean.TRUE, ifact.getProperty(XMLInputFactory.IS_COALESCING)); + assertEquals(Boolean.TRUE, ifact.getProperty(XMLInputFactory.IS_REPLACING_ENTITY_REFERENCES)); + assertEquals(Boolean.FALSE, ifact.getProperty(XMLInputFactory2.P_REPORT_PROLOG_WHITESPACE)); + assertEquals(Boolean.FALSE, ifact.getProperty(XMLInputFactory2.P_REPORT_CDATA)); + assertEquals(Boolean.TRUE, ifact.getProperty(XMLInputFactory2.P_PRESERVE_LOCATION)); + } + + public void testForSpeedProfile() + throws XMLStreamException + { + // configureForSpeed + XMLInputFactory2 ifact = getNewInputFactory(); + ifact.configureForSpeed(); + assertEquals(Boolean.FALSE, ifact.getProperty(XMLInputFactory.IS_COALESCING)); + assertEquals(Boolean.FALSE, ifact.getProperty(XMLInputFactory2.P_PRESERVE_LOCATION)); + assertEquals(Boolean.FALSE, ifact.getProperty(XMLInputFactory2.P_REPORT_PROLOG_WHITESPACE)); + assertEquals(Boolean.TRUE, ifact.getProperty(XMLInputFactory2.P_INTERN_NAMES)); + assertEquals(Boolean.TRUE, ifact.getProperty(XMLInputFactory2.P_INTERN_NS_URIS)); + } + + public void testForLowMemProfile() + throws XMLStreamException + { + // configureForLowMemUsage + XMLInputFactory2 ifact = getNewInputFactory(); + ifact.configureForLowMemUsage(); + assertEquals(Boolean.FALSE, ifact.getProperty(XMLInputFactory.IS_COALESCING)); + assertEquals(Boolean.FALSE, ifact.getProperty(XMLInputFactory2.P_PRESERVE_LOCATION)); + } + + public void testForRoundTrippingProfile() + throws XMLStreamException + { + // configureForRoundTripping + XMLInputFactory2 ifact = getNewInputFactory(); + ifact.configureForRoundTripping(); + assertEquals(Boolean.FALSE, ifact.getProperty(XMLInputFactory.IS_COALESCING)); + assertEquals(Boolean.FALSE, ifact.getProperty(XMLInputFactory.IS_REPLACING_ENTITY_REFERENCES)); + assertEquals(Boolean.TRUE, ifact.getProperty(XMLInputFactory2.P_REPORT_CDATA)); + assertEquals(Boolean.TRUE, ifact.getProperty(XMLInputFactory2.P_REPORT_PROLOG_WHITESPACE)); + } +} diff -Nru libwoodstox-java-4.1.3/src/test/java/stax2/stream/TestDuplicateAttributes.java libwoodstox-java-5.1.0/src/test/java/stax2/stream/TestDuplicateAttributes.java --- libwoodstox-java-4.1.3/src/test/java/stax2/stream/TestDuplicateAttributes.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/stax2/stream/TestDuplicateAttributes.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,43 @@ +package stax2.stream; + +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; + +import stax2.BaseStax2Test; + +/** + * This unit test exposes a bug in Woodstox's duplicate attribute detection logic. + */ +public class TestDuplicateAttributes + extends BaseStax2Test +{ + + /** + * This test shows a scenario where Woodstox correctly complains about duplicate attributes. + */ + public void testDupAttrsMinimal() throws XMLStreamException { + final XMLStreamReader reader = constructNsStreamReader("", false); + try { + reader.next(); + fail("Should have caught duplicate attributes"); + } catch (XMLStreamException e) { + verifyException(e, "duplicate attribute"); + } + reader.close(); + } + + /** + * This test shows a scenario where Woodstox fails to complain about duplicate attributes. + */ + public void testDupAttrsMultiple() throws XMLStreamException { + final XMLStreamReader reader = constructNsStreamReader( + "", false); + try { + reader.next(); + fail("Should have caught duplicate attributes"); + } catch (XMLStreamException e) { + verifyException(e, "duplicate attribute"); + } + reader.close(); + } +} diff -Nru libwoodstox-java-4.1.3/src/test/java/stax2/stream/TestGetElement.java libwoodstox-java-5.1.0/src/test/java/stax2/stream/TestGetElement.java --- libwoodstox-java-4.1.3/src/test/java/stax2/stream/TestGetElement.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/stax2/stream/TestGetElement.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,203 @@ +package stax2.stream; + +import java.io.*; +import java.util.*; + +import javax.xml.stream.*; + +import stax2.BaseStax2Test; + +/** + * Unit test(s) that verify correct functioning of + * {@link XMLStreamReader#getElementText}. This might actually + * belong more to the core StaxTest, but as bug was found from + * Woodstox, let's start by just adding them here first. + * + * @author Tatu Saloranta + * + * @since 3.0 + */ +public class TestGetElement + extends BaseStax2Test +{ + public void testLargeDocCoalesce() throws XMLStreamException + { + _testLargeDoc(true); + } + + public void testLargeDocNonCoalesce() throws XMLStreamException + { + _testLargeDoc(false); + } + + public void testLongSegmentCoalesce() throws XMLStreamException + { + _testLongSegment(true); + } + + public void testLongSegmentNonCoalesce() throws XMLStreamException + { + _testLongSegment(false); + } + + /* + /////////////////////////////////////////////// + // Second level test methods + /////////////////////////////////////////////// + */ + + private void _testLargeDoc(boolean coalesce) + throws XMLStreamException + { + final int LEN = 258000; + final long SEED = 72; + + ByteArrayOutputStream bos = new ByteArrayOutputStream(LEN+2000); + int rowCount = generateDoc(SEED, LEN, bos); + XMLInputFactory f = getInputFactory(); + byte[] docData = bos.toByteArray(); + + // Let's test both coalescing and non-coalescing: + setCoalescing(f, coalesce); + XMLStreamReader sr = f.createXMLStreamReader(new ByteArrayInputStream(docData)); + assertTokenType(START_ELEMENT, sr.next()); + assertEquals("data", sr.getLocalName()); + int actRowCount = 0; + Random r = new Random(SEED); + + while (sr.nextTag() == START_ELEMENT) { // + ++actRowCount; + assertEquals("row", sr.getLocalName()); + expectElemText(sr, "a", String.valueOf(r.nextInt())); + expectElemText(sr, "b", String.valueOf(r.nextLong())); + expectElemText(sr, "c", String.valueOf(r.nextBoolean())); + assertTokenType(END_ELEMENT, sr.nextTag()); // match + } + assertEquals(rowCount, actRowCount); + } + + private void _testLongSegment(boolean coalesce) + throws XMLStreamException + { + final int LEN = 129000; + Random r = new Random(17); + + StringBuilder sb = new StringBuilder(LEN + 2000); + while (sb.length() < LEN) { + switch (r.nextInt() & 7) { + case 0: + sb.append("123"); + break; + case 1: + sb.append("foo\nbar"); + break; + case 2: + sb.append("rock & roll!"); + break; + default: + sb.append(sb.length()); + break; + } + } + + String contentStr = sb.toString(); + StringWriter strw = new StringWriter(LEN + 4000); + XMLStreamWriter sw = getOutputFactory().createXMLStreamWriter(strw); + + sw.writeStartDocument(); + sw.writeStartElement("data"); + sw.writeCharacters(contentStr); + sw.writeEndElement(); + sw.writeEndDocument(); + sw.close(); + + XMLInputFactory f = getInputFactory(); + setCoalescing(f, coalesce); + XMLStreamReader sr = f.createXMLStreamReader(new StringReader(strw.toString())); + assertTokenType(START_ELEMENT, sr.next()); + assertEquals("data", sr.getLocalName()); + String actStr = sr.getElementText(); + assertEquals(contentStr, actStr); + assertTokenType(END_ELEMENT, sr.getEventType()); + assertTokenType(END_DOCUMENT, sr.next()); + } + + public void testGetMixedContentElementText() throws Exception + { + final String XML = "foo"; + + XMLInputFactory ifact = getInputFactory(); + XMLStreamReader sr; + + // Start with non-coalescing case + setCoalescing(ifact, false); + sr = ifact.createXMLStreamReader(new StringReader(XML)); + assertTokenType(START_ELEMENT, sr.next()); + assertEquals("foobar", sr.getElementText()); + assertTokenType(END_ELEMENT, sr.getEventType()); + assertTokenType(END_DOCUMENT, sr.next()); + sr.close(); + + // and then with coalescing + setCoalescing(ifact, true); + sr = ifact.createXMLStreamReader(new StringReader(XML)); + assertTokenType(START_ELEMENT, sr.next()); + assertEquals("foobar", sr.getElementText()); + assertTokenType(END_ELEMENT, sr.getEventType()); + assertTokenType(END_DOCUMENT, sr.next()); + sr.close(); + } + + /* + /////////////////////////////////////////////// + // Helper methods + /////////////////////////////////////////////// + */ + + private int generateDoc(long SEED, int LEN, ByteArrayOutputStream out) + throws XMLStreamException + { + XMLStreamWriter sw = getOutputFactory().createXMLStreamWriter(out, "UTF-8"); + Random r = new Random(SEED); + + sw.writeStartDocument(); + sw.writeStartElement("data"); + + int rowCount = 0; + + while (out.size() < LEN) { + sw.writeStartElement("row"); + + sw.writeStartElement("a"); + sw.writeCharacters(String.valueOf(r.nextInt())); + sw.writeEndElement(); + sw.writeStartElement("b"); + sw.writeCharacters(String.valueOf(r.nextLong())); + sw.writeEndElement(); + sw.writeStartElement("c"); + sw.writeCharacters(String.valueOf(r.nextBoolean())); + sw.writeEndElement(); + sw.writeCharacters("\n"); // to make debugging easier + + sw.writeEndElement(); + sw.flush(); + ++rowCount; + } + sw.writeEndElement(); + sw.writeEndDocument(); + sw.close(); + return rowCount; + } + + private void expectElemText(XMLStreamReader sr, String elem, String value) + throws XMLStreamException + { + assertTokenType(START_ELEMENT, sr.nextTag()); + assertEquals(elem, sr.getLocalName()); + String actValue = sr.getElementText(); + if (!value.equals(actValue)) { + fail("Expected value '"+value+"' (for element '"+elem+"'), got '"+actValue+"' (len "+actValue.length()+"): location "+sr.getLocation()); + } + assertTokenType(END_ELEMENT, sr.getEventType()); + } +} diff -Nru libwoodstox-java-4.1.3/src/test/java/stax2/stream/TestLocationInfo.java libwoodstox-java-5.1.0/src/test/java/stax2/stream/TestLocationInfo.java --- libwoodstox-java-4.1.3/src/test/java/stax2/stream/TestLocationInfo.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/stax2/stream/TestLocationInfo.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,224 @@ +package stax2.stream; + +import javax.xml.stream.*; + +import org.codehaus.stax2.*; + +import stax2.BaseStax2Test; + +/** + * Set of unit tests that checks that the {@link LocationInfo} implementation + * works as expected, provides proper values or -1 to indicate "don't know". + */ +public class TestLocationInfo + extends BaseStax2Test +{ + final static String TEST_DTD_DOC = + "" + +"\n" // fc: 38; row 2 + +"foo'>\n" // fc: 66; row 4 + +"]>\n" // fc: 98; row 5 + +"Entity: " // fc: 101; row 6 + +"&ent; " // fc: 115; row 6 + +"\r\n" // fc: 121; row 6 + +"&ent2;" // fc: 137; row 7 + +""; // fc: 144; row 7 + // EOF, fc: 150; row 7 + + /** + * This document fragment tries ensure that linefeed handling works ok + * as well. + */ + final static String TEST_LF_DOC = + "\n" // row 1 + +"\r\n" // row 2 + +" \r" // row 3 + +"\t\t\n" // row 4 + +" \r\n" // row 5 + +"\t "// row 6 + +""; // row6 + ; + + public void testInitialLocationNoDecl() + throws XMLStreamException + { + // First, let's test 'missing' start doc: + XMLStreamReader2 sr = getReader("", false); + LocationInfo loc = sr.getLocationInfo(); + assertLocation(sr, loc.getStartLocation(), 1, 1, + 0, loc.getStartingByteOffset(), + 0, loc.getStartingCharOffset()); + assertLocation(sr, loc.getEndLocation(), 1, 1, + 0, loc.getEndingByteOffset(), + 0, loc.getEndingCharOffset()); + sr.close(); + } + + public void testInitialLocationWithDecl() + throws XMLStreamException + { + // and then a real one + XMLStreamReader2 sr = getReader("", false); + LocationInfo loc = sr.getLocationInfo(); + assertLocation(sr, loc.getStartLocation(), 1, 1, + 0, loc.getStartingByteOffset(), + 0, loc.getStartingCharOffset()); + assertLocation(sr, loc.getEndLocation(), 3, 2, + 23, loc.getEndingByteOffset(), + 23, loc.getEndingCharOffset()); + sr.close(); + } + + public void testRowAccuracy() + throws XMLStreamException + { + XMLStreamReader2 sr = getReader(TEST_LF_DOC, false); + + assertRow(sr, 1, 1); // (missing) xml decl + + assertTokenType(START_ELEMENT, sr.next()); + assertEquals("root", sr.getLocalName()); + assertRow(sr, 1, 1); + assertTokenType(CHARACTERS, sr.next()); + assertRow(sr, 1, 2); // lf + + assertTokenType(START_ELEMENT, sr.next()); + assertEquals("branch", sr.getLocalName()); + assertRow(sr, 2, 2); + assertTokenType(CHARACTERS, sr.next()); + assertRow(sr, 2, 3); // lf + + assertTokenType(START_ELEMENT, sr.next()); + assertEquals("branch2", sr.getLocalName()); + assertRow(sr, 3, 3); + assertTokenType(CHARACTERS, sr.next()); + assertRow(sr, 3, 4); // lf + + assertTokenType(START_ELEMENT, sr.next()); + assertEquals("leaf", sr.getLocalName()); + assertRow(sr, 4, 4); + assertTokenType(END_ELEMENT, sr.next()); + assertEquals("leaf", sr.getLocalName()); + assertRow(sr, 4, 4); + assertTokenType(CHARACTERS, sr.next()); + assertRow(sr, 4, 5); // lf + + assertTokenType(END_ELEMENT, sr.next()); + assertEquals("branch2", sr.getLocalName()); + assertRow(sr, 5, 5); + assertTokenType(CHARACTERS, sr.next()); + assertRow(sr, 5, 6); + + assertTokenType(END_ELEMENT, sr.next()); + assertEquals("branch", sr.getLocalName()); + assertRow(sr, 6, 6); + assertTokenType(CHARACTERS, sr.next()); + assertRow(sr, 6, 6); + + assertTokenType(END_ELEMENT, sr.next()); + assertEquals("root", sr.getLocalName()); + assertRow(sr, 6, 6); + + sr.close(); + } + + /** + * Test that uses a document with internal DTD subset, to verify that + * location info is still valid. + */ + public void testLocationsWithDTD() + throws XMLStreamException + { + XMLStreamReader2 sr = getReader(TEST_DTD_DOC, true); + // will return null if SUPPORT_DTD fails: + if (sr == null) { + System.err.println("WARN: SupportDTD can not be enabled, need to skip test"); + return; + } + + LocationInfo loc = sr.getLocationInfo(); + assertLocation(sr, loc.getStartLocation(), 1, 1, + 0, loc.getStartingByteOffset(), + 0, loc.getStartingCharOffset()); + assertLocation(sr, loc.getEndLocation(), 22, 1, + 21, loc.getEndingByteOffset(), + 21, loc.getEndingCharOffset()); + + assertTokenType(DTD, sr.next()); + loc = sr.getLocationInfo(); + assertLocation(sr, loc.getStartLocation(), 22, 1, + 21, loc.getStartingByteOffset(), + 21, loc.getStartingCharOffset()); + assertLocation(sr, loc.getEndLocation(), 3, 5, + 100, loc.getEndingByteOffset(), + 100, loc.getEndingCharOffset()); + + // Let's ignore text/space, if there is one: + while (sr.next() != START_ELEMENT) { + ; + } + + loc = sr.getLocationInfo(); + assertLocation(sr, loc.getStartLocation(), 1, 6, + 101, loc.getStartingByteOffset(), + 101, loc.getStartingCharOffset()); + assertLocation(sr, loc.getEndLocation(), 7, 6, + 107, loc.getEndingByteOffset(), + 107, loc.getEndingCharOffset()); + + // !!! TBI + } + + /* + //////////////////////////////////////// + // Private methods + //////////////////////////////////////// + */ + + private void assertRow(XMLStreamReader2 sr, int startRow, int endRow) + throws XMLStreamException + { + LocationInfo li = sr.getLocationInfo(); + Location startLoc = li.getStartLocation(); + assertEquals("Incorrect starting row for event "+tokenTypeDesc(sr.getEventType()), startRow, startLoc.getLineNumber()); + Location endLoc = li.getEndLocation(); + assertEquals("Incorrect ending row for event "+tokenTypeDesc(sr.getEventType()), endRow, endLoc.getLineNumber()); + } + + private void assertLocation(XMLStreamReader sr, XMLStreamLocation2 loc, + int expCol, int expRow, + int expByteOffset, long actByteOffset, + int expCharOffset, long actCharOffset) + { + assertEquals("Incorrect column for "+tokenTypeDesc(sr.getEventType()), + expCol, loc.getColumnNumber()); + assertEquals("Incorrect row for "+tokenTypeDesc(sr.getEventType()), + expRow, loc.getLineNumber()); + + if (actByteOffset == -1) { // no info, that's fine + ; + } else { + assertEquals(expByteOffset, actByteOffset); + } + if (actCharOffset == -1) { // no info, that's fine + ; + } else { + assertEquals(expCharOffset, actCharOffset); + } + } + + private XMLStreamReader2 getReader(String contents, boolean needDTD) + throws XMLStreamException + { + XMLInputFactory f = getInputFactory(); + setCoalescing(f, false); // shouldn't really matter + setNamespaceAware(f, true); + if (!setSupportDTD(f, needDTD)) { + return null; + } + // No need to validate, just need entities + setValidating(f, false); + return constructStreamReader(f, contents); + } +} diff -Nru libwoodstox-java-4.1.3/src/test/java/stax2/stream/TestNamespaces.java libwoodstox-java-5.1.0/src/test/java/stax2/stream/TestNamespaces.java --- libwoodstox-java-4.1.3/src/test/java/stax2/stream/TestNamespaces.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/stax2/stream/TestNamespaces.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,103 @@ +package stax2.stream; + +import javax.xml.namespace.NamespaceContext; +import javax.xml.stream.*; + +import org.codehaus.stax2.*; + +/** + * Unit test suite that tests additional StAX2 namespace information + * accessors. + */ +public class TestNamespaces + extends stax2.BaseStax2Test +{ + public void testNonTransientNsCtxt() + throws XMLStreamException + { + String XML = + "" + +"" + +"" + +"" + +""; + XMLStreamReader2 sr = getNsReader(XML, true); + + assertEquals(START_ELEMENT, sr.next()); + assertEquals("root", sr.getLocalName()); + NamespaceContext curr = sr.getNamespaceContext(); + assertNotNull(curr); + checkValidityOfNs1(curr); + NamespaceContext nc1 = sr.getNonTransientNamespaceContext(); + assertNotNull(nc1); + checkValidityOfNs1(nc1); + + assertEquals(START_ELEMENT, sr.next()); + assertEquals("branch", sr.getLocalName()); + curr = sr.getNamespaceContext(); + // ok, this should have different settings: + assertNull(curr.getPrefix("nosuchurl")); + assertNull(curr.getNamespaceURI("xyz")); + // bindings from parent: + assertEquals("a", curr.getPrefix("whatever")); + assertEquals("whatever", curr.getNamespaceURI("a")); + assertEquals("b", curr.getPrefix("urlforb")); + assertEquals("urlforb", curr.getNamespaceURI("b")); + // and new ones: + assertEquals("", curr.getPrefix("someurl")); + assertEquals("c", curr.getPrefix("yetanotherurl")); + assertEquals("someurl", curr.getNamespaceURI("")); + assertEquals("yetanotherurl", curr.getNamespaceURI("c")); + + // but nc1 should be non-transient... + checkValidityOfNs1(nc1); + + assertEquals(START_ELEMENT, sr.next()); + assertEquals("leaf", sr.getLocalName()); + // should be non-transient... + checkValidityOfNs1(nc1); + + assertEquals(END_ELEMENT, sr.next()); + assertEquals(END_ELEMENT, sr.next()); + assertEquals(END_ELEMENT, sr.next()); + + // and nc1 should persist still + checkValidityOfNs1(nc1); + } + + /* + ////////////////////////////////////////////////////// + // Internal methods + ////////////////////////////////////////////////////// + */ + + private void checkValidityOfNs1(NamespaceContext nc) + throws XMLStreamException + { + // Ok, we have just 2 bindings here. + // First, let's check some non-existing bindings + assertNull(nc.getPrefix("someurl")); + assertNull(nc.getPrefix("whatever")); + assertNull(nc.getNamespaceURI("c")); + // default can be empty or null + String defNs = nc.getNamespaceURI(""); + if (defNs != null && defNs.length() > 0) { + fail("Expected default namespace to be null or empty, was '"+defNs+"'"); + } + // And then the ones that do exist + assertEquals("a", nc.getPrefix("myurl")); + assertEquals("myurl", nc.getNamespaceURI("a")); + assertEquals("b", nc.getPrefix("urlforb")); + assertEquals("urlforb", nc.getNamespaceURI("b")); + } + + private XMLStreamReader2 getNsReader(String contents, boolean coalesce) + throws XMLStreamException + { + XMLInputFactory f = getInputFactory(); + setNamespaceAware(f, true); + setCoalescing(f, coalesce); + setValidating(f, false); + return constructStreamReader(f, contents); + } +} diff -Nru libwoodstox-java-4.1.3/src/test/java/stax2/stream/TestReaderConstruction.java libwoodstox-java-5.1.0/src/test/java/stax2/stream/TestReaderConstruction.java --- libwoodstox-java-4.1.3/src/test/java/stax2/stream/TestReaderConstruction.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/stax2/stream/TestReaderConstruction.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,140 @@ +package stax2.stream; + +import java.io.*; +import java.net.URL; + +import javax.xml.stream.*; + +import org.codehaus.stax2.*; +import org.codehaus.stax2.io.*; + +/** + * Unit test suite that tests additional StAX2 stream reader construction + * methods. + */ +public class TestReaderConstruction + extends stax2.BaseStax2Test +{ + public void testCreateWithFile() + throws IOException, XMLStreamException + { + File f = writeToTempFile("file"); + XMLInputFactory2 ifact = getInputFactory(); + setCoalescing(ifact, true); + verifyXML(ifact.createXMLStreamReader(f), "file"); + } + + @SuppressWarnings("deprecation") + public void testCreateWithURL() + throws IOException, XMLStreamException + { + File f = writeToTempFile("URL"); + XMLInputFactory2 ifact = getInputFactory(); + setCoalescing(ifact, true); + URL url = f.toURL(); + verifyXML(ifact.createXMLStreamReader(url), "URL"); + } + + public void testCreateWithFileSource() + throws IOException, XMLStreamException + { + File f = writeToTempFile("Filesource"); + XMLInputFactory2 ifact = getInputFactory(); + setCoalescing(ifact, true); + verifyXML(ifact.createXMLStreamReader(new Stax2FileSource(f)), + "Filesource"); + } + + @SuppressWarnings("deprecation") + public void testCreateWithURLSource() + throws IOException, XMLStreamException + { + File f = writeToTempFile("URLSource"); + XMLInputFactory2 ifact = getInputFactory(); + setCoalescing(ifact, true); + verifyXML(ifact.createXMLStreamReader(new Stax2URLSource(f.toURL())), + "URLSource"); + } + + public void testCreateWithStringSource() + throws XMLStreamException + { + XMLInputFactory2 ifact = getInputFactory(); + setCoalescing(ifact, true); + String xml = generateXML("Stringsource"); + verifyXML(ifact.createXMLStreamReader(new Stax2StringSource(xml)), + "Stringsource"); + } + + public void testCreateWithCharArraySource() + throws XMLStreamException + { + XMLInputFactory2 ifact = getInputFactory(); + setCoalescing(ifact, true); + String xml = generateXML("CharArraySource"); + char[] ch = xml.toCharArray(); + verifyXML(ifact.createXMLStreamReader(new Stax2CharArraySource(ch, 0, ch.length)), "CharArraySource"); + } + + public void testCreateWithByteArraySource() + throws XMLStreamException, IOException + { + XMLInputFactory2 ifact = getInputFactory(); + setCoalescing(ifact, true); + String xml = generateXML("ByteArraySource"); + byte[] orig = xml.getBytes("UTF-8"); + byte[] b = orig.clone(); + verifyXML(ifact.createXMLStreamReader(new Stax2ByteArraySource(b, 0, b.length)), "ByteArraySource"); + + // Also: let's check that non-0 offset works... + final int OFFSET = 29; + final int DOCLEN = b.length; + byte[] b2 = new byte[OFFSET + DOCLEN + 50]; + System.arraycopy(b, 0, b2, OFFSET, DOCLEN); + verifyXML(ifact.createXMLStreamReader(new Stax2ByteArraySource(b2, OFFSET, DOCLEN)), "ByteArraySource"); + } + + /* + //////////////////////////////////////////////// + // Internal methods + //////////////////////////////////////////////// + */ + + public void verifyXML(XMLStreamReader sr, String textValue) + throws XMLStreamException + { + /* No need to check thoroughly: mostly it's just checking that + * the referenced doc can be found at all + */ + assertTokenType(START_DOCUMENT, sr.getEventType()); + assertTokenType(START_ELEMENT, sr.next()); + assertEquals("root", sr.getLocalName()); + assertTokenType(CHARACTERS, sr.next()); + String str = getAndVerifyText(sr); + assertEquals(textValue, str); + assertTokenType(END_ELEMENT, sr.next()); + assertEquals("root", sr.getLocalName()); + assertTokenType(END_DOCUMENT, sr.next()); + sr.close(); + } + + String generateXML(String text) + { + StringBuffer sb = new StringBuffer(""); + sb.append(text); + sb.append(""); + return sb.toString(); + } + + File writeToTempFile(String text) + throws IOException + { + File f = File.createTempFile("stax2test", null); + Writer w = new OutputStreamWriter(new FileOutputStream(f), "UTF-8"); + w.write(generateXML(text)); + w.flush(); + w.close(); + f.deleteOnExit(); + return f; + } +} diff -Nru libwoodstox-java-4.1.3/src/test/java/stax2/stream/TestStreamReader.java libwoodstox-java-5.1.0/src/test/java/stax2/stream/TestStreamReader.java --- libwoodstox-java-4.1.3/src/test/java/stax2/stream/TestStreamReader.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/stax2/stream/TestStreamReader.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,139 @@ +package stax2.stream; + +import java.io.ByteArrayInputStream; +import java.io.StringReader; + +import javax.xml.stream.*; + +import org.codehaus.stax2.*; + +import stax2.BaseStax2Test; + +public class TestStreamReader + extends BaseStax2Test +{ + /** + * Unit test to verify fixing of (and guard against regression of) + * [WSTX-201]. + */ + public void testIsCharacters() throws Exception + { + XMLInputFactory2 f = getInputFactory(); + setNamespaceAware(f, true); + setCoalescing(f, true); + XMLStreamReader sr = constructStreamReader(f, ""); + assertTokenType(START_ELEMENT, sr.next()); + assertEquals("root", sr.getLocalName()); + // should both return CHARACTERS + assertTokenType(CHARACTERS, sr.next()); + // and be considered of characters... + assertEquals(CHARACTERS, sr.getEventType()); + assertTrue(sr.isCharacters()); + assertTokenType(END_ELEMENT, sr.next()); + } + + /** + * Unit test related to [WSTX-274] + */ + public void testCData() throws Exception + { + XMLInputFactory2 f = getInputFactory(); + setNamespaceAware(f, true); + setCoalescing(f, true); + String strMessage = "" + + "" + + "" + + "outside cdata inside cdata]]>" + + "" + + "" + + ""; + XMLStreamReader reader = f.createXMLStreamReader(new ByteArrayInputStream(strMessage.getBytes("UTF-8"))); + assertTokenType(START_ELEMENT, reader.next()); + assertTokenType(START_ELEMENT, reader.next()); + assertTokenType(START_ELEMENT, reader.next()); + assertTokenType(START_ELEMENT, reader.next()); + // since we are coalescing, must be reported as CHARACTERS, not CDATA + assertTokenType(CHARACTERS, reader.next()); + String cdata = new String(reader.getTextCharacters(), reader.getTextStart(), reader.getTextLength()); + assertEquals("outside cdata inside cdata", cdata); + } + + // Unit test for [WSTX-299]: use of "exotic" URLs + public void testCustomSystemIds() throws Exception + { + XMLInputFactory2 f = getNewInputFactory(); + setCoalescing(f, true); + // important: must prevent access of DTD + setSupportDTD(f, false); + final String sysId = "foobar:slartibartfast"; + + String DOC = "stuff"; + XMLStreamReader2 reader = (XMLStreamReader2) f.createXMLStreamReader(new StringReader(DOC)); + assertTokenType(DTD, reader.next()); + + DTDInfo dtd = reader.getDTDInfo(); + assertNotNull(dtd); + assertEquals(sysId, dtd.getDTDSystemId()); + + assertTokenType(START_ELEMENT, reader.next()); + assertEquals("root", reader.getLocalName()); + assertTokenType(CHARACTERS, reader.next()); + assertEquals("stuff", reader.getText()); + assertTokenType(END_ELEMENT, reader.next()); + assertEquals("root", reader.getLocalName()); + reader.close(); + } + + // Another test for [WSTX-299] + public void testCustomSystemIdWithResolver() throws Exception + { + XMLInputFactory2 f = getNewInputFactory(); + setCoalescing(f, true); + setSupportDTD(f, true); + final String sysId = "foobar:slartibartfast"; + final String EXTERNAL_DTD = ""; + f.setProperty(XMLInputFactory.RESOLVER, + new ExoticResolver(sysId, EXTERNAL_DTD)); + + String DOC = "&foo;"; + XMLStreamReader2 reader = (XMLStreamReader2) f.createXMLStreamReader(new StringReader(DOC)); + assertTokenType(DTD, reader.next()); + + DTDInfo dtd = reader.getDTDInfo(); + assertNotNull(dtd); + assertEquals(sysId, dtd.getDTDSystemId()); + + assertTokenType(START_ELEMENT, reader.next()); + assertEquals("root", reader.getLocalName()); + assertTokenType(CHARACTERS, reader.next()); + assertEquals("bar", reader.getText()); + assertTokenType(END_ELEMENT, reader.next()); + assertEquals("root", reader.getLocalName()); + reader.close(); + } + + /* + /////////////////////////////////////////////////////////// + // Helper classes + /////////////////////////////////////////////////////////// + */ + + final static class ExoticResolver implements XMLResolver + { + protected final String sysId, dtd; + + public ExoticResolver(String sysId, String dtd) { + this.sysId = sysId; + this.dtd = dtd; + } + + @Override + public Object resolveEntity(String publicID, String systemID, String baseURI, String namespace) + { + if (sysId.equals(systemID)) { + return dtd; + } + return null; + } + } +} diff -Nru libwoodstox-java-4.1.3/src/test/java/stax2/stream/TestStreamSource.java libwoodstox-java-5.1.0/src/test/java/stax2/stream/TestStreamSource.java --- libwoodstox-java-4.1.3/src/test/java/stax2/stream/TestStreamSource.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/stax2/stream/TestStreamSource.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,43 @@ +package stax2.stream; + +import java.io.*; +import javax.xml.stream.*; +import javax.xml.transform.stream.StreamSource; + +import stax2.BaseStax2Test; + +/** + * This unit test suite verifies use of {@link StreamSource} as input + * for {@link XMLInputFactory}. + * + * @author Tatu Saloranta + * + * @since 3.0 + */ +public class TestStreamSource + extends BaseStax2Test +{ + /** + * This test is related to problem reported as [WSTX-182], inability + * to use SystemId alone as source. + */ + public void testCreateUsingSystemId() + throws IOException, XMLStreamException + { + File tmpF = File.createTempFile("staxtest", ".xml"); + tmpF.deleteOnExit(); + + // First, need to write contents to the file + Writer w = new OutputStreamWriter(new FileOutputStream(tmpF), "UTF-8"); + w.write(""); + w.close(); + + XMLInputFactory f = getInputFactory(); + StreamSource src = new StreamSource(); + src.setSystemId(tmpF); + XMLStreamReader sr = f.createXMLStreamReader(src); + assertTokenType(START_ELEMENT, sr.next()); + assertTokenType(END_ELEMENT, sr.next()); + sr.close(); + } +} diff -Nru libwoodstox-java-4.1.3/src/test/java/stax2/stream/TestXMLStreamReader2.java libwoodstox-java-5.1.0/src/test/java/stax2/stream/TestXMLStreamReader2.java --- libwoodstox-java-4.1.3/src/test/java/stax2/stream/TestXMLStreamReader2.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/stax2/stream/TestXMLStreamReader2.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,252 @@ +package stax2.stream; + +import java.io.*; +import javax.xml.stream.*; + +import org.codehaus.stax2.*; + +import stax2.BaseStax2Test; + +public class TestXMLStreamReader2 + extends BaseStax2Test +{ + public void testPropertiesNative() + throws XMLStreamException + { + doTestProperties(false, false); + doTestProperties(true, false); + } + + public void testPropertiesWrapped() + throws XMLStreamException + { + doTestProperties(false, true); + doTestProperties(true, true); + } + + public void testSkipElement() + throws XMLStreamException + { + doTestSkipElement(false); + doTestSkipElement(true); + } + + public void testGetPrefixedName() + throws XMLStreamException + { + doTestGetPrefixedName(false); + doTestGetPrefixedName(true); + } + + public void testReportCData() throws XMLStreamException + { + _testCData(false, false); + _testCData(false, true); + _testCData(true, false); + _testCData(true, true); + } + + /** + * Test inspired by [WSTX-211] + */ + public void testLongerCData() throws Exception + { + String SRC_TEXT = +"\r\n123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678\r\n" ++"Woodstox 4.0.5 does not like this embedded element. However, if you take\r\n" ++"out one or more characters from the really long line (so that less than 500 characters come between\r\n" ++"'CDATA[' and the opening of the embeddedElement tag (including LF), then Woodstox will instead\r\n" + +"complain that the CDATA section wasn't ended."; + String DST_TEXT = SRC_TEXT.replace("\r\n", "\n"); + String XML = "\r\n" ++""; + // Hmmh. Seems like we need the BOM... + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + bos.write(0xEF); + bos.write(0xBB); + bos.write(0xBF); + bos.write(XML.getBytes("UTF-8")); + byte[] bytes = bos.toByteArray(); + XMLInputFactory2 f = getInputFactory(); + // important: don't force coalescing, that'll convert CDATA to CHARACTERS + setCoalescing(f, false); + + XMLStreamReader sr = f.createXMLStreamReader(new ByteArrayInputStream(bytes)); + assertTokenType(START_DOCUMENT, sr.getEventType()); + assertTokenType(START_ELEMENT, sr.next()); + assertEquals("test", sr.getLocalName()); + // This should still work, although with linefeed replacements + assertEquals(DST_TEXT, sr.getElementText()); + assertTokenType(END_ELEMENT, sr.getEventType()); + sr.close(); + } + + /* + /////////////////////////////////////////////////////////////////////// + // Private methods, shared test code + /////////////////////////////////////////////////////////////////////// + */ + + public void _testCData(boolean wrapped, boolean report) throws XMLStreamException + { + final String XML = ""; + + XMLInputFactory2 f = getInputFactory(); + // important: don't force coalescing, that'll convert CDATA to CHARACTERS + setCoalescing(f, false); + f.setProperty(XMLInputFactory2.P_REPORT_CDATA, new Boolean(report)); + XMLStreamReader sr = f.createXMLStreamReader(new StringReader(XML)); + if (wrapped) { + sr = wrapWithAdapter(sr); + } + assertTokenType(START_ELEMENT, sr.next()); + int t = sr.next(); + assertEquals("test", getAndVerifyText(sr)); + if (report) { + assertTokenType(CDATA, t); + } else { + assertTokenType(CHARACTERS, t); + } + assertTokenType(END_ELEMENT, sr.next()); + sr.close(); + } + + /** + * @param wrapped If true, will use Stax2ReaderAdapter to + * wrap the stream reader implementation + */ + public void doTestProperties(boolean ns, boolean wrapped) + throws XMLStreamException + { + final String XML = "xxx"; + XMLStreamReader2 sr = getReader(XML, ns); + if (wrapped) { + sr = wrapWithAdapter(sr); + } + + assertTokenType(START_DOCUMENT, sr.getEventType()); + assertEquals(0, sr.getDepth()); + assertFalse(sr.isEmptyElement()); + + assertTokenType(START_ELEMENT, sr.next()); + assertEquals("root", sr.getLocalName()); + assertEquals(1, sr.getDepth()); + assertFalse(sr.isEmptyElement()); + + assertTokenType(START_ELEMENT, sr.next()); + assertEquals("child", sr.getLocalName()); + assertEquals(2, sr.getDepth()); + + /* Can only test this for native readers; adapter has no way + * of implementing it reliably for Stax1 impls: + */ + if (!wrapped) { + assertTrue(sr.isEmptyElement()); + } + assertTokenType(END_ELEMENT, sr.next()); + assertEquals("child", sr.getLocalName()); + assertEquals(2, sr.getDepth()); + if (!wrapped) { // as above, only for non-wrapped + assertFalse(sr.isEmptyElement()); + } + + assertTokenType(START_ELEMENT, sr.next()); + assertEquals("child2", sr.getLocalName()); + assertEquals(2, sr.getDepth()); + if (!wrapped) { // as above, only for non-wrapped + assertFalse(sr.isEmptyElement()); + } + + assertTokenType(CHARACTERS, sr.next()); + assertEquals("xxx", getAndVerifyText(sr)); + assertEquals(2, sr.getDepth()); + // note: shouldn't cause an exception + if (!wrapped) { + assertFalse(sr.isEmptyElement()); + } + + assertTokenType(END_ELEMENT, sr.next()); + assertEquals("child2", sr.getLocalName()); + assertEquals(2, sr.getDepth()); + if (!wrapped) { + assertFalse(sr.isEmptyElement()); + } + + assertTokenType(END_ELEMENT, sr.next()); + assertEquals("root", sr.getLocalName()); + assertEquals(1, sr.getDepth()); + if (!wrapped) { + assertFalse(sr.isEmptyElement()); + } + + assertTokenType(END_DOCUMENT, sr.next()); + assertEquals(0, sr.getDepth()); + if (!wrapped) { + assertFalse(sr.isEmptyElement()); + } + } + + public void doTestSkipElement(boolean ns) + throws XMLStreamException + { + final String XML = "xxx"; + XMLStreamReader2 sr = getReader(XML, ns); + assertTokenType(START_DOCUMENT, sr.getEventType()); + + assertTokenType(START_ELEMENT, sr.next()); + assertEquals("root", sr.getLocalName()); + sr.skipElement(); + assertTokenType(END_ELEMENT, sr.getEventType()); + assertEquals("root", sr.getLocalName()); + assertTokenType(END_DOCUMENT, sr.next()); + } + + public void doTestGetPrefixedName(boolean ns) + throws XMLStreamException + { + final String XML = + "" + +"..." + +"" + ; + XMLStreamReader2 sr = getReader(XML, ns); + try { + assertTokenType(START_ELEMENT, sr.next()); + assertEquals("root", sr.getPrefixedName()); + assertTokenType(START_ELEMENT, sr.next()); + assertEquals("xy:elem", sr.getPrefixedName()); + assertTokenType(PROCESSING_INSTRUCTION, sr.next()); + assertEquals("proc", sr.getPrefixedName()); + assertTokenType(CHARACTERS, sr.next()); + assertTokenType(START_ELEMENT, sr.next()); + assertEquals("another:x", sr.getPrefixedName()); + assertTokenType(END_ELEMENT, sr.next()); + assertEquals("another:x", sr.getPrefixedName()); + assertTokenType(END_ELEMENT, sr.next()); + assertEquals("xy:elem", sr.getPrefixedName()); + assertTokenType(END_ELEMENT, sr.next()); + assertEquals("root", sr.getPrefixedName()); + assertTokenType(END_DOCUMENT, sr.next()); + } catch (XMLStreamException xse) { + fail("Did not expect any problems during parsing, but got: "+xse); + } + } + + /* + /////////////////////////////////////////////////////////////////////// + // Private methods, other + /////////////////////////////////////////////////////////////////////// + */ + + private XMLStreamReader2 getReader(String contents, boolean nsAware) + throws XMLStreamException + { + XMLInputFactory2 f = getInputFactory(); + setCoalescing(f, true); + setSupportDTD(f, true); + setNamespaceAware(f, nsAware); + setValidating(f, false); + return constructStreamReader(f, contents); + } +} + diff -Nru libwoodstox-java-4.1.3/src/test/java/stax2/TestFactories.java libwoodstox-java-5.1.0/src/test/java/stax2/TestFactories.java --- libwoodstox-java-4.1.3/src/test/java/stax2/TestFactories.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/stax2/TestFactories.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,127 @@ +package stax2; + +import java.io.*; + +import javax.xml.stream.*; + +import org.codehaus.stax2.XMLStreamReader2; +import org.codehaus.stax2.XMLStreamWriter2; + +/** + * Unit tests to verify expected handling of property accessors and + * modifiers with Stax2 input and output factories, as well as + * simple readers and writers. + * These are mostly related to issue [WSTX-243] + */ +public class TestFactories extends BaseStax2Test +{ + private final String NO_SUCH_PROPERTY = "noSuchProperty"; + + // [WSTX-243]; verify exception for input factory + public void testPropertiesInputFactory() throws XMLStreamException + { + XMLInputFactory f = getInputFactory(); + // First, verify property is indeed unsupported + assertFalse(f.isPropertySupported(NO_SUCH_PROPERTY)); + + // First: error for trying to access unknown + try { + f.getProperty(NO_SUCH_PROPERTY); + fail("Expected exception"); + } catch (IllegalArgumentException e) { + verifyException(e, NO_SUCH_PROPERTY); + } + + // Ditto for trying to set such property + try { + f.setProperty(NO_SUCH_PROPERTY, "foobar"); + fail("Expected exception"); + } catch (IllegalArgumentException e) { + verifyException(e, NO_SUCH_PROPERTY); + } + } + + public void testPropertiesStreamReader() throws XMLStreamException + { + XMLInputFactory f = getInputFactory(); + XMLStreamReader2 r = (XMLStreamReader2) f.createXMLStreamReader(new StringReader("")); + + // First, verify property is indeed unsupported + assertFalse(r.isPropertySupported(NO_SUCH_PROPERTY)); + + /* Ok: as of Woodstox 4.0, behavior is such that no exception is thrown, + * because javadocs do not indicate that it should be done (save for case + * where property name is null). Whether this is right interpretation or not + * is open to discussion; but for now we will verify that behavior does not + * change from 4.0 without explicit decision. + */ + /* + try { + Object ob = r.getProperty(NO_SUCH_PROPERTY); + fail("Expected exception, instead got result: "+ob); + } catch (IllegalArgumentException e) { + verifyException(e, NO_SUCH_PROPERTY); + } + */ + Object ob = r.getProperty(NO_SUCH_PROPERTY); + assertNull(ob); + + // And although setter is specified by Stax2, it too fails on unrecognized: + try { + r.setProperty(NO_SUCH_PROPERTY, "foobar"); + fail("Expected exception"); + } catch (IllegalArgumentException e) { + verifyException(e, NO_SUCH_PROPERTY); + } + } + + // [WSTX-243]; verify exception for input factory + public void testPropertiesOutputFactory() throws XMLStreamException + { + XMLOutputFactory f = getOutputFactory(); + // First, verify property is indeed unsupported + assertFalse(f.isPropertySupported(NO_SUCH_PROPERTY)); + + // First: error for trying to access unknown + try { + f.getProperty(NO_SUCH_PROPERTY); + fail("Expected exception"); + } catch (IllegalArgumentException e) { + verifyException(e, NO_SUCH_PROPERTY); + } + + // Ditto for trying to set such property + try { + f.setProperty(NO_SUCH_PROPERTY, "foobar"); + fail("Expected exception"); + } catch (IllegalArgumentException e) { + verifyException(e, NO_SUCH_PROPERTY); + } + } + + public void testPropertiesStreamWriter() throws XMLStreamException + { + XMLOutputFactory f = getOutputFactory(); + XMLStreamWriter2 w = (XMLStreamWriter2) f.createXMLStreamWriter(new StringWriter()); + + // First, verify property is indeed unsupported + assertFalse(w.isPropertySupported(NO_SUCH_PROPERTY)); + + // First: error for trying to access unknown, as per Stax 1.0 spec: + try { + w.getProperty(NO_SUCH_PROPERTY); + fail("Expected exception"); + } catch (IllegalArgumentException e) { + verifyException(e, NO_SUCH_PROPERTY); + } + + // And although setter is specified by Stax2, it too fails on unrecognized: + try { + w.setProperty(NO_SUCH_PROPERTY, "foobar"); + fail("Expected exception"); + } catch (IllegalArgumentException e) { + verifyException(e, NO_SUCH_PROPERTY); + } + } + +} diff -Nru libwoodstox-java-4.1.3/src/test/java/stax2/typed/ReaderArrayTestBase.java libwoodstox-java-5.1.0/src/test/java/stax2/typed/ReaderArrayTestBase.java --- libwoodstox-java-4.1.3/src/test/java/stax2/typed/ReaderArrayTestBase.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/stax2/typed/ReaderArrayTestBase.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,569 @@ +package stax2.typed; + +import java.lang.reflect.Array; +import java.util.Random; + +import javax.xml.stream.*; + +import org.codehaus.stax2.*; +import org.codehaus.stax2.typed.*; + +import stax2.BaseStax2Test; + +/** + * Base class that contains set of simple unit tests to verify implementation + * of {@link TypedXMLStreamReader}. Concrete sub-classes are used to + * test both native and wrapped Stax2 implementations. + * + * @author Tatu Saloranta + */ +public abstract class ReaderArrayTestBase + extends BaseStax2Test +{ + // Let's test variable length arrays + final static int[] COUNTS_ELEM = new int[] { + 7, 39, 116, 900, 5003 + }; + final static int[] COUNTS_ATTR = new int[] { + 5, 17, 59, 357, 1920 + }; + + /* + //////////////////////////////////////// + // Abstract methods + //////////////////////////////////////// + */ + + protected abstract XMLStreamReader2 getReader(String contents) + throws XMLStreamException; + + /* + //////////////////////////////////////// + // Test methods, elem, valid + //////////////////////////////////////// + */ + + public void testSimpleIntArrayElem() throws XMLStreamException + { + _testSimpleIntArrayElem(false); + } + public void testSimpleIntArrayElemWithNoise() throws XMLStreamException + { + _testSimpleIntArrayElem(true); + } + + private void _testSimpleIntArrayElem(boolean withNoise) + throws XMLStreamException + { + for (int i = 0; i < COUNTS_ELEM.length; ++i) { + int len = COUNTS_ELEM[i]; + int[] data = intArray(len); + String XML = buildDoc(data, withNoise); + + // First, full read + verifyInts(XML, data, len); + // Then one by one + verifyInts(XML, data, 1); + // And finally, random + verifyInts(XML, data, -1); + } + } + + public void testSimpleLongArrayElem() + throws XMLStreamException + { + _testSimpleLongArrayElem(false); + } + public void testSimpleLongArrayElemWithNoise() + throws XMLStreamException + { + _testSimpleLongArrayElem(true); + } + + private void _testSimpleLongArrayElem(boolean withNoise) + throws XMLStreamException + { + for (int i = 0; i < COUNTS_ELEM.length; ++i) { + int len = COUNTS_ELEM[i]; + long[] data = longArray(len); + String XML = buildDoc(data, withNoise); + + // First, full read + verifyLongs(XML, data, len); + // Then one by one + verifyLongs(XML, data, 1); + // And finally, random + verifyLongs(XML, data, -1); + } + } + + public void testSimpleFloatArrayElem() + throws XMLStreamException + { + _testSimpleFloatArrayElem(false); + } + public void testSimpleFloatArrayElemWithNoise() + throws XMLStreamException + { + _testSimpleFloatArrayElem(true); + } + + private void _testSimpleFloatArrayElem(boolean withNoise) + throws XMLStreamException + { + for (int i = 0; i < COUNTS_ELEM.length; ++i) { + int len = COUNTS_ELEM[i]; + float[] data = floatArray(len); + String XML = buildDoc(data, withNoise); + + // First, full read + verifyFloats(XML, data, len); + // Then one by one + verifyFloats(XML, data, 1); + // And finally, random + verifyFloats(XML, data, -1); + } + } + + public void testSimpleDoubleArrayElem() + throws XMLStreamException + { + _testSimpleDoubleArrayElem(false); + } + public void testSimpleDoubleArrayElemWithNoise() + throws XMLStreamException + { + _testSimpleDoubleArrayElem(true); + } + + private void _testSimpleDoubleArrayElem(boolean withNoise) + throws XMLStreamException + { + for (int i = 0; i < COUNTS_ELEM.length; ++i) { + int len = COUNTS_ELEM[i]; + double[] data = doubleArray(len); + String XML = buildDoc(data, withNoise); + + // First, full read + verifyDoubles(XML, data, len); + // Then one by one + verifyDoubles(XML, data, 1); + // And finally, random + verifyDoubles(XML, data, -1); + } + } + + public void testEmptyElems() + throws XMLStreamException + { + // And then some edge cases too + for (int i = 0; i < 4; ++i) { + XMLStreamReader2 sr = getReader(""); + assertTokenType(START_ELEMENT, sr.next()); + int count; + + switch (i) { + case 0: + count = sr.readElementAsIntArray(new int[1], 0, 1); + break; + case 1: + count = sr.readElementAsLongArray(new long[1], 0, 1); + break; + case 2: + count = sr.readElementAsFloatArray(new float[1], 0, 1); + break; + default: + count = sr.readElementAsDoubleArray(new double[1], 0, 1); + break; + } + sr.close(); + assertEquals(-1, count); + } + } + + /* + //////////////////////////////////////// + // Test methods, elem, invalid + //////////////////////////////////////// + */ + + public void testInvalidIntArrayElem() + throws XMLStreamException + { + XMLStreamReader2 sr; + + for (int i = 0; i < 4; ++i) { + sr = getReader("1 2"); + // Can't call on START_DOCUMENT + try { + switch (i) { + case 0: + sr.readElementAsIntArray(new int[3], 0, 1); + fail("Expected an exception when trying to read at START_DOCUMENT"); + case 1: + sr.readElementAsLongArray(new long[3], 0, 1); + fail("Expected an exception when trying to read at START_DOCUMENT"); + case 2: + sr.readElementAsFloatArray(new float[3], 0, 1); + fail("Expected an exception when trying to read at START_DOCUMENT"); + default: + sr.readElementAsDoubleArray(new double[3], 0, 1); + fail("Expected an exception when trying to read at START_DOCUMENT"); + } + } catch (IllegalStateException ise) { } + + sr = getReader(""); + sr.next(); + assertTokenType(COMMENT, sr.next()); + + /* Hmmh. Should it be illegal to call on COMMENT? + * Let's assume it should + */ + /* + try { + switch (i) { + case 0: + sr.readElementAsIntArray(new int[3], 0, 1); + fail("Expected an exception when trying to read at COMMENT"); + case 1: + sr.readElementAsLongArray(new long[3], 0, 1); + fail("Expected an exception when trying to read at COMMENT"); + case 2: + sr.readElementAsFloatArray(new float[3], 0, 1); + fail("Expected an exception when trying to read at COMMENT"); + default: + sr.readElementAsDoubleArray(new double[3], 0, 1); + fail("Expected an exception when trying to read at COMMENT"); + } + } catch (IllegalStateException ise) { } + */ + } + } + + /* + //////////////////////////////////////// + // Test methods, attr, valid + //////////////////////////////////////// + */ + + public void testSimpleIntArrayAttr() + throws XMLStreamException + { + for (int i = 0; i < COUNTS_ATTR.length; ++i) { + int len = COUNTS_ATTR[i]; + int[] data = intArray(len); + String XML = buildAttrDoc(data); + verifyIntsAttr(XML, data); + } + } + + public void testSimpleLongArrayAttr() + throws XMLStreamException + { + for (int i = 0; i < COUNTS_ATTR.length; ++i) { + int len = COUNTS_ATTR[i]; + long[] data = longArray(len); + String XML = buildAttrDoc(data); + verifyLongsAttr(XML, data); + } + } + + public void testSimpleFloatArrayAttr() + throws XMLStreamException + { + for (int i = 0; i < COUNTS_ATTR.length; ++i) { + int len = COUNTS_ATTR[i]; + float[] data = floatArray(len); + String XML = buildAttrDoc(data); + verifyFloatsAttr(XML, data); + } + } + + public void testSimpleDoubleArrayAttr() + throws XMLStreamException + { + for (int i = 0; i < COUNTS_ATTR.length; ++i) { + int len = COUNTS_ATTR[i]; + double[] data = doubleArray(len); + String XML = buildAttrDoc(data); + verifyDoublesAttr(XML, data); + } + } + + /* + //////////////////////////////////////// + // Helper methods + //////////////////////////////////////// + */ + + private int[] intArray(int count) + { + Random r = new Random(count); + int[] result = new int[count]; + for (int i = 0; i < count; ++i) { + int base = r.nextInt(); + int shift = (r.nextInt() % 24); + result[i] = (base >> shift); + } + return result; + } + + private long[] longArray(int count) + { + Random r = new Random(count); + long[] result = new long[count]; + for (int i = 0; i < count; ++i) { + long base = r.nextLong(); + int shift = (r.nextInt() % 56); + result[i] = (base >> shift); + } + return result; + } + + private float[] floatArray(int count) + { + Random r = new Random(count); + float[] result = new float[count]; + for (int i = 0; i < count; ++i) { + float f = r.nextFloat(); + result[i] = r.nextBoolean() ? -f : f; + } + return result; + } + + private double[] doubleArray(int count) + { + Random r = new Random(count); + double[] result = new double[count]; + for (int i = 0; i < count; ++i) { + double d = r.nextDouble(); + result[i] = r.nextBoolean() ? -d : d; + } + return result; + } + + private String buildDoc(Object dataArray, boolean addNoise) + { + int len = Array.getLength(dataArray); + StringBuilder sb = new StringBuilder(len * 8); + sb.append(""); + Random r = new Random(Array.get(dataArray, 0).hashCode()); + for (int i = 0; i < len; ++i) { + Object value = Array.get(dataArray, i).toString(); + sb.append(value); + // Let's add 25% of time + if (addNoise && r.nextBoolean() && r.nextBoolean()) { + if (r.nextBoolean()) { + sb.append(""); + } else { + sb.append(""); + } + } + sb.append(' '); + } + sb.append(""); + return sb.toString(); + } + + private String buildAttrDoc(Object dataArray) + { + int len = Array.getLength(dataArray); + StringBuilder sb = new StringBuilder(len * 8); + sb.append(""); + return sb.toString(); + } + + private void assertArraysEqual(Object expArray, Object actArray, int actLen) + { + int expLen = Array.getLength(expArray); + if (expLen != actLen) { + fail("Expected number of entries "+expLen+", got "+actLen); + } + for (int i = 0; i < expLen; ++i) { + Object e1 = Array.get(expArray, i); + Object e2 = Array.get(actArray, i); + if (!e1.equals(e2)) { + fail("Elements at #"+i+" (len "+expLen+") differ: expected "+e1+", got "+e2); + } + } + } + + private void verifyInts(String doc, int[] data, int blockLen) + throws XMLStreamException + { + Random r = new Random(blockLen); + int[] buffer = new int[Math.max(blockLen, 256+16)]; + int[] result = new int[data.length]; + int entries = 0; + + XMLStreamReader2 sr = getReader(doc); + sr.next(); + assertTokenType(START_ELEMENT, sr.getEventType()); + + while (true) { + int readLen = (1 + (r.nextInt() & 0xFF)); + int offset = (r.nextInt() & 0xF); + int got; + + try { + got = sr.readElementAsIntArray(buffer, offset, readLen); + if (got < 0) { + break; + } + } catch (XMLStreamException xse) { + fail("Did not expect a failure (readLen "+readLen+", offset "+offset+", total exp elems "+data.length+"), problem: "+xse.getMessage()); + got = 0; // never gets here, but compiler doesn't know + } + if ((entries + got) > result.length) { + // Is that all, or would we get more? + int total = entries+got; + int more = sr.readElementAsIntArray(buffer, 0, 256); + + if (more > 0) { + fail("Expected only "+result.length+" entries, total now "+total+", plus "+more+" more with next call"); + } else { + fail("Expected only "+result.length+" entries, got "+total+" (and that's all)"); + } + } + System.arraycopy(buffer, offset, result, entries, got); + entries += got; + } + assertArraysEqual(data, result, entries); + sr.close(); + } + + private void verifyLongs(String doc, long[] data, int blockLen) + throws XMLStreamException + { + Random r = (blockLen < 0) ? new Random(blockLen) : null; + long[] buffer = new long[Math.max(blockLen, 256)]; + long[] result = new long[data.length]; + int entries = 0; + + XMLStreamReader2 sr = getReader(doc); + sr.next(); + assertTokenType(START_ELEMENT, sr.getEventType()); + + while (true) { + int readLen = (r == null) ? blockLen : (1 + r.nextInt() & 0xFF); + int got = sr.readElementAsLongArray(buffer, 0, readLen); + if (got < 0) { + break; + } + if ((entries + got) > result.length) { + fail("Expected only "+result.length+" entries, already got "+(entries+got)); + } + System.arraycopy(buffer, 0, result, entries, got); + entries += got; + } + assertArraysEqual(data, result, entries); + sr.close(); + } + + private void verifyFloats(String doc, float[] data, int blockLen) + throws XMLStreamException + { + Random r = (blockLen < 0) ? new Random(blockLen) : null; + float[] buffer = new float[Math.max(blockLen, 256)]; + float[] result = new float[data.length]; + int entries = 0; + + XMLStreamReader2 sr = getReader(doc); + sr.next(); + assertTokenType(START_ELEMENT, sr.getEventType()); + + while (true) { + int readLen = (r == null) ? blockLen : (1 + r.nextInt() & 0xFF); + int got = sr.readElementAsFloatArray(buffer, 0, readLen); + if (got < 0) { + break; + } + if ((entries + got) > result.length) { + fail("Expected only "+result.length+" entries, already got "+(entries+got)); + } + System.arraycopy(buffer, 0, result, entries, got); + entries += got; + } + assertArraysEqual(data, result, entries); + sr.close(); + } + + private void verifyDoubles(String doc, double[] data, int blockLen) + throws XMLStreamException + { + Random r = (blockLen < 0) ? new Random(blockLen) : null; + double[] buffer = new double[Math.max(blockLen, 256)]; + double[] result = new double[data.length]; + int entries = 0; + + XMLStreamReader2 sr = getReader(doc); + sr.next(); + assertTokenType(START_ELEMENT, sr.getEventType()); + + while (true) { + int readLen = (r == null) ? blockLen : (1 + r.nextInt() & 0xFF); + int got = sr.readElementAsDoubleArray(buffer, 0, readLen); + if (got < 0) { + break; + } + if ((entries + got) > result.length) { + fail("Expected only "+result.length+" entries, already got "+(entries+got)); + } + System.arraycopy(buffer, 0, result, entries, got); + entries += got; + } + assertArraysEqual(data, result, entries); + sr.close(); + } + + private void verifyIntsAttr(String doc, int[] data) + throws XMLStreamException + { + XMLStreamReader2 sr = getReader(doc); + sr.next(); + assertTokenType(START_ELEMENT, sr.getEventType()); + int[] result = sr.getAttributeAsIntArray(0); + assertArraysEqual(data, result, result.length); + sr.close(); + } + + private void verifyLongsAttr(String doc, long[] data) + throws XMLStreamException + { + XMLStreamReader2 sr = getReader(doc); + sr.next(); + assertTokenType(START_ELEMENT, sr.getEventType()); + long[] result = sr.getAttributeAsLongArray(0); + assertArraysEqual(data, result, result.length); + sr.close(); + } + + private void verifyFloatsAttr(String doc, float[] data) + throws XMLStreamException + { + XMLStreamReader2 sr = getReader(doc); + sr.next(); + assertTokenType(START_ELEMENT, sr.getEventType()); + float[] result = sr.getAttributeAsFloatArray(0); + assertArraysEqual(data, result, result.length); + sr.close(); + } + + private void verifyDoublesAttr(String doc, double[] data) + throws XMLStreamException + { + XMLStreamReader2 sr = getReader(doc); + sr.next(); + assertTokenType(START_ELEMENT, sr.getEventType()); + double[] result = sr.getAttributeAsDoubleArray(0); + assertArraysEqual(data, result, result.length); + sr.close(); + } +} + diff -Nru libwoodstox-java-4.1.3/src/test/java/stax2/typed/ReaderBinaryTestBase.java libwoodstox-java-5.1.0/src/test/java/stax2/typed/ReaderBinaryTestBase.java --- libwoodstox-java-4.1.3/src/test/java/stax2/typed/ReaderBinaryTestBase.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/stax2/typed/ReaderBinaryTestBase.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,744 @@ +package stax2.typed; + +import java.util.Random; +import javax.xml.stream.*; + +import org.codehaus.stax2.*; +import org.codehaus.stax2.ri.typed.AsciiValueEncoder; +import org.codehaus.stax2.ri.typed.ValueEncoderFactory; +import org.codehaus.stax2.typed.*; + +import stax2.BaseStax2Test; + +/** + * Base class that contains set of simple unit tests to verify implementation + * of parts {@link TypedXMLStreamReader} that deal with base64 encoded + * binary data. + * Concrete sub-classes are used to test both native and wrapped Stax2 + * implementations. + * + * @author Tatu Saloranta + */ +public abstract class ReaderBinaryTestBase + extends BaseStax2Test +{ + /** + * For good testing let's try all alternative variants, in addition + * to the default one (MIME) + */ + final static Base64Variant[] sBase64Variants = new Base64Variant[] { + Base64Variants.MIME, + Base64Variants.PEM, + Base64Variants.MODIFIED_FOR_URL + }; + + final static Base64Variant[] sPaddingVariants = new Base64Variant[] { + Base64Variants.MIME, + Base64Variants.PEM + }; + + final static Base64Variant[] sNonPaddingVariants = new Base64Variant[] { + Base64Variants.MODIFIED_FOR_URL + }; + + // Let's test variable length arrays + final static int[] LEN_ELEM = new int[] { + 1, 2, 3, 4, 7, 39, 116, 400, 900, 2890, 5003, 17045, 125000, 499999 + }; + final static int[] LEN_ATTR = new int[] { + 1, 2, 3, 5, 17, 59, 357, 1920, 9000, 63000, 257010 + }; + + final static int[] LEN_ELEM_MULTIPLE = new int[] { + 4, 7, 16, 99, 458, 3000, 12888, 79003, 145000 + }; + + final static int METHOD_SINGLE = 1; + final static int METHOD_FULL = 2; + final static int METHOD_2BYTES = 3; + final static int METHOD_SEGMENTED = 4; + final static int METHOD_FULL_CONVENIENT = 5; + + /** + * Padding characters are only legal as last one or two characters + * of 4-char units. + */ + final static String[] INVALID_PADDING = new String[] { + "AAAA====", "AAAAB===", "AA=A" + }; + + /** + * White space is only allowed between 4-char units, not within. + */ + final static String[] INVALID_WS = new String[] { + "AAA A", "AAAA BBBB C CCC", "ABCD ABCD AB CD" + }; + + /** + * And there are unlimited number of illegal characters within + * base64 sections, too + */ + final String[] INVALID_WEIRD_CHARS = new String[] { + "AAA?", "AAAA@@@@", "ABCD\u00A0BCD" + }; + + /* + //////////////////////////////////////// + // Abstract methods + //////////////////////////////////////// + */ + + protected abstract XMLStreamReader2 getReader(String contents) + throws XMLStreamException; + + protected XMLStreamReader2 getElemReader(String contents) + throws XMLStreamException + { + XMLStreamReader2 sr = getReader(contents); + assertTokenType(START_ELEMENT, sr.next()); + return sr; + } + + /* + //////////////////////////////////////// + // Test methods, elem, valid + //////////////////////////////////////// + */ + + public void testBinaryElemByteByByte() throws XMLStreamException + { + _testBinaryElem(METHOD_SINGLE, false); + _testBinaryElem(METHOD_SINGLE, true); + } + + public void testBinaryElemFull() throws XMLStreamException + { + _testBinaryElem(METHOD_FULL, false); + _testBinaryElem(METHOD_FULL, true); + } + + public void testBinaryElem2Bytes() throws XMLStreamException + { + _testBinaryElem(METHOD_2BYTES, false); + _testBinaryElem(METHOD_2BYTES, true); + } + + public void testBinaryElemSegmented() throws XMLStreamException + { + _testBinaryElem(METHOD_SEGMENTED, false); + _testBinaryElem(METHOD_SEGMENTED, true); + } + + public void testBinaryElemFullConvenient() throws XMLStreamException + { + _testBinaryElem(METHOD_FULL_CONVENIENT, false); + _testBinaryElem(METHOD_FULL_CONVENIENT, true); + } + + /** + * Unit test that verifies that decoding state is properly + * reset even if not all data is read. + * Access is done using supported method (i.e. starting with + * + */ + public void testMultipleBinaryElems() throws XMLStreamException + { + /* Let's try couple of sizes here too, but only check partial + * content; this to ensure content is properly cleared between + * calls + */ + final int REPS = 3; + + for (int bv = 0; bv < sBase64Variants.length; ++bv) { + Base64Variant b64variant = sBase64Variants[bv]; + for (int x = 0; x < LEN_ELEM_MULTIPLE.length; ++x) { + int size = LEN_ELEM_MULTIPLE[x]; + Random r = new Random(size+1); + byte[][] dataTable = generateDataTable(r, size, REPS); + String doc = buildMultiElemDoc(b64variant, dataTable); + // First, get access to root elem + XMLStreamReader2 sr = getElemReader(doc); + + // single-byte check should uncover problems + for (int i = 0; i < REPS; ++i) { + assertTokenType(START_ELEMENT, sr.next()); + _verifyElemData1(sr, b64variant, dataTable[i]); + // Should not have hit END_ELEMENT yet + if (sr.getEventType() == END_ELEMENT) { + fail("Should not have yet advanced to END_ELEMENT, when decoding not finished"); + } + // but needs to if we advance; can see CHARACTERS in between tho + while (CHARACTERS == sr.next()) { } + assertTokenType(END_ELEMENT, sr.getEventType()); + } + sr.close(); + } + } + } + + /** + * Test that uses 'mixed' segments (CHARACTERS and CDATA), in + * which base64 units (4 chars producing 3 bytes) can be split + * between segments. + *

+ * It is not clear if and how non-padding variants could + * be mixed, so this test only covers padding variants + * (it is likely that mixing would make sense whatsoever; but + * at least additional spacing would have to be provided) + */ + public void testBinaryMixedSegments() throws XMLStreamException + { + // We'll do just one long test + Random r = new Random(123); + final int SIZE = 128000; + byte[] data = generateData(r, SIZE); + char[] buffer = new char[100]; + + /* 20-Nov-2008, tatus: Let's test all available base64 + * variants too: + */ + for (int bv = 0; bv < sPaddingVariants.length; ++bv) { + Base64Variant b64variant = sPaddingVariants[bv]; + StringBuffer b64 = new StringBuffer(data.length * 2); + + /* Ok, first, let's first just generate long String of base64 + * data: + */ + int ptr = 0; + do { + int chunkLen = 1 + (r.nextInt() & 0x7); + AsciiValueEncoder enc = new ValueEncoderFactory().getEncoder(b64variant, data, ptr, chunkLen); + ptr += chunkLen; + int len = enc.encodeMore(buffer, 0, buffer.length); + b64.append(buffer, 0, len); + } while (b64.length() < SIZE); + // And then create document, with split content + + final int byteLen = ptr; + String refDoc = ""+b64.toString()+""; + + // But first: let's verify content is encoded correctly: + { + XMLStreamReader2 sr = getElemReader(refDoc); + _verifyElemData(sr, b64variant, r, data, byteLen, METHOD_FULL); + sr.close(); + } + + StringBuffer sb = new StringBuffer(b64.length() * 2); + sb.append(""); + + ptr = 0; + boolean cdata = false; + + while (ptr < b64.length()) { + int segLen = 1 + (r.nextInt() & 0x7); + if (cdata) { + sb.append(""); + } + cdata = !cdata; + } + sb.append(""); + String actualDoc = sb.toString(); + + XMLStreamReader2 sr = getElemReader(actualDoc); + // should be enough to verify byte-by-byte? + _verifyElemData(sr, b64variant, r, data, byteLen, METHOD_SINGLE); + sr.close(); + } + } + + private void _testBinaryElem(int readMethod, boolean addNoise) + throws XMLStreamException + { + for (int bv = 0; bv < sBase64Variants.length; ++bv) { + Base64Variant b64variant = sBase64Variants[bv]; + for (int x = 0; x < LEN_ELEM.length; ++x) { + int size = LEN_ELEM[x]; + Random r = new Random(size); + byte[] data = generateData(r, size); + String doc = buildDoc(b64variant, r, data, addNoise); + XMLStreamReader2 sr = getElemReader(doc); + _verifyElemData(sr, b64variant, r, data, data.length, readMethod); + sr.close(); + } + } + } + + private void _verifyElemData(XMLStreamReader2 sr, Base64Variant b64variant, Random r, byte[] data, int dataLen, int readMethod) + throws XMLStreamException + { + switch (readMethod) { + case METHOD_SINGLE: // minimal reads, single byte at a time + { + byte[] buffer = new byte[5]; + int ptr = 0; + int count; + + while ((count = sr.readElementAsBinary(buffer, 2, 1, b64variant)) > 0) { + assertEquals(1, count); + if ((ptr+1) < dataLen) { + if (data[ptr] != buffer[2]) { + fail("(base64 variant "+b64variant+") Corrupt decode at #"+ptr+"/"+dataLen+", expected "+displayByte(data[ptr])+", got "+displayByte(buffer[2])); + } + } + ++ptr; + } + if (ptr != dataLen) { + fail("(base64 variant "+b64variant+") Expected to get "+dataLen+" bytes, got "+ptr); + } + } + break; + case METHOD_FULL: // full read + { + byte[] buffer = new byte[dataLen + 100]; + /* Let's assume reader will actually read it all: + * while not absolutely required, in practice it should + * happen. If this is not true, need to change unit + * test to reflect it. + */ + int count = sr.readElementAsBinary(buffer, 3, buffer.length-3, b64variant); + assertEquals(dataLen, count); + for (int i = 0; i < dataLen; ++i) { + if (buffer[3+i] != data[i]) { + fail("(base64 variant "+b64variant+") Corrupt decode at #"+i+", expected "+displayByte(data[i])+", got "+displayByte(buffer[3+i])); + } + } + } + break; + + case METHOD_FULL_CONVENIENT: // full read + { + byte[] result = sr.getElementAsBinary(b64variant); + assertEquals(dataLen, result.length); + for (int i = 0; i < dataLen; ++i) { + if (result[i] != data[i]) { + fail("(base64 variant "+b64variant+") Corrupt decode at #"+i+", expected "+displayByte(data[i])+", got "+displayByte(result[i])); + } + } + } + break; + + case METHOD_2BYTES: // 2 bytes at a time + default: // misc sizes + { + boolean random = (readMethod != METHOD_2BYTES); + + byte[] buffer = new byte[200]; + int ptr = 0; + + while (true) { + int len = random ? (20 + (r.nextInt() & 127)) : 2; + int count = sr.readElementAsBinary(buffer, 0, len, b64variant); + if (count < 0) { + break; + } + if ((ptr + count) > dataLen) { + ptr += count; + break; + } + for (int i = 0; i < count; ++i) { + if (data[ptr+i] != buffer[i]) { + fail("(base64 variant "+b64variant+") Corrupt decode at #"+(ptr+i)+"/"+dataLen+" (read len: "+len+"; got "+count+"), expected "+displayByte(data[ptr+i])+", got "+displayByte(buffer[i])); + } + } + ptr += count; + } + + if (ptr != dataLen) { + fail("(base64 variant "+b64variant+") Expected "+dataLen+" bytes, got "+ptr); + } + } + } + assertTokenType(END_ELEMENT, sr.getEventType()); + } + + private void _verifyElemData1(XMLStreamReader2 sr, Base64Variant b64variant, byte[] data) + throws XMLStreamException + { + byte[] buffer = new byte[5]; + assertEquals(1, sr.readElementAsBinary(buffer, 1, 1, b64variant)); + assertEquals(data[0], buffer[1]); + } + + /* + //////////////////////////////////////// + // Test methods, elem, invalid + //////////////////////////////////////// + */ + + /** + * Rules for padding are quite simple: you can use one or two padding + * characters, which indicate 1 or 2 bytes instead full 3 for the + * decode unit. + */ + public void testInvalidElemPadding() + throws XMLStreamException + { + // Let's try out couple of arbitrary broken ones... + final byte[] resultBuffer = new byte[20]; + + // Hmmh. Here we need to skip testing of non-padded variants... + // (ideally would also test non-padding ones, but using different method) + for (int bv = 0; bv < sPaddingVariants.length; ++bv) { + Base64Variant b64variant = sPaddingVariants[bv]; + for (int i = 0; i < INVALID_PADDING.length; ++i) { + String doc = ""+INVALID_PADDING[i]+""; + XMLStreamReader2 sr = getElemReader(doc); + try { + /*int count = */ sr.readElementAsBinary(resultBuffer, 0, resultBuffer.length, b64variant); + fail("Should have received an exception for invalid padding"); + } catch (TypedXMLStreamException ex) { + // any way to check that it's the excepted message? not right now + } + sr.close(); + } + } + } + + /** + * Whitespace is allowed within base64, but only to separate 4 characters + * base64 units. Ideally (and by the spec) they should be used every + * 76 characters (== every 19 units), but it'd be hard to enforce this + * as well as fail on much of existing supposedly base64 compliant + * systems. So, we will just verify that white space can not be used + * within 4 char units. + */ + public void testInvalidWhitespace() + throws XMLStreamException + { + // Let's try out couple of arbitrary broken ones... + final byte[] resultBuffer = new byte[20]; + + for (int bv = 0; bv < sBase64Variants.length; ++bv) { + Base64Variant b64variant = sBase64Variants[bv]; + for (int i = 0; i < INVALID_WS.length; ++i) { + String doc = ""+INVALID_WS[i]+""; + XMLStreamReader2 sr = getElemReader(doc); + try { + /*int count = */ sr.readElementAsBinary(resultBuffer, 0, resultBuffer.length, b64variant); + fail("Should have received an exception for white space used 'inside' 4-char base64 unit"); + } catch (TypedXMLStreamException ex) { + // any way to check that it's the excepted message? not right now + } + sr.close(); + } + } + } + + public void testInvalidWeirdChars() + throws XMLStreamException + { + final byte[] resultBuffer = new byte[20]; + + for (int bv = 0; bv < sBase64Variants.length; ++bv) { + Base64Variant b64variant = sBase64Variants[bv]; + for (int i = 0; i < INVALID_WEIRD_CHARS.length; ++i) { + String doc = ""+INVALID_WEIRD_CHARS[i]+""; + XMLStreamReader2 sr = getElemReader(doc); + try { + /*int count = */ sr.readElementAsBinary(resultBuffer, 0, resultBuffer.length, b64variant); + fail("Should have received an exception for invalid base64 character"); + } catch (TypedXMLStreamException ex) { + // any way to check that it's the excepted message? not right now + } + sr.close(); + } + } + } + + public void testIncompleteInvalidElem() + throws XMLStreamException + { + // Let's just try with short partial segments, data used doesn't matter + final byte[] data = new byte[6]; + final byte[] resultBuffer = new byte[20]; + // plus also skip non-padded variants, for now + + // So first we'll encode 1 to 6 bytes as base64 + for (int bv = 0; bv < sPaddingVariants.length; ++bv) { + Base64Variant b64variant = sPaddingVariants[bv]; + for (int i = 1; i <= data.length; ++i) { + AsciiValueEncoder enc = new ValueEncoderFactory().getEncoder(b64variant, data, 0, i); + char[] cbuf = new char[20]; + int clen = enc.encodeMore(cbuf, 0, cbuf.length); + + // and use all byte last 1, 2 or 3 chars + for (int j = 1; j <= 3; ++j) { + int testLen = clen-j; + StringBuffer sb = new StringBuffer(); + sb.append(""); + sb.append(cbuf, 0, testLen); + sb.append(""); + + XMLStreamReader2 sr = getElemReader(sb.toString()); + try { + /*int count = */ sr.readElementAsBinary(resultBuffer, 0, resultBuffer.length, b64variant); + fail("Should have received an exception for incomplete base64 unit"); + } catch (TypedXMLStreamException ex) { + // any way to check that it's the excepted message? not right now + } + sr.close(); + } + } + } + } + + /* + //////////////////////////////////////// + // Test methods, attr, valid + //////////////////////////////////////// + */ + + /** + * API to access attribute values is much simpler; hence fewer + * things need testing + */ + public void testBinaryAttrValid() throws XMLStreamException + { + final int REPS = 3; + for (int j = 0; j < REPS; ++j) { + for (int bv = 0; bv < sBase64Variants.length; ++bv) { + Base64Variant b64variant = sBase64Variants[bv]; + for (int i = 0; i < LEN_ATTR.length; ++i) { + int size = LEN_ATTR[i]; + byte[] data = generateData(new Random(size), size); + char[] buffer = new char[4 + (data.length * 3 / 2)]; + AsciiValueEncoder enc = new ValueEncoderFactory().getEncoder(b64variant, data, 0, data.length); + int len = enc.encodeMore(buffer, 0, buffer.length); + StringBuilder sb = new StringBuilder(buffer.length + 32); + sb.append(""); + XMLStreamReader2 sr = getElemReader(sb.toString()); + byte[] actData = null; + try { + actData = sr.getAttributeAsBinary(0, b64variant); + } catch (TypedXMLStreamException e) { + fail("Failed for variant "+b64variant+", input '"+e.getLexical()+"': "+e.getMessage()); + } + + assertNotNull(actData); + assertEquals(data.length, actData.length); + for (int x = 0; x < data.length; ++x) { + if (data[x] != actData[x]) { + fail("Corrupt decode at #"+x+"/"+data.length+", expected "+displayByte(data[x])+", got "+displayByte(actData[x])); + } + } + } + } + } + } + + /* + //////////////////////////////////////// + // Test methods, attr, invalid + //////////////////////////////////////// + */ + + public void testInvalidAttrPadding() + throws XMLStreamException + { + // Hmmh. Here we need to skip testing of non-padded variants... + for (int bv = 0; bv < sPaddingVariants.length; ++bv) { + Base64Variant b64variant = sPaddingVariants[bv]; + + for (int i = 0; i < INVALID_PADDING.length; ++i) { + String doc = ""; + XMLStreamReader2 sr = getElemReader(doc); + try { + /*byte[] data = */ sr.getAttributeAsBinary(0, b64variant); + fail("Should have received an exception for invalid padding"); + } catch (TypedXMLStreamException ex) { + // any way to check that it's the excepted message? not right now + } + sr.close(); + } + } + } + + public void testInvalidAttrWhitespace() + throws XMLStreamException + { + for (int bv = 0; bv < sBase64Variants.length; ++bv) { + Base64Variant b64variant = sBase64Variants[bv]; + for (int i = 0; i < INVALID_WS.length; ++i) { + String doc = ""; + XMLStreamReader2 sr = getElemReader(doc); + try { + /*byte[] data = */ sr.getAttributeAsBinary(0, b64variant); + fail("Should have received an exception for white space used 'inside' 4-char base64 unit"); + } catch (TypedXMLStreamException ex) { + // any way to check that it's the excepted message? not right now + } + sr.close(); + } + } + } + + public void testInvalidAttrWeirdChars() + throws XMLStreamException + { + for (int bv = 0; bv < sBase64Variants.length; ++bv) { + Base64Variant b64variant = sBase64Variants[bv]; + for (int i = 0; i < INVALID_WEIRD_CHARS.length; ++i) { + String doc = ""; + XMLStreamReader2 sr = getElemReader(doc); + try { + /*byte[] data = */ sr.getAttributeAsBinary(0, b64variant); + fail("Should have received an exception for invalid base64 character"); + } catch (TypedXMLStreamException ex) { + // any way to check that it's the excepted message? not right now + } + sr.close(); + } + } + } + + public void testInvalidAttrIncomplete() + throws XMLStreamException + { + // Let's just try with short partial segments, data used doesn't matter + final byte[] data = new byte[6]; + // plus also skip non-padded variants, for now + + for (int bv = 0; bv < sPaddingVariants.length; ++bv) { + Base64Variant b64variant = sPaddingVariants[bv]; + + // So first we'll encode 1 to 6 bytes as base64 + for (int i = 1; i <= data.length; ++i) { + AsciiValueEncoder enc = new ValueEncoderFactory().getEncoder(b64variant, data, 0, i); + char[] cbuf = new char[20]; + int clen = enc.encodeMore(cbuf, 0, cbuf.length); + + // and use all byte last 1, 2 or 3 chars + for (int j = 1; j <= 3; ++j) { + int testLen = clen-j; + StringBuffer sb = new StringBuffer(); + sb.append(""); + XMLStreamReader2 sr = getElemReader(sb.toString()); + try { + /*byte[] data = */ sr.getAttributeAsBinary(0, b64variant); + fail("Should have received an exception for incomplete base64 unit"); + } catch (TypedXMLStreamException ex) { + // any way to check that it's the excepted message? not right now + } + sr.close(); + } + } + } + } + + /* + //////////////////////////////////////// + // Helper methods + //////////////////////////////////////// + */ + + private byte[] generateData(Random r, int size) + { + byte[] result = new byte[size]; + r.nextBytes(result); + return result; + } + + private byte[][] generateDataTable(Random r, int size, int reps) + { + byte[][] table = new byte[reps][]; + for (int i = 0; i < reps; ++i) { + table[i] = generateData(r, size); + } + return table; + } + + private String buildDoc(Base64Variant b64variant, Random r, byte[] data, boolean addNoise) + { + // Let's use base64 codec from RI here: + AsciiValueEncoder enc = new ValueEncoderFactory().getEncoder(b64variant, data, 0, data.length); + + StringBuffer sb = new StringBuffer(data.length * 2); + sb.append(""); + + // Without noise it's quite easy, just need enough space: + if (!addNoise) { + // Base64 adds 33% overhead, but let's be generous + char[] buffer = new char[4 + (data.length * 3 / 2)]; + int len = enc.encodeMore(buffer, 0, buffer.length); + sb.append(buffer, 0, len); + } else { + // but with noise, need bit different approach + char[] buffer = new char[300]; + + while (!enc.isCompleted()) { + int offset = r.nextInt() & 0xF; + int len; + int rn = r.nextInt() & 15; + + switch (rn) { + case 1: + case 2: + case 3: + case 4: + len = rn; + break; + case 5: + case 6: + case 7: + len = 3 + (r.nextInt() & 15); + break; + default: + len = 20 + (r.nextInt() & 127); + break; + } + int end = enc.encodeMore(buffer, offset, offset+len); + + // regular or CDATA? + boolean cdata = r.nextBoolean() && r.nextBoolean(); + + if (cdata) { + sb.append(""); + } + + // Let's add noise 25% of time + if (r.nextBoolean() && r.nextBoolean()) { + sb.append(""); + } else { + sb.append(""); + } + } + } + sb.append(""); + return sb.toString(); + } + + private String buildMultiElemDoc(Base64Variant b64variant, byte[][] dataTable) + { + StringBuffer sb = new StringBuffer(16 + dataTable.length * dataTable[0].length); + sb.append(""); + for (int i = 0; i < dataTable.length; ++i) { + byte[] data = dataTable[i]; + char[] buffer = new char[4 + (data.length * 3 / 2)]; + AsciiValueEncoder enc = new ValueEncoderFactory().getEncoder(b64variant, data, 0, data.length); + int len = enc.encodeMore(buffer, 0, buffer.length); + sb.append(""); + sb.append(buffer, 0, len); + sb.append(""); + } + sb.append(""); + return sb.toString(); + } + + final static String displayByte(byte b) { + return "0x"+Integer.toHexString(b & 0xFF); + } +} diff -Nru libwoodstox-java-4.1.3/src/test/java/stax2/typed/ReaderTestBase.java libwoodstox-java-5.1.0/src/test/java/stax2/typed/ReaderTestBase.java --- libwoodstox-java-4.1.3/src/test/java/stax2/typed/ReaderTestBase.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/stax2/typed/ReaderTestBase.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,884 @@ +package stax2.typed; + +import java.math.BigDecimal; +import java.math.BigInteger; +import java.util.Random; + +import javax.xml.namespace.QName; +import javax.xml.stream.*; + +import org.codehaus.stax2.*; +import org.codehaus.stax2.typed.*; + +import stax2.BaseStax2Test; + +/** + * Base class that contains set of simple unit tests to verify implementation + * of {@link TypedXMLStreamReader}. Concrete sub-classes are used to + * test both native and wrapped Stax2 implementations. + * + * @author Tatu Saloranta + */ +public abstract class ReaderTestBase + extends BaseStax2Test +{ + final static long TOO_BIG_FOR_INT = Integer.MAX_VALUE+1L; + final static long TOO_SMALL_FOR_INT = Integer.MIN_VALUE-1L; + + final static BigInteger TOO_BIG_FOR_LONG = BigInteger.valueOf(Long.MAX_VALUE).add(BigInteger.valueOf(123)); + final static BigInteger TOO_SMALL_FOR_LONG = BigInteger.valueOf(Long.MIN_VALUE).subtract(BigInteger.valueOf(123)); + + /* + //////////////////////////////////////// + // Tests for boolean, integral numbers + //////////////////////////////////////// + */ + + public void testSimpleBooleanElem() + throws Exception + { + // simple boolean + checkBooleanElem("true", true); + // with white space normalization + checkBooleanElem("\tfalse\n\r", false); + // Then non9-canonical alternatives + checkBooleanElem("0 \t", false); + checkBooleanElem("\r1", true); + + // And finally invalid ones + checkBooleanElemException("yes"); + /* Although "01" would be valid integer equal to "1", + * it's not a legal boolean nonetheless (as per my reading + * of W3C Schema specs) + */ + checkBooleanElemException("01"); + } + + public void testSimpleBooleanAttr() + throws Exception + { + checkBooleanAttr("", true); + checkBooleanAttr("", false); + checkBooleanAttr("", false); + checkBooleanAttr("", true); + + checkBooleanAttrException(""); + checkBooleanAttrException(""); + } + + public void testMultipleBooleanAttr() + throws Exception + { + XMLStreamReader2 sr = getRootReader(""); + assertEquals(3, sr.getAttributeCount()); + int ix1 = sr.getAttributeIndex("", "a1"); + int ix2 = sr.getAttributeIndex("", "b"); + int ix3 = sr.getAttributeIndex("", "third"); + if (ix1 < 0 || ix2 < 0 || ix3 < 0) { + fail("Couldn't find indexes of attributes: a1="+ix1+", b="+ix2+", third="+ix3); + } + assertTrue(sr.getAttributeAsBoolean(ix1)); + assertFalse(sr.getAttributeAsBoolean(ix2)); + assertFalse(sr.getAttributeAsBoolean(ix3)); + + sr.close(); + } + + public void testSimpleIntElem() + throws Exception + { + checkIntElem("000000000000000000000000012", 12); + + + checkIntElem("0", 0); + // with white space normalization + checkIntElem("291\t", 291); + checkIntElem(" \t1", 1); + checkIntElem("3 ", 3); + checkIntElem(" -7 ", -7); + // with signs, spacing etc + checkIntElem("-1234", -1234); + checkIntElem("+3", 3); + checkIntElem("-0", 0); + checkIntElem("-0000", 0); + checkIntElem("-001", -1); + checkIntElem("+0", 0); + checkIntElem("+0 ", 0); + checkIntElem("+00", 0); + checkIntElem("000000000000000000000000012", 12); + checkIntElem("-00000000", 0); + int v = 1200300400; + checkIntElem(" \r\n+"+v+"", v); + checkIntElem(" "+Integer.MAX_VALUE+"", Integer.MAX_VALUE); + checkIntElem(" "+Integer.MIN_VALUE+"", Integer.MIN_VALUE); + + // And finally invalid ones + checkIntElemException("12a3"); + checkIntElemException("5000100200"); // overflow + checkIntElemException("3100200300"); // overflow + checkIntElemException("-4100200300"); // underflow + checkIntElemException(""+TOO_BIG_FOR_INT+""); // overflow as well + checkIntElemException(""+TOO_SMALL_FOR_INT+""); // underflow as well + checkIntElemException("- "); + checkIntElemException("+"); + checkIntElemException(" -"); + } + + public void testSimpleIntAttr() + throws Exception + { + checkIntAttr("", 0); + checkIntAttr("", 13); + checkIntAttr("", 123); + checkIntAttr("", -12); + checkIntAttr("", 0); + checkIntAttr("", 0); + checkIntAttr("", -12345); + checkIntAttr("", Integer.MAX_VALUE); + checkIntAttr("", Integer.MIN_VALUE); + + checkIntAttrException(""); + checkIntAttrException(""); + checkIntAttrException(""); + checkIntAttrException(""); + checkIntAttrException(""); + checkIntAttrException(""); + } + + public void testMultipleIntAttr() + throws Exception + { + XMLStreamReader2 sr = getRootReader(""); + assertEquals(3, sr.getAttributeCount()); + int ix1 = sr.getAttributeIndex("", "a1"); + int ix2 = sr.getAttributeIndex("", "b"); + int ix3 = sr.getAttributeIndex("", "third"); + if (ix1 < 0 || ix2 < 0 || ix3 < 0) { + fail("Couldn't find indexes of attributes: a1="+ix1+", b="+ix2+", third="+ix3); + } + assertEquals(123456789, sr.getAttributeAsInt(ix1)); + assertEquals(-123456789, sr.getAttributeAsInt(ix2)); + assertEquals(0, sr.getAttributeAsInt(ix3)); + + sr.close(); + } + + public void testSimpleLongElem() + throws Exception + { + checkLongElem("000000000000000000000000012", 12); + + + checkLongElem("0", 0); + // with white space normalization + checkLongElem("10091\t", 10091); + checkLongElem(" \t-1", -1); + checkLongElem("39876 ", 39876); + checkLongElem(" 0701 ", 701); + // with signs, spacing etc + checkLongElem("-1234", -1234); + checkLongElem("+3", 3); + checkLongElem("-0", 0); + checkLongElem("-001", -1); + checkLongElem("+0", 0); + checkLongElem("0000000000000001234567890", 1234567890L); + checkLongElem("-00000000", 0); + long v = 1200300400500600L; + checkLongElem(" \r"+v+"", v); + checkLongElem(" \r\n+"+v+"", v); + v = -1234567890123456789L; + checkLongElem(" \r\n"+v+"", v); + checkLongElem(" "+Long.MAX_VALUE+"", Long.MAX_VALUE); + checkLongElem(" "+Long.MIN_VALUE+"", Long.MIN_VALUE); + + // And finally invalid ones + checkLongElemException("12a3"); + checkLongElemException(""+TOO_BIG_FOR_LONG+""); // overflow as well + checkLongElemException(""+TOO_SMALL_FOR_LONG+""); // underflow as well + checkLongElemException("- "); + checkLongElemException("+"); + checkLongElemException(" -"); + } + + public void testSimpleLongAttr() + throws Exception + { + checkLongAttr("", 0); + checkLongAttr("", 13); + checkLongAttr("", 123); + checkLongAttr("", -12); + checkLongAttr("", 0); + checkLongAttr("", 0); + checkLongAttr("", -12345); + checkLongAttr("", Long.MAX_VALUE); + checkLongAttr("", Long.MIN_VALUE); + + checkLongAttrException(""); + checkLongAttrException(""); + checkLongAttrException(""); + checkLongAttrException(""); + checkLongAttrException(""); + checkLongAttrException(""); + } + + public void testMultipleLongAttr() + throws Exception + { + XMLStreamReader2 sr = getRootReader(""); + assertEquals(3, sr.getAttributeCount()); + int ix1 = sr.getAttributeIndex("", "a1"); + int ix2 = sr.getAttributeIndex("", "b"); + int ix3 = sr.getAttributeIndex("", "third"); + if (ix1 < 0 || ix2 < 0 || ix3 < 0) { + fail("Couldn't find indexes of attributes: a1="+ix1+", b="+ix2+", third="+ix3); + } + assertEquals(12345678900L, sr.getAttributeAsLong(ix1)); + assertEquals(-12345678900L, sr.getAttributeAsLong(ix2)); + assertEquals(0L, sr.getAttributeAsLong(ix3)); + + sr.close(); + } + + /* + //////////////////////////////////////// + // Tests for floating point numbers + //////////////////////////////////////// + */ + + public void testSimpleFloatElem() + throws Exception + { + checkFloatElem("0.0", 0.0f); + checkFloatElem("0", 0.0f); + // with white space normalization + checkFloatElem("1.0\t", 1.0f); + checkFloatElem(" \t-0.1", -0.1f); + checkFloatElem("+.001 ", 0.001f); + checkFloatElem(" -3.1415 ", -3.1415f); + checkFloatElem("27.3E-01", 2.73e-01f); + checkFloatElem(" "+Float.MAX_VALUE+"", Float.MAX_VALUE); + checkFloatElem(" "+Float.MIN_VALUE+"", Float.MIN_VALUE); + checkFloatElem(" NaN", Float.NaN); + checkFloatElem("INF ", Float.POSITIVE_INFINITY); + checkFloatElem("\t-INF\t", Float.NEGATIVE_INFINITY); + + // And finally invalid ones + checkFloatElemException("abcd"); + checkFloatElemException("- "); + checkFloatElemException("+"); + checkFloatElemException(" -"); + checkFloatElemException("1e"); + } + + public void testSimpleFloatAttr() + throws Exception + { + checkFloatAttr("", 0.1f); + checkFloatAttr("", 13.23f); + checkFloatAttr("", 0.123f); + checkFloatAttr("", -12.03f); + checkFloatAttr("", 0.0f); + checkFloatAttr("", 0.0f); + checkFloatAttr("", -12345f); + checkFloatAttr("", Float.MAX_VALUE); + checkFloatAttr("", Float.MIN_VALUE); + checkFloatAttr("", Float.NaN); + checkFloatAttr("", Float.POSITIVE_INFINITY); + checkFloatAttr("", Float.NEGATIVE_INFINITY); + + checkFloatAttrException(""); + checkFloatAttrException(""); + checkFloatAttrException(""); + checkFloatAttrException(""); + } + + public void testMultipleFloatAttr() + throws Exception + { + XMLStreamReader2 sr = getRootReader(""); + assertEquals(3, sr.getAttributeCount()); + int ix1 = sr.getAttributeIndex("", "a1"); + int ix2 = sr.getAttributeIndex("", "b"); + int ix3 = sr.getAttributeIndex("", "third"); + if (ix1 < 0 || ix2 < 0 || ix3 < 0) { + fail("Couldn't find indexes of attributes: a1="+ix1+", b="+ix2+", third="+ix3); + } + assertEquals(-123.456f, sr.getAttributeAsFloat(ix1)); + assertEquals(0.003f, sr.getAttributeAsFloat(ix2)); + assertEquals(-0.0f, sr.getAttributeAsFloat(ix3)); + + sr.close(); + } + + public void testSimpleDoubleElem() + throws Exception + { + checkDoubleElem("0.0", 0.0f); + checkDoubleElem("0", 0.0f); + // with white space normalization + checkDoubleElem("1.0\t", 1.0f); + checkDoubleElem(" \t-0.1", -0.1f); + checkDoubleElem("+.001 ", 0.001f); + checkDoubleElem(" -3.1415 ", -3.1415f); + checkDoubleElem("27.3E-01", 2.73e-01f); + checkDoubleElem(" "+Double.MAX_VALUE+"", Double.MAX_VALUE); + checkDoubleElem(" "+Double.MIN_VALUE+"", Double.MIN_VALUE); + checkDoubleElem(" NaN", Double.NaN); + checkDoubleElem("INF ", Double.POSITIVE_INFINITY); + checkDoubleElem("\t-INF\t", Double.NEGATIVE_INFINITY); + + // And finally invalid ones + checkDoubleElemException("abcd"); + checkDoubleElemException("- "); + checkDoubleElemException("+"); + checkDoubleElemException(" -"); + checkDoubleElemException("1e"); + } + + public void testSimpleDoubleAttr() + throws Exception + { + checkDoubleAttr("", 0.1f); + checkDoubleAttr("", 13.23f); + checkDoubleAttr("", 0.123f); + checkDoubleAttr("", -12.03f); + checkDoubleAttr("", 0.0f); + checkDoubleAttr("", 0.0f); + checkDoubleAttr("", -12345f); + checkDoubleAttr("", Double.MAX_VALUE); + checkDoubleAttr("", Double.MIN_VALUE); + checkDoubleAttr("", Double.NaN); + checkDoubleAttr("", Double.POSITIVE_INFINITY); + checkDoubleAttr("", Double.NEGATIVE_INFINITY); + + checkDoubleAttrException(""); + checkDoubleAttrException(""); + checkDoubleAttrException(""); + checkDoubleAttrException(""); + } + + public void testMultipleDoubleAttr() + throws Exception + { + XMLStreamReader2 sr = getRootReader(""); + assertEquals(3, sr.getAttributeCount()); + int ix1 = sr.getAttributeIndex("", "a1"); + int ix2 = sr.getAttributeIndex("", "b"); + int ix3 = sr.getAttributeIndex("", "third"); + if (ix1 < 0 || ix2 < 0 || ix3 < 0) { + fail("Couldn't find indexes of attributes: a1="+ix1+", b="+ix2+", third="+ix3); + } + assertEquals(-123.456f, sr.getAttributeAsDouble(ix1)); + assertEquals(0.003f, sr.getAttributeAsDouble(ix2)); + assertEquals(-0.0f, sr.getAttributeAsDouble(ix3)); + + sr.close(); + } + + /* + //////////////////////////////////////// + // Tests for "big" numbers + //////////////////////////////////////// + */ + + /** + * With unlimited length BigInteger, it's easier to just generate + * very big (long) numbers, and test variability that way. + */ + public void testBigInteger() + throws Exception + { + /* Let's just generate reasonably big (up to 200 digits) + * numbers, and test some variations + */ + BigInteger I = BigInteger.valueOf(3); + Random rnd = new Random(1); + for (int i = 1; i < 200; ++i) { + // First, regular elem content + String doc; + String istr = I.toString(); + + switch (i % 4) { // some white space variations + case 0: + istr = " \t "+istr; + break; + case 1: + istr = istr+"\r"; + break; + case 2: + istr = "\n"+istr+" "; + break; + } + XMLStreamReader2 sr = getRootReader(""+istr+""); + assertEquals(I, sr.getElementAsInteger()); + sr.close(); + // Then attribute + doc = ""; + sr = getRootReader(doc); + assertEquals(I, sr.getAttributeAsInteger(0)); + sr.close(); + + // And finally, invalid + istr = I.toString(); + + switch (i % 3) { + case 0: + istr = "ab"+istr; + break; + case 1: + istr = istr+"!"; + break; + case 2: + istr = istr+".0"; + break; + } + + sr = getRootReader(""+istr+""); + try { + sr.getElementAsInteger(); + fail("Expected exception for invalid input ["+doc+"]"); + } catch (TypedXMLStreamException xse) { ; // good + } + sr.close(); + + sr = getRootReader(""); + try { + sr.getAttributeAsInteger(0); + fail("Expected exception for invalid input ["+doc+"]"); + } catch (TypedXMLStreamException xse) { ; // good + } + sr.close(); + + // And then, let's just multiply by 10, add a new digit + I = I.multiply(BigInteger.valueOf(10)).add(BigInteger.valueOf(rnd.nextInt() & 0xF)); + + // Plus switch sign every now and then + if ((i % 3) == 0) { + I = I.negate(); + } + } + } + + /** + * As with BigInteger, we better use number generation with + * BigDecimal. + */ + public void testBigDecimal() + throws Exception + { + BigDecimal D = BigDecimal.valueOf(1L); + Random rnd = new Random(6); + // 200 digits seems ok here too + for (int i = 1; i < 200; ++i) { + // First, regular elem content + String doc; + String istr = D.toString(); + + switch (i % 4) { // some white space variations + case 0: + istr = "\t"+istr; + break; + case 1: + istr = istr+" "; + break; + case 2: + istr = " "+istr+"\r"; + break; + } + XMLStreamReader2 sr = getRootReader(""+istr+""); + assertEquals(D, sr.getElementAsDecimal()); + sr.close(); + // Then attribute + doc = ""; + sr = getRootReader(doc); + assertEquals(D, sr.getAttributeAsDecimal(0)); + sr.close(); + + // And finally, invalid + istr = D.toString(); + + switch (i % 3) { + case 0: + istr = "_x"+istr; + break; + case 1: + istr = istr+"?"; + break; + case 2: + istr = istr+"e"; + break; + } + + sr = getRootReader(""+istr+""); + try { + sr.getElementAsDecimal(); + fail("Expected exception for invalid input ["+doc+"]"); + } catch (TypedXMLStreamException xse) { ; // good + } + sr.close(); + + sr = getRootReader(""); + try { + sr.getAttributeAsDecimal(0); + fail("Expected exception for invalid input ["+doc+"]"); + } catch (TypedXMLStreamException xse) { ; // good + } + sr.close(); + + // Ok, then, add a small integer, divide by 10 to generate digits + D = D.add(BigDecimal.valueOf(rnd.nextInt() & 0xF)).divide(BigDecimal.valueOf(10L)); + + // Plus switch sign every now and then + if ((i % 3) == 0) { + D = D.negate(); + } + } + } + + /* + //////////////////////////////////////// + // Tests for name type(s) + //////////////////////////////////////// + */ + + public void testValidQNameElem() + throws Exception + { + String URI = "http://test.org/"; + String XML = "ns:name "; + XMLStreamReader2 sr = getRootReader(XML); + QName n = sr.getElementAsQName(); + assertNotNull(n); + assertEquals("name", n.getLocalPart()); + assertEquals("ns", n.getPrefix()); + assertEquals(URI, n.getNamespaceURI()); + sr.close(); + } + + public void testInvalidQNameElemUnbound() + throws Exception + { + XMLStreamReader2 sr = getRootReader("ns:name "); + // First, unbound namespace prefix + try { + /*QName n =*/ sr.getElementAsQName(); + fail("Expected an exception for unbound QName prefix"); + } catch (TypedXMLStreamException tex) { } + sr.close(); + } + + public void testInvalidQNameElemBadChars() + throws Exception + { + XMLStreamReader2 sr = getRootReader("ns:na?me"); + try { + /* QName n =*/ sr.getElementAsQName(); + fail("Expected an exception for invalid QName (non-xml-name char in the middle)"); + } catch (TypedXMLStreamException tex) { } + sr.close(); + } + + public void testValidQNameAttr() + throws Exception + { + String URI = "http://test.org/"; + String XML = ""; + XMLStreamReader2 sr = getRootReader(XML); + QName n = sr.getAttributeAsQName(0); + assertNotNull(n); + assertEquals("x1", n.getLocalPart()); + assertEquals("abc", n.getPrefix()); + assertEquals(URI, n.getNamespaceURI()); + sr.close(); + } + + public void testInvalidQNameAttrUnbound() + throws Exception + { + XMLStreamReader2 sr = getRootReader(""); + // First, unbound namespace prefix + try { + /* QName n =*/ sr.getAttributeAsQName(0); + fail("Expected an exception for unbound QName prefix"); + } catch (TypedXMLStreamException tex) { } + sr.close(); + } + + public void testInvalidQNameAttrBadChars() + throws Exception + { + XMLStreamReader2 sr = getRootReader(""); + try { + /* QName n =*/ sr.getAttributeAsQName(0); + fail("Expected an exception for invalid QName (non-xml-name char in the middle)"); + } catch (TypedXMLStreamException tex) { } + sr.close(); + } + + /* + //////////////////////////////////////// + // Private methods, second-level tests + //////////////////////////////////////// + */ + + private void checkBooleanElem(String doc, boolean expState) + throws XMLStreamException + { + XMLStreamReader2 sr = getRootReader(doc); + assertEquals(expState, sr.getElementAsBoolean()); + sr.close(); + } + + private void checkBooleanAttr(String doc, boolean expState) + throws XMLStreamException + { + XMLStreamReader2 sr = getRootReader(doc); + // Assumption is that there's just one attribute... + boolean actState = sr.getAttributeAsBoolean(0); + assertEquals(expState, actState); + sr.close(); + } + + private void checkBooleanElemException(String doc) + throws XMLStreamException + { + XMLStreamReader2 sr = getRootReader(doc); + try { + /*boolean b =*/ sr.getElementAsBoolean(); + fail("Expected exception for invalid input ["+doc+"]"); + } catch (TypedXMLStreamException xse) { + ; // good + } + } + + private void checkBooleanAttrException(String doc) + throws XMLStreamException + { + XMLStreamReader2 sr = getRootReader(doc); + try { + /*boolean b =*/ sr.getAttributeAsBoolean(0); + fail("Expected exception for invalid input ["+doc+"]"); + } catch (TypedXMLStreamException xse) { + ; // good + } + } + + private void checkIntElem(String doc, int expState) + throws XMLStreamException + { + XMLStreamReader2 sr = getRootReader(doc); + assertEquals(expState, sr.getElementAsInt()); + sr.close(); + } + + private void checkIntAttr(String doc, int expState) + throws XMLStreamException + { + XMLStreamReader2 sr = getRootReader(doc); + // Assumption is that there's just one attribute... + int actState = sr.getAttributeAsInt(0); + assertEquals(expState, actState); + sr.close(); + } + + private void checkIntElemException(String doc) + throws XMLStreamException + { + XMLStreamReader2 sr = getRootReader(doc); + try { + /*int b =*/ sr.getElementAsInt(); + fail("Expected exception for invalid input ["+doc+"]"); + } catch (TypedXMLStreamException xse) { + ; // good + } + } + + private void checkIntAttrException(String doc) + throws XMLStreamException + { + XMLStreamReader2 sr = getRootReader(doc); + try { + /*int b =*/ sr.getAttributeAsInt(0); + fail("Expected exception for invalid input ["+doc+"]"); + } catch (TypedXMLStreamException xse) { + ; // good + } + } + + private void checkLongElem(String doc, long expState) + throws XMLStreamException + { + XMLStreamReader2 sr = getRootReader(doc); + assertEquals(expState, sr.getElementAsLong()); + sr.close(); + } + + private void checkLongAttr(String doc, long expState) + throws XMLStreamException + { + XMLStreamReader2 sr = getRootReader(doc); + // Assumption is that there's just one attribute... + long actState = sr.getAttributeAsLong(0); + assertEquals(expState, actState); + sr.close(); + } + + private void checkLongElemException(String doc) + throws XMLStreamException + { + XMLStreamReader2 sr = getRootReader(doc); + try { + /*long b =*/ sr.getElementAsLong(); + fail("Expected exception for invalid input ["+doc+"]"); + } catch (TypedXMLStreamException xse) { + ; // good + } + } + + private void checkLongAttrException(String doc) + throws XMLStreamException + { + XMLStreamReader2 sr = getRootReader(doc); + try { + /*long b =*/ sr.getAttributeAsLong(0); + fail("Expected exception for invalid input ["+doc+"]"); + } catch (TypedXMLStreamException xse) { + ; // good + } + } + + private void checkFloatElem(String doc, float expState) + throws XMLStreamException + { + XMLStreamReader2 sr = getRootReader(doc); + assertEquals(expState, sr.getElementAsFloat()); + sr.close(); + } + + private void checkFloatAttr(String doc, float expState) + throws XMLStreamException + { + XMLStreamReader2 sr = getRootReader(doc); + // Assumption is that there's just one attribute... + float actState = sr.getAttributeAsFloat(0); + assertEquals(expState, actState); + sr.close(); + } + + private void checkFloatElemException(String doc) + throws XMLStreamException + { + XMLStreamReader2 sr = getRootReader(doc); + try { + /*float b =*/ sr.getElementAsFloat(); + fail("Expected exception for invalid input ["+doc+"]"); + } catch (TypedXMLStreamException xse) { + ; // good + } + } + + private void checkFloatAttrException(String doc) + throws XMLStreamException + { + XMLStreamReader2 sr = getRootReader(doc); + try { + /*float b =*/ sr.getAttributeAsFloat(0); + fail("Expected exception for invalid input ["+doc+"]"); + } catch (TypedXMLStreamException xse) { + ; // good + } + } + + private void checkDoubleElem(String doc, double expState) + throws XMLStreamException + { + XMLStreamReader2 sr = getRootReader(doc); + assertEquals(expState, sr.getElementAsDouble()); + sr.close(); + } + + private void checkDoubleAttr(String doc, double expState) + throws XMLStreamException + { + XMLStreamReader2 sr = getRootReader(doc); + // Assumption is that there's just one attribute... + double actState = sr.getAttributeAsDouble(0); + assertEquals(expState, actState); + sr.close(); + } + + private void checkDoubleElemException(String doc) + throws XMLStreamException + { + XMLStreamReader2 sr = getRootReader(doc); + try { + /*double b =*/ sr.getElementAsDouble(); + fail("Expected exception for invalid input ["+doc+"]"); + } catch (TypedXMLStreamException xse) { + ; // good + } + } + + private void checkDoubleAttrException(String doc) + throws XMLStreamException + { + XMLStreamReader2 sr = getRootReader(doc); + try { + /*double b =*/ sr.getAttributeAsDouble(0); + fail("Expected exception for invalid input ["+doc+"]"); + } catch (TypedXMLStreamException xse) { + ; // good + } + } + + /* + //////////////////////////////////////// + // Abstract methods + //////////////////////////////////////// + */ + + protected abstract XMLStreamReader2 getReader(String contents) + throws Exception; + + /* + //////////////////////////////////////// + // Private methods + //////////////////////////////////////// + */ + + private void assertEquals(float a, float b) + { + if (Float.isNaN(a)) { + assertTrue(Float.isNaN(b)); + } else if (a != b) { + assertEquals(a, b, 1000.0f); // just to make it fail + } + } + + private void assertEquals(double a, double b) + { + if (Double.isNaN(a)) { + assertTrue(Double.isNaN(b)); + } else if (a != b) { + assertEquals(a, b, 1000.0f); // just to make it fail + } + } + + // XMLStreamReader2 extends TypedXMLStreamReader + protected XMLStreamReader2 getRootReader(String str) + throws XMLStreamException + { + XMLStreamReader2 sr; + try { + sr = getReader(str); + } catch (XMLStreamException xse) { + throw xse; + } catch (Exception e) { + throw new XMLStreamException(e); + } + assertTokenType(START_DOCUMENT, sr.getEventType()); + while (sr.next() != START_ELEMENT) { } + assertTokenType(START_ELEMENT, sr.getEventType()); + return sr; + } +} diff -Nru libwoodstox-java-4.1.3/src/test/java/stax2/typed/TestBinaryRoundTrip.java libwoodstox-java-5.1.0/src/test/java/stax2/typed/TestBinaryRoundTrip.java --- libwoodstox-java-4.1.3/src/test/java/stax2/typed/TestBinaryRoundTrip.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/stax2/typed/TestBinaryRoundTrip.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,108 @@ +package stax2.typed; + +import java.io.*; +import java.util.Arrays; + +import javax.xml.stream.*; + +import org.codehaus.stax2.*; +import org.codehaus.stax2.typed.*; + +import stax2.BaseStax2Test; + +public class TestBinaryRoundTrip + extends BaseStax2Test +{ + /** + * Test to verify [WSTX-224]. Note that problems occur only when + * in coalescing mode. + */ + public void testWstx224() throws Exception + { + Base64Variant bv = Base64Variants.MIME; + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + XMLStreamWriter2 writer = getTypedWriter(bos); + byte[] data = new byte[2990]; + // contents shouldn't matter a lot, but: + Arrays.fill(data, (byte) 33); + + writer.writeStartDocument(); + writer.writeStartElement("doc"); + writer.writeStartElement("data"); + writer.writeBinary(bv, data, 0, data.length); + + writer.writeEndElement(); + writer.writeEndElement(); + + writer.writeEndDocument(); + writer.close(); + + byte[] xml = bos.toByteArray(); + + // First: using explicit reads + _doTest224(data, xml, bv, false); + _doTest224(data, xml, bv, true); + } + + private void _doTest224(byte[] data, byte[] xml, Base64Variant bv, boolean useConvAccessor) + throws XMLStreamException + { + XMLStreamReader2 reader = getReader(xml); + byte[] result = null; + while (reader.hasNext()) { + if (reader.next() == XMLStreamConstants.START_ELEMENT && "data".equals(reader.getLocalName())) { + result = _readBinary(reader, bv, xml.length, useConvAccessor); + break; + } + } + assertNotNull(result); + assertEquals(data.length, result.length); + for (int i = 0; i < data.length; ++i) { + if (data[i] != result[i]) { + fail("Data differs at offset #"+i+"; expected "+data[i]+", got "+result[i]); + } + } + } + + private byte[] _readBinary(XMLStreamReader2 sr, Base64Variant bv, + int expSize, + boolean useConvenienceMethod) + throws XMLStreamException + { + // Simplest: just use aggregating... + if (useConvenienceMethod) { + return sr.getElementAsBinary(bv); + } + + byte[] buffer = new byte[expSize+100]; + int offset = 0; + + while (offset < buffer.length) { + int count = sr.readElementAsBinary(buffer, offset, buffer.length-offset, bv); + if (count < 0) { + break; + } + offset += count; + } + byte[] result = new byte[offset]; + System.arraycopy(buffer, 0, result, 0, offset); + return result; + } + + private XMLStreamReader2 getReader(byte[] data) + throws XMLStreamException + { + XMLInputFactory f = getInputFactory(); + setCoalescing(f, true); + setNamespaceAware(f, true); + return (XMLStreamReader2) f.createXMLStreamReader(new ByteArrayInputStream(data)); + } + + protected XMLStreamWriter2 getTypedWriter(ByteArrayOutputStream out) + throws XMLStreamException + { + XMLOutputFactory outf = getOutputFactory(); + return (XMLStreamWriter2) outf.createXMLStreamWriter(out, "UTF-8"); + } +} + diff -Nru libwoodstox-java-4.1.3/src/test/java/stax2/typed/TestDOMArrayReader.java libwoodstox-java-5.1.0/src/test/java/stax2/typed/TestDOMArrayReader.java --- libwoodstox-java-4.1.3/src/test/java/stax2/typed/TestDOMArrayReader.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/stax2/typed/TestDOMArrayReader.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,42 @@ +package stax2.typed; + +import java.io.StringReader; + +import javax.xml.parsers.*; +import javax.xml.stream.*; +import javax.xml.transform.dom.DOMSource; + +import org.w3c.dom.Document; +import org.xml.sax.InputSource; + +import org.codehaus.stax2.XMLStreamReader2; + +/** + * Stax2 Typed Access API basic reader tests for array handling, + * using native Stax2 typed reader implementation. + */ +public class TestDOMArrayReader + extends ReaderArrayTestBase +{ + @Override + protected XMLStreamReader2 getReader(String contents) + throws XMLStreamException + { + try { + XMLInputFactory f = getInputFactory(); + setCoalescing(f, false); // shouldn't really matter + setNamespaceAware(f, true); + + // First, need to parse using JAXP DOM: + DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); + dbf.setNamespaceAware(true); + DocumentBuilder db = dbf.newDocumentBuilder(); + Document doc = db.parse(new InputSource(new StringReader(contents))); + + return (XMLStreamReader2) f.createXMLStreamReader(new DOMSource(doc)); + } catch (Exception e) { + throw new XMLStreamException(e); + } + } +} + diff -Nru libwoodstox-java-4.1.3/src/test/java/stax2/typed/TestDOMBinaryReader.java libwoodstox-java-5.1.0/src/test/java/stax2/typed/TestDOMBinaryReader.java --- libwoodstox-java-4.1.3/src/test/java/stax2/typed/TestDOMBinaryReader.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/stax2/typed/TestDOMBinaryReader.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,42 @@ +package stax2.typed; + +import java.io.StringReader; + +import javax.xml.parsers.*; +import javax.xml.stream.*; +import javax.xml.transform.dom.DOMSource; + +import org.w3c.dom.Document; +import org.xml.sax.InputSource; + +import org.codehaus.stax2.XMLStreamReader2; + +/** + * Stax2 Typed Access API basic reader tests for binary content handling + * using DOM-backed Stax2 typed reader implementation. + */ +public class TestDOMBinaryReader + extends ReaderBinaryTestBase +{ + @Override + protected XMLStreamReader2 getReader(String contents) + throws XMLStreamException + { + try { + XMLInputFactory f = getInputFactory(); + setCoalescing(f, false); // shouldn't really matter + setNamespaceAware(f, true); + + // First, need to parse using JAXP DOM: + DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); + dbf.setNamespaceAware(true); + DocumentBuilder db = dbf.newDocumentBuilder(); + Document doc = db.parse(new InputSource(new StringReader(contents))); + + return (XMLStreamReader2) f.createXMLStreamReader(new DOMSource(doc)); + } catch (Exception e) { + throw new XMLStreamException(e); + } + } +} + diff -Nru libwoodstox-java-4.1.3/src/test/java/stax2/typed/TestDOMReader.java libwoodstox-java-5.1.0/src/test/java/stax2/typed/TestDOMReader.java --- libwoodstox-java-4.1.3/src/test/java/stax2/typed/TestDOMReader.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/stax2/typed/TestDOMReader.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,83 @@ +package stax2.typed; + +import java.io.StringReader; + +import javax.xml.parsers.*; +import javax.xml.stream.*; +import javax.xml.transform.dom.DOMSource; + +import org.w3c.dom.Document; +import org.xml.sax.InputSource; + +import org.codehaus.stax2.XMLStreamReader2; + +/** + * Stax2 Typed Access API basic reader tests, using DOM-backed + * implementation. + */ +public class TestDOMReader + extends ReaderTestBase +{ + @Override + protected XMLStreamReader2 getReader(String contents) throws Exception + { + XMLInputFactory f = getInputFactory(); + setCoalescing(f, false); // shouldn't really matter + setNamespaceAware(f, true); + + // First, need to parse using JAXP DOM: + DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); + dbf.setNamespaceAware(true); + DocumentBuilder db = dbf.newDocumentBuilder(); + Document doc = db.parse(new InputSource(new StringReader(contents))); + + return (XMLStreamReader2) f.createXMLStreamReader(new DOMSource(doc)); + } + + /* + /////////////////////////////////////////////////////////////// + // Need to mask some tests, won't work with current DOM wrapper + /////////////////////////////////////////////////////////////// + */ + + @Override + public void testValidQNameElem() + { + // Ugh: due to missing NS lookups, even this would fail... + warn("(skipping TestDOMReader.testValidQNameElem()"); + } + + @Override + public void testInvalidQNameElemBadChars() + { + warn("(skipping TestDOMReader.testInvalidQNameElemBadChars)"); + } + + @Override + public void testInvalidQNameElemUnbound() + { + // Need DOM3 to support namespace lookups + warn("(skipping TestDOMReader.testInvalidQNameElemUnbound()"); + } + + @Override + public void testValidQNameAttr() + { + warn("(skipping TestDOMReader.testValidQNameAttr()"); + } + + @Override + public void testInvalidQNameAttrBadChars() + { + warn("(skipping TestDOMReader.testInvalidQNameAttrBadChars)"); + } + + @Override + public void testInvalidQNameAttrUnbound() + { + // Need DOM3 to support namespace lookups + warn("(skipping TestDOMReader.testInvalidQNameAttrUnbound()"); + } +} + + diff -Nru libwoodstox-java-4.1.3/src/test/java/stax2/typed/TestDOMWriter.java libwoodstox-java-5.1.0/src/test/java/stax2/typed/TestDOMWriter.java --- libwoodstox-java-4.1.3/src/test/java/stax2/typed/TestDOMWriter.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/stax2/typed/TestDOMWriter.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,76 @@ +package stax2.typed; + +import java.io.*; + +import javax.xml.parsers.*; +import javax.xml.stream.*; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.dom.DOMResult; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.stream.StreamResult; + +import org.w3c.dom.*; +import org.codehaus.stax2.*; + +/** + * Stax2 Typed Access API basic reader tests, using DOM-backed + * typed writer implementation. + *

+ * Note: currently some functionality is only supported with native + * writers + */ +public class TestDOMWriter + extends WriterTestBase +{ + /** + * Nasty hack: we need to remember DOM document we are serializing into, + * to be able to fetch back the results. + */ + Document mDoc; + + @Override + protected XMLStreamWriter2 getTypedWriter(ByteArrayOutputStream out, + boolean repairing) + throws XMLStreamException + { + out.reset(); + XMLOutputFactory outf = getOutputFactory(); + mDoc = createDOMDoc(true); + setRepairing(outf, repairing); + return (XMLStreamWriter2) outf.createXMLStreamWriter(new DOMResult(mDoc)); + } + + @Override + protected byte[] closeWriter(XMLStreamWriter sw, ByteArrayOutputStream out) + throws XMLStreamException + { + sw.close(); + + // Let's use Trax identity "transformer" + try { + Transformer t = TransformerFactory.newInstance().newTransformer(); + t.transform(new DOMSource(mDoc), new StreamResult(out)); + } catch (Exception e) { + throw new RuntimeException(e); + } + return out.toByteArray(); + } + + /* + /////////////////////////////////////////////////////// + // Helper methods + /////////////////////////////////////////////////////// + */ + + private Document createDOMDoc(boolean nsAware) + { + try { + DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); + dbf.setNamespaceAware(nsAware); + return dbf.newDocumentBuilder().newDocument(); + } catch (Exception e) { + throw new RuntimeException(e); + } + } +} diff -Nru libwoodstox-java-4.1.3/src/test/java/stax2/typed/TestNativeArrayReader.java libwoodstox-java-5.1.0/src/test/java/stax2/typed/TestNativeArrayReader.java --- libwoodstox-java-4.1.3/src/test/java/stax2/typed/TestNativeArrayReader.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/stax2/typed/TestNativeArrayReader.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,24 @@ +package stax2.typed; + +import javax.xml.stream.*; + +import org.codehaus.stax2.XMLStreamReader2; + +/** + * Stax2 Typed Access API basic reader tests for array handling, + * using native Stax2 typed reader implementation. + */ +public class TestNativeArrayReader + extends ReaderArrayTestBase +{ + @Override + protected XMLStreamReader2 getReader(String contents) + throws XMLStreamException + { + XMLInputFactory f = getInputFactory(); + setCoalescing(f, false); // shouldn't really matter + setNamespaceAware(f, true); + return constructStreamReader(f, contents); + } +} + diff -Nru libwoodstox-java-4.1.3/src/test/java/stax2/typed/TestNativeBinaryReader.java libwoodstox-java-5.1.0/src/test/java/stax2/typed/TestNativeBinaryReader.java --- libwoodstox-java-4.1.3/src/test/java/stax2/typed/TestNativeBinaryReader.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/stax2/typed/TestNativeBinaryReader.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,24 @@ +package stax2.typed; + +import javax.xml.stream.*; + +import org.codehaus.stax2.XMLStreamReader2; + +/** + * Stax2 Typed Access API basic reader tests for binary content handling + * using native Stax2 typed reader implementation. + */ +public class TestNativeBinaryReader + extends ReaderBinaryTestBase +{ + @Override + protected XMLStreamReader2 getReader(String contents) + throws XMLStreamException + { + XMLInputFactory f = getInputFactory(); + setCoalescing(f, false); // shouldn't really matter + setNamespaceAware(f, true); + return constructStreamReader(f, contents); + } +} + diff -Nru libwoodstox-java-4.1.3/src/test/java/stax2/typed/TestNativeReader.java libwoodstox-java-5.1.0/src/test/java/stax2/typed/TestNativeReader.java --- libwoodstox-java-4.1.3/src/test/java/stax2/typed/TestNativeReader.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/stax2/typed/TestNativeReader.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,27 @@ +package stax2.typed; + +import javax.xml.stream.*; + +import org.codehaus.stax2.XMLStreamReader2; + +/** + * Stax2 Typed Access API basic reader tests, using native Stax2 + * typed reader implementation. + *

+ * Note: currently some functionality is only supported with native + * readers + */ +public class TestNativeReader + extends ReaderTestBase +{ + @Override + protected XMLStreamReader2 getReader(String contents) + throws XMLStreamException + { + XMLInputFactory f = getInputFactory(); + setCoalescing(f, false); // shouldn't really matter + setNamespaceAware(f, true); + return constructStreamReader(f, contents); + } +} + diff -Nru libwoodstox-java-4.1.3/src/test/java/stax2/typed/TestNativeWriter.java libwoodstox-java-5.1.0/src/test/java/stax2/typed/TestNativeWriter.java --- libwoodstox-java-4.1.3/src/test/java/stax2/typed/TestNativeWriter.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/stax2/typed/TestNativeWriter.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,37 @@ +package stax2.typed; + +import java.io.*; + +import javax.xml.stream.*; + +import org.codehaus.stax2.*; + +/** + * Stax2 Typed Access API basic reader tests, using native Stax2 + * typed writer implementation. + *

+ * Note: currently some functionality is only supported with native + * writers + */ +public class TestNativeWriter + extends WriterTestBase +{ + @Override + protected XMLStreamWriter2 getTypedWriter(ByteArrayOutputStream out, + boolean repairing) + throws XMLStreamException + { + out.reset(); + XMLOutputFactory outf = getOutputFactory(); + setRepairing(outf, repairing); + return (XMLStreamWriter2) outf.createXMLStreamWriter(out, "UTF-8"); + } + + @Override + protected byte[] closeWriter(XMLStreamWriter sw, ByteArrayOutputStream out) + throws XMLStreamException + { + sw.close(); + return out.toByteArray(); + } +} diff -Nru libwoodstox-java-4.1.3/src/test/java/stax2/typed/TestWrappedArrayReader.java libwoodstox-java-5.1.0/src/test/java/stax2/typed/TestWrappedArrayReader.java --- libwoodstox-java-4.1.3/src/test/java/stax2/typed/TestWrappedArrayReader.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/stax2/typed/TestWrappedArrayReader.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,43 @@ +package stax2.typed; + +import javax.xml.stream.*; + +import org.codehaus.stax2.XMLStreamReader2; +import org.codehaus.stax2.ri.Stax2ReaderAdapter; + +/** + * Stax2 Typed Access API basic reader tests for array handling, + * using native Stax2 typed reader implementation. + */ +public class TestWrappedArrayReader + extends ReaderArrayTestBase +{ + @Override + protected XMLStreamReader2 getReader(String contents) + throws XMLStreamException + { + XMLInputFactory f = getInputFactory(); + setCoalescing(f, false); // shouldn't really matter + setNamespaceAware(f, true); + + /* Twist: let's wrap, as if it was a regular stax1 reader; + * let's force wrapping via constructor + * (i.e. not call "wrapIfNecessary") + */ + return new MyAdapter(constructStreamReader(f, contents)); + } + + /** + * Need a dummy base class to be able to access protected + * constructor for testing purposes. + */ + final static class MyAdapter + extends Stax2ReaderAdapter + { + public MyAdapter(XMLStreamReader sr) + { + super(sr); + } + } +} + diff -Nru libwoodstox-java-4.1.3/src/test/java/stax2/typed/TestWrappedBinaryReader.java libwoodstox-java-5.1.0/src/test/java/stax2/typed/TestWrappedBinaryReader.java --- libwoodstox-java-4.1.3/src/test/java/stax2/typed/TestWrappedBinaryReader.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/stax2/typed/TestWrappedBinaryReader.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,43 @@ +package stax2.typed; + +import javax.xml.stream.*; + +import org.codehaus.stax2.XMLStreamReader2; +import org.codehaus.stax2.ri.Stax2ReaderAdapter; + +/** + * Stax2 Typed Access API basic reader tests for binary content handling + * using wrapped Stax2 typed reader implementation. + */ +public class TestWrappedBinaryReader + extends ReaderBinaryTestBase +{ + @Override + protected XMLStreamReader2 getReader(String contents) + throws XMLStreamException + { + XMLInputFactory f = getInputFactory(); + setCoalescing(f, false); // shouldn't really matter + setNamespaceAware(f, true); + + /* Twist: let's wrap, as if it was a regular stax1 reader; + * let's force wrapping via constructor + * (i.e. not call "wrapIfNecessary") + */ + return new MyAdapter(constructStreamReader(f, contents)); + } + + /** + * Need a dummy base class to be able to access protected + * constructor for testing purposes. + */ + final static class MyAdapter + extends Stax2ReaderAdapter + { + public MyAdapter(XMLStreamReader sr) + { + super(sr); + } + } +} + diff -Nru libwoodstox-java-4.1.3/src/test/java/stax2/typed/TestWrappedReader.java libwoodstox-java-5.1.0/src/test/java/stax2/typed/TestWrappedReader.java --- libwoodstox-java-4.1.3/src/test/java/stax2/typed/TestWrappedReader.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/stax2/typed/TestWrappedReader.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,50 @@ +package stax2.typed; + +import javax.xml.stream.*; + +import org.codehaus.stax2.XMLStreamReader2; + +/** + * Stax2 Typed Access API basic reader tests, using Stax2 adapter + * which implements Stax2 functionality non-natively, on top of + * any regular Stax 1.0 implementation. + */ +public class TestWrappedReader + extends ReaderTestBase +{ + @Override + protected XMLStreamReader2 getReader(String contents) + throws XMLStreamException + { + XMLInputFactory f = getInputFactory(); + setCoalescing(f, false); // shouldn't really matter + setNamespaceAware(f, true); + + /* Twist: let's wrap, as if it was a regular stax1 reader; + * let's force wrapping via constructor + * (i.e. not call "wrapIfNecessary") + */ + return wrapWithAdapter(constructStreamReader(f, contents)); + } + + /* + /////////////////////////////////////////////////////////////// + // Need to mask some tests, won't work with current wrapper + /////////////////////////////////////////////////////////////// + */ + + @Override + public void testInvalidQNameElemBadChars() + throws Exception + { + System.out.println("(skipping TestWrappedReader.testInvalidQNameElemBadChars)"); + } + + @Override + public void testInvalidQNameAttrBadChars() + { + System.out.println("(skipping TestWrappedReader.testInvalidQNameAttrBadChars)"); + } +} + + diff -Nru libwoodstox-java-4.1.3/src/test/java/stax2/typed/TestWrappedWriter.java libwoodstox-java-5.1.0/src/test/java/stax2/typed/TestWrappedWriter.java --- libwoodstox-java-4.1.3/src/test/java/stax2/typed/TestWrappedWriter.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/stax2/typed/TestWrappedWriter.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,55 @@ +package stax2.typed; + +import java.io.*; + +import javax.xml.stream.*; + +import org.codehaus.stax2.*; +import org.codehaus.stax2.ri.Stax2WriterAdapter; + +/** + * Stax2 Typed Access API basic reader tests, using Stax2 adapter + * which implements Stax2 functionality non-natively, on top of + * any regular Stax 1.0 implementation. + */ +public class TestWrappedWriter + extends WriterTestBase +{ + @Override + protected XMLStreamWriter2 getTypedWriter(ByteArrayOutputStream out, + boolean repairing) + throws XMLStreamException + { + out.reset(); + XMLOutputFactory outf = getOutputFactory(); + setRepairing(outf, repairing); + return new MyAdapter(outf.createXMLStreamWriter(out, "UTF-8")); + } + + @Override + protected byte[] closeWriter(XMLStreamWriter sw, ByteArrayOutputStream out) + throws XMLStreamException + { + sw.close(); + return out.toByteArray(); + } + + /* + //////////////////////////////////////// + // Helper class + //////////////////////////////////////// + */ + + /** + * Need a dummy base class to be able to access protected + * constructor for testing purposes. + */ + final static class MyAdapter + extends Stax2WriterAdapter + { + public MyAdapter(XMLStreamWriter sw) + { + super(sw); + } + } +} diff -Nru libwoodstox-java-4.1.3/src/test/java/stax2/typed/WriterTestBase.java libwoodstox-java-5.1.0/src/test/java/stax2/typed/WriterTestBase.java --- libwoodstox-java-4.1.3/src/test/java/stax2/typed/WriterTestBase.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/stax2/typed/WriterTestBase.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,1023 @@ +package stax2.typed; + +import java.io.*; +import java.math.BigDecimal; +import java.math.BigInteger; +import java.util.Random; +import java.util.StringTokenizer; + +import javax.xml.namespace.QName; +import javax.xml.stream.*; + +import org.codehaus.stax2.*; +import org.codehaus.stax2.typed.*; + +import stax2.BaseStax2Test; + +/** + * Base class that contains set of simple unit tests to verify implementation + * of {@link TypedXMLStreamWriter}. Concrete sub-classes are used to + * test both native and wrapped Stax2 implementations. + * + * @author Tatu Saloranta + */ +public abstract class WriterTestBase + extends BaseStax2Test +{ + final static int[] ARRAY_TEST_LENGTHS = new int[] { + 3, 8, 25, 120, 16, 99, 253, 1099, 2866, 37242 + }; + + /* + //////////////////////////////////////// + // Tests for numeric/enum types + //////////////////////////////////////// + */ + + public void testSimpleBooleanElem() + throws XMLStreamException + { + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + XMLStreamWriter2 w = getTypedWriter(bos); + writeBooleanElem(w, true); + byte[] data = closeWriter(w, bos); + checkBooleanElem(data, true); + + w = getTypedWriter(bos); + writeBooleanElem(w, false); + data = closeWriter(w, bos); + checkBooleanElem(data, false); + } + + public void testSimpleBooleanAttr() + throws XMLStreamException + { + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + XMLStreamWriter2 w = getTypedWriter(bos); + writeBooleanAttr(w, true); + byte[] data = closeWriter(w, bos); + checkBooleanAttr(data, true); + + w = getTypedWriter(bos); + writeBooleanAttr(w, false); + data = closeWriter(w, bos); + checkBooleanAttr(data, false); + } + + public void testMultipleBooleanAttr() + throws XMLStreamException + { + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + XMLStreamWriter2 w = getTypedWriter(bos); + + w.writeStartDocument(); + w.writeStartElement("root"); + + w.writeBooleanAttribute(null, null, "a1", true); + w.writeBooleanAttribute(null, null, "xyz", false); + w.writeBooleanAttribute(null, null, "_attr3", true); + + w.writeEndElement(); + w.writeEndDocument(); + + byte[] data = closeWriter(w, bos); + XMLStreamReader2 sr = getRootReader(data); + assertEquals(3, sr.getAttributeCount()); + int ix1 = sr.getAttributeIndex("", "a1"); + int ix2 = sr.getAttributeIndex("", "xyz"); + int ix3 = sr.getAttributeIndex("", "_attr3"); + if (ix1 < 0 || ix2 < 0 || ix3 < 0) { + fail("Couldn't find indexes of attributes: a1="+ix1+", xyz="+ix2+", _attr3="+ix3); + } + assertTrue(sr.getAttributeAsBoolean(ix1)); + assertFalse(sr.getAttributeAsBoolean(ix2)); + assertTrue(sr.getAttributeAsBoolean(ix3)); + + sr.close(); + } + + public void testSimpleIntElem() + throws XMLStreamException + { + int[] values = new int[] { + 0, 3, -9, 999, -77, 1000000000, -1000000000, + Integer.MIN_VALUE, Integer.MAX_VALUE + }; + for (int i = 0; i < values.length; ++i) { + int value = values[i]; + assertXML(""+value+"", writeIntElemDoc("root", value)); + } + } + + public void testSimpleIntAttr() + throws XMLStreamException + { + int[] values = new int[] { + 0, 3, -7, 123, -102, 1000000, -999999, + Integer.MIN_VALUE, Integer.MAX_VALUE + }; + for (int i = 0; i < values.length; ++i) { + int value = values[i]; + assertXML("", writeIntAttrDoc("a", "attr", value)); + } + } + + public void testMultipleIntAttr() + throws XMLStreamException + { + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + XMLStreamWriter2 w = getTypedWriter(bos); + + w.writeStartDocument(); + w.writeStartElement("root"); + + w.writeIntAttribute(null, null, "a", 0); + w.writeIntAttribute(null, null, "bz", Integer.MAX_VALUE); + w.writeIntAttribute(null, null, "___", -1200300400); + + w.writeEndElement(); + w.writeEndDocument(); + + byte[] data = closeWriter(w, bos); + XMLStreamReader2 sr = getRootReader(data); + assertEquals(3, sr.getAttributeCount()); + int ix1 = sr.getAttributeIndex("", "a"); + int ix2 = sr.getAttributeIndex("", "bz"); + int ix3 = sr.getAttributeIndex("", "___"); + if (ix1 < 0 || ix2 < 0 || ix3 < 0) { + fail("Couldn't find indexes of attributes: a="+ix1+", bz="+ix2+", ___="+ix3); + } + assertEquals(0, sr.getAttributeAsInt(ix1)); + assertEquals(Integer.MAX_VALUE, sr.getAttributeAsInt(ix2)); + assertEquals(-1200300400, sr.getAttributeAsInt(ix3)); + + sr.close(); + } + + public void testSimpleLongElem() + throws XMLStreamException + { + long[] values = new long[] { + 0, 3, -9, 999, -77, 1000000000, -1000000000, + 123456789012345678L, + -987654321098765423L, + Long.MIN_VALUE, Long.MAX_VALUE + }; + for (int i = 0; i < values.length; ++i) { + long value = values[i]; + assertXML(""+value+"", writeLongElemDoc("root", value)); + } + } + + public void testSimpleLongAttr() + throws XMLStreamException + { + long[] values = new long[] { + 0, 3, -9, 999, -77, 1000000002, -2000000004, + 123456789012345678L, + -987654321098765423L, + Long.MIN_VALUE, Long.MAX_VALUE + }; + for (int i = 0; i < values.length; ++i) { + long value = values[i]; + assertXML("", writeLongAttrDoc("a", "attr", value)); + } + } + + public void testMultipleLongAttr() + throws XMLStreamException + { + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + XMLStreamWriter2 w = getTypedWriter(bos); + + w.writeStartDocument(); + w.writeStartElement("root"); + + w.writeLongAttribute(null, null, "a", 0L); + w.writeLongAttribute(null, null, "bz", Long.MAX_VALUE); + w.writeLongAttribute(null, null, "___", -1200300400L); + + w.writeEndElement(); + w.writeEndDocument(); + + byte[] data = closeWriter(w, bos); + XMLStreamReader2 sr = getRootReader(data); + assertEquals(3, sr.getAttributeCount()); + int ix1 = sr.getAttributeIndex("", "a"); + int ix2 = sr.getAttributeIndex("", "bz"); + int ix3 = sr.getAttributeIndex("", "___"); + if (ix1 < 0 || ix2 < 0 || ix3 < 0) { + fail("Couldn't find indexes of attributes: a="+ix1+", bz="+ix2+", ___="+ix3); + } + assertEquals(0L, sr.getAttributeAsLong(ix1)); + assertEquals(Long.MAX_VALUE, sr.getAttributeAsLong(ix2)); + assertEquals(-1200300400L, sr.getAttributeAsLong(ix3)); + + sr.close(); + } + + public void testSimpleFloatElem() + throws XMLStreamException + { + float[] values = new float[] { + 0.0f, 10.47f, (float) (1.0 / 3.0), -0.25f, + Float.MIN_VALUE, Float.MAX_VALUE, + Float.NaN, Float.POSITIVE_INFINITY, Float.NEGATIVE_INFINITY + }; + for (int i = 0; i < values.length; ++i) { + float value = values[i]; + assertXML(""+value+"", writeFloatElemDoc("root", value)); + } + } + + public void testSimpleFloatAttr() + throws XMLStreamException + { + float[] values = new float[] { + 0.0f, 10.47f, (float) (1.0 / 3.0), -0.25f, + Float.MIN_VALUE, Float.MAX_VALUE, + Float.NaN, Float.POSITIVE_INFINITY, Float.NEGATIVE_INFINITY + }; + for (int i = 0; i < values.length; ++i) { + float value = values[i]; + assertXML("", writeFloatAttrDoc("a", "attr", value)); + } + } + + public void testSimpleDoubleElem() + throws XMLStreamException + { + double[] values = new double[] { + 0.0f, 10.47f, (1.0 / 3.0), -0.25f, + Double.MIN_VALUE, Double.MAX_VALUE, + Double.NaN, Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY + }; + for (int i = 0; i < values.length; ++i) { + double value = values[i]; + assertXML(""+value+"", writeDoubleElemDoc("root", value)); + } + } + + public void testSimpleDoubleAttr() + throws XMLStreamException + { + double[] values = new double[] { + 0.0f, 10.47f, (1.0 / 3.0), -0.25f, + Double.MIN_VALUE, Double.MAX_VALUE, + Double.NaN, Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY + }; + for (int i = 0; i < values.length; ++i) { + double value = values[i]; + assertXML("", writeDoubleAttrDoc("a", "attr", value)); + } + } + + public void testBigInteger() + throws XMLStreamException + { + BigInteger I = BigInteger.valueOf(3); + Random rnd = new Random(2); + for (int i = 1; i < 200; ++i) { + assertXML(""+I+"", writeIntegerElemDoc("root", I)); + assertXML("", writeIntegerAttrDoc("a", "attr", I)); + I = I.multiply(BigInteger.valueOf(10)).add(BigInteger.valueOf(rnd.nextInt() & 0xF)); + } + } + + public void testBigDecimal() + throws XMLStreamException + { + BigDecimal D = BigDecimal.valueOf(1L); + Random rnd = new Random(9); + for (int i = 1; i < 200; ++i) { + assertXML(""+D+"", writeDecimalElemDoc("root", D)); + assertXML("", writeDecimalAttrDoc("a", "attr", D)); + // Ok, then, add a small integer, divide by 10 to generate digits + D = D.add(BigDecimal.valueOf(rnd.nextInt() & 0xF)).divide(BigDecimal.valueOf(10L)); + } + } + + public void testQNameNonRepairing() + throws XMLStreamException + { + doTestQName(false); + } + + public void testQNameRepairing() + throws XMLStreamException + { + doTestQName(true); + } + + private void doTestQName(boolean repairing) + throws XMLStreamException + { + final String URI = "http://my.uri"; + QName n = new QName(URI, "elem", "ns"); + + assertXML("ns:elem", writeQNameElemDoc("root", n, repairing)); + assertXML("", + writeQNameAttrDoc("root", "attr", n, repairing)); + } + + public void testIntArraysElem() + throws XMLStreamException + { + doTestIntArrays(false); + } + + public void testIntArraysAttr() + throws XMLStreamException + { + doTestIntArrays(true); + } + + private void doTestIntArrays(boolean testAttr) + throws XMLStreamException + { + for (int i = 0; i <= ARRAY_TEST_LENGTHS.length; ++i) { + int[] data; + if (i == 0) { + data = new int[] { + 0, -139, 29, Integer.MAX_VALUE, 1, Integer.MIN_VALUE }; + } else { + Random rnd = new Random(9); + int len = ARRAY_TEST_LENGTHS[i-1]; + data = new int[len]; + for (int ix = 0; ix < len; ++ix) { + data[ix] = rnd.nextInt(); + } + } + String contents; + if (testAttr) { + contents = getAttributeContent(writeIntArrayAttrDoc("root", "attr", data)); + } else { + contents = getElementContent(writeIntArrayElemDoc("root", data)); + } + StringTokenizer st = new StringTokenizer(contents); + int count = 0; + while (st.hasMoreTokens()) { + String exp = String.valueOf(data[count]); + String act = st.nextToken(); + + if (!exp.equals(act)) { + fail("Incorrect entry #"+count+"/"+data.length+": act = '"+act+"' (exp '"+exp+"')"); + } + ++count; + } + assertEquals(data.length, count); + } + } + + public void testLongArraysElem() + throws XMLStreamException + { + doTestLongArrays(false); + } + + public void testLongArraysAttr() + throws XMLStreamException + { + doTestLongArrays(true); + } + + private void doTestLongArrays(boolean testAttr) + throws XMLStreamException + { + for (int i = 0; i <= ARRAY_TEST_LENGTHS.length; ++i) { + long[] data; + if (i == 0) { + data = new long[] { + 0, -139, 29, Long.MAX_VALUE, 1, Long.MIN_VALUE }; + } else { + Random rnd = new Random(9); + int len = ARRAY_TEST_LENGTHS[i-1]; + data = new long[len]; + for (int ix = 0; ix < len; ++ix) { + data[ix] = rnd.nextLong(); + } + } + String contents; + if (testAttr) { + contents = getAttributeContent(writeLongArrayAttrDoc("root", "attr", data)); + } else { + contents = getElementContent(writeLongArrayElemDoc("root", data)); + } + StringTokenizer st = new StringTokenizer(contents); + int count = 0; + while (st.hasMoreTokens()) { + String exp = String.valueOf(data[count]); + String act = st.nextToken(); + + if (!exp.equals(act)) { + fail("Incorrect entry #"+count+"/"+data.length+": act = '"+act+"' (exp '"+exp+"')"); + } + ++count; + } + assertEquals(data.length, count); + } + } + + public void testFloatArraysElem() + throws XMLStreamException + { + doTestFloatArrays(false); + } + + public void testFloatArraysAttr() + throws XMLStreamException + { + doTestFloatArrays(true); + } + + @SuppressWarnings("cast") + private void doTestFloatArrays(boolean testAttr) + throws XMLStreamException + { + for (int i = 0; i <= ARRAY_TEST_LENGTHS.length; ++i) { + float[] data; + if (i == 0) { + data = new float[] { + 0, -139, 29, Float.MAX_VALUE, 1, Float.MIN_VALUE }; + } else { + Random rnd = new Random(9); + int len = ARRAY_TEST_LENGTHS[i-1]; + data = new float[len]; + for (int ix = 0; ix < len; ++ix) { + // Need to scale: nextFloat is [0.0, 1.0[ + float value = rnd.nextFloat(); + if (rnd.nextBoolean()) { + value = (float) (value * rnd.nextInt()); + } + if (rnd.nextBoolean()) { + value = -value; + } + data[ix] = value; + } + } + String contents; + if (testAttr) { + contents = getAttributeContent(writeFloatArrayAttrDoc("root", "attr", data)); + } else { + contents = getElementContent(writeFloatArrayElemDoc("root", data)); + } + StringTokenizer st = new StringTokenizer(contents); + int count = 0; + while (st.hasMoreTokens()) { + String exp = String.valueOf(data[count]); + String act = st.nextToken(); + + if (!exp.equals(act)) { + fail("Incorrect entry #"+count+"/"+data.length+": act = '"+act+"' (exp '"+exp+"')"); + } + ++count; + } + assertEquals(data.length, count); + } + } + + public void testDoubleArraysElem() + throws XMLStreamException + { + doTestDoubleArrays(false); + } + + public void testDoubleArraysAttr() + throws XMLStreamException + { + doTestDoubleArrays(true); + } + + private void doTestDoubleArrays(boolean testAttr) + throws XMLStreamException + { + for (int i = 0; i <= ARRAY_TEST_LENGTHS.length; ++i) { + double[] data; + if (i == 0) { + data = new double[] { + 0, -139, 29, Double.MAX_VALUE, 1, Double.MIN_VALUE }; + } else { + Random rnd = new Random(9); + int len = ARRAY_TEST_LENGTHS[i-1]; + data = new double[len]; + for (int ix = 0; ix < len; ++ix) { + // Need to scale: nextDouble is [0.0, 1.0[ + double value = rnd.nextDouble(); + if (rnd.nextBoolean()) { + value = (value * rnd.nextLong()); + } + if (rnd.nextBoolean()) { + value = -value; + } + data[ix] = value; + } + } + String contents; + if (testAttr) { + contents = getAttributeContent(writeDoubleArrayAttrDoc("root", "attr", data)); + } else { + contents = getElementContent(writeDoubleArrayElemDoc("root", data)); + } + StringTokenizer st = new StringTokenizer(contents); + int count = 0; + while (st.hasMoreTokens()) { + String exp = String.valueOf(data[count]); + String act = st.nextToken(); + + if (!exp.equals(act)) { + fail("Incorrect entry #"+count+"/"+data.length+": act = '"+act+"' (exp '"+exp+"')"); + } + ++count; + } + assertEquals(data.length, count); + } + } + + /* + //////////////////////////////////////// + // Private methods, checking typed doc + //////////////////////////////////////// + */ + + private void checkBooleanElem(byte[] data, boolean expState) + throws XMLStreamException + { + XMLStreamReader2 sr = getRootReader(data); + assertEquals(expState, sr.getElementAsBoolean()); + sr.close(); + } + + private void checkBooleanAttr(byte[] data, boolean expState) + throws XMLStreamException + { + XMLStreamReader2 sr = getRootReader(data); + assertEquals(expState, sr.getAttributeAsBoolean(0)); + sr.close(); + } + + private void writeBooleanElem(TypedXMLStreamWriter sw, boolean b) + throws XMLStreamException + { + sw.writeStartDocument(); + sw.writeStartElement("root"); + sw.writeBoolean(b); + sw.writeEndElement(); + sw.writeEndDocument(); + } + + private void writeBooleanAttr(TypedXMLStreamWriter sw, boolean b) + throws XMLStreamException + { + sw.writeStartDocument(); + sw.writeStartElement("root"); + sw.writeBooleanAttribute(null, null, "attr", b); + sw.writeEndElement(); + sw.writeEndDocument(); + } + + private String writeIntElemDoc(String elem, int value) + throws XMLStreamException + { + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + XMLStreamWriter2 sw = getTypedWriter(bos); + // Let's not write start doc, to avoid getting xml declaration + //sw.writeStartDocument(); + sw.writeStartElement(elem); + sw.writeInt(value); + sw.writeEndElement(); + sw.writeEndDocument(); + return getUTF8(sw, bos); + } + + private String writeIntAttrDoc(String elem, String attr, int value) + throws XMLStreamException + { + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + XMLStreamWriter2 sw = getTypedWriter(bos); + // Let's not write start doc, to avoid getting xml declaration + //sw.writeStartDocument(); + sw.writeStartElement(elem); + sw.writeIntAttribute(null, null, attr, value); + sw.writeCharacters(""); // to avoid empty elem + sw.writeEndElement(); + sw.writeEndDocument(); + String str = getUTF8(sw, bos); + // One twist: need to ensure quotes are single-quotes (for the test) + return str.replace('"', '\''); + } + + private String writeLongElemDoc(String elem, long value) + throws XMLStreamException + { + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + XMLStreamWriter2 sw = getTypedWriter(bos); + // Let's not write start doc, to avoid getting xml declaration + //sw.writeStartDocument(); + sw.writeStartElement(elem); + sw.writeLong(value); + sw.writeEndElement(); + sw.writeEndDocument(); + return getUTF8(sw, bos); + } + + private String writeLongAttrDoc(String elem, String attr, long value) + throws XMLStreamException + { + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + XMLStreamWriter2 sw = getTypedWriter(bos); + // Let's not write start doc, to avoid getting xml declaration + //sw.writeStartDocument(); + sw.writeStartElement(elem); + sw.writeLongAttribute(null, null, attr, value); + sw.writeCharacters(""); // to avoid empty elem + sw.writeEndElement(); + sw.writeEndDocument(); + String str = getUTF8(sw, bos); + // One twist: need to ensure quotes are single-quotes (for the test) + return str.replace('"', '\''); + } + + private String writeFloatElemDoc(String elem, float value) + throws XMLStreamException + { + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + XMLStreamWriter2 sw = getTypedWriter(bos); + // Let's not write start doc, to avoid getting xml declaration + //sw.writeStartDocument(); + sw.writeStartElement(elem); + sw.writeFloat(value); + sw.writeEndElement(); + sw.writeEndDocument(); + return getUTF8(sw, bos); + } + + private String writeFloatAttrDoc(String elem, String attr, float value) + throws XMLStreamException + { + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + XMLStreamWriter2 sw = getTypedWriter(bos); + // Let's not write start doc, to avoid getting xml declaration + //sw.writeStartDocument(); + sw.writeStartElement(elem); + sw.writeFloatAttribute(null, null, attr, value); + sw.writeCharacters(""); // to avoid empty elem + sw.writeEndElement(); + sw.writeEndDocument(); + String str = getUTF8(sw, bos); + // One twist: need to ensure quotes are single-quotes (for the test) + return str.replace('"', '\''); + } + + private String writeDoubleElemDoc(String elem, double value) + throws XMLStreamException + { + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + XMLStreamWriter2 sw = getTypedWriter(bos); + sw.writeStartElement(elem); + sw.writeDouble(value); + sw.writeEndElement(); + sw.writeEndDocument(); + return getUTF8(sw, bos); + } + + private String writeDoubleAttrDoc(String elem, String attr, double value) + throws XMLStreamException + { + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + XMLStreamWriter2 sw = getTypedWriter(bos); + sw.writeStartElement(elem); + sw.writeDoubleAttribute(null, null, attr, value); + sw.writeCharacters(""); // to avoid empty elem + sw.writeEndElement(); + sw.writeEndDocument(); + String str = getUTF8(sw, bos); + // One twist: need to ensure quotes are single-quotes (for the test) + return str.replace('"', '\''); + } + + private String writeIntegerElemDoc(String elem, BigInteger value) + throws XMLStreamException + { + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + XMLStreamWriter2 sw = getTypedWriter(bos); + sw.writeStartElement(elem); + sw.writeInteger(value); + sw.writeEndElement(); + sw.writeEndDocument(); + return getUTF8(sw, bos); + } + + private String writeIntegerAttrDoc(String elem, String attr, BigInteger value) + throws XMLStreamException + { + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + XMLStreamWriter2 sw = getTypedWriter(bos); + sw.writeStartElement(elem); + sw.writeIntegerAttribute(null, null, attr, value); + sw.writeCharacters(""); // to avoid empty elem + sw.writeEndElement(); + sw.writeEndDocument(); + String str = getUTF8(sw, bos); + // One twist: need to ensure quotes are single-quotes (for the test) + return str.replace('"', '\''); + } + + private String writeDecimalElemDoc(String elem, BigDecimal value) + throws XMLStreamException + { + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + XMLStreamWriter2 sw = getTypedWriter(bos); + sw.writeStartElement(elem); + sw.writeDecimal(value); + sw.writeEndElement(); + sw.writeEndDocument(); + return getUTF8(sw, bos); + } + + private String writeDecimalAttrDoc(String elem, String attr, BigDecimal value) + throws XMLStreamException + { + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + XMLStreamWriter2 sw = getTypedWriter(bos); + sw.writeStartElement(elem); + sw.writeDecimalAttribute(null, null, attr, value); + sw.writeCharacters(""); // to avoid empty elem + sw.writeEndElement(); + sw.writeEndDocument(); + String str = getUTF8(sw, bos); + // One twist: need to ensure quotes are single-quotes (for the test) + return str.replace('"', '\''); + } + + private String writeQNameElemDoc(String elem, QName n, boolean repairing) + throws XMLStreamException + { + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + XMLStreamWriter2 sw = getTypedWriter(bos, repairing); + sw.writeStartElement(elem); + if (!repairing) { + sw.writeNamespace(n.getPrefix(), n.getNamespaceURI()); + } + sw.writeQName(n); + sw.writeEndElement(); + sw.writeEndDocument(); + String str = getUTF8(sw, bos); + return str.replace('"', '\''); + } + + private String writeQNameAttrDoc(String elem, String attr, QName n, boolean repairing) + throws XMLStreamException + { + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + XMLStreamWriter2 sw = getTypedWriter(bos, repairing); + sw.writeStartElement(elem); + if (!repairing) { + sw.writeNamespace(n.getPrefix(), n.getNamespaceURI()); + } + sw.writeQNameAttribute(null, null, attr, n); + sw.writeCharacters(""); // to avoid empty elem + sw.writeEndElement(); + sw.writeEndDocument(); + String str = getUTF8(sw, bos); + return str.replace('"', '\''); + } + + private byte[] writeIntArrayElemDoc(String elem, int[] values) + throws XMLStreamException + { + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + XMLStreamWriter2 sw = getTypedWriter(bos); + sw.writeStartElement(elem); + if ((values.length % 2) == 1) { // odd -> single write + sw.writeIntArray(values, 0, values.length); + } else { // even -> split in halves + int offset = values.length / 2; + sw.writeIntArray(values, 0, offset); + sw.writeIntArray(values, offset, values.length - offset); + } + sw.writeEndElement(); + sw.writeEndDocument(); + return closeWriter(sw, bos); + } + + private byte[] writeIntArrayAttrDoc(String elem, String attr, int[] values) + throws XMLStreamException + { + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + XMLStreamWriter2 sw = getTypedWriter(bos); + sw.writeStartElement(elem); + sw.writeIntArrayAttribute(null, null, attr, values); + sw.writeEndElement(); + sw.writeEndDocument(); + return closeWriter(sw, bos); + } + + private byte[] writeLongArrayElemDoc(String elem, long[] values) + throws XMLStreamException + { + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + XMLStreamWriter2 sw = getTypedWriter(bos); + sw.writeStartElement(elem); + if ((values.length % 2) == 1) { // odd -> single write + sw.writeLongArray(values, 0, values.length); + } else { // even -> split in halves + int offset = values.length / 2; + sw.writeLongArray(values, 0, offset); + sw.writeLongArray(values, offset, values.length - offset); + } + sw.writeEndElement(); + sw.writeEndDocument(); + return closeWriter(sw, bos); + } + + private byte[] writeLongArrayAttrDoc(String elem, String attr, long[] values) + throws XMLStreamException + { + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + XMLStreamWriter2 sw = getTypedWriter(bos); + sw.writeStartElement(elem); + sw.writeLongArrayAttribute(null, null, attr, values); + sw.writeEndElement(); + sw.writeEndDocument(); + return closeWriter(sw, bos); + } + + private byte[] writeFloatArrayElemDoc(String elem, float[] values) + throws XMLStreamException + { + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + XMLStreamWriter2 sw = getTypedWriter(bos); + sw.writeStartElement(elem); + if ((values.length % 2) == 1) { // odd -> single write + sw.writeFloatArray(values, 0, values.length); + } else { // even -> split in halves + int offset = values.length / 2; + sw.writeFloatArray(values, 0, offset); + sw.writeFloatArray(values, offset, values.length - offset); + } + sw.writeEndElement(); + sw.writeEndDocument(); + return closeWriter(sw, bos); + } + + private byte[] writeFloatArrayAttrDoc(String elem, String attr, float[] values) + throws XMLStreamException + { + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + XMLStreamWriter2 sw = getTypedWriter(bos); + sw.writeStartElement(elem); + sw.writeFloatArrayAttribute(null, null, attr, values); + sw.writeEndElement(); + sw.writeEndDocument(); + return closeWriter(sw, bos); + } + + private byte[] writeDoubleArrayElemDoc(String elem, double[] values) + throws XMLStreamException + { + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + XMLStreamWriter2 sw = getTypedWriter(bos); + sw.writeStartElement(elem); + if ((values.length % 2) == 1) { // odd -> single write + sw.writeDoubleArray(values, 0, values.length); + } else { // even -> split in halves + int offset = values.length / 2; + sw.writeDoubleArray(values, 0, offset); + sw.writeDoubleArray(values, offset, values.length - offset); + } + sw.writeEndElement(); + sw.writeEndDocument(); + return closeWriter(sw, bos); + } + + private byte[] writeDoubleArrayAttrDoc(String elem, String attr, double[] values) + throws XMLStreamException + { + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + XMLStreamWriter2 sw = getTypedWriter(bos); + sw.writeStartElement(elem); + sw.writeDoubleArrayAttribute(null, null, attr, values); + sw.writeEndElement(); + sw.writeEndDocument(); + return closeWriter(sw, bos); + } + + /* + //////////////////////////////////////// + // Abstract methods + //////////////////////////////////////// + */ + + protected abstract XMLStreamWriter2 getTypedWriter(ByteArrayOutputStream out, + boolean repairing) + throws XMLStreamException; + + protected abstract byte[] closeWriter(XMLStreamWriter sw, ByteArrayOutputStream out) + throws XMLStreamException; + + /* + //////////////////////////////////////// + // Private methods, constructing writers + //////////////////////////////////////// + */ + + private XMLStreamWriter2 getTypedWriter(ByteArrayOutputStream out) + throws XMLStreamException + { + return getTypedWriter(out, false); + } + + // XMLStreamReader2 extends TypedXMLStreamReader + private XMLStreamReader2 getRootReader(byte[] data) + throws XMLStreamException + { + XMLStreamReader2 sr = getReader(data); + assertTokenType(START_DOCUMENT, sr.getEventType()); + while (sr.next() != START_ELEMENT) { } + assertTokenType(START_ELEMENT, sr.getEventType()); + return sr; + } + + private XMLStreamReader2 getReader(byte[] data) + throws XMLStreamException + { + XMLInputFactory f = getInputFactory(); + setCoalescing(f, false); // shouldn't really matter + setNamespaceAware(f, true); + return (XMLStreamReader2) f.createXMLStreamReader(new ByteArrayInputStream(data)); + } + + private String getUTF8(XMLStreamWriter sw, ByteArrayOutputStream bos) + throws XMLStreamException + { + byte[] data = closeWriter(sw, bos); + try { + return new String(data, "UTF-8"); + } catch (IOException ioe) { + throw new IllegalArgumentException(ioe); + } + } + + private String getElementContent(byte[] data) + throws XMLStreamException + { + XMLStreamReader sr = getReader(data); + assertTokenType(START_DOCUMENT, sr.getEventType()); + while (sr.next() != START_ELEMENT) { } + assertTokenType(START_ELEMENT, sr.getEventType()); + String content = sr.getElementText(); + sr.close(); + return content; + } + + private String getAttributeContent(byte[] data) + throws XMLStreamException + { + XMLStreamReader sr = getReader(data); + assertTokenType(START_DOCUMENT, sr.getEventType()); + while (sr.next() != START_ELEMENT) { } + assertTokenType(START_ELEMENT, sr.getEventType()); + assertEquals(1, sr.getAttributeCount()); + String content = sr.getAttributeValue(0); + sr.close(); + return content; + } + + /** + * Helper method to contain modifications we may need to + * reliably compare equivalency of result xml to expected + * results. + */ + void assertXML(String exp, String act) + { + // First: let's trim out xml decl, if any + act = act.trim(); + if (act.startsWith(""); + act = act.substring(ix+2); + } + // Usually this is enough: + if (exp.equals(act)) { + return; + } + /* If not, let's see if we can still find them equal; + * given simplicity of docs, we only need to be concerned + * with '' -> '' change it seems. Expected + * results seem to only differ by that much, for now... + */ + int ix = act.indexOf("/>"); + if (ix > 0) { + // ugh. this is ugly, yes... if it breaks, should just rewrite completely + String prefix = act.substring(0, ix).trim(); + String suffix = act.substring(ix+2); // probably empty tho + + ix = prefix.lastIndexOf("<"); + int ix2 = prefix.indexOf(' ', ix); + // If it was just name it'd be simpler, but there may be attr(s) + String name = (ix2 < 0) ? prefix.substring(ix+1) : prefix.substring(ix+1, ix2); + + act = prefix + ">"+suffix; + } + assertEquals(exp, act); + } +} diff -Nru libwoodstox-java-4.1.3/src/test/java/stax2/vwstream/BaseOutputTest.java libwoodstox-java-5.1.0/src/test/java/stax2/vwstream/BaseOutputTest.java --- libwoodstox-java-4.1.3/src/test/java/stax2/vwstream/BaseOutputTest.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/stax2/vwstream/BaseOutputTest.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,49 @@ +package stax2.vwstream; + +import java.io.*; +import javax.xml.stream.*; + +import org.codehaus.stax2.*; +import org.codehaus.stax2.validation.*; + +import stax2.BaseStax2Test; + +abstract class BaseOutputTest + extends BaseStax2Test +{ + public XMLStreamWriter2 getDTDValidatingWriter(Writer w, String dtdSrc, + boolean nsAware, boolean repairing) + throws XMLStreamException + { + XMLOutputFactory2 outf = getOutputFactory(); + outf.setProperty(XMLStreamProperties.XSP_NAMESPACE_AWARE, new Boolean(nsAware)); + outf.setProperty(XMLOutputFactory.IS_REPAIRING_NAMESPACES, new Boolean(repairing)); + + XMLStreamWriter2 strw = (XMLStreamWriter2)outf.createXMLStreamWriter(w); + XMLValidationSchemaFactory vd = XMLValidationSchemaFactory.newInstance(XMLValidationSchema.SCHEMA_ID_DTD); + + XMLValidationSchema schema = vd.createSchema(new StringReader(dtdSrc)); + + strw.validateAgainst(schema); + strw.writeStartDocument(); + return strw; + } + + public XMLStreamWriter2 getSchemaValidatingWriter(Writer w, String schemaSrc, + boolean repairing) + throws XMLStreamException + { + XMLOutputFactory2 outf = getOutputFactory(); + outf.setProperty(XMLStreamProperties.XSP_NAMESPACE_AWARE, true); + outf.setProperty(XMLOutputFactory.IS_REPAIRING_NAMESPACES, new Boolean(repairing)); + + XMLStreamWriter2 strw = (XMLStreamWriter2)outf.createXMLStreamWriter(w); + XMLValidationSchemaFactory vd = XMLValidationSchemaFactory.newInstance(XMLValidationSchema.SCHEMA_ID_W3C_SCHEMA); + + XMLValidationSchema schema = vd.createSchema(new StringReader(schemaSrc)); + + strw.validateAgainst(schema); + strw.writeStartDocument(); + return strw; + } +} diff -Nru libwoodstox-java-4.1.3/src/test/java/stax2/vwstream/TestAttributeValidation.java libwoodstox-java-5.1.0/src/test/java/stax2/vwstream/TestAttributeValidation.java --- libwoodstox-java-4.1.3/src/test/java/stax2/vwstream/TestAttributeValidation.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/stax2/vwstream/TestAttributeValidation.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,255 @@ +package stax2.vwstream; + +import java.io.*; + +import javax.xml.stream.*; + +import org.codehaus.stax2.XMLStreamWriter2; +import org.codehaus.stax2.validation.*; + +/** + * Unit tests for testing handling of attribute value validation, mostly + * focusing on default value modifiers (#FIXED, #REQUIRED). + * Validation for specific types are in type-specific additional tests. + */ +public class TestAttributeValidation + extends BaseOutputTest +{ + final String NS_PREFIX = "ns"; + final String NS_PREFIX2 = "ns2"; + final String NS_URI = "http://ns"; + + final String FIXED_DTD_STR = "\n" + +"\n"; + final String REQUIRED_DTD_STR = "\n" + +"\n"; + final String IMPLIED_NS_DTD_STR = "\n" + +"\n"; + + public void testValidFixedAttr() + throws XMLStreamException + { + for (int i = 0; i < 3; ++i) { + boolean nsAware = (i >= 1); + boolean repairing = (i == 2); + StringWriter strw = new StringWriter(); + + // Ok either without being added: + XMLStreamWriter2 sw = getDTDValidatingWriter(strw, FIXED_DTD_STR, nsAware, repairing); + sw.writeStartElement("root"); + sw.writeEndElement(); + sw.writeEndDocument(); + sw.close(); + + sw = getDTDValidatingWriter(strw, FIXED_DTD_STR, nsAware, repairing); + sw.writeEmptyElement("root"); + sw.writeEndDocument(); + sw.close(); + + // or by using the exact same value + sw = getDTDValidatingWriter(strw, FIXED_DTD_STR, nsAware, repairing); + sw.writeStartElement("root"); + sw.writeAttribute("fixAttr", "fixedValue"); + sw.writeEndElement(); + sw.writeEndDocument(); + sw.close(); + } + } + + public void testInvalidFixedAttr() + throws XMLStreamException + { + for (int i = 0; i < 3; ++i) { + boolean nsAware, repairing; + String modeDesc; + + switch (i) { + case 0: + modeDesc = "[non-namespace-aware]"; + nsAware = repairing = false; + break; + case 1: + modeDesc = "[namespace-aware, non-repairing]"; + nsAware = true; + repairing = false; + break; + default: + modeDesc = "[namespace-aware, repairing]"; + nsAware = repairing = true; + break; + } + + // Invalid case, trying to add some other value: + + // non-empty but not same + StringWriter strw = new StringWriter(); + XMLStreamWriter2 sw = getDTDValidatingWriter(strw, FIXED_DTD_STR, nsAware, repairing); + sw.writeStartElement("root"); + try { + sw.writeAttribute("fixAttr", "otherValue"); + fail(modeDesc+" Expected a validation exception when trying to add a #FIXED attribute with 'wrong' value"); + } catch (XMLValidationException vex) { + // expected... + } + // Should not close, since stream is invalid now... + + // empty is not the same as leaving it out: + strw = new StringWriter(); + sw = getDTDValidatingWriter(strw, FIXED_DTD_STR, nsAware, repairing); + sw.writeStartElement("root"); + try { + sw.writeAttribute("fixAttr", ""); + fail(modeDesc+" Expected a validation exception when trying to add a #FIXED attribute with an empty value"); + } catch (XMLValidationException vex) { + // expected... + } + + // And finally, same for empty elem in case impl. is different + strw = new StringWriter(); + sw = getDTDValidatingWriter(strw, FIXED_DTD_STR, nsAware, repairing); + sw.writeEmptyElement("root"); + try { + sw.writeAttribute("fixAttr", "foobar"); + fail(modeDesc+" Expected a validation exception when trying to add a #FIXED attribute with an empty value"); + } catch (XMLValidationException vex) { + // expected... + } + } + } + + public void testValidRequiredAttr() + throws XMLStreamException + { + for (int i = 0; i < 3; ++i) { + boolean nsAware = (i >= 1); + boolean repairing = (i == 2); + StringWriter strw = new StringWriter(); + + // Ok if value is added: + XMLStreamWriter2 sw = getDTDValidatingWriter(strw, REQUIRED_DTD_STR, nsAware, repairing); + sw.writeStartElement("root"); + sw.writeAttribute("reqAttr", "value"); + sw.writeEndElement(); + sw.writeEndDocument(); + sw.close(); + + // ... even if with empty value (for CDATA type, at least) + sw = getDTDValidatingWriter(strw, REQUIRED_DTD_STR, nsAware, repairing); + sw.writeStartElement("root"); + sw.writeAttribute("reqAttr", ""); + sw.writeEndElement(); + sw.writeEndDocument(); + sw.close(); + + // and ditto for empty element: + sw = getDTDValidatingWriter(strw, REQUIRED_DTD_STR, nsAware, repairing); + sw.writeEmptyElement("root"); + sw.writeAttribute("reqAttr", "hii & haa"); + sw.writeEndDocument(); + sw.close(); + } + } + + public void testInvalidRequiredAttr() + throws XMLStreamException + { + for (int i = 0; i < 3; ++i) { + boolean nsAware, repairing; + String modeDesc; + + switch (i) { + case 0: + modeDesc = "[non-namespace-aware]"; + nsAware = repairing = false; + break; + case 1: + modeDesc = "[namespace-aware, non-repairing]"; + nsAware = true; + repairing = false; + break; + default: + modeDesc = "[namespace-aware, repairing]"; + nsAware = repairing = true; + break; + } + + // Invalid case: leaving the required attr out: + StringWriter strw = new StringWriter(); + XMLStreamWriter2 sw = getDTDValidatingWriter(strw, REQUIRED_DTD_STR, nsAware, repairing); + sw.writeStartElement("root"); + try { + sw.writeEndElement(); + fail(modeDesc+" Expected a validation exception when omitting a #REQUIRED attribute"); + } catch (XMLValidationException vex) { + // expected... + } + // Should not close, since stream is invalid now... + } + } + + /** + * Test to ensure that the namespace-prefix mapping works (to the degree + * it can... wrt dtd-non-ns-awareness) with attributes. + */ + public void testValidNsAttr() + throws XMLStreamException + { + for (int i = 0; i < 2; ++i) { + boolean repairing = (i > 0); + StringWriter strw = new StringWriter(); + + /* Ok, as long as we use the right ns prefix... better also + * output namespace declaration, in non-repairing mode. + */ + XMLStreamWriter2 sw = getDTDValidatingWriter(strw, IMPLIED_NS_DTD_STR, true, repairing); + sw.writeStartElement("root"); + if (!repairing) { + sw.writeNamespace(NS_PREFIX, NS_URI); + } + // prefix, uri, localname (for attrs!) + sw.writeAttribute(NS_PREFIX, NS_URI, "attr", "value"); + sw.writeEndElement(); + sw.writeEndDocument(); + sw.close(); + } + } + + public void testInvalidNsAttr() + throws XMLStreamException + { + for (int i = 0; i < 2; ++i) { + boolean repairing; + String modeDesc; + + switch (i) { + case 0: + modeDesc = "[namespace-aware, non-repairing]"; + repairing = false; + break; + default: + modeDesc = "[namespace-aware, repairing]"; + repairing = true; + break; + } + + // Invalid case, trying to use "wrong" prefix: + + StringWriter strw = new StringWriter(); + XMLStreamWriter2 sw = getDTDValidatingWriter(strw, IMPLIED_NS_DTD_STR, true, repairing); + sw.writeStartElement("root"); + if (!repairing) { + sw.writeNamespace(NS_PREFIX, NS_URI); + } + // prefix, uri, localname (for attrs!) + try { + sw.writeAttribute(NS_PREFIX2, NS_URI, "attr", "value"); + fail(modeDesc+" Expected a validation exception when trying to add an attribute with wrong ns prefix"); + } catch (XMLValidationException vex) { + // expected... + } + // Should not close, since stream is invalid now... + } + } + +} + diff -Nru libwoodstox-java-4.1.3/src/test/java/stax2/vwstream/TestOutputValidation.java libwoodstox-java-5.1.0/src/test/java/stax2/vwstream/TestOutputValidation.java --- libwoodstox-java-4.1.3/src/test/java/stax2/vwstream/TestOutputValidation.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/stax2/vwstream/TestOutputValidation.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,320 @@ +package stax2.vwstream; + +import java.io.*; + +import javax.xml.stream.*; + +import org.codehaus.stax2.XMLStreamWriter2; +import org.codehaus.stax2.validation.*; + +/** + * Unit test suite that test basic aspects of (DTD validation, + * mostly regarding specialized content types (EMPTY, ANY, #PCDATA) + * + */ +public class TestOutputValidation + extends BaseOutputTest +{ + public void testValidMixedContent() + throws XMLStreamException + { + final String dtdStr = + "\n" + +"\n" + ; + + for (int i = 0; i < 3; ++i) { + boolean nsAware = (i >= 1); + boolean repairing = (i == 2); + StringWriter strw = new StringWriter(); + XMLStreamWriter2 sw = getDTDValidatingWriter(strw, dtdStr, nsAware, repairing); + sw.writeStartElement("root"); + // Should be fine now + sw.writeCharacters("Text that should be ok"); + sw.writeStartElement("branch"); + // Also, all-whitespace is ok in non-mixed too + sw.writeCharacters("\t \t \r \n"); + sw.writeEndElement(); + sw.writeEndElement(); + sw.writeEndDocument(); + } + } + + public void testInvalidMixedContent() + throws XMLStreamException + { + final String dtdStr = + "\n" + +"\n" + ; + + for (int i = 0; i < 3; ++i) { + boolean nsAware = (i >= 1); + boolean repairing = (i == 2); + StringWriter strw = new StringWriter(); + XMLStreamWriter2 sw = getDTDValidatingWriter(strw, dtdStr, nsAware, repairing); + sw.writeStartElement("root"); + // Should get validation exception here: + try { + sw.writeCharacters("Illegal text!"); + fail("Expected a validation exception for non-whitespace text output on non-mixed element content"); + } catch (XMLValidationException vex) { + // expected... + } + } + } + + public void testValidEmptyContent() + throws XMLStreamException + { + final String dtdStr = "\n" + +"\n"; + + for (int i = 0; i < 3; ++i) { + boolean nsAware = (i >= 1); + boolean repairing = (i == 2); + StringWriter strw = new StringWriter(); + + XMLStreamWriter2 sw = getDTDValidatingWriter(strw, dtdStr, nsAware, repairing); + + sw.writeStartElement("root"); + // No content whatsoever is allowed... + sw.writeEndElement(); + sw.writeEndDocument(); + sw.close(); + + // Next; same but with an attribute + sw = getDTDValidatingWriter(strw, dtdStr, nsAware, repairing); + + sw.writeStartElement("root"); + // no content, but attribute is fine + sw.writeAttribute("attr", "value"); + + sw.writeEndElement(); + sw.writeEndDocument(); + sw.close(); + + // And then using empty element write method(s) + sw = getDTDValidatingWriter(strw, dtdStr, nsAware, repairing); + sw.writeEmptyElement("root"); + // note: empty element need/can not be closed + sw.writeEndDocument(); + sw.close(); + + // and finally empty with attribute + sw = getDTDValidatingWriter(strw, dtdStr, nsAware, repairing); + sw.writeEmptyElement("root"); + sw.writeAttribute("attr", "otherValue"); + sw.writeEndDocument(); + sw.close(); + } + } + + public void testInvalidEmptyContent() + throws XMLStreamException + { + final String dtdStr = "\n" + +"\n" + +"\n" + ; + + for (int i = 0; i < 3; ++i) { + boolean nsAware, repairing; + String modeDesc; + + switch (i) { + case 0: + modeDesc = "[non-namespace-aware]"; + nsAware = repairing = false; + break; + case 1: + modeDesc = "[namespace-aware, non-repairing]"; + nsAware = true; + repairing = false; + break; + default: + modeDesc = "[namespace-aware, repairing]"; + nsAware = repairing = true; + break; + } + + StringWriter strw = new StringWriter(); + + // No content whatsoever is allowed with EMPTY. + // Let's first test with a regualr child element: + + XMLStreamWriter2 sw = getDTDValidatingWriter(strw, dtdStr, nsAware, repairing); + sw.writeStartElement("root"); + try { + sw.writeStartElement("leaf"); + fail(modeDesc+" Expected a validation exception when trying to add an element into EMPTY content model"); + } catch (XMLValidationException vex) { + // expected... + } + sw.close(); + + // Then with an empty child + sw = getDTDValidatingWriter(strw, dtdStr, nsAware, repairing); + sw.writeStartElement("root"); + try { + sw.writeEmptyElement("leaf"); + fail(modeDesc+" Expected a validation exception when trying to add an element into EMPTY content model"); + } catch (XMLValidationException vex) { + // expected... + } + sw.close(); + + // Then with any text (even just white space): + sw = getDTDValidatingWriter(strw, dtdStr, nsAware, repairing); + sw.writeStartElement("root"); + try { + sw.writeCharacters(" "); + fail(modeDesc+" Expected a validation exception when trying to any text into EMPTY content model"); + } catch (XMLValidationException vex) { } + sw.close(); + + // Then CDATA + sw = getDTDValidatingWriter(strw, dtdStr, nsAware, repairing); + sw.writeStartElement("root"); + try { + sw.writeCData("foo"); + fail(modeDesc+" Expected a validation exception when trying to add CDATA into EMPTY content model"); + } catch (XMLValidationException vex) { } + sw.close(); + + // Then ENTITY + sw = getDTDValidatingWriter(strw, dtdStr, nsAware, repairing); + sw.writeStartElement("root"); + try { + sw.writeEntityRef("amp"); + fail(modeDesc+" Expected a validation exception when trying to add CDATA into EMPTY content model"); + } catch (XMLValidationException vex) { } + sw.close(); + + // Then comment + sw = getDTDValidatingWriter(strw, dtdStr, nsAware, repairing); + sw.writeStartElement("root"); + try { + sw.writeComment("comment"); + fail(modeDesc+" Expected a validation exception when trying to add comment into EMPTY content model"); + } catch (XMLValidationException vex) { } + sw.close(); + + // Then proc. instr. + sw = getDTDValidatingWriter(strw, dtdStr, nsAware, repairing); + sw.writeStartElement("root"); + try { + sw.writeProcessingInstruction("target", "data"); + fail(modeDesc+" Expected a validation exception when trying to add processing instruction into EMPTY content model"); + } catch (XMLValidationException vex) { } + sw.close(); + } + } + + public void testValidAnyContent() + throws XMLStreamException + { + final String dtdStr = "\n" + +"\n" + +"\n" + ; + + for (int i = 0; i < 3; ++i) { + boolean nsAware = (i >= 1); + boolean repairing = (i == 2); + StringWriter strw = new StringWriter(); + + // First simplest case + XMLStreamWriter2 sw = getDTDValidatingWriter(strw, dtdStr, nsAware, repairing); + sw.writeStartElement("root"); + sw.writeStartElement("leaf"); + sw.writeCharacters("whatever"); + sw.writeEndElement(); + sw.writeEndElement(); + sw.writeEndDocument(); + sw.close(); + + // Then one with no content + sw = getDTDValidatingWriter(strw, dtdStr, nsAware, repairing); + sw.writeStartElement("root"); + sw.writeEndElement(); + sw.writeEndDocument(); + sw.close(); + + // Then one with explicitly empty elem + sw = getDTDValidatingWriter(strw, dtdStr, nsAware, repairing); + sw.writeStartElement("root"); + sw.writeEmptyElement("leaf"); + sw.writeEndElement(); + sw.writeEndDocument(); + sw.close(); + + // Then one with an attribute + sw = getDTDValidatingWriter(strw, dtdStr, nsAware, repairing); + sw.writeStartElement("root"); + sw.writeAttribute("attr", "value"); + sw.writeStartElement("leaf"); + sw.writeEndElement(); + sw.writeEndElement(); + sw.writeEndDocument(); + sw.close(); + } + } + + public void testInvalidAnyContent() + throws XMLStreamException + { + final String dtdStr = "\n" + +"\n" + +"\n"; + + for (int i = 0; i < 3; ++i) { + boolean nsAware, repairing; + String modeDesc; + + switch (i) { + case 0: + modeDesc = "[non-namespace-aware]"; + nsAware = repairing = false; + break; + case 1: + modeDesc = "[namespace-aware, non-repairing]"; + nsAware = true; + repairing = false; + break; + default: + modeDesc = "[namespace-aware, repairing]"; + nsAware = repairing = true; + break; + } + + StringWriter strw = new StringWriter(); + + XMLStreamWriter2 sw = getDTDValidatingWriter(strw, dtdStr, nsAware, repairing); + + /* The only obviously invalid cases are using non-declared + * elements or attributes... so let's test them here (these + * may be redundant to some degree) + */ + sw.writeStartElement("root"); + try { + sw.writeStartElement("unknown"); + fail(modeDesc+" Expected a validation exception when trying to add an undeclared element"); + } catch (XMLValidationException vex) { + // expected... + } + sw.close(); + + // undecl attr: + sw = getDTDValidatingWriter(strw, dtdStr, nsAware, repairing); + sw.writeStartElement("root"); + try { + sw.writeAttribute("unknown", "value"); + fail(modeDesc+" Expected a validation exception when trying to add an undeclared attribute"); + } catch (XMLValidationException vex) { + // expected... + } + sw.close(); + } + } +} diff -Nru libwoodstox-java-4.1.3/src/test/java/stax2/vwstream/TestStructuralValidation.java libwoodstox-java-5.1.0/src/test/java/stax2/vwstream/TestStructuralValidation.java --- libwoodstox-java-4.1.3/src/test/java/stax2/vwstream/TestStructuralValidation.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/stax2/vwstream/TestStructuralValidation.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,263 @@ +package stax2.vwstream; + +import java.io.*; + +import javax.xml.stream.*; + +import org.codehaus.stax2.XMLStreamWriter2; +import org.codehaus.stax2.validation.*; + +/** + * Unit tests for testing structural validation (except for test for + * special content types like EMPTY and ANY). + */ +public class TestStructuralValidation + extends BaseOutputTest +{ + final String NS_PREFIX = "ns"; + final String NS_PREFIX2 = "ns2"; + final String NS_URI = "http://ns"; + + final String SIMPLE_DTD = + "\n" + +"\n" + +"\n" + +"\n" + ; + + final String SIMPLE_NS_DTD = + "\n" + +"\n" + ; + + public void testInvalidRootElem() + throws XMLStreamException + { + for (int i = 0; i < 3; ++i) { + boolean nsAware, repairing; + String modeDesc; + + switch (i) { + case 0: + modeDesc = "[non-namespace-aware]"; + nsAware = repairing = false; + break; + case 1: + modeDesc = "[namespace-aware, non-repairing]"; + nsAware = true; + repairing = false; + break; + default: + modeDesc = "[namespace-aware, repairing]"; + nsAware = repairing = true; + break; + } + + StringWriter strw = new StringWriter(); + + /* Ok; can test for "wrong" root element only if we explicitly + * output DOCTYPE declaration with specific name... + */ + XMLStreamWriter2 sw = getDTDValidatingWriter(strw, SIMPLE_DTD, nsAware, repairing); + sw.writeDTD("root", "http://foo", "public-id", SIMPLE_DTD); + try { + sw.writeStartElement("branch"); + fail(modeDesc+" Expected a validation exception when trying to write wrong root element"); + } catch (XMLValidationException vex) { + // expected... + } + // should not continue after exception; state may not be valid + + // And then undeclared root: + sw = getDTDValidatingWriter(strw, SIMPLE_DTD, nsAware, repairing); + try { + sw.writeStartElement("undefined"); + fail(modeDesc+" Expected a validation exception when trying to write an undefined root element"); + } catch (XMLValidationException vex) { + // expected... + } + + // and same for explicitly empty element; wrong root + sw = getDTDValidatingWriter(strw, SIMPLE_DTD, nsAware, repairing); + sw.writeDTD("root", "http://foo", "public-id", SIMPLE_DTD); + try { + sw.writeEmptyElement("branch"); + fail(modeDesc+" Expected a validation exception when trying to write wrong root element"); + } catch (XMLValidationException vex) { + // expected... + } + } + } + + public void testValidStructure() + throws XMLStreamException + { + for (int i = 0; i < 3; ++i) { + boolean nsAware = (i >= 1); + boolean repairing = (i == 2); + + StringWriter strw = new StringWriter(); + XMLStreamWriter2 sw = getDTDValidatingWriter(strw, SIMPLE_DTD, nsAware, repairing); + sw.writeStartElement("root"); + sw.writeCharacters(" "); // imitating indentation + sw.writeStartElement("branch"); + sw.writeEndElement(); + sw.writeStartElement("branch"); + sw.writeCharacters("test"); + sw.writeComment("comment"); + sw.writeEndElement(); + sw.writeEmptyElement("branch"); + sw.writeEmptyElement("end"); + sw.writeAttribute("endAttr", "value"); + sw.writeCharacters("\n"); // imitating indentation + sw.writeEndElement(); // for root + } + } + + public void testInvalidStructure() + throws XMLStreamException + { + for (int i = 0; i < 3; ++i) { + boolean nsAware, repairing; + String modeDesc; + + switch (i) { + case 0: + modeDesc = "[non-namespace-aware]"; + nsAware = repairing = false; + break; + case 1: + modeDesc = "[namespace-aware, non-repairing]"; + nsAware = true; + repairing = false; + break; + default: + modeDesc = "[namespace-aware, repairing]"; + nsAware = repairing = true; + break; + } + + StringWriter strw = new StringWriter(); + + // Let's try omitting the end element, first... + + XMLStreamWriter2 sw = getDTDValidatingWriter(strw, SIMPLE_DTD, nsAware, repairing); + sw.writeStartElement("root"); + sw.writeCharacters(" "); // imitating indentation + sw.writeStartElement("branch"); + sw.writeEndElement(); + sw.writeStartElement("branch"); + sw.writeCharacters("test"); + sw.writeComment("comment"); + sw.writeEndElement(); + sw.writeEmptyElement("branch"); + sw.writeCharacters("\n"); // imitating indentation + try { + sw.writeEndElement(); // for root + fail(modeDesc+" Expected a validation exception when omitting non-optional element"); + } catch (XMLValidationException vex) { + // expected... + } + // should not continue after exception; state may not be valid + + // And then leaving out branch... + sw = getDTDValidatingWriter(strw, SIMPLE_DTD, nsAware, repairing); + sw.writeStartElement("root"); + sw.writeCharacters(" "); // imitating indentation + sw.writeComment("comment"); + try { + sw.writeEmptyElement("end"); + fail(modeDesc+" Expected a validation exception when omitting non-optional element"); + } catch (XMLValidationException vex) { + // expected... + } + } + } + + public void testValidNsElem() + throws XMLStreamException + { + for (int i = 0; i < 3; ++i) { + boolean repairing = (i == 2); + StringWriter strw = new StringWriter(); + + XMLStreamWriter2 sw = getDTDValidatingWriter(strw, SIMPLE_NS_DTD, true, repairing); + // prefix, local name, uri (for elems) + sw.writeStartElement(NS_PREFIX, "root", NS_URI); + if (!repairing) { + sw.writeNamespace(NS_PREFIX, NS_URI); + } + sw.writeEndElement(); + sw.writeEndDocument(); + sw.close(); + + // and same with empty elem + sw = getDTDValidatingWriter(strw, SIMPLE_NS_DTD, true, repairing); + sw.writeEmptyElement(NS_PREFIX, "root", NS_URI); + if (!repairing) { + sw.writeNamespace(NS_PREFIX, NS_URI); + } + sw.writeEndDocument(); + sw.close(); + } + } + + /** + * Let's also do quick testing on structure that would be ok but + * where namespace prefix is not what dtd expects... + */ + public void testInvalidNsElem() + throws XMLStreamException + { + for (int i = 0; i < 2; ++i) { + boolean repairing; + String modeDesc; + + switch (i) { + case 0: + modeDesc = "[namespace-aware, non-repairing]"; + repairing = false; + break; + default: + modeDesc = "[namespace-aware, repairing]"; + repairing = true; + break; + } + + StringWriter strw = new StringWriter(); + + // Let's try omitting the end element, first... + + XMLStreamWriter2 sw = getDTDValidatingWriter(strw, SIMPLE_NS_DTD, true, repairing); + // prefix, local name, uri (for elems) + try { + sw.writeStartElement(NS_PREFIX2, "root", NS_URI); + fail(modeDesc+" Expected a validation exception when passing wrong (unexpected) ns for element"); + } catch (XMLValidationException vex) { + // expected... + } + // should not continue after exception; state may not be valid + + // and then the same for empty elem + sw = getDTDValidatingWriter(strw, SIMPLE_NS_DTD, true, repairing); + // prefix, local name, uri (for elems) + try { + sw.writeEmptyElement(NS_PREFIX2, NS_URI, "root"); + fail(modeDesc+" Expected a validation exception when passing wrong (unexpected) ns for element"); + } catch (XMLValidationException vex) { + // expected... + } + + // Oh, and finally, using non-ns DTD: + sw = getDTDValidatingWriter(strw, SIMPLE_DTD, true, repairing); + // prefix, local name, uri (for elems) + try { + sw.writeEmptyElement(NS_PREFIX, NS_URI, "root"); + fail(modeDesc+" Expected a validation exception when passing wrong (unexpected) ns for element"); + } catch (XMLValidationException vex) { + // expected... + } + } + } +} + diff -Nru libwoodstox-java-4.1.3/src/test/java/stax2/vwstream/W3CSchemaWrite16Test.java libwoodstox-java-5.1.0/src/test/java/stax2/vwstream/W3CSchemaWrite16Test.java --- libwoodstox-java-4.1.3/src/test/java/stax2/vwstream/W3CSchemaWrite16Test.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/stax2/vwstream/W3CSchemaWrite16Test.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,73 @@ +package stax2.vwstream; + +import java.io.StringWriter; + +import org.codehaus.stax2.*; + +import org.codehaus.stax2.validation.XMLValidationSchema; + +import wstxtest.vstream.BaseValidationTest; + +// for [woodstox-core#16] +public class W3CSchemaWrite16Test + extends BaseValidationTest +{ + final static String SIMPLE_WRITE_SCHEMA = +"\n"+ +"\n"+ +" \n"+ +" \n"+ +" \n"+ +" \n"+ +" \n"+ +" \n"+ +" \n"+ +" \n"+ +" \n"+ +" \n"+ +" \n"+ +" \n"+ +" \n"+ +" \n"+ +"\n"+ +""; + + public void testSimpleWriteValidation() throws Exception + { + final String XML = +"\n"+ +" \n"+ +" 1234567890\n"+ +" \n"+ +" \n"+ +" 1234567891\n"+ +" \n"+ +"\n" + ; + + XMLInputFactory2 f = getInputFactory(); + + XMLValidationSchema schema = parseW3CSchema(SIMPLE_WRITE_SCHEMA); + XMLStreamReader2 xmlReader = constructStreamReader(f, XML); + StringWriter strw = new StringWriter(); + + XMLStreamWriter2 xmlWriter = (XMLStreamWriter2) + getOutputFactory().createXMLStreamWriter(strw); + xmlWriter.validateAgainst(schema); + + xmlWriter.copyEventFromReader(xmlReader, false); + + while (xmlReader.hasNext()) { + xmlReader.next(); + + xmlWriter.copyEventFromReader(xmlReader, true); + } + + String validatedXML = strw.toString(); + if (validatedXML.indexOf("JobStatus") <= 0) { + fail("Wrong XML: "+validatedXML); + } +//System.err.println("XML: "+validatedXML); + } +} diff -Nru libwoodstox-java-4.1.3/src/test/java/stax2/vwstream/W3CSchemaWrite23Test.java libwoodstox-java-5.1.0/src/test/java/stax2/vwstream/W3CSchemaWrite23Test.java --- libwoodstox-java-4.1.3/src/test/java/stax2/vwstream/W3CSchemaWrite23Test.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/stax2/vwstream/W3CSchemaWrite23Test.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,39 @@ +package stax2.vwstream; + +import java.io.*; + +import org.codehaus.stax2.XMLStreamReader2; +import org.codehaus.stax2.XMLStreamWriter2; + +public class W3CSchemaWrite23Test + extends BaseOutputTest +{ + public void testSchemaValidatingCopy23() throws Exception + { + final String SCHEMA = "\n" ++"\n" ++" \n" ++""; + final String CONTENT = "124"; + final String DOC = "\n"+CONTENT; + + + StringWriter strw = new StringWriter(); + XMLStreamWriter2 xmlWriter = getSchemaValidatingWriter(strw, SCHEMA, false); + XMLStreamReader2 xmlReader = constructNsStreamReader(DOC, false); + + while (xmlReader.hasNext()) { + /*int type =*/ xmlReader.next(); + xmlWriter.copyEventFromReader(xmlReader, true); + } + + xmlWriter.close(); + xmlReader.close(); + + String xml = strw.toString(); + if (!xml.contains(CONTENT)) { + fail("Should contain ["+CONTENT+"], does not: ["+xml+"]"); + } + } +} diff -Nru libwoodstox-java-4.1.3/src/test/java/stax2/wstream/BaseWriterTest.java libwoodstox-java-5.1.0/src/test/java/stax2/wstream/BaseWriterTest.java --- libwoodstox-java-4.1.3/src/test/java/stax2/wstream/BaseWriterTest.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/stax2/wstream/BaseWriterTest.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,70 @@ +package stax2.wstream; + +import java.io.*; + +import javax.xml.stream.*; + +import org.codehaus.stax2.*; + +/** + * Base class for all StaxTest unit tests that test basic + * stream (cursor) writer API functionality. + * + * @author Tatu Saloranta + */ +public abstract class BaseWriterTest + extends stax2.BaseStax2Test +{ + public XMLStreamWriter2 getRepairingWriter(Writer w) + throws XMLStreamException + { + XMLOutputFactory f = getOutputFactory(); + f.setProperty(XMLStreamProperties.XSP_NAMESPACE_AWARE, Boolean.TRUE); + f.setProperty(XMLOutputFactory.IS_REPAIRING_NAMESPACES, + Boolean.TRUE); + return (XMLStreamWriter2) f.createXMLStreamWriter(w); + } + + public XMLStreamWriter2 getRepairingWriter(Writer w, String enc) + throws XMLStreamException + { + XMLOutputFactory2 f = getOutputFactory(); + f.setProperty(XMLStreamProperties.XSP_NAMESPACE_AWARE, Boolean.TRUE); + f.setProperty(XMLOutputFactory.IS_REPAIRING_NAMESPACES, + Boolean.TRUE); + return f.createXMLStreamWriter(w, enc); + } + + public XMLStreamWriter2 getNonRepairingWriter(Writer w, boolean nsAware) + throws XMLStreamException + { + XMLOutputFactory f = getOutputFactory(); + f.setProperty(XMLOutputFactory.IS_REPAIRING_NAMESPACES, + Boolean.FALSE); + f.setProperty(XMLStreamProperties.XSP_NAMESPACE_AWARE, + Boolean.valueOf(nsAware)); + return (XMLStreamWriter2) f.createXMLStreamWriter(w); + } + + public XMLStreamWriter2 getNonRepairingWriter(Writer w, String enc, boolean nsAware) + throws XMLStreamException + { + XMLOutputFactory2 f = getOutputFactory(); + f.setProperty(XMLOutputFactory.IS_REPAIRING_NAMESPACES, + Boolean.FALSE); + f.setProperty(XMLStreamProperties.XSP_NAMESPACE_AWARE, + Boolean.valueOf(nsAware)); + return f.createXMLStreamWriter(w, enc); + } + + public XMLStreamWriter2 getNonRepairingWriter(OutputStream os, String enc, boolean nsAware) + throws XMLStreamException + { + XMLOutputFactory2 f = getOutputFactory(); + f.setProperty(XMLOutputFactory.IS_REPAIRING_NAMESPACES, + Boolean.FALSE); + f.setProperty(XMLStreamProperties.XSP_NAMESPACE_AWARE, + Boolean.valueOf(nsAware)); + return (XMLStreamWriter2) f.createXMLStreamWriter(os, enc); + } +} diff -Nru libwoodstox-java-4.1.3/src/test/java/stax2/wstream/TestClosing.java libwoodstox-java-5.1.0/src/test/java/stax2/wstream/TestClosing.java --- libwoodstox-java-4.1.3/src/test/java/stax2/wstream/TestClosing.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/stax2/wstream/TestClosing.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,242 @@ +package stax2.wstream; + +import java.io.*; + +import javax.xml.stream.*; +import javax.xml.transform.stream.StreamResult; + +import org.codehaus.stax2.*; +import org.codehaus.stax2.io.Stax2BlockResult; + +/** + * This unit test suite verifies that the auto-closing feature works + * as expected (both explicitly, and via Result object being passed). + */ +@SuppressWarnings("resource") +public class TestClosing + extends BaseWriterTest +{ + /** + * This unit test checks the default behaviour; with no auto-close, no + * automatic closing should occur, nor explicit one unless specific + * forcing method is used. + */ + public void testNoAutoCloseWriter() + throws XMLStreamException + { + XMLOutputFactory2 f = getFactory(false); + MyWriter output = new MyWriter(); + XMLStreamWriter2 sw = (XMLStreamWriter2) f.createXMLStreamWriter(output); + // shouldn't be closed to begin with... + assertFalse(output.isClosed()); + writeDoc(sw); + assertFalse(output.isClosed()); + + // nor closed half-way through with basic close() + sw.close(); + assertFalse(output.isClosed()); + + // but needs to close when forced to: + sw.closeCompletely(); + assertTrue(output.isClosed()); + + // ... and should be ok to call it multiple times: + sw.closeCompletely(); + sw.closeCompletely(); + assertTrue(output.isClosed()); + } + + public void testNoAutoCloseStream() + throws XMLStreamException + { + XMLOutputFactory2 f = getFactory(false); + MyStream output = new MyStream(); + XMLStreamWriter2 sw = (XMLStreamWriter2) f.createXMLStreamWriter(output, "UTF-8"); + // shouldn't be closed to begin with... + assertFalse(output.isClosed()); + writeDoc(sw); + assertFalse(output.isClosed()); + + // nor closed half-way through with basic close() + sw.close(); + assertFalse(output.isClosed()); + + // but needs to close when forced to: + sw.closeCompletely(); + assertTrue(output.isClosed()); + + // ... and should be ok to call it multiple times: + sw.closeCompletely(); + sw.closeCompletely(); + assertTrue(output.isClosed()); + } + + /** + * This unit test checks that when auto-closing option is set, the + * passed in output stream does get properly closed + * when we call close(), as well as when do writeEndDocument(). + */ + public void testEnabledAutoClose() + throws XMLStreamException + { + // First, explicit close: + XMLOutputFactory2 f = getFactory(true); + MyWriter output = new MyWriter(); + XMLStreamWriter2 sw = (XMLStreamWriter2) f.createXMLStreamWriter(output); + assertFalse(output.isClosed()); + + writeDoc(sw); + + sw.close(); + assertTrue(output.isClosed()); + + // also, let's verify we can call more than once: + sw.close(); + sw.close(); + assertTrue(output.isClosed()); + + // Then implicit close: + output = new MyWriter(); + sw = (XMLStreamWriter2) f.createXMLStreamWriter(output); + writeDoc(sw); + assertTrue(output.isClosed()); + } + + /** + * This unit test checks what happens when we use Result abstraction + * for passing in result stream/writer. Their handling differs depending + * on whether caller is considered to have access to the underlying + * physical object or not. + */ + public void testAutoCloseImplicit() + throws XMLStreamException + { + XMLOutputFactory2 f = getFactory(false); // auto-close disabled + + /* Ok, first: with regular (OutputStream, Writer) results not auto-closing + * because caller does have access: StreamResult does retain given + * stream/writer as is. + */ + MyResult output = new MyResult(); + XMLStreamWriter2 sw = (XMLStreamWriter2) f.createXMLStreamWriter(output); + assertFalse(output.isClosed()); + writeDoc(sw); + sw.close(); + assertFalse(output.isClosed()); + + /* And then more interesting case; verifying that Stax2Source + * sub-classes are implicitly auto-closed: they need to be, because + * they do not (necessarily) expose underlying physical stream. + * We can test this by using any Stax2Source impl. + */ + MyStringResult result = new MyStringResult(); + sw = (XMLStreamWriter2) f.createXMLStreamWriter(result); + // closed if we write end doc + writeDoc(sw); + assertTrue(result.isClosed()); + + // as well as if we just call regular close + result = new MyStringResult(); + sw = (XMLStreamWriter2) f.createXMLStreamWriter(result); + sw.writeStartDocument(); + sw.writeEmptyElement("test"); + // no call to write end doc, so writer can't yet close; but we do call close: + sw.close(); + assertTrue(result.isClosed()); + } + + /* + //////////////////////////////////////// + // Non-test methods + //////////////////////////////////////// + */ + + XMLOutputFactory2 getFactory(boolean autoClose) + { + XMLOutputFactory2 f = getOutputFactory(); + f.setProperty(XMLOutputFactory2.P_AUTO_CLOSE_OUTPUT, Boolean.valueOf(autoClose)); + return f; + } + + void writeDoc(XMLStreamWriter sw) throws XMLStreamException + { + sw.writeStartDocument(); + sw.writeEmptyElement("root"); + sw.writeEndDocument(); + } + + /* + //////////////////////////////////////// + // Helper mock classes + //////////////////////////////////////// + */ + + final static class MyWriter + extends StringWriter + { + boolean mIsClosed = false; + + public MyWriter() { } + + @Override + public void close() throws IOException { + mIsClosed = true; + super.close(); + } + + public boolean isClosed() { return mIsClosed; } + } + + final static class MyStream + extends ByteArrayOutputStream + { + boolean mIsClosed = false; + + public MyStream() { } + + @Override + public void close() throws IOException { + mIsClosed = true; + super.close(); + } + public boolean isClosed() { return mIsClosed; } + } + + final static class MyResult + extends StreamResult + { + final MyWriter mWriter; + + private MyResult() { + super(); + mWriter = new MyWriter(); + setWriter(mWriter); + } + + public boolean isClosed() { + return mWriter.isClosed(); + } + } + + /** + * Need a helper class to verify whether resources (OutputStream, Writer) + * created via Stax2Result instances are (auto)closed or not. + */ + private final static class MyStringResult + extends Stax2BlockResult + { + MyWriter mWriter; + + public MyStringResult() { super(); } + + @Override + public Writer constructWriter() { + mWriter = new MyWriter(); + return mWriter; + } + @Override + public OutputStream constructOutputStream() { return null; } + + public boolean isClosed() { return mWriter.isClosed(); } + } +} diff -Nru libwoodstox-java-4.1.3/src/test/java/stax2/wstream/TestConfig.java libwoodstox-java-5.1.0/src/test/java/stax2/wstream/TestConfig.java --- libwoodstox-java-4.1.3/src/test/java/stax2/wstream/TestConfig.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/stax2/wstream/TestConfig.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,32 @@ +package stax2.wstream; + +import javax.xml.stream.*; + +import org.codehaus.stax2.*; + +/** + * Set of unit tests that checks that configuring of + * {@link XMLOutputFactory2} works ok. + *

+ * Note: for now there isn't much meat in this unit test: it's mostly + * used to do simple smoke testing for profile setters. + */ +public class TestConfig + extends BaseWriterTest +{ + public void testProfiles() + throws XMLStreamException + { + // configureForXmlConformance + XMLOutputFactory2 ofact = getNewOutputFactory(); + ofact.configureForXmlConformance(); + + // configureForRobustness + ofact = getNewOutputFactory(); + ofact.configureForRobustness(); + + // configureForSpeed + ofact = getNewOutputFactory(); + ofact.configureForSpeed(); + } +} diff -Nru libwoodstox-java-4.1.3/src/test/java/stax2/wstream/TestEscaping.java libwoodstox-java-5.1.0/src/test/java/stax2/wstream/TestEscaping.java --- libwoodstox-java-4.1.3/src/test/java/stax2/wstream/TestEscaping.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/stax2/wstream/TestEscaping.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,148 @@ +package stax2.wstream; + +import java.io.*; + +import javax.xml.stream.*; + +import org.codehaus.stax2.*; + +/** + * This test checks to see that text/attribute value escaping is + * working properly. + */ +public class TestEscaping + extends BaseWriterTest +{ + /** + * This test checks that even though it's 'wrong' to use non-URL/URI + * namespace URIs, it's not a fatal error; and that the 'uri' value + * should come back as it was written out. + */ + public void testBrokenNsURLs() + throws XMLStreamException + { + final String BROKEN_URL1 = ""; + final String BROKEN_URL2 = "\""; + final String BROKEN_URL3 = "x&"; + + StringWriter strw = new StringWriter(); + XMLStreamWriter2 w = getNonRepairingWriter(strw, true); + + w.writeStartDocument(); + w.writeStartElement("", "test", ""); + w.writeNamespace("ns", BROKEN_URL1); + w.writeStartElement("", "test", ""); + w.writeNamespace("ns", BROKEN_URL2); + w.writeStartElement("", "test", ""); + w.writeNamespace("ns", BROKEN_URL3); + + w.writeEndElement(); + w.writeEndElement(); + w.writeEndElement(); + + w.writeEndDocument(); + w.close(); + + // And then let's parse and verify it all: + + String input = strw.toString(); + + XMLStreamReader sr = constructNsStreamReader(input, true); + assertTokenType(START_DOCUMENT, sr.getEventType()); + + assertTokenType(START_ELEMENT, sr.next()); + assertEquals("test", sr.getLocalName()); + assertEquals(1, sr.getNamespaceCount()); + assertEquals("ns", sr.getNamespacePrefix(0)); + assertEquals(BROKEN_URL1, sr.getNamespaceURI(0)); + + assertTokenType(START_ELEMENT, sr.next()); + assertEquals("test", sr.getLocalName()); + assertEquals(1, sr.getNamespaceCount()); + assertEquals("ns", sr.getNamespacePrefix(0)); + assertEquals(BROKEN_URL2, sr.getNamespaceURI(0)); + + assertTokenType(START_ELEMENT, sr.next()); + assertEquals("test", sr.getLocalName()); + assertEquals(1, sr.getNamespaceCount()); + assertEquals("ns", sr.getNamespacePrefix(0)); + assertEquals(BROKEN_URL3, sr.getNamespaceURI(0)); + + assertTokenType(END_ELEMENT, sr.next()); + assertTokenType(END_ELEMENT, sr.next()); + assertTokenType(END_ELEMENT, sr.next()); + + assertTokenType(END_DOCUMENT, sr.next()); + + sr.close(); + } + + public void testLatin1Quoting() + throws XMLStreamException + { + final String TEXT = "ab\u00A0cd\tef\u00D8gh\u3c00..."; + + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + XMLStreamWriter2 w = getNonRepairingWriter(bos, "ISO-8859-1", true); + + w.writeStartDocument(); + w.writeStartElement("root"); + w.writeCharacters(TEXT); + w.writeEndElement(); + w.writeEndDocument(); + w.close(); + + InputStream in = new ByteArrayInputStream(bos.toByteArray()); + XMLStreamReader sr = constructNsStreamReader(in, true); + assertTokenType(START_DOCUMENT, sr.getEventType()); + assertTokenType(START_ELEMENT, sr.next()); + assertEquals("root", sr.getLocalName()); + assertTokenType(CHARACTERS, sr.next()); + + assertEquals(TEXT, sr.getText()); + + assertTokenType(END_ELEMENT, sr.next()); + } + + public void testAsciiQuoting() + throws XMLStreamException + { + final String TEXT = "ab\u00A0cd\tef\u00D8gh\u3c00..."; + + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + XMLStreamWriter2 w = getNonRepairingWriter(bos, "US-ASCII", true); + + w.writeStartDocument(); + w.writeStartElement("root"); + w.writeCharacters(TEXT); + w.writeEndElement(); + w.writeEndDocument(); + w.close(); + + InputStream in = new ByteArrayInputStream(bos.toByteArray()); + XMLStreamReader sr = constructNsStreamReader(in, true); + assertTokenType(START_DOCUMENT, sr.getEventType()); + assertTokenType(START_ELEMENT, sr.next()); + assertEquals("root", sr.getLocalName()); + assertTokenType(CHARACTERS, sr.next()); + + assertEquals(TEXT, sr.getText()); + + assertTokenType(END_ELEMENT, sr.next()); + } + + public void testLinefeedQuoting() throws Exception + { + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + XMLStreamWriter2 w = getNonRepairingWriter(bos, "US-ASCII", true); + + w.writeStartElement("root"); + w.writeCharacters("a\nb\rc"); + w.writeEndElement(); + w.writeEndDocument(); + w.close(); + + String xml = bos.toString("UTF-8"); + assertEquals("a\nb c", xml); + } +} diff -Nru libwoodstox-java-4.1.3/src/test/java/stax2/wstream/TestNamespaceCopying.java libwoodstox-java-5.1.0/src/test/java/stax2/wstream/TestNamespaceCopying.java --- libwoodstox-java-4.1.3/src/test/java/stax2/wstream/TestNamespaceCopying.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/stax2/wstream/TestNamespaceCopying.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,69 @@ +package stax2.wstream; + +import java.io.*; +import java.util.*; + +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.stream.*; +import javax.xml.transform.dom.DOMResult; + +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +/** + * Tests that namespaces are written to the output stream in namespace + * repairing mode. See [WSTX-193] for details. + * + * @author Christopher Paul Simmons + */ +public class TestNamespaceCopying + extends BaseWriterTest +{ + XMLInputFactory _inputFactory; + XMLOutputFactory _outputFactory; + XMLEventFactory _eventFactory; + + @Override + protected void setUp() throws Exception { + _outputFactory = getOutputFactory(); + setRepairing(_outputFactory, true); + _eventFactory = getEventFactory(); + _inputFactory = getInputFactory(); + } + + public void testStreamXMLNSDeclaration() throws Exception { + final StringWriter stringWriter = new StringWriter(); + XMLEventWriter xmlWriter = _outputFactory.createXMLEventWriter(stringWriter); + xmlWriter.add(_eventFactory.createStartDocument("UFT-8")); + xmlWriter.add(_eventFactory.createStartElement("foo", "fooNS", "root", Collections.EMPTY_LIST.iterator(), Arrays.asList(_eventFactory.createNamespace("bar", "barNS")).iterator())); + xmlWriter.add(_eventFactory.createNamespace("baz", "bazNS")); + xmlWriter.add(_eventFactory.createCharacters("bar:qname")); + xmlWriter.add(_eventFactory.createEndElement("foo", "fooNS", "root")); + xmlWriter.add(_eventFactory.createEndDocument()); + + // The document is just to inspect the result. + final Document document = buildDocument(stringWriter.toString()); + + Element documentElement = document.getDocumentElement(); + assertEquals("fooNS", getNamespaceForPrefix(documentElement, "foo")); + // This line fails in 3.2.7 + assertEquals("barNS", getNamespaceForPrefix(documentElement, "bar")); + assertEquals("bazNS", getNamespaceForPrefix(documentElement, "baz")); + } + + private String getNamespaceForPrefix(final Element element, final String prefix) { + return element.getAttributeNS("http://www.w3.org/2000/xmlns/", prefix); + } + + private Document buildDocument(final String string) throws XMLStreamException, ParserConfigurationException { + // Less painful to do this using XMLUnit if you use it. + XMLEventReader reader = _inputFactory.createXMLEventReader(new StringReader(string)); + final DocumentBuilderFactory documentBuilder = DocumentBuilderFactory.newInstance(); + documentBuilder.setNamespaceAware(true); + final Document document = documentBuilder.newDocumentBuilder().newDocument(); + XMLEventWriter writer = _outputFactory.createXMLEventWriter(new DOMResult(document)); + writer.add(reader); + return document; + } +} diff -Nru libwoodstox-java-4.1.3/src/test/java/stax2/wstream/TestStreamResult.java libwoodstox-java-5.1.0/src/test/java/stax2/wstream/TestStreamResult.java --- libwoodstox-java-4.1.3/src/test/java/stax2/wstream/TestStreamResult.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/stax2/wstream/TestStreamResult.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,49 @@ +package stax2.wstream; + +import java.io.*; +import javax.xml.stream.*; +import javax.xml.transform.stream.StreamResult; + +import org.codehaus.stax2.XMLInputFactory2; + +import stax2.BaseStax2Test; + +/** + * This unit test suite verifies use of {@link StreamResult} as output + * for {@link XMLOutputFactory}. + * + * @author Tatu Saloranta + * + * @since 3.0 + */ +public class TestStreamResult + extends BaseStax2Test +{ + /** + * This test is related to problem reported as [WSTX-182], inability + * to use SystemId alone as source. + */ + public void testCreateUsingSystemId() + throws IOException, XMLStreamException + { + File tmpF = File.createTempFile("staxtest", ".xml"); + tmpF.deleteOnExit(); + + XMLOutputFactory f = getOutputFactory(); + StreamResult dst = new StreamResult(); + dst.setSystemId(tmpF); + XMLStreamWriter sw = f.createXMLStreamWriter(dst); + + sw.writeStartDocument(); + sw.writeEmptyElement("root"); + sw.writeEndDocument(); + sw.close(); + + // plus let's read and check it + XMLInputFactory2 inf = getInputFactory(); + XMLStreamReader sr = inf.createXMLStreamReader(tmpF); + assertTokenType(START_ELEMENT, sr.next()); + assertTokenType(END_ELEMENT, sr.next()); + sr.close(); + } +} diff -Nru libwoodstox-java-4.1.3/src/test/java/stax2/wstream/TestStreamWriter.java libwoodstox-java-5.1.0/src/test/java/stax2/wstream/TestStreamWriter.java --- libwoodstox-java-4.1.3/src/test/java/stax2/wstream/TestStreamWriter.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/stax2/wstream/TestStreamWriter.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,428 @@ +package stax2.wstream; + +import java.io.*; + +import javax.xml.stream.*; + +import org.codehaus.stax2.*; + +/** + * Unit test suite that focuses on testing additional methods that + * StAX2 has for stream writers. + */ +public class TestStreamWriter + extends BaseWriterTest +{ + /* + ////////////////////////////////////////////////////////// + // First tests for simple accessors + ////////////////////////////////////////////////////////// + */ + + public void testGetEncoding() + throws XMLStreamException + { + // Let's test with US-ASCII for fun + final String ENC = "US-ASCII"; + + for (int isWriter = 0; isWriter < 2; ++isWriter) { + for (int i = 0; i < 3; ++i) { + boolean ns = (i > 0); + boolean repairing = (i == 2); + XMLOutputFactory2 of = getFactory(ns, repairing); + XMLStreamWriter2 w; + + if (isWriter > 0) { + StringWriter strw = new StringWriter(); + w = of.createXMLStreamWriter(strw, ENC); + } else { + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + w = (XMLStreamWriter2)of.createXMLStreamWriter(bos, ENC); + } + assertEquals(ENC, w.getEncoding()); + // Need to output something, otherwise it'll be empty doc + w.writeEmptyElement("root"); + w.close(); + + /* Ok good, but how about the case where it's only + * passed for writeStartDocument()? Note: when wrapping + * a stream, factory has to use default (UTF-8). + */ + if (isWriter > 0) { + StringWriter strw = new StringWriter(); + w = (XMLStreamWriter2)of.createXMLStreamWriter(strw); + w.writeStartDocument(ENC, "1.0"); + assertEquals(ENC, w.getEncoding()); + } else { + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + w = (XMLStreamWriter2)of.createXMLStreamWriter(bos); + w.writeStartDocument(ENC, "1.0"); + assertEquals("UTF-8", w.getEncoding()); + } + w.writeEmptyElement("root"); + w.close(); + } + } + } + + /** + * Additional tests based on [WSTX-146]; JDK may report legacy + * encoding names, we shouldn't report those but rather IANA + * approved canonical equivalents. + */ + public void testLegacyEncodings() + throws Exception + { + String[] encs = new String[] { "UTF-8", "US-ASCII", "ISO-8859-1" }; + + XMLOutputFactory2 outf = getFactory(true, false); + XMLInputFactory2 inf = getNewInputFactory(); + + for (int i = 0; i < encs.length; ++i) { + String enc = encs[i]; + ByteArrayOutputStream os = new ByteArrayOutputStream(); + XMLStreamWriter sw = outf.createXMLStreamWriter(new OutputStreamWriter(os, enc)); + sw.writeStartDocument("1.0"); + sw.writeEmptyElement("foo"); + sw.writeEndDocument(); + // Parse it and check the encoding + XMLStreamReader sr = inf.createXMLStreamReader(new ByteArrayInputStream(os.toByteArray())); + String act = sr.getCharacterEncodingScheme(); + if (!enc.equals(act)) { + fail("Expected encoding to be returned correctly as \""+enc+"\", got \""+act+"\""); + } + } + } + + /** + * Since Woodstox doesn't yet actually implement the method, we'll + * just call the method and do not expect and exception. Returned + * object (or lack thereof) is not inspected + */ + public void testGetLocation() + throws XMLStreamException + { + for (int i = 0; i < 3; ++i) { + boolean ns = (i > 0); + boolean repairing = (i == 2); + XMLOutputFactory2 of = getFactory(ns, repairing); + StringWriter strw = new StringWriter(); + XMLStreamWriter2 w = (XMLStreamWriter2)of.createXMLStreamWriter(strw); + XMLStreamLocation2 loc = w.getLocation(); + assertNotNull(loc); + // Need to output something, otherwise it'll be empty doc + w.writeEmptyElement("root"); + w.close(); + } + } + + /* + ////////////////////////////////////////////////////////// + // Then new output methods, or improved existing ones + ////////////////////////////////////////////////////////// + */ + + public void testCData() + throws XMLStreamException + { + final String CDATA_TEXT = "Let's test it with some ] ]> data; s and && chars and all!"; + + for (int i = 0; i < 2; ++i) { + boolean ns = (i > 0); + StringWriter strw = new StringWriter(); + XMLStreamWriter2 w = getNonRepairingWriter(strw, ns); + + w.writeStartDocument(); + w.writeStartElement("test"); + + char[] cbuf = new char[CDATA_TEXT.length() + 10]; + CDATA_TEXT.getChars(0, CDATA_TEXT.length(), cbuf, 3); + w.writeCData(cbuf, 3, CDATA_TEXT.length()); + w.writeEndElement(); + w.writeEndDocument(); + w.close(); + + // And then let's parse and verify it all: + + XMLStreamReader sr = constructNsStreamReader(strw.toString(), true); + assertTokenType(START_DOCUMENT, sr.getEventType()); + assertTokenType(START_ELEMENT, sr.next()); + + // Now, parsers are allowed to report CHARACTERS or CDATA + int tt = sr.next(); + if (tt != CHARACTERS && tt != CDATA) { + assertTokenType(CDATA, tt); // to cause failure + } + assertFalse(sr.isWhiteSpace()); + assertEquals(CDATA_TEXT, getAndVerifyText(sr)); + assertTokenType(END_ELEMENT, sr.next()); + assertTokenType(END_DOCUMENT, sr.next()); + } + } + + /** + * This test was inspired by a failing regression test: it required + * long enough COMMENT content to trigger buffar boundary problems + */ + public void testLongerComment() + throws XMLStreamException + { + doTestLonger(COMMENT, false, false, "UTF-8"); + doTestLonger(COMMENT, false, false, "ISO-8859-1"); + doTestLonger(COMMENT, false, false, "US-ASCII"); + doTestLonger(COMMENT, true, false, "UTF-8"); + doTestLonger(COMMENT, true, false, "ISO-8859-1"); + doTestLonger(COMMENT, true, false, "US-ASCII"); + doTestLonger(COMMENT, true, true, "UTF-8"); + doTestLonger(COMMENT, true, true, "ISO-8859-1"); + doTestLonger(COMMENT, true, true, "US-ASCII"); + } + + public void testLongerPI() + throws XMLStreamException + { + doTestLonger(PROCESSING_INSTRUCTION, false, false, "UTF-8"); + doTestLonger(PROCESSING_INSTRUCTION, false, false, "ISO-8859-1"); + doTestLonger(PROCESSING_INSTRUCTION, false, false, "US-ASCII"); + doTestLonger(PROCESSING_INSTRUCTION, true, false, "UTF-8"); + doTestLonger(PROCESSING_INSTRUCTION, true, false, "ISO-8859-1"); + doTestLonger(PROCESSING_INSTRUCTION, true, false, "US-ASCII"); + doTestLonger(PROCESSING_INSTRUCTION, true, true, "UTF-8"); + doTestLonger(PROCESSING_INSTRUCTION, true, true, "ISO-8859-1"); + doTestLonger(PROCESSING_INSTRUCTION, true, true, "US-ASCII"); + } + + public void testCopy() + throws XMLStreamException + { + final String XML = + "\n" + +" ]>\n" + +"\n" + +"" + +"Text: & " + +" there you have it!]]>" + +"" + ; + + for (int i = 0; i < 2; ++i) { + boolean ns = (i > 0); + //boolean repairing = (i == 2); + boolean repairing = (i == 1); + XMLStreamReader2 sr = constructNsStreamReader(XML, ns); + StringWriter strw = new StringWriter(); + XMLStreamWriter2 w; + + if (repairing) { + w = getRepairingWriter(strw); + } else { + w = getNonRepairingWriter(strw, ns); + } + + while (sr.hasNext()) { + sr.next(); + w.copyEventFromReader(sr, false); + } + sr.close(); + w.close(); + String xmlOut = strw.toString(); + + // And let's parse it to verify it's still well-formed... + // (should also verify its accuracy...) + sr = constructNsStreamReader(xmlOut, ns); + streamThrough(sr); + } + } + + /** + * Unit test for verifyin that writeRaw() works as expected. + */ + public void testRaw() + throws XMLStreamException + { + String RAW2 = "foo&bar"; + + for (int i = 0; i < 3; ++i) { + boolean ns = (i > 0); + StringWriter strw = new StringWriter(); + XMLStreamWriter2 w = (i == 2) ? getRepairingWriter(strw) + : getNonRepairingWriter(strw, ns); + w.writeStartDocument(); + w.writeStartElement("test"); + w.writeAttribute("attr", "value"); + w.writeRaw("this or 'that'"); + char[] cbuf = new char[RAW2.length() + 10]; + RAW2.getChars(0, RAW2.length(), cbuf, 3); + w.writeRaw(cbuf, 3, RAW2.length()); + w.writeEndElement(); + w.writeEndDocument(); + w.close(); + + // And then let's parse and verify it all: + XMLStreamReader sr = constructNsStreamReader(strw.toString(), true); + assertTokenType(START_DOCUMENT, sr.getEventType()); + assertTokenType(START_ELEMENT, sr.next()); + assertEquals("test", sr.getLocalName()); + assertEquals(1, sr.getAttributeCount()); + assertEquals("attr", sr.getAttributeLocalName(0)); + assertEquals("value", sr.getAttributeValue(0)); + assertTokenType(CHARACTERS, sr.next()); + assertEquals("this or 'that'", getAndVerifyText(sr)); + assertTokenType(START_ELEMENT, sr.next()); + assertEquals("elem", sr.getLocalName()); + assertTokenType(CHARACTERS, sr.next()); + assertEquals("foo&bar", getAndVerifyText(sr)); + assertTokenType(END_ELEMENT, sr.next()); + assertEquals("elem", sr.getLocalName()); + assertTokenType(END_ELEMENT, sr.next()); + assertEquals("test", sr.getLocalName()); + assertTokenType(END_DOCUMENT, sr.next()); + } + } + + /* + ////////////////////////////////////////////////////////// + // Then custom quoting/escaping writers + ////////////////////////////////////////////////////////// + */ + + /** + * First a simplish testing of how exotic characters are escaped + * in attribute values. + */ + public void testAttrValueWriterSimple() + throws IOException, XMLStreamException + { + // Let's just ensure escaping is done for chars that need it + //String IN = "Ok, lessee \u00A0; -- \t and this: \u0531."; + String IN = "Ok, nbsp: \u00A0; and 'quotes' and \"doubles\" too; and multi-bytes too: [\u0531]"; + doTestAttrValueWriter("ISO-8859-1", IN); + doTestAttrValueWriter("UTF-8", IN); + doTestAttrValueWriter("US-ASCII", IN); + } + + /** + * And then bit more advanced test for things that need special + * support for round-tripping + */ + public void testAttrValueWriterTabsEtc() + throws IOException, XMLStreamException + { + String IN = "How about tabs: [\t] or cr+lf [\r\n]"; + doTestAttrValueWriter("ISO-8859-1", IN); + doTestAttrValueWriter("UTF-8", IN); + doTestAttrValueWriter("US-ASCII", IN); + } + + /* + ////////////////////////////////////////////////////////// + // Non-test methods: + ////////////////////////////////////////////////////////// + */ + + public XMLOutputFactory2 getFactory(boolean nsAware, boolean repairing) + throws XMLStreamException + { + XMLOutputFactory2 f = getOutputFactory(); + f.setProperty(XMLStreamProperties.XSP_NAMESPACE_AWARE, + Boolean.valueOf(nsAware)); + f.setProperty(XMLOutputFactory.IS_REPAIRING_NAMESPACES, + Boolean.valueOf(repairing)); + return f; + } + + private void doTestAttrValueWriter(String enc, String IN) + throws IOException, XMLStreamException + { + // First, let's explicitly pass the encoding... + XMLOutputFactory of = getFactory(false, false); + ByteArrayOutputStream out = new ByteArrayOutputStream(); + Writer w = new OutputStreamWriter(out, enc); + /* 26-Mar-2008, tatus: Note: we may get legacy encoding + * names from here (like "ASCII" over "US-ASCII" etc). + * Additionally, should we count on output factory knowing + * how to find underlying encoding from OutputStreamWriter? + * Could (should?) explicitly pass encoding instead. + */ + XMLStreamWriter sw = of.createXMLStreamWriter(w); + + // So shouldn't we do this? + //XMLStreamWriter sw = of.createXMLStreamWriter(w, enc); + + sw.writeStartDocument(enc, "1.0"); + sw.writeStartElement("elem"); + sw.writeAttribute("attr", IN); + sw.writeEndElement(); + sw.writeEndDocument(); + sw.close(); + w.close(); + + // Can we parse it ok? + XMLInputFactory ifact = getInputFactory(); + XMLStreamReader sr = ifact.createXMLStreamReader(new ByteArrayInputStream(out.toByteArray()), enc); + + // First, let's ensure we see the encoding: + assertTokenType(START_DOCUMENT, sr.getEventType()); + assertEquals(enc, sr.getCharacterEncodingScheme()); + + assertTokenType(START_ELEMENT, sr.next()); + assertEquals(1, sr.getAttributeCount()); + String attrValue = sr.getAttributeValue(0); + if (!IN.equals(attrValue)) { + failStrings("Incorrect writing/reading of attribute value (encoding '"+enc+"')", + IN, attrValue); + } + assertTokenType(END_ELEMENT, sr.next()); + assertTokenType(END_DOCUMENT, sr.next()); + sr.close(); + } + + public void doTestLonger(int type, boolean ns, boolean repair, String enc) + throws XMLStreamException + { + final String TEXT = +" Table of types of doubts\n" ++"doubt: specific error or issue with the test case\n" ++"extension: uses an extension feature\n" ++"gray-area: the spec does not give enough precision to distinguish correct behavior on the indicated detail\n" ++"processor-specific: processors are required to provide a unique value (should be marked as \"manual\" compare in catalog)\n" ++"serial: processor has options regarding serialization (This doubt only used for detail issues, not general discretion about encoding.)" + ; + + for (int i = 0; i < 2; ++i) { + StringWriter strw = new StringWriter(); + XMLStreamWriter2 w; + if (repair) { + w = getRepairingWriter(strw, enc); + } else { + w = getNonRepairingWriter(strw, enc, ns); + } + w.writeStartDocument(enc, "1.0"); + if (type == COMMENT) { + w.writeComment(TEXT); + } else { + w.writeProcessingInstruction("pi", TEXT); + } + w.writeEmptyElement("root"); + w.writeEndDocument(); + w.close(); + + // And then let's parse and verify the contents: + XMLStreamReader sr = constructNsStreamReader(strw.toString(), true); + assertTokenType(START_DOCUMENT, sr.getEventType()); + + if (type == COMMENT) { + assertTokenType(COMMENT, sr.next()); + assertEquals(TEXT, getAndVerifyText(sr)); + } else { + assertTokenType(PROCESSING_INSTRUCTION, sr.next()); + // PI data excludes leading space... need to trim + assertEquals(TEXT.trim(), sr.getPIData().trim()); + } + assertTokenType(START_ELEMENT, sr.next()); + assertTokenType(END_ELEMENT, sr.next()); + assertTokenType(END_DOCUMENT, sr.next()); + sr.close(); + } + } +} diff -Nru libwoodstox-java-4.1.3/src/test/java/stax2/wstream/TestWriterConstruction.java libwoodstox-java-5.1.0/src/test/java/stax2/wstream/TestWriterConstruction.java --- libwoodstox-java-4.1.3/src/test/java/stax2/wstream/TestWriterConstruction.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/stax2/wstream/TestWriterConstruction.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,79 @@ +package stax2.wstream; + +import java.io.*; + +import javax.xml.stream.*; + +import org.codehaus.stax2.*; +import org.codehaus.stax2.io.*; + +/** + * Unit test suite that tests additional StAX2 stream writer construction + * methods. + */ +public class TestWriterConstruction + extends BaseWriterTest +{ + public void testCreateWithFileSource() + throws IOException, XMLStreamException + { + XMLOutputFactory2 outf = getOutputFactory(); + File f = createTempFile(); + XMLStreamWriter sw = outf.createXMLStreamWriter(new Stax2FileResult(f)); + writeAndVerify(sw, f, "withFileSource"); + } + + public void testCreateWithFileStreamReader() + throws IOException, XMLStreamException + { + // Doesn't do much, yet... just constructs, for now + StringWriter strw = new StringWriter(); + XMLStreamWriter sw = getNonRepairingWriter(strw, true); + XMLEventWriter ew = getOutputFactory().createXMLEventWriter(sw); + + assertNotNull(ew); + + // TODO: try it out... + } + + /* + //////////////////////////////////////////////// + // Internal methods + //////////////////////////////////////////////// + */ + + File createTempFile() + throws IOException + { + File f = File.createTempFile("stax2test", null); + f.deleteOnExit(); + return f; + } + + private void writeAndVerify(XMLStreamWriter sw, File f, String text) + throws XMLStreamException + { + /* No need to write elaborate doc, just to ensure creation and + * later access work ok. + */ + sw.writeStartDocument("UTF-8", "1.0"); + sw.writeStartElement("write"); + sw.writeCharacters(text); + sw.writeEndElement(); + sw.writeEndDocument(); + sw.close(); + + // And then reader + XMLInputFactory2 ifact = getInputFactory(); + setCoalescing(ifact, true); + XMLStreamReader sr = ifact.createXMLStreamReader(new Stax2FileSource(f)); + assertTokenType(START_ELEMENT, sr.next()); + assertEquals("write", sr.getLocalName()); + assertTokenType(CHARACTERS, sr.next()); + assertEquals(text, getAndVerifyText(sr)); + assertTokenType(END_ELEMENT, sr.next()); + assertEquals("write", sr.getLocalName()); + assertTokenType(END_DOCUMENT, sr.next()); + sr.close(); + } +} diff -Nru libwoodstox-java-4.1.3/src/test/java/wstxtest/BaseWstxTest.java libwoodstox-java-5.1.0/src/test/java/wstxtest/BaseWstxTest.java --- libwoodstox-java-4.1.3/src/test/java/wstxtest/BaseWstxTest.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/wstxtest/BaseWstxTest.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,608 @@ +package wstxtest; + +import java.io.*; +import java.util.HashMap; + +import javax.xml.stream.*; +import javax.xml.stream.events.XMLEvent; + +import org.codehaus.stax2.*; +import org.codehaus.stax2.evt.*; + +import com.ctc.wstx.api.WstxInputProperties; +import com.ctc.wstx.api.WstxOutputProperties; +import com.ctc.wstx.cfg.XmlConsts; +import com.ctc.wstx.stax.WstxEventFactory; +import com.ctc.wstx.stax.WstxInputFactory; +import com.ctc.wstx.stax.WstxOutputFactory; + +import stax2.BaseStax2Test; + +public abstract class BaseWstxTest + extends BaseStax2Test + implements XMLStreamConstants +{ + final static HashMap mTokenTypes = new HashMap(); + static { + mTokenTypes.put(new Integer(START_ELEMENT), "START_ELEMENT"); + mTokenTypes.put(new Integer(END_ELEMENT), "END_ELEMENT"); + mTokenTypes.put(new Integer(START_DOCUMENT), "START_DOCUMENT"); + mTokenTypes.put(new Integer(END_DOCUMENT), "END_DOCUMENT"); + mTokenTypes.put(new Integer(CHARACTERS), "CHARACTERS"); + mTokenTypes.put(new Integer(CDATA), "CDATA"); + mTokenTypes.put(new Integer(COMMENT), "COMMENT"); + mTokenTypes.put(new Integer(PROCESSING_INSTRUCTION), "PROCESSING_INSTRUCTION"); + mTokenTypes.put(new Integer(DTD), "DTD"); + mTokenTypes.put(new Integer(SPACE), "SPACE"); + mTokenTypes.put(new Integer(ENTITY_REFERENCE), "ENTITY_REFERENCE"); + } + + /** + * Switch that can be turned on to verify to display ALL exact Exceptions + * thrown when Exceptions are expected. This is sometimes necessary + * when debugging, since it's impossible to automatically verify + * that Exception is exactly the right one, since there is no + * strict Exception type hierarchy for StAX problems. + *

+ * Note: Not made 'final static', so that compiler won't inline + * it. Makes possible to do partial re-compilations. + * Note: Since it's only used as the default value, sub-classes + * can separately turn it off as necessary + */ + //protected static boolean DEF_PRINT_EXP_EXCEPTION = true; +// protected static boolean DEF_PRINT_EXP_EXCEPTION = false; + +// protected boolean PRINT_EXP_EXCEPTION = DEF_PRINT_EXP_EXCEPTION; + + /* + /////////////////////////////////////////////////// + // Lazy-loaded thingies + /////////////////////////////////////////////////// + */ + + XMLInputFactory2 mInputFactory = null; + XMLOutputFactory2 mOutputFactory = null; + XMLEventFactory2 mEventFactory = null; + + /* + ////////////////////////////////////////////////// + // Factory methods + ////////////////////////////////////////////////// + */ + + @Override + protected XMLInputFactory2 getInputFactory() + { + if (mInputFactory == null) { + mInputFactory = getNewInputFactory(); + } + return mInputFactory; + } + + @Override + protected XMLEventFactory2 getEventFactory() + { + if (mEventFactory == null) { + mEventFactory = new WstxEventFactory(); + } + return mEventFactory; + } + + protected WstxInputFactory getWstxInputFactory() { + return (WstxInputFactory) getInputFactory(); + } + + protected static XMLInputFactory2 getNewInputFactory() { + return new WstxInputFactory(); + } + + @Override + protected XMLOutputFactory2 getOutputFactory() + { + if (mOutputFactory == null) { + mOutputFactory = getNewOutputFactory(); + } + return mOutputFactory; + } + + protected WstxOutputFactory getWstxOutputFactory() { + return (WstxOutputFactory) getOutputFactory(); + } + + protected static XMLOutputFactory2 getNewOutputFactory() { + return new WstxOutputFactory(); + } + + protected static XMLStreamReader2 constructStreamReader(XMLInputFactory f, String content) + throws XMLStreamException + { + return (XMLStreamReader2) f.createXMLStreamReader(new StringReader(content)); + } + + @SuppressWarnings({ "deprecation", "resource" }) + protected static XMLStreamReader2 constructStreamReaderForFile(XMLInputFactory f, String filename) + throws IOException, XMLStreamException + { + File inf = new File(filename); + XMLStreamReader sr = f.createXMLStreamReader(inf.toURL().toString(), + new FileReader(inf)); + assertEquals(sr.getEventType(), START_DOCUMENT); + return (XMLStreamReader2) sr; + } + + protected static XMLEventReader2 constructEventReader(XMLInputFactory f, String content) + throws XMLStreamException + { + return (XMLEventReader2) f.createXMLEventReader(new StringReader(content)); + } + + @Override + protected XMLStreamReader2 constructNsStreamReader(String content, boolean coal) + throws XMLStreamException + { + XMLInputFactory f = getInputFactory(); + setNamespaceAware(f, true); + setCoalescing(f, coal); + return (XMLStreamReader2) f.createXMLStreamReader(new StringReader(content)); + } + + @Override + protected XMLStreamReader2 constructNsStreamReader(InputStream in, boolean coal) + throws XMLStreamException + { + XMLInputFactory f = getInputFactory(); + setNamespaceAware(f, true); + setCoalescing(f, coal); + return (XMLStreamReader2) f.createXMLStreamReader(in); + } + + @Override + protected XMLStreamReader2 constructNonNsStreamReader(String content, boolean coal) + throws XMLStreamException + { + XMLInputFactory f = getInputFactory(); + setNamespaceAware(f, false); + setCoalescing(f, coal); + return (XMLStreamReader2) f.createXMLStreamReader(new StringReader(content)); + } + + /* + ////////////////////////////////////////////////// + // Configuring input factory + ////////////////////////////////////////////////// + */ + + protected static void setLazyParsing(XMLInputFactory f, boolean state) + throws XMLStreamException + { + f.setProperty(XMLInputFactory2.P_LAZY_PARSING, + state ? Boolean.TRUE : Boolean.FALSE); + } + + protected static void setMinTextSegment(XMLInputFactory f, int len) + throws XMLStreamException + { + f.setProperty(WstxInputProperties.P_MIN_TEXT_SEGMENT, new Integer(len)); + } + + /* + ////////////////////////////////////////////////// + // Configuring output factory + ////////////////////////////////////////////////// + */ + + protected static void setRepairing(XMLOutputFactory f, boolean state) + { + f.setProperty(XMLOutputFactory.IS_REPAIRING_NAMESPACES, + Boolean.valueOf(state)); + } + + protected static void setValidateStructure(XMLOutputFactory f, boolean state) + { + f.setProperty(WstxOutputProperties.P_OUTPUT_VALIDATE_STRUCTURE, + Boolean.valueOf(state)); + } + + protected static void setValidateContent(XMLOutputFactory f, boolean state) + { + f.setProperty(WstxOutputProperties.P_OUTPUT_VALIDATE_CONTENT, + Boolean.valueOf(state)); + } + + protected static void setValidateNames(XMLOutputFactory f, boolean state) + { + f.setProperty(WstxOutputProperties.P_OUTPUT_VALIDATE_NAMES, + Boolean.valueOf(state)); + } + + protected static void setValidateAll(XMLOutputFactory f, boolean state) + { + setValidateStructure(f, state); + setValidateContent(f, state); + setValidateNames(f, state); + } + + protected static void setFixContent(XMLOutputFactory f, boolean state) + { + f.setProperty(WstxOutputProperties.P_OUTPUT_FIX_CONTENT, + Boolean.valueOf(state)); + } + + /* + ////////////////////////////////////////////////// + // Higher-level test methods + ////////////////////////////////////////////////// + */ + + /** + * Method that will iterate through contents of an XML document + * using specified stream reader; will also access some of data + * to make sure reader reads most of lazy-loadable data. + * Method is usually called to try to get an exception for invalid + * content. + * + * @return Dummy value calculated on contents; used to make sure + * no dead code is eliminated + */ + @Override + protected int streamThrough(XMLStreamReader sr) + throws XMLStreamException + { + int result = 0; + + while (sr.hasNext()) { + int type = sr.next(); + result += type; + if (sr.hasText()) { + // will also do basic verification for text content, to + // see that all text accessor methods return same content + result += getAndVerifyText(sr).hashCode(); + } + if (sr.hasName()) { + result += sr.getName().hashCode(); + } + } + + return result; + } + + @Override + protected int streamThroughFailing(XMLInputFactory f, String contents, + String msg) + throws XMLStreamException + { + int result = 0; + try { + XMLStreamReader sr = constructStreamReader(f, contents); + result = streamThrough(sr); + } catch (XMLStreamException ex) { // good + if (PRINT_EXP_EXCEPTION) { + System.out.println("Expected failure: '"+ex.getMessage()+"' " + +"(matching message: '"+msg+"')"); + } + return 0; + } catch (RuntimeException ex2) { // ok + if (PRINT_EXP_EXCEPTION) { + System.out.println("Expected failure: '"+ex2.getMessage()+"' " + +"(matching message: '"+msg+"')"); + } + return 0; + } catch (Throwable t) { // not so good + fail("Expected an XMLStreamException or RuntimeException for "+msg + +", got: "+t); + } + + fail("Expected an exception for "+msg); + return result; // never gets here + } + + @Override + protected int streamThroughFailing(XMLStreamReader sr, String msg) + throws XMLStreamException + { + int result = 0; + try { + result = streamThrough(sr); + } catch (XMLStreamException ex) { // good + if (PRINT_EXP_EXCEPTION) { + System.out.println("Expected failure: '"+ex.getMessage()+"' " + +"(matching message: '"+msg+"')"); + } + return 0; + } catch (RuntimeException ex2) { // ok + if (PRINT_EXP_EXCEPTION) { + System.out.println("Expected failure: '"+ex2.getMessage()+"' " + +"(matching message: '"+msg+"')"); + } + return 0; + } catch (Throwable t) { // not so good + fail("Expected an XMLStreamException or RuntimeException for "+msg + +", got: "+t); + } + + fail("Expected an exception for "+msg); + return result; // never gets here + } + + /* + ////////////////////////////////////////////////// + // Assertions + ////////////////////////////////////////////////// + */ + + protected static String tokenTypeDesc(int tt) + { + String desc = mTokenTypes.get(Integer.valueOf(tt)); + return (desc == null) ? ("["+tt+"]") : desc; + } + + protected static void assertTokenType(int expType, int actType) + { + if (expType != actType) { + String expStr = tokenTypeDesc(expType); + String actStr = tokenTypeDesc(actType); + + if (expStr == null) { + expStr = ""+expType; + } + if (actStr == null) { + actStr = ""+actType; + } + fail("Expected token "+expStr+"; got "+actStr+"."); + } + } + + protected static void assertTokenType(int expType, XMLEvent event) + { + if (event == null) { + fail("Expected event of type "+tokenTypeDesc(expType)+"; got `null`"); + } + int actType = event.getEventType(); + if (expType != actType) { + String expStr = tokenTypeDesc(expType); + String actStr = tokenTypeDesc(actType); + + if (expStr == null) { + expStr = ""+expType; + } + if (actStr == null) { + actStr = ""+actType; + } + fail("Expected token "+expStr+"; got "+actStr+"."); + } + } + + /** + * Helper assertion that assert that the String is either null or + * empty (""). + */ + protected static void assertNullOrEmpty(String str) + { + if (str != null && str.length() > 0) { + fail("Expected String to be empty or null; was '"+str+"' (length " + +str.length()+")"); + } + } + + protected static void assertNotNullOrEmpty(String str) + { + if (str == null || str.length() == 0) { + fail("Expected String to be non-empty; got " + +((str == null) ? "NULL" : "\"\"")); + } + } + + /** + * Method that can be used to verify that the current element + * pointed to by the stream reader has no prefix. + */ + protected static void assertNoElemPrefix(XMLStreamReader sr) + throws XMLStreamException + { + String prefix = sr.getPrefix(); + if (prefix != XmlConsts.ELEM_NO_PREFIX) { + fail("Element that does not have a prefix should be indicated with <"+XmlConsts.ELEM_NO_PREFIX+">, not <"+prefix+">"); + } + } + + /** + * Helper method for ensuring that the given return value for + * attribute prefix accessor has returned a value that + * represents "no prefix" value. + *

+ * Current thinking (early 2008) is that empty string is the + * expected value here. + */ + protected static void assertNoAttrPrefix(String attrPrefix) + throws XMLStreamException + { + if (attrPrefix != XmlConsts.ATTR_NO_PREFIX) { + fail("Attribute that does not have a prefix should be indicated with <"+XmlConsts.ATTR_NO_PREFIX+">, not <"+attrPrefix+">"); + } + } + + /** + * Method that can be used to verify that the current element + * pointed to by the stream reader does not belong to a namespace. + */ + protected static void assertElemNotInNamespace(XMLStreamReader sr) + throws XMLStreamException + { + String uri = sr.getNamespaceURI(); + if (uri == null) { + fail("Excepted empty String to indicate \"no namespace\": got null"); + } else if (uri.length() != 0) { + fail("Excepted no (null) namespace URI: got '"+uri+"'"); + } + } + + protected static void assertNoAttrNamespace(String attrNsURI) + throws XMLStreamException + { + if (attrNsURI == null) { + fail("Expected empty String to indicate \"no namespace\" (for attribute): got null"); + } else if (attrNsURI.length() != 0) { + fail("Expected empty String to indicate \"no namespace\" (for attribute): got '"+attrNsURI+"'"); + } + } + + protected static void failStrings(String msg, String exp, String act) + { + // !!! TODO: Indicate position where Strings differ + fail(msg+": expected "+quotedPrintable(exp)+", got " + +quotedPrintable(act)); + } + + /** + * Method that not only gets currently available text from the + * reader, but also checks that its consistenly accessible using + * different (basic) StAX methods. + */ + protected static String getAndVerifyText(XMLStreamReader sr) + throws XMLStreamException + { + /* 05-Apr-2006, TSa: Although getText() is available for DTD + * and ENTITY_REFERENCE, getTextXxx() are not. Thus, can not + * do more checks for those types. + */ + int type = sr.getEventType(); + if (type == ENTITY_REFERENCE || type == DTD) { + return sr.getText(); + } + + int expLen = sr.getTextLength(); + /* Hmmh. It's only ok to return empty text for DTD event... well, + * maybe also for CDATA, since empty CDATA blocks are legal? + */ + /* !!! 01-Sep-2004, TSa: + * note: theoretically, in coalescing mode, it could be possible + * to have empty CDATA section(s) get converted to CHARACTERS, + * which would be empty... may need to enhance this to check that + * mode is not coalescing? Or something + */ + if (type == CHARACTERS) { + assertTrue("Stream reader should never return empty Strings.", (expLen > 0)); + } + String text = sr.getText(); + assertNotNull("getText() should never return null.", text); + assertEquals("Expected text length of "+expLen+", got "+text.length(), + expLen, text.length()); + char[] textChars = sr.getTextCharacters(); + int start = sr.getTextStart(); + String text2 = new String(textChars, start, expLen); + assertEquals(text, text2); + return text; + } + + /* + ////////////////////////////////////////////////// + // Debug/output helpers + ////////////////////////////////////////////////// + */ + + public static void warn(String msg) + { + System.err.println("WARN: "+msg); + } + + @SuppressWarnings("cast") + public static String printable(char ch) + { + if (ch == '\n') { + return "\\n"; + } + if (ch == '\r') { + return "\\r"; + } + if (ch == '\t') { + return "\\t"; + } + if (ch == ' ') { + return "_"; + } + if (ch > 127 || ch < 32) { + StringBuilder sb = new StringBuilder(6); + sb.append("\\u"); + String hex = Integer.toHexString((int)ch); + for (int i = 0, len = 4 - hex.length(); i < len; i++) { + sb.append('0'); + } + sb.append(hex); + return sb.toString(); + } + return null; + } + + @SuppressWarnings("cast") + public static String printableWithSpaces(char ch) + { + if (ch == '\n') { + return "\\n"; + } + if (ch == '\r') { + return "\\r"; + } + if (ch == '\t') { + return "\\t"; + } + if (ch > 127 || ch < 32) { + StringBuffer sb = new StringBuffer(6); + sb.append("\\u"); + String hex = Integer.toHexString((int)ch); + for (int i = 0, len = 4 - hex.length(); i < len; i++) { + sb.append('0'); + } + sb.append(hex); + return sb.toString(); + } + return null; + } + + public static String printable(String str) + { + if (str == null || str.length() == 0) { + return str; + } + + int len = str.length(); + StringBuffer sb = new StringBuffer(len + 64); + for (int i = 0; i < len; ++i) { + char c = str.charAt(i); + String res = printable(c); + if (res == null) { + sb.append(c); + } else { + sb.append(res); + } + } + return sb.toString(); + } + + public static String printableWithSpaces(String str) + { + if (str == null || str.length() == 0) { + return str; + } + + int len = str.length(); + StringBuffer sb = new StringBuffer(len + 64); + for (int i = 0; i < len; ++i) { + char c = str.charAt(i); + String res = printableWithSpaces(c); + if (res == null) { + sb.append(c); + } else { + sb.append(res); + } + } + return sb.toString(); + } + + protected static String quotedPrintable(String str) + { + if (str == null || str.length() == 0) { + return "[0]''"; + } + return "[len: "+str.length()+"] '"+printable(str)+"'"; + } +} diff -Nru libwoodstox-java-4.1.3/src/test/java/wstxtest/cfg/Configs.java libwoodstox-java-5.1.0/src/test/java/wstxtest/cfg/Configs.java --- libwoodstox-java-4.1.3/src/test/java/wstxtest/cfg/Configs.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/wstxtest/cfg/Configs.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,234 @@ +package wstxtest.cfg; + +import javax.xml.stream.XMLInputFactory; + +import com.ctc.wstx.stax.WstxInputFactory; + +public class Configs +{ + private Configs() { } + + // // // Configs for standard Woodstox properties + + public static void addAll(InputConfigIterator it) { + // First standard configs: + it.addConfig(getNamespaceConfig()) + .addConfig(getCoalescingConfig()) + .addConfig(getEntityExpansionConfig()); + + // Then woodstox-specific ones + it.addConfig(getLazyParsingConfig()) + .addConfig(getInputBufferSizeConfig()) + .addConfig(getMinTextSegmentConfig()); + } + + // // // Configs for standard Woodstox properties + + public static InputTestConfig getNamespaceConfig() { + return new NamespaceConfig(); + } + + public static InputTestConfig getCoalescingConfig() { + return new CoalescingConfig(); + } + + public static InputTestConfig getEntityExpansionConfig() { + return new EntityExpansionConfig(); + } + + // // // Configs for Woodstox properties + + public static InputTestConfig getLazyParsingConfig() { + return new LazyParsingConfig(); + } + + public static InputTestConfig getInputBufferSizeConfig() { + return new InputBufferSizeConfig(); + } + + public static InputTestConfig getMinTextSegmentConfig() { + return new TextSegmentConfig(); + } + + /* + ///////////////////////////////////////////////////// + // Config base class + ///////////////////////////////////////////////////// + */ + + abstract static class BaseConfig + implements InputTestConfig + { + final int mTotalCount; + + int mPos; + + BaseConfig(int count) { + mTotalCount = count; + mPos = -1; + } + + @Override + public boolean nextConfig(XMLInputFactory f) { + if (++mPos >= mTotalCount) { + return false; + } + config(f, mPos); + return true; + } + + @Override + public void firstConfig(XMLInputFactory f) { + mPos = 0; + config(f, 0); + } + + @Override + public String getDesc() { + return getDesc(mPos); + } + + @Override + public String toString() { return getDesc(); } + + public static boolean booleanFromInt(int i) { + return (i != 0); + } + + // // // Abstract methods for sub-classes + + public abstract String getDesc(int index); + + public abstract void config(XMLInputFactory f, int index); + } + + /* + ///////////////////////////////////////////////////// + // Actual config classes, std StAX properties + ///////////////////////////////////////////////////// + */ + + public static class NamespaceConfig + extends BaseConfig + { + NamespaceConfig() { + super(2); + } + + @Override + public String getDesc(int index) { + return "namespaces: "+booleanFromInt(index); + } + + @Override + public void config(XMLInputFactory f, int index) { + ((WstxInputFactory) f).getConfig().doSupportNamespaces(booleanFromInt(index)); + } + } + + public static class CoalescingConfig + extends BaseConfig + { + CoalescingConfig() { + super(2); + } + + @Override + public String getDesc(int index) { + return "coalescing: "+booleanFromInt(index); + } + + @Override + public void config(XMLInputFactory f, int index) { + ((WstxInputFactory) f).getConfig().doCoalesceText(booleanFromInt(index)); + } + } + + public static class EntityExpansionConfig + extends BaseConfig + { + EntityExpansionConfig() { + super(2); + } + + @Override + public String getDesc(int index) { + return "expand-entities: "+booleanFromInt(index); + } + + @Override + public void config(XMLInputFactory f, int index) { + ((WstxInputFactory) f).getConfig().doReplaceEntityRefs(booleanFromInt(index)); + } + } + + /* + ///////////////////////////////////////////////////// + // Actual config classes, Woodstox custom properties + ///////////////////////////////////////////////////// + */ + + public static class LazyParsingConfig + extends BaseConfig + { + LazyParsingConfig() { + super(2); + } + + @Override + public String getDesc(int index) { + return "lazy-parsing: "+booleanFromInt(index); + } + + @Override + public void config(XMLInputFactory f, int index) { + ((WstxInputFactory) f).getConfig().doParseLazily(booleanFromInt(index)); + } + } + + public static class InputBufferSizeConfig + extends BaseConfig + { + final static int[] mSizes = new int[] { + 8, 17, 200, 4000 + }; + + InputBufferSizeConfig() { + super(4); + } + + @Override + public String getDesc(int index) { + return "input-buffer: "+mSizes[index]; + } + + @Override + public void config(XMLInputFactory f, int index) { + ((WstxInputFactory) f).getConfig().setInputBufferLength(mSizes[index]); + } + } + + public static class TextSegmentConfig + extends BaseConfig + { + final static int[] mSizes = new int[] { + 6, 23, 100, 4000 + }; + + TextSegmentConfig() { + super(4); + } + + @Override + public String getDesc(int index) { + return "min-text-segment: "+mSizes[index]; + } + + @Override + public void config(XMLInputFactory f, int index) { + ((WstxInputFactory ) f).getConfig().setShortestReportedTextSegment(mSizes[index]); + } + } +} + + diff -Nru libwoodstox-java-4.1.3/src/test/java/wstxtest/cfg/InputConfigIterator.java libwoodstox-java-5.1.0/src/test/java/wstxtest/cfg/InputConfigIterator.java --- libwoodstox-java-4.1.3/src/test/java/wstxtest/cfg/InputConfigIterator.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/wstxtest/cfg/InputConfigIterator.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,108 @@ +package wstxtest.cfg; + +import java.util.*; + +import javax.xml.stream.XMLInputFactory; + +import wstxtest.cfg.InputTestConfig; + +/** + * Class that implements iteration over set of input configuration + * Objects, so that the input factory gets configured to all test + * values for each configuration, and a test method is called once + * per each configuration setting combination + */ +public class InputConfigIterator +{ + final ArrayList mConfigs = new ArrayList(); + + /* + ///////////////////////////////////////////////// + // Life-cycle (constructor, configuration) + ///////////////////////////////////////////////// + */ + + /** + * Index of the iteration step; may be used for debugging + */ + int mIndex; + + public InputConfigIterator() { + } + + public InputConfigIterator addConfig(InputTestConfig cfg) { + mConfigs.add(cfg); + return this; + } + + /* + ///////////////////////////////////////////////// + // Public API + ///////////////////////////////////////////////// + */ + + public void iterate(XMLInputFactory f, InputTestMethod callback) + throws Exception + { + mIndex = 0; + + // First need to initialize the factory with first settings: + final int len = mConfigs.size(); + for (int i = 0; i < len; ++i) { + mConfigs.get(i).nextConfig(f); + } + + // And then the main iteration + while (true) { + // First let's call the test method + callback.runTest(f, this); + + // And then iterate to next configuration setting combo: + int i = 0; + for (; i < len; ++i) { + InputTestConfig cfg = mConfigs.get(i); + // Still more settings for this config? Then let's break: + if (cfg.nextConfig(f)) { + break; + } + // Nope, need to reset this one, and continue for next: + cfg.firstConfig(f); + } + + // Got them all done? + if (i == len) { + break; + } + ++mIndex; + } + } + + public int getIndex() { + return mIndex; + } + + /* + ///////////////////////////////////////////////// + // Overridden standard methods + ///////////////////////////////////////////////// + */ + + @Override + public String toString() + { + int len = mConfigs.size(); + StringBuffer sb = new StringBuffer(16 + (len << 4)); + sb.append('('); + sb.append(len); + sb.append(") "); + + for (int i = 0; i < len; ++i) { + if (i > 0) { + sb.append(", "); + } + sb.append((mConfigs.get(i)).getDesc()); + } + return sb.toString(); + } +} + diff -Nru libwoodstox-java-4.1.3/src/test/java/wstxtest/cfg/InputTestConfig.java libwoodstox-java-5.1.0/src/test/java/wstxtest/cfg/InputTestConfig.java --- libwoodstox-java-4.1.3/src/test/java/wstxtest/cfg/InputTestConfig.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/wstxtest/cfg/InputTestConfig.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,20 @@ +package wstxtest.cfg; + +import javax.xml.stream.XMLInputFactory; + +public interface InputTestConfig +{ + public boolean nextConfig(XMLInputFactory f); + + /** + * Method that will reset iteration state to the initial, ie. state + * before any iteration + */ + public void firstConfig(XMLInputFactory f); + + /** + * @return String that describes current settings this configuration + * Object has (has set when {@link #nextConfig} was called) + */ + public String getDesc(); +} diff -Nru libwoodstox-java-4.1.3/src/test/java/wstxtest/cfg/InputTestMethod.java libwoodstox-java-5.1.0/src/test/java/wstxtest/cfg/InputTestMethod.java --- libwoodstox-java-4.1.3/src/test/java/wstxtest/cfg/InputTestMethod.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/wstxtest/cfg/InputTestMethod.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,9 @@ +package wstxtest.cfg; + +import javax.xml.stream.XMLInputFactory; + +public interface InputTestMethod +{ + public void runTest(XMLInputFactory f, InputConfigIterator it) + throws Exception; +} diff -Nru libwoodstox-java-4.1.3/src/test/java/wstxtest/evt/TestEventReader.java libwoodstox-java-5.1.0/src/test/java/wstxtest/evt/TestEventReader.java --- libwoodstox-java-4.1.3/src/test/java/wstxtest/evt/TestEventReader.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/wstxtest/evt/TestEventReader.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,166 @@ +package wstxtest.evt; + +import java.net.URL; +import java.util.*; + +import javax.xml.stream.*; +import javax.xml.stream.events.DTD; +import javax.xml.stream.events.XMLEvent; + +import org.codehaus.stax2.XMLEventReader2; +import org.codehaus.stax2.evt.NotationDeclaration2; + +import com.ctc.wstx.api.WstxInputProperties; +import com.ctc.wstx.exc.*; + +/** + * Set of unit tests that verify that Woodstox implementation of + * {@link XMLEventReader} does obey additional constraints Woodstox + * guarantees. Specifically: + *

+ */ + +public class TestEventReader + extends wstxtest.BaseWstxTest +{ + public void testEventReaderNonLaziness() + throws XMLStreamException + { + /* We can test this by forcing coalescing to happen, and injecting + * an intentional error after first two segments. In lazy mode, + * coalescing is done not when event type is fetched, but only + * when getText() is called. In non-lazy mode, it's thrown right + * from next() method. Although the exact mechanism is hidden by + * the Event API, what we do see is the type of exception we get -- + * that should be XMLStreamException, NOT a runtime wrapper instead + * of it. + */ + final String XML = + "Some text and & &error;" + ; + XMLEventReader er = getReader(XML, true); + XMLEvent evt = er.nextEvent(); // start document + assertTrue(evt.isStartDocument()); + assertTrue(er.nextEvent().isStartElement()); + + // Ok, and now... + try { + evt = er.nextEvent(); + // should NOT get this far... + fail("Expected an exception for invalid content: coalescing not workig?"); + } catch (WstxParsingException wex) { + // This is correct... parsing exc for entity, hopefully + //System.err.println("GOOD: got "+wex.getClass()+": "+wex); + } catch (WstxException wex2) { + // Unexpected... not a catastrophe, but not right + fail("Should have gotten a non-lazy parsing exception; got non-lazy other wstx exception (why?): "+wex2); + } catch (WstxLazyException lex) { + // Not good... + fail("Should not get a lazy exception via (default) event reader; received: "+lex); + } catch (Throwable t) { + fail("Unexpected excpetion caught: "+t); + } + } + + public void testEventReaderLongSegments() + throws XMLStreamException + { + /* Ok. And here we should just check that we do not get 2 adjacent + * separate Characters event. We can try to trigger this by long + * segment and a set of char entities... + */ + final String XML = + "Some text and & also "quoted" stuff..." + +" not sure If we\r\nreally need anything much more but" + +" let's still make this longer" + +""; + ; + + // Need to disable coalescing though for test to work: + XMLEventReader er = getReader(XML, false); + XMLEvent evt = er.nextEvent(); // start document + assertTrue(evt.isStartDocument()); + assertTrue(er.nextEvent().isStartElement()); + assertTrue(er.nextEvent().isCharacters()); + + evt = er.nextEvent(); + if (evt.isEndElement()) { + ; // good + } else { + if (evt.isCharacters()) { + fail("Even in the absence of coalescing, event reader should not split CHARACTERS segments (Woodstox guarantee): did get 2 adjacent separate Characters events."); + } else { // hmmh. strange + fail("Unexpected event object type after CHARACTERS: "+evt.getClass()); + } + } + } + + /** + * As of Stax 3.0 (Woodstox 4.0+), there is additional info for + * NotationDeclarations (base URI). Let's verify it gets properly + * populated. + */ + public void testDtdNotations() + throws Exception + { + final String URI = "http://test"; + + /* Ok. And here we should just check that we do not get 2 adjacent + * separate Characters event. We can try to trigger this by long + * segment and a set of char entities... + */ + final String XML = "" + +"\n" + +"\n" + +"]>" + +""; + + // Need to disable coalescing though for test to work: + XMLEventReader2 er = getReader(XML, false); + // Need to set Base URI; can do it for factory or instance + er.setProperty(WstxInputProperties.P_BASE_URL, new URL(URI)); + assertTrue(er.nextEvent().isStartDocument()); + XMLEvent evt = er.nextEvent(); // DTD + assertTokenType(DTD, evt.getEventType()); + + DTD dtd = (DTD) evt; + List nots = dtd.getNotations(); + assertEquals(1, nots.size()); + NotationDeclaration2 notDecl = (NotationDeclaration2) nots.get(0); + + assertEquals(URI, notDecl.getBaseURI()); + } + + /* + ////////////////////////////////////////////////////// + // Internal methods + ////////////////////////////////////////////////////// + */ + + private XMLEventReader2 getReader(String contents, boolean coalescing) + throws XMLStreamException + { + XMLInputFactory f = getInputFactory(); + setNamespaceAware(f, true); + setCoalescing(f, coalescing); + setLazyParsing(f, true); // shouldn't have effect for event readers! + setMinTextSegment(f, 8); // likewise + return constructEventReader(f, contents); + } +} + + diff -Nru libwoodstox-java-4.1.3/src/test/java/wstxtest/io/TestUTF8Reader.java libwoodstox-java-5.1.0/src/test/java/wstxtest/io/TestUTF8Reader.java --- libwoodstox-java-4.1.3/src/test/java/wstxtest/io/TestUTF8Reader.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/wstxtest/io/TestUTF8Reader.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,44 @@ +package wstxtest.io; + +import java.io.*; + +import junit.framework.TestCase; + +import com.ctc.wstx.api.ReaderConfig; +import com.ctc.wstx.io.UTF8Reader; + +/** + * Unit test created to verify fix to + * WSTX-143. + * + * @author Matt Gormley + */ +public class TestUTF8Reader extends TestCase +{ + @SuppressWarnings("resource") + public void testDelAtBufferBoundary() throws IOException + { + final int BYTE_BUFFER_SIZE = 4; + final int CHAR_BUFFER_SIZE = 1 + BYTE_BUFFER_SIZE; + final int INPUT_SIZE = 4 * BYTE_BUFFER_SIZE; // could be of arbitrary size + final byte CHAR_FILLER = 32; // doesn't even matter, just need an ascii char + final byte CHAR_DEL = 127; + + // Create input that will cause the array index out of bounds exception + byte[] inputBytes = new byte[INPUT_SIZE]; + for (int i=0; i < inputBytes.length; i++) { + inputBytes[i] = CHAR_FILLER; + } + inputBytes[BYTE_BUFFER_SIZE - 1] = CHAR_DEL; + InputStream in = new ByteArrayInputStream(inputBytes); + + // Create the UTF8Reader + ReaderConfig cfg = ReaderConfig.createFullDefaults(); + byte[] byteBuffer = new byte[BYTE_BUFFER_SIZE]; + UTF8Reader reader = new UTF8Reader(cfg,in, byteBuffer, 0, 0, false); + + // Run the reader on the input + char[] charBuffer = new char[CHAR_BUFFER_SIZE]; + reader.read(charBuffer, 0, charBuffer.length); + } +} diff -Nru libwoodstox-java-4.1.3/src/test/java/wstxtest/msv/test-message.xml libwoodstox-java-5.1.0/src/test/java/wstxtest/msv/test-message.xml --- libwoodstox-java-4.1.3/src/test/java/wstxtest/msv/test-message.xml 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/wstxtest/msv/test-message.xml 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,8 @@ + + + + + Here is text + + + \ No newline at end of file diff -Nru libwoodstox-java-4.1.3/src/test/java/wstxtest/msv/TestW3CSchema.java libwoodstox-java-5.1.0/src/test/java/wstxtest/msv/TestW3CSchema.java --- libwoodstox-java-4.1.3/src/test/java/wstxtest/msv/TestW3CSchema.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/wstxtest/msv/TestW3CSchema.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,365 @@ +package wstxtest.msv; + +import javax.xml.stream.*; + +import org.codehaus.stax2.*; +import org.codehaus.stax2.validation.*; + +import wstxtest.vstream.BaseValidationTest; + +/** + * This is a simple base-line "smoke test" that checks that W3C Schema + * validation works at least minimally. + */ +public class TestW3CSchema + extends BaseValidationTest +{ + /** + * Sample schema, using sample 'personal.xsd' found from the web + */ + final static String SIMPLE_NON_NS_SCHEMA = "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + "\n" + "\n"; + + final static String SIMPLE_XML = "" + + "" + " " + + "FamilyFred" + " " + + " " + " " + + " " + + " BlowJoe" + + " " + " " + " " + ""; + + /** + * Test validation against a simple document valid according to a very + * simple W3C schema. + */ + public void testSimpleNonNs() throws XMLStreamException + { + XMLValidationSchema schema = parseW3CSchema(SIMPLE_NON_NS_SCHEMA); + XMLStreamReader2 sr = getReader(SIMPLE_XML); + sr.validateAgainst(schema); + + try { + assertTokenType(START_ELEMENT, sr.next()); + assertEquals("personnel", sr.getLocalName()); + + while (sr.hasNext()) { + /* int type = */sr.next(); + } + } catch (XMLValidationException vex) { + fail("Did not expect validation exception, got: " + vex); + } + assertTokenType(END_DOCUMENT, sr.getEventType()); + } + + public void testSimplePartialNonNs() throws XMLStreamException + { + XMLValidationSchema schema = parseW3CSchema(SIMPLE_NON_NS_SCHEMA); + XMLStreamReader2 sr = getReader(SIMPLE_XML); + + assertTokenType(START_ELEMENT, sr.next()); + assertEquals("personnel", sr.getLocalName()); + sr.validateAgainst(schema); + try { + assertTokenType(START_ELEMENT, sr.next()); + assertEquals("person", sr.getLocalName()); + while (sr.hasNext()) { + /* int type = */sr.next(); + } + } catch (XMLValidationException vex) { + fail("Did not expect validation exception, got: " + vex); + } + assertTokenType(END_DOCUMENT, sr.getEventType()); + } + + /** + * Test validation of a simple document that is invalid according to the + * simple test schema. + */ + public void testSimpleNonNsMissingId() throws XMLStreamException + { + XMLValidationSchema schema = parseW3CSchema(SIMPLE_NON_NS_SCHEMA); + String XML = "" + + "FG" + + ""; + verifyFailure(XML, schema, "missing id attribute", + "is missing \"id\" attribute"); + } + + public void testSimpleNonNsUndefinedId() throws XMLStreamException + { + XMLValidationSchema schema = parseW3CSchema(SIMPLE_NON_NS_SCHEMA); + String XML = "" + + "FG" + + ""; + verifyFailure(XML, schema, "undefined referenced id ('m3')", + "Undefined ID 'm3'"); + } + + public void testSimpleDataTypes() throws XMLStreamException + { + // Another sample schema, from + String SCHEMA = "\n" + + "\n" + + " \n" + + " \n" + + " " + + " " + + " " + + " " + + "" + + ""; + + XMLValidationSchema schema = parseW3CSchema(SCHEMA); + + // First, valid doc: + String XML = "3 \r\n4.05"; + XMLStreamReader2 sr = getReader(XML); + sr.validateAgainst(schema); + + try { + assertTokenType(START_ELEMENT, sr.next()); + assertEquals("item", sr.getLocalName()); + + assertTokenType(START_ELEMENT, sr.next()); + assertEquals("quantity", sr.getLocalName()); + String str = sr.getElementText(); + assertEquals("3", str.trim()); + + assertTokenType(START_ELEMENT, sr.next()); + assertEquals("price", sr.getLocalName()); + str = sr.getElementText(); + assertEquals("4.05", str.trim()); + + assertTokenType(END_ELEMENT, sr.next()); + assertTokenType(END_DOCUMENT, sr.next()); + } catch (XMLValidationException vex) { + fail("Did not expect validation exception, got: " + vex); + } + sr.close(); + + // Then invalid (wrong type for value) + XML = "34b1.00"; + sr.validateAgainst(schema); + verifyFailure(XML, schema, "invalid 'positive integer' datatype", + "does not satisfy the \"positiveInteger\""); + sr.close(); + + // Another invalid, empty value + XML = " 1.00"; + sr.validateAgainst(schema); + // 12-Nov-2008, TSa: still having MSV bug here, need to suppress failure + verifyFailure(XML, schema, "invalid (missing) positive integer value", + "does not satisfy the \"positiveInteger\"", false); + sr.close(); + + // Another invalid, missing value + XML = "1.00"; + sr.validateAgainst(schema); + // 12-Nov-2008, TSa: still having MSV bug here, need to suppress failure + verifyFailure(XML, schema, "invalid (missing) positive integer value", + "does not satisfy the \"positiveInteger\"", false); + sr.close(); + } + + public void testSimpleText() throws XMLStreamException + { + String SCHEMA = "\n" + + "\n" + + "" + + ""; + XMLValidationSchema schema = parseW3CSchema(SCHEMA); + + // First, 3 valid docs: + String XML = "xyz"; + XMLStreamReader2 sr = getReader(XML); + sr.validateAgainst(schema); + streamThrough(sr); + sr.close(); + + XML = ""; + sr = getReader(XML); + sr.validateAgainst(schema); + streamThrough(sr); + sr.close(); + + XML = ""; + sr = getReader(XML); + sr.validateAgainst(schema); + streamThrough(sr); + sr.close(); + + // Then invalid? + XML = ""; + sr = getReader(XML); + sr.validateAgainst(schema); + verifyFailure(XML, schema, "should warn about wrong root element", + "tag name \"foobar\" is not allowed", false); + } + + /** + * Test for reproducing [WSTX-191] + */ + public void testConstrainedText() throws XMLStreamException + { + String SCHEMA = "\n" + + "\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + " \n" + + " \n" + "\n"; + + XMLValidationSchema schema = parseW3CSchema(SCHEMA); + + // first cases where there is text, and 1 to 5 descs + _testValidDesc(schema, "Du Texte"); + _testValidDesc( + schema, + "123"); + _testValidDesc(schema, + ""); + _testValidDesc(schema, + "??"); + _testValidDesc(schema, ""); + _testValidDesc(schema, ""); + _testValidDesc(schema, ""); + } + + private void _testValidDesc(XMLValidationSchema schema, String descSnippet) throws XMLStreamException + { + // These should all be valid according to the schema + String XML = "" + + descSnippet + ""; + XMLStreamReader2 sr = getReader(XML); + sr.validateAgainst(schema); + streamThrough(sr); + sr.close(); + } + + public void testValidationHandler() throws XMLStreamException + { + String SCHEMA = "\n" + + "\n" + + "" + + ""; + XMLValidationSchema schema = parseW3CSchema(SCHEMA); + + // Then invalid? + String XML = ""; + XMLStreamReader2 sr = getReader(XML); + sr.setValidationProblemHandler(new ValidationProblemHandler() { + @Override + public void reportProblem(XMLValidationProblem problem) + throws XMLValidationException { + throw new LocalValidationError(problem); + } + }); + sr.validateAgainst(schema); + boolean threw = false; + try { + while (sr.hasNext()) { + /* int type = */sr.next(); + } + } catch (LocalValidationError lve) { + threw = true; + } + assertTrue(threw); + } + + /* + /////////////////////////////////////////////////////////////////////// + // Helper methods + /////////////////////////////////////////////////////////////////////// + */ + + XMLStreamReader2 getReader(String contents) throws XMLStreamException + { + XMLInputFactory2 f = getInputFactory(); + setValidating(f, false); + return constructStreamReader(f, contents); + } + + /* + /////////////////////////////////////////////////////////////////////// + // Helper classes + /////////////////////////////////////////////////////////////////////// + */ + + public static class LocalValidationError extends RuntimeException + { + private static final long serialVersionUID = 1L; + + protected XMLValidationProblem problem; + + LocalValidationError(XMLValidationProblem problem) { + this.problem = problem; + } + + public XMLValidationProblem getProblem() { + return problem; + } + } +} diff -Nru libwoodstox-java-4.1.3/src/test/java/wstxtest/msv/TestW3CSchemaTypes.java libwoodstox-java-5.1.0/src/test/java/wstxtest/msv/TestW3CSchemaTypes.java --- libwoodstox-java-4.1.3/src/test/java/wstxtest/msv/TestW3CSchemaTypes.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/wstxtest/msv/TestW3CSchemaTypes.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,97 @@ +package wstxtest.msv; + +import javax.xml.stream.*; + +import org.codehaus.stax2.*; +import org.codehaus.stax2.validation.*; + +import wstxtest.vstream.BaseValidationTest; + +import java.io.StringWriter; + +/** + * Simple testing of W3C Schema datatypes. + * Added to test [WSTX-210]. + * + * @author Tatu Saloranta + */ +public class TestW3CSchemaTypes + extends BaseValidationTest +{ + final static String SCHEMA_INT = + "\n" + +"" + +"\n" + ; + + final static String SCHEMA_FLOAT = + "\n" + +"" + +"\n" + ; + + // // // First 'int' datatype + + public void testSimpleValidInt() throws Exception + { + XMLValidationSchema schema = parseW3CSchema(SCHEMA_INT); + XMLStreamReader2 sr = getReader("129"); + sr.validateAgainst(schema); + streamThrough(sr); + } + + public void testSimpleInvalidInt() throws Exception + { + XMLValidationSchema schema = parseW3CSchema(SCHEMA_INT); + verifyFailure("abc", schema, "invalid 'int' value", + "does not satisfy the \"int\" type"); + } + + // // // Then 'float' datatype + + public void testSimpleValidFloat() throws Exception + { + XMLValidationSchema schema = parseW3CSchema(SCHEMA_FLOAT); + XMLStreamReader2 sr = getReader("1.00"); + sr.validateAgainst(schema); + streamThrough(sr); + } + + public void testSimpleInvalidFloat() throws Exception + { + XMLValidationSchema schema = parseW3CSchema(SCHEMA_FLOAT); + verifyFailure("abc", schema, "invalid 'float' value", + "does not satisfy the \"float\" type"); + } + + // // // Writing + + public void testValdiationWhenWritingCharactersFromArray() throws Exception + { + XMLValidationSchema schema = parseW3CSchema(SCHEMA_INT); + + XMLOutputFactory2 f = getOutputFactory(); + XMLStreamWriter2 sw = (XMLStreamWriter2)f.createXMLStreamWriter(new StringWriter()); + sw.validateAgainst(schema); + + String xml = "129"; + + sw.writeStartElement("price"); + sw.writeCharacters(xml.toCharArray(), xml.indexOf("1"), 3); + sw.writeEndElement(); + sw.flush(); + } + + /* + /////////////////////////////////////////////////////////////////////// + // Helper + /////////////////////////////////////////////////////////////////////// + */ + + XMLStreamReader2 getReader(String contents) throws XMLStreamException + { + XMLInputFactory2 f = getInputFactory(); + setValidating(f, false); + return constructStreamReader(f, contents); + } +} diff -Nru libwoodstox-java-4.1.3/src/test/java/wstxtest/msv/TestWsdlValidation.java libwoodstox-java-5.1.0/src/test/java/wstxtest/msv/TestWsdlValidation.java --- libwoodstox-java-4.1.3/src/test/java/wstxtest/msv/TestWsdlValidation.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/wstxtest/msv/TestWsdlValidation.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,112 @@ +/** + * + */ +package wstxtest.msv; + +import java.io.IOException; +import java.net.URL; + +import javax.xml.namespace.QName; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.SAXParserFactory; +import javax.xml.stream.XMLStreamConstants; +import javax.xml.transform.dom.DOMSource; + +import org.codehaus.stax2.XMLInputFactory2; +import org.codehaus.stax2.XMLStreamReader2; +import org.w3c.dom.Document; +import org.w3c.dom.ls.LSResourceResolver; +import org.xml.sax.InputSource; +import org.xml.sax.Locator; +import org.xml.sax.SAXException; + +import stax2.BaseStax2Test; + +import com.ctc.wstx.msv.W3CSchema; +import com.sun.msv.grammar.xmlschema.XMLSchemaGrammar; +import com.sun.msv.reader.GrammarReaderController2; +import com.sun.msv.reader.xmlschema.WSDLSchemaReader; + +public class TestWsdlValidation extends BaseStax2Test { + + private static class LocalController implements GrammarReaderController2 { + + @Override + public LSResourceResolver getLSResourceResolver() { + return null; + } + + @Override + public void error(Locator[] locs, String errorMessage, Exception nestedException) { + StringBuffer errors = new StringBuffer(); + for (Locator loc : locs) { + errors.append("in " + loc.getSystemId() + " " + loc.getLineNumber() + ":" + + loc.getColumnNumber()); + } + throw new RuntimeException(errors.toString(), nestedException); + } + + @Override + public void warning(Locator[] locs, String errorMessage) { + StringBuffer errors = new StringBuffer(); + for (Locator loc : locs) { + errors.append("in " + loc.getSystemId() + " " + loc.getLineNumber() + ":" + + loc.getColumnNumber()); + } + // no warning allowed. + throw new RuntimeException("warning: " + errors.toString()); + } + + @Override + public InputSource resolveEntity(String publicId, String systemId) throws SAXException, IOException { + return null; + } + } + + private XMLSchemaGrammar wsdlgrammar; + private W3CSchema schema; + + @Override + protected void setUp() throws Exception { + super.setUp(); + DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance(); + documentBuilderFactory.setNamespaceAware(true); + DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder(); + URL wsdlUri = getClass().getResource("test.wsdl"); + Document wsdl = documentBuilder.parse(wsdlUri.openStream()); + String wsdlSystemId = wsdlUri.toExternalForm(); + DOMSource source = new DOMSource(wsdl); + source.setSystemId(wsdlSystemId); + + LocalController controller = new LocalController(); + SAXParserFactory factory = SAXParserFactory.newInstance(); + factory.setNamespaceAware(true); + wsdlgrammar = WSDLSchemaReader.read(source, factory, controller); + schema = new W3CSchema(wsdlgrammar); + } + + public void testWsdlValidation() throws Exception { + String runMe = System.getProperty("testWsdlValidation"); + if (runMe == null || "".equals(runMe)) { + return; + } + XMLInputFactory2 factory = getInputFactory(); + XMLStreamReader2 reader = (XMLStreamReader2) factory.createXMLStreamReader(getClass().getResourceAsStream("test-message.xml"), "utf-8"); + QName msgQName = new QName("http://server.hw.demo/", "sayHi"); + while (true) { + int what = reader.nextTag(); + if (what == XMLStreamConstants.START_ELEMENT) { + if (reader.getName().equals(msgQName)) { + reader.validateAgainst(schema); + } + } else if (what == XMLStreamConstants.END_ELEMENT) { + if (reader.getName().equals(msgQName)) { + reader.stopValidatingAgainst(schema); + } + } else if (what == XMLStreamConstants.END_DOCUMENT) { + break; + } + } + } +} diff -Nru libwoodstox-java-4.1.3/src/test/java/wstxtest/osgi/TestBasic.java libwoodstox-java-5.1.0/src/test/java/wstxtest/osgi/TestBasic.java --- libwoodstox-java-4.1.3/src/test/java/wstxtest/osgi/TestBasic.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/wstxtest/osgi/TestBasic.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,43 @@ +package wstxtest.osgi; + +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Method; +import java.lang.reflect.Proxy; + +import wstxtest.BaseWstxTest; + +import org.osgi.framework.*; + +import com.ctc.wstx.osgi.*; + +public class TestBasic + extends BaseWstxTest +{ + public void testBundleActivation() + { + // Hmmh. Context is a beastly class... let's just proxy it + InvocationHandler h = new ContextHandler(); + BundleContext ctxt = (BundleContext) Proxy.newProxyInstance(BundleContext.class.getClassLoader(), new Class[] { BundleContext.class }, h); + WstxBundleActivator act = new WstxBundleActivator(); + + // won't prove much... but at least there's noo fundamental flaw: + act.start(ctxt); + } + + /* + ////////////////////////////////////////// + // Helper classes + ////////////////////////////////////////// + */ + + final static class ContextHandler + implements InvocationHandler + { + @Override + public Object invoke(Object proxy, Method method, Object[] args) + { + // !!! TODO: make do something... + return null; + } + } +} diff -Nru libwoodstox-java-4.1.3/src/test/java/wstxtest/sax/TestBasicSax.java libwoodstox-java-5.1.0/src/test/java/wstxtest/sax/TestBasicSax.java --- libwoodstox-java-4.1.3/src/test/java/wstxtest/sax/TestBasicSax.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/wstxtest/sax/TestBasicSax.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,140 @@ +package wstxtest.sax; + +import java.io.*; + +import javax.xml.parsers.SAXParser; +import javax.xml.parsers.SAXParserFactory; + +import org.xml.sax.*; +import org.xml.sax.helpers.DefaultHandler; + +import com.ctc.wstx.sax.*; + +import wstxtest.BaseWstxTest; + +/** + * Simple unit tests to verify that most fundamental parsing functionality + * works via Woodstox SAX implementation. + */ +public class TestBasicSax + extends BaseWstxTest +{ + final static String XML = "\n" + +"" + +"" + +"rock'n "; + + public void testSimpleNs() + throws Exception + { + doTestSimple(true, false); + doTestSimple(true, true); + } + + public void testSimpleNonNs() + throws Exception + { + doTestSimple(false, false); + doTestSimple(false, true); + } + + /** + * Test for [WSTX-226]: ensure that given encoding is used + * as specified + */ + public void testEncoding() throws Exception + { + SAXParser parser = new WstxSAXParser(); + String encoding = "ISO-8859-1"; + String text = "mit hei\u00DFem Bem\u00FCh'n"; + byte[] content = ("" + text + "").getBytes(encoding); + InputSource is = new InputSource(new ByteArrayInputStream(content)); + is.setEncoding(encoding); + TextExtractor handler = new TextExtractor(); + parser.parse(is, handler); + assertEquals(text, handler.getText()); + + // And second time around, with declaration + /* 02-Jan-2010, tatu: Looks like we can NOT reuse parser... why? + * Is that a bug or unsupported way to use it. Hmmh. Need to check. + */ + parser = new WstxSAXParser(); + content = ("" + text + "").getBytes(encoding); + is = new InputSource(new ByteArrayInputStream(content)); + is.setEncoding(encoding); + handler = new TextExtractor(); + parser.parse(is, handler); + assertEquals(text, handler.getText()); + } + + /* + //////////////////////////////////////////////////// + // Helper methods + //////////////////////////////////////////////////// + */ + + public void doTestSimple(boolean ns, boolean useReader) + throws Exception + { + // no need to test JAXP introspection... + SAXParserFactory spf = new WstxSAXParserFactory(); + spf.setNamespaceAware(ns); + SAXParser sp = spf.newSAXParser(); + MyHandler h = new MyHandler(); + + InputSource src; + + if (useReader) { + src = new InputSource(new StringReader(XML)); + } else { + src = new InputSource(new ByteArrayInputStream(XML.getBytes("UTF-8"))); + } + + sp.parse(src, h); + assertEquals(2, h._elems); + assertEquals(1, h._attrs); + assertEquals(11, h._charCount); + } + + static class TextExtractor extends DefaultHandler { + private final StringBuffer buffer = new StringBuffer(); + @Override + public void characters(char[] ch, int start, int length) throws SAXException { + buffer.append(ch, start, length); + } + + public String getText() { + return buffer.toString(); + } + } + + final static class MyHandler + extends DefaultHandler + { + public int _elems, _attrs; + + public int _charCount; + + @Override + public void characters(char[] ch, int start, int length) { + _charCount += length; + } + + @Override + public void startElement(String uri, String ln, String qname, + Attributes a) + { + ++_elems; + int ac = a.getLength(); + _attrs += ac; + + for (int i = 0; i < ac; ++i) { + a.getLocalName(i); + a.getQName(i); + a.getURI(i); + a.getValue(i); + a.getType(i); + } + } + } +} diff -Nru libwoodstox-java-4.1.3/src/test/java/wstxtest/sax/TestEntityResolver.java libwoodstox-java-5.1.0/src/test/java/wstxtest/sax/TestEntityResolver.java --- libwoodstox-java-4.1.3/src/test/java/wstxtest/sax/TestEntityResolver.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/wstxtest/sax/TestEntityResolver.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,75 @@ +package wstxtest.sax; + +import java.io.*; + +import javax.xml.parsers.SAXParser; +import javax.xml.parsers.SAXParserFactory; + +import org.xml.sax.*; +import org.xml.sax.helpers.DefaultHandler; + +import com.ctc.wstx.sax.WstxSAXParserFactory; + +import wstxtest.BaseWstxTest; + +/** + * Simple unit tests to verify that most fundamental parsing functionality + * works via Woodstox SAX implementation. + */ +public class TestEntityResolver + extends BaseWstxTest +{ + public void testWithDummyExtSubset() + throws Exception + { + final String XML = + "\n" + +"" + ; + + SAXParserFactory spf = new WstxSAXParserFactory(); + spf.setNamespaceAware(true); + SAXParser sp = spf.newSAXParser(); + DefaultHandler h = new DefaultHandler(); + + /* First: let's verify that we get an exception for + * unresolved reference... + */ + try { + sp.parse(new InputSource(new StringReader(XML)), h); + } catch (SAXException e) { + verifyException(e, "No such file or directory"); + } + + // And then with dummy resolver; should work ok now + sp = spf.newSAXParser(); + sp.getXMLReader().setEntityResolver(new MyResolver(" ")); + h = new DefaultHandler(); + try { + sp.parse(new InputSource(new StringReader(XML)), h); + } catch (SAXException e) { + fail("Should not have failed with entity resolver, got ("+e.getClass()+"): "+e.getMessage()); + } + } + + /* + /////////////////////////////////////////////////////// + // Helper classes + /////////////////////////////////////////////////////// + */ + + static class MyResolver + implements EntityResolver + { + final String mContents; + + public MyResolver(String c) { + mContents = c; + } + + @Override + public InputSource resolveEntity(String publicId, String systemId) { + return new InputSource(new StringReader(mContents)); + } + } +} diff -Nru libwoodstox-java-4.1.3/src/test/java/wstxtest/stream/BaseStreamTest.java libwoodstox-java-5.1.0/src/test/java/wstxtest/stream/BaseStreamTest.java --- libwoodstox-java-4.1.3/src/test/java/wstxtest/stream/BaseStreamTest.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/wstxtest/stream/BaseStreamTest.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,474 @@ +package wstxtest.stream; + +import java.io.*; +import java.util.Random; + +import javax.xml.stream.*; + +import org.codehaus.stax2.XMLStreamReader2; + +import wstxtest.BaseWstxTest; +import wstxtest.cfg.*; + +public abstract class BaseStreamTest + extends BaseWstxTest +{ + protected BaseStreamTest() { super(); } + + /* + /////////////////////////////////////////////////////////// + // "Special" accessors + /////////////////////////////////////////////////////////// + */ + + /** + * Method that not only gets currently available text from the + * reader, but also checks that its consistenly accessible using + * different StAX methods. + */ + protected static String getAndVerifyText(XMLStreamReader sr) + throws XMLStreamException + { + int expLen = sr.getTextLength(); + // Hmmh. It's only ok to return empty text for DTD event + if (sr.getEventType() != DTD) { + assertTrue("Stream reader should never return empty Strings.", (expLen > 0)); + } + String text = sr.getText(); + assertNotNull("getText() should never return null.", text); + assertEquals(expLen, text.length()); + char[] textChars = sr.getTextCharacters(); + int start = sr.getTextStart(); + String text2 = new String(textChars, start, expLen); + assertEquals(text, text2); + return text; + } + + protected static String getStreamingText(XMLStreamReader sr) + throws IOException, XMLStreamException + { + StringWriter sw = new StringWriter(); + ((XMLStreamReader2) sr).getText(sw, false); + return sw.toString(); + } + + /* + /////////////////////////////////////////////////////////// + // Higher-level test methods + /////////////////////////////////////////////////////////// + */ + + protected int streamAndCheck(XMLInputFactory f, InputConfigIterator it, + String input, String expOutput, + boolean reallyStreaming) + throws IOException, XMLStreamException, UnsupportedEncodingException + { + int count = 0; + + // Let's loop couple of input methods + for (int m = 0; m < 3; ++m) { + XMLStreamReader sr; + + /* Contents shouldn't really contain anything + * outside ISO-Latin; however, detection may + * be tricky.. so let's just test with UTF-8, + * for now? + */ + + switch (m) { + case 0: // simple StringReader: + sr = constructStreamReader(f, input); + break; + case 1: // via InputStream and auto-detection + { + ByteArrayInputStream bin = new ByteArrayInputStream + (input.getBytes("UTF-8")); + sr = f.createXMLStreamReader(bin); + } + break; + case 2: // explicit UTF-8 stream + { + ByteArrayInputStream bin = new ByteArrayInputStream + (input.getBytes("UTF-8")); + Reader br = new InputStreamReader(bin, "UTF-8"); + sr = f.createXMLStreamReader(br); + } + break; + default: throw new Error("Internal error"); + } + + count += streamAndCheck(sr, it, input, expOutput, + reallyStreaming); + } + return count; + } + + protected int streamAndCheck(XMLStreamReader sr, InputConfigIterator it, + String input, String expOutput, + boolean reallyStreaming) + throws IOException, XMLStreamException + { + int type; + + /* Let's ignore leading white space and DTD; and stop on encountering + * something else + */ + do { + type = sr.next(); + } while ((type == SPACE) || (type == DTD)); + + StringBuffer act = new StringBuffer(1000); + int count = 0; + + do { + count += type; + if (type == START_ELEMENT || type == END_ELEMENT) { + act.append('<'); + if (type == END_ELEMENT) { + act.append('/'); + } + String prefix = sr.getPrefix(); + if (prefix != null && prefix.length() > 0) { + act.append(prefix); + act.append(':'); + } + act.append(sr.getLocalName()); + act.append('>'); + } else if (type == CHARACTERS || type == SPACE || type == CDATA) { + // No quoting, doesn't have to result in legal XML + if (reallyStreaming) { + StringWriter sw = new StringWriter(); + // important: false to indicate 'don't preserve contents' + int gotLen = ((XMLStreamReader2)sr).getText(sw, false); + String text = sw.toString(); + int textLen = text.length(); + if (textLen != gotLen) { + if (text.length() > 60) { + text = text.substring(0, 30) + "<...>" + text.substring(textLen-30); + } + assertEquals("Incorrect return value from streaming getText() for "+ + tokenTypeDesc(type)+" [string '"+text+"']", textLen, gotLen); + } + act.append(text); + } else { + act.append(sr.getText()); + } + } else if (type == COMMENT) { + act.append(""); + } else if (type == PROCESSING_INSTRUCTION) { + act.append(""); + } else if (type == ENTITY_REFERENCE) { + act.append(sr.getText()); + } else { + fail("Unexpected event type "+tokenTypeDesc(type)); + } + } while ((type = sr.next()) != END_DOCUMENT); + + String result = act.toString(); + if (!result.equals(expOutput)) { + String desc = it.toString(); + int round = it.getIndex(); + + // uncomment for debugging: + + /* + System.err.println("FAIL: round "+round+" ["+desc+"]"); + System.err.println("Input: '"+input.toString()+"'"); + System.err.println("Exp: '"+expOutput.toString()+"'"); + System.err.println("Actual: '"+act.toString()+"'"); + */ + + fail("Failure with '"+desc+"' (round #"+round+"):\n
" + +"Input : {"+printableWithSpaces(input)+"}\n
" + +"Output: {"+printableWithSpaces(result)+"}\n
" + +"Exp. : {"+printableWithSpaces(expOutput)+"}\n
"); + } + + return count; + } + + protected int streamAndSkip(XMLInputFactory f, InputConfigIterator it, + String input) + throws XMLStreamException, UnsupportedEncodingException + { + int count = 0; + + // Let's loop couple of input methods + for (int m = 0; m < 3; ++m) { + XMLStreamReader sr; + + switch (m) { + case 0: // simple StringReader: + sr = constructStreamReader(f, input); + break; + case 1: // via InputStream and auto-detection + { + ByteArrayInputStream bin = new ByteArrayInputStream + (input.getBytes("UTF-8")); + sr = f.createXMLStreamReader(bin); + } + break; + case 2: // explicit UTF-8 stream + { + ByteArrayInputStream bin = new ByteArrayInputStream + (input.getBytes("UTF-8")); + Reader br = new InputStreamReader(bin, "UTF-8"); + sr = f.createXMLStreamReader(br); + } + break; + default: throw new Error("Internal error"); + } + + count += streamAndSkip(sr); + } + return count; + } + + protected int streamAndSkip(XMLStreamReader sr) + throws XMLStreamException + { + int count = 0; + + while (sr.hasNext()) { + count += sr.next(); + } + return count; + } + + protected void generateData(Random r, StringBuffer input, + StringBuffer output, boolean autoEnt) + { + final String PREAMBLE = + "" + +"\n" + +" \n" + +" \n" + +"]>"; + + /* Ok; template will use '*' chars as placeholders, to be replaced + * by pseudo-randomly selected choices. + */ + final String TEMPLATE = + "" + + // Short one for trouble shooting: + /* + +" * Text ****\n" + */ + + // Real one for regression testing: + +" * Text ****\n" + +"** * xx\n" + +"Text ******\n" + +"*......**" + +"******" + +"*** ****" + +"* ***" + +"a*b*c*d*e*f*g*h*i*j*k" + +"
" + ; + + input.append(TEMPLATE); + output.append(TEMPLATE); + + for (int i = TEMPLATE.length(); --i >= 0; ) { + char c = TEMPLATE.charAt(i); + + if (c == '*') { + replaceEntity(input, output, autoEnt, r, i); + } + } + + // Let's also insert preamble into input now + input.insert(0, PREAMBLE); + } + + protected void replaceEntity(StringBuffer input, StringBuffer output, + boolean autoEnt, + Random r, int index) + { + String in, out; + + switch (Math.abs(r.nextInt()) % 6) { + case 0: // Let's use one of pre-def'd entities: + switch (Math.abs(r.nextInt()) % 5) { + case 0: + in = "&"; out = "&"; + break; + case 1: + in = "'"; out = "'"; + break; + case 2: + in = "<"; out = "<"; + break; + case 3: + in = ">"; out = ">"; + break; + case 4: + in = """; out = "\""; + break; + default: throw new Error("Internal error!"); + } + break; + case 1: // How about some CDATA? + switch (Math.abs(r.nextInt()) % 5) { + case 0: + in = "]]>"; + out = "]] >"; + break; + case 1: + in = ""; + out = "xyz&abc"; + break; + case 2: + in = ""; + out = " "; + break; + case 3: + in = ""; + out = ""; + break; + case 4: + in = ""; + out = " \nxyz"; + break; + default: throw new Error("Internal error!"); + } + + case 2: // and COMMENTS + switch (Math.abs(r.nextInt()) % 5) { + case 0: + in = ""; + out = ""; + break; + case 1: + in = out = ""; + break; + case 2: + in = out = ""; + break; + case 3: + //in = out = ""; + in = out = ""; + break; + case 4: + in = out = ""; + break; + default: throw new Error("Internal error!"); + } + break; + case 3: // Char entities? + switch (Math.abs(r.nextInt()) % 4) { + case 0: + in = "#"; + out = "#"; + break; + case 1: + in = "$"; + out = "$"; + break; + case 2: + in = "©"; // above US-Ascii, copyright symbol + out = "\u00A9"; + break; + case 3: + in = "Ä"; // Upper-case a with umlauts + out = "\u00C4"; + break; + default: throw new Error("Internal error!"); + } + break; + case 4: // Full entities + switch (Math.abs(r.nextInt()) % 3) { + case 0: + in = "&ent1;"; + out = "ent1Value"; + break; + case 1: + in = "&x;"; + out = "Y"; + break; + case 2: + in = "&both;"; + out = autoEnt ? "ent1ValueY" : "&ent1;&x;"; + break; + default: throw new Error("Internal error!"); + } + break; + + case 5: // Plain text, ISO-Latin chars: + in = out = "(\u00A9)"; // copyright symbol + break; + + case 6: // Proc. instr? + switch (Math.abs(r.nextInt()) % 5) { + case 0: + in = out = ""; + break; + case 1: + in = out = ""; + break; + case 2: + in = out = ""; + break; + case 3: + in = out = "? ?>"; + break; + case 4: + in = out = "two
\r\r\r"; + break; + default: throw new Error("Internal error!"); + } + + default: + throw new Error("Internal error!"); + } + input.replace(index, index+1, in); + output.replace(index, index+1, out); + } + + /** + * Method that will normalize all unnormalized LFs (\r, \r\n) into + * normalized one (\n). + */ + protected void normalizeLFs(StringBuffer input) + { + int len = input.length(); + for (int i = len; --i >= 0; ) { + char c = input.charAt(i); + if (c == '\r') { + if (i < (len-1) && input.charAt(i+1) == '\n') { + input.deleteCharAt(i); + } else { + input.setCharAt(i, '\n'); + } + } + } + } +} diff -Nru libwoodstox-java-4.1.3/src/test/java/wstxtest/stream/TestAttributeLimits.java libwoodstox-java-5.1.0/src/test/java/wstxtest/stream/TestAttributeLimits.java --- libwoodstox-java-4.1.3/src/test/java/wstxtest/stream/TestAttributeLimits.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/wstxtest/stream/TestAttributeLimits.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,87 @@ +package wstxtest.stream; + +import java.io.IOException; +import java.io.Reader; +import java.io.StringReader; + +import javax.xml.stream.XMLInputFactory; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; + +import com.ctc.wstx.api.WstxInputProperties; + +public class TestAttributeLimits extends BaseStreamTest +{ + public void testMaxAttributesLimit() throws Exception + { + final int max = 100; + XMLInputFactory factory = getNewInputFactory(); + factory.setProperty(WstxInputProperties.P_MAX_ATTRIBUTES_PER_ELEMENT, Integer.valueOf(50)); + Reader reader = new Reader() { + StringReader sreader = new StringReader(""); + done = true; + } + i = sreader.read(cbuf, off, len); + } + return i; + } + @Override + public void close() throws IOException { } + }; + XMLStreamReader xmlreader = factory.createXMLStreamReader(reader); + try { + xmlreader.nextTag(); + fail("Should have failed"); + } catch (XMLStreamException ex) { + verifyException(ex, "Attribute limit (50)"); + } + reader.close(); + } + + public void testLongAttribute() throws Exception { + final int max = 500; + Reader reader = new Reader() { + StringReader sreader = new StringReader(""); + done = true; + } + i = sreader.read(cbuf, off, len); + } + return i; + } + @Override + public void close() throws IOException { } + }; + try { + XMLInputFactory factory = getNewInputFactory(); + factory.setProperty(WstxInputProperties.P_MAX_ATTRIBUTE_SIZE, Integer.valueOf(100)); + XMLStreamReader xmlreader = factory.createXMLStreamReader(reader); + while (xmlreader.next() != XMLStreamReader.END_DOCUMENT) { + } + fail("Should have failed"); + } catch (XMLStreamException ex) { + verifyException(ex, "Maximum attribute size"); + } + reader.close(); // never gets here + } +} diff -Nru libwoodstox-java-4.1.3/src/test/java/wstxtest/stream/TestAttr.java libwoodstox-java-5.1.0/src/test/java/wstxtest/stream/TestAttr.java --- libwoodstox-java-4.1.3/src/test/java/wstxtest/stream/TestAttr.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/wstxtest/stream/TestAttr.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,256 @@ +package wstxtest.stream; + +import javax.xml.stream.*; + +import com.ctc.wstx.stax.WstxInputFactory; + +public class TestAttr + extends BaseStreamTest +{ + final static String XML_11_ATTRS = + ""; + + /** + * This test case was added after encountering a specific problem, which + * only occurs when many attributes were spilled from main hash area.... + * and that's why exact attribute names do matter. + */ + public void testManyAttrs() + throws Exception + { + // First non-NS + XMLStreamReader sr = getReader(XML_11_ATTRS, false); + streamThrough(sr); + // Then NS + sr = getReader(XML_11_ATTRS, true); + streamThrough(sr); + } + + /** + * Tests that the attributes are returned in the document order; + * an invariant Woodstox honors (even though not mandated by StAX 1.0). + */ + public void testAttributeOrder() + throws XMLStreamException + { + String XML = "" + +"\n" + +"\n" + +"\n" + +"\n" + +"\n" + +"\n" + +"]>" + +"" + ; + + final String[] EXP = { + "attr4", "4", + "attr3", "3", + "defAttr", "foobar", + "attr2", "2", + "realDef", "def", + }; + + for (int i = 0; i < 2; ++i) { + boolean ns = (i > 0); + // (May) need validating, to get default attribute values + XMLStreamReader sr = getValidatingReader(XML, ns); + + assertTokenType(START_DOCUMENT, sr.getEventType()); + assertTokenType(DTD, sr.next()); + assertTokenType(START_ELEMENT, sr.next()); + + assertEquals(5, sr.getAttributeCount()); + + for (int ix = 0, len = sr.getAttributeCount(); ix < len; ++ix) { + String lname = sr.getAttributeLocalName(ix); + assertEquals("Attr #"+ix+" name", EXP[ix+ix], lname); + assertEquals("Attr #"+ix+" value", + EXP[ix+ix+1], sr.getAttributeValue(ix)); + + assertEquals("Attribute '"+lname+"' wrongly identified WRT isSpecified: ", + !lname.equals("realDef"), + sr.isAttributeSpecified(ix)); + } + + assertTokenType(END_ELEMENT, sr.next()); + } + } + + final static String NESTED_XML = + "" + +"\n" + +"\n" + +"\n" + +"\n" + +"\n" + +"\n" + +"\n" + +"\n" + +"\n" + +"\n" + +"\n" + +"\n" + +"\n" + +"\n" + +"\n" + +"\n" + +"\n" + +"\n" + +"\n" + +"]>" + +"" + +"" + +"" + +"" + +"" + +"" + +"" + ; + + /** + * Test that verifies that the counts of attributes, values etc. + * are consistent within nested elements, and in the presence/absence + * of DTD default attributes. This is tested since attribute collectors + * are highly specialized for performance, and small problems might + * not manifest with simpler tests. + *

+ * Note: one more implicit assumption tested: not only is the ordering + * of explicit attributes fixed, but so is that of defaulted attributes. + * Latter always come after explicit ones, and in the same order as + * they were declared in DTD. + */ + public void testNestedAttrsNs() + throws Exception + { + XMLStreamReader sr = getValidatingReader(NESTED_XML, true); + assertTokenType(DTD, sr.next()); + + // root elem: + assertTokenType(START_ELEMENT, sr.next()); + assertEquals(3, sr.getAttributeCount()); + assertEquals("123", sr.getAttributeValue(0)); // explicit + assertEquals("rootValue", sr.getAttributeValue(1)); // default + assertEquals("xyz", sr.getAttributeValue(2)); // default + + // 1st branch: + assertTokenType(START_ELEMENT, sr.next()); + assertEquals(2, sr.getAttributeCount()); + assertEquals("a", sr.getAttributePrefix(0)); + assertEquals("b", sr.getAttributeLocalName(0)); + assertEquals("ns", sr.getAttributeNamespace(0)); + assertEquals("ab", sr.getAttributeValue(0)); // explicit + assertEquals("branchValue", sr.getAttributeValue(1)); // default + + // and how about what should NOT be found? + assertNull(sr.getAttributeValue(null, "xyz")); + + // 2nd branch: + assertTokenType(START_ELEMENT, sr.next()); + assertEquals(5, sr.getAttributeCount()); + assertEquals("a", sr.getAttributeLocalName(0)); + assertEquals("value", sr.getAttributeValue(0)); // explicit + assertEquals("xyz", sr.getAttributeLocalName(1)); + assertEquals("456", sr.getAttributeValue(1)); // explicit + assertEquals("c", sr.getAttributeLocalName(2)); + assertEquals("1", sr.getAttributeValue(2)); // explicit + assertEquals("f", sr.getAttributeLocalName(3)); + assertEquals("", sr.getAttributeValue(3)); // explicit + assertEquals("a", sr.getAttributePrefix(4)); + assertEquals("ns", sr.getAttributeNamespace(4)); + assertEquals("b", sr.getAttributeLocalName(4)); + assertEquals("xyz", sr.getAttributeValue(4)); // default + + // 1st leaf: + assertTokenType(START_ELEMENT, sr.next()); + assertEquals(2, sr.getAttributeCount()); + assertEquals("leafValue", sr.getAttributeValue(0)); // default + assertEquals("123", sr.getAttributeValue(1)); // default + + // and how about what should not be found? + assertNull(sr.getAttributeValue(null, "foo")); + assertNull(sr.getAttributeValue(null, "a")); + assertNull(sr.getAttributeValue(null, "c")); + assertNull(sr.getAttributeValue(null, "f")); + assertNull(sr.getAttributeValue(null, "xyz")); + + // close leaf + assertTokenType(END_ELEMENT, sr.next()); + + // close 2nd branch + assertTokenType(END_ELEMENT, sr.next()); + + // close 1st branch + assertTokenType(END_ELEMENT, sr.next()); + + // close root + assertTokenType(END_ELEMENT, sr.next()); + + assertTokenType(END_DOCUMENT, sr.next()); + } + + /** + * This tests handling of ATTLIST declarations for "xmlns:xx" and "xmlns" + * attributes (that is, namespace declarations). Some legacy DTDs + * (most notably, XHTML dtd) do this, and Woodstox had some problems with + * this concept... + */ + public void testNsAttr() + throws XMLStreamException + { + String XML = + "\n" + +"\n" + +"]>" + ; + XMLStreamReader sr = getReader(XML, true); + + assertTokenType(DTD, sr.next()); + assertTokenType(START_ELEMENT, sr.next()); + assertEquals(1, sr.getNamespaceCount()); + assertEquals("ns", sr.getNamespacePrefix(0)); + assertEquals("foobar", sr.getNamespaceURI(0)); + /* This will be 2, if namespace attr declarations are not handled + * properly... + */ + assertEquals(1, sr.getAttributeCount()); + assertEquals("attr", sr.getAttributeLocalName(0)); + assertEquals("123", sr.getAttributeValue(0)); + sr.close(); + } + + /* + ////////////////////////////////////////////////////// + // Internal methods + ////////////////////////////////////////////////////// + */ + + private XMLStreamReader getReader(String contents, boolean nsAware) + throws XMLStreamException + { + WstxInputFactory f = getWstxInputFactory(); + f.getConfig().doValidateWithDTD(false); + f.getConfig().doSupportNamespaces(nsAware); + return constructStreamReader(f, contents); + } + + private XMLStreamReader getValidatingReader(String contents, boolean nsAware) + throws XMLStreamException + { + WstxInputFactory f = getWstxInputFactory(); + f.getConfig().doSupportNamespaces(nsAware); + f.getConfig().doSupportDTDs(true); + f.getConfig().doValidateWithDTD(true); + return constructStreamReader(f, contents); + } +} + diff -Nru libwoodstox-java-4.1.3/src/test/java/wstxtest/stream/TestBufferRecycling.java libwoodstox-java-5.1.0/src/test/java/wstxtest/stream/TestBufferRecycling.java --- libwoodstox-java-4.1.3/src/test/java/wstxtest/stream/TestBufferRecycling.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/wstxtest/stream/TestBufferRecycling.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,76 @@ +package wstxtest.stream; + +import java.io.StringReader; + +import javax.xml.stream.*; + +/** + * Simple unit tests to try to verify that underlying buffers are + * properly recycled. + *

+ * Please note that due to arbitrary nature of GC and its interactions + * with soft reference, as well as the way JUnit may run its unit + * tests, these tests may not be as robust as they should be. + */ +public class TestBufferRecycling + extends BaseStreamTest +{ + final static String DOC = "text"; + + /** + * Test that verifies that the underlying character buffer should + * be reused between two parsing rounds + */ + public void testCharBufferRecycling() + throws Exception + { + XMLInputFactory f = getInputFactory(); + + char[] buf1 = getCharBuffer(f.createXMLStreamReader(new StringReader(DOC)), true); + char[] buf2 = getCharBuffer(f.createXMLStreamReader(new StringReader(DOC)), true); + + if (buf1 != buf2) { + fail("Expected underlying character buffer to be recycled"); + } + } + + /** + * Inverted test to verify that the buffers are NOT shared when they + * can not be. + */ + public void testCharBufferNonRecycling() + throws Exception + { + XMLInputFactory f = getInputFactory(); + + XMLStreamReader sr1 = f.createXMLStreamReader(new StringReader(DOC)); + XMLStreamReader sr2 = f.createXMLStreamReader(new StringReader(DOC)); + char[] buf1 = getCharBuffer(sr1, false); + char[] buf2 = getCharBuffer(sr2, false); + + sr1.close(); + sr2.close(); + + if (buf1 == buf2) { + fail("Should not have identical underlying character buffers when using concurrent stream readers"); + } + } + + /* + ////////////////////////////////////////////////////// + // Internal methods + ////////////////////////////////////////////////////// + */ + + char[] getCharBuffer(XMLStreamReader sr, boolean close) + throws XMLStreamException + { + assertTokenType(START_ELEMENT, sr.next()); + assertTokenType(CHARACTERS, sr.next()); + char[] buf = sr.getTextCharacters(); + if (close) { + sr.close(); + } + return buf; + } +} diff -Nru libwoodstox-java-4.1.3/src/test/java/wstxtest/stream/TestCharacterLimits.java libwoodstox-java-5.1.0/src/test/java/wstxtest/stream/TestCharacterLimits.java --- libwoodstox-java-4.1.3/src/test/java/wstxtest/stream/TestCharacterLimits.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/wstxtest/stream/TestCharacterLimits.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,225 @@ +package wstxtest.stream; + +import java.io.IOException; +import java.io.Reader; +import java.io.StringReader; + +import javax.xml.stream.XMLInputFactory; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; + +import com.ctc.wstx.api.WstxInputProperties; + +@SuppressWarnings("resource") +public class TestCharacterLimits + extends BaseStreamTest +{ + public TestCharacterLimits() { } + + public void testLongGetElementText() throws Exception { + try { + Reader reader = createLongReader("", "", false); + XMLInputFactory factory = getNewInputFactory(); + factory.setProperty(WstxInputProperties.P_MAX_TEXT_LENGTH, Integer.valueOf(1000)); + XMLStreamReader xmlreader = factory.createXMLStreamReader(reader); + while (xmlreader.next() != XMLStreamReader.START_ELEMENT) { + } + System.out.println(xmlreader.getElementText()); + fail("Should have failed"); + } catch (XMLStreamException ex) { + _verifyTextLimitException(ex); + } + } + + public void testLongElementText() throws Exception { + try { + Reader reader = createLongReader("", "", false); + XMLInputFactory factory = getNewInputFactory(); + factory.setProperty(WstxInputProperties.P_MAX_TEXT_LENGTH, Integer.valueOf(100000)); + XMLStreamReader xmlreader = factory.createXMLStreamReader(reader); + while (xmlreader.next() != XMLStreamReader.START_ELEMENT) { + } + assertEquals(XMLStreamReader.CHARACTERS, xmlreader.next()); + while (xmlreader.next() != XMLStreamReader.START_ELEMENT) { + } + fail("Should have failed"); + } catch (XMLStreamException ex) { + _verifyTextLimitException(ex); + } + } + public void testLongWhitespaceNextTag() throws Exception { + try { + Reader reader = createLongReader("", "", true); + XMLInputFactory factory = getNewInputFactory(); + factory.setProperty(WstxInputProperties.P_MAX_TEXT_LENGTH, Integer.valueOf(1000)); + XMLStreamReader xmlreader = factory.createXMLStreamReader(reader); + while (xmlreader.next() != XMLStreamReader.START_ELEMENT) { + } + xmlreader.nextTag(); + fail("Should have failed"); + } catch (XMLStreamException ex) { + _verifyTextLimitException(ex); + } + } + + public void testLongWhitespace() throws Exception { + try { + Reader reader = createLongReader("", "", true); + XMLInputFactory factory = getNewInputFactory(); + factory.setProperty(WstxInputProperties.P_MAX_TEXT_LENGTH, Integer.valueOf(50000)); + XMLStreamReader xmlreader = factory.createXMLStreamReader(reader); + while (xmlreader.next() != XMLStreamReader.START_ELEMENT) { + } + assertEquals(XMLStreamReader.CHARACTERS, xmlreader.next()); + while (xmlreader.next() != XMLStreamReader.START_ELEMENT) { + } + fail("Should have failed"); + } catch (XMLStreamException ex) { + _verifyTextLimitException(ex); + } + } + + public void testLongCDATA() throws Exception { + try { + Reader reader = createLongReader("", true); + XMLInputFactory factory = getNewInputFactory(); + factory.setProperty(WstxInputProperties.P_MAX_TEXT_LENGTH, Integer.valueOf(50000)); + XMLStreamReader xmlreader = factory.createXMLStreamReader(reader); + while (xmlreader.next() != XMLStreamReader.START_ELEMENT) { + } + assertEquals(XMLStreamReader.CDATA, xmlreader.next()); + while (xmlreader.next() != XMLStreamReader.START_ELEMENT) { + } + fail("Should have failed"); + } catch (XMLStreamException ex) { + _verifyTextLimitException(ex); + } + } + + public void testLongCDATANextTag() throws Exception { + Reader reader = createLongReader("", true); + XMLInputFactory factory = getNewInputFactory(); + factory.setProperty(WstxInputProperties.P_MAX_TEXT_LENGTH, Integer.valueOf(1000)); + XMLStreamReader xmlreader = factory.createXMLStreamReader(reader); + try { + int tokens = 0; + while (xmlreader.next() != XMLStreamReader.START_ELEMENT) { + ++tokens; + } + int code = xmlreader.nextTag(); + fail("Should have failed: instead got "+tokens+" tokens; and one following START_ELEMENT: "+code); + } catch (XMLStreamException ex) { + _verifyTextLimitException(ex); + } + } + + public void testLongComment() throws Exception { + try { + Reader reader = createLongReader("", true); + XMLInputFactory factory = getNewInputFactory(); + factory.setProperty(WstxInputProperties.P_MAX_TEXT_LENGTH, Integer.valueOf(1000)); + XMLStreamReader xmlreader = factory.createXMLStreamReader(reader); + while (xmlreader.next() != XMLStreamReader.COMMENT) { + } + // important, due to lazy handling only triggers problem here: + String str = xmlreader.getText(); + fail("Should have failed; instead got: "+str); + } catch (Exception ex) { + _verifyTextLimitException(ex); + } + } + + public void testLongCommentNextTag() throws Exception { + try { + Reader reader = createLongReader("", true); + XMLInputFactory factory = getNewInputFactory(); + factory.setProperty(WstxInputProperties.P_MAX_TEXT_LENGTH, Integer.valueOf(1000)); + XMLStreamReader xmlreader = factory.createXMLStreamReader(reader); + while (xmlreader.next() != XMLStreamReader.COMMENT) { + } + xmlreader.nextTag(); + fail("Should have failed"); + } catch (XMLStreamException ex) { + _verifyTextLimitException(ex); + } + } + + public void testLongCommentCoalescing() throws Exception { + try { + Reader reader = createLongReader("", true); + XMLInputFactory factory = getNewInputFactory(); + factory.setProperty(XMLInputFactory.IS_COALESCING, Boolean.TRUE); + factory.setProperty(WstxInputProperties.P_MAX_TEXT_LENGTH, Integer.valueOf(1000)); + XMLStreamReader xmlreader = factory.createXMLStreamReader(reader); + while (xmlreader.next() != XMLStreamReader.START_ELEMENT) { + } + xmlreader.nextTag(); + fail("Should have failed"); + } catch (XMLStreamException ex) { + _verifyTextLimitException(ex); + } + } + + public void testLongWhitespaceCoalescing() throws Exception { + try { + Reader reader = createLongReader("", "", true); + XMLInputFactory factory = getNewInputFactory(); + factory.setProperty(XMLInputFactory.IS_COALESCING, Boolean.TRUE); + factory.setProperty(WstxInputProperties.P_MAX_TEXT_LENGTH, Integer.valueOf(1000)); + XMLStreamReader xmlreader = factory.createXMLStreamReader(reader); + while (xmlreader.next() != XMLStreamReader.START_ELEMENT) { + } + xmlreader.nextTag(); + fail("Should have failed"); + } catch (XMLStreamException ex) { + _verifyTextLimitException(ex); + } + } + + private Reader createLongReader(final String pre, final String post, final boolean ws) + { + // 17-Aug-2016, tatu: used to be Integer.MAX_VALUE, but since we are testing with + // way smaller limit, just do 1 meg + final int maxLength = 16 * 1024 * 1024; + final StringBuffer start = new StringBuffer("" + pre); + + return new Reader() { + StringReader sreader = new StringReader(start.toString()); + int count; + boolean done; + + @Override + public int read(char[] cbuf, int off, int len) throws IOException { + if (done) { + return -1; + } + int i = sreader.read(cbuf, off, len); + if (i < 0) { + String text; + if (count < maxLength) { + text = ws ? " " + : "123456789012378901234567890"; + } else { + text = post + + (ws ? "" + : "foo"); + done = true; + } + sreader = new StringReader(text); + count += text.length(); + i = sreader.read(cbuf, off, len); + } + return i; + } + + @Override + public void close() throws IOException { + } + }; + } + + private void _verifyTextLimitException(Exception ex) { + verifyException(ex, "Text size limit"); + verifyException(ex, "exceeded"); + } +} diff -Nru libwoodstox-java-4.1.3/src/test/java/wstxtest/stream/TestComments.java libwoodstox-java-5.1.0/src/test/java/wstxtest/stream/TestComments.java --- libwoodstox-java-4.1.3/src/test/java/wstxtest/stream/TestComments.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/wstxtest/stream/TestComments.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,54 @@ +package wstxtest.stream; + +import javax.xml.stream.*; + +import wstxtest.cfg.*; + +public class TestComments + extends BaseStreamTest + implements InputTestMethod +{ + InputConfigIterator mConfigs; + + public TestComments() { + super(); + mConfigs = new InputConfigIterator(); + Configs.addAll(mConfigs); + } + + public void testValid() + throws Exception + { + mConfigs.iterate(getInputFactory(), this); + } + + /* + ////////////////////////////////////////////////////// + // Internal methods + ////////////////////////////////////////////////////// + */ + + /** + * Method called via input config iterator, with all possible + * configurations + */ + @Override + public void runTest(XMLInputFactory f, InputConfigIterator it) + throws Exception + { + String XML = "" + +"\n" + +" " + +"" + +"\n" + +""; + XMLStreamReader sr = constructStreamReader(f, XML); + streamAndCheck(sr, it, XML, XML, false); + // Let's also test real streaming... + sr = constructStreamReader(f, XML); + streamAndCheck(sr, it, XML, XML, true); + } + +} + diff -Nru libwoodstox-java-4.1.3/src/test/java/wstxtest/stream/TestConfig.java libwoodstox-java-5.1.0/src/test/java/wstxtest/stream/TestConfig.java --- libwoodstox-java-4.1.3/src/test/java/wstxtest/stream/TestConfig.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/wstxtest/stream/TestConfig.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,123 @@ +package wstxtest.stream; + +import javax.xml.stream.*; + +import org.codehaus.stax2.XMLStreamProperties; + +import com.ctc.wstx.api.WstxInputProperties; + +/** + * Set of unit tests that check how Woodstox handles white space in + * prolog and/or epilog. + */ +public class TestConfig + extends BaseStreamTest +{ + final static String WSTX_NAME = "woodstox"; + + /* !!! 18-Dec-2006, TSa: This needs to be resolved some other way, + * shouldn't have repeat it here (against DRY principle) + */ + final static String WSTX_VERSION = "5.0"; + + public void testSettingResolvers() + throws XMLStreamException + { + XMLInputFactory ifact = getNewInputFactory(); + // Default should be "no custom resolvers" + assertNull(ifact.getProperty(WstxInputProperties.P_DTD_RESOLVER)); + assertNull(ifact.getProperty(WstxInputProperties.P_ENTITY_RESOLVER)); + + // But if and when they are set, they should stick for both factory: + XMLResolver dtdR = new DTDResolver(); + XMLResolver entityR = new EntityResolver(); + + ifact.setProperty(WstxInputProperties.P_DTD_RESOLVER, dtdR); + ifact.setProperty(WstxInputProperties.P_ENTITY_RESOLVER, entityR); + + Object gotDtdR = ifact.getProperty(WstxInputProperties.P_DTD_RESOLVER); + Object gotEntityR = ifact.getProperty(WstxInputProperties.P_ENTITY_RESOLVER); + assertTrue("DTD resolver set for factory should stick: didn't except value ["+gotDtdR+"]", + dtdR == gotDtdR); + assertTrue("Entity resolver set for factory should stick: didn't except value ["+gotEntityR+"]", + entityR == gotEntityR); + + // and for the instances as well: + XMLStreamReader sr = constructStreamReader(ifact, ""); + gotDtdR = sr.getProperty(WstxInputProperties.P_DTD_RESOLVER); + gotEntityR = sr.getProperty(WstxInputProperties.P_ENTITY_RESOLVER); + + assertTrue("DTD resolver set should be passed to instance by factory: didn't except value ["+gotDtdR+"]", + dtdR == gotDtdR); + assertTrue("Entity resolver set should be passed to instance by factory: didn't except value ["+gotEntityR+"]", + entityR == gotEntityR); + } + + /** + * Unit test that ensures that DTD resolver gets properly called + * when configured + */ + public void testUsingDTDResolver() + throws XMLStreamException + { + // !!! TBI + } + + /** + * Unit test that ensures that entity resolver gets properly called + * when configured + */ + public void testUsingEntityResolver() + throws XMLStreamException + { + // !!! TBI + } + + public void testReaderProperties() + throws XMLStreamException + { + XMLInputFactory ifact = getNewInputFactory(); + assertEquals(WSTX_NAME, ifact.getProperty(XMLStreamProperties.XSP_IMPLEMENTATION_NAME)); + assertEquals(WSTX_VERSION, ifact.getProperty(XMLStreamProperties.XSP_IMPLEMENTATION_VERSION)); + assertEquals(Boolean.TRUE, + ifact.getProperty(XMLStreamProperties.XSP_SUPPORTS_XML11)); + } + + public void testWriterProperties() + throws XMLStreamException + { + XMLOutputFactory ofact = getNewOutputFactory(); + assertEquals(WSTX_NAME, ofact.getProperty(XMLStreamProperties.XSP_IMPLEMENTATION_NAME)); + assertEquals(WSTX_VERSION, ofact.getProperty(XMLStreamProperties.XSP_IMPLEMENTATION_VERSION)); + assertEquals(Boolean.TRUE, + ofact.getProperty(XMLStreamProperties.XSP_SUPPORTS_XML11)); + } + + /* + ////////////////////////////////////////////////////// + // Helper classes: + ////////////////////////////////////////////////////// + */ + + private final static class DTDResolver + implements XMLResolver + { + @Override + public Object resolveEntity(String publicID, String systemID, + String baseURI, String namespace) + { + return null; + } + } + + private final static class EntityResolver + implements XMLResolver + { + @Override + public Object resolveEntity(String publicID, String systemID, + String baseURI, String namespace) + { + return null; + } + } +} diff -Nru libwoodstox-java-4.1.3/src/test/java/wstxtest/stream/TestDTD.java libwoodstox-java-5.1.0/src/test/java/wstxtest/stream/TestDTD.java --- libwoodstox-java-4.1.3/src/test/java/wstxtest/stream/TestDTD.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/wstxtest/stream/TestDTD.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,40 @@ +package wstxtest.stream; + +import javax.xml.stream.*; + +import org.codehaus.stax2.*; + +/** + * Set of unit tests that checks some additional invariants Woodstox + * guarantees with respect to DOCTYPE declaration handling. + */ +public class TestDTD + extends BaseStreamTest +{ + + /** + * Tests that the DOCTYPE declaration can be succesfully skipped in + * the non-DTD-support mode. + */ + public void testSkipping() + throws XMLStreamException + { + String XML = "\n" + +"\r\n" + +"" + +"" + +"]>" + +""; + + XMLInputFactory2 f = getInputFactory(); + setSupportDTD(f, false); + XMLStreamReader2 sr = constructStreamReader(f, XML); + assertTokenType(DTD, sr.next()); + + DTDInfo info = sr.getDTDInfo(); + assertNotNull(info); + + assertTokenType(START_ELEMENT, sr.next()); + } +} diff -Nru libwoodstox-java-4.1.3/src/test/java/wstxtest/stream/TestElementLimits.java libwoodstox-java-5.1.0/src/test/java/wstxtest/stream/TestElementLimits.java --- libwoodstox-java-4.1.3/src/test/java/wstxtest/stream/TestElementLimits.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/wstxtest/stream/TestElementLimits.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,166 @@ +package wstxtest.stream; + +import java.io.IOException; +import java.io.Reader; +import java.io.StringReader; + +import javax.xml.stream.*; + +import com.ctc.wstx.api.WstxInputProperties; +import com.ctc.wstx.sr.BasicStreamReader; + +/** + * Unit test suite that tests handling of limits for elements in + * XML documents. + * + * @since 4.2 + */ +@SuppressWarnings("resource") +public class TestElementLimits extends BaseStreamTest +{ + public void testSuperDeep() throws Exception + { + final int max = Integer.MAX_VALUE; + Reader reader = new Reader() { + StringReader sreader = new StringReader(""); + int count; + boolean done; + @Override + public int read(char[] cbuf, int off, int len) throws IOException { + int i = sreader.read(cbuf, off, len); + if (i == -1) { + if (count < max) { + sreader = new StringReader(""); + count++; + } else if (!done) { + sreader = new StringReader(""); + done = true; + } + i = sreader.read(cbuf, off, len); + } + return i; + } + @Override + public void close() throws IOException { + } + }; + XMLInputFactory factory = getNewInputFactory(); + factory.setProperty(WstxInputProperties.P_MAX_ELEMENT_DEPTH, Integer.valueOf(25)); + XMLStreamReader xmlreader = factory.createXMLStreamReader(reader); + try { + while (xmlreader.next() != XMLStreamReader.END_ELEMENT) { + ; + } + fail("Should have failed"); + } catch (XMLStreamException ex) { + verifyException(ex, "Maximum Element Depth limit"); + } + } + public void testManyChildren() throws Exception + { + final int max = Integer.MAX_VALUE; + Reader reader = new Reader() { + StringReader sreader = new StringReader(""); + int count; + boolean done; + @Override + public int read(char[] cbuf, int off, int len) throws IOException { + int i = sreader.read(cbuf, off, len); + if (i == -1) { + if (count < max) { + sreader = new StringReader(""); + count++; + } else if (!done) { + sreader = new StringReader(""); + done = true; + } + i = sreader.read(cbuf, off, len); + } + return i; + } + @Override + public void close() throws IOException { + } + }; + XMLInputFactory factory = getNewInputFactory(); + factory.setProperty(WstxInputProperties.P_MAX_CHILDREN_PER_ELEMENT, Integer.valueOf(100)); + try { + XMLStreamReader xmlreader = factory.createXMLStreamReader(reader); + while (xmlreader.next() != XMLStreamReader.END_DOCUMENT) { + } + fail("Should have failed"); + } catch (XMLStreamException ex) { + verifyException(ex, "Maximum Number of Child Elements"); + } + } + + public void testManyElements() throws Exception + { + + try { + XMLInputFactory factory = getNewInputFactory(); + factory.setProperty(WstxInputProperties.P_MAX_ELEMENT_COUNT, Integer.valueOf(100)); + XMLStreamReader xmlreader = factory.createXMLStreamReader(createManyElementReader()); + while (xmlreader.next() != XMLStreamReader.END_DOCUMENT) { + } + fail("Should have failed"); + } catch (XMLStreamException ex) { + //expected + } + XMLInputFactory factory = getNewInputFactory(); + XMLStreamReader xmlreader = factory.createXMLStreamReader(createManyElementReader()); + try { + ((BasicStreamReader)xmlreader).setProperty(WstxInputProperties.P_MAX_ELEMENT_COUNT, + Integer.valueOf(100)); + while (xmlreader.next() != XMLStreamReader.END_DOCUMENT) { + } + fail("Should have failed"); + } catch (XMLStreamException ex) { + verifyException(ex, "Maximum Element Count limit"); + } + } + + public void testCharacterLimit() throws Exception { + try { + XMLInputFactory factory = getNewInputFactory(); + factory.setProperty(WstxInputProperties.P_MAX_CHARACTERS, Integer.valueOf(100)); + XMLStreamReader xmlreader = factory.createXMLStreamReader(createManyElementReader()); + while (xmlreader.next() != XMLStreamReader.END_DOCUMENT) { + } + fail("Should have failed"); + } catch (XMLStreamException ex) { + verifyException(ex, "Maximum document characters limit"); + } + } + + private Reader createManyElementReader() { + final int max = Integer.MAX_VALUE; + Reader reader = new Reader() { + StringReader sreader = new StringReader(""); + int count; + int count2; + @Override + public int read(char[] cbuf, int off, int len) throws IOException { + int i = sreader.read(cbuf, off, len); + if (i == -1) { + if ((count % 5000) == 1) { + String close = ""; + count2++; + sreader = new StringReader(close + ""); + } else if (count < max) { + sreader = new StringReader(""); + count++; + } + + i = sreader.read(cbuf, off, len); + } + return i; + } + @Override + public void close() throws IOException { + } + }; + return reader; + } +} + diff -Nru libwoodstox-java-4.1.3/src/test/java/wstxtest/stream/TestEncodingDetection.java libwoodstox-java-5.1.0/src/test/java/wstxtest/stream/TestEncodingDetection.java --- libwoodstox-java-4.1.3/src/test/java/wstxtest/stream/TestEncodingDetection.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/wstxtest/stream/TestEncodingDetection.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,139 @@ +package wstxtest.stream; + +import java.io.*; + +import javax.xml.stream.*; + +/** + * This set on unit tests checks that woodstox-specific invariants + * regarding automatic input encoding detection are maintained. Some + * of these might be required by stax specification too, but it is not + * quite certain, thus tests are included in woodstox-specific packages. + */ +public class TestEncodingDetection + extends BaseStreamTest +{ + final static String ENC_EBCDIC_IN_PREFIX = "cp"; + + final static String ENC_EBCDIC_OUT_PREFIX = "IBM"; + + public void testUtf8() + throws IOException, XMLStreamException + { + /* Default is, in absence of any other indications, UTF-8... + * let's check the shortest legal doc: + */ + String XML = ""; + byte[] b = XML.getBytes("UTF-8"); + XMLStreamReader sr = getReader(b); + assertTokenType(START_DOCUMENT, sr.getEventType()); + assertNull(sr.getCharacterEncodingScheme()); + assertEquals("UTF-8", sr.getEncoding()); + // let's iterate just for fun though + assertTokenType(START_ELEMENT, sr.next()); + sr.close(); + } + + public void testUtf16() + throws XMLStreamException + { + // Should be able to figure out encoding... + String XML = "."; + + /* Let's first check a somewhat common case; figuring out UTF-16 + * encoded doc (which has to have BOM, thus); first, big-endian + */ + StringBuffer sb = new StringBuffer(XML); + sb.setCharAt(0, (char) 0xFEFF); + + byte[] b = getUtf16Bytes(sb.toString(), true); + XMLStreamReader sr = getReader(b); + assertTokenType(START_DOCUMENT, sr.getEventType()); + assertNull(sr.getCharacterEncodingScheme()); + assertEquals("UTF-16BE", sr.getEncoding()); + // let's iterate just for fun though + assertTokenType(START_ELEMENT, sr.next()); + sr.close(); + + // and then little-endian + b = getUtf16Bytes(sb.toString(), false); + sr = getReader(b); + assertTokenType(START_DOCUMENT, sr.getEventType()); + assertNull(sr.getCharacterEncodingScheme()); + assertEquals("UTF-16LE", sr.getEncoding()); + assertTokenType(START_ELEMENT, sr.next()); + sr.close(); + } + + /** + * Testing for EBCDIC is tricky, mostly due to possible + * complexity of the things to support, as well as lack + * of sample documents and difficulty in reading ones + * that exist (it not being 7-bit ascii compatible). + * But let's try a straight-forward (naive?) test + * to verify that what is supposed to work does. + */ + public void testEBCDIC() + throws IOException, XMLStreamException + { + final String[] subtypes = new String[] { + "037", "277", "278", "280", "284", "285", "297", + "420", "424", "500", "870", "871", "918", + }; + + for (int i = 0; i < subtypes.length; ++i) { + String actEnc = ENC_EBCDIC_IN_PREFIX + subtypes[i]; + String xml = "" + +"rock & roll!"; + byte[] bytes = xml.getBytes(actEnc); + XMLStreamReader sr = getReader(bytes); + + assertTokenType(START_DOCUMENT, sr.getEventType()); + + // Declared encoding should match 100% + assertEquals(actEnc, sr.getCharacterEncodingScheme()); + + // Found encoding, though, can be changed + String expEnc = ENC_EBCDIC_OUT_PREFIX + subtypes[i]; + assertEquals(expEnc, sr.getEncoding()); + + assertTokenType(START_ELEMENT, sr.next()); + assertEquals("root", sr.getLocalName()); + assertTokenType(CHARACTERS, sr.next()); + assertEquals("rock & roll!", getAndVerifyText(sr)); + assertTokenType(COMMENT, sr.next()); + assertEquals(" comment ", getAndVerifyText(sr)); + assertTokenType(END_ELEMENT, sr.next()); + assertEquals("root", sr.getLocalName()); + sr.close(); + } + } + + + /* + ///////////////////////////////////////// + // Non-test methods + ///////////////////////////////////////// + */ + + private byte[] getUtf16Bytes(String input, boolean bigEndian) + { + int len = input.length(); + byte[] b = new byte[len+len]; + int offset = bigEndian ? 1 : 0; // offset for LSB + for (int i = 0; i < len; ++i) { + int c = input.charAt(i); + // BOM is 2-byte, others 1 byte... + b[i+i+offset] = (byte) (c & 0xFF); + b[i+i+(1 - offset)] = (byte) (c >> 8); + } + return b; + } + + private XMLStreamReader getReader(byte[] b) + throws XMLStreamException + { + XMLInputFactory f = getInputFactory(); + return f.createXMLStreamReader(new ByteArrayInputStream(b)); + } +} diff -Nru libwoodstox-java-4.1.3/src/test/java/wstxtest/stream/TestEntityLimits.java libwoodstox-java-5.1.0/src/test/java/wstxtest/stream/TestEntityLimits.java --- libwoodstox-java-4.1.3/src/test/java/wstxtest/stream/TestEntityLimits.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/wstxtest/stream/TestEntityLimits.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,109 @@ +package wstxtest.stream; + +import java.io.StringReader; + +import javax.xml.stream.*; + +import com.ctc.wstx.api.WstxInputProperties; + +/** + * Tests that verify that it is possible to limit aspects of general parsed + * entity handling: specifically, total number of expansions per document, + * and maximum nesting depth of entity expansion. + * + * @since 4.3 + */ +public class TestEntityLimits + extends BaseStreamTest +{ + public void testMaxEntityNesting() throws XMLStreamException + { + String XML = "\n" + +" \n" + +" \n" + +"]>" + ; + + // First: with default limits (high), should be fine + XMLInputFactory f = getNewInputFactory(); + XMLStreamReader sr = f.createXMLStreamReader(new StringReader(XML)); + assertTokenType(DTD, sr.next()); + assertTokenType(START_ELEMENT, sr.next()); + assertTokenType(CHARACTERS, sr.next()); + assertTokenType(END_ELEMENT, sr.next()); + sr.close(); + + // and with max depth of 3 as well + f.setProperty(WstxInputProperties.P_MAX_ENTITY_DEPTH, Integer.valueOf(3)); + sr = f.createXMLStreamReader(new StringReader(XML)); + assertTokenType(DTD, sr.next()); + assertTokenType(START_ELEMENT, sr.next()); + assertTokenType(CHARACTERS, sr.next()); + assertTokenType(END_ELEMENT, sr.next()); + sr.close(); + + // but not with 2 + f.setProperty(WstxInputProperties.P_MAX_ENTITY_DEPTH, Integer.valueOf(2)); + sr = f.createXMLStreamReader(new StringReader(XML)); + assertTokenType(DTD, sr.next()); + assertTokenType(START_ELEMENT, sr.next()); + try { + sr.next(); + fail("Should have failed with entity depth limit extension"); + } catch (XMLStreamException e) { + verifyException(e, "Maximum entity expansion depth"); + } + sr.close(); + } + + public void testMaxEntityExpansionCount() throws XMLStreamException + { + String XML = "\n" + +" \n" + +" \n" + +"]>" + ; + + // expands to 16 segments, via 21 expansions (1 -> 4 -> 16) + + // fine with default settings + XMLInputFactory f = getNewInputFactory(); + setCoalescing(f, true); + XMLStreamReader sr = f.createXMLStreamReader(new StringReader(XML)); + assertTokenType(DTD, sr.next()); + assertTokenType(START_ELEMENT, sr.next()); + assertTokenType(CHARACTERS, sr.next()); + assertTokenType(END_ELEMENT, sr.next()); + sr.close(); + + // and with max set to 21 expansions + f.setProperty(WstxInputProperties.P_MAX_ENTITY_COUNT, Integer.valueOf(21)); + sr = f.createXMLStreamReader(new StringReader(XML)); + assertTokenType(DTD, sr.next()); + assertTokenType(START_ELEMENT, sr.next()); + assertTokenType(CHARACTERS, sr.next()); + sr.getText(); + assertTokenType(END_ELEMENT, sr.next()); + sr.close(); + + // but not with one less + f.setProperty(WstxInputProperties.P_MAX_ENTITY_COUNT, Integer.valueOf(20)); + sr = f.createXMLStreamReader(new StringReader(XML)); + assertTokenType(DTD, sr.next()); + assertTokenType(START_ELEMENT, sr.next()); + try { + sr.next(); + assertTokenType(CHARACTERS, sr.getEventType()); + // may require either reading of content (getText()) or advancing to next; + // in former case, will get lazily thrown exception unfortunately so: + sr.next(); + fail("Should have failed with entity count limit extension"); + } catch (XMLStreamException e) { + verifyException(e, "Maximum entity expansion count"); + } + sr.close(); + } + +} diff -Nru libwoodstox-java-4.1.3/src/test/java/wstxtest/stream/TestEntityRead.java libwoodstox-java-5.1.0/src/test/java/wstxtest/stream/TestEntityRead.java --- libwoodstox-java-4.1.3/src/test/java/wstxtest/stream/TestEntityRead.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/wstxtest/stream/TestEntityRead.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,282 @@ +package wstxtest.stream; + +import java.util.*; +import javax.xml.stream.*; + +import org.codehaus.stax2.*; + +import com.ctc.wstx.api.WstxInputProperties; +import com.ctc.wstx.ent.EntityDecl; +import com.ctc.wstx.exc.WstxLazyException; +import com.ctc.wstx.sr.BasicStreamReader; + +/** + * This unit test suite checks to see that Woodstox implementation dependant + * functionality works the way it's planned to. In some cases future StAX + * revisions may dictate exact behaviour expected, but for now expected + * behaviour is based on + * a combination of educated guessing and intuitive behaviour. + */ +public class TestEntityRead + extends BaseStreamTest +{ + /** + * This unit test checks that the information received as part of the + * event, in non-expanding mode, is as expected. + */ + public void testDeclaredInNonExpandingMode() + throws XMLStreamException + { + String XML = "\n" + +"]>text:&myent;more" + ; + + // Non-expanding, coalescing: + BasicStreamReader sr = getReader(XML, false, true); + assertTokenType(DTD, sr.next()); + DTDInfo dtd = sr.getDTDInfo(); + assertNotNull(dtd); + + assertTokenType(START_ELEMENT, sr.next()); + assertEquals("root", sr.getLocalName()); + + assertTokenType(CHARACTERS, sr.next()); + assertTokenType(ENTITY_REFERENCE, sr.next()); + assertEquals("myent", sr.getLocalName()); + EntityDecl ed = sr.getCurrentEntityDecl(); + assertNotNull(ed); + assertEquals("myent", ed.getName()); + assertEquals("value", ed.getReplacementText()); + + // The pure stax way: + assertEquals("value", sr.getText()); + + // Finally, let's see that location info is about right? + Location loc = ed.getLocation(); + assertNotNull(loc); + assertEquals(2, loc.getLineNumber()); + + /* Hmmh. Not 100% if this location makes sense, but... it's the + * current behaviour, so we can regression test it. + */ + assertEquals(3, loc.getColumnNumber()); + // don't care about offsets here... location tests catch them + + assertTokenType(CHARACTERS, sr.next()); + assertTokenType(END_ELEMENT, sr.next()); + assertEquals("root", sr.getLocalName()); + + assertTokenType(END_DOCUMENT, sr.next()); + sr.close(); + } + + /** + * This unit test checks that in non-expanding mode it is acceptable + * to refer to undeclared entities. + */ + public void testUndeclaredInNonExpandingMode() + throws Exception + { + String XML = "text:&myent;more" + ; + + // Non-expanding, coalescing: + BasicStreamReader sr = getReader(XML, false, true); + assertTokenType(DTD, sr.next()); + DTDInfo dtd = sr.getDTDInfo(); + assertNotNull(dtd); + + assertTokenType(START_ELEMENT, sr.next()); + assertEquals("root", sr.getLocalName()); + + assertTokenType(CHARACTERS, sr.next()); + + /* Exception would be a real possibility, so let's catch one (if + * any) for debugging purposes: + */ + + try { + assertTokenType(ENTITY_REFERENCE, sr.next()); + } catch (XMLStreamException sex) { + fail("Did not except a stream exception on undeclared entity in non-entity-expanding mode; got: "+sex); + } + + assertEquals("myent", sr.getLocalName()); + EntityDecl ed = sr.getCurrentEntityDecl(); + assertNull(ed); + + assertTokenType(CHARACTERS, sr.next()); + assertTokenType(END_ELEMENT, sr.next()); + assertEquals("root", sr.getLocalName()); + + assertTokenType(END_DOCUMENT, sr.next()); + sr.close(); + } + + /** + * This unit test verifies that it's possible to add a Map of + * expansions from Entity names to + */ + @SuppressWarnings("deprecation") + public void testUndeclaredUsingCustomMap() + throws XMLStreamException + { + // First, let's check actual usage: + + String XML = "ok: &myent;&myent2;"; + String EXP_TEXT = "ok: (simple)expand to ([text])"; + XMLInputFactory fact = getConfiguredFactory(true, true); + Map m = new HashMap(); + m.put("myent", "(simple)"); + m.put("myent3", "[text]"); + m.put("myent2", "expand to (&myent3;)"); + fact.setProperty(WstxInputProperties.P_CUSTOM_INTERNAL_ENTITIES, m); + XMLStreamReader sr = constructStreamReader(fact, XML); + assertTokenType(START_ELEMENT, sr.next()); + assertEquals("root", sr.getLocalName()); + assertTokenType(CHARACTERS, sr.next()); + assertEquals(EXP_TEXT, getAndVerifyText(sr)); + assertTokenType(END_ELEMENT, sr.next()); + sr.close(); + + /* And then see if we can query configured value and get expected + * types of results + */ + @SuppressWarnings("unchecked") + Map mr = (Map) fact.getProperty(WstxInputProperties.P_CUSTOM_INTERNAL_ENTITIES); + assertNotNull(mr); + assertEquals(3, mr.size()); + for (Map.Entry entry : mr.entrySet()) { + String name = entry.getKey().toString(); + if (name.equals("myent") || name.equals("myent2") + || name.equals("myent3")) { + // fine, let's just verify the type + EntityDecl ed = (EntityDecl) entry.getValue(); + assertNotNull(ed); + } else { + fail("Unexpected entity '"+name+"' in the custom entity map"); + } + } + } + + /** + * This unit test checks that it is possible to deal with undeclared + * entities in resolving mode too, as long as a special resolver + * is used. + */ + public void testUndeclaredButResolved() + throws Exception + { + XMLInputFactory fact = getConfiguredFactory(true, true); + + for (int i = 0; i < 3; ++i) { + String XML, expText; + XMLResolver resolver; + + switch (i) { + case 0: + XML = "value: &myent;"; + resolver = new Resolver("myent", "value"); + expText = "value: value"; + break; + case 1: + XML = "expands to:&myent;..."; + resolver = new Resolver("myent", "X&Y"); + expText = "expands to:X&Y..."; + break; + default: + XML = "testing: &myent;"; + resolver = new Resolver("dummy", "foobar"); + expText = ""; // whatever; + break; + } + + fact.setProperty(WstxInputProperties.P_UNDECLARED_ENTITY_RESOLVER, + resolver); + XMLStreamReader sr = constructStreamReader(fact, XML); + assertTokenType(START_ELEMENT, sr.next()); + assertEquals("root", sr.getLocalName()); + + if (i == 2) { // Should throw an exception, then: + try { + sr.next(); + /*String text =*/ sr.getText(); // to force parsing + fail("Expected an exception for undefined entity 'myent' that doesn't resolve via customer resolver"); + } catch (XMLStreamException sex) { + ; // good; + } catch (WstxLazyException lex) { + ; // likewise + } + } else { + try { + assertTokenType(CHARACTERS, sr.next()); + } catch (XMLStreamException sex) { + // only caught to provide more meaningful fail info: + fail("Did not expect an exception, since 'myent' should have resolved; got: "+sex); + } + assertEquals(expText, sr.getText()); + assertTokenType(END_ELEMENT, sr.next()); + assertEquals("root", sr.getLocalName()); + } + } + } + + /* + /////////////////////////////////////////////////////////// + // Private methods, other + /////////////////////////////////////////////////////////// + */ + + /** + * Note: all readers for this set of unit tests enable DTD handling; + * otherwise entity definitions wouldn't be read. Validation shouldn't + * need to be enabled just for that purpose. + */ + private BasicStreamReader getReader(String contents, boolean replEntities, + boolean coalescing) + throws XMLStreamException + { + XMLInputFactory f = getConfiguredFactory(replEntities, coalescing); + return (BasicStreamReader) constructStreamReader(f, contents); + } + + private XMLInputFactory getConfiguredFactory(boolean replEntities, boolean coalescing) + throws XMLStreamException + { + XMLInputFactory f = getInputFactory(); + setNamespaceAware(f, true); + setSupportDTD(f, true); + setValidating(f, false); + setReplaceEntities(f, replEntities); + setCoalescing(f, coalescing); + return f; + } + + /* + /////////////////////////////////////////////////////////// + // Helper classes + /////////////////////////////////////////////////////////// + */ + + final static class Resolver + implements XMLResolver + { + final String mKey, mValue; + + public Resolver(String key, String value) { + mKey = key; + mValue = value; + } + + @Override + public Object resolveEntity(String publicID, String systemID, String baseURI, String namespace) + { + if (mKey.equals(namespace)) { + return mValue; + } + return null; + } + } +} diff -Nru libwoodstox-java-4.1.3/src/test/java/wstxtest/stream/TestLocation.java libwoodstox-java-5.1.0/src/test/java/wstxtest/stream/TestLocation.java --- libwoodstox-java-4.1.3/src/test/java/wstxtest/stream/TestLocation.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/wstxtest/stream/TestLocation.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,202 @@ +package wstxtest.stream; + +import java.io.*; +import java.util.Random; +import javax.xml.stream.*; + +import org.codehaus.stax2.*; +import com.ctc.wstx.stax.WstxInputFactory; + +/** + * Unit tests for testing Woodstox-specific features of location + * tracking. + */ +public class TestLocation + extends BaseStreamTest +{ + public void testSimpleLocation() + throws XMLStreamException + { + final String XML = "\r\n \r\n "; + + XMLInputFactory f = getWstxInputFactory(); + XMLStreamReader2 sr = (XMLStreamReader2)f.createXMLStreamReader(new StringReader(XML)); + + int type = sr.next(); + if (type == XMLStreamConstants.SPACE) { + type = sr.next(); + } + assertTokenType(START_ELEMENT, type); + + Location loc = sr.getLocationInfo().getStartLocation(); + assertEquals(2, loc.getLineNumber()); + assertEquals(3, loc.getColumnNumber()); + assertEquals(4, loc.getCharacterOffset()); + + assertTokenType(CHARACTERS, sr.next()); + assertTokenType(END_ELEMENT, sr.next()); + loc = sr.getLocationInfo().getStartLocation(); + assertEquals(3, loc.getLineNumber()); + assertEquals(2, loc.getColumnNumber()); + assertEquals(13, loc.getCharacterOffset()); + } + + public void testLineNumbers() + throws XMLStreamException + { + final int SEED = 129; + final int ROWS = 1000; + + // First, let's create xml doc: + StringBuffer sb = new StringBuffer(); + sb.append(""); + Random r = new Random(SEED); + for (int i = 0; i < ROWS; ++i) { + switch (r.nextInt() % 3) { + case 0: + sb.append("\r"); + break; + case 1: + sb.append("\r\n"); + break; + default: + sb.append("\n"); + } + int ind = r.nextInt() % 7; + while (--ind >= 0) { + sb.append(' '); + } + sb.append(""); + } + sb.append(""); + + // And then we'll parse to ensure line numbers and offsets are ok + + WstxInputFactory f = getWstxInputFactory(); + // Need to shrink it to get faster convergence + f.getConfig().setInputBufferLength(23); + XMLStreamReader2 sr = (XMLStreamReader2) f.createXMLStreamReader(new StringReader(sb.toString())); + + assertTokenType(START_ELEMENT, sr.next()); + + int linenr = 1; + int col = 4; + int chars = 3; + + r = new Random(SEED); + while (true) { + // END_ELEM signals end... + int type = sr.next(); + if (type == END_ELEMENT) { + assertEquals("a", sr.getLocalName()); + break; + } + assertTokenType(type, type); + + Location loc = sr.getLocationInfo().getStartLocation(); + assertEquals(linenr, loc.getLineNumber()); + assertEquals(col, loc.getColumnNumber()); + assertEquals(chars, loc.getCharacterOffset()); + + sb = new StringBuffer(); + boolean offByOne = false; + switch (r.nextInt() % 3) { + case 1: + offByOne = true; // Since \r\n gets truncated to \n + } + sb.append("\n"); + int ind = r.nextInt() % 7; + while (--ind >= 0) { + sb.append(' '); + } + String ws = sb.toString(); + if (!ws.equals(sr.getText())) { + fail("Expected "+quotedPrintable(ws)+", got "+quotedPrintable(sr.getText())); + } + + /* Char offset refers to input chars, and thus includes original + * linefeed (which is longer than result, for \r\n) + */ + chars += ws.length(); + if (offByOne) { + ++chars; + } + ++linenr; + // Column won't, but since it's one-based, it'll still equal ws len + col = sb.length(); + + assertTokenType(START_ELEMENT, sr.next()); + assertEquals("b", sr.getLocalName()); + loc = sr.getLocationInfo().getStartLocation(); + assertEquals("Line number wrong", linenr, loc.getLineNumber()); + assertEquals("Column number wrong (line "+linenr+")", col, loc.getColumnNumber()); + assertEquals("Character offset wrong (line "+linenr+")", chars, loc.getCharacterOffset()); + assertTokenType(END_ELEMENT, sr.next()); + assertEquals("b", sr.getLocalName()); + + chars += 4; + col += 4; + } + } + + /** + * This test was added due to bug [WSTX-97]: although it is hard to + * verify exact offset calculation, it is quite straight-forward + * to verify that it's monotonically increasing, at least. + */ + public void testOffsetIncrementing() + throws XMLStreamException + { + doTestOffset(false, false); // non-coalesce + doTestOffset(false, true); // non-coalesce + + doTestOffset(true, false); // coalesce + doTestOffset(true, true); // coalesce + } + + /* + ///////////////////////////////////////////////////////// + // Helper methods: + ///////////////////////////////////////////////////////// + */ + + public void doTestOffset(boolean coal, boolean readAll) + throws XMLStreamException + { + // First, let's create some input... + StringBuffer inputBuf = new StringBuffer(); + StringBuffer expOut = new StringBuffer(); + generateData(new Random(123), inputBuf, expOut, true); + String inputStr = inputBuf.toString(); + + WstxInputFactory f = getWstxInputFactory(); + // Should shrink it to get faster convergence + f.getConfig().setInputBufferLength(17); + f.getConfig().doCoalesceText(coal); + XMLStreamReader2 sr = (XMLStreamReader2) f.createXMLStreamReader(new StringReader(inputStr)); + + int lastLine = 0; + int lastOffset = 0; + + while (sr.next() != XMLStreamConstants.END_DOCUMENT) { + Location loc = sr.getLocation(); + int line = loc.getLineNumber(); + int offset = loc.getCharacterOffset(); + + if (line < lastLine) { + fail("Location.getLineNumber() should increase steadily, old value: "+lastLine+", new: "+line); + } + if (offset < lastOffset) { + fail("Location.getCharacterOffset() should increase steadily, old value: "+lastOffset+", new: "+offset); + } + lastLine = line; + lastOffset = offset; + + if (readAll) { // read it, or just skip? + if (sr.hasText()) { + /*String text =*/ sr.getText(); + } + } + } + } +} diff -Nru libwoodstox-java-4.1.3/src/test/java/wstxtest/stream/TestParsingModeForTokens.java libwoodstox-java-5.1.0/src/test/java/wstxtest/stream/TestParsingModeForTokens.java --- libwoodstox-java-4.1.3/src/test/java/wstxtest/stream/TestParsingModeForTokens.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/wstxtest/stream/TestParsingModeForTokens.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,148 @@ +package wstxtest.stream; + +import javax.xml.stream.*; +import javax.xml.stream.events.XMLEvent; + +import org.codehaus.stax2.XMLEventReader2; + +import com.ctc.wstx.api.WstxInputProperties; + +/** + * This unit tests verifies that different input parsing modes + * (set via property {@link WstxInputProperties#P_INPUT_PARSING_MODE}) + * behave as expected + */ +public class TestParsingModeForTokens + extends BaseStreamTest +{ + final static String XML_SINGLE_DOC = + "text" + ; + + final static String XML_MULTI_DOC = + "text\n" + +"text\n" + +"text" + +"text" + +"text" + +"text" + ; + + final static String XML_FRAGMENT = + "textmore" + ; + final static String XML_FRAGMENT2 = + "some text "; + ; + + final static String XML_UNBALANCED = + "text" + ; + + public void testSingleDocumentMode() + throws XMLStreamException + { + // First the valid case: + streamThrough(getReader(XML_SINGLE_DOC, + WstxInputProperties.PARSING_MODE_DOCUMENT)); + + // Others will fail though + streamThroughFailing(getReader(XML_FRAGMENT, + WstxInputProperties.PARSING_MODE_DOCUMENT), + "Expected an exception for fragment (non-single root) input, in single-document mode"); + streamThroughFailing(getReader(XML_FRAGMENT2, + WstxInputProperties.PARSING_MODE_DOCUMENT), + "Expected an exception for fragment (root-level text) input, in single-document mode"); + streamThroughFailing(getReader(XML_MULTI_DOC, + WstxInputProperties.PARSING_MODE_DOCUMENT), + "Expected an exception for multi-document input, in single-document mode"); + + + // As should the generally invalid ones: + streamThroughFailing(getReader(XML_UNBALANCED, + WstxInputProperties.PARSING_MODE_DOCUMENT), + "Expected an exception for unbalanced xml content"); + } + + public void testMultiDocumentMode() throws XMLStreamException + { + // First the main valid case: + streamThroughOk(getReader(XML_MULTI_DOC, + WstxInputProperties.PARSING_MODE_DOCUMENTS), + "multi-doc input in multi-doc mode"); + + // But the alternate cases should actually work too: + streamThroughOk(getReader(XML_SINGLE_DOC, + WstxInputProperties.PARSING_MODE_DOCUMENTS), + "single-doc input in multi-doc mode"); + streamThroughOk(getReader(XML_FRAGMENT, + WstxInputProperties.PARSING_MODE_DOCUMENTS), + "fragment input in multi-doc mode"); + + + // Except for some fragment cases: + streamThroughFailing(getReader(XML_FRAGMENT2, + WstxInputProperties.PARSING_MODE_DOCUMENTS), + "Expected an exception for fragments with root-level textual content"); + + // And broken one not + streamThroughFailing(getReader(XML_UNBALANCED, + WstxInputProperties.PARSING_MODE_DOCUMENTS), + "Expected an exception for unbalanced xml content"); + } + + public void testFragmentMode() + throws XMLStreamException + { + // First the main valid case2: + streamThroughOk(getReader(XML_FRAGMENT, + WstxInputProperties.PARSING_MODE_FRAGMENT), + "fragment input in fragment mode"); + streamThroughOk(getReader(XML_FRAGMENT2, + WstxInputProperties.PARSING_MODE_FRAGMENT), + "fragment input in fragment mode"); + + /* The single doc case actually works, since the xml declaration + * gets handled by the bootstrapper... (kind of implementation + * side effect) + */ + streamThroughOk(getReader(XML_SINGLE_DOC, + WstxInputProperties.PARSING_MODE_FRAGMENT), + "single-doc input in fragment mode"); + + // But multi-doc will fail, due to second xml declaration + streamThroughFailing(getReader(XML_MULTI_DOC, + WstxInputProperties.PARSING_MODE_FRAGMENT), + "Expected an exception for multi-document input, in fragment mode"); + + + // But not the invalid one: + streamThroughFailing(getReader(XML_UNBALANCED, + WstxInputProperties.PARSING_MODE_FRAGMENT), + "Expected an exception for unbalanced xml content"); + } + + /* + //////////////////////////////////////// + // Private methods, other + //////////////////////////////////////// + */ + + private XMLStreamReader getReader(String contents, WstxInputProperties.ParsingMode mode) + throws XMLStreamException + { + XMLInputFactory f = getInputFactory(); + f.setProperty(WstxInputProperties.P_INPUT_PARSING_MODE, mode); + return constructStreamReader(f, contents); + } + + void streamThroughOk(XMLStreamReader sr, String type) + throws XMLStreamException + { + try { + streamThrough(sr); + } catch (XMLStreamException sex) { + fail("Did not expect and exception for "+type+"; got: "+sex); + } + } +} diff -Nru libwoodstox-java-4.1.3/src/test/java/wstxtest/stream/TestPrologWS.java libwoodstox-java-5.1.0/src/test/java/wstxtest/stream/TestPrologWS.java --- libwoodstox-java-4.1.3/src/test/java/wstxtest/stream/TestPrologWS.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/wstxtest/stream/TestPrologWS.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,121 @@ +package wstxtest.stream; + +import java.io.*; + +import javax.xml.stream.*; + +import com.ctc.wstx.stax.WstxInputFactory; + +import wstxtest.cfg.*; + +/** + * Set of unit tests that check how Woodstox handles white space in + * prolog and/or epilog. + */ +import com.ctc.wstx.api.ReaderConfig; + +public class TestPrologWS + extends BaseStreamTest +{ + final static String XML1 = " \n"; + final static String XML2 = "\n \n "; + + public void testReportPrologWS() + throws IOException, XMLStreamException + { + for (int i = 0; i < 8; ++i) { + boolean lazy = (i & 1) == 0; + boolean firstDoc = (i & 2) == 0; + String content = firstDoc ? XML1 : XML2; + boolean streaming = (i & 4) != 0; + XMLStreamReader sr = getReader(content, true, lazy); + + assertTokenType(START_DOCUMENT, sr.getEventType()); + + assertTokenType(SPACE, sr.next()); + String text = streaming ? getStreamingText(sr):getAndVerifyText(sr); + if (firstDoc) { + assertEquals(" ", text); + } else { + assertEquals("\n \n", text); + } + + assertTokenType(START_ELEMENT, sr.next()); + assertTokenType(END_ELEMENT, sr.next()); + + assertTokenType(SPACE, sr.next()); + + text = streaming ? getStreamingText(sr):getAndVerifyText(sr); + if (firstDoc) { + assertEquals("\n", text); + } else { + assertEquals(" ", text); + } + + assertTokenType(END_DOCUMENT, sr.next()); + } + } + + public void testIgnorePrologWS() + throws XMLStreamException + { + for (int i = 0; i < 4; ++i) { + boolean lazy = (i & 1) == 0; + String content = ((i & 2) == 0) ? XML1 : XML2; + XMLStreamReader sr = getReader(content, false, lazy); + + assertTokenType(START_DOCUMENT, sr.getEventType()); + + assertTokenType(START_ELEMENT, sr.next()); + assertEquals("root", sr.getLocalName()); + assertTokenType(END_ELEMENT, sr.next()); + + assertTokenType(END_DOCUMENT, sr.next()); + } + } + + /* + ////////////////////////////////////////////////////// + // Internal methods + ////////////////////////////////////////////////////// + */ + + /** + * Method called via input config iterator, with all possible + * configurations + */ + public void runTest(XMLInputFactory f, InputConfigIterator it) + throws Exception + { + String XML = "" + +"\n" + +" " + +"" + +"\n" + +""; + XMLStreamReader sr = constructStreamReader(f, XML); + + streamAndCheck(sr, it, XML, XML, false); + // Let's also try 'real' streaming... + streamAndCheck(sr, it, XML, XML, true); + } + + /* + //////////////////////////////////////// + // Private methods, other + //////////////////////////////////////// + */ + + private XMLStreamReader getReader(String contents, boolean prologWS, + boolean lazyParsing) + throws XMLStreamException + { + WstxInputFactory f = (WstxInputFactory) getInputFactory(); + ReaderConfig cfg = f.getConfig(); + cfg.doReportPrologWhitespace(prologWS); + cfg.doParseLazily(lazyParsing); + return constructStreamReader(f, contents); + } +} + diff -Nru libwoodstox-java-4.1.3/src/test/java/wstxtest/stream/TestRandomStream.java libwoodstox-java-5.1.0/src/test/java/wstxtest/stream/TestRandomStream.java --- libwoodstox-java-4.1.3/src/test/java/wstxtest/stream/TestRandomStream.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/wstxtest/stream/TestRandomStream.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,163 @@ +package wstxtest.stream; + +import java.util.Random; +import javax.xml.stream.*; + +import wstxtest.cfg.*; + +import com.ctc.wstx.api.ReaderConfig; +import com.ctc.wstx.stax.WstxInputFactory; + +/** + * Unit test suite that ensures that independent of combinations of settings + * such as namespace-awareness, coalescing, automatic entity replacement, + * parsing results remain the same when they should. + */ +public class TestRandomStream + extends BaseStreamTest + implements InputTestMethod +{ + InputConfigIterator mConfigs; + + public TestRandomStream() { + super(); + mConfigs = new InputConfigIterator(); + mConfigs.addConfig(Configs.getLazyParsingConfig()) + .addConfig(Configs.getInputBufferSizeConfig()) + .addConfig(Configs.getMinTextSegmentConfig()) + ; + } + + public void testCoalescingAutoEntity() + throws Exception + { + mReallyStreaming = false; + doTest(false, true, true); // non-ns + doTest(true, true, true); // ns-aware + } + + public void testCoalescingAutoEntityStreaming() + throws Exception + { + mReallyStreaming = true; + doTest(true, true, true); // ns-aware + } + + public void testNonCoalescingAutoEntity() + throws Exception + { + mReallyStreaming = false; + doTest(false, false, true); // non-ns + doTest(true, false, true); // ns-aware + } + + public void testNonCoalescingAutoEntityStreaming() + throws Exception + { + mReallyStreaming = true; + doTest(true, false, true); // ns-aware + } + + public void testCoalescingNonAutoEntity() + throws Exception + { + mReallyStreaming = false; + doTest(false, true, false); // non-ns + doTest(true, true, false); // ns-aware + } + + public void testCoalescingNonAutoEntityStreaming() + throws Exception + { + mReallyStreaming = true; + doTest(true, true, false); // ns-aware + } + + public void testNonCoalescingNonAutoEntity() + throws Exception + { + mReallyStreaming = false; + doTest(false, false, false); // non-ns + doTest(true, false, false); // ns-aware + } + + public void testNonCoalescingNonAutoEntityStreaming() + throws Exception + { + mReallyStreaming = true; + doTest(true, false, false); // ns-aware + } + + /* + //////////////////////////////////////// + // Private methods, common test code + //////////////////////////////////////// + */ + + String mInput; + String mExpOutputNorm; + + boolean mReallyStreaming = false; + boolean mNormalizeLFs = true; + + /** + * Main branching point has settings for standard features; it + * will further need to loop over Woodstox-specific settings. + */ + private void doTest(boolean ns, boolean coalescing, boolean autoEntity) + throws Exception + { + /* Let's generate seed from args so it's reproducible; String hash + * code only depend on text it contains, so it'll be fixed for + * specific String. + */ + String baseArgStr = "ns: "+ns+", coalesce: "+coalescing+", entityExp: "+autoEntity; + long seed = baseArgStr.hashCode(); + + WstxInputFactory f = (WstxInputFactory) getInputFactory(); + ReaderConfig cfg = f.getConfig(); + + // Settings we always need: + cfg.doSupportDTDs(true); + cfg.doValidateWithDTD(false); + + // Then variable ones we got settings for: + cfg.doSupportNamespaces(ns); + cfg.doCoalesceText(coalescing); + cfg.doReplaceEntityRefs(autoEntity); + + /* How many random permutations do we want to try? + */ + final int ROUNDS = 5; + + for (int round = 0; round < ROUNDS; ++round) { + Random r = new Random(seed+round); + StringBuffer inputBuf = new StringBuffer(1000); + StringBuffer expOutputBuf = new StringBuffer(1000); + + generateData(r, inputBuf, expOutputBuf, autoEntity); + + mInput = inputBuf.toString(); + normalizeLFs(expOutputBuf); + mExpOutputNorm = expOutputBuf.toString(); + mConfigs.iterate(f, this); + } + } + + /** + * Method called via input config iterator, with all possible + * configurations + */ + @Override + public void runTest(XMLInputFactory f, InputConfigIterator it) + throws Exception + { + String exp = mExpOutputNorm; + + // First, let's skip through it all + streamAndSkip(f, it, mInput); + + // and then the 'real' test: + streamAndCheck(f, it, mInput, exp, mReallyStreaming); + } +} diff -Nru libwoodstox-java-4.1.3/src/test/java/wstxtest/stream/TestStreaming.java libwoodstox-java-5.1.0/src/test/java/wstxtest/stream/TestStreaming.java --- libwoodstox-java-4.1.3/src/test/java/wstxtest/stream/TestStreaming.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/wstxtest/stream/TestStreaming.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,158 @@ +package wstxtest.stream; + +import java.io.*; + +import javax.xml.stream.*; + +import org.codehaus.stax2.XMLStreamReader2; + +import com.ctc.wstx.stax.WstxInputFactory; + +/** + * This test verifies that the "fully streaming" text access method(s) + * do not return partial text/CDATA segments no matter what the mode + * is. + *

+ * Note that although this test should really be part of StAX2 test + * suite, currently there is no standard way to define properties that + * would make it more likely that the parser may return partial + * text segments; but Woodstox does. So, for now we can at least + * test that Woodstox is conformant... ;-) + */ +public class TestStreaming + extends BaseStreamTest +{ + public void testTextStreaming() + throws IOException, XMLStreamException + { + String CONTENT_IN = + "Some content\nthat will be " + +""streamed" & sliced" + +" and\nprocessed..."; + ; + String CONTENT_OUT = + "Some content\nthat will be " + +"\"streamed\" & sliced" + +" and\nprocessed..."; + ; + /* Let's also add trailing CDATA, to ensure no coalescing is done + * when not requested + */ + String XML = "" + CONTENT_IN + ""; + XMLStreamReader2 sr = getReader(XML, false); + assertTokenType(START_ELEMENT, sr.next()); + assertTokenType(CHARACTERS, sr.next()); + StringWriter sw = new StringWriter(); + sr.getText(sw, false); + String act = sw.toString(); + if (!act.equals(CONTENT_OUT)) { + if (CONTENT_OUT.startsWith(act)) { + fail("Streaming text accessors returned partial match; first " + +act.length()+" chars of the expected " + +CONTENT_OUT.length()+" chars"); + } + fail("Content accessed using streaming text accessor (len " + +act.length()+"; exp "+CONTENT_OUT.length()+" chars) wrong: " + +"expected ["+CONTENT_OUT+"], got ["+act+"]"); + } + + // And should get the following CDATA, then: + assertTokenType(CDATA, sr.next()); + // and then closing element; let's not check CDATA contents here + assertTokenType(END_ELEMENT, sr.next()); + } + + public void testCDataStreaming() + throws IOException, XMLStreamException + { + String CONTENT_INOUT = + "Some content\nthat will be stored in a\n" + +"CDATA Block <[*]>\n" + +" yet not be split in any way...." + ; + /* Let's also add trailing text, to ensure no coalescing is done + * when not requested + */ + String XML = "some text!"; + XMLStreamReader2 sr = getReader(XML, false); + assertTokenType(START_ELEMENT, sr.next()); + assertTokenType(CDATA, sr.next()); + StringWriter sw = new StringWriter(); + sr.getText(sw, false); + String act = sw.toString(); + if (!act.equals(CONTENT_INOUT)) { + if (CONTENT_INOUT.startsWith(act)) { + fail("Streaming text accessors returned partial match; first " + +act.length()+" chars of the expected " + +CONTENT_INOUT.length()+" chars"); + } + fail("Content accessed using streaming text accessor (len " + +act.length()+"; exp "+CONTENT_INOUT.length()+" chars) wrong: " + +"expected ["+CONTENT_INOUT+"], got ["+act+"]"); + } + + // And should get the following CHARACTERS then: + assertTokenType(CHARACTERS, sr.next()); + // and then closing element; let's not check text contents here + assertTokenType(END_ELEMENT, sr.next()); + } + + /** + * Let's also ensure that coalescing still works ok with streaming + * as well... + */ + public void testCoalescingStreaming() + throws IOException, XMLStreamException + { + String CONTENT_IN1 = + "First text\n cdata " + ; + String CONTENT_OUT1 = "First text\n and cdata ..."; + String CONTENT_IN2 = + " and textneat-o!"; + ; + String CONTENT_OUT2 = "Then CDATA and text...\nneat-o!"; + + for (int i = 0; i < 2; ++i) { + boolean first = (i == 0); + String XML = "" + (first ? CONTENT_IN1 : CONTENT_IN2) + ""; + XMLStreamReader2 sr = getReader(XML, true); + assertTokenType(START_ELEMENT, sr.next()); + assertTokenType(CHARACTERS, sr.next()); + StringWriter sw = new StringWriter(); + sr.getText(sw, false); + String act = sw.toString(); + String exp = first ? CONTENT_OUT1 : CONTENT_OUT2; + if (!act.equals(exp)) { + if (exp.startsWith(act)) { + fail("Streaming text accessors returned partial match; first " + +act.length()+" chars of the expected " + +exp.length()+" chars"); + } + fail("Content accessed using streaming text accessor (len " + +act.length()+"; exp "+exp.length()+" chars) wrong: " + +"expected ["+exp+"], got ["+act+"]"); + } + // and then closing element + assertTokenType(END_ELEMENT, sr.next()); + } + } + + /* + ////////////////////////////////////////////////////// + // Internal methods + ////////////////////////////////////////////////////// + */ + + private XMLStreamReader2 getReader(String contents, boolean coalesce) + throws XMLStreamException + { + WstxInputFactory f = getWstxInputFactory(); + f.getConfig().doSupportNamespaces(true); + f.getConfig().doCoalesceText(coalesce); + f.getConfig().setInputBufferLength(16); + f.getConfig().setShortestReportedTextSegment(4); + return constructStreamReader(f, contents); + } + +} diff -Nru libwoodstox-java-4.1.3/src/test/java/wstxtest/stream/TestTreatCharRefAsEnts.java libwoodstox-java-5.1.0/src/test/java/wstxtest/stream/TestTreatCharRefAsEnts.java --- libwoodstox-java-4.1.3/src/test/java/wstxtest/stream/TestTreatCharRefAsEnts.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/wstxtest/stream/TestTreatCharRefAsEnts.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,118 @@ +/** + * $Id$ + * + * (c) 2006 acrolinx GmbH All rights reserved. + * + * Created on 09.04.2010 Last changed: $Date$ + * + * @author schwarz, last changed by $Author$ + * @version $Revision$ + */ + +package wstxtest.stream; + +import javax.xml.stream.Location; +import javax.xml.stream.XMLInputFactory; +import javax.xml.stream.XMLStreamException; + +import com.ctc.wstx.api.WstxInputProperties; +import com.ctc.wstx.ent.EntityDecl; +import com.ctc.wstx.sr.BasicStreamReader; + +/** + * @author schwarz + * + */ +public class TestTreatCharRefAsEnts + extends BaseStreamTest +{ + protected static void setTreatCharRefsAsEnts(XMLInputFactory f, boolean state) + throws XMLStreamException + { + f.setProperty(WstxInputProperties.P_TREAT_CHAR_REFS_AS_ENTS, + state ? Boolean.TRUE : Boolean.FALSE); + } + + public void testReturnEntityForCharReference() throws Exception + { + + String XML = "text & more"; + + BasicStreamReader sr = getReader(XML, true, true, 1); + + assertTokenType(START_ELEMENT, sr.next()); + assertEquals("root", sr.getLocalName()); + + assertTokenType(CHARACTERS, sr.next()); + + assertEquals("text ", sr.getText()); + + assertTokenType(ENTITY_REFERENCE, sr.next()); + assertEquals("amp", sr.getLocalName()); + EntityDecl ed = sr.getCurrentEntityDecl(); + assertNotNull(ed); + assertEquals("amp", ed.getName()); + assertEquals("&", ed.getReplacementText()); + + // The pure stax way: + assertEquals("&", sr.getText()); + + // Finally, let's see that location info is about right? + Location loc = sr.getCurrentLocation(); + assertNotNull(loc); + assertEquals(16, loc.getCharacterOffset()); + } + + public void testReturnCharsReference() throws Exception + { + String XML = "text & more"; + + // 64 is the default + BasicStreamReader sr = getReader(XML, true, false, 1); + + assertTokenType(START_ELEMENT, sr.next()); + assertEquals("root", sr.getLocalName()); + + assertTokenType(CHARACTERS, sr.next()); + assertEquals("text ", sr.getText()); + + assertTokenType(CHARACTERS, sr.next()); + assertEquals("& more", sr.getText()); + } + + public void testReturnCharsReferenceWithHighMinTextSegment() throws Exception + { + String XML = "text & more"; + + // 64 is the default + BasicStreamReader sr = getReader(XML, true, true, 64); + + assertTokenType(START_ELEMENT, sr.next()); + assertEquals("root", sr.getLocalName()); + + assertTokenType(CHARACTERS, sr.next()); + + assertEquals("text & more", sr.getText()); + } + + private BasicStreamReader getReader(String contents, boolean replEntities, + boolean treatCharRefsAsEnts, int minTextSegment) + throws XMLStreamException + { + XMLInputFactory f = getConfiguredFactory(replEntities, treatCharRefsAsEnts, minTextSegment); + return (BasicStreamReader) constructStreamReader(f, contents); + } + + private XMLInputFactory getConfiguredFactory(boolean replEntities, boolean treatCharRefsAsEnts, + int minTextSegment) + throws XMLStreamException + { + XMLInputFactory f = getInputFactory(); + setValidating(f, false); + setReplaceEntities(f, replEntities); + setTreatCharRefsAsEnts(f, treatCharRefsAsEnts); + setMinTextSegment(f, minTextSegment); + return f; + } + +} diff -Nru libwoodstox-java-4.1.3/src/test/java/wstxtest/stream/TestXml11.java libwoodstox-java-5.1.0/src/test/java/wstxtest/stream/TestXml11.java --- libwoodstox-java-4.1.3/src/test/java/wstxtest/stream/TestXml11.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/wstxtest/stream/TestXml11.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,109 @@ +package wstxtest.stream; + +import javax.xml.stream.*; + +/** + * This is a small test suite has some checks for features of xml 1.1 + * that are different from those of 1.0. + */ +public class TestXml11 + extends BaseStreamTest +{ + /** + * This test checks that it is illegal to try to unbind a prefix; + * only default namespace can be unbound. + */ + public void testInvalidUnbinding() + throws XMLStreamException + { + final String XML = + "" + +"" + +"" + ; + XMLStreamReader sr = getReader(XML); + assertTokenType(START_ELEMENT, sr.next()); + // This should result in an exception: + try { + /*int type =*/ sr.next(); // usually fails here + /*type =*/ sr.next(); // but if not, at least here (END_ELEMENT) + fail("Expected a stream exception due to namespace unbind for xml 1.0 document"); + } catch (XMLStreamException sex) { + ; //good + } + } + + /** + * Test case adapted from XMLTest (based on + * xmlconf/eduni/namespaces/1.1/004.xml) + */ + public void testValidRebinding() + throws XMLStreamException + { + final String XML = + "" ++"" ++"" ++"" ++"" ++"" + ; + XMLStreamReader sr = getReader(XML); + assertTokenType(START_ELEMENT, sr.next()); // foo + assertEquals("foo", sr.getLocalName()); + + assertTokenType(START_ELEMENT, sr.next()); // bar + assertEquals("bar", sr.getLocalName()); + + assertTokenType(START_ELEMENT, sr.next()); // foo (inner) + assertEquals("foo", sr.getLocalName()); + + assertTokenType(END_ELEMENT, sr.next()); // /foo (inner) + assertEquals("foo", sr.getLocalName()); + assertTokenType(END_ELEMENT, sr.next()); // /bar + assertEquals("bar", sr.getLocalName()); + assertTokenType(END_ELEMENT, sr.next()); // /foo + assertEquals("foo", sr.getLocalName()); + } + + /** + * Test case adapted from XMLTest (based on + * xmlconf/eduni/namespaces/1.1/005.xml) + */ + public void testInvalidUseOfUnbound() + throws XMLStreamException + { + final String XML = + "" + +"" + +"" + ; + XMLStreamReader sr = getReader(XML); + assertTokenType(START_ELEMENT, sr.next()); + // This should result in an exception: + try { + sr.next(); // usually fails here + sr.next(); // but if not, at least here + fail("Expected a stream exception due to a reference to an explicitly unbound prefix 'a'"); + } catch (XMLStreamException sex) { + ; //good + } + } + + /* + ////////////////////////////////////////////////// + // Helper methods + ////////////////////////////////////////////////// + */ + + private XMLStreamReader getReader(String contents) + throws XMLStreamException + { + XMLInputFactory f = getWstxInputFactory(); + setNamespaceAware(f, true); + setCoalescing(f, false); + setValidating(f, false); + setSupportDTD(f, false); + return constructStreamReader(f, contents); + } +} diff -Nru libwoodstox-java-4.1.3/src/test/java/wstxtest/stream/TestXmlId.java libwoodstox-java-5.1.0/src/test/java/wstxtest/stream/TestXmlId.java --- libwoodstox-java-4.1.3/src/test/java/wstxtest/stream/TestXmlId.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/wstxtest/stream/TestXmlId.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,207 @@ +package wstxtest.stream; + +import javax.xml.stream.*; + +import org.codehaus.stax2.XMLInputFactory2; +import org.codehaus.stax2.XMLStreamReader2; +import org.codehaus.stax2.validation.XMLValidationException; + +/** + * Set of unit tests that check that Woodstox support for Xml:id works + * as expected. + */ +public class TestXmlId + extends BaseStreamTest +{ + final static String XML_WITH_XMLID = + "" + +"" + +"" + +"" + +"" + ; + + final static String XML_WITH_XMLID_INVALID = + "\n" + +"\n" + +"]>" + ; + + public void testXmlIdEnabledNs() + throws XMLStreamException + { + doTestXmlId(true, true, false); // xmlid enabled, non-coal + doTestXmlId(true, true, true); // xmlid enabled, coal + } + + public void testXmlIdDisabledNs() + throws XMLStreamException + { + doTestXmlId(false, true, false); // xmlid disabled, non-coal + doTestXmlId(false, true, true); // xmlid disabled, coal + } + + public void testXmlIdEnabledNonNs() + throws XMLStreamException + { + doTestXmlId(true, false, false); // xmlid enabled, non-coal + doTestXmlId(true, false, true); // xmlid enabled, coal + } + + public void testXmlIdDisabledNonNs() + throws XMLStreamException + { + doTestXmlId(false, false, false); // xmlid disabled, non-coal + doTestXmlId(false, false, true); // xmlid disabled, coal + } + + /** + * This unit test verifies that incorrect DTD attribute type for + * xml:id causes a validation exception + */ + public void testInvalidXmlIdNs() + throws XMLStreamException + { + doTestInvalid(true, false); + doTestInvalid(true, true); + } + + public void testInvalidXmlIdNonNs() + throws XMLStreamException + { + doTestInvalid(false, false); + doTestInvalid(false, true); + } + + public void testInvalidXmlIdDisabledNs() + throws XMLStreamException + { + doTestInvalidDisabled(true, false); + doTestInvalidDisabled(true, true); + } + + public void testInvalidXmlIdDisabledNonNs() + throws XMLStreamException + { + doTestInvalidDisabled(false, false); + doTestInvalidDisabled(false, true); + } + + /* + ///////////////////////////////////// + // + ///////////////////////////////////// + */ + + private void doTestXmlId(boolean xmlidEnabled, + boolean nsAware, boolean coal) + throws XMLStreamException + { + XMLStreamReader2 sr = getReader(XML_WITH_XMLID, xmlidEnabled, nsAware, coal); + final String xmlidType = xmlidEnabled ? "ID" : "CDATA"; + + // root: + assertTokenType(START_ELEMENT, sr.next()); + assertEquals(1, sr.getAttributeCount()); + assertEquals("id", sr.getAttributeLocalName(0)); + assertEquals("CDATA", sr.getAttributeType(0)); + assertEquals(-1, sr.getAttributeInfo().getIdAttributeIndex()); + + // leaf#1: + assertTokenType(START_ELEMENT, sr.next()); + assertEquals(1, sr.getAttributeCount()); + assertEquals("abc", sr.getAttributeValue(0)); + if (xmlidEnabled) { + assertEquals(0, sr.getAttributeInfo().getIdAttributeIndex()); + } else { + assertEquals(-1, sr.getAttributeInfo().getIdAttributeIndex()); + } + assertEquals(xmlidType, sr.getAttributeType(0)); + assertTokenType(END_ELEMENT, sr.next()); + + // leaf#2: + assertTokenType(START_ELEMENT, sr.next()); + assertEquals(1, sr.getAttributeCount()); + assertEquals("foobar", sr.getAttributeValue(0)); + assertEquals("id", sr.getAttributeLocalName(0)); + assertEquals(-1, sr.getAttributeInfo().getIdAttributeIndex()); + assertEquals("CDATA", sr.getAttributeType(0)); + assertTokenType(END_ELEMENT, sr.next()); + + // leaf#3: + assertTokenType(START_ELEMENT, sr.next()); + assertEquals(1, sr.getAttributeCount()); + assertEquals(xmlidType, sr.getAttributeType(0)); + if (xmlidEnabled) { + assertEquals(0, sr.getAttributeInfo().getIdAttributeIndex()); + } else { + assertEquals(-1, sr.getAttributeInfo().getIdAttributeIndex()); + } + + // also, should be normalized: + if (xmlidEnabled) { + assertEquals("_otherId", sr.getAttributeValue(0)); + } else { + assertEquals(" _otherId ", sr.getAttributeValue(0)); + } + assertTokenType(END_ELEMENT, sr.next()); + + sr.close(); + } + + private void doTestInvalid(boolean nsAware, boolean coal) + throws XMLStreamException + { + XMLStreamReader2 sr = getValidatingReader(XML_WITH_XMLID_INVALID, nsAware, coal); + try { + assertTokenType(DTD, sr.next()); + assertTokenType(START_ELEMENT, sr.next()); + fail("Expected a validation exception for invalid Xml:id attribute declaration"); + } catch (XMLValidationException vex) { + //System.err.println("VLD exc -> "+vex); + } + } + + private void doTestInvalidDisabled(boolean nsAware, boolean coal) + throws XMLStreamException + { + /* In non-validating mode, shouldn't matter: but just to make sure, + * let's also disable xml:id processing + */ + XMLStreamReader2 sr = getReader(XML_WITH_XMLID_INVALID, false, nsAware, coal); + assertTokenType(DTD, sr.next()); + assertTokenType(START_ELEMENT, sr.next()); + } + + private XMLStreamReader2 getReader(String contents, + boolean xmlidEnabled, + boolean nsAware, boolean coal) + throws XMLStreamException + { + XMLInputFactory2 f = getInputFactory(); + setSupportDTD(f, true); + setValidating(f, false); + setCoalescing(f, coal); + setNamespaceAware(f, nsAware); + f.setProperty(XMLInputFactory2.XSP_SUPPORT_XMLID, + xmlidEnabled + ? XMLInputFactory2.XSP_V_XMLID_TYPING + : XMLInputFactory2.XSP_V_XMLID_NONE); + return constructStreamReader(f, contents); + } + + private XMLStreamReader2 getValidatingReader(String contents, + boolean nsAware, boolean coal) + throws XMLStreamException + { + XMLInputFactory2 f = getInputFactory(); + setSupportDTD(f, true); + setValidating(f, true); + setCoalescing(f, coal); + setNamespaceAware(f, nsAware); + f.setProperty(XMLInputFactory2.XSP_SUPPORT_XMLID, + XMLInputFactory2.XSP_V_XMLID_TYPING); + return constructStreamReader(f, contents); + } +} diff -Nru libwoodstox-java-4.1.3/src/test/java/wstxtest/TestDefaultNamespacePrefix.java libwoodstox-java-5.1.0/src/test/java/wstxtest/TestDefaultNamespacePrefix.java --- libwoodstox-java-4.1.3/src/test/java/wstxtest/TestDefaultNamespacePrefix.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/wstxtest/TestDefaultNamespacePrefix.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,49 @@ + +package wstxtest; + +import java.io.StringReader; + +import javax.xml.stream.XMLInputFactory; +import javax.xml.stream.XMLStreamReader; + +import com.ctc.wstx.api.WstxInputProperties; + +/** + * @since 4.1.2 + */ +public class TestDefaultNamespacePrefix extends BaseWstxTest +{ + public void testDefaultNamespacePrefixAsNull() throws Exception + { + String XML = "foo"; +// System.setProperty("com.ctc.wstx.returnNullForDefaultNamespace", "true"); + XMLInputFactory factory = getNewInputFactory(); + + assertEquals(Boolean.FALSE, factory.getProperty(WstxInputProperties.P_RETURN_NULL_FOR_DEFAULT_NAMESPACE)); + + factory.setProperty(WstxInputProperties.P_RETURN_NULL_FOR_DEFAULT_NAMESPACE, true); + XMLStreamReader r = factory.createXMLStreamReader(new StringReader(XML)); + assertTokenType(START_ELEMENT, r.next()); + String prefix = r.getNamespacePrefix(0); + if (prefix != null) { + fail("Null value is not returned for the default namespace prefix while " + + WstxInputProperties.P_RETURN_NULL_FOR_DEFAULT_NAMESPACE + " is set true"); + } + } + + public void testDefaultNamespacePrefixAsEmptyString() throws Exception + { + String XML = "foo"; +// System.setProperty("com.ctc.wstx.returnNullForDefaultNamespace", "false"); + XMLInputFactory factory = getNewInputFactory(); + assertEquals(Boolean.FALSE, factory.getProperty(WstxInputProperties.P_RETURN_NULL_FOR_DEFAULT_NAMESPACE)); +// factory.setProperty(WstxInputProperties.P_RETURN_NULL_FOR_DEFAULT_NAMESPACE, false); + XMLStreamReader r = factory.createXMLStreamReader(new StringReader(XML)); + assertTokenType(START_ELEMENT, r.next()); + String prefix = r.getNamespacePrefix(0); + if (!"".equals(prefix)) { + fail("Null value is returned for the default namespace prefix while " + + WstxInputProperties.P_RETURN_NULL_FOR_DEFAULT_NAMESPACE + " is set false"); + } + } +} diff -Nru libwoodstox-java-4.1.3/src/test/java/wstxtest/TestInputFactory.java libwoodstox-java-5.1.0/src/test/java/wstxtest/TestInputFactory.java --- libwoodstox-java-4.1.3/src/test/java/wstxtest/TestInputFactory.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/wstxtest/TestInputFactory.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,67 @@ +package wstxtest; + +import javax.xml.stream.*; + +import org.codehaus.stax2.*; + +import com.ctc.wstx.cfg.ErrorConsts; +import com.ctc.wstx.api.ReaderConfig; +import com.ctc.wstx.stax.WstxInputFactory; + +/** + * Simple test-driver that tries to exercise some of basic input factory + * settings, like instantiating various reader instances, checking for + * invalid arguments and so on. + */ +public class TestInputFactory + extends BaseWstxTest +{ + public void testConfig() + throws XMLStreamException + { + XMLInputFactory2 f = getNewInputFactory(); + + ReaderConfig cfg = ((WstxInputFactory) f).getConfig(); + assertNotNull(cfg); + + assertNull(f.getEventAllocator()); + assertNull(f.getXMLResolver()); + + assertNull(f.getXMLReporter()); + MyReporter rep = new MyReporter(); + f.setXMLReporter(rep); + assertEquals(rep, f.getXMLReporter()); + + assertFalse(f.isPropertySupported("foobar")); + } + + public void testMisc() + throws XMLStreamException + { + /* This is silly, but coverage testing is not happy that our + * error-constant-defining class is never constructed. + * So here we go, just to mark it off the list... + */ + ErrorConsts ec = new ErrorConsts(); + assertNotNull(ec); // silly, but otherwise eclipse would about unused.. + assertNotNull(ErrorConsts.tokenTypeDesc(XMLStreamConstants.START_DOCUMENT)); + assertNotNull(ErrorConsts.tokenTypeDesc(XMLStreamConstants.END_DOCUMENT)); + assertNotNull(ErrorConsts.tokenTypeDesc(XMLStreamConstants.ATTRIBUTE)); + } + + /* + //////////////////////////////////////////////////////////// + // Non-test methods etc + //////////////////////////////////////////////////////////// + */ + + final static class MyReporter + implements XMLReporter + { + @Override + public void report(String message, String errorType, Object relatedInformation, Location location) + { + // fine... + } + } +} diff -Nru libwoodstox-java-4.1.3/src/test/java/wstxtest/TestOutputFactory.java libwoodstox-java-5.1.0/src/test/java/wstxtest/TestOutputFactory.java --- libwoodstox-java-4.1.3/src/test/java/wstxtest/TestOutputFactory.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/wstxtest/TestOutputFactory.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,82 @@ +package wstxtest; + +import javax.xml.stream.*; + +import org.codehaus.stax2.*; + +import com.ctc.wstx.api.WriterConfig; +import com.ctc.wstx.api.WstxInputProperties; +import com.ctc.wstx.api.WstxOutputProperties; +import com.ctc.wstx.stax.WstxOutputFactory; + +/** + * Simple test-driver that tries to exercise some of basic output factory + * settings, like instantiating various writer instances, checking for + * invalid arguments and so on. + */ +public class TestOutputFactory + extends BaseWstxTest +{ + public void testConfig() + throws XMLStreamException + { + XMLOutputFactory2 f = getNewOutputFactory(); + + WriterConfig cfg = ((WstxOutputFactory) f).getConfig(); + assertNotNull(cfg); + + assertFalse(f.isPropertySupported("foobar")); + + // Let's just test some of known properties that should be supported... + assertTrue(f.isPropertySupported(WstxOutputProperties.P_OUTPUT_VALIDATE_STRUCTURE)); + assertTrue(f.isPropertySupported(WstxOutputProperties.P_OUTPUT_VALIDATE_CONTENT)); + + // And their default values? + assertEquals(Boolean.TRUE, f.getProperty(WstxOutputProperties.P_OUTPUT_VALIDATE_STRUCTURE)); + assertEquals(Boolean.TRUE, f.getProperty(WstxOutputProperties.P_OUTPUT_VALIDATE_CONTENT)); + + assertEquals(Boolean.FALSE, f.getProperty(WstxOutputProperties.P_OUTPUT_VALIDATE_ATTR)); + assertEquals(Boolean.FALSE, f.getProperty(WstxOutputProperties.P_OUTPUT_VALIDATE_NAMES)); + assertEquals(Boolean.FALSE, f.getProperty(WstxOutputProperties.P_OUTPUT_CDATA_AS_TEXT)); + assertEquals(Boolean.FALSE, f.getProperty(WstxOutputProperties.P_COPY_DEFAULT_ATTRS)); + + // As per [WSTX-120], default with Woodstox 4.0 is false: + assertEquals(Boolean.FALSE, f.getProperty(WstxOutputProperties.P_OUTPUT_FIX_CONTENT)); + assertEquals(Boolean.TRUE, f.getProperty(XMLOutputFactory2.P_AUTOMATIC_EMPTY_ELEMENTS)); + assertEquals(Boolean.TRUE, f.getProperty(XMLStreamProperties.XSP_NAMESPACE_AWARE)); + + assertNull(f.getProperty(XMLStreamProperties.XSP_PROBLEM_REPORTER)); + assertNull(f.getProperty(XMLOutputFactory2.P_TEXT_ESCAPER)); + assertNull(f.getProperty(XMLOutputFactory2.P_ATTR_VALUE_ESCAPER)); + + // ... which can be changed + f.setProperty(WstxOutputProperties.P_OUTPUT_VALIDATE_STRUCTURE, Boolean.FALSE); + assertEquals(Boolean.FALSE, f.getProperty(WstxOutputProperties.P_OUTPUT_VALIDATE_STRUCTURE)); + + f.setProperty(WstxOutputProperties.P_OUTPUT_VALIDATE_CONTENT, Boolean.FALSE); + assertEquals(Boolean.FALSE, f.getProperty(WstxOutputProperties.P_OUTPUT_VALIDATE_CONTENT)); + + f.setProperty(WstxOutputProperties.P_OUTPUT_VALIDATE_CONTENT, Boolean.FALSE); + assertEquals(Boolean.FALSE, f.getProperty(WstxOutputProperties.P_OUTPUT_VALIDATE_CONTENT)); + + f.setProperty(WstxOutputProperties.P_OUTPUT_VALIDATE_NAMES, Boolean.TRUE); + assertEquals(Boolean.TRUE, f.getProperty(WstxOutputProperties.P_OUTPUT_VALIDATE_NAMES)); + f.setProperty(WstxOutputProperties.P_OUTPUT_VALIDATE_ATTR, Boolean.TRUE); + assertEquals(Boolean.TRUE, f.getProperty(WstxOutputProperties.P_OUTPUT_VALIDATE_ATTR)); + } + + public void testMisc() + throws XMLStreamException + { + /* This is silly, but coverage testing is not happy that our + * constant-defining classes are never constructed. So here we go, + * just to mark it off the list... + */ + WstxInputProperties fooin = new WstxInputProperties(); + WstxOutputProperties fooout = new WstxOutputProperties(); + + // These just to keep compilers/FindBugs etc happy + assertNotNull(fooin); + assertNotNull(fooout); + } +} diff -Nru libwoodstox-java-4.1.3/src/test/java/wstxtest/util/TestArgUtil.java libwoodstox-java-5.1.0/src/test/java/wstxtest/util/TestArgUtil.java --- libwoodstox-java-4.1.3/src/test/java/wstxtest/util/TestArgUtil.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/wstxtest/util/TestArgUtil.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,56 @@ +package wstxtest.util; + +import java.util.*; + +import junit.framework.TestCase; + +import com.ctc.wstx.util.ArgUtil; + +/** + * Simple unit tests for testing methods in {@link ArgUtil}. + */ +public class TestArgUtil + extends TestCase +{ + public void testBoolean() + { + assertFalse(ArgUtil.convertToBoolean("test", "false")); + assertFalse(ArgUtil.convertToBoolean("test", "False")); + assertFalse(ArgUtil.convertToBoolean("test", "FALSE")); + assertTrue(ArgUtil.convertToBoolean("test", "true")); + assertTrue(ArgUtil.convertToBoolean("test", "True")); + assertTrue(ArgUtil.convertToBoolean("test", "TRUE")); + assertFalse(ArgUtil.convertToBoolean("test", null)); + + // and then errors: + try { + /*boolean b =*/ ArgUtil.convertToBoolean("test", new Integer(0)); + fail("Expected an IllegalArgumentException"); + } catch (IllegalArgumentException iae) { } + + try { + /*boolean b =*/ ArgUtil.convertToBoolean("test", "foobar"); + fail("Expected an IllegalArgumentException"); + } catch (IllegalArgumentException iae) { } + } + + public void testInt() + { + assertEquals(14, ArgUtil.convertToInt("test", "14", 0)); + assertEquals(14, ArgUtil.convertToInt("test", new Integer(14), 0)); + assertEquals(14, ArgUtil.convertToInt("test", new Long(14L), 0)); + assertEquals(14, ArgUtil.convertToInt("test", new Short((short) 14), 0)); + assertEquals(14, ArgUtil.convertToInt("test", new Byte((byte) 14), 0)); + + // and then errors: + try { + /*int x =*/ ArgUtil.convertToInt("test", new HashMap(), 0); + fail("Expected an IllegalArgumentException"); + } catch (IllegalArgumentException iae) { } + + try { + /*int x =*/ ArgUtil.convertToInt("test", "foobar", 0); + fail("Expected an IllegalArgumentException"); + } catch (IllegalArgumentException iae) { } + } +} diff -Nru libwoodstox-java-4.1.3/src/test/java/wstxtest/util/TestBijectiveNsMap.java libwoodstox-java-5.1.0/src/test/java/wstxtest/util/TestBijectiveNsMap.java --- libwoodstox-java-4.1.3/src/test/java/wstxtest/util/TestBijectiveNsMap.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/wstxtest/util/TestBijectiveNsMap.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,51 @@ +package wstxtest.util; + +import java.util.*; + +import junit.framework.TestCase; + +import com.ctc.wstx.util.BijectiveNsMap; + +/** + * Unit test to verify problem [WSTX-202]. + */ +public class TestBijectiveNsMap + extends TestCase +{ + public void testMaskingForFindPrefix() throws Exception + { + BijectiveNsMap nsMap = BijectiveNsMap.createEmpty(); + nsMap.addMapping("ns", "abc"); + assertEquals("ns", nsMap.findPrefixByUri("abc")); + // and then let's mask it + nsMap = nsMap.createChild(); + nsMap.addMapping("ns", "xyz"); + String uri = nsMap.findPrefixByUri("abc"); + if (uri != null) { + fail("Expected null for masked prefix, got '"+uri+"'"); + } + } + + public void testMaskingForGetBoundPrefixes() throws Exception + { + BijectiveNsMap nsMap = BijectiveNsMap.createEmpty(); + nsMap.addMapping("ns", "abc"); + List l = nsMap.getPrefixesBoundToUri("abc", null); + assertEquals(1, l.size()); + assertEquals("ns", l.iterator().next()); + + // and then let's mask it + nsMap = nsMap.createChild(); + nsMap.addMapping("ns", "xyz"); + assertEquals(0, nsMap.getPrefixesBoundToUri("abc", new ArrayList()).size()); + + // and finally, let's re-bind it + nsMap = nsMap.createChild(); + nsMap.addMapping("ns", "abc"); + assertEquals(1, nsMap.getPrefixesBoundToUri("abc", null).size()); + + // and add another similar binding + nsMap.addMapping("ns2", "abc"); + assertEquals(2, nsMap.getPrefixesBoundToUri("abc", null).size()); + } +} diff -Nru libwoodstox-java-4.1.3/src/test/java/wstxtest/util/TestDataUtil.java libwoodstox-java-5.1.0/src/test/java/wstxtest/util/TestDataUtil.java --- libwoodstox-java-4.1.3/src/test/java/wstxtest/util/TestDataUtil.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/wstxtest/util/TestDataUtil.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,101 @@ +package wstxtest.util; + +import java.util.*; + +import junit.framework.TestCase; + +import com.ctc.wstx.util.DataUtil; + +/** + * Simple unit tests for testing methods in {@link DataUtil}. + */ +public class TestDataUtil + extends TestCase +{ + public void testBasic() + { + char[] empty = DataUtil.getEmptyCharArray(); + assertEquals(0, empty.length); + } + + public void testContainment() + { + // First, no match: + + Collection c1 = new HashSet(); + c1.add("foo"); + c1.add(new String("bar")); + Collection c2 = new ArrayList(); + c2.add("foobar"); + c2.add(new Integer(3)); + + assertFalse(DataUtil.anyValuesInCommon(c1, c2)); + + // Then a match + c1.add(new Integer(3)); + assertTrue(DataUtil.anyValuesInCommon(c1, c2)); + + // And another one: + c2.clear(); + c2.add("bar"); + assertTrue(DataUtil.anyValuesInCommon(c1, c2)); + } + + public void testExpansion() + { + final int MAGIC_INDEX = 1; + + final int MAGIC_INT = 732; + final String MAGIC_STRING = "yeehaw"; + + int[] ia = new int[6]; + // let's also add a marker to test + ia[MAGIC_INDEX] = MAGIC_INT; + int[] ia2 = (int[]) DataUtil.growArrayBy50Pct(ia); + assertEquals(9, ia2.length); + assertEquals(MAGIC_INT, ia2[MAGIC_INDEX]); + ia2 = (int[]) DataUtil.growArrayToAtLeast(ia, 7); + if (ia2.length < 7) { + fail("Expected array to grow to at least 7, was "+ia.length); + } + assertEquals(MAGIC_INT, ia2[MAGIC_INDEX]); + ia2 = DataUtil.growArrayBy(ia, 2); + assertEquals(8, ia2.length); + assertEquals(MAGIC_INT, ia2[MAGIC_INDEX]); + ia2 = DataUtil.growArrayBy((int[])null, 4); + assertEquals(4, ia2.length); + // no magic value, should just have 0 + assertEquals(0, ia2[MAGIC_INDEX]); + + String[] s1 = new String[10]; + s1[MAGIC_INDEX] = MAGIC_STRING; + String[] s2 = (String[]) DataUtil.growArrayBy50Pct(s1); + assertEquals(15, s2.length); + assertEquals(MAGIC_STRING, s2[MAGIC_INDEX]); + s2 = (String[]) DataUtil.growArrayToAtLeast(s1, 19); + if (s2.length < 19) { + fail("Expected array to grow to at least 19, was "+s2.length); + } + s2 = DataUtil.growArrayBy(s1, 3); + assertEquals(13, s2.length); + assertEquals(MAGIC_STRING, s2[MAGIC_INDEX]); + s2 = DataUtil.growArrayBy((String[])null, 3); + assertEquals(3, s2.length); + // nothing to copy from + assertNull(s2[MAGIC_INDEX]); + + // And then exceptions... + try { + s2 = (String[]) DataUtil.growArrayBy50Pct((String[])null); + fail("Expected an IllegalArgumentException when passing null"); + } catch (IllegalArgumentException ie) { + ; // good + } + try { + s2 = (String[]) DataUtil.growArrayToAtLeast((String[])null, 5); + fail("Expected an IllegalArgumentException when passing null"); + } catch (IllegalArgumentException ie) { + ; // good + } + } +} diff -Nru libwoodstox-java-4.1.3/src/test/java/wstxtest/util/TestStringUtil.java libwoodstox-java-5.1.0/src/test/java/wstxtest/util/TestStringUtil.java --- libwoodstox-java-4.1.3/src/test/java/wstxtest/util/TestStringUtil.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/wstxtest/util/TestStringUtil.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,96 @@ +package wstxtest.util; + +import java.util.*; + +import com.ctc.wstx.util.StringUtil; + +/** + * Simple unit tests for testing methods of {@link StringUtil} utility + * class. + */ +public class TestStringUtil + extends wstxtest.BaseWstxTest +{ + public void testConcatEntries() + { + List l = new ArrayList(); + l.add("first"); + l.add("second"); + l.add("third"); + assertEquals("first, second and third", + StringUtil.concatEntries(l, ", ", " and ")); + + l = new ArrayList(); + l.add("the only"); + assertEquals("the only", + StringUtil.concatEntries(l, ", ", " and ")); + } + + public void testIsAllWhitespace() + { + assertTrue(StringUtil.isAllWhitespace(" \r \r\n \t")); + assertTrue(StringUtil.isAllWhitespace(" ")); + assertTrue(StringUtil.isAllWhitespace(" ".toCharArray(), 0, 1)); + assertTrue(StringUtil.isAllWhitespace("\r\n\t")); + assertTrue(StringUtil.isAllWhitespace("\r\n\t".toCharArray(), 0, 3)); + assertTrue(StringUtil.isAllWhitespace("x \t".toCharArray(), 1, 2)); + assertTrue(StringUtil.isAllWhitespace("")); + assertTrue(StringUtil.isAllWhitespace(new char[0], 0, 0)); + + assertFalse(StringUtil.isAllWhitespace("x")); + assertFalse(StringUtil.isAllWhitespace(" !")); + } + + public void testNormalizeSpaces() + { + String str = " my my"; + assertEquals("my my", StringUtil.normalizeSpaces(str.toCharArray(), 0, + str.length())); + + str = "foo bar"; + assertEquals("foo bar", StringUtil.normalizeSpaces(str.toCharArray(), 0, + str.length())); + + str = "my_my"; + assertFalse("my my".equals(StringUtil.normalizeSpaces(str.toCharArray(), + 0, str.length()))); + + str = "Xoh no Z!"; + assertEquals("oh no", + StringUtil.normalizeSpaces(str.toCharArray(), 1, + str.length() - 3)); + + + /* Also, how about other white-space; not to be normalized fully, + * so in this case should get null (no normalization done) + */ + str = "some \t text"; + String result = StringUtil.normalizeSpaces(str.toCharArray(), 0, str.length()); + if (result != null) { + fail("Expected , not '"+quotedPrintable(result)+"' when normalizing '"+quotedPrintable(str)+"'"); + } + } + + public void testEqualEncodings() + { + assertTrue(StringUtil.equalEncodings("utf-8", "utf-8")); + assertTrue(StringUtil.equalEncodings("UTF-8", "utf-8")); + assertTrue(StringUtil.equalEncodings("UTF-8", "utf8")); + assertTrue(StringUtil.equalEncodings("UTF8", "utf_8")); + assertTrue(StringUtil.equalEncodings("US_ASCII", "us-ascii")); + assertTrue(StringUtil.equalEncodings("utf 8", "Utf-8")); + + assertFalse(StringUtil.equalEncodings("utf-8", "utf-16")); + assertFalse(StringUtil.equalEncodings("isolatin", "iso-8859-1")); + assertFalse(StringUtil.equalEncodings("utf8", "utf")); + } + + public void testMatches() + { + String STR = "fooBar!"; + String STR2 = "foobar_"; + assertTrue(StringUtil.matches(STR, STR.toCharArray(), 0, STR.length())); + assertFalse(StringUtil.matches(STR, STR.toCharArray(), 0, STR.length()-1)); + assertFalse(StringUtil.matches(STR, STR2.toCharArray(), 0, STR2.length())); + } +} diff -Nru libwoodstox-java-4.1.3/src/test/java/wstxtest/util/TestStringVector.java libwoodstox-java-5.1.0/src/test/java/wstxtest/util/TestStringVector.java --- libwoodstox-java-4.1.3/src/test/java/wstxtest/util/TestStringVector.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/wstxtest/util/TestStringVector.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,37 @@ +package wstxtest.util; + +import junit.framework.TestCase; + +import com.ctc.wstx.util.StringVector; + +/** + * Simple unit tests for testing {@link StringVector}. + */ +public class TestStringVector + extends TestCase +{ + public void testBasic() + { + StringVector sv = new StringVector(2); + + sv.addString("foo"); + sv.addString("xyz"); + assertEquals(2, sv.size()); + sv.addStrings("bar", "foo2"); + assertEquals(4, sv.size()); + sv.setString(3, "foo3"); + assertEquals(4, sv.size()); + assertEquals("foo3", sv.getString(3)); + + sv.addString(new String("foo")); // so as to be different from entry 0 + sv.addString(new String("bar")); + assertEquals("foo", sv.getString(4)); + // this uses identity + assertEquals("xyz", sv.findLastFromMap("foo")); + // and this equality + assertEquals("bar", sv.findLastNonInterned("foo")); + + sv.clear(true); + assertEquals(0, sv.size()); + } +} diff -Nru libwoodstox-java-4.1.3/src/test/java/wstxtest/util/TestTextAccumulator.java libwoodstox-java-5.1.0/src/test/java/wstxtest/util/TestTextAccumulator.java --- libwoodstox-java-4.1.3/src/test/java/wstxtest/util/TestTextAccumulator.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/wstxtest/util/TestTextAccumulator.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,45 @@ +package wstxtest.util; + +import junit.framework.TestCase; + +import com.ctc.wstx.util.TextAccumulator; + +/** + * Simple unit tests for testing {@link TextAccumulator}. That class + * is generally used to try to minimize shuffling between char arrays, + * Strings and StringBuilders -- most common case being that only one + * instance is passed, before a String is needed. + */ +public class TestTextAccumulator + extends TestCase +{ + public void testBasic() + { + TextAccumulator acc = new TextAccumulator(); + + acc.addText("foo"); + assertEquals("foo", acc.getAndClear()); + + acc.addText("foo".toCharArray(), 0, 3); + acc.addText("bar"); + assertEquals("foobar", acc.getAndClear()); + } + + // as per [WSTX-349] + public void testBasicWithCharArray() + { + TextAccumulator acc = new TextAccumulator(); + + acc.addText("foobar".toCharArray(), 3, 5); + assertEquals("ba", acc.getAndClear()); + + acc.addText("xxfoo".toCharArray(), 2, 5); + acc.addText("bar".toCharArray(), 2, 3); + acc.addText(new char[] { '1', '2', '3' }, 2, 3); + assertEquals("foor3", acc.getAndClear()); + + acc.addText("a"); + acc.addText(new char[] { '1', '2', '3' }, 2, 3); + assertEquals("a3", acc.getAndClear()); + } +} diff -Nru libwoodstox-java-4.1.3/src/test/java/wstxtest/util/TestTextBuffer.java libwoodstox-java-5.1.0/src/test/java/wstxtest/util/TestTextBuffer.java --- libwoodstox-java-4.1.3/src/test/java/wstxtest/util/TestTextBuffer.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/wstxtest/util/TestTextBuffer.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,44 @@ +package wstxtest.util; + +import junit.framework.TestCase; + +import com.ctc.wstx.util.TextBuffer; + +/** + * Simple unit tests for testing {@link TextBuffer}. + */ +public class TestTextBuffer + extends TestCase +{ + public void testBasic() + { + String INPUT = "Whatever input text doesn't really matter but should have some content " + +"so as not to be too short"; + TextBuffer tb = TextBuffer.createTemporaryBuffer(); + final char[] ch = new char[1]; + for (int i = 0, len = INPUT.length(); i < len; ++i) { + if ((i & 1) != 0) { + ch[0] = INPUT.charAt(i); + tb.append(ch, 0, 1); + } else { + tb.append(INPUT.substring(i, i+1)); + } + } + + assertEquals(INPUT, tb.toString()); + assertEquals(INPUT, tb.contentsAsString()); + assertFalse(tb.endsWith("shor")); + assertTrue(tb.endsWith("so as not to be too short")); + assertFalse(tb.isAllWhitespace()); + + assertTrue(tb.equalsString(INPUT)); + + /* + tb.clear(); + + assertEquals("", tb.toString()); + assertEquals("", tb.contentsAsString()); + */ + } +} + diff -Nru libwoodstox-java-4.1.3/src/test/java/wstxtest/util/TestURLUtil.java libwoodstox-java-5.1.0/src/test/java/wstxtest/util/TestURLUtil.java --- libwoodstox-java-4.1.3/src/test/java/wstxtest/util/TestURLUtil.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/wstxtest/util/TestURLUtil.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,26 @@ +package wstxtest.util; + +import com.ctc.wstx.util.URLUtil; + +import junit.framework.TestCase; + +/** + * Tests for [WSTX-275] + */ +public class TestURLUtil extends TestCase +{ + public void testUriCreationFromSystemIdWithPipe() throws Exception { + URLUtil.uriFromSystemId("file:///C|/InfoShare/Web/Author/ASP/DocTypes/dita-oasis/1.2/technicalContent/dtd/map.dtd"); + URLUtil.urlFromSystemId("file:///C|/InfoShare/Web/Author/ASP/DocTypes/dita-oasis/1.2/technicalContent/dtd/map.dtd"); + } + + public void testRelativePath() throws Exception { + URLUtil.uriFromSystemId("relative/path/to/dtd"); + URLUtil.urlFromSystemId("relative/path/to/dtd"); + } + + public void testAbsoluteUnixPath() throws Exception { + URLUtil.uriFromSystemId("file:///absolute/path/to/dtd"); + URLUtil.urlFromSystemId("file:///absolute/path/to/dtd"); + } +} diff -Nru libwoodstox-java-4.1.3/src/test/java/wstxtest/util/TestWordResolver.java libwoodstox-java-5.1.0/src/test/java/wstxtest/util/TestWordResolver.java --- libwoodstox-java-4.1.3/src/test/java/wstxtest/util/TestWordResolver.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/wstxtest/util/TestWordResolver.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,106 @@ +package wstxtest.util; + +import java.util.*; + +import junit.framework.TestCase; + +import com.ctc.wstx.util.WordResolver; + +/** + * Simple unit tests for testing {@link WordResolver}. + */ +public class TestWordResolver + extends TestCase +{ + public void testNormal() + { + checkResolver(new String[] { + "word", "123", "len", "length", + "leno", "1", "foobar", + }, new String[] { + "foo", "21", "__", "12", "lengt", + }); + } + + /** + * This unit test was created as a regression test, to check for + * a bug that was found during development. + */ + public void testSingle() + { + // this caused an arrayindexoutofbounds exception + checkResolver(new String[] { "CDATA" }, + new String[] { "value", "aaa", "ZZZ", "CDAT" }); + + checkResolver(new String[] { "somethingelse" }, + new String[] { "value", "aaa", "ZZZ", "CDAT" }); + } + + /** + * This unit test tries to verify that things work ok with even bigger + * word sets + */ + public void testLarge() + { + // this caused an arrayindexoutofbounds exception + checkResolver(new String[] { + "a", "a1", "a2", "a4", "a5", "a6", "ab", "az", "a9", "aa", "ax", + "c", "ca", "caa", "caaa", "caad", "caaa", + }, new String[] { + "a3", "aA", "a0", "b" + }); + } + + /* + /////////////////////////////////////////////////////// + // Private methods: + /////////////////////////////////////////////////////// + */ + + private void checkResolver(String[] words, String[] missingWords) + { + TreeSet set = new TreeSet(); + for (int i = 0, len = words.length; i < len; ++i) { + set.add(words[i]); + } + + WordResolver wr = WordResolver.constructInstance(set); + + assertEquals(wr.size(), set.size()); + + Iterator it = set.iterator(); + + // Let's first check if words that should be there, are: + while (it.hasNext()) { + String str = it.next(); + + assertEquals(str, wr.find(str)); + // And then, let's make sure intern()ing isn't needed: + assertEquals(str, wr.find(""+str)); + + char[] strArr = str.toCharArray(); + char[] strArr2 = new char[strArr.length + 4]; + System.arraycopy(strArr, 0, strArr2, 3, strArr.length); + assertEquals(str, wr.find(strArr, 0, str.length())); + assertEquals(str, wr.find(strArr2, 3, str.length() + 3)); + } + + // And then that ones shouldn't be there aren't: + for (int i = 0, len = missingWords.length; i < len; ++i) { + checkNotFind(wr, missingWords[i]); + } + } + + private void checkNotFind(WordResolver wr, String str) + { + char[] strArr = str.toCharArray(); + char[] strArr2 = new char[strArr.length + 4]; + System.arraycopy(strArr, 0, strArr2, 1, strArr.length); + + assertNull(wr.find(str)); + assertNull(wr.find(strArr, 0, strArr.length)); + assertNull(wr.find(strArr2, 1, strArr.length + 1)); + } + +} + diff -Nru libwoodstox-java-4.1.3/src/test/java/wstxtest/util/TestWordSet.java libwoodstox-java-5.1.0/src/test/java/wstxtest/util/TestWordSet.java --- libwoodstox-java-4.1.3/src/test/java/wstxtest/util/TestWordSet.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/wstxtest/util/TestWordSet.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,68 @@ +package wstxtest.util; + +import java.util.*; + +import junit.framework.TestCase; + +import com.ctc.wstx.util.WordSet; + +/** + * Simple unit tests for testing {@link WordSet}. + */ +public class TestWordSet + extends TestCase +{ + public TestWordSet(String name) { + super(name); + } + + public void testNormal() + { + TreeSet set = new TreeSet(); + + set.add("word"); + set.add("123"); + set.add("len"); + set.add("length"); + set.add("leno"); + set.add("1"); + set.add("foobar"); + + WordSet ws = WordSet.constructSet(set); + + // Let's first check if words that should be there, are: + for (String str : set) { + assertTrue(ws.contains(str)); + // And then, let's make sure intern()ing isn't needed: + assertTrue(ws.contains(""+str)); + + char[] strArr = str.toCharArray(); + char[] strArr2 = new char[strArr.length + 4]; + System.arraycopy(strArr, 0, strArr2, 3, strArr.length); + assertTrue(ws.contains(strArr, 0, str.length())); + assertTrue(ws.contains(strArr2, 3, str.length() + 3)); + } + + // And then that ones shouldn't be there aren't: + checkNotFind(ws, "foo"); + + } + + /* + /////////////////////////////////////////////////////// + // Private methods: + /////////////////////////////////////////////////////// + */ + + private void checkNotFind(WordSet ws, String str) + { + char[] strArr = str.toCharArray(); + char[] strArr2 = new char[strArr.length + 4]; + System.arraycopy(strArr, 0, strArr2, 1, strArr.length); + + assertFalse(ws.contains(str)); + assertFalse(ws.contains(strArr, 0, strArr.length)); + assertFalse(ws.contains(strArr2, 1, strArr.length + 1)); + } +} + diff -Nru libwoodstox-java-4.1.3/src/test/java/wstxtest/util/TestXmlChars.java libwoodstox-java-5.1.0/src/test/java/wstxtest/util/TestXmlChars.java --- libwoodstox-java-4.1.3/src/test/java/wstxtest/util/TestXmlChars.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/wstxtest/util/TestXmlChars.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,73 @@ +package wstxtest.util; + +import junit.framework.TestCase; + +import com.ctc.wstx.io.WstxInputData; + +/** + * Simple unit tests for testing methods in {@link com.ctc.wstx.util.XmlChars} + * and {@link com.ctc.wstx.io.WstxInputData} + */ +public class TestXmlChars + extends TestCase +{ + public void testXml10Chars() + { + // First, 8-bit range: + assertTrue(WstxInputData.isNameStartChar('F', true, false)); + assertTrue(WstxInputData.isNameChar('F', true, false)); + assertTrue(WstxInputData.isNameStartChar('_', true, false)); + assertTrue(WstxInputData.isNameChar('_', true, false)); + assertTrue(WstxInputData.isNameChar('x', true, false)); + assertFalse(WstxInputData.isNameStartChar('-', true, false)); + assertTrue(WstxInputData.isNameChar('-', true, false)); + assertFalse(WstxInputData.isNameStartChar('.', true, false)); + assertTrue(WstxInputData.isNameChar('.', true, false)); + + // Then more exotic chars: + + assertTrue(WstxInputData.isNameStartChar((char) 0x03ce, true, false)); + assertTrue(WstxInputData.isNameChar((char) 0x03ce, true, false)); + assertTrue(WstxInputData.isNameStartChar((char) 0x0e21, true, false)); + assertTrue(WstxInputData.isNameChar((char) 0x0e21, true, false)); + assertTrue(WstxInputData.isNameStartChar((char) 0x3007, true, false)); + assertFalse(WstxInputData.isNameStartChar(' ', true, false)); + /* colon is NOT a start char for this method; although it is + * in xml specs -- reason has to do with namespace handling + */ + assertFalse(WstxInputData.isNameStartChar(':', true, false)); + + assertFalse(WstxInputData.isNameStartChar((char) 0x3008, true, false)); + assertFalse(WstxInputData.isNameChar((char) 0x3008, true, false)); + assertTrue(WstxInputData.isNameStartChar((char) 0x30ea, true, false)); + assertTrue(WstxInputData.isNameChar((char) 0x30ea, true, false)); + } + + public void testXml11NameStartChars() + { + // First, 8-bit range: + assertTrue(WstxInputData.isNameStartChar('F', true, true)); + assertTrue(WstxInputData.isNameChar('F', true, true)); + assertTrue(WstxInputData.isNameStartChar('_', true, true)); + assertTrue(WstxInputData.isNameChar('_', true, true)); + assertTrue(WstxInputData.isNameChar('x', true, true)); + assertFalse(WstxInputData.isNameStartChar('-', true, true)); + assertTrue(WstxInputData.isNameChar('-', true, true)); + assertFalse(WstxInputData.isNameStartChar('.', true, true)); + assertTrue(WstxInputData.isNameChar('.', true, true)); + + // Then more exotic chars: + + assertTrue(WstxInputData.isNameStartChar((char) 0x03ce, true, true)); + assertTrue(WstxInputData.isNameChar((char) 0x03ce, true, true)); + assertTrue(WstxInputData.isNameStartChar((char) 0x0e21, true, true)); + assertTrue(WstxInputData.isNameChar((char) 0x0e21, true, true)); + assertTrue(WstxInputData.isNameStartChar((char) 0x3007, true, true)); + assertFalse(WstxInputData.isNameStartChar(' ', true, true)); + /* colon is NOT a start char for this method; although it is + * in xml specs -- reason has to do with namespace handling + */ + assertFalse(WstxInputData.isNameStartChar(':', true, true)); + assertFalse(WstxInputData.isNameStartChar((char) 0x3000, true, true)); + } +} diff -Nru libwoodstox-java-4.1.3/src/test/java/wstxtest/vstream/BaseValidationTest.java libwoodstox-java-5.1.0/src/test/java/wstxtest/vstream/BaseValidationTest.java --- libwoodstox-java-4.1.3/src/test/java/wstxtest/vstream/BaseValidationTest.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/wstxtest/vstream/BaseValidationTest.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,82 @@ +package wstxtest.vstream; + +import java.io.StringReader; +import java.net.URL; + +import javax.xml.stream.XMLStreamException; + +import org.codehaus.stax2.XMLStreamReader2; +import org.codehaus.stax2.validation.*; + +public abstract class BaseValidationTest + extends wstxtest.stream.BaseStreamTest +{ + protected XMLValidationSchema parseSchema(String contents, String schemaType) + throws XMLStreamException + { + XMLValidationSchemaFactory schF = XMLValidationSchemaFactory.newInstance(schemaType); + return schF.createSchema(new StringReader(contents)); + } + + protected XMLValidationSchema parseSchema(URL ref, String schemaType) + throws XMLStreamException + { + XMLValidationSchemaFactory schF = XMLValidationSchemaFactory.newInstance(schemaType); + return schF.createSchema(ref); + } + + protected XMLValidationSchema parseRngSchema(String contents) + throws XMLStreamException + { + return parseSchema(contents, XMLValidationSchema.SCHEMA_ID_RELAXNG); + } + + protected XMLValidationSchema parseDTDSchema(String contents) + throws XMLStreamException + { + return parseSchema(contents, XMLValidationSchema.SCHEMA_ID_DTD); + } + + protected XMLValidationSchema parseW3CSchema(String contents) + throws XMLStreamException + { + return parseSchema(contents, XMLValidationSchema.SCHEMA_ID_W3C_SCHEMA); + } + + protected void verifyFailure(String xml, XMLValidationSchema schema, String failMsg, + String failPhrase) throws XMLStreamException + { + // default to strict handling: + verifyFailure(xml, schema, failMsg, failPhrase, true); + } + + protected void verifyFailure(String xml, XMLValidationSchema schema, String failMsg, + String failPhrase, boolean strict) throws XMLStreamException + { + XMLStreamReader2 sr = constructStreamReader(getInputFactory(), xml); + sr.validateAgainst(schema); + try { + while (sr.hasNext()) { + /* int type = */sr.next(); + } + fail("Expected validity exception for " + failMsg); + } catch (XMLValidationException vex) { + String origMsg = vex.getMessage(); + String msg = (origMsg == null) ? "" : origMsg.toLowerCase(); + if (msg.indexOf(failPhrase.toLowerCase()) < 0) { + String actualMsg = "Expected validation exception for " + + failMsg + ", containing phrase '" + failPhrase + + "': got '" + origMsg + "'"; + if (strict) { + fail(actualMsg); + } + warn("suppressing failure due to MSV bug, failure: '" + + actualMsg + "'"); + } + // should get this specific type; not basic stream exception + } catch (XMLStreamException sex) { + fail("Expected XMLValidationException for " + failMsg + + "; instead got " + sex.getMessage()); + } + } +} diff -Nru libwoodstox-java-4.1.3/src/test/java/wstxtest/vstream/TestDTD.java libwoodstox-java-5.1.0/src/test/java/wstxtest/vstream/TestDTD.java --- libwoodstox-java-4.1.3/src/test/java/wstxtest/vstream/TestDTD.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/wstxtest/vstream/TestDTD.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,190 @@ +package wstxtest.vstream; + +import java.io.*; +import java.net.*; + +import javax.xml.stream.*; + +import org.codehaus.stax2.XMLStreamReader2; +import org.codehaus.stax2.validation.*; + +/** + * This test suite should really be part of wstx-tools package, but since + * there is some supporting code within core Woodstox, it was added here. + * That way it is easier to check that no DTDFlatten functionality is + * broken by low-level changes. + */ +public class TestDTD + extends BaseValidationTest +{ + final static class MyReporter implements XMLReporter + { + public int count = 0; + + @Override + public void report(String message, String errorType, Object relatedInformation, Location location) + { + ++count; + } + } + + final static String SIMPLE_DTD = + "\n" + +"\n" + +"\n" + ; + + /** + * Test to show how [WSTX-190] occurs. + */ + public void testMissingAttrWithReporter() + throws XMLStreamException + { + String XML = "\n" + +"]>"; + MyReporter rep = new MyReporter(); + XMLStreamReader sr = getValidatingReader(XML, rep); + assertTokenType(DTD, sr.next()); + // and now should get a validation problem + assertTokenType(START_ELEMENT, sr.next()); + assertTokenType(END_ELEMENT, sr.next()); + sr.close(); + assertEquals(1, rep.count); + } + + public void testFullValidationOk() throws XMLStreamException + { + String XML = ""; + XMLValidationSchema schema = parseDTDSchema(SIMPLE_DTD); + XMLStreamReader2 sr = getReader(XML); + sr.validateAgainst(schema); + while (sr.next() != END_DOCUMENT) { } + sr.close(); + } + + // [woodstox#23] + public void testFullValidationIssue23() throws XMLStreamException + { + final String INPUT_DTD = "\n" + +"\n" + ; + String XML = "foobar"; + XMLInputFactory f = getInputFactory(); + + /* + Resolver resolver = new XMLResolver() { + @Override + public Object resolveEntity(String publicID, String systemID, String baseURI, String namespace) { + return new StringReader(DTD); + } + }; + f.setXMLResolver(resolver); + */ + + XMLValidationSchemaFactory schemaFactory = + XMLValidationSchemaFactory.newInstance(XMLValidationSchema.SCHEMA_ID_DTD); + XMLValidationSchema schema = schemaFactory.createSchema(new StringReader(INPUT_DTD)); + XMLStreamReader2 sr = (XMLStreamReader2)f.createXMLStreamReader( + new StringReader(XML)); + + sr.validateAgainst(schema); + while (sr.next() != END_DOCUMENT) { + /* + System.err.println("Curr == "+sr.getEventType()); + if (sr.getEventType() == CHARACTERS) { + System.err.println(" text: "+sr.getText()); + } + */ + } + sr.close(); + } + + /** + * And then a test for validating starting when stream points + * to START_ELEMENT + */ + public void testPartialValidationOk() + throws XMLStreamException + { + String XML = ""; + XMLValidationSchema schema = parseDTDSchema(SIMPLE_DTD); + XMLStreamReader2 sr = getReader(XML); + assertTokenType(START_ELEMENT, sr.next()); + sr.validateAgainst(schema); + while (sr.next() != END_DOCUMENT) { } + sr.close(); + } + + /* + * Another test for checking that validation does end when + * sub-tree ends... + */ + /* 29-Apr-2009, TSa: Actually: not a valid test; as per + * Stax2 v3.0 javadocs, validation does NOT end with + * sub-tree... + */ + /* + public void testPartialValidationFollowedBy() + throws XMLStreamException + { + String XML = ""; + XMLValidationSchema schema = parseDTDSchema(SIMPLE_DTD); + XMLStreamReader2 sr = getReader(XML); + assertTokenType(START_ELEMENT, sr.next()); + assertEquals("x", sr.getLocalName()); + assertTokenType(START_ELEMENT, sr.next()); + assertEquals("root", sr.getLocalName()); + sr.validateAgainst(schema); + while (sr.next() != END_DOCUMENT) { } + sr.close(); + } + */ + + /** + * Test to verify [WSTX-207] + */ + public void testSchemaWithFunnyFilename() + throws Exception + { + // assuming CWD is the svn root + // 2014-05-19, tatu: Very fragile, should read via resource. But: + File f = new File("").getAbsoluteFile(); + f = new File(f, "src"); + f = new File(f, "test"); + f = new File(f, "java"); + f = new File(f, "wstxtest"); + f = new File(f, "empty and spaces.dtd"); + + URL url = f.toURI().toURL(); + + XMLValidationSchema sch = parseSchema(url, XMLValidationSchema.SCHEMA_ID_DTD); + assertNotNull(sch); + } + + /* + ////////////////////////////////////////////////////// + // Helper methods + ////////////////////////////////////////////////////// + */ + + private XMLStreamReader2 getReader(String contents) + throws XMLStreamException + { + XMLInputFactory f = getInputFactory(); + setValidating(f, false); + return constructStreamReader(f, contents); + } + + private XMLStreamReader getValidatingReader(String contents, XMLReporter rep) + throws XMLStreamException + { + XMLInputFactory f = getInputFactory(); + if (rep != null) { + f.setProperty(XMLInputFactory.REPORTER, rep); + } + setSupportDTD(f, true); + setValidating(f, true); + return constructStreamReader(f, contents); + } +} diff -Nru libwoodstox-java-4.1.3/src/test/java/wstxtest/vstream/TestFlattening.java libwoodstox-java-5.1.0/src/test/java/wstxtest/vstream/TestFlattening.java --- libwoodstox-java-4.1.3/src/test/java/wstxtest/vstream/TestFlattening.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/wstxtest/vstream/TestFlattening.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,81 @@ +package wstxtest.vstream; + +import java.io.*; + +import javax.xml.stream.*; + +import com.ctc.wstx.api.ReaderConfig; +import com.ctc.wstx.cfg.XmlConsts; +import com.ctc.wstx.dtd.DTDSubset; +import com.ctc.wstx.dtd.FullDTDReader; +import com.ctc.wstx.io.DefaultInputResolver; +import com.ctc.wstx.io.WstxInputSource; + +import wstxtest.stream.BaseStreamTest; + +/** + * This test suite should really be part of wstx-tools package, but since + * there is some supporting code within core Woodstox, it was added here. + * That way it is easier to check that no DTDFlatten functionality is + * broken by low-level changes. + */ +public class TestFlattening + extends BaseStreamTest +{ + public void testFlatteningInclusive() + throws IOException, XMLStreamException + { + /* Note: since we deal with this as an external resource, it may + * need encoding pseudo-attribute if there's xml declaration + */ + final String INPUT_DTD = + "\n" + +"\n" + +"\n" + +"\n" + +"'>\n" + +"\n" + +"\n" + +"\n" + +"]]>\n" + +"\n" + +"%pe;\n" + +"\n" + +"\r\n" + ; + //StringReader strr = new StringReader(DTD); + ReaderConfig cfg = ReaderConfig.createFullDefaults(); + for (int i = 0; i < 8; ++i) { + boolean inclComments = (i & 4) != 0; + boolean inclConditionals = (i & 2) != 0; + boolean inclPEs = (i & 1) != 0; + WstxInputSource input = DefaultInputResolver.sourceFromString + (null, cfg, "[dtd]", /*xml version for compat checks*/ XmlConsts.XML_V_UNKNOWN, INPUT_DTD); + StringWriter strw = new StringWriter(); + /*DTDSubset ss =*/ FullDTDReader.flattenExternalSubset + (input, strw, + inclComments, inclConditionals, inclPEs); + strw.flush(); + String output = strw.toString(); + + /* Ok, so... how do we test it? For now, let's actually + * just re-parse it to ensure it seems valid? And let's also + * compare second-time output. + */ + input = DefaultInputResolver.sourceFromString + (null, cfg, "[dtd]", /*xml version for compatibility checks*/ XmlConsts.XML_V_UNKNOWN, output); + + strw = new StringWriter(); + DTDSubset ss = FullDTDReader.flattenExternalSubset + (input, strw, inclComments, inclConditionals, inclPEs); + assertNotNull(ss); + strw.flush(); + String output2 = strw.toString(); + + assertEquals(output, output2); + } + } +} + diff -Nru libwoodstox-java-4.1.3/src/test/java/wstxtest/vstream/TestRelaxNG.java libwoodstox-java-5.1.0/src/test/java/wstxtest/vstream/TestRelaxNG.java --- libwoodstox-java-4.1.3/src/test/java/wstxtest/vstream/TestRelaxNG.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/wstxtest/vstream/TestRelaxNG.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,544 @@ +package wstxtest.vstream; + +import javax.xml.stream.*; + +import org.codehaus.stax2.*; +import org.codehaus.stax2.validation.*; + +/** + * This is a simple base-line "smoke test" that checks that RelaxNG + * validation works at least minimally. + */ +public class TestRelaxNG + extends BaseValidationTest +{ + final static String SIMPLE_RNG_SCHEMA = + "\n" + +" \n" + +" \n" + +" \n" + +" \n" + +" \n" + +" \n" + +" \n" + +" \n" + +" \n" + +" \n" + +" \n" + +" \n" + +"" + ; + + /** + * Similar schema, but one that uses namespaces + */ + final static String SIMPLE_RNG_NS_SCHEMA = + "\n" + +" \n" + +" \n" + +" \n" + +" \n" + +" \n" + +" \n" + +" \n" + +" \n" + +" \n" + +" \n" + +" \n" + +"" + ; + + /** + * Test validation against a simple document valid according + * to a simple RNG schema. + */ + public void testSimpleNonNs() + throws XMLStreamException + { + String XML = + "" + +"\n" + +" \n" + +" foobar\n" + +" Foo Bar\n" + +" " + +" \n" + +" fuzzy\n" + +" adjective\n" + +" " + +"" + ; + + XMLValidationSchema schema = parseRngSchema(SIMPLE_RNG_SCHEMA); + XMLStreamReader2 sr = getReader(XML); + sr.validateAgainst(schema); + + try { + assertTokenType(START_ELEMENT, sr.next()); + assertEquals("dict", sr.getLocalName()); + + while (sr.hasNext()) { + sr.next(); + } + } catch (XMLValidationException vex) { + fail("Did not expect validation exception, got: "+vex); + } + + assertTokenType(END_DOCUMENT, sr.getEventType()); + } + + /** + * This unit test checks for couple of simple validity problems + * against the simple rng schema. It does not use namespaces + * (a separate test is needed for ns handling). + */ + public void testInvalidNonNs() + throws XMLStreamException + { + XMLValidationSchema schema = parseRngSchema(SIMPLE_RNG_SCHEMA); + + // First, wrong root element: + String XML = "\n" + +" foobar\n" + +" Foo Bar\n" + +""; + verifyRngFailure(XML, schema, "wrong root element", + "is not allowed. Possible tag names are"); + + // Then, wrong child ordering: + XML = "\n" + +"\n" + +" Foo Bar\n" + +" foobar\n" + +""; + verifyRngFailure(XML, schema, "illegal child element ordering", + "tag name \"description\" is not allowed. Possible tag names are"); + + // Then, missing children: + XML = "\n" + +"\n" + +""; + verifyRngFailure(XML, schema, "missing children", + "uncompleted content model. expecting: "); + + XML = "\n" + +"\n" + +"word" + +""; + verifyRngFailure(XML, schema, "incomplete children", + "uncompleted content model. expecting: "); + + // Then illegal text in non-mixed element + XML = "\n" + +"No text allowed here" + +" foobar\n" + +" Foo Bar\n" + +""; + verifyRngFailure(XML, schema, "invalid non-whitespace text", + "Element has non-mixed content specification; can not contain non-white space text"); + + // missing attribute + XML = "\n" + +"" + +" foobar\n" + +" Foo Bar\n" + +""; + // Then undeclared attributes + XML = "\n" + +"" + +" foobar\n" + +" Foo Bar\n" + +""; + verifyRngFailure(XML, schema, "undeclared attribute", + "unexpected attribute \"attr\""); + XML = "\n" + +"" + +" foobar\n" + +" Foo Bar\n" + +""; + verifyRngFailure(XML, schema, "undeclared attribute", + "unexpected attribute \"type\""); + } + + public void testSimpleNs() + throws XMLStreamException + { + String XML = "\n" + +" \n" + +" \n" + +"" + ; + + XMLValidationSchema schema = parseRngSchema(SIMPLE_RNG_NS_SCHEMA); + XMLStreamReader2 sr = getReader(XML); + sr.validateAgainst(schema); + + try { + assertTokenType(START_ELEMENT, sr.next()); + assertEquals("root", sr.getLocalName()); + + while (sr.hasNext()) { + sr.next(); + } + } catch (XMLValidationException vex) { + fail("Did not expect validation exception, got: "+vex); + } + + assertTokenType(END_DOCUMENT, sr.getEventType()); + } + + /** + * Unit test checks that the namespace matching works as + * expected. + */ + public void testInvalidNs() + throws XMLStreamException + { + XMLValidationSchema schema = parseRngSchema(SIMPLE_RNG_NS_SCHEMA); + + // First, wrong root element: + String XML = "\n" + +"\n" + +""; + verifyRngFailure(XML, schema, "wrong root element", + "namespace URI of tag \"root\" is wrong"); + + // Wrong child namespace + XML = "\n" + +"\n" + +""; + verifyRngFailure(XML, schema, "wrong child element namespace", + "namespace URI of tag \"leaf\" is wrong."); + + // Wrong attribute namespace + XML = "\n" + +"\n" + +""; + verifyRngFailure(XML, schema, "wrong attribute namespace", + "unexpected attribute \"attr1\""); + } + + /** + * This unit test verifies that the validation can be stopped + * half-way through processing, so that sub-trees (for example) + * can be validated. In this case, we will verify this functionality + * by trying to validate invalid document up to the point where it + * is (or may) still be valid, stop validation, and then continue + * reading. This should not result in an exception. + */ + public void testSimplePartialNonNs() + throws XMLStreamException + { + String XML = + "" + +"" + +"" + +"" + +"" + ; + + XMLValidationSchema schema = parseRngSchema(SIMPLE_RNG_SCHEMA); + + XMLStreamReader2 sr = getReader(XML); + XMLValidator vtor = sr.validateAgainst(schema); + + assertTokenType(START_ELEMENT, sr.next()); + assertEquals("dict", sr.getLocalName()); + assertTokenType(START_ELEMENT, sr.next()); + assertEquals("term", sr.getLocalName()); + + /* So far so good; but here we'd get an exception... so + * let's stop validating + */ + assertSame(vtor, sr.stopValidatingAgainst(schema)); + try { + // And should be good to go + assertTokenType(START_ELEMENT, sr.next()); + assertEquals("invalid", sr.getLocalName()); + assertTokenType(END_ELEMENT, sr.next()); + assertEquals("invalid", sr.getLocalName()); + assertTokenType(END_ELEMENT, sr.next()); + assertEquals("term", sr.getLocalName()); + assertTokenType(END_ELEMENT, sr.next()); + assertEquals("dict", sr.getLocalName()); + assertTokenType(END_DOCUMENT, sr.next()); + } catch (XMLValidationException vex) { + fail("Did not expect validation exception after stopping validation, got: "+vex); + } + sr.close(); + + // And let's do the same, just using the other stopValidatingAgainst method + sr = getReader(XML); + vtor = sr.validateAgainst(schema); + + assertTokenType(START_ELEMENT, sr.next()); + assertEquals("dict", sr.getLocalName()); + assertTokenType(START_ELEMENT, sr.next()); + assertEquals("term", sr.getLocalName()); + + assertSame(vtor, sr.stopValidatingAgainst(vtor)); + try { + // And should be good to go + assertTokenType(START_ELEMENT, sr.next()); + assertEquals("invalid", sr.getLocalName()); + assertTokenType(END_ELEMENT, sr.next()); + assertEquals("invalid", sr.getLocalName()); + assertTokenType(END_ELEMENT, sr.next()); + assertEquals("term", sr.getLocalName()); + assertTokenType(END_ELEMENT, sr.next()); + assertEquals("dict", sr.getLocalName()); + assertTokenType(END_DOCUMENT, sr.next()); + } catch (XMLValidationException vex) { + fail("Did not expect validation exception after stopping validation, got: "+vex); + } + sr.close(); + } + + public void testSimpleEnumAttr() + throws XMLStreamException + { + final String schemaDef = + "\n" + +" \n" + +" \n" + +" value1\n" + +" another\n" + +" 42\n" + +" \n" + +" \n" + +"" + ; + XMLValidationSchema schema = parseRngSchema(schemaDef); + + // First, simple valid document + String XML = ""; + XMLStreamReader2 sr = getReader(XML); + sr.validateAgainst(schema); + while (sr.next() != END_DOCUMENT) { } + sr.close(); + + // And then invalid one, with unrecognized value + XML = ""; + verifyRngFailure(XML, schema, "enum attribute with unknown value", + "attribute \"enumAttr\" has a bad value"); + } + + /** + * Test case for testing handling ID/IDREF/IDREF attributes, using + * schema datatype library. + */ + public void testSimpleIdAttrs() + throws XMLStreamException + { + final String schemaDef = + "\n" + +" \n" + +" \n" + +" \n" + +" \n" + +" \n" + +" \n" + +" \n" + +" \n" + +" \n" + +" \n" + +" \n" + +"" + ; + + XMLValidationSchema schema = parseRngSchema(schemaDef); + + // First, a simple valid document + String XML = "" + +" \n" + +" \n" + +" \n" + +"" + ; + XMLStreamReader2 sr = getReader(XML); + sr.validateAgainst(schema); + while (sr.next() != END_DOCUMENT) { } + sr.close(); + + // Then one with malformed id + XML = ""; + verifyRngFailure(XML, schema, "malformed id", + "attribute \"id\" has a bad value"); + + // Then with malformed IDREF value (would be valid IDREFS) + XML = "" + +" \n" + +" \n" + +"" + ; + verifyRngFailure(XML, schema, "malformed id", + "attribute \"ref\" has a bad value"); + + // And then invalid one, with dangling ref + XML = "" + +" \n" + +"" + ; + verifyRngFailure(XML, schema, "reference to undefined id", + "Undefined ID"); + + // and another one with some of refs undefined + XML = "" + +" \n" + +"" + ; + verifyRngFailure(XML, schema, "reference to undefined id", + "Undefined ID"); + } + + public void testSimpleIntAttr() + throws XMLStreamException + { + final String schemaDef = + "\n" + +" \n" + +" \n" + +" \n" + +"" + ; + + XMLValidationSchema schema = parseRngSchema(schemaDef); + + // First, a simple valid document + XMLStreamReader2 sr = getReader(""); + sr.validateAgainst(schema); + while (sr.next() != END_DOCUMENT) { } + sr.close(); + + // Then one with invalid element value + verifyRngFailure("", + schema, "invalid integer attribute value", + "does not satisfy the \"integer\" type"); + // And missing attribute + verifyRngFailure("", + schema, "missing integer attribute value", + "is missing \"nr\" attribute"); + + // And then two variations of having empty value + verifyRngFailure("", + schema, "missing integer attribute value", + "does not satisfy the \"integer\" type"); + verifyRngFailure("", + schema, "missing integer attribute value", + "does not satisfy the \"integer\" type"); + } + + /** + * Another test, but one that verifies that empty tags do not + * cause problems with validation + */ + public void testSimpleBooleanElem2() + throws XMLStreamException + { + final String schemaDef = + "\n" + +" \n" + +" \n" + +" \n" + +" \n" + +"" + ; + + XMLValidationSchema schema = parseRngSchema(schemaDef); + + // First, a simple valid document + XMLStreamReader2 sr = getReader("abctrue"); + sr.validateAgainst(schema); + while (sr.next() != END_DOCUMENT) { } + sr.close(); + + // Then another valid, but with empty tag for leaf1 + sr = getReader("false"); + sr.validateAgainst(schema); + while (sr.next() != END_DOCUMENT) { } + sr.close(); + + // And then one more invalid case + verifyRngFailure("true false", + schema, "missing boolean element value", + "does not satisfy the \"boolean\" type"); + } + + /** + * And then a test for validating starting when stream points + * to START_ELEMENT + */ + public void testPartialValidationOk() + throws XMLStreamException + { + /* Hmmh... RelaxNG does define expected root. So need to + * wrap the doc... + */ + String XML = + "\n" + +"\n" + +"\n" + +" foobar\n" + +" Foo Bar\n" + +"\n" + +"" + ; + XMLValidationSchema schema = parseRngSchema(SIMPLE_RNG_SCHEMA); + XMLStreamReader2 sr = getReader(XML); + assertTokenType(START_ELEMENT, sr.next()); + sr.validateAgainst(schema); + while (sr.next() != END_DOCUMENT) { } + sr.close(); + } + + + /* + ////////////////////////////////////////////////////////////// + // Helper methods + ////////////////////////////////////////////////////////////// + */ + + private XMLStreamReader2 getReader(String contents) throws XMLStreamException + { + XMLInputFactory2 f = getInputFactory(); + setValidating(f, false); + return constructStreamReader(f, contents); + } + + private void verifyRngFailure(String xml, XMLValidationSchema schema, String failMsg, String failPhrase) + throws XMLStreamException + { + // By default, yes we are strict... + verifyRngFailure(xml, schema, failMsg, failPhrase, true); + } + + private void verifyRngFailure(String xml, XMLValidationSchema schema, String failMsg, String failPhrase, + boolean strict) + throws XMLStreamException + { + XMLStreamReader2 sr = getReader(xml); + sr.validateAgainst(schema); + try { + while (sr.hasNext()) { + /*int type =*/ sr.next(); + } + fail("Expected validity exception for "+failMsg); + } catch (XMLValidationException vex) { + String origMsg = vex.getMessage(); + String msg = (origMsg == null) ? "" : origMsg.toLowerCase(); + if (msg.indexOf(failPhrase.toLowerCase()) < 0) { + String actualMsg = "Expected validation exception for "+failMsg+", containing phrase '"+failPhrase+"': got '"+origMsg+"'"; + if (strict) { + fail(actualMsg); + } + warn("suppressing failure due to MSV bug, failure: '"+actualMsg+"'"); + } + // should get this specific type; not basic stream exception + } catch (XMLStreamException sex) { + fail("Expected XMLValidationException for "+failMsg); + } + } +} diff -Nru libwoodstox-java-4.1.3/src/test/java/wstxtest/vstream/TestXmlId.java libwoodstox-java-5.1.0/src/test/java/wstxtest/vstream/TestXmlId.java --- libwoodstox-java-4.1.3/src/test/java/wstxtest/vstream/TestXmlId.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/wstxtest/vstream/TestXmlId.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,60 @@ +package wstxtest.vstream; + +import javax.xml.stream.*; + +import wstxtest.stream.BaseStreamTest; + +public class TestXmlId + extends BaseStreamTest +{ + /** + * This is a simple regression test -- at one point, last character + * of id attributes was dropped. + */ + public void testSimpleNonNs() + throws XMLStreamException + { + doTestSimple(false); + } + + public void testSimpleNs() + throws XMLStreamException + { + doTestSimple(true); + } + + /* + ////////////////////////////////////////////////// + // Helper methods + ////////////////////////////////////////////////// + */ + + private void doTestSimple(boolean ns) + throws XMLStreamException + { + final String XML = + "\n" + +"\n" + +"\n" + +"]>\n" + +"\n" + +"\n" + +"\n" + +"\n" + ; + XMLStreamReader sr = getReader(XML, ns); + // Should succeed + streamThrough(sr); + } + + private XMLStreamReader getReader(String xml, boolean nsAware) + throws XMLStreamException + { + XMLInputFactory f = getInputFactory(); + setNamespaceAware(f, nsAware); + setSupportDTD(f, true); + setValidating(f, true); + return constructStreamReader(f, xml); + } +} diff -Nru libwoodstox-java-4.1.3/src/test/java/wstxtest/vstream/TestXMLReporter.java libwoodstox-java-5.1.0/src/test/java/wstxtest/vstream/TestXMLReporter.java --- libwoodstox-java-4.1.3/src/test/java/wstxtest/vstream/TestXMLReporter.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/wstxtest/vstream/TestXMLReporter.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,283 @@ +package wstxtest.vstream; + +import javax.xml.stream.*; + +import org.codehaus.stax2.XMLReporter2; +import org.codehaus.stax2.validation.XMLValidationProblem; + +import wstxtest.stream.BaseStreamTest; + +/** + * Simple testing to ensure that {@link XMLReporter} works as + * expected with respect to validation errors. + *

+ * As of Woodstox 4.0, we will be actually using {@link XMLReporter2} + * interface, both to test that the improved interface works, and + * to get access to more accurate information. + */ +public class TestXMLReporter + extends BaseStreamTest +{ + /** + * Basic unit test for verifying that XMLReporter gets validation + * errors reported. + */ + public void testValidationError() + throws XMLStreamException + { + String XML = + "\n" + +"]>..." + ; + testOldReporterProblems(XML, 0); + testNewReporterProblems(XML, null); + + // Then invalid, with one error + XML = + "\n" + +"]>"; + ; + testOldReporterProblems(XML, 1); + testNewReporterProblems(XML, "at least one element "); + } + + /** + * Test for specific validation error, mostly to verify + * fix to [WSTX-155] (and guard against regression) + */ + public void testMissingAttrError() + throws XMLStreamException + { + String XML = + "\n" + +" \n" + +"]>"; + ; + testOldReporterProblems(XML, 1); + testNewReporterProblems(XML, "Required attribute"); + } + + public void testInvalidFixedAttr() + throws XMLStreamException + { + // Not ok to have any other value, either completely different + String XML = "\n" + +"\n" + +"]>\n"; + testOldReporterProblems(XML, 1); + testNewReporterProblems(XML, "FIXED attribute"); + + // Or one with extra white space (CDATA won't get fully normalized) + XML = "\n" + +"\n" + +"]>\n"; + testOldReporterProblems(XML, 1); + testNewReporterProblems(XML, "FIXED attribute"); + } + + public void testInvalidIdAttr() + throws XMLStreamException + { + // Error: undefined id 'someId' + String XML = "\n" + +"\n" + +"\n" + +"]>\n"; + testOldReporterProblems(XML, 1); + testNewReporterProblems(XML, "Undefined id"); + + // Error: empty idref value + XML = "\n" + +"\n" + +"\n" + +"]>\n"; + testOldReporterProblems(XML, 1); + testNewReporterProblems(XML, "IDREF value"); + } + + public void testInvalidSimpleChoiceStructure() + throws XMLStreamException + { + String XML = "\n" + +"\n" + +"\n" + +"]>\n" + +""; + testOldReporterProblems(XML, 1); + testNewReporterProblems(XML, "Expected at least one of elements"); + } + + /** + * This test verifies that exception XMLReporter rethrows gets + * properly propagated. + */ + public void testErrorRethrow() + throws XMLStreamException + { + String XML = + "\n" + +"]>"; + ; + MyReporterOld rep = new MyReporterOld(); + rep.enableThrow(); + XMLStreamReader sr = getReader(XML, rep); + try { + streamThrough(sr); + fail("Expected a re-thrown exception for invalid content"); + } catch (XMLStreamException xse) { + ; + } + sr.close(); + assertEquals(1, rep.getCount()); + testNewReporterProblems(XML, "element "); + } + + /* + ////////////////////////////////////////////////// + // Helper methods + ////////////////////////////////////////////////// + */ + + private XMLStreamReader getReader(String xml, XMLReporter rep) + throws XMLStreamException + { + XMLInputFactory f = getInputFactory(); + setNamespaceAware(f, true); + setSupportDTD(f, true); + setValidating(f, true); + f.setXMLReporter(rep); + return constructStreamReader(f, xml); + } + + private void testOldReporterProblems(String XML, int expFails) + throws XMLStreamException + { + MyReporterOld rep = new MyReporterOld(); + XMLStreamReader sr = getReader(XML, rep); + + streamThrough(sr); + sr.close(); + int actFails = rep.getCount(); + assertEquals("Expected "+expFails+" fail(s), got "+actFails, + expFails, actFails); + } + + private void testNewReporterProblems(String XML, String expMsg) + throws XMLStreamException + { + MyReporter2 rep = new MyReporter2(); + XMLStreamReader sr = getReader(XML, rep); + + streamThrough(sr); + sr.close(); + int actFails = rep.getCount(); + int expFails = (expMsg == null) ? 0 : 1; + + assertEquals("Expected "+expFails+" fail(s), got "+actFails, + expFails, actFails); + if (expFails > 0) { + String actMsg = rep.getMessage(); + if (actMsg == null) { + actMsg = ""; + } + if (actMsg.indexOf(expMsg) < 0) { + fail("Expected failure to contain phrase '"+expMsg+"', did not, was: '"+actMsg+"'"); + } + } + } + + /* + ////////////////////////////////////////////////// + // Helper classes + ////////////////////////////////////////////////// + */ + + /** + * Base Report class, used to verify some aspects of using + * plain old XMLReporter class (for example that we do + * get 'relatedInfo' populated with XMLValidationProblem) + */ + static class MyReporterOld + implements XMLReporter + { + protected int _count = 0; + + protected String _firstMessage; + + protected boolean _doThrow = false; + + public MyReporterOld() { } + + public void enableThrow() { _doThrow = true; } + + @Override + public void report(String message,String errorType, + Object relatedInfo, Location location) + throws XMLStreamException + { + ++_count; + if (_firstMessage != null) { + _firstMessage = message; + } + if (_doThrow) { + throw new XMLStreamException(message, location); + } + /* 30-May-2008, TSa: Need to ensure that extraArg is of + * type XMLValidationProblem; new constraint for Woodstox + */ + if (relatedInfo == null) { + throw new IllegalArgumentException("relatedInformation null, should be an instance of XMLValidationProblem"); + } + if (!(relatedInfo instanceof XMLValidationProblem)) { + throw new IllegalArgumentException("relatedInformation not an instance of XMLValidationProblem (but "+relatedInfo.getClass().getName()+")"); + } + } + + public int getCount() { return _count; } + public String getMessage() { return _firstMessage; } + } + + static class MyReporter2 + extends MyReporterOld + implements XMLReporter2 + { + public MyReporter2() { super(); } + + @Override + public void report(String message, String errorType, + Object relatedInfo, Location location) + throws XMLStreamException + { + throw new Error("Should not get a call through old XMLReporter interface, when registering XMLReporter2"); + } + + @Override + public void report(XMLValidationProblem prob) + throws XMLStreamException + { + ++_count; + String msg = prob.getMessage(); + // Let's require a message here... for now + if (msg == null) { + throw new RuntimeException("Problem object missing 'message' property"); + } + if (_firstMessage == null) { + _firstMessage = msg; + } + if (_doThrow) { + throw prob.toException(); + } + } + } +} + + diff -Nru libwoodstox-java-4.1.3/src/test/java/wstxtest/vstream/TestXmlSpace.java libwoodstox-java-5.1.0/src/test/java/wstxtest/vstream/TestXmlSpace.java --- libwoodstox-java-4.1.3/src/test/java/wstxtest/vstream/TestXmlSpace.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/wstxtest/vstream/TestXmlSpace.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,95 @@ +package wstxtest.vstream; + +import javax.xml.stream.*; + +import org.codehaus.stax2.validation.*; + +import wstxtest.stream.BaseStreamTest; + +/** + * Simple test for ensuring handling of "xml:space" attribute. Not + * sure if this should go in the main StaxTest (or perhaps Stax2), since + * it's not 100% clear if the validity violations should result in + * XMLStreamException, or something else. + */ +public class TestXmlSpace + extends BaseStreamTest +{ + public void testSimpleNonNs() + throws XMLStreamException + { + // First, legal declarations: + for (int i = 0; i < 2; ++i) { + boolean nsAware = (i > 0); + + String XML = "\n" + +"\n" + +"]>"; + XMLStreamReader sr = getReader(XML, nsAware); + assertTokenType(DTD, sr.next()); + assertTokenType(START_ELEMENT, sr.next()); + assertTokenType(END_ELEMENT, sr.next()); + sr.close(); + + XML = "\n" + +"\n" + +"]>"; + sr = getReader(XML, nsAware); + assertTokenType(DTD, sr.next()); + assertTokenType(START_ELEMENT, sr.next()); + assertTokenType(END_ELEMENT, sr.next()); + sr.close(); + + // And then some non-legal ones: + XML = "\n" + +"\n" + +"]>"; + sr = getReader(XML, nsAware); + try { + int type = sr.next(); + assertTokenType(DTD, type); + type = sr.next(); + assertTokenType(START_ELEMENT, type); + fail("Expected a validity exception for invalid xml:space declaration (ns-aware: "+nsAware+")"); + } catch (XMLValidationException vex) { + ; // good + } + sr.close(); + + XML = "\n" + +"\n" + +"]>"; + sr = getReader(XML, nsAware); + try { + int type = sr.next(); + assertTokenType(DTD, type); + type = sr.next(); + assertTokenType(START_ELEMENT, type); + fail("Expected a validity exception for invalid xml:space declaration (ns-aware: "+nsAware+")"); + } catch (XMLValidationException vex) { + ; // good + } + sr.close(); + } + } + + /* + ////////////////////////////////////////////////// + // Helper methods + ////////////////////////////////////////////////// + */ + + private XMLStreamReader getReader(String xml, boolean nsAware) + throws XMLStreamException + { + XMLInputFactory f = getInputFactory(); + setNamespaceAware(f, nsAware); + setSupportDTD(f, true); + setValidating(f, true); + return constructStreamReader(f, xml); + } +} diff -Nru libwoodstox-java-4.1.3/src/test/java/wstxtest/wstream/BaseWriterTest.java libwoodstox-java-5.1.0/src/test/java/wstxtest/wstream/BaseWriterTest.java --- libwoodstox-java-4.1.3/src/test/java/wstxtest/wstream/BaseWriterTest.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/wstxtest/wstream/BaseWriterTest.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,25 @@ +package wstxtest.wstream; + +import java.io.*; + +import javax.xml.stream.*; + +import org.codehaus.stax2.XMLStreamReader2; + +import wstxtest.BaseWstxTest; + +abstract class BaseWriterTest + extends BaseWstxTest +{ + protected BaseWriterTest() { } + + @Override + protected XMLStreamReader2 constructNsStreamReader(String content, boolean coal) + throws XMLStreamException + { + XMLInputFactory f = getInputFactory(); + setNamespaceAware(f, true); + setCoalescing(f, coal); + return (XMLStreamReader2) f.createXMLStreamReader(new StringReader(content)); + } +} diff -Nru libwoodstox-java-4.1.3/src/test/java/wstxtest/wstream/TestAttrValidation.java libwoodstox-java-5.1.0/src/test/java/wstxtest/wstream/TestAttrValidation.java --- libwoodstox-java-4.1.3/src/test/java/wstxtest/wstream/TestAttrValidation.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/wstxtest/wstream/TestAttrValidation.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,37 @@ +package wstxtest.wstream; + +import java.io.*; + +import javax.xml.stream.*; + +import org.codehaus.stax2.*; + +/** + * This unit test suite verifies that output-side content validation + * works as expected, when enabled. + */ +public class TestAttrValidation + extends BaseWriterTest +{ + /** + * Unit test suite for testing violations of structural checks, when + * trying to output things in prolog/epilog. + */ + public void testSimpleAttrs() + throws Exception + { + XMLOutputFactory2 f = getOutputFactory(); + StringWriter w = new StringWriter(); + XMLStreamWriter sw = f.createXMLStreamWriter(w, "UTF-8"); + + sw.writeStartDocument(); + sw.writeEmptyElement("root"); + try { + sw.writeAttribute("foo", "Null is invalid: \0"); + fail("Expected an exception when trying to write attribute value with null character"); + } catch (XMLStreamException sex) { + ; + } + sw.writeEndDocument(); + } +} diff -Nru libwoodstox-java-4.1.3/src/test/java/wstxtest/wstream/TestAutoEndElems.java libwoodstox-java-5.1.0/src/test/java/wstxtest/wstream/TestAutoEndElems.java --- libwoodstox-java-4.1.3/src/test/java/wstxtest/wstream/TestAutoEndElems.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/wstxtest/wstream/TestAutoEndElems.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,56 @@ +package wstxtest.wstream; + +import java.io.*; + +import javax.xml.stream.*; + +import com.ctc.wstx.api.WstxOutputProperties; + +/** + * Unit tests for verifying that [WSTX-165] works ok. + */ +public class TestAutoEndElems + extends BaseWriterTest +{ + public void testAutomaticEndElemsEnabled() + throws XMLStreamException + { + StringWriter strw = new StringWriter(); + XMLStreamWriter sw = getFactory(true).createXMLStreamWriter(strw); + sw.writeStartElement("root"); + sw.writeStartElement("leaf"); + sw.writeCharacters(""); // to prevent empty elem, simplify testing + sw.close(); + + assertEquals("", strw.toString()); + } + + public void testAutomaticEndElemsDisabled() + throws XMLStreamException + { + StringWriter strw = new StringWriter(); + XMLStreamWriter sw = getFactory(false).createXMLStreamWriter(strw); + sw.writeStartElement("root"); + sw.writeStartElement("leaf"); + sw.writeCharacters(""); // to prevent empty elem, simplify testing + sw.close(); + + assertEquals("", strw.toString()); + } + + /* + //////////////////////////////////////////////////// + // Helper methods + //////////////////////////////////////////////////// + */ + + private XMLOutputFactory getFactory(boolean autoEndElems) + throws XMLStreamException + { + XMLOutputFactory f = getOutputFactory(); + // ns-awareness, repairing shouldn't matter, just whether automatic end elems enabled + f.setProperty(WstxOutputProperties.P_AUTOMATIC_END_ELEMENTS, autoEndElems ? Boolean.TRUE : Boolean.FALSE); + return f; + } + +} diff -Nru libwoodstox-java-4.1.3/src/test/java/wstxtest/wstream/TestContentValidation.java libwoodstox-java-5.1.0/src/test/java/wstxtest/wstream/TestContentValidation.java --- libwoodstox-java-4.1.3/src/test/java/wstxtest/wstream/TestContentValidation.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/wstxtest/wstream/TestContentValidation.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,307 @@ +package wstxtest.wstream; + +import java.io.*; + +import javax.xml.stream.*; + +import org.codehaus.stax2.*; + +/** + * This unit test suite verifies that output-side content validation + * works as expected, when enabled. + */ +public class TestContentValidation + extends BaseWriterTest +{ + final String COMMENT_CONTENT_IN = "can not have -- in there"; + final String COMMENT_CONTENT_OUT = "can not have - - in there"; + + final String CDATA_CONTENT_IN = "CData in: "; + final String CDATA_CONTENT_OUT = "CData in: "; + + final String PI_CONTENT_IN = "this should end PI: ?> shouldn't it?"; + final String PI_CONTENT_OUT = "this should end PI: ?> shouldn't it?"; + + /* + //////////////////////////////////////////////////// + // Main test methods + //////////////////////////////////////////////////// + */ + + public void testCommentChecking() + throws XMLStreamException + { + for (int i = 0; i <= 2; ++i) { + XMLOutputFactory2 f = getFactory(i, true, false); + for (int enc = 0; enc < 3; ++enc) { + XMLStreamWriter2 sw; + + if (enc == 0) { + StringWriter strw = new StringWriter(); + sw = (XMLStreamWriter2) f.createXMLStreamWriter(strw); + } else { + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + String encStr = (enc == 1) ? "UTF-8" : "ISO-8859-1"; + sw = (XMLStreamWriter2) f.createXMLStreamWriter(bos, encStr); + } + sw.writeStartDocument(); + sw.writeStartElement("root"); + try { + sw.writeComment(COMMENT_CONTENT_IN); + fail("Expected an XMLStreamException for illegal comment content (contains '--') in checking + non-fixing mode (type "+i+")"); + } catch (XMLStreamException sex) { + // good + } catch (Throwable t) { + fail("Expected an XMLStreamException for illegal comment content (contains '--') in checking + non-fixing mode; got: "+t); + } + } + } + } + + public void testCommentFixing() + throws Exception + { + for (int i = 0; i <= 2; ++i) { + XMLOutputFactory2 f = getFactory(i, true, true); + + /* 24-Aug-2006, TSa: Let's also test with output stream-based + * output... writers may use different code + */ + for (int enc = 0; enc < 3; ++enc) { + XMLStreamWriter2 sw; + StringWriter strw = null; + ByteArrayOutputStream bos = null; + String encStr = null; + + if (enc == 0) { + strw = new StringWriter(); + sw = (XMLStreamWriter2) f.createXMLStreamWriter(strw); + } else { + bos = new ByteArrayOutputStream(); + encStr = (enc == 1) ? "UTF-8" : "ISO-8859-1"; + sw = (XMLStreamWriter2) f.createXMLStreamWriter(bos, encStr); + } + sw.writeStartDocument(); + sw.writeStartElement("root"); + /* now it should be ok, and result in one padded or + * 2 separate comments... + */ + sw.writeComment(COMMENT_CONTENT_IN); + sw.writeEndElement(); + sw.writeEndDocument(); + sw.close(); + + String output; + if (strw != null) { + output = strw.toString(); + } else { + output = new String(bos.toByteArray(), encStr); + } + + // so far so good; but let's ensure it also parses: + XMLStreamReader sr = getReader(output); + assertTokenType(START_ELEMENT, sr.next()); + assertTokenType(COMMENT, sr.next()); + StringBuffer sb = new StringBuffer(); + sb.append(getAndVerifyText(sr)); + + // May get another one too...? + int type; + + while ((type = sr.next()) == COMMENT) { + sb.append(getAndVerifyText(sr)); + } + + /* Ok... now, except for additional spaces, we should have + * about the same content: + */ + /* For now, since it's wstx-specific, let's just hard-code + * exactly what we are to get: + */ + String act = sb.toString(); + if (!COMMENT_CONTENT_OUT.equals(act)) { + failStrings("Failed to properly quote comment content (type "+i+")", + COMMENT_CONTENT_OUT, act); + } + assertTokenType(END_ELEMENT, type); + } + } + } + + public void testCDataChecking() + throws Exception + { + for (int i = 0; i <= 2; ++i) { + for (int itype = 0; itype < 2; ++itype) { + XMLOutputFactory2 f = getFactory(i, true, false); + + /* 24-Aug-2006, TSa: Let's also test with output stream-based + * output... writers may use different code + */ + for (int enc = 0; enc < 3; ++enc) { + XMLStreamWriter2 sw; + + if (enc == 0) { + StringWriter strw = new StringWriter(); + sw = (XMLStreamWriter2) f.createXMLStreamWriter(strw); + } else { + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + sw = (XMLStreamWriter2) f.createXMLStreamWriter + (bos, (enc == 1) ? "UTF-8" : "ISO-8859-1"); + } + sw.writeStartDocument(); + sw.writeStartElement("root"); + try { + if (itype == 0) { + sw.writeCData(CDATA_CONTENT_IN); + } else { + char[] ch = CDATA_CONTENT_IN.toCharArray(); + sw.writeCData(ch, 0, ch.length); + } + fail("Expected an XMLStreamException for illegal CDATA content (contains ']]>') in checking + non-fixing mode (type "+i+", itype "+itype+")"); + } catch (XMLStreamException sex) { + // good + } catch (Exception t) { + fail("Expected an XMLStreamException for illegal CDATA content (contains ']]>') in checking + non-fixing mode; got: "+t); + } + } + } + } + } + + public void testCDataFixing() + throws Exception + { + for (int i = 0; i <= 2; ++i) { + for (int itype = 0; itype < 2; ++itype) { + XMLOutputFactory2 f = getFactory(i, true, true); + + /* 24-Aug-2006, TSa: Let's also test with output stream-based + * output... writers may use different code + */ + for (int enc = 0; enc < 3; ++enc) { + XMLStreamWriter2 sw; + StringWriter strw = null; + ByteArrayOutputStream bos = null; + String encStr = null; + + if (enc == 0) { + strw = new StringWriter(); + sw = (XMLStreamWriter2) f.createXMLStreamWriter(strw); + } else { + bos = new ByteArrayOutputStream(); + encStr = (enc == 1) ? "UTF-8" : "ISO-8859-1"; + sw = (XMLStreamWriter2) f.createXMLStreamWriter(bos, encStr); + } + + sw.writeStartDocument(); + sw.writeStartElement("root"); + /* now it should be ok, and result in two separate CDATA + * segments... + */ + if (itype == 0) { + sw.writeCData(CDATA_CONTENT_IN); + } else { + char[] ch = CDATA_CONTENT_IN.toCharArray(); + sw.writeCData(ch, 0, ch.length); + } + sw.writeEndElement(); + sw.writeEndDocument(); + sw.close(); + + String output; + if (strw != null) { + output = strw.toString(); + } else { + output = new String(bos.toByteArray(), encStr); + } + + // so far so good; but let's ensure it also parses: + XMLStreamReader sr = getReader(output); + assertTokenType(START_ELEMENT, sr.next()); + int type = sr.next(); + + assertTokenType(CDATA, type); + StringBuffer sb = new StringBuffer(); + sb.append(getAndVerifyText(sr)); + + // Should be getting one or more segments... + while ((type = sr.next()) == CDATA) { + sb.append(getAndVerifyText(sr)); + } + + String act = sb.toString(); + if (!CDATA_CONTENT_OUT.equals(act)) { + failStrings("Failed to properly quote CDATA content (type "+i+", itype "+itype+")", + CDATA_CONTENT_OUT, act); + } + assertTokenType(END_ELEMENT, type); + } + } + } + } + + public void testPIChecking() + throws Exception + { + for (int i = 0; i <= 2; ++i) { + XMLOutputFactory2 f = getFactory(i, true, false); + + /* 24-Aug-2006, TSa: Let's also test with output stream-based + * output... writers may use different code + */ + for (int enc = 0; enc < 3; ++enc) { + XMLStreamWriter2 sw; + + if (enc == 0) { + StringWriter strw = new StringWriter(); + sw = (XMLStreamWriter2) f.createXMLStreamWriter(strw); + } else { + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + sw = (XMLStreamWriter2) f.createXMLStreamWriter + (bos, (enc == 1) ? "UTF-8" : "ISO-8859-1"); + } + sw.writeStartDocument(); + sw.writeStartElement("root"); + try { + sw.writeProcessingInstruction("target", PI_CONTENT_IN); + fail("Expected an XMLStreamException for illegal PI content (contains '?>') in checking + non-fixing mode (type "+enc+")"); + } catch (XMLStreamException sex) { + // good + } catch (Exception t) { + fail("Expected an XMLStreamException for illegal PI content (contains '?>') in checking + non-fixing mode; got: "+t); + } + } + } + } + + // // Note: no way (currently?) to fix PI content; thus, no test: + + + /* +//////////////////////////////////////////////////// +// Internal methods +//////////////////////////////////////////////////// +*/ + + private XMLOutputFactory2 getFactory(int type, boolean checkAll, boolean fixAll) + throws XMLStreamException + { + XMLOutputFactory2 f = getOutputFactory(); + // type 0 -> non-ns, 1 -> ns, non-repairing, 2 -> ns, repairing + setNamespaceAware(f, type > 0); + setRepairing(f, type > 1); + setValidateAll(f, checkAll); + setFixContent(f, fixAll); + return f; + } + + private XMLStreamReader getReader(String content) + throws XMLStreamException + { + XMLInputFactory2 f = getInputFactory(); + setCoalescing(f, false); + return f.createXMLStreamReader(new StringReader(content)); + } +} + diff -Nru libwoodstox-java-4.1.3/src/test/java/wstxtest/wstream/TestEmptyElementWriter.java libwoodstox-java-5.1.0/src/test/java/wstxtest/wstream/TestEmptyElementWriter.java --- libwoodstox-java-4.1.3/src/test/java/wstxtest/wstream/TestEmptyElementWriter.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/wstxtest/wstream/TestEmptyElementWriter.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,77 @@ +package wstxtest.wstream; + +import java.io.*; +import java.util.*; + +import javax.xml.stream.*; + +import com.ctc.wstx.api.EmptyElementHandler; +import com.ctc.wstx.api.WstxOutputProperties; + +/** + * Unit tests to verify that [WSTX-252] (ability to control whether + * an empty element can be written using empty element instead of + * separate start/end tags) has been completely implemented. + * + * @since 4.1 + */ +public class TestEmptyElementWriter + extends BaseWriterTest +{ + public void testDefaults() throws Exception + { + XMLOutputFactory f = getOutputFactory(); + // by default, empty elements can be used for everything + StringWriter sw = new StringWriter(); + XMLStreamWriter w = f.createXMLStreamWriter(sw); + w.writeStartElement("root"); + w.writeStartElement("a"); + w.writeEndElement(); + w.writeStartElement("b"); + w.writeEndElement(); + w.writeEndElement(); + w.writeEndDocument(); + w.close(); + assertEquals("", sw.toString()); + } + + public void testSimple() throws Exception + { + XMLOutputFactory f = getOutputFactory(); + // test with simple handler that lists explicitly all tags to close + Set tags = new HashSet (); + tags.add("a"); + f.setProperty(WstxOutputProperties.P_OUTPUT_EMPTY_ELEMENT_HANDLER, + new EmptyElementHandler.SetEmptyElementHandler(tags)); + StringWriter sw = new StringWriter(); + XMLStreamWriter w = f.createXMLStreamWriter(sw); + w.writeStartElement("root"); + w.writeStartElement("a"); + w.writeEndElement(); + w.writeStartElement("b"); + w.writeEndElement(); + w.writeEndElement(); + w.writeEndDocument(); + w.close(); + assertEquals("", sw.toString()); + } + + public void testHTML() throws Exception + { + XMLOutputFactory f = getOutputFactory(); + f.setProperty(WstxOutputProperties.P_OUTPUT_EMPTY_ELEMENT_HANDLER, + EmptyElementHandler.HtmlEmptyElementHandler.getInstance()); + StringWriter sw = new StringWriter(); + XMLStreamWriter w = f.createXMLStreamWriter(sw); + w.writeStartElement("root"); + w.writeStartElement("a"); + w.writeEndElement(); + w.writeStartElement("br"); + w.writeEndElement(); + w.writeEndElement(); + w.writeEndDocument(); + w.close(); + assertEquals("
", sw.toString()); + } + +} diff -Nru libwoodstox-java-4.1.3/src/test/java/wstxtest/wstream/TestEscaping.java libwoodstox-java-5.1.0/src/test/java/wstxtest/wstream/TestEscaping.java --- libwoodstox-java-4.1.3/src/test/java/wstxtest/wstream/TestEscaping.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/wstxtest/wstream/TestEscaping.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,110 @@ +package wstxtest.wstream; + +import java.io.*; + +import javax.xml.stream.*; + +import org.codehaus.stax2.*; + +import com.ctc.wstx.api.WstxOutputProperties; + +/** + * This unit test suite verifies Woodstox-specific output-side + * character escaping options + */ +public class TestEscaping + extends BaseWriterTest +{ + public void testCrHandlingEscaping() + throws XMLStreamException + { + doTestCrHandling(true, "Cr: \r.", "Cr: \r.", "Cr: \r."); + doTestCrHandling(true, "CrLF: \r\n.", "CrLF: \r\n.", "CrLF: \r\n."); + } + + public void testCrHandlingNonEscaping() + throws XMLStreamException + { + doTestCrHandling(false, "Cr: \r.", "Cr: \n.", "Cr: ."); + // attribute output is same, but parser handling differs, so: + doTestCrHandling(false, "CrLF: \r\n.", "CrLF: \n.", "CrLF: \n."); + } + + /* + //////////////////////////////////////////////////// + // Helper methods + //////////////////////////////////////////////////// + */ + + private void doTestCrHandling(boolean escaping, String input, + String elemOutput, String attrOutput) + throws XMLStreamException + { + // Let's try out 2 main encoding types: + String[] ENC = new String[] { "UTF-8", "ISO-8859-1", "US-ASCII" }; + for (int encIx = 0; encIx < ENC.length; ++encIx) { + // And 3 writer types: + for (int type = 0; type < 3; ++type) { + String enc = ENC[encIx]; + XMLOutputFactory2 f = getFactory(type, escaping); + ByteArrayOutputStream out = new ByteArrayOutputStream(); + XMLStreamWriter sw = f.createXMLStreamWriter(out, enc); + writeDoc(sw, input); + sw.close(); + + // Ok, do we get what we should? + verifyDoc(escaping, enc, out.toByteArray(), + elemOutput, attrOutput, sw); + } + } + } + + private void writeDoc(XMLStreamWriter sw, String text) + throws XMLStreamException + { + sw.writeStartDocument(); + sw.writeStartElement("root"); + sw.writeAttribute("attr", text); + sw.writeCharacters(text); + sw.writeEndElement(); + sw.writeEndDocument(); + } + + private void verifyDoc(boolean escaping, String encoding, byte[] data, + String expElem, String expAttr, XMLStreamWriter sw) + throws XMLStreamException + { + XMLStreamReader2 sr = constructNsStreamReader(new ByteArrayInputStream(data), true); + String actualText; + assertTokenType(START_ELEMENT, sr.next()); + assertEquals("root", sr.getLocalName()); + + assertEquals(1, sr.getAttributeCount()); + actualText = sr.getAttributeValue(0); + if (!expAttr.equals(actualText)) { + failStrings("Attribute value incorrect (CR-escaping: "+escaping+", encoding: "+encoding+"; writer: "+sw+")", expAttr, actualText); + } + + assertTokenType(CHARACTERS, sr.next()); + actualText = getAndVerifyText(sr); + if (!expElem.equals(actualText)) { + failStrings("Element value incorrect (CR-escaping: "+escaping+", encoding: "+encoding+", writer "+sw+")", expElem, actualText); + } + assertTokenType(END_ELEMENT, sr.next()); + assertEquals("root", sr.getLocalName()); + } + + private XMLOutputFactory2 getFactory(int type, boolean escapeCr) + throws XMLStreamException + { + XMLOutputFactory2 f = getOutputFactory(); + // type 0 -> non-ns, 1 -> ns, non-repairing, 2 -> ns, repairing + setNamespaceAware(f, type > 0); + setRepairing(f, type > 1); + + f.setProperty(WstxOutputProperties.P_OUTPUT_ESCAPE_CR, escapeCr ? Boolean.TRUE : Boolean.FALSE); + + return f; + } +} + diff -Nru libwoodstox-java-4.1.3/src/test/java/wstxtest/wstream/TestImplicitStartDoc.java libwoodstox-java-5.1.0/src/test/java/wstxtest/wstream/TestImplicitStartDoc.java --- libwoodstox-java-4.1.3/src/test/java/wstxtest/wstream/TestImplicitStartDoc.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/wstxtest/wstream/TestImplicitStartDoc.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,39 @@ +package wstxtest.wstream; + +import java.io.StringWriter; + +import javax.xml.stream.*; + +/** + * This test suite verifies that it is ok to omit writing of + * START_DOCUMENT event, to avoid getting xml declaration output + * (for example to write xml fragments). + * It was created to verify that issue + * WSTX-84 + * is not due to missing writeStartDocument() call. + */ +public class TestImplicitStartDoc + extends BaseWriterTest +{ + public void testWriteImplicitStartDoc() + throws XMLStreamException + { + XMLOutputFactory f = getOutputFactory(); + StringWriter strw = new StringWriter(); + XMLStreamWriter sw = f.createXMLStreamWriter(strw); + try { + sw.writeStartElement("root"); + } catch (Exception e) { + fail("Did not expected writeStartElement to fail, got: "+e); + } + sw.writeCharacters("x"); + sw.writeEndElement(); + + // Writing of end document should be optional, so let's check here + sw.flush(); + assertEquals("x", strw.toString()); + + sw.writeEndDocument(); + assertEquals("x", strw.toString()); + } +} diff -Nru libwoodstox-java-4.1.3/src/test/java/wstxtest/wstream/TestInvalidChars.java libwoodstox-java-5.1.0/src/test/java/wstxtest/wstream/TestInvalidChars.java --- libwoodstox-java-4.1.3/src/test/java/wstxtest/wstream/TestInvalidChars.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/wstxtest/wstream/TestInvalidChars.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,219 @@ +package wstxtest.wstream; + +import java.io.*; + +import javax.xml.stream.*; + +import org.codehaus.stax2.*; + +import com.ctc.wstx.api.InvalidCharHandler; +import com.ctc.wstx.api.WstxOutputProperties; + +/** + * This unit test suite verifies handling of invalid/illegal xml + * characters, with or without explicit handlers + * + * @since 4.0 + */ +public class TestInvalidChars + extends BaseWriterTest +{ + final static String INVALID_TEXT = "\u0003"; + + final static Character REPL_CHAR = Character.valueOf('*'); + + // // First let's verify that we do catch problematic chars + + public void testInvalidCatchingCharacters() throws XMLStreamException + { + doTestInvalid(CHARACTERS); + } + + public void testInvalidCatchingCData() throws XMLStreamException + { + doTestInvalid(CDATA); + } + public void testInvalidCatchingComment() throws XMLStreamException + { + doTestInvalid(COMMENT); + } + public void testInvalidCatchingPI() throws XMLStreamException + { + doTestInvalid(PROCESSING_INSTRUCTION); + } + + public void testInvalidCatchingAttribute() throws XMLStreamException + { + doTestInvalid(ATTRIBUTE); + } + + // // And then also that we can fix problems + + public void testValidReplacingCharacters() throws Exception + { + doTestValid(CHARACTERS); + } + + public void testValidReplacingCData() throws Exception + { + doTestValid(CDATA); + } + public void testValidReplacingComment() throws Exception + { + doTestValid(COMMENT); + } + public void testValidReplacingPI() throws Exception + { + doTestValid(PROCESSING_INSTRUCTION); + } + + public void testValidReplacingAttribute() throws Exception + { + doTestValid(ATTRIBUTE); + } + + /* + ////////////////////////////////////////////// + // Shared test code + ////////////////////////////////////////////// + */ + + private void doTestInvalid(int evtType) + throws XMLStreamException + { + XMLOutputFactory2 f = getFactory(null); + doTestInvalid(evtType, f.createXMLStreamWriter(new ByteArrayOutputStream(), "ISO-8859-1"), true); + doTestInvalid(evtType, f.createXMLStreamWriter(new ByteArrayOutputStream(), "US-ASCII"), true); + // [WSTX-173] affects backends that do not do their own encoding: + doTestInvalid(evtType, f.createXMLStreamWriter(new StringWriter()), false); + doTestInvalid(evtType, f.createXMLStreamWriter(new ByteArrayOutputStream(), "UTF-8"), false); + } + + /** + * @param strictChecks Due to [WSTX-173], may need to relax some checks + * to pass for now. Not needed once bug is fixed. + */ + private void doTestInvalid(int evtType, XMLStreamWriter sw1, + boolean strictChecks) + throws XMLStreamException + { + XMLStreamWriter2 sw = (XMLStreamWriter2) sw1; + sw.writeStartDocument(); + sw.writeStartElement("root"); + try { + switch (evtType) { + case ATTRIBUTE: + sw.writeAttribute("attr", INVALID_TEXT); + // always strict for attributes and characters + handleFailure(sw, "Expected an exception for ATTRIBUTE", true); + break; + case CHARACTERS: + sw.writeCharacters(INVALID_TEXT); + handleFailure(sw, "Expected an exception for CHARACTERS", true); + break; + case CDATA: + sw.writeCData(INVALID_TEXT); + handleFailure(sw, "Expected an exception for CDATA", strictChecks); + break; + case COMMENT: + sw.writeComment(INVALID_TEXT); + handleFailure(sw, "Expected an exception for COMMENT", strictChecks); + break; + case PROCESSING_INSTRUCTION: + sw.writeProcessingInstruction("pi", INVALID_TEXT); + handleFailure(sw, "Expected an exception for PROCESSING_INSTRUCTION", strictChecks); + break; + } + } catch (XMLStreamException xse) { + sw.closeCompletely(); + } + } + + private void doTestValid(int evtType) + throws IOException, XMLStreamException + { + XMLOutputFactory2 f = getFactory(REPL_CHAR); + doTestValid(f, evtType, "ISO-8859-1", true); + doTestValid(f, evtType, "US-ASCII", true); + + // [WSTX-173] affects backends that do not do their own encoding: + doTestValid(f, evtType, "UTF-8", false); + + StringWriter strw = new StringWriter(); + XMLStreamWriter sw = f.createXMLStreamWriter(strw); + buildValid(evtType, sw); + verifyValidReplacement(evtType, sw, strw.toString(), false); + } + + private void doTestValid(XMLOutputFactory2 f, int evtType, String enc, boolean strict) + throws IOException, XMLStreamException + { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + XMLStreamWriter sw = f.createXMLStreamWriter(out, enc); + buildValid(evtType, sw); + verifyValidReplacement(evtType, sw, out.toString(enc), strict); + } + + private void verifyValidReplacement(int evtType, XMLStreamWriter sw, String doc, boolean strict) + { + if (doc.indexOf(REPL_CHAR.charValue()) < 0) { // no replacement... + handleFailure(sw, "Failed to replace invalid char, event "+tokenTypeDesc(evtType)+", xml = '"+doc+"'", strict); + } + } + + private void buildValid(int evtType, XMLStreamWriter sw1) + throws XMLStreamException + { + XMLStreamWriter2 sw = (XMLStreamWriter2) sw1; + sw.writeStartDocument(); + sw.writeStartElement("root"); + + switch (evtType) { + case ATTRIBUTE: + sw.writeAttribute("attr", INVALID_TEXT); + break; + case CHARACTERS: + sw.writeCharacters(INVALID_TEXT); + break; + case CDATA: + sw.writeCData(INVALID_TEXT); + break; + case COMMENT: + sw.writeComment(INVALID_TEXT); + break; + case PROCESSING_INSTRUCTION: + sw.writeProcessingInstruction("pi", INVALID_TEXT); + break; + } + sw.writeEndElement(); + sw.writeEndDocument(); + sw.closeCompletely(); + } + + private void handleFailure(XMLStreamWriter sw, String msg, boolean doFail) + { + if (doFail) { + fail(msg+" (stream writer: "+sw+")"); + } else { + warn("suppressing failure '"+msg+"' (stream writer: "+sw+")"); + } + } + + /* + ////////////////////////////////////////////// + // Helper methods, low-level + ////////////////////////////////////////////// + */ + + private XMLOutputFactory2 getFactory(Character replChar) + throws XMLStreamException + { + XMLOutputFactory2 f = getOutputFactory(); + setRepairing(f, false); + setValidateContent(f, true); + f.setProperty(WstxOutputProperties.P_OUTPUT_INVALID_CHAR_HANDLER, + (replChar == null) ? null : new InvalidCharHandler.ReplacingHandler(replChar.charValue())); + return f; + } +} + diff -Nru libwoodstox-java-4.1.3/src/test/java/wstxtest/wstream/TestNameValidation.java libwoodstox-java-5.1.0/src/test/java/wstxtest/wstream/TestNameValidation.java --- libwoodstox-java-4.1.3/src/test/java/wstxtest/wstream/TestNameValidation.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/wstxtest/wstream/TestNameValidation.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,451 @@ +package wstxtest.wstream; + +import java.io.*; + +import javax.xml.stream.*; + +import org.codehaus.stax2.*; + +/** + * Woodstox-specific stream writer test suite that will ensure that the + * name validation property works properly (as expected) + */ +public class TestNameValidation + extends BaseWriterTest +{ + final static String DUMMY_URL = "http://someurl"; + final static String ATTR_VALUE = "value"; + final static String PI_DATA = "just some proc.instr. content!!"; + + /* Notes about validity + * + * - Dot is valid, but not as first name char + */ + + final static String[] VALID_NS_PREFIXES = new String[] { + "a", "ab_123", "this.attr", "_uber", "pre-fix" + }; + final static String[] VALID_NS_NAMES = new String[] { + "tag", "i", "my.dotted.name", + // note: dot is valid only as non-first char... + "x.12", "a_32", "__mymy", "a-ha" + }; + final static String[] VALID_NON_NS_NAMES = new String[] { + "ns:elem", ":::a", "xyz" + }; + final static String[] VALID_NS_ROOT_NAMES = new String[] { + "ns:elem", "abc", "a1:foobar" + }; + + final static String[] INVALID_NS_PREFIXES = new String[] { + "a:1", "1abc", "xy+z", "r&b", "", "fun\tny", ".ns", "-a" + }; + final static String[] INVALID_NS_NAMES = new String[] { + ":abc", "ns:elem", ".name", "", "1", "afoo", "", "1abc", " space", ".abc", "-23" + }; + final static String[] INVALID_NS_ROOT_NAMES = new String[] { + "ns:elem:blah", "a<>2", "", ".x", "-ab", "3cpu" + }; + + /* + //////////////////////////////////////////////////// + // Main test methods + //////////////////////////////////////////////////// + */ + + public void testValidElemNames() + throws XMLStreamException + { + for (int n = 0; n < 4; ++n) { + boolean ns = ((n & 1) == 0); + boolean validate = ((n & 2) == 0); + XMLStreamWriter sw = startDoc(validate, ns); + + // Let's add a dummy root: + sw.writeStartElement("dummy"); + + if (ns) { // need to check both prefixes and names + /* Note: when not repairing, need not worry about + * namespace binding... makes life easier here + */ + for (int i = 0; i < VALID_NS_NAMES.length; ++i) { + String name = VALID_NS_NAMES[i]; + sw.writeEmptyElement(name); + sw.writeStartElement(name); + sw.writeEndElement(); + } + for (int i = 0; i < VALID_NS_PREFIXES.length; ++i) { + String prefix = VALID_NS_PREFIXES[i]; + sw.writeEmptyElement(prefix, "elem", DUMMY_URL); + sw.writeStartElement(prefix, "elem", DUMMY_URL); + sw.writeEndElement(); + } + } else { + for (int i = 0; i < VALID_NON_NS_NAMES.length; ++i) { + String name = VALID_NON_NS_NAMES[i]; + sw.writeEmptyElement(name); + sw.writeStartElement(name); + sw.writeEndElement(); + } + } + + sw.writeEndElement(); + closeDoc(sw); + } + } + + public void testInvalidElemNames() + throws XMLStreamException + { + for (int n = 0; n < 2; ++n) { + boolean ns = (n == 1); + if (ns) { // need to check both prefixes and names + for (int i = 0; i < INVALID_NS_NAMES.length; ++i) { + String name = INVALID_NS_NAMES[i]; + for (int j = 0; j < INVALID_NS_PREFIXES.length; ++j) { + String prefix = INVALID_NS_PREFIXES[j]; + doTestInvalidElemName(true, prefix, name); + doTestInvalidElemName(true, null, name); + } + } + } else { + for (int i = 0; i < INVALID_NON_NS_NAMES.length; ++i) { + String name = INVALID_NON_NS_NAMES[i]; + doTestInvalidElemName(false, null, name); + } + } + } + } + + private void doTestInvalidElemName(boolean ns, String prefix, String name) + throws XMLStreamException + { + for (int i = 0; i < 2; ++i) { // to test both empty and non-empty elems + boolean empty = (i == 1); + try { + XMLStreamWriter sw = startDoc(true, ns); + sw.writeStartElement("dummy"); + + if (prefix == null) { + if (empty) { + sw.writeEmptyElement(name); + } else { + sw.writeStartElement(name); + sw.writeEndElement(); + } + } else { + if (empty) { + sw.writeEmptyElement(prefix, name, DUMMY_URL); + } else { + sw.writeStartElement(prefix, name, DUMMY_URL); + sw.writeEndElement(); + } + } + + sw.writeEndElement(); + closeDoc(sw); + + } catch (XMLStreamException iae) { + continue; // good + } + + fail("Failed to catch an invalid element name/prefix (ns = "+ns+"); name='" + +name+"', prefix = " + +((prefix == null) ? "NULL" : ("'"+prefix+"'"))+"."); + } + } + + public void testValidAttrNames() + throws Exception + { + for (int n = 0; n < 4; ++n) { + boolean ns = ((n & 1) == 0); + boolean validate = ((n & 2) == 0); + XMLStreamWriter sw = startDoc(validate, ns); + + // Let's add a dummy root: + sw.writeStartElement("dummy"); + + if (ns) { + for (int i = 0; i < VALID_NS_NAMES.length; ++i) { + String name = VALID_NS_NAMES[i]; + sw.writeAttribute(name, ATTR_VALUE); + } + for (int i = 0; i < VALID_NS_PREFIXES.length; ++i) { + String prefix = VALID_NS_PREFIXES[i]; + sw.writeAttribute(prefix, DUMMY_URL, "attr", ATTR_VALUE); + } + } else { + for (int i = 0; i < VALID_NON_NS_NAMES.length; ++i) { + String name = VALID_NON_NS_NAMES[i]; + sw.writeAttribute(name, ATTR_VALUE); + } + } + + sw.writeEndElement(); + closeDoc(sw); + } + } + + public void testInvalidAttrNames() + throws Exception + { + for (int n = 0; n < 2; ++n) { + boolean ns = (n == 1); + if (ns) { // need to check both prefixes and names + for (int i = 0; i < INVALID_NS_NAMES.length; ++i) { + String name = INVALID_NS_NAMES[i]; + for (int j = 0; j < INVALID_NS_PREFIXES.length; ++j) { + String prefix = INVALID_NS_PREFIXES[j]; + doTestInvalidAttrName(true, prefix, name); + doTestInvalidAttrName(true, null, name); + } + } + } else { + for (int i = 0; i < INVALID_NON_NS_NAMES.length; ++i) { + String name = INVALID_NON_NS_NAMES[i]; + doTestInvalidAttrName(false, null, name); + } + } + } + } + + private void doTestInvalidAttrName(boolean ns, String prefix, String name) + throws XMLStreamException + { + XMLStreamWriter sw = startDoc(true, ns); + sw.writeStartElement("dummy"); + try { + if (prefix == null) { + sw.writeAttribute(name, ATTR_VALUE); + } else { + sw.writeAttribute(prefix, DUMMY_URL, name, ATTR_VALUE); + } + } catch (XMLStreamException sex) { + sw.writeEndElement(); + closeDoc(sw); + return; // good + } + + fail("Failed to catch an invalid attr name/prefix (ns = "+ns+"); name='" + +name+"', prefix = " + +((prefix == null) ? "NULL" : ("'"+prefix+"'"))+"."); + } + + /** + * According to XML Namespaces 1.1 specification, PI targets + * can not contain colons either... + */ + public void testValidPiNames() + throws Exception + { + for (int n = 0; n < 4; ++n) { + boolean ns = ((n & 1) == 0); + boolean validate = ((n & 2) == 0); + XMLStreamWriter sw = startDoc(validate, ns); + + // Let's add a dummy root: + sw.writeStartElement("dummy"); + + /* No colons allowed in namespace-aware mode + */ + String[] strs = ns ? VALID_NS_NAMES : VALID_NON_NS_NAMES; + for (int i = 0; i < strs.length; ++i) { + String name = strs[i]; + sw.writeProcessingInstruction(name); + sw.writeProcessingInstruction(name, PI_DATA); + } + + sw.writeEndElement(); + closeDoc(sw); + } + } + + public void testInvalidPiNames() + throws Exception + { + for (int n = 0; n < 4; ++n) { + boolean ns = ((n & 1) == 0); + boolean empty = ((n & 2) == 0); + String[] strs = ns ? INVALID_NS_NAMES : INVALID_NON_NS_NAMES; + + for (int i = 0; i < strs.length; ++i) { + String name = strs[i]; + XMLStreamWriter sw = startDoc(true, ns); + sw.writeStartElement("dummy"); + + + try { + if (empty) { + sw.writeProcessingInstruction(name); + } else { + sw.writeProcessingInstruction(name, PI_DATA); + } + } catch (XMLStreamException sex) { + sw.writeEndElement(); + closeDoc(sw); + continue; // good + } + + fail("Failed to catch an invalid proc.instr. name (ns = "+ns+") '" + +name+"'."); + } + } + } + + /** + * Since the root element name is NOT really properly split (ie. it's + * never dealt with as a scoped name), we can only check if that it has + * zero or one colons (in NS-awre) mode, but nothing further + */ + public void testValidRootNames() + throws Exception + { + for (int n = 0; n < 4; ++n) { + boolean ns = ((n & 1) == 0); + boolean validate = ((n & 2) == 0); + + String[] strs = ns ? VALID_NS_ROOT_NAMES : VALID_NON_NS_NAMES; + for (int i = 0; i < strs.length; ++i) { + XMLStreamWriter2 sw = (XMLStreamWriter2)startDoc(validate, ns); + String rootName = strs[i]; + // only root name is mandatory, others are optional + sw.writeDTD(rootName, null, null, null); + // need a matching root, then: + if (ns) { // may need to split + int ix = rootName.indexOf(':'); + if (ix > 0) { + sw.writeEmptyElement(rootName.substring(0, ix), + rootName.substring(ix+1), + DUMMY_URL); + } else { + sw.writeEmptyElement(rootName); + } + } else { + sw.writeEmptyElement(rootName); + } + closeDoc(sw); + } + } + } + + public void testInvalidRootNames() + throws Exception + { + for (int n = 0; n < 2; ++n) { + boolean ns = ((n & 1) == 0); + String[] strs = ns ? INVALID_NS_ROOT_NAMES : INVALID_NON_NS_NAMES; + + for (int i = 0; i < strs.length; ++i) { + String rootName = strs[i]; + XMLStreamWriter2 sw = (XMLStreamWriter2)startDoc(true, ns); + try { + // only root name is mandatory, others are optional + sw.writeDTD(rootName, null, null, null); + sw.writeEmptyElement(rootName); // need a root...and should match too + } catch (XMLStreamException sex) { + continue; // good + } + + fail("Failed to catch an invalid DTD root name (ns = "+ns+") '" + +rootName+"'."); + } + } + } + + /** + * According to XML Namespaces 1.1 specification, entity names (ids) + * can not contain colons either... + *

+ * Note: Here we count on the fact that the current stream writer + * does not (and actually, can not!) verify whether the entity + * has been properly declared. + */ + public void testValidEntityNames() + throws Exception + { + for (int n = 0; n < 4; ++n) { + boolean ns = ((n & 1) == 0); + boolean validate = ((n & 2) == 0); + XMLStreamWriter sw = startDoc(validate, ns); + + // Let's add a dummy root: + sw.writeStartElement("dummy"); + + /* No colons allowed in namespace-aware mode + */ + String[] strs = ns ? VALID_NS_NAMES : VALID_NON_NS_NAMES; + for (int i = 0; i < strs.length; ++i) { + String name = strs[i]; + sw.writeEntityRef(name); + } + + sw.writeEndElement(); + closeDoc(sw); + } + } + + public void testInvalidEntityNames() + throws XMLStreamException + { + for (int n = 0; n < 2; ++n) { + boolean ns = ((n & 1) == 0); + String[] strs = ns ? INVALID_NS_ROOT_NAMES : INVALID_NON_NS_NAMES; + + for (int i = 0; i < strs.length; ++i) { + String name = strs[i]; + XMLStreamWriter2 sw = (XMLStreamWriter2)startDoc(true, ns); + sw.writeStartElement("dummy"); + try { + // only root name is mandatory, others are optional + sw.writeEntityRef(name); + } catch (XMLStreamException sex) { + sw.writeEndElement(); + closeDoc(sw); + continue; // good + } + + fail("Failed to catch an invalid entity name (ns = "+ns+") '" + +name+"'."); + } + } + } + + /* + //////////////////////////////////////////////////// + // Internal methods + //////////////////////////////////////////////////// + */ + + private XMLOutputFactory getFactory(boolean validateNames, boolean ns) + throws XMLStreamException + { + XMLOutputFactory f = getOutputFactory(); + setValidateNames(f, validateNames); + setNamespaceAware(f, ns); + // Let's disable repairing + setRepairing(f, false); + return f; + } + + private XMLStreamWriter startDoc(boolean validateNames, boolean ns) + throws XMLStreamException + { + XMLOutputFactory f = getFactory(validateNames, ns); + XMLStreamWriter sw = f.createXMLStreamWriter(new StringWriter()); + sw.writeStartDocument(); + return sw; + } + + private void closeDoc(XMLStreamWriter sw) + throws XMLStreamException + { + sw.writeEndDocument(); + sw.close(); + } +} + diff -Nru libwoodstox-java-4.1.3/src/test/java/wstxtest/wstream/TestOptions.java libwoodstox-java-5.1.0/src/test/java/wstxtest/wstream/TestOptions.java --- libwoodstox-java-4.1.3/src/test/java/wstxtest/wstream/TestOptions.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/wstxtest/wstream/TestOptions.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,69 @@ +package wstxtest.wstream; + +import java.io.*; + +import javax.xml.stream.*; + +import com.ctc.wstx.api.WstxOutputProperties; + +/** + * This unit test suite verifies Woodstox-specific writer-side options + */ +public class TestOptions + extends BaseWriterTest +{ + public void testEmptyElemSpaces() + throws IOException, XMLStreamException + { + /* Need to test both with and without space; as well as + * using Writer and using an OutputStream (since backends + * for the two are very different). + */ + for (int i = 0; i < 6; ++i) { + boolean space = ((i & 1) == 0); + String str; + boolean writer = (i < 2); + StringWriter strw = new StringWriter(); + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + XMLStreamWriter sw; + + if (writer) { + sw = getWriter(space, strw, null, null); + } else { + sw = getWriter(space, null, bos, (i < 4) ? "UTF-8" : "ISO-8859--1"); + } + sw.writeStartDocument(); + sw.writeEmptyElement("root"); + sw.writeEndDocument(); + sw.close(); + // Should have a space! + if (writer) { + str = strw.toString(); + } else { + str = new String(bos.toByteArray(), "UTF-8"); + } + + if (space) { + if (str.indexOf("") < 0) { + fail("Expected '' when space is to be added: got '"+str+"'"); + } + } else { + if (str.indexOf("") < 0) { + fail("Expected '' when space is NOT to be added: got '"+str+"'"); + } + } + } + } + + private XMLStreamWriter getWriter(boolean addSpace, Writer sw, OutputStream out, String enc) + throws IOException, XMLStreamException + { + XMLOutputFactory f = getOutputFactory(); + f.setProperty(WstxOutputProperties.P_ADD_SPACE_AFTER_EMPTY_ELEM, + Boolean.valueOf(addSpace)); + if (sw != null) { + return f.createXMLStreamWriter(sw); + } + return f.createXMLStreamWriter(out, enc); + } +} diff -Nru libwoodstox-java-4.1.3/src/test/java/wstxtest/wstream/TestRepairingNsOutput.java libwoodstox-java-5.1.0/src/test/java/wstxtest/wstream/TestRepairingNsOutput.java --- libwoodstox-java-4.1.3/src/test/java/wstxtest/wstream/TestRepairingNsOutput.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/wstxtest/wstream/TestRepairingNsOutput.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,211 @@ +package wstxtest.wstream; + +import java.io.*; + +import javax.xml.stream.*; + +public class TestRepairingNsOutput + extends BaseWriterTest +{ + + /* + //////////////////////////////////////////////////// + // Main test methods + //////////////////////////////////////////////////// + */ + + public void testNoDummyDefaultNs() + throws XMLStreamException + { + XMLOutputFactory f = getFactory(); + StringWriter strw = new StringWriter(); + XMLStreamWriter sw = f.createXMLStreamWriter(strw); + + sw.writeStartDocument(); + sw.writeStartElement("", "root", ""); + sw.writeAttribute("attr", "value"); + sw.writeAttribute("", "", "attr2", "value2"); + sw.writeStartElement("", "leaf", ""); + sw.writeAttribute("", "", "foop", "value2"); + sw.writeCharacters("Sub-text\n"); + sw.writeEndElement(); + sw.writeEndDocument(); + sw.close(); + + String result = strw.toString(); + + if (result.indexOf("xmlns=\"\"") > 0) { + fail("Did not expect unnecessary default NS declarations, but found some in result: ["+result+"]"); + } + } + + /** + * Starting with Woodstox 3.1, the repairing writer is to honour + * non-conflicting namespace write requests. This may be needed to + * either try to preserve ns declaration canonicality, and/or to + * minimize number of declarations (a common root can bind a namespace + * for children, even without having to use it for its own attributes + * or element name). + *

+ * Since this functionality is not required (or even suggested from what + * I can tell) by Stax 1.0 specs (and Stax2 does not change definitions + * of core API), this is in woodstox-specific section of tests. + */ + public void testExplicitNsWrites() + throws XMLStreamException + { + final String URI = "http://bar"; + XMLOutputFactory f = getFactory(); + StringWriter strw = new StringWriter(); + XMLStreamWriter sw = f.createXMLStreamWriter(strw); + + sw.writeStartDocument(); + /* root in no namespace, no attributes; but want to add + * an 'early' ns declaration for ns prefix 'foo', + * with URI 'http://bar' + */ + sw.writeStartElement("", "root"); + sw.writeNamespace("foo", URI); + // leaf in that namespace, then: + sw.writeStartElement(URI, "leaf"); + sw.writeEndElement(); + sw.writeEndElement(); + sw.writeEndDocument(); + sw.close(); + + String result = strw.toString(); + + // Ok, so let's parse and verify: + XMLStreamReader sr = constructNsStreamReader(result, false); + assertTokenType(START_ELEMENT, sr.next()); + assertEquals("root", sr.getLocalName()); + assertElemNotInNamespace(sr); + + int nsCount = sr.getNamespaceCount(); + assertEquals("Expected one (and only one) namespace declaration, got "+nsCount, 1, nsCount); + assertEquals("foo", sr.getNamespacePrefix(0)); + assertEquals(URI, sr.getNamespaceURI(0)); + + // And then the branch should have no ns decls: + assertTokenType(START_ELEMENT, sr.next()); + assertEquals("leaf", sr.getLocalName()); + assertEquals(URI, sr.getNamespaceURI()); + + assertEquals(0, sr.getNamespaceCount()); + + assertTokenType(END_ELEMENT, sr.next()); + assertEquals("leaf", sr.getLocalName()); + + // fine, rest is ok + sr.close(); + } + + /** + * Similar to {@link #testExplicitNsWrites}, but tests behavior + * of calls to XMLStreamWriter.writeDefaultNamespace + */ + public void testExplicitDefaultNsWrite() + throws XMLStreamException + { + final String URI1 = "http://foo"; + final String URI2 = "http://bar"; + XMLOutputFactory f = getFactory(); + StringWriter strw = new StringWriter(); + XMLStreamWriter sw = f.createXMLStreamWriter(strw); + + sw.writeStartDocument(); + /* root in explicit namespace, but additionally want to + * reserve the default ns: + */ + sw.writeStartElement("myns", "root", URI1); + sw.writeDefaultNamespace(URI2); + // leaf in that namespace, then: + sw.writeStartElement(URI2, "leaf"); + sw.writeEndElement(); + sw.writeEndElement(); + sw.writeEndDocument(); + sw.close(); + + String result = strw.toString(); + + // Ok, so let's parse and verify: + XMLStreamReader sr = constructNsStreamReader(result, false); + assertTokenType(START_ELEMENT, sr.next()); + assertEquals("root", sr.getLocalName()); + assertEquals("myns", sr.getPrefix()); + assertEquals(URI1, sr.getNamespaceURI()); + + int nsCount = sr.getNamespaceCount(); + assertEquals("Expected two namespace declarations, got "+nsCount, 2, nsCount); + + // And then leaf should have no ns decls: + assertTokenType(START_ELEMENT, sr.next()); + assertEquals("leaf", sr.getLocalName()); + assertNoElemPrefix(sr); + assertEquals(URI2, sr.getNamespaceURI()); + assertEquals(0, sr.getNamespaceCount()); + + assertTokenType(END_ELEMENT, sr.next()); + assertEquals("leaf", sr.getLocalName()); + + // fine, rest is ok + sr.close(); + } + + /** + * This test further verifies that caller's prefix-preference + * has higher priority than that of trying to find an existing + * prefix to use. + */ + public void testExplicitDupNsWrite() + throws XMLStreamException + { + final String URI = "http://bar"; + XMLOutputFactory f = getFactory(); + StringWriter strw = new StringWriter(); + XMLStreamWriter sw = f.createXMLStreamWriter(strw); + + sw.writeStartDocument(); + sw.writeStartElement("ns", "root", URI); + sw.writeAttribute("attrns", URI, "attr", "value"); + + sw.writeEndElement(); + sw.writeEndDocument(); + sw.close(); + + String result = strw.toString(); + + // Ok, so let's parse and verify: + XMLStreamReader sr = constructNsStreamReader(result, false); + assertTokenType(START_ELEMENT, sr.next()); + assertEquals("root", sr.getLocalName()); + assertEquals(URI, sr.getNamespaceURI()); + assertEquals(1, sr.getAttributeCount()); + assertEquals("attr", sr.getAttributeLocalName(0)); + assertEquals(URI, sr.getAttributeNamespace(0)); + // so far so good: but let's verify prefix is also what caller specified + assertEquals("attrns", sr.getAttributePrefix(0)); + + assertEquals(2, sr.getNamespaceCount()); + + // fine, rest is ok + sr.close(); + } + + /* + //////////////////////////////////////////////////// + // Internal methods + //////////////////////////////////////////////////// + */ + + private XMLOutputFactory getFactory() + throws XMLStreamException + { + XMLOutputFactory f = getOutputFactory(); + setNamespaceAware(f, true); + setRepairing(f, true); + return f; + } + +} + diff -Nru libwoodstox-java-4.1.3/src/test/java/wstxtest/wstream/TestStructuralValidation.java libwoodstox-java-5.1.0/src/test/java/wstxtest/wstream/TestStructuralValidation.java --- libwoodstox-java-4.1.3/src/test/java/wstxtest/wstream/TestStructuralValidation.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/wstxtest/wstream/TestStructuralValidation.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,177 @@ +package wstxtest.wstream; + +import java.io.*; + +import javax.xml.stream.*; + +import org.codehaus.stax2.*; + +/** + * This unit test suite verifies that output-side content validation + * works as expected, when enabled. + */ +public class TestStructuralValidation + extends BaseWriterTest +{ + /* + //////////////////////////////////////////////////// + // Main test methods + //////////////////////////////////////////////////// + */ + + /** + * Unit test suite for testing violations of structural checks, when + * trying to output things in prolog/epilog. + */ + public void testPrologChecks() + throws Exception + { + for (int i = 0; i <= 2; ++i) { // non-ns, simple-ns, repairing-ns + for (int j = 0; j < 2; ++j) { // prolog / epilog + boolean epilog = (j > 0); + final String prologMsg = epilog ? " in epilog" : " in prolog"; + + for (int op = 0; op <= 4; ++op) { + XMLOutputFactory2 f = getFactory(i, true); + StringWriter strw = new StringWriter(); + XMLStreamWriter2 sw = (XMLStreamWriter2) f.createXMLStreamWriter(strw); + String failMsg = null; + sw.writeStartDocument(); + + if (epilog) { + sw.writeStartElement("root"); + sw.writeEndElement(); + } + + try { + switch (op) { + case 0: // No non-white space text in prolog/epilog + failMsg = "when calling writeCharacters() for non-white space text"; + sw.writeCharacters("test!"); + break; + case 1: // - "" - + failMsg = "when calling writeCharacters() for non-white space text"; + sw.writeCharacters(new char[] { 't', 'e', 's', 't' }, 0, 4); + break; + case 2: // No CDATA in prolog/epilog + failMsg = "when calling writeCData()"; + sw.writeCData("cdata"); + case 3: // - "" - + failMsg = "when calling writeCData()"; + sw.writeCData(new char[] { 't', 'e', 's', 't' }, 0, 4); + case 4: // no entity refs in prolog/epilog: + failMsg = "when calling writeEntityRef()"; + sw.writeEntityRef("entity"); + default: + throw new Error("Internal error: illegal test index "+op); + } + } catch (XMLStreamException sex) { + // good + continue; + } catch (Throwable t) { + fail("Expected an XMLStreamException for "+failMsg+prologMsg+"; got "+t); + } finally { + if (epilog) { + sw.close(); + } + } + + fail("Expected an XMLStreamException for "+failMsg+prologMsg+"; no exception thrown"); + } + } + } + } + + /** + * Unit test that verifies that root element structural problems (no root, + * that is, an empty doc; more than one root element) are caught. + */ + public void testRootElementChecks() + throws XMLStreamException + { + for (int i = 0; i <= 2; ++i) { // non-ns, simple-ns, repairing-ns + for (int op = 0; op < 2; ++op) { + XMLOutputFactory2 f = getFactory(i, true); + StringWriter strw = new StringWriter(); + XMLStreamWriter2 sw = (XMLStreamWriter2) f.createXMLStreamWriter(strw); + String failMsg = null; + sw.writeStartDocument(); + + try { + switch (op) { + case 0: // No root element? + failMsg = "missing root element"; + sw.writeEndDocument(); + break; + case 1: // Two root elements... + failMsg = "second root element"; + sw.writeStartElement("root1"); + sw.writeEndElement(); + sw.writeStartElement("root1"); + sw.writeEndElement(); + break; + default: + throw new Error("Internal error: illegal test index "+op); + } + } catch (XMLStreamException sex) { + // good + continue; + } catch (Throwable t) { + fail("Expected an XMLStreamException for "+failMsg); + } + } + } + } + + public void testWriteElementChecks() + throws XMLStreamException + { + /* + for (int i = 0; i <= 2; ++i) { + // First, checks for prolog: + + for (int op = 0; op < 2; ++op) { + XMLOutputFactory2 f = getFactory(i, true); + StringWriter strw = new StringWriter(); + XMLStreamWriter2 sw = (XMLStreamWriter2) f.createXMLStreamWriter(strw); + String failMsg = null; + + sw.writeStartDocument(); + + // No non-white space text in prolog + try { + switch (op) { + case 0: + failMsg = "when calling writeCharacters() for non-white space text in prolog"; + sw.writeCharacters("test!"); + break; + default: + } + } catch (XMLStreamException sex) { + // good + } catch (Throwable t) { + fail("Expected an XMLStreamException for illegal comment content (contains '--') in checking + non-fixing mode; got: "+t); + } + sw.close(); + } + } + */ + } + + /* + //////////////////////////////////////////////////// + // Helper methods + //////////////////////////////////////////////////// + */ + + private XMLOutputFactory2 getFactory(int type, boolean checkStruct) + throws XMLStreamException + { + XMLOutputFactory2 f = getOutputFactory(); + // type 0 -> non-ns, 1 -> ns, non-repairing, 2 -> ns, repairing + setNamespaceAware(f, type > 0); + setRepairing(f, type > 1); + setValidateStructure(f, checkStruct); + return f; + } +} diff -Nru libwoodstox-java-4.1.3/src/test/java/wstxtest/wstream/TestWriterProperties.java libwoodstox-java-5.1.0/src/test/java/wstxtest/wstream/TestWriterProperties.java --- libwoodstox-java-4.1.3/src/test/java/wstxtest/wstream/TestWriterProperties.java 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/java/wstxtest/wstream/TestWriterProperties.java 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,35 @@ +package wstxtest.wstream; + +import java.io.*; + +import javax.xml.stream.*; + +import com.ctc.wstx.api.WstxOutputProperties; + +/** + * This unit test suite checks that per-writer properties are + * accessible as expected. + */ +public class TestWriterProperties + extends BaseWriterTest +{ + public void testAccessStream() + throws XMLStreamException + { + XMLOutputFactory f = getOutputFactory(); + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + XMLStreamWriter sw = f.createXMLStreamWriter(bos, "UTF-8"); + + assertSame(bos, sw.getProperty(WstxOutputProperties.P_OUTPUT_UNDERLYING_STREAM)); + } + + public void testAccessWriter() + throws XMLStreamException + { + XMLOutputFactory f = getOutputFactory(); + StringWriter strw = new StringWriter(); + XMLStreamWriter sw = f.createXMLStreamWriter(strw); + + assertSame(strw, sw.getProperty(WstxOutputProperties.P_OUTPUT_UNDERLYING_WRITER)); + } +} diff -Nru libwoodstox-java-4.1.3/src/test/org/codehaus/stax/test/BaseStaxTest.java libwoodstox-java-5.1.0/src/test/org/codehaus/stax/test/BaseStaxTest.java --- libwoodstox-java-4.1.3/src/test/org/codehaus/stax/test/BaseStaxTest.java 2012-04-24 04:38:21.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/org/codehaus/stax/test/BaseStaxTest.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,655 +0,0 @@ -package org.codehaus.stax.test; - -import java.io.*; -import java.util.HashMap; - -import junit.framework.TestCase; - -import javax.xml.stream.*; -import javax.xml.stream.events.XMLEvent; - -/* Latest updates: - * - * - 07-Sep-2007, TSa: Updating based on latest understanding of - * the proper use of null and Empty String wrt. "no prefix" and - * "no namespace" cases. - */ - -/** - * Base class for all StaxTest unit test classes. Contains shared - * functionality for many common set up tasks, as well as for - * outputting diagnostics. - * - * @author Tatu Saloranta - */ -public abstract class BaseStaxTest - extends TestCase - implements XMLStreamConstants -{ - /** - * This is the de facto standard property that enables accurate reporting - * of CDATA events. - */ - final static String PROP_REPORT_CDATA = "http://java.sun.com/xml/stream/properties/report-cdata-event"; - - final static HashMap mTokenTypes = new HashMap(); - static { - mTokenTypes.put(new Integer(START_ELEMENT), "START_ELEMENT"); - mTokenTypes.put(new Integer(END_ELEMENT), "END_ELEMENT"); - mTokenTypes.put(new Integer(START_DOCUMENT), "START_DOCUMENT"); - mTokenTypes.put(new Integer(END_DOCUMENT), "END_DOCUMENT"); - mTokenTypes.put(new Integer(CHARACTERS), "CHARACTERS"); - mTokenTypes.put(new Integer(CDATA), "CDATA"); - mTokenTypes.put(new Integer(COMMENT), "COMMENT"); - mTokenTypes.put(new Integer(PROCESSING_INSTRUCTION), "PROCESSING_INSTRUCTION"); - mTokenTypes.put(new Integer(DTD), "DTD"); - mTokenTypes.put(new Integer(SPACE), "SPACE"); - mTokenTypes.put(new Integer(ENTITY_REFERENCE), "ENTITY_REFERENCE"); - mTokenTypes.put(new Integer(NAMESPACE), "NAMESPACE_DECLARATION"); - mTokenTypes.put(new Integer(NOTATION_DECLARATION), "NOTATION_DECLARATION"); - mTokenTypes.put(new Integer(ENTITY_DECLARATION), "ENTITY_DECLARATION"); - } - - /* - /////////////////////////////////////////////////// - // Consts for expected values - /////////////////////////////////////////////////// - */ - - /** - * Expected return value for streamReader.getNamespaceURI() in - * non-namespace-aware mode. - */ - protected final String DEFAULT_URI_NON_NS = ""; - - protected final String DEFAULT_URI_NS = ""; - - /* - /////////////////////////////////////////////////// - // Other consts - /////////////////////////////////////////////////// - */ - - /* - /////////////////////////////////////////////////// - // Cached instances - /////////////////////////////////////////////////// - */ - - XMLInputFactory mInputFactory; - XMLOutputFactory mOutputFactory; - XMLEventFactory mEventFactory; - - protected BaseStaxTest(String name) { super(name); } - - protected BaseStaxTest() { super(); } - - /* - ////////////////////////////////////////////////// - // Factory methods - ////////////////////////////////////////////////// - */ - - protected XMLInputFactory getInputFactory() - { - if (mInputFactory == null) { - mInputFactory = getNewInputFactory(); - } - return mInputFactory; - } - - protected static XMLInputFactory getNewInputFactory() - { - return XMLInputFactory.newInstance(); - } - - protected XMLOutputFactory getOutputFactory() - { - if (mOutputFactory == null) { - mOutputFactory = getNewOutputFactory(); - } - return mOutputFactory; - } - - protected static XMLOutputFactory getNewOutputFactory() - { - return XMLOutputFactory.newInstance(); - } - - protected XMLEventFactory getEventFactory() - { - if (mEventFactory == null) { - mEventFactory = XMLEventFactory.newInstance(); - } - return mEventFactory; - } - - protected static XMLStreamReader constructUtf8StreamReader(XMLInputFactory f, String content) - throws XMLStreamException - { - try { - return f.createXMLStreamReader(new ByteArrayInputStream(content.getBytes("UTF-8"))); - } catch (UnsupportedEncodingException e) { - throw new RuntimeException(e); - } - } - - protected static XMLStreamReader constructCharStreamReader(XMLInputFactory f, String content) - throws XMLStreamException - { - return f.createXMLStreamReader(new StringReader(content)); - } - - protected static XMLStreamReader constructStreamReader(XMLInputFactory f, String content) - throws XMLStreamException - { - /* Can either create a simple reader from String, or go with - * input stream & decoding? - */ - //return constructCharStreamReader(f, content); - return constructUtf8StreamReader(f, content); - } - - protected static XMLStreamReader constructStreamReader(XMLInputFactory f, byte[] b) - throws XMLStreamException - { - return f.createXMLStreamReader(new ByteArrayInputStream(b)); - } - - protected static XMLStreamReader constructStreamReaderForFile(XMLInputFactory f, String filename) - throws IOException, XMLStreamException - { - File inf = new File(filename); - XMLStreamReader sr = f.createXMLStreamReader(inf.toURL().toString(), - new FileReader(inf)); - assertEquals(START_DOCUMENT, sr.getEventType()); - return sr; - } - - protected XMLStreamReader constructNsStreamReader(String content) - throws XMLStreamException - { - XMLInputFactory f = getInputFactory(); - setNamespaceAware(f, true); - return f.createXMLStreamReader(new StringReader(content)); - } - - protected XMLStreamReader constructNsStreamReader(String content, boolean coal) - throws XMLStreamException - { - XMLInputFactory f = getInputFactory(); - setNamespaceAware(f, true); - setCoalescing(f, coal); - return f.createXMLStreamReader(new StringReader(content)); - } - - /* - ////////////////////////////////////////////////// - // Configuring input factory - ////////////////////////////////////////////////// - */ - - protected static boolean isCoalescing(XMLInputFactory f) - throws XMLStreamException - { - return ((Boolean) f.getProperty(XMLInputFactory.IS_COALESCING)).booleanValue(); - } - - protected static void setCoalescing(XMLInputFactory f, boolean state) - throws XMLStreamException - { - Boolean b = state ? Boolean.TRUE : Boolean.FALSE; - f.setProperty(XMLInputFactory.IS_COALESCING, b); - // Let's just double-check it... - assertEquals(state, isCoalescing(f)); - } - - protected static boolean isValidating(XMLInputFactory f) - throws XMLStreamException - { - return ((Boolean) f.getProperty(XMLInputFactory.IS_VALIDATING)).booleanValue(); - } - - protected static void setValidating(XMLInputFactory f, boolean state) - throws XMLStreamException - { - try { - Boolean b = state ? Boolean.TRUE : Boolean.FALSE; - f.setProperty(XMLInputFactory.IS_VALIDATING, b); - } catch (IllegalArgumentException iae) { - fail("Could not set DTD validating mode to "+state+": "+iae); - //throw new XMLStreamException(iae.getMessage(), iae); - } - assertEquals(state, isValidating(f)); - } - - protected static boolean isNamespaceAware(XMLInputFactory f) - throws XMLStreamException - { - return ((Boolean) f.getProperty(XMLInputFactory.IS_NAMESPACE_AWARE)).booleanValue(); - } - - /** - * @return True if setting succeeded, and property supposedly was - * succesfully set to the value specified; false if there was a problem. - */ - protected static boolean setNamespaceAware(XMLInputFactory f, boolean state) - throws XMLStreamException - { - try { - f.setProperty(XMLInputFactory.IS_NAMESPACE_AWARE, - state ? Boolean.TRUE : Boolean.FALSE); - - /* 07-Sep-2005, TSa: Let's not assert, but instead let's see if - * it sticks. Some implementations might choose to silently - * ignore setting, at least for 'false'? - */ - return (isNamespaceAware(f) == state); - } catch (IllegalArgumentException e) { - /* Let's assume, then, that the property (or specific value for it) - * is NOT supported... - */ - return false; - } - } - - protected static void setReplaceEntities(XMLInputFactory f, boolean state) - throws XMLStreamException - { - Boolean b = state ? Boolean.TRUE : Boolean.FALSE; - f.setProperty(XMLInputFactory.IS_REPLACING_ENTITY_REFERENCES, b); - assertEquals(b, f.getProperty(XMLInputFactory.IS_REPLACING_ENTITY_REFERENCES)); - } - - protected static void setSupportDTD(XMLInputFactory f, boolean state) - throws XMLStreamException - { - Boolean b = state ? Boolean.TRUE : Boolean.FALSE; - f.setProperty(XMLInputFactory.SUPPORT_DTD, b); - assertEquals(b, f.getProperty(XMLInputFactory.SUPPORT_DTD)); - } - - protected static boolean setSupportExternalEntities(XMLInputFactory f, boolean state) - throws XMLStreamException - { - Boolean b = state ? Boolean.TRUE : Boolean.FALSE; - try { - f.setProperty(XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES, b); - Object act = f.getProperty(XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES); - return (act instanceof Boolean) && ((Boolean) act).booleanValue() == state; - } catch (IllegalArgumentException e) { - /* Let's assume, then, that the property (or specific value for it) - * is NOT supported... - */ - return false; - } - } - - protected static void setResolver(XMLInputFactory f, XMLResolver resolver) - throws XMLStreamException - { - f.setProperty(XMLInputFactory.RESOLVER, resolver); - } - - protected static boolean setReportCData(XMLInputFactory f, boolean state) - throws XMLStreamException - { - - Boolean b = state ? Boolean.TRUE : Boolean.FALSE; - if (f.isPropertySupported(PROP_REPORT_CDATA)) { - f.setProperty(PROP_REPORT_CDATA, b); - return true; - } - return false; - } - - /* - ////////////////////////////////////////////////// - // Stream reader accessors - ////////////////////////////////////////////////// - */ - - /** - * Method that not only gets currently available text from the - * reader, but also checks that its consistenly accessible using - * different StAX methods. - */ - protected static String getAndVerifyText(XMLStreamReader sr) - throws XMLStreamException - { - String text = sr.getText(); - - /* 05-Apr-2006, TSa: Although getText() is available for DTD - * and ENTITY_REFERENCE, getTextXxx() are not. Thus, can not - * do more checks for those types. - */ - int type = sr.getEventType(); - if (type != ENTITY_REFERENCE && type != DTD) { - assertNotNull("getText() should never return null.", text); - int expLen = sr.getTextLength(); - /* Hmmh. Can only return empty text for CDATA (since empty - * blocks are legal). - */ - /* !!! 01-Sep-2004, TSa: - * note: theoretically, in coalescing mode, it could be possible - * to have empty CDATA section(s) get converted to CHARACTERS, - * which would be empty... may need to enhance this to check that - * mode is not coalescing? Or something - */ - if (sr.getEventType() == CHARACTERS) { - if (expLen == 0) { - fail("Stream reader should never return empty Strings."); - } - } - assertEquals("Expected text length of "+expLen+", got "+text.length(), - expLen, text.length()); - char[] textChars = sr.getTextCharacters(); - int start = sr.getTextStart(); - String text2 = new String(textChars, start, expLen); - assertEquals("Expected getText() and getTextCharacters() to return same value for event of type ("+tokenTypeDesc(sr.getEventType())+")", text, text2); - } else { // DTD or ENTITY_REFERENCE - // not sure if null is legal for these either, but... - if (text == null) { // let's prevent an NPE at caller - text = ""; - } - } - return text; - } - - protected static String getAllText(XMLStreamReader sr) - throws XMLStreamException - { - StringBuffer sb = new StringBuffer(); - while (true) { - int tt = sr.getEventType(); - if (tt != CHARACTERS && tt != SPACE && tt != CDATA) { - break; - } - sb.append(getAndVerifyText(sr)); - sr.next(); - } - return sb.toString(); - } - - protected static String getAllCData(XMLStreamReader sr) - throws XMLStreamException - { - StringBuffer sb = new StringBuffer(); - while (true) { - /* Note: CDATA sections CAN be reported as CHARACTERS, but - * not as SPACE - */ - int tt = sr.getEventType(); - if (tt != CHARACTERS && tt != CDATA) { - break; - } - sb.append(getAndVerifyText(sr)); - sr.next(); - } - return sb.toString(); - } - - /* - ////////////////////////////////////////////////// - // Derived assert/fail methods - ////////////////////////////////////////////////// - */ - - protected static void assertTokenType(int expType, int actType) - { - if (expType == actType) { - return; - } - fail("Expected token "+tokenTypeDesc(expType) - +"; got "+tokenTypeDesc(actType)+"."); - } - - protected static void assertTokenType(int expType, int actType, - XMLStreamReader sr) - { - if (expType == actType) { - return; - } - fail("Expected token "+tokenTypeDesc(expType) - +"; got "+tokenTypeDesc(actType, sr)+"."); - } - - protected static void assertTextualTokenType(int actType) - { - if (actType != CHARACTERS && actType != SPACE - && actType != CDATA) { - fail("Expected textual token (CHARACTERS, SPACE or CDATA)" - +"; got "+tokenTypeDesc(actType)+"."); - } - } - - protected static void failStrings(String msg, String exp, String act) - { - // !!! TODO: Indicate position where Strings differ - fail(msg+": expected "+quotedPrintable(exp)+", got " - +quotedPrintable(act)); - } - - /** - * Helper method for ensuring that the current element - * (START_ELEMENT, END_ELEMENT) has no prefix - *

- * Specific method makes sense, since earlier it was not clear - * whether null or empty string (or perhaps both) would be the - * right answer when there is no prefix. - *

- * Current thinking (early 2008) is that empty string is the - * expected value - */ - protected static void assertNoPrefix(XMLStreamReader sr) - throws XMLStreamException - { - String prefix = sr.getPrefix(); - if (prefix == null) { - fail("Expected \"\" to signify missing prefix (see XMLStreamReader#getPrefix() JavaDocs): got null"); - } else { - if (prefix.length() > 0) { - fail("Current element should not have a prefix: got '"+prefix+"'"); - } - } - } - - /** - * Helper method for ensuring that the given return value for - * attribute prefix accessor has returned a value that - * represents "no prefix" value. - *

- * Current thinking (early 2008) is that empty string is the - * expected value here. - */ - protected static void assertNoAttrPrefix(String attrPrefix) - throws XMLStreamException - { - if (attrPrefix == null) { - fail("Attribute that does not have a prefix should be indicated with \"\", not null"); - } else { - if (attrPrefix.length() > 0) { - fail("Attribute should not have prefix (had '"+attrPrefix+"')"); - } - } - } - - /** - * Similar to {@link #assertNoPrefix}, but here we do know that unbound - * namespace URI should be indicated as empty String. - */ - protected static void assertNoNsURI(XMLStreamReader sr) - throws XMLStreamException - { - String uri = sr.getNamespaceURI(); - if (uri == null) { - fail("Expected empty String to indicate \"no namespace\": got null"); - } else if (uri.length() != 0) { - fail("Expected empty String to indicate \"no namespace\": got '"+uri+"'"); - } - } - - protected static void assertNoAttrNamespace(String attrNsURI) - throws XMLStreamException - { - if (attrNsURI == null) { - fail("Expected empty String to indicate \"no namespace\" (for attribute): got null"); - } else if (attrNsURI.length() != 0) { - fail("Expected empty String to indicate \"no namespace\" (for attribute): got '"+attrNsURI+"'"); - } - } - - protected static void assertNoPrefixOrNs(XMLStreamReader sr) - throws XMLStreamException - { - assertNoPrefix(sr); - assertNoNsURI(sr); - } - - /** - * Helper assertion that assert that the String is either null or - * empty (""). - */ - protected static void assertNullOrEmpty(String str) - { - if (str != null && str.length() > 0) { - fail("Expected String to be empty or null; was '"+str+"' (length " - +str.length()+")"); - } - } - - /* - ////////////////////////////////////////////////// - // Debug/output helpers - ////////////////////////////////////////////////// - */ - - protected static String tokenTypeDesc(int tt) - { - String desc = (String) mTokenTypes.get(new Integer(tt)); - if (desc == null) { - return "["+tt+"]"; - } - return desc; - } - - protected static String tokenTypeDesc(XMLEvent evt) - { - return tokenTypeDesc(evt.getEventType()); - } - - final static int MAX_DESC_TEXT_CHARS = 8; - - protected static String tokenTypeDesc(int tt, XMLStreamReader sr) - { - String desc = tokenTypeDesc(tt); - // Let's show first 8 chars or so... - if (tt == CHARACTERS || tt == SPACE || tt == CDATA) { - String str = sr.getText(); - if (str.length() > MAX_DESC_TEXT_CHARS) { - desc = "\""+str.substring(0, MAX_DESC_TEXT_CHARS) + "\"[...]"; - } else { - desc = "\"" + desc + "\""; - } - desc = " ("+desc+")"; - } - return desc; - } - - protected static String valueDesc(String value) - { - if (value == null) { - return "[NULL]"; - } - return "\"" + value + "\""; - } - - protected static String printable(char ch) - { - if (ch == '\n') { - return "\\n"; - } - if (ch == '\r') { - return "\\r"; - } - if (ch == '\t') { - return "\\t"; - } - if (ch == ' ') { - return "_"; - } - if (ch > 127 || ch < 32) { - StringBuffer sb = new StringBuffer(6); - sb.append("\\u"); - String hex = Integer.toHexString((int)ch); - for (int i = 0, len = 4 - hex.length(); i < len; i++) { - sb.append('0'); - } - sb.append(hex); - return sb.toString(); - } - return null; - } - - protected static String printable(String str) - { - if (str == null || str.length() == 0) { - return str; - } - - int len = str.length(); - StringBuffer sb = new StringBuffer(len + 64); - for (int i = 0; i < len; ++i) { - char c = str.charAt(i); - String res = printable(c); - if (res == null) { - sb.append(c); - } else { - sb.append(res); - } - } - return sb.toString(); - } - - protected static String quotedPrintable(String str) - { - if (str == null || str.length() == 0) { - return "[0]''"; - } - return "[len: "+str.length()+"] '"+printable(str)+"'"; - } - - protected void reportNADueToProperty(String method, String prop) - { - String clsName = getClass().getName(); - /* 27-Sep-2005, TSa: Should probably use some other mechanism for - * reporting this. Does JUnit have something applicable? - */ - System.err.println("Skipping "+clsName+"#"+method+": property '" - +prop+"' (or one of its values) not supported."); - } - - protected void reportNADueToNS(String method) - { - reportNADueToProperty(method, "IS_NAMESPACE_AWARE"); - } - - protected void reportNADueToExtEnt(String method) - { - reportNADueToProperty(method, "IS_SUPPORTING_EXTERNAL_ENTITIES"); - } - - protected void reportNADueToEntityExpansion(String method, int type) - { - String clsName = getClass().getName(); - String msg = (type > 0) ? " (next event: "+tokenTypeDesc(type)+")" : ""; - System.err.println("Skipping "+clsName+"#"+method+": entity expansion does not seem to be functioning properly"+msg+"."); - } - - protected void warn(String msg) - { - // Hmmh. Should we add a dependency to log4j or j.u.l? - // For now let's just dump to console. - System.err.println("WARN: "+msg); - } -} diff -Nru libwoodstox-java-4.1.3/src/test/org/codehaus/stax/test/dtd/BaseTestForDTD.java libwoodstox-java-5.1.0/src/test/org/codehaus/stax/test/dtd/BaseTestForDTD.java --- libwoodstox-java-4.1.3/src/test/org/codehaus/stax/test/dtd/BaseTestForDTD.java 2012-04-24 04:38:21.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/org/codehaus/stax/test/dtd/BaseTestForDTD.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,22 +0,0 @@ -package org.codehaus.stax.test.dtd; - -import javax.xml.stream.XMLInputFactory; -import javax.xml.stream.XMLStreamException; -import javax.xml.stream.XMLStreamReader; - -import org.codehaus.stax.test.stream.BaseStreamTest; - -abstract class BaseTestForDTD extends BaseStreamTest -{ - protected XMLStreamReader getDTDAwareReader(String contents, boolean validate) - throws XMLStreamException - { - XMLInputFactory f = getInputFactory(); - setCoalescing(f, false); - setNamespaceAware(f, true); - setSupportDTD(f, true); - // Let's make sure DTD is really parsed? - setValidating(f, validate); - return constructStreamReader(f, contents); - } -} diff -Nru libwoodstox-java-4.1.3/src/test/org/codehaus/stax/test/dtd/TestDtdWithUnicodeEntities.java libwoodstox-java-5.1.0/src/test/org/codehaus/stax/test/dtd/TestDtdWithUnicodeEntities.java --- libwoodstox-java-4.1.3/src/test/org/codehaus/stax/test/dtd/TestDtdWithUnicodeEntities.java 2012-04-24 04:38:21.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/org/codehaus/stax/test/dtd/TestDtdWithUnicodeEntities.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,32 +0,0 @@ -package org.codehaus.stax.test.dtd; - -import javax.xml.stream.XMLStreamReader; - -public class TestDtdWithUnicodeEntities extends BaseTestForDTD -{ - /** - * Test to verify [WSTX-256], issues with character entities for DTD-declared - * entities. - */ - public void testEntitiesEmbedded() throws Exception - { - final String XML = "" - +"]>\n" - +"&Abc;\n&Abc;" - ; - XMLStreamReader sr = getDTDAwareReader(XML, false); - assertTokenType(DTD, sr.next()); - assertTokenType(START_ELEMENT, sr.next()); - assertEquals("root", sr.getLocalName()); - assertTokenType(CHARACTERS, sr.next()); - String text = getAllText(sr); - // we should have two surrogate pairs in there... - assertEquals(5, text.length()); - assertEquals(0x1D504, Character.codePointAt(text, 0)); - assertEquals(0x1D504, Character.codePointAt(text, 3)); - assertTokenType(END_ELEMENT, sr.getEventType()); - assertEquals("root", sr.getLocalName()); - assertTokenType(END_DOCUMENT, sr.next()); - } -} diff -Nru libwoodstox-java-4.1.3/src/test/org/codehaus/stax/test/evt/BaseEventTest.java libwoodstox-java-5.1.0/src/test/org/codehaus/stax/test/evt/BaseEventTest.java --- libwoodstox-java-4.1.3/src/test/org/codehaus/stax/test/evt/BaseEventTest.java 2012-04-24 04:38:21.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/org/codehaus/stax/test/evt/BaseEventTest.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,147 +0,0 @@ -package org.codehaus.stax.test.evt; - -import java.io.*; -import java.util.Iterator; - -import javax.xml.stream.*; -import javax.xml.stream.events.*; - -import org.codehaus.stax.test.BaseStaxTest; - -/** - * Base class for all StaxTest unit tests that test Event API - * functionality. - * - * @author Tatu Saloranta - */ -abstract class BaseEventTest - extends BaseStaxTest -{ - protected BaseEventTest() { super(); } - - /* - /////////////////////////////////////////////////////////// - // Utility methods - /////////////////////////////////////////////////////////// - */ - - protected XMLEventFactory getEventFactory() - throws FactoryConfigurationError - { - return XMLEventFactory.newInstance(); - } - - protected static XMLEventReader constructEventReader(XMLInputFactory f, String content) - throws XMLStreamException - { - return f.createXMLEventReader(new StringReader(content)); - } - - protected static XMLEventReader constructEventReaderForFile(XMLInputFactory f, String filename) - throws IOException, XMLStreamException - { - File inf = new File(filename); - XMLEventReader er = f.createXMLEventReader(inf.toURL().toString(), - new FileReader(inf)); - return er; - } - - /** - * Method that will iterate through contents of an XML document - * using specified event reader; will also access some of data - * to make sure reader reads most of lazy-loadable data. - * Method is usually called to try to get an exception for invalid - * content. - * - * @return Dummy value calculated on contents; used to make sure - * no dead code is eliminated - */ - protected int streamThrough(XMLEventReader er) - throws XMLStreamException - { - int result = 0; - - while (er.hasNext()) { - XMLEvent evt = er.nextEvent(); - int type = evt.getEventType(); - result += type; - if (evt.isCharacters()) { - result += evt.asCharacters().getData().hashCode(); - } - } - - return result; - } - - protected int calcAttrCount(StartElement elem) - throws XMLStreamException - { - int count = 0; - Iterator it = elem.getAttributes(); - if (it != null) { - while (it.hasNext()) { - Attribute attr = (Attribute) it.next(); - ++count; - } - } - return count; - } - - public static void checkEventIsMethods(int type, XMLEvent evt) - { - int actualType = evt.getEventType(); - if (actualType != type) { - /* Minor deviation; should Characters objects that are constructed - * for CDATA and SPACE return true type or CHARACTERS? - */ - if (type == CHARACTERS && - (actualType == SPACE || actualType == CDATA)) { - // for now let's let this pass... - } else { - assertTokenType(type, actualType); // this'll fail and output descs for types - } - } - - /* Hmmh. Whether Namespace object should return true or false - * is an open question. So let's accept both - */ - if (type == NAMESPACE) { - /* for now let's just ask for it (to make sure it won't throw - * exceptions), but not verify the value - */ - boolean isAttr = evt.isAttribute(); - } else { - assertEquals((type == ATTRIBUTE), evt.isAttribute()); - } - - assertEquals((type == CHARACTERS), evt.isCharacters()); - assertEquals((type == START_DOCUMENT), evt.isStartDocument()); - assertEquals((type == END_DOCUMENT), evt.isEndDocument()); - assertEquals((type == START_ELEMENT), evt.isStartElement()); - assertEquals((type == END_ELEMENT), evt.isEndElement()); - assertEquals((type == ENTITY_REFERENCE), evt.isEntityReference()); - assertEquals((type == NAMESPACE), evt.isNamespace()); - assertEquals((type == PROCESSING_INSTRUCTION), evt.isProcessingInstruction()); - } - - /** - * Simple test utility method that just calls output method, to verify - * it does not throw anything nasty, and does output something. - * Not enough to verify actual working, but should exercise code path - * to check for fatal problems. - */ - public void testEventWritability(XMLEvent evt) - throws XMLStreamException - { - StringWriter sw = new StringWriter(); - evt.writeAsEncodedUnicode(sw); - - // Some events do not (have to) output anything: - switch (evt.getEventType()) { - case END_DOCUMENT: // nothing to output, usually - return; - } - - assertTrue(sw.toString().length() > 0); - } -} diff -Nru libwoodstox-java-4.1.3/src/test/org/codehaus/stax/test/evt/TestEventCopy.java libwoodstox-java-5.1.0/src/test/org/codehaus/stax/test/evt/TestEventCopy.java --- libwoodstox-java-4.1.3/src/test/org/codehaus/stax/test/evt/TestEventCopy.java 2012-04-24 04:38:21.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/org/codehaus/stax/test/evt/TestEventCopy.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,147 +0,0 @@ -package org.codehaus.stax.test.evt; - -import java.util.NoSuchElementException; - -import javax.xml.namespace.QName; -import javax.xml.stream.*; -import javax.xml.stream.events.*; - -import java.io.*; -import java.util.*; - -/** - * This test tries to verify that events can be copied from event reader - * to event writer, and result in well-formed output - * - * @author Tatu Saloranta - */ -public class TestEventCopy - extends BaseEventTest -{ - public void testCopy() - throws XMLStreamException - { - final String XML = - "\n" - +" \n" - +" " - +" \n" - +" " - +"" - ; - XMLEventReader er = getEventReader(XML, true, true); - StringWriter strw = new StringWriter(); - XMLOutputFactory f = getOutputFactory(); - XMLEventWriter ew = f.createXMLEventWriter(strw); - - while (er.hasNext()) { - ew.add(er.nextEvent()); - } - ew.close(); - - // And let's then just verify it's well-formed still - String results = strw.toString(); - er = getEventReader(results, true, true); - XMLEvent evt; - - // Plus that events are the way they ought to be - assertNotNull((evt = er.nextEvent())); - assertTrue(evt.isStartDocument()); - - evt = er.nextEvent(); - assertEquals(new QName("root"), evt.asStartElement().getName()); - - evt = er.nextEvent(); - assertTrue(evt.isCharacters()); - assertTrue(evt.asCharacters().isWhiteSpace()); - - evt = er.nextEvent(); - assertTrue(evt.isStartElement()); - assertEquals(new QName("branch"), evt.asStartElement().getName()); - - evt = er.nextEvent(); - assertTrue(evt.isCharacters()); - assertTrue(evt.asCharacters().isWhiteSpace()); - - evt = er.nextEvent(); - assertTrue(evt.isStartElement()); - assertEquals(new QName("leaf"), evt.asStartElement().getName()); - evt = er.nextEvent(); - assertTrue(evt.isEndElement()); - assertEquals(new QName("leaf"), evt.asEndElement().getName()); - - evt = er.nextEvent(); - assertTrue(evt.isCharacters()); - assertTrue(evt.asCharacters().isWhiteSpace()); - - evt = er.nextEvent(); - assertTrue(evt.isEndElement()); - assertEquals(new QName("branch"), evt.asEndElement().getName()); - - evt = er.nextEvent(); - assertTrue(evt.isCharacters()); - assertTrue(evt.asCharacters().isWhiteSpace()); - - evt = er.nextEvent(); - assertTrue(evt.isStartElement()); - assertEquals(new QName("leaf"), evt.asStartElement().getName()); - evt = er.nextEvent(); - assertTrue(evt.isEndElement()); - assertEquals(new QName("leaf"), evt.asEndElement().getName()); - - evt = er.nextEvent(); - assertTrue(evt.isEndElement()); - assertEquals(new QName("root"), evt.asEndElement().getName()); - } - - public void testCopyWithCData() - throws XMLStreamException - { - final String XML = - ""; - - XMLEventReader er = getEventReader(XML, true, false); - StringWriter strw = new StringWriter(); - XMLOutputFactory f = getOutputFactory(); - XMLEventWriter ew = f.createXMLEventWriter(strw); - - while (er.hasNext()) { - ew.add(er.nextEvent()); - } - ew.close(); - - // And then test what it looks like - String results = strw.toString(); - er = getEventReader(results, true, false); - XMLEvent evt; - - // Plus that events are the way they ought to be - assertNotNull((evt = er.nextEvent())); - assertTrue(evt.isStartDocument()); - - evt = er.nextEvent(); - assertTrue(evt.isStartElement()); - assertEquals(new QName("root"), evt.asStartElement().getName()); - - evt = er.nextEvent(); - assertTrue(evt.isCharacters()); - assertTrue("Expected CDATA block to generate a Characters event for which isCData() returns true", evt.asCharacters().isCData()); - assertEquals("a&b", evt.asCharacters().getData()); - - evt = er.nextEvent(); - assertTrue(evt.isEndElement()); - assertEquals(new QName("root"), evt.asEndElement().getName()); - - } - - private XMLEventReader getEventReader(String contents, boolean nsAware, boolean coal) - throws XMLStreamException - { - XMLInputFactory f = getInputFactory(); - setNamespaceAware(f, nsAware); - setCoalescing(f, coal); - setSupportDTD(f, true); - setValidating(f, false); - return constructEventReader(f, contents); - } -} diff -Nru libwoodstox-java-4.1.3/src/test/org/codehaus/stax/test/evt/TestEventDTD.java libwoodstox-java-5.1.0/src/test/org/codehaus/stax/test/evt/TestEventDTD.java --- libwoodstox-java-4.1.3/src/test/org/codehaus/stax/test/evt/TestEventDTD.java 2012-04-24 04:38:21.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/org/codehaus/stax/test/evt/TestEventDTD.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,187 +0,0 @@ -package org.codehaus.stax.test.evt; - -import java.util.NoSuchElementException; - -import javax.xml.stream.*; -import javax.xml.stream.events.*; - -import java.util.*; - -/** - * Tests for verifying behavior of Event API implementation with events - * that depend on (internal) DTD subset(s). - * - * @author Tatu Saloranta - */ -public class TestEventDTD - extends BaseEventTest -{ - /** - * Test that checks that entity objects are properly returned in - * non-expanding mode. - */ - public void testNonExpandingEntities() - throws XMLStreamException - { - // Let's test all entity types - final String URL1 = "nosuchdir/dummyent.xml"; - String XML = "" - +"\n" - +"\n" - +"\n" - // Hmmh: can't test this, but let's declare it anyway - +"\n" - +"]>" - //+"&intEnt;&extParsedEnt;&extUnparsedEnt;" - +"&intEnt;&extParsedEnt;" - ; - - for (int i = 0; i < 2; ++i) { - boolean ns = (i & 1) != 0; - /* 08-Sep-2007, TSa: Alas, not all impls (like sjsxp) support - * combination of non-expanding and coalescing; thus, - * can only test non-coalescing mode here. - */ - //boolean coal = (i & 2) != 0; - boolean coal = false; - // false -> do not expand entities - XMLEventReader er = getReader(XML, ns, coal, false); - - assertTokenType(START_DOCUMENT, er.nextEvent().getEventType()); - assertTokenType(DTD, er.nextEvent().getEventType()); - XMLEvent evt = er.nextEvent(); - assertTrue(evt.isStartElement()); - - evt = er.nextEvent(); - assertTokenType(ENTITY_REFERENCE, evt.getEventType()); - EntityReference ref = (EntityReference) evt; - assertNotNull(ref); - assertTrue(ref.isEntityReference()); - assertEquals("intEnt", ref.getName()); - EntityDeclaration ed = ref.getDeclaration(); - assertNotNull("Declaration of internal entity 'intEnt' should not be null", ed); - assertEquals("intEnt", ed.getName()); - assertEquals("internal", ed.getReplacementText()); - assertNullOrEmpty(ed.getNotationName()); - assertNullOrEmpty(ed.getPublicId()); - assertNullOrEmpty(ed.getSystemId()); - - evt = er.nextEvent(); - assertTokenType(ENTITY_REFERENCE, evt.getEventType()); - ref = (EntityReference) evt; - assertNotNull(ref); - assertTrue(ref.isEntityReference()); - assertEquals("extParsedEnt", ref.getName()); - ed = ref.getDeclaration(); - assertNotNull("Declaration of external entity 'extParsedEnt' should not be null", ed); - assertEquals("extParsedEnt", ed.getName()); - assertNullOrEmpty(ed.getNotationName()); - assertNullOrEmpty(ed.getPublicId()); - assertEquals(URL1, ed.getSystemId()); - - /* - evt = er.nextEvent(); - assertTokenType(ENTITY_REFERENCE, evt.getEventType()); - ref = (EntityReference) evt; - assertEquals("extUnparsedEnt", ref.getName()); - assertNotNull(ref); - assertTrue(ref.isEntityReference()); - ed = ref.getDeclaration(); - assertNotNull(ed); - assertEquals("notation", ed.getNotationName()); - */ - - evt = er.nextEvent(); - assertTrue(evt.isEndElement()); - assertTokenType(END_DOCUMENT, er.nextEvent().getEventType()); - assertFalse(er.hasNext()); - } - } - - /** - * This unit test checks that a DTD event that results from parsing - * a valid document, to the degree it is done without having to - * validate anything - */ - public void testValidDtdEvent() - throws XMLStreamException - { - String XML = "" - +"\n" - +"\n" - +"\n" - +"\n" - +"\n" - +"]>" - +"" - ; - for (int i = 0; i < 4; ++i) { - boolean ns = (i & 1) != 0; - boolean coal = (i & 2) != 0; - XMLEventReader er = getReader(XML, ns, coal); - - assertTokenType(START_DOCUMENT, er.nextEvent().getEventType()); - XMLEvent evt = er.nextEvent(); - assertTokenType(DTD, evt.getEventType()); - DTD dtd = (DTD) evt; - /* isXxx() methods and writability are tested by a different - * unit test (in TestEventTypes()); here let's just check for - * entities and notations - */ - List entities = dtd.getEntities(); - assertNotNull("Entity list for a DTD declaration with entities should not be null", entities); - assertEquals(3, entities.size()); - - // Let's also verify they are all of right type... - testListElems(entities, EntityDeclaration.class); - - List notations = dtd.getNotations(); - - // Let's also verify they are all of right type... - testListElems(notations, NotationDeclaration.class); - - assertNotNull("Notation list for a DTD declaration with notations should not be null", entities); - assertNotNull(notations); - assertEquals(2, notations.size()); - } - } - - /* - ///////////////////////////////////////////////// - // Internal methods: - ///////////////////////////////////////////////// - */ - - private XMLEventReader getReader(String contents, boolean nsAware, - boolean coalesce) - throws XMLStreamException - { - return getReader(contents, nsAware, coalesce, true); - } - - private XMLEventReader getReader(String contents, boolean nsAware, - boolean coalesce, boolean expandEnt) - throws XMLStreamException - { - //XMLInputFactory f = getInputFactory(); - XMLInputFactory f = getNewInputFactory(); - setNamespaceAware(f, nsAware); - setCoalescing(f, coalesce); - setSupportDTD(f, true); - setValidating(f, false); - setReplaceEntities(f, expandEnt); - return constructEventReader(f, contents); - } - - private void testListElems(List l, Class expType) - { - Iterator it = l.iterator(); - while (it.hasNext()) { - Object o = it.next(); - assertNotNull(o); - assertTrue(expType.isAssignableFrom(o.getClass())); - } - } -} diff -Nru libwoodstox-java-4.1.3/src/test/org/codehaus/stax/test/evt/TestEventFactory.java libwoodstox-java-5.1.0/src/test/org/codehaus/stax/test/evt/TestEventFactory.java --- libwoodstox-java-4.1.3/src/test/org/codehaus/stax/test/evt/TestEventFactory.java 2012-04-24 04:38:21.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/org/codehaus/stax/test/evt/TestEventFactory.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,349 +0,0 @@ -package org.codehaus.stax.test.evt; - -import java.io.StringWriter; -import java.util.*; - -import javax.xml.namespace.QName; -import javax.xml.stream.*; -import javax.xml.stream.events.*; - -/** - * Class that contains simple tests for making sure that event objets - * created by the {@link XMLEventFactory} have expected properties. - * - * @author Tatu Saloranta - */ -public class TestEventFactory - extends BaseEventTest -{ - public void testAttribute() - throws XMLStreamException - { - XMLEventFactory f = getEventFactory(); - final String URI = "http://foo.com"; - - QName attrName = new QName(URI, "attr", "ns"); - Attribute attr = f.createAttribute(attrName, "value"); - - checkEventIsMethods(ATTRIBUTE, attr); - testEventWritability(attr); - - Attribute attr2 = f.createAttribute("ns", URI, "attr", "value'2'"); - Attribute attr3 = f.createAttribute("attr", "this&more"); - - /* No way to associate with a DTD, should have fairly basic - * settings: - */ - assertEquals("CDATA", attr.getDTDType()); - assertEquals("CDATA", attr2.getDTDType()); - assertEquals("CDATA", attr3.getDTDType()); - - /* 26-Jan-2008, TSa: Hmmh. Should these be constructed as - * defined/specified or not? - */ - if (!attr.isSpecified()) { - /* - assertTrue("Attribute 'ns:attr' should be created as 'defined'", - attr.isSpecified()); - assertTrue("Attribute 'ns:attr' should be created as 'defined'", - attr2.isSpecified()); - assertTrue("Attribute 'attr' should be created as 'defined'", - attr3.isSpecified()); - */ - warn("Attribute.isSpecified() returns false for XMLEventFactory generated Attribute events -- does that make sense?"); - } - assertEquals("value", attr.getValue()); - assertEquals("value'2'", attr2.getValue()); - assertEquals("this&more", attr3.getValue()); - - // Ok, then names... - assertEquals(attrName, attr.getName()); - assertEquals(attrName, attr2.getName()); - - QName name3 = attr3.getName(); - /* Alas, QName doesn't seem to retain nulls... so let's - * be bit more lenient here: - */ - assertEquals("attr", name3.getLocalPart()); - String str = name3.getPrefix(); - assertTrue(str == null || str.length() == 0); - str = name3.getNamespaceURI(); - assertTrue(str == null || str.length() == 0); - } - - public void testCData() - throws XMLStreamException - { - final String contents = "test text & more! [[]] --"; - XMLEventFactory f = getEventFactory(); - Characters c = f.createCData(contents); - checkEventIsMethods(CHARACTERS, c); - testEventWritability(c); - - assertEquals(contents, c.getData()); - assertTrue(c.isCData()); - assertFalse(c.isIgnorableWhiteSpace()); - assertFalse(c.isWhiteSpace()); - } - - public void testCharacters() - throws XMLStreamException - { - final String contents = "test text & more! [[]] --"; - XMLEventFactory f = getEventFactory(); - Characters c = f.createCharacters(contents); - - checkEventIsMethods(CHARACTERS, c); - testEventWritability(c); - - assertEquals(contents, c.getData()); - assertFalse(c.isCData()); - assertFalse(c.isIgnorableWhiteSpace()); - assertFalse(c.isWhiteSpace()); - } - - public void testComment() - throws XMLStreamException - { - final String content = "Comment - how interesting!"; - - XMLEventFactory f = getEventFactory(); - Comment c = f.createComment(content); - - checkEventIsMethods(COMMENT, c); - testEventWritability(c); - - assertEquals(content, c.getText()); - } - - public void testDTD() - throws XMLStreamException - { - XMLEventFactory f = getEventFactory(); - DTD d = f.createDTD(""); - - checkEventIsMethods(DTD, d); - testEventWritability(d); - - // !!! TBI - } - - public void testEndDocument() - throws XMLStreamException - { - XMLEventFactory f = getEventFactory(); - EndDocument ed = f.createEndDocument(); - - // No properties -- as long as we got instance of right type, it's ok - checkEventIsMethods(END_DOCUMENT, ed); - testEventWritability(ed); - } - - public void testEndElement() - throws XMLStreamException - { - XMLEventFactory f = getEventFactory(); - final String LOCALNAME = "elem"; - - // prefix, uri, localName - EndElement ee = f.createEndElement("", "", LOCALNAME); - checkEventIsMethods(END_ELEMENT, ee); - testEventWritability(ee); - - QName n = ee.getName(); - assertNotNull(n); - assertEquals(LOCALNAME, n.getLocalPart()); - } - - public void testEntityReference() - throws XMLStreamException - { - XMLEventFactory f = getEventFactory(); - - /* 22-Dec-2005, TSa: ... but how can we create the entity declaration - * that is needed? Should null be ok? For now, can't really test... - */ - //EntityReference ref = f.createEntityReference("ref", decl); - //checkEventIsMethods(ENTITY_REFERENCE, ref); - //testEventWritability(ref); - } - - public void testIgnorableSpace() - throws XMLStreamException - { - final String contents = " \t \n "; - XMLEventFactory f = getEventFactory(); - Characters c = f.createIgnorableSpace(contents); - - checkEventIsMethods(CHARACTERS, c); - testEventWritability(c); - - assertEquals(contents, c.getData()); - assertFalse(c.isCData()); - assertTrue(c.isIgnorableWhiteSpace()); - assertTrue(c.isWhiteSpace()); - } - - public void testNamespace() - throws XMLStreamException - { - XMLEventFactory f = getEventFactory(); - final String PREFIX = "prefix"; - final String URI = "http://foo"; - - // First default: - Namespace ns = f.createNamespace(URI); - - checkEventIsMethods(NAMESPACE, ns); - testEventWritability(ns); - - String prefix = ns.getPrefix(); - // Both null and empty are ok? - if (prefix != null && prefix.length() > 0) { - fail("Expected prefix to be null or empty for default namespace event object"); - } - assertEquals(URI, ns.getNamespaceURI()); - assertTrue(ns.isDefaultNamespaceDeclaration()); - - // Then non-default: - ns = f.createNamespace(PREFIX, URI); - checkEventIsMethods(NAMESPACE, ns); - assertEquals(PREFIX, ns.getPrefix()); - assertEquals(URI, ns.getNamespaceURI()); - assertFalse(ns.isDefaultNamespaceDeclaration()); - } - - public void testProcInstr() - throws XMLStreamException - { - XMLEventFactory f = getEventFactory(); - ProcessingInstruction pi = f.createProcessingInstruction("target", "data"); - checkEventIsMethods(PROCESSING_INSTRUCTION, pi); - testEventWritability(pi); - - assertEquals("target", pi.getTarget()); - assertEquals("data", pi.getData()); - - } - - public void testSpace() - throws XMLStreamException - { - final String contents = " \t \n "; - XMLEventFactory f = getEventFactory(); - Characters c = f.createSpace(contents); - assertEquals(contents, c.getData()); - - checkEventIsMethods(CHARACTERS, c); - testEventWritability(c); - - assertFalse(c.isCData()); - assertFalse(c.isIgnorableWhiteSpace()); - assertTrue(c.isWhiteSpace()); - } - - public void testStartDocument() - throws XMLStreamException - { - XMLEventFactory f = getEventFactory(); - StartDocument sd = f.createStartDocument(); - checkEventIsMethods(START_DOCUMENT, sd); - testEventWritability(sd); - - assertFalse(sd.encodingSet()); - assertFalse(sd.standaloneSet()); - - final String ENCODING = "ISO-8859-1"; - final String VERSION = "1.0"; - sd = f.createStartDocument(ENCODING, VERSION, true); - checkEventIsMethods(START_DOCUMENT, sd); - assertTrue("Expected StartDocument.encodingSet() to be true when constructing via factory method that passes in non-empty encoding value", sd.encodingSet()); - assertTrue(sd.standaloneSet()); - assertEquals(ENCODING, sd.getCharacterEncodingScheme()); - assertEquals(VERSION, sd.getVersion()); - } - - public void testStartElement() - throws XMLStreamException - { - final String LOCALNAME = "root"; - final String PREFIX = "ns"; - final String URI = "urn:whatever"; - - XMLEventFactory f = getEventFactory(); - // prefix, uri, localname - StartElement se = f.createStartElement("", "", LOCALNAME); - testEventWritability(se); - - checkEventIsMethods(START_ELEMENT, se); - QName n = se.getName(); - assertNotNull(n); - assertEquals(LOCALNAME, n.getLocalPart()); - - se = f.createStartElement(PREFIX, URI, LOCALNAME); - checkEventIsMethods(START_ELEMENT, se); - n = se.getName(); - assertNotNull(n); - assertEquals(LOCALNAME, n.getLocalPart()); - assertEquals(PREFIX, n.getPrefix()); - assertEquals(URI, n.getNamespaceURI()); - } - - public void testStartElementWithAttrs() - throws XMLStreamException - { - final String NS_URI = "http://foo"; - - XMLEventFactory f = getEventFactory(); - ArrayList attrs = new ArrayList(); - Attribute attr1 = f.createAttribute(new QName("attr1"), "value"); - testEventWritability(attr1); - attrs.add(attr1); - checkEventIsMethods(ATTRIBUTE, attr1); - attrs.add(f.createAttribute(new QName(NS_URI, "attr2"), "value2")); - - // Ok, so let's create the start element, and check it's ok: - StartElement se = f.createStartElement(new QName("root"), - attrs.iterator(), null); - testEventWritability(se); - checkEventIsMethods(START_ELEMENT, se); - QName n = se.getName(); - assertNotNull(n); - assertEquals("root", n.getLocalPart()); - - // Then let's check both existing attrs: - Attribute resultAttr = se.getAttributeByName(new QName("attr1")); - assertNotNull(resultAttr); - n = resultAttr.getName(); - assertEquals("attr1", n.getLocalPart()); - assertEquals("value", resultAttr.getValue()); - - resultAttr = se.getAttributeByName(new QName(NS_URI, "attr2")); - assertNotNull(resultAttr); - n = resultAttr.getName(); - assertEquals("attr2", n.getLocalPart()); - assertEquals("value2", resultAttr.getValue()); - - // Then non-existing ones (switch ns URIs around) - assertNull(se.getAttributeByName(new QName(NS_URI, "attr1"))); - assertNull(se.getAttributeByName(new QName("attr2"))); - - // and finally raw count - Iterator it = se.getAttributes(); - assertNotNull(it); - int count = 0; - - while (it.hasNext()) { - Attribute a = (Attribute) it.next(); - ++count; - } - assertEquals(2, count); - } - - /* - //////////////////////////////////////// - // Private methods, tests - //////////////////////////////////////// - */ -} - diff -Nru libwoodstox-java-4.1.3/src/test/org/codehaus/stax/test/evt/TestEventReader.java libwoodstox-java-5.1.0/src/test/org/codehaus/stax/test/evt/TestEventReader.java --- libwoodstox-java-4.1.3/src/test/org/codehaus/stax/test/evt/TestEventReader.java 2012-04-24 04:38:21.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/org/codehaus/stax/test/evt/TestEventReader.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,374 +0,0 @@ -package org.codehaus.stax.test.evt; - -import java.util.NoSuchElementException; - -import javax.xml.stream.*; -import javax.xml.stream.events.*; - -import java.util.*; - -/** - * Class that contains simple tests for making sure that event objects - * created by the {@link XMLEventFactory} have expected properties. - * - * @author Tatu Saloranta - */ -public class TestEventReader - extends BaseEventTest -{ - public void testSimpleValid() - throws XMLStreamException - { - /* Whether prolog/epilog white space is reported is not defined - * by StAX specs, thus, let's not add any - */ - String XML = "" - +"" - +"\n" - +""; - - for (int i = 0; i < 4; ++i) { - boolean ns = (i & 1) != 0; - boolean coal = (i & 2) != 0; - XMLEventReader er = getReader(XML, ns, coal); - - assertTokenType(START_DOCUMENT, er.nextEvent().getEventType()); - assertTokenType(DTD, er.nextEvent().getEventType()); - assertTokenType(START_ELEMENT, er.nextEvent().getEventType()); - assertTokenType(COMMENT, er.nextEvent().getEventType()); - // for fun, let's just use next() instead of nextEvent() - XMLEvent evt = (XMLEvent) er.next(); - assertTokenType(CHARACTERS, evt.getEventType()); - assertTokenType(END_ELEMENT, er.nextEvent().getEventType()); - assertTokenType(END_DOCUMENT, er.nextEvent().getEventType()); - assertFalse(er.hasNext()); - er.close(); - } - } - - public void testInvalidUsage() - throws XMLStreamException - { - String XML = ""; - for (int i = 0; i < 4; ++i) { - boolean ns = (i & 1) != 0; - boolean coal = (i & 2) != 0; - XMLEventReader er = getReader(XML, ns, coal); - - XMLEvent evt = er.nextEvent(); - - // Let's try removal: - String msg = null; - try { - er.remove(); - msg = "Was expecting UnsupportedOperationException for XMLEventReader.remove()"; - } catch (UnsupportedOperationException e) { - ; // good - } catch (Throwable t) { - msg = "Was expecting UnsupportedOperationException for XMLEventReader.remove(); instead got: "+t; - } - if (msg != null) { - fail(msg); - } - } - } - - /** - * The main purpose of this test is to ensure that an exception - * is thrown at the end. - */ - public void testIterationEndException() - throws XMLStreamException - { - String XML = ""; - - for (int i = 0; i < 4; ++i) { - boolean coal = (i & 1) != 0; - boolean checkHasNext = (i & 2) != 0; - XMLEventReader er = getReader(XML, true, coal); - - assertTokenType(START_DOCUMENT, er.nextEvent().getEventType()); - assertTokenType(START_ELEMENT, er.nextEvent().getEventType()); - assertTokenType(END_ELEMENT, er.nextEvent().getEventType()); - assertTokenType(END_DOCUMENT, er.nextEvent().getEventType()); - - if (checkHasNext) { - assertFalse(er.hasNext()); - } - - XMLEvent ev = null; - try { - ev = er.nextEvent(); - } catch (NoSuchElementException nex) { - continue; // good - } catch (Throwable t) { - fail("Expected a NoSuchElementException after iterating through the document; got "+t); - } - - // Shouldn't get this far... - fail("Expected a NoSuchElementException after iterating through the document; got event: "+ev); - } - } - - public void testNextTagOk() - throws XMLStreamException - { - String XML = "\n" - +" " - +""; - - for (int i = 0; i < 4; ++i) { - boolean ns = (i & 1) != 0; - boolean coal = (i & 2) != 0; - XMLEventReader er = getReader(XML, ns, coal); - - assertTokenType(START_DOCUMENT, er.nextEvent().getEventType()); - - assertTokenType(START_ELEMENT, er.nextTag().getEventType()); - assertTokenType(START_ELEMENT, er.nextTag().getEventType()); - /* Ok, let's mix in bit of peeking to ensure reader won't - * be confused too badly... - */ - // This should be space between and ... - assertTokenType(CHARACTERS, er.peek().getEventType()); - - // And then the leaf - assertTokenType(START_ELEMENT, er.nextTag().getEventType()); - - assertTokenType(END_ELEMENT, er.nextTag().getEventType()); - assertTokenType(END_ELEMENT, er.nextTag().getEventType()); - assertTokenType(END_ELEMENT, er.nextTag().getEventType()); - - assertTokenType(END_DOCUMENT, er.nextEvent().getEventType()); - assertFalse(er.hasNext()); - } - } - - public void testNextTagInvalid() - throws XMLStreamException - { - String XML = " non-empty"; - String XML2 = "text "; - - for (int i = 0; i < 4; ++i) { - boolean ns = (i & 1) != 0; - boolean coal = (i & 2) != 0; - XMLEventReader er = getReader(XML, ns, coal); - assertTokenType(START_DOCUMENT, er.nextEvent().getEventType()); - assertTokenType(START_ELEMENT, er.nextEvent().getEventType()); - String msg = null; - try { - XMLEvent evt = er.nextTag(); - msg = "Expected a XMLStreamException when trying to call XMLEventReader.nextTag() on non-empty CHARACTERS"; - } catch (XMLStreamException sex) { - // fine! - } catch (Throwable t) { - msg = "Expected a XMLStreamException when trying to call XMLEventReader.nextTag() on non-empty CHARACTERS; got ("+t.getClass()+"): "+t; - } - if (msg != null) { - fail(msg); - } - er.close(); - - /* any other easily failing cases? Maybe if we are on top of - * END_ELEMENT, and will hit another one? - */ - er = getReader(XML2, ns, coal); - assertTokenType(START_DOCUMENT, er.nextEvent().getEventType()); - assertTokenType(START_ELEMENT, er.nextEvent().getEventType()); - assertTokenType(START_ELEMENT, er.nextEvent().getEventType()); - assertTokenType(END_ELEMENT, er.nextEvent().getEventType()); - - try { - XMLEvent evt = er.nextTag(); - msg = "Expected a XMLStreamException when trying to call XMLEventReader.nextTag() on END_ELEMENT and hitting non-ws text; got event "+tokenTypeDesc(evt); - } catch (XMLStreamException sex) { - msg = null; // fine! - } catch (Throwable t) { - msg = "Expected a XMLStreamException when trying to call XMLEventReader.nextTag() on END_ELEMENT and hitting non-ws text; got: "+t; - } - if (msg != null) { - fail(msg); - } - er.close(); - } - } - - public void testSkip() - throws XMLStreamException - { - String XML = "\n" - +" " - +""; - - for (int i = 0; i < 4; ++i) { - boolean ns = (i & 1) != 0; - boolean coal = (i & 2) != 0; - XMLEventReader er = getReader(XML, ns, coal); - XMLEvent ev; - - assertTokenType(START_DOCUMENT, er.peek().getEventType()); - assertTokenType(START_DOCUMENT, er.nextEvent().getEventType()); - assertTokenType(DTD, er.peek().getEventType()); - assertTokenType(DTD, er.nextEvent().getEventType()); - assertTokenType(START_ELEMENT, er.peek().getEventType()); - assertTokenType(START_ELEMENT, er.nextEvent().getEventType()); - - assertTokenType(CHARACTERS, er.peek().getEventType()); - assertTokenType(CHARACTERS, er.nextEvent().getEventType()); - - // branch - assertTokenType(START_ELEMENT, er.peek().getEventType()); - assertTokenType(START_ELEMENT, er.nextEvent().getEventType()); - assertTokenType(CHARACTERS, er.peek().getEventType()); - assertTokenType(CHARACTERS, er.nextEvent().getEventType()); - - // leaf - assertTokenType(START_ELEMENT, er.peek().getEventType()); - assertTokenType(START_ELEMENT, er.nextEvent().getEventType()); - assertTokenType(CHARACTERS, er.peek().getEventType()); - assertTokenType(CHARACTERS, er.nextEvent().getEventType()); - assertTokenType(END_ELEMENT, er.peek().getEventType()); - assertTokenType(END_ELEMENT, er.nextEvent().getEventType()); - - assertTokenType(END_ELEMENT, er.peek().getEventType()); - assertTokenType(END_ELEMENT, er.nextEvent().getEventType()); - - assertTokenType(COMMENT, er.peek().getEventType()); - assertTokenType(COMMENT, er.nextEvent().getEventType()); - assertTokenType(END_ELEMENT, er.peek().getEventType()); - assertTokenType(END_ELEMENT, er.nextEvent().getEventType()); - - assertTokenType(END_DOCUMENT, er.peek().getEventType()); - assertTokenType(END_DOCUMENT, er.nextEvent().getEventType()); - assertFalse(er.hasNext()); - } - } - - /** - * This test was inspired by an actual bug in one of implementations: - * initial state was not properly set if nextTag() was called (instead - * of nextEvent()), and subsequent peek() failed. - */ - public void testPeek() - throws XMLStreamException - { - String XML = "text"; - - for (int i = 0; i < 4; ++i) { - boolean ns = (i & 1) != 0; - boolean coal = (i & 2) != 0; - XMLEventReader er = getReader(XML, ns, coal); - assertTokenType(START_DOCUMENT, er.nextEvent().getEventType()); - - XMLEvent tag = er.nextTag(); - assertTokenType(START_ELEMENT, tag.getEventType()); - - // Now, peek() should produce text.. - XMLEvent text = er.peek(); - assertTokenType(CHARACTERS, text.getEventType()); - Characters chars = text.asCharacters(); - assertNotNull(chars); - assertEquals("text", chars.getData()); - - // and need nextEvent() to get rid of it, too: - text = er.nextEvent(); - // Let's verify it again: - assertTokenType(CHARACTERS, text.getEventType()); - chars = text.asCharacters(); - assertNotNull(chars); - assertEquals("text", chars.getData()); - assertTokenType(END_ELEMENT, er.nextTag().getEventType()); - assertTokenType(END_DOCUMENT, er.nextEvent().getEventType()); - - // And at the end, peek() should return null - assertNull(er.peek()); - } - } - - public void testElementText() - throws XMLStreamException - { - String TEXT1 = "some\ntest"; - String TEXT2 = "inside CDATA too!"; - - String XML = ""+TEXT1+""; - - // First, let's see how things work without peeking: - for (int i = 0; i < 4; ++i) { - boolean ns = (i & 1) != 0; - boolean coal = (i & 2) != 0; - XMLEventReader er = getReader(XML, ns, coal); - assertTokenType(START_DOCUMENT, er.nextEvent().getEventType()); - XMLEvent elem = er.nextEvent(); - assertTokenType(START_ELEMENT, elem.getEventType()); - - try { - assertEquals(TEXT1+TEXT2, er.getElementText()); - } catch (XMLStreamException sex) { - fail("Failed on XMLEventReader.getElementText(): "+sex); - } - - /* 06-Jan-2006, TSa: I'm really not sure whether to expect - * END_ELEMENT, or END_DOCUMENT here... maybe the latter - * makes more sense? For now let's accept both, however. - */ - elem = er.nextEvent(); - if (elem.getEventType() != END_DOCUMENT - && elem.getEventType() != END_ELEMENT) { - fail("Expected END_DOCUMENT or END_ELEMENT, got "+tokenTypeDesc(elem.getEventType())); - } - } - - // and then with peeking: - for (int i = 0; i < 4; ++i) { - boolean ns = (i & 1) != 0; - boolean coal = (i & 2) != 0; - XMLEventReader er = getReader(XML, ns, coal); - assertTokenType(START_DOCUMENT, er.nextEvent().getEventType()); - XMLEvent elem = er.nextEvent(); - assertTokenType(START_ELEMENT, elem.getEventType()); - XMLEvent peeked = er.peek(); - assertTokenType(CHARACTERS, peeked.getEventType()); - assertEquals(TEXT1+TEXT2, er.getElementText()); - - /* 06-Jan-2006, TSa: I'm really not sure whether to expect - * END_ELEMENT, or END_DOCUMENT here... maybe the latter - * makes more sense? For now let's accept both, however. - */ - elem = er.nextEvent(); - - if (elem.getEventType() != END_DOCUMENT - && elem.getEventType() != END_ELEMENT) { - fail("Expected END_DOCUMENT or END_ELEMENT, got "+tokenTypeDesc(elem.getEventType())); - } - } - } - - /* - ///////////////////////////////////////////////// - // Internal methods: - ///////////////////////////////////////////////// - */ - - private XMLEventReader getReader(String contents, boolean nsAware, - boolean coalesce) - throws XMLStreamException - { - return getReader(contents, nsAware, coalesce, true); - } - - private XMLEventReader getReader(String contents, boolean nsAware, - boolean coalesce, boolean expandEnt) - throws XMLStreamException - { - //XMLInputFactory f = getInputFactory(); - XMLInputFactory f = getNewInputFactory(); - setNamespaceAware(f, nsAware); - setCoalescing(f, coalesce); - setSupportDTD(f, true); - setValidating(f, false); - setReplaceEntities(f, expandEnt); - return constructEventReader(f, contents); - } -} diff -Nru libwoodstox-java-4.1.3/src/test/org/codehaus/stax/test/evt/TestEventTypes.java libwoodstox-java-5.1.0/src/test/org/codehaus/stax/test/evt/TestEventTypes.java --- libwoodstox-java-4.1.3/src/test/org/codehaus/stax/test/evt/TestEventTypes.java 2012-04-24 04:38:21.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/org/codehaus/stax/test/evt/TestEventTypes.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,171 +0,0 @@ -package org.codehaus.stax.test.evt; - -import javax.xml.namespace.QName; -import javax.xml.stream.*; -import javax.xml.stream.events.*; - -/** - * Class that contains simple tests for making sure that event types - * produced have expected settings. - * - * @author Tatu Saloranta - */ -public class TestEventTypes - extends BaseEventTest -{ - public void testTypes() - throws XMLStreamException - { - doTestTypes(false); // non-namespace - doTestTypes(true); // namespace-aware - } - - /* - //////////////////////////////////////// - // Private methods, tests - //////////////////////////////////////// - */ - - private void doTestTypes(boolean useNs) - throws XMLStreamException - { - String INPUT = - "" - +"" - +"" - +"" - +"some text" - +""; - - XMLEventReader er = getReader(INPUT, useNs); - - // First, should get START_DOCUMENT: - XMLEvent evt = er.nextEvent(); - assertEquals(START_DOCUMENT, evt.getEventType()); - assertTrue(evt.isStartDocument()); - { - StartDocument doc = (StartDocument) evt; - assertFalse(doc.encodingSet()); - /* Not sure how to test getCharacterEncodingScheme(); problem - * is, XML parser are allowed to auto-detect things... but don't - * have to. - */ - // ... same is true about system id too - - if (doc.standaloneSet()) { - fail("Reporting stand-alone as set, even though xml declaration has no value (should assume 'false')"); - } - - // I guess parser should NOT think it is stand-alone without decl? - assertFalse("Should assume 'no' as stand-alone value if no extra information", doc.isStandalone()); - } - - // Then, proc. instr: - evt = er.nextEvent(); - assertEquals(PROCESSING_INSTRUCTION, evt.getEventType()); - assertTrue(evt.isProcessingInstruction()); - { - ProcessingInstruction pi = (ProcessingInstruction) evt; - assertEquals("proc", pi.getTarget()); - // data may or may not contain the space between target and data... - String data = pi.getData().trim(); - assertEquals("instr", data); - } - - // Then COMMENT - evt = er.nextEvent(); - assertEquals(COMMENT, evt.getEventType()); - { - Comment c = (Comment) evt; - assertEquals("comment - - contents", c.getText()); - } - - // Then DTD - evt = er.nextEvent(); - assertEquals(DTD, evt.getEventType()); - { - DTD dtd = (DTD) evt; - checkEventIsMethods(DTD, dtd); - testEventWritability(dtd); - assertNotNull(dtd.getDocumentTypeDeclaration()); - } - - // Then START_ELEMENT - evt = er.nextEvent(); - assertEquals(START_ELEMENT, evt.getEventType()); - assertTrue(evt.isStartElement()); - QName elemName; - - { - StartElement elem = evt.asStartElement(); - elemName = elem.getName(); - assertEquals("root", elemName.getLocalPart()); - - assertEquals(1, calcAttrCount(elem)); - - Attribute noSuchAttr = elem.getAttributeByName(new QName("foobar")); - assertNull("Should not have found attribute 'foobar' from the element", noSuchAttr); - - Attribute attr = elem.getAttributeByName(new QName("attr")); - assertNotNull("Should have found attribute 'attr' from the element", attr); - assertTrue(attr.isAttribute()); - assertEquals("value", attr.getValue()); - assertEquals("CDATA", attr.getDTDType()); - assertTrue(attr.isSpecified()); - QName an = attr.getName(); - assertEquals("attr", an.getLocalPart()); - } - - // Then CHARACTERS - evt = er.nextEvent(); - assertEquals(CHARACTERS, evt.getEventType()); - assertTrue(evt.isCharacters()); - { - Characters ch = evt.asCharacters(); - assertFalse(ch.isCData()); - assertFalse(ch.isIgnorableWhiteSpace()); - assertFalse(ch.isWhiteSpace()); - assertEquals("some text", ch.getData()); - } - - // Then END_ELEMENT - evt = er.nextEvent(); - assertEquals(END_ELEMENT, evt.getEventType()); - assertTrue(evt.isEndElement()); - { - EndElement elem = evt.asEndElement(); - QName endName = elem.getName(); - assertEquals("root", endName.getLocalPart()); - // Let's also verify it's equal to the start element name... - assertEquals(elemName, endName); - } - - // And finally END_DOCUMENT - evt = er.nextEvent(); - assertEquals(END_DOCUMENT, evt.getEventType()); - assertTrue(evt.isEndDocument()); - // Nothing to test, but let's case to ensure it's of right type - { - EndDocument doc = (EndDocument) evt; - } - } - - /* - //////////////////////////////////////// - // Private methods, other - //////////////////////////////////////// - */ - - private XMLEventReader getReader(String contents, boolean nsAware) - throws XMLStreamException - { - XMLInputFactory f = getInputFactory(); - setCoalescing(f, true); - setNamespaceAware(f, nsAware); - setValidating(f, false); - setSupportDTD(f, true); - return constructEventReader(f, contents); - } - -} - diff -Nru libwoodstox-java-4.1.3/src/test/org/codehaus/stax/test/evt/TestEventWriter.java libwoodstox-java-5.1.0/src/test/org/codehaus/stax/test/evt/TestEventWriter.java --- libwoodstox-java-4.1.3/src/test/org/codehaus/stax/test/evt/TestEventWriter.java 2012-04-24 04:38:21.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/org/codehaus/stax/test/evt/TestEventWriter.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,188 +0,0 @@ -package org.codehaus.stax.test.evt; - -import java.io.StringWriter; -import java.util.*; - -import javax.xml.stream.*; -import javax.xml.stream.events.*; - -/** - * Class that contains simple tests for making sure that event objects - * get serialized properly when using {@link XMLEventWriter}. - * - * @author Tatu Saloranta - */ -public class TestEventWriter - extends BaseEventTest -{ - public void testNonRepairingNsWrite() - throws XMLStreamException - { - XMLOutputFactory f = getOutputFactory(); - StringWriter strw = new StringWriter(); - XMLEventWriter w = f.createXMLEventWriter(strw); - - XMLEventFactory evtf = getEventFactory(); - - ArrayList attrs = new ArrayList(); - attrs.add(evtf.createAttribute("attr", "value")); - attrs.add(evtf.createAttribute("ns", "uri", "attr2", "value2")); - ArrayList ns = new ArrayList(); - ns.add(evtf.createNamespace("ns", "uri")); - StartElement elem = evtf.createStartElement("", "", "root", - attrs.iterator(), - ns.iterator()); - - w.add(elem); - w.add(evtf.createEndElement("", "", "root")); - w.close(); - - // Ok, let's read it back: - String contents = strw.toString(); - - XMLStreamReader sr = getReader(contents, true, true); - - assertTokenType(START_DOCUMENT, sr.getEventType()); - assertTokenType(START_ELEMENT, sr.next()); - - assertEquals("root", sr.getLocalName()); - assertEquals(2, sr.getAttributeCount()); - - // Ordering of attrs is not guaranteed... - String ln = sr.getAttributeLocalName(0); - if (ln.equals("attr")) { - assertEquals("attr2", sr.getAttributeLocalName(1)); - assertEquals("ns", sr.getAttributePrefix(1)); - assertEquals("uri", sr.getAttributeNamespace(1)); - } else if (ln.equals("attr2")) { - assertEquals("attr", sr.getAttributeLocalName(1)); - assertEquals("ns", sr.getAttributePrefix(0)); - assertEquals("uri", sr.getAttributeNamespace(0)); - } else { - fail("Unexpected attr local name '"+ln+"' for attribute #0; expected 'attr' or 'attr2'"); - } - - assertTokenType(END_ELEMENT, sr.next()); - } - - /** - * The idea of this test is to basically verify that given a simplish - * input document, we can parse, output and re-parse it; and second - * time around still get the same events (at least by type, and maybe - * doing some simple sanity checks). - */ - public void testPassThrough() - throws XMLStreamException - { - final String INPUT = - "" - +"\n" - +"\n" - +" \n" - +" \n" - +" \n" - +" ]]>\n" - +" \n" - +" " - +""; - ; - XMLEventReader er = getEventReader(INPUT, true, true); - List list1 = collectEvents(er); - - StringWriter strw = new StringWriter(); - XMLOutputFactory f = getOutputFactory(); - XMLEventWriter ew = f.createXMLEventWriter(strw); - Iterator it = list1.iterator(); - while (it.hasNext()) { - ew.add((XMLEvent) it.next()); - } - - // And re-parse... - er = getEventReader(INPUT, true, true); - List list2 = collectEvents(er); - - assertEquals("Should have gotten same number of events", - list1.size(), list2.size()); - - // And finally, let's at least compare types we have: - it = list1.iterator(); - Iterator it2 = list2.iterator(); - - for (int ix = 0; it.hasNext(); ++ix) { - XMLEvent evt1 = (XMLEvent) it.next(); - XMLEvent evt2 = (XMLEvent) it2.next(); - - if (evt1.getEventType() != evt2.getEventType()) { - fail("Event #"+ix+"; first time got event "+evt1.getEventType() - +", second time "+evt2.getEventType()); - } - - if (evt1.isStartElement()) { - /* ok, should have same attrs and ns decls. For now, let's - * just verify raw counts; can/should test contents too - * in future. - */ - StartElement se1 = evt1.asStartElement(); - StartElement se2 = evt2.asStartElement(); - List attrs1 = fetchElems(se1.getAttributes()); - List attrs2 = fetchElems(se2.getAttributes()); - assertEquals(attrs1.size(), attrs2.size()); - - List ns1 = fetchElems(se1.getNamespaces()); - List ns2 = fetchElems(se2.getNamespaces()); - assertEquals(ns1.size(), ns2.size()); - } - } - } - - private List fetchElems(Iterator it) - { - ArrayList l = new ArrayList(); - while (it.hasNext()) { - l.add(it.next()); - } - return l; - } - - /* - //////////////////////////////////////// - // Private methods, other - //////////////////////////////////////// - */ - - private XMLStreamReader getReader(String contents, boolean nsAware, - boolean coalesce) - throws XMLStreamException - { - XMLInputFactory f = getInputFactory(); - setNamespaceAware(f, nsAware); - setCoalescing(f, coalesce); - setSupportDTD(f, true); - setValidating(f, false); - return constructStreamReader(f, contents); - } - - private XMLEventReader getEventReader(String contents, boolean nsAware, - boolean coalesce) - throws XMLStreamException - { - XMLInputFactory f = getInputFactory(); - setNamespaceAware(f, nsAware); - setCoalescing(f, coalesce); - setSupportDTD(f, true); - setValidating(f, false); - XMLStreamReader sr = constructStreamReader(f, contents); - return f.createXMLEventReader(sr); - } - - private List collectEvents(XMLEventReader er) - throws XMLStreamException - { - ArrayList events = new ArrayList(); - while (er.hasNext()) { - events.add(er.nextEvent()); - } - return events; - } -} diff -Nru libwoodstox-java-4.1.3/src/test/org/codehaus/stax/test/evt/TestFilteredReader.java libwoodstox-java-5.1.0/src/test/org/codehaus/stax/test/evt/TestFilteredReader.java --- libwoodstox-java-4.1.3/src/test/org/codehaus/stax/test/evt/TestFilteredReader.java 2012-04-24 04:38:21.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/org/codehaus/stax/test/evt/TestFilteredReader.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,62 +0,0 @@ -package org.codehaus.stax.test.evt; - -import javax.xml.stream.*; -import javax.xml.stream.events.*; - -/** - * Simple unit test suite that tries to if filtered stream readers are - * constructed and can be used. - *

- * One thing to note, though, is that the StAX specs do not tell much - * anything about expected ways that the implementation is to deal with - * problems resulting from filtering END_DOCUMENT event and so forth. - * - * @author Tatu Saloranta - */ -public class TestFilteredReader - extends BaseEventTest -{ - /** - * Simplest possible test: let's only check that we can actually - * construct an instance with dummy filter that accepts everything, - * and that we can traverse through all the events as usual. - */ - public void testCreation() - throws XMLStreamException - { - XMLEventReader er = createFilteredReader(new MyFilter(), "text", true); - - assertTokenType(START_DOCUMENT, er.nextEvent().getEventType()); - XMLEvent evt = er.nextEvent(); - assertTokenType(START_ELEMENT, evt.getEventType()); - assertNotNull(evt.asStartElement().getName()); - assertTokenType(CHARACTERS, er.nextEvent().getEventType()); - assertTokenType(END_ELEMENT, er.nextEvent().getEventType()); - assertTokenType(END_DOCUMENT, er.nextEvent().getEventType()); - } - - /* - //////////////////////////////////////// - // Non-test methods - //////////////////////////////////////// - */ - - private XMLEventReader createFilteredReader(EventFilter filter, String content, - boolean nsAware) - throws XMLStreamException - { - XMLInputFactory f = getInputFactory(); - setNamespaceAware(f, nsAware); - XMLEventReader base = constructEventReader(f, content); - return f.createFilteredReader(base, filter); - } - - final static class MyFilter - implements EventFilter - { - public boolean accept(XMLEvent event) { - return true; - } - } -} - diff -Nru libwoodstox-java-4.1.3/src/test/org/codehaus/stax/test/evt/TestStartDocument.java libwoodstox-java-5.1.0/src/test/org/codehaus/stax/test/evt/TestStartDocument.java --- libwoodstox-java-4.1.3/src/test/org/codehaus/stax/test/evt/TestStartDocument.java 2012-04-24 04:38:21.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/org/codehaus/stax/test/evt/TestStartDocument.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,179 +0,0 @@ -package org.codehaus.stax.test.evt; - -import java.util.NoSuchElementException; - -import javax.xml.namespace.QName; -import javax.xml.stream.*; -import javax.xml.stream.events.*; - -import java.util.*; - -/** - * Class that tests basic dealing of the StartDocument event (skipping, - * accessing) - * - * @author Tatu Saloranta - */ -public class TestStartDocument - extends BaseEventTest -{ - /** - * First, let's see what happens when there's no decl - */ - public void testTrivialValid() - throws XMLStreamException - { - String XML = ""; - for (int i = 0; i < 4; ++i) { - boolean ns = (i & 1) != 0; - boolean coal = (i & 2) != 0; - XMLEventReader er = getReader(XML, ns, coal); - - // First, explicit access without peek - XMLEvent evt = er.nextEvent(); - assertTrue(evt.isStartDocument()); - StartDocument devt = (StartDocument) evt; - assertFalse(devt.encodingSet()); - assertFalse("Stand-alone should not be assumed true if not included in xml declaration", devt.standaloneSet()); - // Version is to default to "1.0", as per stax 1.0 javadocs - assertEquals("1.0", devt.getVersion()); - er.close(); - } - - // And then let's check with peeking: - for (int i = 0; i < 4; ++i) { - boolean ns = (i & 1) != 0; - boolean coal = (i & 2) != 0; - XMLEventReader er = getReader(XML, ns, coal); - XMLEvent evt = er.peek(); - assertTrue(evt.isStartDocument()); - StartDocument devt = (StartDocument) evt; - assertFalse(devt.encodingSet()); - assertFalse(devt.standaloneSet()); - // Version is to default to "1.0", as per stax 1.0 javadocs - assertEquals("1.0", devt.getVersion()); - er.close(); - - // And then let's see that we can still access it normally too - evt = er.peek(); - assertTrue(evt.isStartDocument()); - // and cast just for fun (to check it really is startdoc event) - devt = (StartDocument) evt; - } - } - - public void testNormalValid() - throws XMLStreamException - { - String XML = "" - +""; - for (int i = 0; i < 4; ++i) { - boolean ns = (i & 1) != 0; - boolean coal = (i & 2) != 0; - XMLEventReader er = getReader(XML, ns, coal); - - // First, explicit access without peek - XMLEvent evt = er.nextEvent(); - assertTrue(evt.isStartDocument()); - StartDocument devt = (StartDocument) evt; - assertEquals("1.0", devt.getVersion()); - assertTrue(devt.encodingSet()); - assertEquals("UTF-8", devt.getCharacterEncodingScheme()); - assertTrue(devt.standaloneSet()); - assertTrue(devt.isStandalone()); - er.close(); - } - - // And then let's check with peeking: - for (int i = 0; i < 4; ++i) { - boolean ns = (i & 1) != 0; - boolean coal = (i & 2) != 0; - XMLEventReader er = getReader(XML, ns, coal); - - XMLEvent evt = er.peek(); - assertTrue(evt.isStartDocument()); - StartDocument devt = (StartDocument) evt; - assertEquals("1.0", devt.getVersion()); - assertTrue(devt.encodingSet()); - assertEquals("UTF-8", devt.getCharacterEncodingScheme()); - assertTrue(devt.standaloneSet()); - assertTrue(devt.isStandalone()); - er.close(); - - // And then let's see that we can still access it normally too - evt = er.peek(); - assertTrue(evt.isStartDocument()); - // and cast just for fun (to check it really is startdoc event) - devt = (StartDocument) evt; - } - } - - /** - * Let's also quickly verify that we can skip xml declaration (actual - * or virtual) to the root element -- should work ok. - */ - public void testNextEvent() - throws XMLStreamException - { - String XML = ""; - for (int i = 0; i < 4; ++i) { - boolean ns = (i & 1) != 0; - boolean coal = (i & 2) != 0; - XMLEventReader er = getReader(XML, ns, coal); - - XMLEvent evt = er.nextTag(); - assertNotNull(evt); - assertTrue(evt.isStartElement()); - StartElement elem = evt.asStartElement(); - QName n = elem.getName(); - assertNotNull(n); - assertEquals("root", n.getLocalPart()); - } - - XML = "" - +""; - for (int i = 0; i < 4; ++i) { - boolean ns = (i & 1) != 0; - boolean coal = (i & 2) != 0; - XMLEventReader er = getReader(XML, ns, coal); - XMLEvent evt = er.peek(); - - assertTrue(evt.isStartDocument()); - - // Fine, and then should get the start elem anyways - evt = er.nextTag(); - assertNotNull(evt); - assertTrue(evt.isStartElement()); - StartElement elem = evt.asStartElement(); - QName n = elem.getName(); - assertNotNull(n); - assertEquals("root", n.getLocalPart()); - } - } - - /* - ///////////////////////////////////////////////// - // Internal methods: - ///////////////////////////////////////////////// - */ - - private XMLEventReader getReader(String contents, boolean nsAware, - boolean coalesce) - throws XMLStreamException - { - return getReader(contents, nsAware, coalesce, true); - } - - private XMLEventReader getReader(String contents, boolean nsAware, - boolean coalesce, boolean expandEnt) - throws XMLStreamException - { - XMLInputFactory f = getInputFactory(); - setNamespaceAware(f, nsAware); - setCoalescing(f, coalesce); - setSupportDTD(f, true); - setValidating(f, false); - setReplaceEntities(f, expandEnt); - return constructEventReader(f, contents); - } -} diff -Nru libwoodstox-java-4.1.3/src/test/org/codehaus/stax/test/evt/TestStartElem.java libwoodstox-java-5.1.0/src/test/org/codehaus/stax/test/evt/TestStartElem.java --- libwoodstox-java-4.1.3/src/test/org/codehaus/stax/test/evt/TestStartElem.java 2012-04-24 04:38:21.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/org/codehaus/stax/test/evt/TestStartElem.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,388 +0,0 @@ -package org.codehaus.stax.test.evt; - -import java.util.*; - -import javax.xml.namespace.NamespaceContext; -import javax.xml.namespace.QName; -import javax.xml.stream.*; -import javax.xml.stream.events.*; - -/** - * Unit tests for testing that START_ELEMENT event object behaves - * as expected - * - * @author Tatu Saloranta - */ -public class TestStartElem - extends BaseEventTest -{ - /** - * Simple tests to ensure that the namespace declarations are properly - * parsed and accessible via {@link StartElement}. - */ - public void testStartElemNs() - throws XMLStreamException - { - String XML = ""; - - XMLEventReader er = getReader(XML, true, false); - assertTokenType(START_DOCUMENT, er.nextEvent().getEventType()); - XMLEvent evt = er.nextEvent(); - assertTokenType(START_ELEMENT, evt.getEventType()); - // Ok, got the start element... is it ok? - assertTrue(evt.isStartElement()); - StartElement se = evt.asStartElement(); - testEventWritability(se); - - NamespaceContext nsCtxt = se.getNamespaceContext(); - - assertNotNull("StartElement.getNamespaceContext() should never return null", nsCtxt); - // First, ones we shouldn't get: - assertNull(nsCtxt.getPrefix("a")); - assertNull(nsCtxt.getPrefix("http://foobar")); - assertNull(nsCtxt.getNamespaceURI("b")); - assertNull(nsCtxt.getNamespaceURI("http://my")); - - { - Iterator it = nsCtxt.getPrefixes("http://foobar"); - // Specs don't specify if we should get null, or empty iterator - assertTrue((it == null) || !it.hasNext()); - it = nsCtxt.getPrefixes("a"); - assertTrue((it == null) || !it.hasNext()); - } - // Then ones we should: - - assertEquals("a", nsCtxt.getPrefix("ns:attrs")); - assertEquals("", nsCtxt.getPrefix("http://my")); - assertEquals("http://my", nsCtxt.getNamespaceURI("")); - assertEquals("ns:attrs", nsCtxt.getNamespaceURI("a")); - - // Plus, let's check the other namespace access: - Iterator it = se.getNamespaces(); - assertEquals(2, countElements(it)); - - assertTokenType(END_ELEMENT, er.nextEvent().getEventType()); - assertTokenType(END_DOCUMENT, er.nextEvent().getEventType()); - assertFalse(er.hasNext()); - } - - public void testNestedStartElemNs() - throws XMLStreamException - { - String XML = "" - +"" - +"" - +""; - - XMLEventReader er = getReader(XML, true, false); - assertTokenType(START_DOCUMENT, er.nextEvent().getEventType()); - XMLEvent evt = er.nextEvent(); - assertTokenType(START_ELEMENT, evt.getEventType()); - StartElement se = evt.asStartElement(); - testEventWritability(se); - - // Let's first check that it has 1 declaration: - assertEquals(0, countElements(se.getNamespaces())); - NamespaceContext nsCtxt = se.getNamespaceContext(); - assertNotNull("StartElement.getNamespaceContext() should never return null", nsCtxt); - assertNull(nsCtxt.getPrefix("a")); - assertNull(nsCtxt.getNamespaceURI("b")); - - // then first leaf: - evt = er.nextEvent(); - assertTrue(evt.isStartElement()); - se = evt.asStartElement(); - assertEquals("leaf", se.getName().getLocalPart()); - assertEquals(1, countElements(se.getNamespaces())); - assertEquals("x", se.getName().getNamespaceURI()); - nsCtxt = se.getNamespaceContext(); - assertEquals("x", nsCtxt.getNamespaceURI("")); - assertEquals("", nsCtxt.getPrefix("x")); - testEventWritability(se); - - evt = er.nextEvent(); - assertTrue(evt.isEndElement()); - testEventWritability(evt); - - // Ok, branch: - evt = er.nextEvent(); - assertTrue(evt.isStartElement()); - se = evt.asStartElement(); - assertEquals("branch", se.getName().getLocalPart()); - assertEquals(2, countElements(se.getNamespaces())); - nsCtxt = se.getNamespaceContext(); - assertEquals("a", nsCtxt.getPrefix("b")); - assertEquals("b", nsCtxt.getNamespaceURI("a")); - assertEquals("x", nsCtxt.getPrefix("url")); - assertEquals("url", nsCtxt.getNamespaceURI("x")); - testEventWritability(se); - - // second leaf - evt = er.nextEvent(); - assertTrue(evt.isStartElement()); - se = evt.asStartElement(); - nsCtxt = se.getNamespaceContext(); - assertEquals("leaf", se.getName().getLocalPart()); - // only one declared in this particular element - assertEquals(1, countElements(se.getNamespaces())); - // but should still show the other bound ns from parent - nsCtxt = se.getNamespaceContext(); - assertEquals("a", nsCtxt.getPrefix("c")); - assertEquals("c", nsCtxt.getNamespaceURI("a")); - assertEquals("x", nsCtxt.getPrefix("url")); - assertEquals("url", nsCtxt.getNamespaceURI("x")); - // ok, but how about masking: - assertNull(nsCtxt.getPrefix("b")); - - // Ok, fine... others we don't care about: - assertTrue(er.nextEvent().isEndElement()); - } - - /** - * Another unit test, one that checks a special case of namespace - * enclosures and namespace context objects. - */ - public void testNestedStartElemNs2() - throws XMLStreamException - { - String XML = ""; - - XMLEventReader er = getReader(XML, true, false); - assertTokenType(START_DOCUMENT, er.nextEvent().getEventType()); - - XMLEvent evt = er.nextEvent(); // root - assertTokenType(START_ELEMENT, evt.getEventType()); - StartElement se = evt.asStartElement(); - assertEquals("root", se.getName().getLocalPart()); - assertEquals(0, countElements(se.getNamespaces())); - - evt = er.nextEvent(); // branch - assertTokenType(START_ELEMENT, evt.getEventType()); - se = evt.asStartElement(); - assertEquals("branch", se.getName().getLocalPart()); - assertEquals(1, countElements(se.getNamespaces())); - NamespaceContext nsCtxt = se.getNamespaceContext(); - assertNotNull("StartElement.getNamespaceContext() should never return null", nsCtxt); - assertEquals("url", nsCtxt.getNamespaceURI("a")); - assertEquals("a", nsCtxt.getPrefix("url")); - - evt = er.nextEvent(); // leaf - assertTokenType(START_ELEMENT, evt.getEventType()); - se = evt.asStartElement(); - assertEquals("leaf", se.getName().getLocalPart()); - assertEquals(0, countElements(se.getNamespaces())); - nsCtxt = se.getNamespaceContext(); - assertEquals("url", nsCtxt.getNamespaceURI("a")); - assertEquals("a", nsCtxt.getPrefix("url")); - - assertTrue(er.nextEvent().isEndElement()); // /leaf - assertTrue(er.nextEvent().isEndElement()); // /branch - assertTrue(er.nextEvent().isEndElement()); // /root - } - - - /** - * Test to check that attributes can be accessed normally via - * {@link StartElement} instances. - */ - public void testStartElemAttrs() - throws XMLStreamException - { - String XML = ""; - - XMLEventReader er = getReader(XML, true, false); - assertTokenType(START_DOCUMENT, er.nextEvent().getEventType()); - - XMLEvent evt = er.nextEvent(); - assertTokenType(START_ELEMENT, evt.getEventType()); - StartElement se = evt.asStartElement(); - - assertAttr(se, "", "attr1", "value1"); - // ... and same without ns uri being passed - assertNqAttr(se, "attr1", "value1"); - assertAttr(se, "ns:attrs", "attr2", "value2"); - assertAttr(se, "", "attr2", null); - assertNqAttr(se, "attr2", null); - assertAttr(se, "ns:attrs", "attr1", null); - - evt = er.nextEvent(); - assertTokenType(START_ELEMENT, evt.getEventType()); - se = evt.asStartElement(); - - // One we should find (note: def. ns is not used!) - assertAttr(se, "", "attr", "x"); - assertNqAttr(se, "attr", "x"); - - // and then ones that aren't there... - assertAttr(se, "url:ns2", "attr", null); - assertAttr(se, "url:ns2", "x", null); - assertAttr(se, "ns:foo", "foobar", null); - assertAttr(se, "", "attr1", null); - assertNqAttr(se, "attr1", null); - - assertTokenType(END_ELEMENT, er.nextEvent().getEventType()); - assertTokenType(END_ELEMENT, er.nextEvent().getEventType()); - assertTokenType(END_DOCUMENT, er.nextEvent().getEventType()); - } - - public void testStartElemManyAttrsNs() - throws XMLStreamException - { - XMLEventReader er = getReader(get11AttrDoc(), true, false); - assertTokenType(START_DOCUMENT, er.nextEvent().getEventType()); - XMLEvent evt = er.nextEvent(); - assertTokenType(START_ELEMENT, evt.getEventType()); - StartElement se = evt.asStartElement(); - assertEquals(11, countElements(se.getAttributes())); - - // Let's verify we can find all attrs: - for (int i = ATTR11_NAMES.length; --i >= 0; ) { - String name = ATTR11_NAMES[i]; - String value = ATTR11_VALUES[i]; - // First, via string constant: - assertAttr11Value(se, name, value); - // Then using non-interned: - assertAttr11Value(se, ""+name, value); - - // Then that non-existing ones are not found: - String start = name.substring(0, 1); - assertAttr11Value(se, name+start, null); - assertAttr11Value(se, start+name, null); - } - assertTokenType(END_ELEMENT, er.nextEvent().getEventType()); - er.close(); - } - - /* - ///////////////////////////////////////////////// - // Internal methods: - ///////////////////////////////////////////////// - */ - - final static String[] ATTR11_NAMES = new String[] { - "method", "activeShell", "source", "data", - "widget", "length", "start", "styledTextNewValue", - "replacedText", "styledTextFunction", "raw" - }; - final static String[] ATTR11_VALUES = new String[] { - "a", "x", "y", "z", - "a", "1", "2", "t", - "", "f", "b" - }; - - private void assertAttr11Value(StartElement elem, String localName, String expValue) - { - String msg = "Wrong value for attribute '"+localName+"'; "; - - Attribute attr = elem.getAttributeByName(new QName(localName)); - String actValue = (attr == null) ? null : attr.getValue(); - if (expValue == null) { - assertNull(msg, actValue); - } else { - assertEquals(msg, expValue, actValue); - } - - // Let's also try with the other qname constructors, just to be sure - attr = elem.getAttributeByName(new QName("", localName)); - actValue = (attr == null) ? null : attr.getValue(); - if (expValue == null) { - assertNull(msg, actValue); - } else { - assertEquals(msg, expValue, actValue); - } - - attr = elem.getAttributeByName(new QName("", localName, "")); - actValue = (attr == null) ? null : attr.getValue(); - if (expValue == null) { - assertNull(msg, actValue); - } else { - assertEquals(msg, expValue, actValue); - } - } - - private String get11AttrDoc() - { - StringBuffer sb = new StringBuffer(); - sb.append(""); - return sb.toString(); - } - - private int countElements(Iterator it) { - int count = 0; - if (it != null) { - while (it.hasNext()) { - ++count; - it.next(); - } - } - return count; - } - - private void assertAttr(StartElement se, String nsURI, String localName, - String expValue) - { - QName qn = new QName(nsURI, localName); - Attribute attr = se.getAttributeByName(qn); - - if (expValue == null) { - assertNull("Should not find attribute '"+qn+"'", attr); - } else { - assertNotNull("Should find attribute '"+qn+"' but got null", attr); - assertEquals("Attribute '"+qn+"' has unexpected value", - expValue, attr.getValue()); - } - } - - private void assertNqAttr(StartElement se, String localName, String expValue) - { - QName qn = new QName(localName); - Attribute attr = se.getAttributeByName(qn); - - if (expValue == null) { - assertNull("Should not find attribute '"+qn+"'", attr); - } else { - assertNotNull("Should find attribute '"+qn+"' but got null", attr); - assertEquals("Attribute '"+qn+"' has unexpected value", - expValue, attr.getValue()); - } - - /* 21-Sep-2006, TSa: Let's also try it with different QName - * constructor, just to be sure - */ - qn = new QName("", localName); - attr = se.getAttributeByName(qn); - if (expValue == null) { - assertNull("Should not find attribute '"+qn+"'", attr); - } else { - assertNotNull("Should find attribute '"+qn+"' but got null", attr); - assertEquals("Attribute '"+qn+"' has unexpected value", - expValue, attr.getValue()); - } - } - - private XMLEventReader getReader(String contents, boolean nsAware, - boolean coalesce) - throws XMLStreamException - { - XMLInputFactory f = getInputFactory(); - setNamespaceAware(f, nsAware); - setCoalescing(f, coalesce); - setSupportDTD(f, true); - setValidating(f, false); - return constructEventReader(f, contents); - } -} diff -Nru libwoodstox-java-4.1.3/src/test/org/codehaus/stax/test/SimpleResolver.java libwoodstox-java-5.1.0/src/test/org/codehaus/stax/test/SimpleResolver.java --- libwoodstox-java-4.1.3/src/test/org/codehaus/stax/test/SimpleResolver.java 2012-04-24 04:38:21.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/org/codehaus/stax/test/SimpleResolver.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,31 +0,0 @@ -package org.codehaus.stax.test; - -import javax.xml.stream.XMLResolver; - -/** - * This is a simple and stupid resolver, that does not check what is - * being resolved; and thus it should only be used if only one thing - * (a single external entity; a single external subset) is to - * be expanded (although that single entity can be repeated multiple - * times). - */ -public class SimpleResolver - implements XMLResolver -{ - final String ENC = "UTF-8"; - final byte[] mData; - - public SimpleResolver(String content) - { - try { - mData = content.getBytes(ENC); - } catch (java.io.IOException ioe) { - throw new Error(ioe.toString()); - } - } - - public Object resolveEntity(String publicID, String systemID, String baseURI, String namespace) - { - return new java.io.ByteArrayInputStream(mData); - } -} diff -Nru libwoodstox-java-4.1.3/src/test/org/codehaus/stax/test/stream/BaseStreamTest.java libwoodstox-java-5.1.0/src/test/org/codehaus/stax/test/stream/BaseStreamTest.java --- libwoodstox-java-4.1.3/src/test/org/codehaus/stax/test/stream/BaseStreamTest.java 2012-04-24 04:38:21.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/org/codehaus/stax/test/stream/BaseStreamTest.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,157 +0,0 @@ -package org.codehaus.stax.test.stream; - -import javax.xml.namespace.QName; -import javax.xml.stream.XMLInputFactory; -import javax.xml.stream.XMLStreamException; -import javax.xml.stream.XMLStreamReader; - -import org.codehaus.stax.test.BaseStaxTest; - -/** - * Base class for all StaxTest unit tests that test basic non-validating - * stream (cursor) API functionality. - * - * @author Tatu Saloranta - */ -public abstract class BaseStreamTest - extends BaseStaxTest -{ - /** - * Switch that can be turned on to verify to display ALL exact Exceptions - * thrown when Exceptions are expected. This is sometimes necessary - * when debugging, since it's impossible to automatically verify - * that Exception is exactly the right one, since there is no - * strict Exception type hierarchy for StAX problems. - *

- * Note: Not made 'final static', so that compiler won't inline - * it. Makes possible to do partial re-compilations. - * Note: Since it's only used as the default value, sub-classes - * can separately turn it off as necessary - */ - //protected static boolean DEF_PRINT_EXP_EXCEPTION = true; - protected static boolean DEF_PRINT_EXP_EXCEPTION = false; - - protected boolean PRINT_EXP_EXCEPTION = DEF_PRINT_EXP_EXCEPTION; - - protected BaseStreamTest() { super(); } - - protected BaseStreamTest(String name) { super(name); } - - /* - ////////////////////////////////////////////////// - // Higher-level test methods - ////////////////////////////////////////////////// - */ - - /** - * Method that will iterate through contents of an XML document - * using specified stream reader; will also access some of data - * to make sure reader reads most of lazy-loadable data. - * Method is usually called to try to get an exception for invalid - * content. - * - * @return Dummy value calculated on contents; used to make sure - * no dead code is eliminated - */ - protected int streamThrough(XMLStreamReader sr) - throws XMLStreamException - { - int result = 0; - - assertNotNull(sr); - try { - while (sr.hasNext()) { - int type = sr.next(); - result += type; - if (sr.hasText()) { - /* will also do basic verification for text content, to - * see that all text accessor methods return same content - */ - result += getAndVerifyText(sr).hashCode(); - } - if (sr.hasName()) { - QName n = sr.getName(); - assertNotNull(n); - result += n.hashCode(); - } - } - } catch (RuntimeException rex) { - // Let's try to find a nested XMLStreamException, if possible - Throwable t = rex; - while (t != null) { - t = t.getCause(); - if (t instanceof XMLStreamException) { - throw (XMLStreamException) t; - } - } - // Nope, just a runtime exception - throw rex; - } - - return result; - } - - protected int streamThroughFailing(XMLInputFactory f, String contents, - String msg) - { - int result = 0; - try { - XMLStreamReader sr = constructStreamReader(f, contents); - result = streamThrough(sr); - } catch (XMLStreamException ex) { // good - if (PRINT_EXP_EXCEPTION) { - System.out.println("Expected failure: '"+ex.getMessage()+"' " - +"(matching message: '"+msg+"')"); - } - return 0; - } catch (Exception ex2) { // may still be ok: - if (ex2.getCause() instanceof XMLStreamException) { - if (PRINT_EXP_EXCEPTION) { - System.out.println("Expected failure: '"+ex2.getMessage()+"' " - +"(matching message: '"+msg+"')"); - } - return 0; - } - fail("Expected an XMLStreamException (either direct, or getCause() of a primary exception) for "+msg - +", got: "+ex2); - } - - fail("Expected an exception for "+msg); - return result; // never gets here - } - - protected int streamThroughFailing(XMLStreamReader sr, String msg) - { - int result = 0; - try { - result = streamThrough(sr); - } catch (XMLStreamException ex) { // good - if (PRINT_EXP_EXCEPTION) { - System.out.println("Expected failure: '"+ex.getMessage()+"' " - +"(matching message: '"+msg+"')"); - } - return 0; - } catch (Exception ex2) { // ok; iff links to XMLStreamException - Throwable t = ex2; - while (t.getCause() != null && !(t instanceof XMLStreamException)) { - t = t.getCause(); - } - if (t instanceof XMLStreamException) { - if (PRINT_EXP_EXCEPTION) { - System.out.println("Expected failure: '"+ex2.getMessage()+"' " - +"(matching message: '"+msg+"')"); - } - return 0; - } - if (t == ex2) { - fail("Expected an XMLStreamException (either direct, or getCause() of a primary exception) for "+msg - +", got: "+ex2); - } - fail("Expected an XMLStreamException (either direct, or getCause() of a primary exception) for "+msg - +", got: "+ex2+" (root: "+t+")"); - } - - fail("Expected an exception for "+msg); - return result; // never gets here - } -} diff -Nru libwoodstox-java-4.1.3/src/test/org/codehaus/stax/test/stream/BlockingStream.java libwoodstox-java-5.1.0/src/test/org/codehaus/stax/test/stream/BlockingStream.java --- libwoodstox-java-4.1.3/src/test/org/codehaus/stax/test/stream/BlockingStream.java 2012-04-24 04:38:21.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/org/codehaus/stax/test/stream/BlockingStream.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,44 +0,0 @@ -package org.codehaus.stax.test.stream; - -import java.io.*; - -/** - * Test stream used to test whether Reader using this stream would - * 'accidentally' cause blocking. Used by {@link TestStreaming} - * unit test suite. - */ -class BlockingStream - extends FilterInputStream -{ - public boolean mBlocked = false; - - // dummy ctor to keep JUnit happy - public BlockingStream() { super(null); } - - public BlockingStream(InputStream is) - { - super(is); - } - - public boolean hasBlocked() { - return mBlocked; - } - - public int read() throws IOException - { - int r = super.read(); - if (r < 0) { - mBlocked = true; - } - return r; - } - - public int read(byte[] b, int off, int len) throws IOException - { - int r = super.read(b, off, len); - if (r < 0) { - mBlocked = true; - } - return r; - } -} diff -Nru libwoodstox-java-4.1.3/src/test/org/codehaus/stax/test/stream/TestAttributeDTD.java libwoodstox-java-5.1.0/src/test/org/codehaus/stax/test/stream/TestAttributeDTD.java --- libwoodstox-java-4.1.3/src/test/org/codehaus/stax/test/stream/TestAttributeDTD.java 2012-04-24 04:38:21.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/org/codehaus/stax/test/stream/TestAttributeDTD.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,45 +0,0 @@ -package org.codehaus.stax.test.stream; - -import javax.xml.namespace.QName; -import javax.xml.stream.*; - -/** - * Unit tests related to handling of attributes that depend on DTD subsets. - * - * @author Tatu Saloranta - */ -public class TestAttributeDTD - extends BaseStreamTest -{ - - /** - * Test to make sure that quotes can be used in attribute values - * via entity expansion - */ - final String VALID_ATTRS_WITH_QUOTES - = "\n" - + " ]>\n" - + ""; - - public void testQuotesViaEntities() - throws XMLStreamException - { - XMLInputFactory ifact = getNewInputFactory(); - setNamespaceAware(ifact, false); // shouldn't matter - // These are needed to get entities read and expanded: - setSupportDTD(ifact, true); - setReplaceEntities(ifact, true); - - XMLStreamReader sr = constructStreamReader(ifact, - VALID_ATTRS_WITH_QUOTES); - // Shouldn't get exceptions... - - try { - streamThrough(sr); - } catch (XMLStreamException ex) { - fail("Failed to parse attributes with quotes expanded from entities: "+ex); - } - } -} diff -Nru libwoodstox-java-4.1.3/src/test/org/codehaus/stax/test/stream/TestAttributeRead.java libwoodstox-java-5.1.0/src/test/org/codehaus/stax/test/stream/TestAttributeRead.java --- libwoodstox-java-4.1.3/src/test/org/codehaus/stax/test/stream/TestAttributeRead.java 2012-04-24 04:38:21.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/org/codehaus/stax/test/stream/TestAttributeRead.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,518 +0,0 @@ -package org.codehaus.stax.test.stream; - -import javax.xml.namespace.QName; -import javax.xml.stream.*; - -/** - * Unit test suite that tests handling of the XML attributes, both - * in namespace aware and non-namespace modes, including ensuring - * that values are properly normalized with regards to white space. - * There are tests for both well-formed and non-wellformed cases. - * - * @author Tatu Saloranta - */ -public class TestAttributeRead - extends BaseStreamTest -{ - final String VALID_XML1 - = ""; - - final String VALID_XML2 - = ""; - - final String VALID_XML3 - = ""; - - public void testValidNsAttrsByName() - throws XMLStreamException - { - XMLStreamReader sr = getReader(VALID_XML1, true); - assertEquals(START_ELEMENT, sr.next()); - assertEquals(1, sr.getNamespaceCount()); - assertEquals(2, sr.getAttributeCount()); - - assertEquals("r&b", sr.getAttributeValue(null, "a")); - assertEquals("\"", sr.getAttributeValue("url", "b")); - - // Shoulnd't allow using prefix instead of URI - String val = sr.getAttributeValue("a", "b"); - assertNull("Should get null, not '"+val+"'", val); - val = sr.getAttributeValue("", "b"); - assertNull("Should get null, not '"+val+"'", val); - - assertEquals(END_ELEMENT, sr.next()); - assertEquals(END_DOCUMENT, sr.next()); - } - - /** - * Additional unit test that verifies that empty namespace URI - * can be used as expected - */ - public void testValidNsAttrsByName2() - throws XMLStreamException - { - XMLStreamReader sr = getReader("", true); - assertEquals(START_ELEMENT, sr.next()); - assertEquals(0, sr.getNamespaceCount()); - assertEquals(1, sr.getAttributeCount()); - - /* Both null and "" should work as well - * (note: specs are bit confusing and contradictory wrt - * how null is to be handled, but in this case all interpretations - * would produce same result) - */ - assertEquals("1", sr.getAttributeValue(null, "attr")); - assertEquals("1", sr.getAttributeValue("", "attr")); - - assertNull(sr.getAttributeValue(null, "b")); - assertNull(sr.getAttributeValue("", "b")); - - assertEquals(END_ELEMENT, sr.next()); - assertEquals(END_DOCUMENT, sr.next()); - } - - public void testValidNsAttrsByIndex() - throws XMLStreamException - { - XMLStreamReader sr = getReader(VALID_XML1, true); - assertEquals(START_ELEMENT, sr.next()); - assertEquals(1, sr.getNamespaceCount()); - assertEquals(2, sr.getAttributeCount()); - - /* Note: we can not assume on stream reader returning attributes - * in document order... most will do that, but it's not a - * strict StAX requirement. - */ - - String ln1 = sr.getAttributeLocalName(0); - - int index1 = 0; - int index2 = 1; - - if (ln1.equals("a")) { - ; - } else if (ln1.equals("b")) { - index1 = 1; - index2 = 0; - } else { - fail("Unexpected local name for attribute #0; expected either 'a' or 'b'; got '"+ln1+"'."); - } - - assertEquals("a", sr.getAttributeLocalName(index1)); - assertEquals("b", sr.getAttributeLocalName(index2)); - - assertEquals("r&b", sr.getAttributeValue(index1)); - assertEquals("\"", sr.getAttributeValue(index2)); - - assertNoAttrPrefix(sr.getAttributePrefix(index1)); - assertEquals("a", sr.getAttributePrefix(index2)); - assertNoAttrNamespace(sr.getAttributeNamespace(index1)); - assertEquals("url", sr.getAttributeNamespace(index2)); - } - - public void testValidNsAttrs2() - throws XMLStreamException - { - XMLStreamReader sr = getReader(VALID_XML3, true); - assertEquals(START_ELEMENT, sr.next()); - assertEquals("root", sr.getLocalName()); - - assertEquals(START_ELEMENT, sr.next()); - assertEquals("e1", sr.getLocalName()); - assertEquals(1, sr.getAttributeCount()); - assertEquals("a", sr.getAttributeLocalName(0)); - assertEquals("123", sr.getAttributeValue(0)); - assertEquals("123", sr.getAttributeValue(null, "a")); - assertEquals(END_ELEMENT, sr.next()); - assertEquals("e1", sr.getLocalName()); - - assertEquals(START_ELEMENT, sr.next()); - assertEquals("e2", sr.getLocalName()); - assertEquals(0, sr.getAttributeCount()); - String val = sr.getAttributeValue(null, "a"); - if (val != null) { - fail("Should not find a value for attribute 'a', found '"+val+"'"); - } - - assertEquals(END_ELEMENT, sr.next()); - assertEquals("e2", sr.getLocalName()); - - assertEquals(END_ELEMENT, sr.next()); - assertEquals("root", sr.getLocalName()); - sr.close(); - } - - public void testValidNsAttrNsInfo() - throws XMLStreamException - { - XMLStreamReader sr = getReader - ("", - true); - - assertEquals(START_ELEMENT, sr.next()); - assertEquals("root", sr.getLocalName()); - assertEquals(1, sr.getNamespaceCount()); - assertEquals(1, sr.getAttributeCount()); - assertNoAttrPrefix(sr.getAttributePrefix(0)); - assertNoAttrNamespace(sr.getAttributeNamespace(0)); - assertEquals("xyz", sr.getAttributeValue(0)); - - assertEquals(START_ELEMENT, sr.next()); - assertEquals("leaf", sr.getLocalName()); - assertEquals(0, sr.getNamespaceCount()); - assertEquals(1, sr.getAttributeCount()); - assertEquals("b", sr.getAttributePrefix(0)); - assertEquals("http://foo", sr.getAttributeNamespace(0)); - assertEquals("1", sr.getAttributeValue(0)); - - assertEquals(END_ELEMENT, sr.next()); - assertEquals("leaf", sr.getLocalName()); - assertEquals(END_ELEMENT, sr.next()); - assertEquals("root", sr.getLocalName()); - - assertEquals(END_DOCUMENT, sr.next()); - } - - public void testValidNonNsAttrs() - throws XMLStreamException - { - XMLStreamReader sr = getReader(VALID_XML1, false); - - // Does the impl support non-ns mode? - if (sr == null) { // nope! - return; - } - - assertEquals(START_ELEMENT, sr.next()); - assertEquals(0, sr.getNamespaceCount()); - assertEquals(3, sr.getAttributeCount()); - - assertEquals("r&b", sr.getAttributeValue(null, "a")); - assertEquals("\"", sr.getAttributeValue(null, "a:b")); - - assertEquals(END_ELEMENT, sr.next()); - assertEquals(END_DOCUMENT, sr.next()); - } - - public void testValidNonNsAttrsByIndex() - throws XMLStreamException - { - // = ""; - XMLStreamReader sr = getReader(VALID_XML2, false); - - // Does the impl support non-ns mode? - if (sr == null) { // nope! - return; - } - - assertEquals(START_ELEMENT, sr.next()); - assertEquals(0, sr.getNamespaceCount()); - assertEquals(2, sr.getAttributeCount()); - - /* Note: we can not assume on stream reader returning attributes - * in document order... most will do that, but it's not a - * strict StAX requirement. - */ - - String ln1 = sr.getAttributeLocalName(0); - - int index1 = 0; - int index2 = 1; - - if (ln1.equals("a:b")) { - ; - } else if (ln1.equals("xmlns:a")) { - index1 = 1; - index2 = 0; - } else { - fail("Unexpected local name for attribute #0; expected either 'a:b' or 'xmlns:a'; got '"+ln1+"'."); - } - - assertEquals("a:b", sr.getAttributeLocalName(index1)); - assertEquals("xmlns:a", sr.getAttributeLocalName(index2)); - - assertEquals("\"", sr.getAttributeValue(index1)); - assertEquals("url", sr.getAttributeValue(index2)); - assertNoAttrPrefix(sr.getAttributePrefix(index1)); - assertNoAttrPrefix(sr.getAttributePrefix(index2)); - - assertNoAttrNamespace(sr.getAttributeNamespace(index1)); - assertNoAttrNamespace(sr.getAttributeNamespace(index2)); - } - - public void testInvalidAttrNames() - throws XMLStreamException - { - // First NS-aware, then non-NS: - XMLStreamReader sr = getReader("", true); - if (sr != null) { - streamThroughFailing(sr, "invalid attribute name; can not start with '.'"); - } - sr = getReader("", false); - if (sr != null) { - streamThroughFailing(sr, "invalid attribute name; can not start with '.'"); - } - sr = getReader("", false); - if (sr != null) { - streamThroughFailing(sr, "invalid attribute name can not contain '?'"); - } - sr = getReader("", true); - if (sr != null) { - streamThroughFailing(sr, "invalid attribute name can not contain '?'"); - } - } - - public void testInvalidAttrValue() - throws XMLStreamException - { - for (int i = 0; i < 2; ++i) { - boolean ns = (i > 0); - // Invalid, '<' not allowed in attribute value - String XML = ""; - - XMLStreamReader sr = getReader(XML, ns); - // Does the impl support non-ns mode? - if (sr == null) { // nope! shouldn't test... - continue; - } - streamThroughFailing(sr, "unquoted '<' in attribute value"); - - XML = ""; - streamThroughFailing(getReader(XML, ns), - "missing value for attribute"); - } - } - - /** - * This tests that spaces are actually needed between attributes... - */ - public void testInvalidAttrSpaces() - throws XMLStreamException - { - for (int i = 0; i < 2; ++i) { - boolean ns = (i > 0); - String XML = ""; - XMLStreamReader sr = getReader(XML, ns); - // Does the impl support non-ns mode? - if (sr == null) { // nope! shouldn't test... - continue; - } - streamThroughFailing(sr, "missing space between attributes"); - XML = ""; - streamThroughFailing(getReader(XML, ns), - "missing space between attributes"); - } - } - - public void testInvalidNsAttrDup() - throws XMLStreamException - { - // Invalid; straight duplicate attrs: - String XML = ""; - streamThroughFailing(getReader(XML, true), "duplicate attributes"); - // Invalid; sneakier duplicate attrs: - XML = ""; - streamThroughFailing(getReader(XML, true), - "duplicate attributes (same URI, different prefix)"); - - /* Also, let's add some more, in case parser just checks for adjacent - * ones, or has special cases for small number of attrs... - */ - XML = ""; - streamThroughFailing(getReader(XML, true), "duplicate attributes"); - - XML = ""; - streamThroughFailing(getReader(XML, true), - "duplicate attributes (same URI, different prefix)"); - } - - public void testInvalidNonNsAttrDup() - throws XMLStreamException - { - // Invalid; duplicate attrs even without namespaces - String XML = ""; - XMLStreamReader sr = getReader(XML, false); - if (sr != null) { - streamThroughFailing(sr, "duplicate attributes"); - } - - // Valid when namespaces not enabled: - XML = ""; - try { - sr = getReader(XML, false); - // Does the impl support non-ns mode? - if (sr == null) { // nope! shouldn't test... - return; - } - streamThrough(sr); - } catch (Exception e) { - fail("Didn't expect an exception when namespace support not enabled: "+e); - } - } - - /** - * This test verifies that handling of multiple attributes should - * work as expected - */ - public void testManyAttrsNs() - throws Exception - { - doTestManyAttrs(true); - } - - public void testManyAttrsNonNs() - throws Exception - { - doTestManyAttrs(false); - } - - /** - * Unit test that verifies that by-index attribute accessors - * will throw proper exception when using invalid index to - * access data (value, name, uri/prefix). - */ - public void testInvalidAccessByIndex() - throws Exception - { - String XML = ""; - - XMLStreamReader sr = getReader(XML, true); - assertTokenType(START_ELEMENT, sr.next()); - assertEquals(2, sr.getAttributeCount()); - assertTokenType(START_ELEMENT, sr.next()); - assertEquals(1, sr.getAttributeCount()); - - try { - String str = sr.getAttributeValue(1); - fail("Expected IllegalArgumentException for sr.getAttributeValue() with illegal index, no exception, value = ["+str+"]"); - } catch (IllegalArgumentException iae) { - ; // good - } catch (Exception e) { - // almost ok - fail("Expected IllegalArgumentException for sr.getAttributeValue() with illegal index, got: "+e); - } - - try { - QName n = sr.getAttributeName(1); - fail("Expected IllegalArgumentException for sr.getAttributeName() with illegal index, no exception, name = ["+n+"]"); - } catch (IllegalArgumentException iae) { - ; // good - } catch (Exception e) { - // almost ok - fail("Expected IllegalArgumentException for sr.getAttributeName() with illegal index, got: "+e); - } - - try { - String n = sr.getAttributeLocalName(1); - fail("Expected IllegalArgumentException for sr.getAttributeLocalName() with illegal index, no exception, got = ["+n+"]"); - } catch (IllegalArgumentException iae) { - ; // good - } catch (Exception e) { - // almost ok - fail("Expected IllegalArgumentException for sr.getAttributeLocalName() with illegal index, got: "+e); - } - - try { - String n = sr.getAttributeNamespace(1); - fail("Expected IllegalArgumentException for sr.getAttributeNamespace() with illegal index, no exception, got = ["+n+"]"); - } catch (IllegalArgumentException iae) { - ; // good - } catch (Exception e) { - // almost ok - fail("Expected IllegalArgumentException for sr.getAttributeNamespace() with illegal index, got: "+e); - } - - try { - String n = sr.getAttributePrefix(1); - fail("Expected IllegalArgumentException for sr.getAttributePrefix() with illegal index, no exception, got = ["+n+"]"); - } catch (IllegalArgumentException iae) { - ; // good - } catch (Exception e) { - // almost ok - fail("Expected IllegalArgumentException for sr.getAttributePrefix() with illegal index, got: "+e); - } - - sr.close(); - } - - - /* - //////////////////////////////////////// - // Private methods, other - //////////////////////////////////////// - */ - - final static String[] ATTR11_NAMES = new String[] { - "method", "activeShell", "source", "data", - "widget", "length", "start", "styledTextNewValue", - "replacedText", "styledTextFunction", "raw" - }; - final static String[] ATTR11_VALUES = new String[] { - "a", "x", "y", "z", - "a", "1", "2", "t", - "", "f", "b" - }; - - private String get11AttrDoc() - { - StringBuffer sb = new StringBuffer(); - sb.append(""); - return sb.toString(); - } - - private void doTestManyAttrs(boolean ns) - throws XMLStreamException - { - XMLStreamReader sr = getReader(get11AttrDoc(), ns); - // If non-ns mode not available, that's ok; we'll skip the test - if (sr == null) { - return; - } - assertTokenType(START_ELEMENT, sr.next()); - assertEquals(11, sr.getAttributeCount()); - /* Let's verify we can find them all - */ - for (int i = ATTR11_NAMES.length; --i >= 0; ) { - String name = ATTR11_NAMES[i]; - String value = ATTR11_VALUES[i]; - // First, via string constant: - assertEquals(value, sr.getAttributeValue(null, name)); - // Then via new String (non-interned) - assertEquals(value, sr.getAttributeValue(null, ""+name)); - - // Then that non-existing ones are not found: - String start = name.substring(0, 1); - assertNull(value, sr.getAttributeValue(null, name+start)); - assertNull(value, sr.getAttributeValue(null, start+name)); - } - assertTokenType(END_ELEMENT, sr.next()); - } - - /** - * @return Stream reader constructed if initialization succeeded (all - * setting supported by the impl); null if some settings (namespace - * awareness) not supported. - */ - private XMLStreamReader getReader(String contents, boolean nsAware) - throws XMLStreamException - { - XMLInputFactory f = getInputFactory(); - if (!setNamespaceAware(f, nsAware)) { - return null; - } - - setCoalescing(f, true); // shouldn't matter - setValidating(f, false); - return constructStreamReader(f, contents); - } -} diff -Nru libwoodstox-java-4.1.3/src/test/org/codehaus/stax/test/stream/TestCDataRead.java libwoodstox-java-5.1.0/src/test/org/codehaus/stax/test/stream/TestCDataRead.java --- libwoodstox-java-4.1.3/src/test/org/codehaus/stax/test/stream/TestCDataRead.java 2012-04-24 04:38:21.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/org/codehaus/stax/test/stream/TestCDataRead.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,193 +0,0 @@ -package org.codehaus.stax.test.stream; - -import javax.xml.stream.*; - -/** - * Unit test suite that tests that the stream reader does in fact - * coalesce adjacent text/CDATA segments when told to do so. - */ -public class TestCDataRead - extends BaseStreamTest -{ - final static String CDATA1; - final static String CDATA2; - static { - StringBuffer sb1 = new StringBuffer(8000); - StringBuffer sb2 = new StringBuffer(8000); - - sb1.append("..."); - sb2.append("\n \n\n "); - - /* Let's add enough stuff to probably cause segmentation... - */ - for (int i = 0; i < 200; ++i) { - String txt = "Round #"+i+"; & that's fun: &x"+i+"; <> %xx; &ent <<< %%% ]> "; - sb1.append(txt); - sb1.append(" "); - sb2.append("\n"); - sb2.append(txt); - } - - CDATA1 = sb1.toString(); - CDATA2 = sb2.toString(); - } - - final static String CDATA3 = " ]] "; - - final static String EXP_CDATA = CDATA1 + CDATA2 + CDATA3; - - final static String VALID_XML = - "" - +"" - +"" - +"" - +"" - +""; - - /** - * This test verifies that no character quoting need (or can) be - * done within CDATA section. - */ - public void testCDataSimple() - throws XMLStreamException - { - String XML = "]]]>"; - String EXP = "<&]>]"; - XMLStreamReader sr = getReader(XML, true); - assertTokenType(START_ELEMENT, sr.next()); - // In coalescing mode, all CDATA are reported as CHARACTERS - assertTokenType(CHARACTERS, sr.next()); - String act = getAndVerifyText(sr); - assertEquals(EXP, act); - assertTokenType(END_ELEMENT, sr.next()); - } - - public void testCDataCoalescing() - throws XMLStreamException - { - XMLStreamReader sr = getReader(VALID_XML, true); - assertTokenType(START_ELEMENT, sr.next()); - // In coalescing mode, all CDATA are reported as CHARACTERS - assertTokenType(CHARACTERS, sr.next()); - String act = getAndVerifyText(sr); - assertEquals(EXP_CDATA, act); - assertTokenType(END_ELEMENT, sr.next()); - } - - public void testCDataNonCoalescing() - throws XMLStreamException - { - XMLStreamReader sr = getReader(VALID_XML, false); - assertTokenType(START_ELEMENT, sr.next()); - int type = sr.next(); - /* 07-Dec-2004, TSa: StAX specs actually allow returning - * CHARACTERS too... - */ - if (type != CHARACTERS) { - assertEquals("Unexpected token type (" - +tokenTypeDesc(type) - +") returned; expected CDATA or CHARACTERS", - CDATA, type); - } - - StringBuffer sb = new StringBuffer(16000); - do { - sb.append(getAndVerifyText(sr)); - type = sr.next(); - } while (type == CDATA || type == CHARACTERS); - assertEquals(EXP_CDATA, sb.toString()); - assertTokenType(END_ELEMENT, sr.getEventType()); - } - - public void testInvalidCData() - throws XMLStreamException - { - String XML = ""; - String MSG = "unfinished CDATA section"; - streamThroughFailing(getReader(XML, false), MSG); - streamThroughFailing(getReader(XML, true), MSG); - - XML = " "; - MSG = "malformed CDATA section"; - streamThroughFailing(getReader(XML, false), MSG); - streamThroughFailing(getReader(XML, true), MSG); - - XML = " "; - streamThroughFailing(getReader(XML, false), MSG); - streamThroughFailing(getReader(XML, true), MSG); - - XML = " "; - streamThroughFailing(getReader(XML, false), MSG); - streamThroughFailing(getReader(XML, true), MSG); - } - - /** - * This unit test verifies that nested CData sections cause - * an error. It is related to another test, which just checks - * that ]]> (with no quoting) is illegal, but parsers may deal - * with them differently. - *

- * Note: this is directly based on XMLTest/SAXTest #735. - */ - public void testInvalidNestedCData() - throws XMLStreamException - { - String XML = "\n\n" - +"\n]]>\n"; - - main_loop: - for (int i = 0; i < 2; ++i) { - boolean coal = (i > 0); - XMLStreamReader sr = getReader(XML, coal); - assertTokenType(START_ELEMENT, sr.next()); - // Ok, now should get an exception... - StringBuffer sb = new StringBuffer(); - int type = -1; - try { - while (true) { - type = sr.next(); - if (type != CDATA && type != CHARACTERS) { - break; - } - sb.append(getAndVerifyText(sr)); - } - } catch (XMLStreamException sex) { - // good - continue; - } catch (RuntimeException rex) { - /* Hmmh. Some implementations may throw a runtime exception, - * if things are lazily parsed (for example, Woodstox). - * But let's allow this only if a nested exception is - * of proper type - */ - Throwable t = rex; - while (t != null) { - if (t instanceof XMLStreamException) { - continue main_loop; - } - t = t.getCause(); - } - fail("Expected an XMLStreamException for nested CDATA section (coalescing: "+coal+"); instead got exception ("+rex.getClass()+"): "+rex.getMessage()); - } - fail("Expected an exception for nested CDATA section (coalescing: "+coal+"); instead got text \""+sb.toString()+"\" (next event "+tokenTypeDesc(type)+")"); - } - } - - /* - //////////////////////////////////////// - // Private methods, other - //////////////////////////////////////// - */ - - private XMLStreamReader getReader(String contents, boolean coalescing) - throws XMLStreamException - { - XMLInputFactory f = getInputFactory(); - setCoalescing(f, coalescing); - setReplaceEntities(f, true); - setValidating(f, false); - return constructStreamReader(f, contents); - } - -} diff -Nru libwoodstox-java-4.1.3/src/test/org/codehaus/stax/test/stream/TestCommentRead.java libwoodstox-java-5.1.0/src/test/org/codehaus/stax/test/stream/TestCommentRead.java --- libwoodstox-java-4.1.3/src/test/org/codehaus/stax/test/stream/TestCommentRead.java 2012-04-24 04:38:21.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/org/codehaus/stax/test/stream/TestCommentRead.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,235 +0,0 @@ -package org.codehaus.stax.test.stream; - -import javax.xml.stream.*; - -/** - * Unit test suite that tests handling of XML comments (except for the - * linefeed normalization which is tested elsewhere); mostly just what - * properties is the stream reader returning when pointing to a comment. - * - * @author Tatu Saloranta - */ -public class TestCommentRead - extends BaseStreamTest -{ - public void testValidComments() - throws XMLStreamException - { - String XML = " "; - streamThrough(getReader(XML, true)); - streamThrough(getReader(XML, false)); - XML = " "; - streamThrough(getReader(XML, true)); - streamThrough(getReader(XML, false)); - } - - /** - * Method that checks properties of COMMENT - * returned by the stream reader are correct according to StAX specs. - */ - public void testCommentProperties() - throws XMLStreamException - { - /* Neither ns-awareness nor dtd-support should make any difference, - * but let's double check them... - */ - doTestProperties(true, true); - doTestProperties(true, false); - doTestProperties(false, true); - doTestProperties(false, false); - } - - public void testInvalidComment() - throws XMLStreamException - { - String XML = " "; - String XML2 = ""; - String XML3 = ""; - - for (int i = 0; i < 1; ++i) { - boolean ns = (i & 1) != 0; - - streamThroughFailing(getReader(XML, ns), - "invalid comment content (embedded \"--\")"); - streamThroughFailing(getReader(XML2, ns), - "malformed comment (extra space)"); - streamThroughFailing(getReader(XML3, ns), - "malformed comment (extra space)"); - } - } - - public void testUnfinishedComment() - throws XMLStreamException - { - String XML = ""; - - XMLStreamReader sr = getReader(XML, true); - try { - // May get an exception when parsing entity declaration... ? - // (since it contains partial token) - assertTokenType(DTD, sr.next()); - assertTokenType(START_ELEMENT, sr.next()); - int type = sr.next(); - if (type != COMMENT) { - reportNADueToEntityExpansion("testRunawayComment", type); - return; - } - type = sr.next(); - fail("Expected an exception for split/runaway comment (instead got event "+tokenTypeDesc(type)+")"); - } catch (XMLStreamException sex) { - // good - } catch (RuntimeException rex) { - // some impls. throw lazy exceptions, too... - } - } - - public void testLongComments() - throws XMLStreamException - { - final String COMMENT1 = - "Some longish comment to see if the input buffer size restrictions might apply here: the reference\nimplementation had problems beyond 256 characters\n" - +" so let's add at least that much, and preferably quite a bit more\n" - +"too... Blah blah yadda yadda: also, unquoted '&' and '<' are kosher here" - +"\nwithout any specific problems or issues." - +" Is this long enough now? :-)" - ; - - String XML = "" -+"" -+"" -+" \n" -+"]>" - ; - XMLStreamReader sr = getReader(XML, true); - assertTokenType(COMMENT, sr.next()); - assertEquals(COMMENT1, getAndVerifyText(sr)); - assertTokenType(PROCESSING_INSTRUCTION, sr.next()); - assertTokenType(DTD, sr.next()); - assertTokenType(START_ELEMENT, sr.next()); - assertEquals("root", sr.getLocalName()); - assertTokenType(COMMENT, sr.next()); - assertEquals(COMMENT1, getAndVerifyText(sr)); - assertTokenType(END_ELEMENT, sr.next()); - } - - /* - //////////////////////////////////////// - // Private methods, shared test code - //////////////////////////////////////// - */ - - private void doTestProperties(boolean nsAware, boolean dtd) - throws XMLStreamException - { - XMLStreamReader sr = getReader("", - nsAware); - assertEquals(COMMENT, sr.next()); - - // Type info - assertEquals(false, sr.isStartElement()); - assertEquals(false, sr.isEndElement()); - assertEquals(false, sr.isCharacters()); - assertEquals(false, sr.isWhiteSpace()); - - // indirect type info - assertEquals(false, sr.hasName()); - assertEquals(true, sr.hasText()); - - assertNotNull(sr.getLocation()); - if (nsAware) { - assertNotNull(sr.getNamespaceContext()); - } - - // And then let's check methods that should throw specific exception - for (int i = 0; i < 8; ++i) { - String method = ""; - - try { - Object result = null; - switch (i) { - case 0: - method = "getName"; - result = sr.getName(); - break; - case 1: - method = "getPrefix"; - result = sr.getPrefix(); - break; - case 2: - method = "getLocalName"; - result = sr.getLocalName(); - break; - case 3: - method = "getNamespaceURI"; - result = sr.getNamespaceURI(); - break; - case 4: - method = "getNamespaceCount"; - result = new Integer(sr.getNamespaceCount()); - break; - case 5: - method = "getAttributeCount"; - result = new Integer(sr.getAttributeCount()); - break; - case 6: - method = "getPITarget"; - result = sr.getPITarget(); - break; - case 7: - method = "getPIData"; - result = sr.getPIData(); - break; - } - fail("Expected IllegalStateException, when calling " - +method+"() for COMMENT"); - } catch (IllegalStateException iae) { - ; // good - } - } - - String content = getAndVerifyText(sr); - assertEquals("comment & ", content); - } - - /* - //////////////////////////////////////// - // Private methods, other - //////////////////////////////////////// - */ - - private XMLStreamReader getReader(String contents, boolean nsAware) - throws XMLStreamException - { - XMLInputFactory f = getInputFactory(); - setCoalescing(f, false); // shouldn't really matter - setNamespaceAware(f, nsAware); - setValidating(f, false); - return constructStreamReader(f, contents); - } -} diff -Nru libwoodstox-java-4.1.3/src/test/org/codehaus/stax/test/stream/TestDoctypeDecl.java libwoodstox-java-5.1.0/src/test/org/codehaus/stax/test/stream/TestDoctypeDecl.java --- libwoodstox-java-4.1.3/src/test/org/codehaus/stax/test/stream/TestDoctypeDecl.java 2012-04-24 04:38:21.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/org/codehaus/stax/test/stream/TestDoctypeDecl.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,362 +0,0 @@ -package org.codehaus.stax.test.stream; - -import java.util.List; - -import javax.xml.stream.*; -import javax.xml.stream.events.EntityDeclaration; -import javax.xml.stream.events.NotationDeclaration; - -/** - * Unit test suite that tests handling of the DOCTYPE declaration event - * (XMLStreamConstants.DTD). - * Note that these tests are all related to the non-validating DTD-aware - * mode: actual validation tests are in separate package. Some of the - * tests are complementary to the validating mode, however, often testing - * explicitly that validity violations are not to be reported as exceptions - * in non-validating mode. - * - * @author Tatu Saloranta - */ -public class TestDoctypeDecl - extends BaseStreamTest -{ - /** - * Method that verifies properties that should be active when - * DTD is the current event. - */ - public void testProperties() - throws XMLStreamException - { - doTestProperties(false); - doTestProperties(true); - } - - public void testMinimalValidDecl() - throws XMLStreamException - { - doTestMinimalValid(false); - doTestMinimalValid(true); - } - - public void testSimpleValidDecl() - throws XMLStreamException - { - doTestSimpleValid(false); - doTestSimpleValid(true); - } - - public void testTypicalValid() - throws XMLStreamException - { - doTestTypicalValid(false); - doTestTypicalValid(true); - } - - public void testSimpleInvalidDecl() - throws XMLStreamException - { - doTestSimpleInvalid(false); - doTestSimpleInvalid(true); - } - - final static String UNPARSED_ENTITY_XML = - "\n" - +"\n" - +"]>"; - - - public void testSimpleEntity() - throws XMLStreamException - { - XMLStreamReader sr = getReader(UNPARSED_ENTITY_XML, true); - assertTokenType(DTD, sr.next()); - List l = (List) sr.getProperty("javax.xml.stream.entities"); - assertNotNull(l); - assertEquals(1, l.size()); - EntityDeclaration ed = (EntityDeclaration) l.get(0); - assertEquals("unp", ed.getName()); - assertEquals("mynot", ed.getNotationName()); - - sr.close(); - } - - public void testSimpleNotation() - throws XMLStreamException - { - XMLStreamReader sr = getReader(UNPARSED_ENTITY_XML, true); - assertTokenType(DTD, sr.next()); - List l = (List) sr.getProperty("javax.xml.stream.notations"); - assertNotNull(l); - assertEquals(1, l.size()); - NotationDeclaration nd = (NotationDeclaration) l.get(0); - assertEquals("mynot", nd.getName()); - } - - /** - * This test specifically checks to see that xml validation is - * only to be done when enabled; not just because DTD-awareness - * is enabled. - */ - public void testNonVldWithEmptyContentModel() - throws XMLStreamException - { - final boolean NS = true; - final String XML1 = - "\n" - +"\n" - +"]>" - +""; - final String XML2 = ""; - - // First, let's verify regular text is ok - XMLStreamReader sr = getReader(XML1 + "some text" + XML2, NS); - assertTokenType(DTD, sr.next()); - assertTokenType(START_ELEMENT, sr.next()); - assertTokenType(CHARACTERS, sr.next()); - streamThrough(sr); - sr.close(); - - // Then that char/general entities are - sr = getReader(XML1 + "&" + XML2, NS); - assertTokenType(DTD, sr.next()); - streamThrough(sr); - sr.close(); - - /* And then that a (declared) element is fine too - * (undeclared should be, too, but there's separate test - * elsewhere for that) - */ - sr = getReader(XML1 + "" + XML2, NS); - assertTokenType(DTD, sr.next()); - streamThrough(sr); - sr.close(); - } - - public void testNonVldWithNonMixedContentModel() - throws XMLStreamException - { - final boolean NS = true; - final String XML1 = - "\n" - +"\n" - +"]>" - +""; - final String XML2 = ""; - - XMLStreamReader sr = getReader(XML1 + "some text" + XML2, NS); - assertTokenType(DTD, sr.next()); - assertTokenType(START_ELEMENT, sr.next()); - assertTokenType(CHARACTERS, sr.next()); - streamThrough(sr); - sr.close(); - - // Then that entities are ok too - sr = getReader(XML1 + "& xxx" + XML2, NS); - assertTokenType(DTD, sr.next()); - streamThrough(sr); - sr.close(); - } - - /* - //////////////////////////////////////// - // Private methods, shared test code - //////////////////////////////////////// - */ - - private void doTestProperties(boolean nsAware) - throws XMLStreamException - { - final String PROP_TEST = - " ]>"; - - XMLStreamReader sr = getReader(PROP_TEST, nsAware); - assertEquals(DTD, sr.next()); - // Type info - assertEquals(false, sr.isStartElement()); - assertEquals(false, sr.isEndElement()); - assertEquals(false, sr.isCharacters()); - assertEquals(false, sr.isWhiteSpace()); - - // indirect type info - assertEquals(false, sr.hasName()); - assertEquals(true, sr.hasText()); - - // And then let's check methods that should throw specific exception - for (int i = 0; i <= 10; ++i) { - String method = ""; - - try { - Object result = null; - switch (i) { - case 0: - method = "getName"; - result = sr.getName(); - break; - case 1: - method = "getPrefix"; - result = sr.getPrefix(); - break; - case 2: - method = "getLocalName"; - result = sr.getLocalName(); - break; - case 3: - method = "getNamespaceURI"; - result = sr.getNamespaceURI(); - break; - case 4: - method = "getNamespaceCount"; - result = new Integer(sr.getNamespaceCount()); - break; - case 5: - method = "getAttributeCount"; - result = new Integer(sr.getAttributeCount()); - break; - case 6: - method = "getPITarget"; - result = sr.getPITarget(); - break; - case 7: - method = "getPIData"; - result = sr.getPIData(); - break; - case 8: - method = "getTextCharacters"; - result = sr.getTextCharacters(); - break; - case 9: - method = "getTextStart"; - result = new Integer(sr.getTextStart()); - break; - case 10: - method = "getTextLength"; - result = new Integer(sr.getTextLength()); - break; - } - fail("Expected IllegalStateException, when calling " - +method+"() for DTD"); - } catch (IllegalStateException iae) { - ; // good - } - } - - /* Here let's only check it's not null or empty, not exact contents - * (there are other tests for checking contents) - */ - String str = sr.getText(); - if (str == null || str.trim().length() == 0) { - fail("Internal subset not available; StreamReader.getText() returned an empty String (after trim())"); - } - } - - private void doTestMinimalValid(boolean nsAware) - throws XMLStreamException - { - final String VALID_TEST = ""; - - XMLStreamReader sr = getReader(VALID_TEST, nsAware); - - assertEquals(DTD, sr.next()); - assertEquals(START_ELEMENT, sr.next()); - } - - private void doTestSimpleValid(boolean nsAware) - throws XMLStreamException - { - final String INT_SUBSET = ""; - final String VALID_TEST = - ""; - - XMLStreamReader sr = getReader(VALID_TEST, nsAware); - assertTokenType(DTD, sr.next()); - - /* Now... exactly what should be returned is not quite clear. - * Let's assume that leading/trailing white space may be truncated, - * but that otherwise we'll get stuff back, with linefeeds - * normalized? - */ - String str = getAndVerifyText(sr).trim(); - - /* 16-Aug-2004, TSa: Hmmh. Specs are bit confusing; in some places - * claiming it should be only the internal subset, in others that - * it should be the full DOCTYPE declaration production... - */ - assertEquals(INT_SUBSET, str); - - sr.close(); - - /* 05-Apr-2006, TSa: Following is actually invalid, but - * well-formed. And as such, it should not throw an exception - * in non-validating mode (but should in validating mode). - */ - final String VALID_TEST2 = ""; - sr = getReader(VALID_TEST2, nsAware); - assertTokenType(DTD, sr.next()); - assertTokenType(START_ELEMENT, sr.next()); - assertEquals("fubar", sr.getLocalName()); - assertTokenType(END_ELEMENT, sr.next()); - assertTokenType(END_DOCUMENT, sr.next()); - - - } - - private void doTestTypicalValid(boolean nsAware) - throws XMLStreamException - { - final String VALID_TEST = "\n" - +"\n" - +"]>\n" - +""; - - XMLStreamReader sr = getReader(VALID_TEST, nsAware); - - assertTokenType(DTD, sr.next()); - // May or may not get SPACE... if we get it, will skip - int type; - while ((type = sr.next()) == SPACE) { - ; - } - assertTokenType(START_ELEMENT, type); - } - - private void doTestSimpleInvalid(boolean nsAware) - throws XMLStreamException - { - final String INVALID1 = " "; - streamThroughFailing(getReader(INVALID1, nsAware), - "invalid DOCTYPE declaration (missing root element)"); - - final String INVALID3 = ""; - streamThroughFailing(getReader(INVALID3, nsAware), - "invalid DOCTYPE declaration (missing SYSTEM identifier for DTD)"); - - final String INVALID4 = ""; - streamThroughFailing(getReader(INVALID4, nsAware), - "invalid DOCTYPE declaration (missing PUBLIC identifier for DTD)"); - - final String INVALID5 = ""; - streamThroughFailing(getReader(INVALID5, nsAware), - "invalid DOCTYPE declaration (unexpected ampersand character)"); - } - - /* - //////////////////////////////////////// - // Private methods, other - //////////////////////////////////////// - */ - - private XMLStreamReader getReader(String contents, boolean nsAware) - throws XMLStreamException - { - XMLInputFactory f = getInputFactory(); - setCoalescing(f, false); // shouldn't matter - setNamespaceAware(f, nsAware); - setValidating(f, false); - setSupportDTD(f, true); - return constructStreamReader(f, contents); - } -} diff -Nru libwoodstox-java-4.1.3/src/test/org/codehaus/stax/test/stream/TestElements.java libwoodstox-java-5.1.0/src/test/org/codehaus/stax/test/stream/TestElements.java --- libwoodstox-java-4.1.3/src/test/org/codehaus/stax/test/stream/TestElements.java 2012-04-24 04:38:21.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/org/codehaus/stax/test/stream/TestElements.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,366 +0,0 @@ -package org.codehaus.stax.test.stream; - -import javax.xml.namespace.*; -import javax.xml.stream.*; - -/** - * Unit test suite that tests handling of XML elements, both in namespace - * aware and non-namespace modes. - * - * @author Tatu Saloranta - */ -public class TestElements - extends BaseStreamTest -{ - /** - * Method that checks properties of START_ELEMENT and END_ELEMENT - * returned by the stream reader are correct according to StAX specs. - */ - public void testNsProperties() - throws XMLStreamException - { - testProperties(true, "testNsProperties"); - } - - public void testNonNsProperties() - throws XMLStreamException - { - testProperties(false, "testNonNsProperties"); - } - - /** - * Does test for simple element structure in namespace aware mode - */ - public void testValidNsElems() - throws XMLStreamException - { - testValid(true, "testValidNsElems"); - } - - public void testValidNonNsElems() - throws XMLStreamException - { - testValid(false, "testValidNonNsElems"); - } - - public void testInvalidNsElems() - throws XMLStreamException - { - testInvalid(true, "testInvalidNsElems"); - } - - public void testInvalidNonNsElems() - throws XMLStreamException - { - testInvalid(false, "testInvalidNonNsElems"); - } - - public void testEmptyDocument() - throws XMLStreamException - { - String EMPTY_XML = " "; - - // Empty documents are not valid (missing root element) - - streamThroughFailing(getElemReader(EMPTY_XML, true), - "empty document (not valid, missing root element)"); - - XMLStreamReader sr = getElemReader(EMPTY_XML, false); - if (sr != null) { // only if non-ns-aware mode supported - streamThroughFailing(sr, - "empty document (not valid, missing root element)"); - } - } - - public void testNoRootDocument() - throws XMLStreamException - { - String NOROOT_XML = "\n" - +" "; - - // Documents without root are not valid - streamThroughFailing(getElemReader(NOROOT_XML, true), - "document without root element"); - - XMLStreamReader sr = getElemReader(NOROOT_XML, false); - if (sr != null) { // only if non-ns-aware mode supported - streamThroughFailing(sr, "document without root element"); - } - } - - public void testInvalidEmptyElem() - throws XMLStreamException - { - String XML = " "; - String MSG = "malformed empty element (space between '/' and '>')"; - - streamThroughFailing(getElemReader(XML, true), MSG); - - XMLStreamReader sr = getElemReader(XML, false); - if (sr != null) { // only if non-ns-aware mode supported - streamThroughFailing(sr, MSG); - } - } - - /* - //////////////////////////////////////// - // Private methods, shared test code - //////////////////////////////////////// - */ - - private void testProperties(boolean nsAware, String method) - throws XMLStreamException - { - XMLStreamReader sr = getElemReader("", nsAware); - if (sr == null) { - reportNADueToNS(method); - return; - } - - assertEquals(START_ELEMENT, sr.next()); - testStartOrEnd(nsAware, sr, true); - - assertEquals(END_ELEMENT, sr.next()); - testStartOrEnd(nsAware, sr, false); - } - - private void testStartOrEnd(boolean nsAware, XMLStreamReader sr, - boolean isStart) - throws XMLStreamException - { - int evtType = isStart ? START_ELEMENT : END_ELEMENT; - assertEquals(evtType, sr.getEventType()); - String eventStr = tokenTypeDesc(evtType); - - // simple type info - assertEquals(isStart, sr.isStartElement()); - assertEquals(!isStart, sr.isEndElement()); - assertEquals(false, sr.isCharacters()); - assertEquals(false, sr.isWhiteSpace()); - - // indirect type info - assertEquals(true, sr.hasName()); - assertEquals(false, sr.hasText()); - - assertNotNull(sr.getLocation()); - QName n = sr.getName(); - assertNotNull(n); - assertEquals("root", n.getLocalPart()); - /* 07-Sep-2007, TSa: The current thinking within Stax community - * is that empty String is the right answer for all unbound - * prefixes and namespace URIs, unless explicitly defined - * that null is to be used for individual methods. - */ - assertEquals("", n.getPrefix()); - assertNoNsURI(sr); - - if (isStart) { - assertEquals(0, sr.getAttributeCount()); - } else { - try { - int count = sr.getAttributeCount(); - fail("Expected an IllegalStateException when trying to call getAttributeCount() for "+eventStr); - } catch (IllegalStateException e) { - // good - } - } - assertEquals(0, sr.getNamespaceCount()); - if (nsAware) { - /* but how about if namespaces are not supported? Can/should - * it return null? - */ - assertNotNull(sr.getNamespaceContext()); - } - - for (int i = 0; i < 4; ++i) { - String method = ""; - - try { - Object result = null; - switch (i) { - case 0: - method = "getText"; - result = sr.getText(); - break; - case 1: - method = "getTextCharacters"; - result = sr.getTextCharacters(); - break; - case 2: - method = "getPITarget"; - result = sr.getPITarget(); - break; - case 3: - method = "getPIData"; - result = sr.getPIData(); - break; - } - fail("Expected IllegalStateException, when calling "+method+"() for "+eventStr); - } catch (IllegalStateException iae) { - ; // good - } - } - } - - private void testValid(boolean nsAware, String method) - throws XMLStreamException - { - final String NS_URL1 = "http://www.stax.org"; - final String NS_PREFIX1 = "prefix1"; - - final String NS_URL2 = "urn://mydummyid"; - final String NS_PREFIX2 = "prefix2"; - - final String VALID_CONTENT - = "<"+NS_PREFIX1+":elem xmlns:"+NS_PREFIX1 - +"='"+NS_URL1+"' "+NS_PREFIX1+":attr='value'>Text" - +"" - +""; - - /* First of all, let's check that it can be completely - * parsed: - */ - XMLStreamReader sr = getElemReader(VALID_CONTENT, nsAware); - if (sr == null) { - reportNADueToNS(method); - return; - } - - streamThrough(sr); - - // And then let's do it step by step - sr = getElemReader(VALID_CONTENT, nsAware); - - // First, need to get - assertTokenType(START_ELEMENT, sr.next()); - assertEquals("root", sr.getLocalName()); - assertNoPrefix(sr); - assertNoNsURI(sr); - - // Let's also check QName seems valid: - QName name = sr.getName(); - assertNotNull("Shouldn't get null QName for any start element", name); - assertEquals(name, new QName("root")); - assertNoNsURI(sr); - assertEquals(0, sr.getAttributeCount()); - assertEquals(0, sr.getNamespaceCount()); - - // And then - assertEquals(START_ELEMENT, sr.next()); - if (nsAware) { - assertEquals("elem", sr.getLocalName()); - assertEquals(NS_PREFIX1, sr.getPrefix()); - assertEquals(NS_URL1, sr.getNamespaceURI()); - } else { - assertEquals(NS_PREFIX1+":elem", sr.getLocalName()); - assertNoPrefix(sr); - assertNoNsURI(sr); - } - - int expNs = nsAware ? 1 : 0; - int expAttr = nsAware ? 1 : 2; - - /* Let's just check counts, not values; attribute test can - * do thorough tests for values and access - */ - assertEquals(expAttr, sr.getAttributeCount()); - assertEquals(expNs, sr.getNamespaceCount()); - - assertEquals(CHARACTERS, sr.next()); - assertEquals("Text", getAndVerifyText(sr)); - - assertEquals(END_ELEMENT, sr.next()); - if (nsAware) { - assertEquals("elem", sr.getLocalName()); - assertEquals(NS_PREFIX1, sr.getPrefix()); - assertEquals(NS_URL1, sr.getNamespaceURI()); - } else { - assertEquals(NS_PREFIX1+":elem", sr.getLocalName()); - assertNoPrefix(sr); - assertNoNsURI(sr); - } - assertEquals(expNs, sr.getNamespaceCount()); - - assertEquals(START_ELEMENT, sr.next()); - assertEquals("elem2", sr.getLocalName()); - - assertNoPrefix(sr); - if (nsAware) { - assertEquals(NS_URL2, sr.getNamespaceURI()); - } else { - assertNoNsURI(sr); - } - assertEquals(expAttr, sr.getAttributeCount()); - assertEquals(expNs, sr.getNamespaceCount()); - - assertEquals(END_ELEMENT, sr.next()); - assertEquals("elem2", sr.getLocalName()); - - assertNoPrefix(sr); - if (nsAware) { - assertEquals(NS_URL2, sr.getNamespaceURI()); - } else { - assertNoNsURI(sr); - } - assertEquals(expNs, sr.getNamespaceCount()); - - assertEquals(END_ELEMENT, sr.next()); - assertEquals("root", sr.getLocalName()); - assertNoNsURI(sr); - assertNoPrefix(sr); - assertEquals(0, sr.getNamespaceCount()); - } - - /** - * Simple tests to check for incorrect nesting - */ - private void testInvalid(boolean nsAware, String method) - throws XMLStreamException - { - // Wrong end element: - String XML = " text "; - - XMLStreamReader sr = getElemReader(XML, nsAware); - if (sr == null) { - reportNADueToNS(method); - return; - } - - streamThroughFailing(sr, "incorrect nesting (wrong end element name)"); - - // For namespace mode, has to be same prefix (not just same URI) - if (nsAware) { - XML = " text "; - sr = getElemReader(XML, nsAware); - streamThroughFailing(sr, "incorrect nesting (namespace prefix in close element not the same as in start element)"); - } - - // Missing end element: - XML = " text "; - streamThroughFailing(getElemReader(XML, nsAware), - "incorrect nesting (missing end element)"); - - // More than one root: - XML = ""; - streamThroughFailing(getElemReader(XML, nsAware), - "more than one root element"); - } - - /* - //////////////////////////////////////// - // Private methods, other - //////////////////////////////////////// - */ - - private XMLStreamReader getElemReader(String contents, boolean nsAware) - throws XMLStreamException - { - XMLInputFactory f = getInputFactory(); - if (!setNamespaceAware(f, nsAware)) { - return null; - } - setCoalescing(f, true); - setValidating(f, false); - return constructStreamReader(f, contents); - } -} diff -Nru libwoodstox-java-4.1.3/src/test/org/codehaus/stax/test/stream/TestEncodingRead.java libwoodstox-java-5.1.0/src/test/org/codehaus/stax/test/stream/TestEncodingRead.java --- libwoodstox-java-4.1.3/src/test/org/codehaus/stax/test/stream/TestEncodingRead.java 2012-04-24 04:38:21.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/org/codehaus/stax/test/stream/TestEncodingRead.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,212 +0,0 @@ -package org.codehaus.stax.test.stream; - -import java.io.*; - -import javax.xml.stream.*; - -/** - * Unit test suite that tests handling of text encoding, as specified - * by XML declaration and/or specific byte-order markers. - */ -public class TestEncodingRead - extends BaseStreamTest -{ - public TestEncodingRead(String name) { - super(name); - } - - final String UTF_1 = String.valueOf((char) 0x41); // 'A' - final String UTF_2 = String.valueOf((char) 0xA0); // nbsp - final String UTF_3 = String.valueOf((char) 0xB61); // some char that needs 3-byte encoding - - final String UTF_CONTENT = "" - +UTF_1 + UTF_2 + UTF_3 - +UTF_1 + UTF_1 + UTF_2 + UTF_2 + UTF_3 + UTF_3 - +UTF_3 + UTF_3 + UTF_2 + UTF_2 + UTF_1 + UTF_1 - +UTF_1 + UTF_3 + UTF_2 - +UTF_2 + UTF_1 + UTF_3 - +UTF_2 + UTF_3 + UTF_1 - +UTF_3 + UTF_1 + UTF_2 - +UTF_3 + UTF_2 + UTF_1 - ; - - final static byte[] BE_BOM = new byte[] { (byte) 0xFE, (byte) 0xFF }; - final static byte[] LE_BOM = new byte[] { (byte) 0xFF, (byte) 0xFE }; - final static byte[] UTF8_BOM = new byte[] { (byte) 0xEF, (byte) 0xBB, (byte) 0xBF }; - - /** - * Test to check that UTF-8 stream with no leading BOM is succesfully - * handled by parser. - */ - public void testUTF8() - throws Exception - { - doTestEncoding("UTF-8", "UTF-8", null); - doTestEncoding("UTF-8", null, null); - } - - /** - * Test to check that UTF-8 stream with leading BOM is succesfully - * handled by parser. - */ - public void testUTF8WithBOM() - throws Exception - { - doTestEncoding("UTF-8", "UTF-8", UTF8_BOM); - doTestEncoding("UTF-8", null, UTF8_BOM); - } - - public void testUTF8Surrogates() - throws XMLStreamException, IOException - { - String XML = "XXXX"; - int ix = XML.indexOf('X'); - byte[] src = XML.getBytes("UTF-8"); - - // A somewhat random high-order Unicode char: - src[ix] = (byte)0xF1; - src[ix+1] = (byte)0x90; - src[ix+2] = (byte)0x88; - src[ix+3] = (byte)0x88; - - InputStream in = new ByteArrayInputStream(src); - XMLInputFactory f = getInputFactory(); - XMLStreamReader sr = f.createXMLStreamReader(in); - - assertTokenType(START_ELEMENT, sr.next()); - assertEquals("root", sr.getLocalName()); - assertTokenType(CHARACTERS, sr.next()); - String str = getAndVerifyText(sr); - // Should result in a surrogate pair... - assertEquals(2, str.length()); - assertEquals((char) 0xd900, str.charAt(0)); - assertEquals((char) 0xde08, str.charAt(1)); - assertTokenType(END_ELEMENT, sr.next()); - } - - public void testUTF16BEWithBOM() - throws XMLStreamException, - UnsupportedEncodingException - { - doTestEncoding("UTF-16BE", "UTF-16", BE_BOM); - doTestEncoding("UTF-16BE", null, BE_BOM); - - doTestEncoding2(true); - } - - public void testUTF16LEWithBOM() - throws XMLStreamException, - UnsupportedEncodingException - { - doTestEncoding("UTF-16LE", "UTF-16", LE_BOM); - doTestEncoding("UTF-16LE", null, LE_BOM); - - doTestEncoding2(false); - } - - /* - //////////////////////////////////////// - // Private methods, shared test code - //////////////////////////////////////// - */ - - /** - * @param javaEnc Name of encoding as understood by JDK; used to - * instantiate JDK encoder/decoder to use for test - * @param xmlEnc Name of encoding as included in xml declaration; - * null to indicate nothing should be added - * @param bom Pre-defined bom bytes to prepend to input, if any. - */ - public void doTestEncoding(String javaEnc, String xmlEnc, - byte[] bom) - throws XMLStreamException, - UnsupportedEncodingException - { - String XML = ""+UTF_CONTENT+""; - - byte[] b = XML.getBytes(javaEnc); - if (bom != null) { - byte[] orig = b; - b = new byte[b.length + bom.length]; - System.arraycopy(bom, 0, b, 0, bom.length); - System.arraycopy(orig, 0, b, bom.length, orig.length); - } - - XMLStreamReader sr = getReader(b); - - if (xmlEnc != null) { - assertEquals(xmlEnc, sr.getCharacterEncodingScheme()); - } else { - /* otherwise... should we get some info? Preferably yes; - * (getEncoding() should return auto-detected encoding) - * but this is not strictly mandated by the specs? - */ - } - - assertEquals(START_ELEMENT, sr.next()); - assertEquals(CHARACTERS, sr.next()); - - assertEquals(UTF_CONTENT, getAllText(sr)); - - assertEquals(END_ELEMENT, sr.getEventType()); - assertEquals(END_DOCUMENT, sr.next()); - } - - private void doTestEncoding2(boolean bigEndian) - throws XMLStreamException - { - - /* 20-Jan-2006, TSa: Ok, let's try another variation that may - * causes problem; UTF-16 is vague, and if using JDK provided - * readers, parser has to indicate endianness. - */ - final String XML = "\n" - +"text"; - int len = XML.length(); - byte[] b = new byte[2 + len + len]; - - if (bigEndian) { - b[0] = (byte) 0xFE; - b[1] = (byte) 0xFF; - } else { - b[0] = (byte) 0xFF; - b[1] = (byte) 0xFE; - } - - int offset = bigEndian ? 3 : 2; - for (int i = 0; i < len; ++i) { - b[offset + i + i] = (byte) XML.charAt(i); - } - XMLStreamReader sr = getReader(b); - // may get white space... - int type = sr.next(); - if (type == SPACE) { - type = sr.next(); - } - assertTokenType(COMMENT, type); - assertTokenType(START_ELEMENT, sr.next()); - assertTokenType(CHARACTERS, sr.next()); - assertEquals("text", getAndVerifyText(sr)); - assertTokenType(END_ELEMENT, sr.next()); - sr.close(); - } - - /* - //////////////////////////////////////// - // Private methods, other - //////////////////////////////////////// - */ - - private XMLStreamReader getReader(byte[] contents) - throws XMLStreamException - { - XMLInputFactory f = getInputFactory(); - setValidating(f, false); - return constructStreamReader(f, contents); - } -} diff -Nru libwoodstox-java-4.1.3/src/test/org/codehaus/stax/test/stream/TestEntityRead.java libwoodstox-java-5.1.0/src/test/org/codehaus/stax/test/stream/TestEntityRead.java --- libwoodstox-java-4.1.3/src/test/org/codehaus/stax/test/stream/TestEntityRead.java 2012-04-24 04:38:21.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/org/codehaus/stax/test/stream/TestEntityRead.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,633 +0,0 @@ -package org.codehaus.stax.test.stream; - -import javax.xml.stream.*; - -import org.codehaus.stax.test.SimpleResolver; - -/** - * Unit test suite that tests handling of various kinds of entities. - */ -public class TestEntityRead - extends BaseStreamTest -{ - public TestEntityRead(String name) { - super(name); - } - - /** - * Method that tests properties of unresolved DTD event. - */ - public void testEntityProperties() - throws XMLStreamException - { - // Ns-awareness should make no different, but let's double-check it: - doTestProperties(true); - doTestProperties(false); - } - - public void testValidPredefdEntities() - throws XMLStreamException - { - String EXP = "Testing \"this\" & 'that' !? !"; - String XML = "Testing "this" & 'that' !? !"; - - XMLStreamReader sr = getReader(XML, false, true, true); - - assertTokenType(START_ELEMENT, sr.next()); - assertTokenType(CHARACTERS, sr.next()); - - // Let's not count on coalescing working, though... - StringBuffer sb = new StringBuffer(getAndVerifyText(sr)); - int type; - - while ((type = sr.next()) == CHARACTERS) { - sb.append(getAndVerifyText(sr)); - } - assertEquals(EXP, sb.toString()); - assertTokenType(END_ELEMENT, type); - } - - /** - * This unit test checks that handling of character entities works - * as expected, including corner cases like characters that expand - * to surrogate pairs in Java. - */ - public void testValidCharEntities() - throws XMLStreamException - { - String XML = "surrogates: 񐀀."; - XMLStreamReader sr = getReader(XML, true, true, true); - - assertTokenType(START_ELEMENT, sr.next()); - assertTokenType(CHARACTERS, sr.next()); - // may still be split, though (buggy coalescing) - StringBuffer sb = new StringBuffer(getAndVerifyText(sr)); - int type; - - while ((type = sr.next()) == CHARACTERS) { - sb.append(getAndVerifyText(sr)); - } - String result = sb.toString(); - String exp = "surrogates: \uD900\uDC00."; - - if (!exp.equals(result)) { - failStrings("Expected character entity &x#50000 to expand to surrogate pair with chars 0xD900 and 0xDC00", exp, result); - } - - assertTokenType(END_ELEMENT, type); - sr.close(); - } - - public void testValidGeneralEntities() - throws XMLStreamException - { - String EXP = "y yabc abc&"; - String XML = "\n" - +"" - +"" - +"]>\n" - +"&x; &both; &aa;&myAmp;"; - - XMLStreamReader sr = getReader(XML, false, true, true); - - assertTokenType(DTD, sr.next()); - int type = sr.next(); - if (type == SPACE) { - type = sr.next(); - } - assertTokenType(START_ELEMENT, type); - try { - assertTokenType(CHARACTERS, sr.next()); - } catch (XMLStreamException xse) { - fail("Expected succesful entity expansion, got: "+xse); - } - - String actual = getAndVerifyText(sr); - assertEquals(EXP, actual); - - /* !!! TBI: test things like: - * - * - Allow using single and double quotes in entity expansion value - * via param entity expansion (see next entry) - * - Rules for expanding char entities vs. generic entities (esp. - * regarding parameter entities) - */ - } - - /** - * Test that checks that generic parsed entities are returned as - * entity reference events, when automatic entity expansion is disabled. - */ - public void testUnexpandedEntities() - throws XMLStreamException - { - String XML = "]>\n" - +"&Start"&myent;End!"; - - XMLStreamReader sr = getReader(XML, false, true, false); - - assertTokenType(DTD, sr.next()); - int type = sr.next(); - - // May or may not get SPACE events in epilog (before root) - while (type == SPACE) { - type = sr.next(); - } - - assertTokenType(START_ELEMENT, type); - - assertTokenType(CHARACTERS, sr.next()); - assertEquals("&Start\"", getAndVerifyText(sr)); - - assertTokenType(ENTITY_REFERENCE, sr.next()); - assertEquals("myent", sr.getLocalName()); - assertEquals("data", getAndVerifyText(sr)); - - assertTokenType(CHARACTERS, sr.next()); - assertEquals("End!", getAndVerifyText(sr)); - - assertTokenType(END_ELEMENT, sr.next()); - assertTokenType(END_DOCUMENT, sr.next()); - - /* And then, for good measure, let's just do a longer - * one, but without exact type checks, and both with and - * without coalescing: - */ - - XML = "]>\n" - +"&Start"&myent;End!\n" - +" !&myent;&myent;&myent;&" - +""; - - // First, no coalescing - sr = getReader(XML, false, false, false); - streamThrough(sr); - - // then with coalescing - sr = getReader(XML, false, true, false); - streamThrough(sr); - } - - public void testUnexpandedEntities2() - throws XMLStreamException - { - /* Note: as per XML 1.0 specs, non-char entities (including pre-defined - * entities like 'amp' and 'lt'!) are not to be expanded before entity - * that contains them is expanded... so they are returned unexpanded. - * Char entities, however, are to be expanded. - */ - String ENTITY_VALUE = "Something slightly longer & challenging\nwhich may or may not work"; - String XML = "]>" - +"&myent;"; - - XMLStreamReader sr = getReader(XML, false, true, false); - - assertTokenType(DTD, sr.next()); - assertTokenType(START_ELEMENT, sr.next()); - assertTokenType(ENTITY_REFERENCE, sr.next()); - assertEquals("myent", sr.getLocalName()); - - // Ok, let's try the other access method: - /* 05-Apr-2006, TSa: Actually, getTextXxx() methods are not - * legal for ENTITY_REFERENCEs, can't check: - */ - /* - int len = sr.getTextLength(); - assertEquals(ENTITY_VALUE.length(), len); - int start = sr.getTextStart(); - char[] ch = new char[len]; - sr.getTextCharacters(0, ch, 0, len); - assertEquals(ENTITY_VALUE, new String(ch)); - */ - assertEquals(ENTITY_VALUE, sr.getText()); - - assertTokenType(END_ELEMENT, sr.next()); - assertTokenType(END_DOCUMENT, sr.next()); - } - - /** - * Test that checks that entities that expand to elements, comments - * and processing instructions are properly handled. - */ - public void testElementEntities() - throws XMLStreamException - { - String XML = "text'>\n" - +" '>\n" - +" '>\n" - +" \n" - +" \n" - +"]>\n" - +"&ent1;&ent2;&ent3;&ent4a;"; - - XMLStreamReader sr = getReader(XML, true, true, true); - - assertTokenType(DTD, sr.next()); - // May or may not get whitespace - int type = sr.next(); - if (type == SPACE) { - type = sr.next(); - } - assertTokenType(START_ELEMENT, type); - assertEquals("root", sr.getLocalName()); - - // First, entity that expands to element - try { - type = sr.next(); - } catch (XMLStreamException xse) { - fail("Expected succesful entity expansion, got: "+xse); - } - if (type != START_ELEMENT) { // failure - if (type == ENTITY_REFERENCE) { // most likely failure? - fail("Implementation fails to re-parse general entity expansion text: instead of element , received entity reference &"+sr.getLocalName()+";"); - } - if (type == CHARACTERS) { - String text = sr.getText(); - fail("Implementation fails to re-parse general entity expansion text: instead of element , received text ["+text.length()+"]: '"+text+"'"); - } - assertTokenType(START_ELEMENT, type); - } - assertEquals("tag", sr.getLocalName()); - assertTokenType(CHARACTERS, sr.next()); - assertEquals("text", sr.getText()); - assertTokenType(END_ELEMENT, sr.next()); - assertEquals("tag", sr.getLocalName()); - - // Then one that expands to comment - assertTokenType(COMMENT, sr.next()); - assertEquals("comment", sr.getText()); - - // Then one that expands to a PI - assertTokenType(PROCESSING_INSTRUCTION, sr.next()); - assertEquals("proc", sr.getPITarget()); - assertEquals("instr", sr.getPIData().trim()); - - // Then one that expands to text (single char) - assertTokenType(CHARACTERS, sr.next()); - assertEquals("A", sr.getText()); - - assertTokenType(END_ELEMENT, sr.next()); - assertEquals("root", sr.getLocalName()); - } - - /** - * Test that verifies that it is possible to quote CDATA end marker - * ("]]>") using character and general entities. - */ - public void testQuotedCDataEndMarker() - throws XMLStreamException - { - try { - // First, using pre-defined/char entities - String XML = "" - +"Ok the usual one: ]]>" - +" and then alternatives: ]]>" - +", ]]>" - +""; - XMLStreamReader sr = getReader(XML, true, false, true); - streamThrough(sr); - } catch (Exception e) { - fail("Didn't except problems with pre-def/char entity quoted ']]>'; got: "+e); - } - - try { - // Then using general entities: - String XML = "\n" - +"]>\n" - +"" - +" &doubleBracket;> and &doubleBracket;>" - +""; - XMLStreamReader sr = getReader(XML, true, false, true); - streamThrough(sr); - } catch (Exception e) { - fail("Didn't except problems with general entity quoted ']]>'; got: "+e); - } - } - - /** - * Test that ensures that entities can have quotes in them, if quotes - * are expanded from (parameter) entities. For that need to use - * external entities, or at least ext. subset. - */ - /* - public void testValidEntityWithQuotes() - throws XMLStreamException - { - } - */ - - public void testInvalidEntityUndeclared() - throws XMLStreamException - { - XMLStreamReader sr = getReader("&myent;", - true, false, true); - try { - streamThrough(sr); - fail("Expected an exception for invalid comment content"); - } catch (Exception e) { } - } - - public void testInvalidEntityRecursive() - throws XMLStreamException - { - XMLStreamReader sr = getReader - ("\n" - +"\n" - +"]> &ent1;", - false, true, true); - - streamThroughFailing(sr, "recursive general entity/ies"); - - /* !!! TBI: test things like: - * - * - Incorrectly nested entities (only start element, no end etc) - */ - } - - public void testInvalidEntityPEInIntSubset() - throws XMLStreamException - { - /* Although PEs are allowed in int. subset, they can only be - * used to replace whole declarations; not in entity value - * expansions. - */ - XMLStreamReader sr = getReader - ("\n" - +"\n" - +"]> ", - false, true, true); - - streamThroughFailing(sr, "declaring a parameter entity in the internal DTD subset"); - } - - /** - * Test that ensures that an invalid 'partial' entity is caught; - * partial meaning that only beginning part of an entity (ie ampersand - * and zero or more of the first characters of entity id) come from - * another expanded entity, and rest comes from content following. - * Such partial entities are not legal according to XML specs. - */ - public void testInvalidEntityPartial() - throws XMLStreamException - { - XMLStreamReader sr = getReader - ("\n" - +"]>&partial;;", - false, false, true); - - /* Hmmh. Actually, fully conforming implementations should throw - * an exception when parsing internal DTD subset. But better - * late than never; it's ok to fail on expansion too, as far as - * this test is concerned. - */ - int type1, type2; - int lastType; - - try { - type1 = sr.next(); - type2 = sr.next(); - while ((lastType = sr.next()) == CHARACTERS) { - ; - } - } catch (XMLStreamException e) { - return; // ok - } catch (RuntimeException e) { // some impls throw lazy exceptions - return; // ok - } - assertTokenType(DTD, type1); - assertTokenType(START_ELEMENT, type2); - fail("Expected an exception for partial entity reference: current token after text: "+tokenTypeDesc(lastType)); - } - - /** - * This unit test checks that external entities can be resolved; and - * to do that without requiring external files, will use a simple - * helper resolver - */ - public void testExternalEntityWithResolver() - throws XMLStreamException - { - String ENTITY_VALUE1 = "some text from the external entity"; - String ACTUAL_VALUE1 = "ent='"+ENTITY_VALUE1+"'"; - String XML = - "\n" - +"]>ent='&extEnt;'"; - - // ns-aware, coalescing (to simplify verifying), entity expanding - XMLInputFactory f = doGetFactory(true, true, true); - - if (!setSupportExternalEntities(f, true)) { - reportNADueToExtEnt("testExternalEntityWithResolver"); - return; - } - - setResolver(f, new SimpleResolver(ENTITY_VALUE1)); - - // First, simple content without further expansion etc - XMLStreamReader sr = constructStreamReader(f, XML); - assertTokenType(DTD, sr.next()); - assertTokenType(START_ELEMENT, sr.next()); - assertTokenType(CHARACTERS, sr.next()); - assertEquals(ACTUAL_VALUE1, getAndVerifyText(sr)); - assertTokenType(END_ELEMENT, sr.next()); - sr.close(); - - // Then bit more complicated one: - - String ENTITY_VALUE2 = "external entity: this & that &intEnt;"; - String ACTUAL_VALUE2a = "ent='external entity: "; - String ACTUAL_VALUE2b = " this & that & more!'"; - String XML2 = - "\n" - +"\n" - +"]>ent='&extEnt;'"; - setResolver(f, new SimpleResolver(ENTITY_VALUE2)); - - sr = constructStreamReader(f, XML2); - assertTokenType(DTD, sr.next()); - assertTokenType(START_ELEMENT, sr.next()); - assertTokenType(CHARACTERS, sr.next()); - assertEquals(ACTUAL_VALUE2a, getAndVerifyText(sr)); - assertTokenType(START_ELEMENT, sr.next()); - assertEquals("leaf", sr.getLocalName()); - assertTokenType(END_ELEMENT, sr.next()); - assertTokenType(CHARACTERS, sr.next()); - assertEquals(ACTUAL_VALUE2b, getAndVerifyText(sr)); - assertTokenType(END_ELEMENT, sr.next()); - sr.close(); - } - - /* - //////////////////////////////////////// - // Private methods, shared test code - //////////////////////////////////////// - */ - - private void doTestProperties(boolean nsAware) - throws XMLStreamException - { - XMLStreamReader sr = getReader - ("\n" - +"\n" - +"]>&myent;&ent2;", - nsAware, false, false); - - assertTokenType(DTD, sr.next()); - assertTokenType(START_ELEMENT, sr.next()); - assertTokenType(ENTITY_REFERENCE, sr.next()); - - /* Ok, now we can test actual properties we - * are interested in: - */ - - // Type info - assertEquals(false, sr.isStartElement()); - assertEquals(false, sr.isEndElement()); - assertEquals(false, sr.isCharacters()); - assertEquals(false, sr.isWhiteSpace()); - - // indirect type info - /* 29-Jul-2004: It's kind of unintuitive, but API says hasName() - * is only true for start/end elements... - */ - assertEquals(false, sr.hasName()); - - /* And this returns true at least for internal entities, like the one - * we hit first - */ - assertEquals(true, sr.hasText()); - - // Now, local name is accessible, still: - assertEquals("myent", sr.getLocalName()); - - // And replacement text too: - assertEquals("value", getAndVerifyText(sr)); - - assertNotNull(sr.getLocation()); - if (nsAware) { - assertNotNull(sr.getNamespaceContext()); - } - - // And then let's check methods that should throw specific exception - for (int i = 0; i <= 9; ++i) { - String method = ""; - - try { - Object result = null; - switch (i) { - case 0: - method = "getName"; - result = sr.getName(); - break; - case 1: - method = "getPrefix"; - result = sr.getPrefix(); - break; - case 2: - method = "getNamespaceURI"; - result = sr.getNamespaceURI(); - break; - case 3: - method = "getNamespaceCount"; - result = new Integer(sr.getNamespaceCount()); - break; - case 4: - method = "getAttributeCount"; - result = new Integer(sr.getAttributeCount()); - break; - case 5: - method = "getPITarget"; - result = sr.getPITarget(); - break; - case 6: - method = "getPIData"; - result = sr.getPIData(); - break; - case 7: - method = "getTextCharacters"; - result = sr.getTextCharacters(); - break; - case 8: - method = "getTextStart"; - result = new Integer(sr.getTextStart()); - break; - case 9: - method = "getTextLength"; - result = new Integer(sr.getTextLength()); - break; - } - fail("Expected IllegalArgumentException, when calling " - +method+"() for ENTITY_REFERENCE"); - } catch (IllegalStateException iae) { - ; // good - } - } - - - // // Ok, and the second entity; an external one - - assertTokenType(ENTITY_REFERENCE, sr.next()); - - assertEquals("ent2", sr.getLocalName()); - - /* Now, text replacement... it seems like hasText() should still - * return true, by default, but getText() (etc) should return - * null? - */ - String text = sr.getText(); - - if (text != null && text.length() > 0) { - fail("Expected getText() for external entity 'ent2' to return null or empty String; instead got '"+text+"'"); - } - - // // ok, should be good: - assertTokenType(END_ELEMENT, sr.next()); - assertTokenType(END_DOCUMENT, sr.next()); - - } - - /* - //////////////////////////////////////// - // Private methods, other - //////////////////////////////////////// - */ - - /** - * Note: all readers for this set of unit tests enable DTD handling; - * otherwise entity definitions wouldn't be read. Validation shouldn't - * need to be enabled just for that purpose. - */ - private XMLStreamReader getReader(String contents, boolean nsAware, - boolean coalescing, boolean replEntities) - throws XMLStreamException - { - XMLInputFactory f = doGetFactory(nsAware, coalescing, replEntities); - return constructStreamReader(f, contents); - } - - private XMLInputFactory doGetFactory(boolean nsAware, - boolean coalescing, boolean replEntities) - throws XMLStreamException - { - XMLInputFactory f = getInputFactory(); - setNamespaceAware(f, nsAware); - setSupportDTD(f, true); - setCoalescing(f, coalescing); - setSupportExternalEntities(f, true); - setReplaceEntities(f, replEntities); - setValidating(f, false); - return f; - } -} diff -Nru libwoodstox-java-4.1.3/src/test/org/codehaus/stax/test/stream/TestEpilog.java libwoodstox-java-5.1.0/src/test/org/codehaus/stax/test/stream/TestEpilog.java --- libwoodstox-java-4.1.3/src/test/org/codehaus/stax/test/stream/TestEpilog.java 2012-04-24 04:38:21.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/org/codehaus/stax/test/stream/TestEpilog.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,109 +0,0 @@ -package org.codehaus.stax.test.stream; - -import javax.xml.stream.*; - -/** - * Unit test suite that tests that events from prolog and epilog are - * correctly reported (and normalized if need be) by the stream reader. - */ -public class TestEpilog - extends BaseStreamTest -{ - public TestEpilog(String name) { - super(name); - } - - public void testValidEpilog() - throws XMLStreamException - { - String XML = " "; - - XMLStreamReader sr = getReader(XML, true); - assertTokenType(COMMENT, sr.next()); - assertEquals(" test comment ", getAndVerifyText(sr)); - - // May or may not get white space in epilog... - int type; - while ((type = sr.next()) == SPACE) { - ; - } - assertTokenType(START_ELEMENT, type); - assertTokenType(END_ELEMENT, sr.next()); - - while ((type = sr.next()) == SPACE) { - ; - } - assertTokenType(PROCESSING_INSTRUCTION, type); - assertEquals("some", sr.getPITarget()); - // Not sure if the white space between target and data is included... - assertEquals("processing instruction", sr.getPIData().trim()); - - while ((type = sr.next()) == SPACE) { - ; - } - - assertTokenType(COMMENT, type); - assertEquals(" another comment! ", getAndVerifyText(sr)); - - while ((type = sr.next()) == SPACE) { - ; - } - assertTokenType(END_DOCUMENT, type); - } - - public void testInvalidEpilog() - throws XMLStreamException - { - /* Once again, ns/non-ns shouldn't matter... but you - * never know - */ - doTestInvalid(false); - doTestInvalid(true); - } - - /* - //////////////////////////////////////// - // Private methods, shared test code - //////////////////////////////////////// - */ - - private void doTestInvalid(boolean nsAware) - throws XMLStreamException - { - // Text before the root element: - String XML = " yeehaw! "; - try { - streamThrough(getReader(XML, nsAware)); - fail("Expected an exception for text in prolog"); - } catch (Exception e) { - ; // good - } - - // Text after the root element: - XML = " foobar"; - try { - streamThrough(getReader(XML, nsAware)); - fail("Expected an exception for text in epilog"); - } catch (Exception e) { - ; // good - } - - } - - /* - //////////////////////////////////////// - // Private methods, other - //////////////////////////////////////// - */ - - private XMLStreamReader getReader(String contents, boolean nsAware) - throws XMLStreamException - { - XMLInputFactory f = getInputFactory(); - // Let's coalesce, makes it easier to skip white space - setCoalescing(f, true); - setNamespaceAware(f, nsAware); - setValidating(f, false); - return constructStreamReader(f, contents); - } -} diff -Nru libwoodstox-java-4.1.3/src/test/org/codehaus/stax/test/stream/TestFilteredReader.java libwoodstox-java-5.1.0/src/test/org/codehaus/stax/test/stream/TestFilteredReader.java --- libwoodstox-java-4.1.3/src/test/org/codehaus/stax/test/stream/TestFilteredReader.java 2012-04-24 04:38:21.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/org/codehaus/stax/test/stream/TestFilteredReader.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,96 +0,0 @@ -package org.codehaus.stax.test.stream; - -import java.io.*; - -import javax.xml.stream.*; - -/** - * Simple unit test suite that tries to if filtered stream readers are - * constructed and can be used. - *

- * One thing to note, though, is that the StAX specs do not tell much - * anything about expected ways that the implementation is to deal with - * problems resulting from filtering END_DOCUMENT event and so forth. - * - * @author Tatu Saloranta - */ -public class TestFilteredReader - extends BaseStreamTest -{ - /** - * Simplest possible test: let's only check that we can actually - * construct an instance with dummy filter that accepts everything, - * and that we can traverse through all the events as usual. - */ - public void testCreation() - throws XMLStreamException - { - XMLStreamReader sr = createFilteredReader(new MyFilter(), "text", true); - - assertTokenType(START_DOCUMENT, sr.getEventType()); - assertTokenType(START_ELEMENT, sr.next()); - assertEquals("root", sr.getLocalName()); - assertEquals(0, sr.getAttributeCount()); - assertNotNull(sr.getName()); - assertTokenType(CHARACTERS, sr.next()); - assertEquals("text", getAndVerifyText(sr)); - assertTokenType(END_ELEMENT, sr.next()); - assertEquals("root", sr.getLocalName()); - assertTokenType(END_DOCUMENT, sr.next()); - } - - public void testStartElemFilter1() - throws XMLStreamException - { - XMLStreamReader sr = createFilteredReader - (getElementFilter("elem"), - "text", true); - // Should skip the START_DOCUMENT due to filter - assertTokenType(START_ELEMENT, sr.getEventType()); - } - - public void testStartElemFilter2() - throws XMLStreamException - { - XMLStreamReader sr = createFilteredReader - (getElementFilter("elem"), - "...text", true); - // Should skip START_DOCUMENT, START_ELEMENT and CHARACTERS - assertTokenType(START_ELEMENT, sr.getEventType()); - assertEquals("elem", sr.getLocalName()); - } - - /* - //////////////////////////////////////// - // Non-test methods - //////////////////////////////////////// - */ - - private StreamFilter getElementFilter(final String localName) - { - return new StreamFilter() { - public boolean accept(XMLStreamReader r) { - return r.getEventType() == XMLStreamConstants.START_ELEMENT && - r.getLocalName().equals(localName); - } - }; - } - - private XMLStreamReader createFilteredReader(StreamFilter filter, String content, - boolean nsAware) - throws XMLStreamException - { - XMLInputFactory f = getInputFactory(); - setNamespaceAware(f, nsAware); - XMLStreamReader base = constructStreamReader(f, content); - return f.createFilteredReader(base, filter); - } - - final static class MyFilter - implements StreamFilter - { - public boolean accept(XMLStreamReader reader) { - return true; - } - } -} diff -Nru libwoodstox-java-4.1.3/src/test/org/codehaus/stax/test/stream/TestGetSegmentedText.java libwoodstox-java-5.1.0/src/test/org/codehaus/stax/test/stream/TestGetSegmentedText.java --- libwoodstox-java-4.1.3/src/test/org/codehaus/stax/test/stream/TestGetSegmentedText.java 2012-04-24 04:38:21.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/org/codehaus/stax/test/stream/TestGetSegmentedText.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,285 +0,0 @@ -package org.codehaus.stax.test.stream; - -import java.io.*; -import java.util.Random; - -import javax.xml.stream.*; - -/** - * Unit test suite that ensures that the 'segmented' text accessors - * (multi-argument getTextCharacters) works as expected, with various - * combinations of access lengths, and orderings. - * - * @author Tatu Saloranta - */ -public class TestGetSegmentedText - extends BaseStreamTest -{ - static String sXmlInput = null; - static String sExpResult = null; - - public void testCoalescingAutoEntity() - throws Exception - { - doTest(false, true, true); // non-ns - doTest(true, true, true); // ns-aware - } - - public void testNonCoalescingAutoEntity() - throws Exception - { - doTest(false, false, true); // non-ns - doTest(true, false, true); // ns-aware - } - - public void testCoalescingNonAutoEntity() - throws Exception - { - doTest(false, true, false); // non-ns - doTest(true, true, false); // ns-aware - } - - public void testNonCoalescingNonAutoEntity() - throws Exception - { - doTest(false, false, false); // non-ns - doTest(true, false, false); // ns-aware - } - - public void testSegmentedGetCharacters() - throws XMLStreamException - { - final String TEXT = "Let's just add some content in here ('') to fill some of the parser buffers, to test multi-argument getTextCharacters() method"; - final String XML = ""+TEXT+""; - - XMLInputFactory f = getFactory(true, false, true); - XMLStreamReader sr = constructStreamReader(f, XML); - - // May or may not get the prolog comment - int type = sr.next(); - if (type == COMMENT) { - type = sr.next(); - } - assertTokenType(START_ELEMENT, type); - assertTokenType(PROCESSING_INSTRUCTION, sr.next()); - type = sr.next(); - assertTokenType(CHARACTERS, type); - - /* Ok... let's just access all the text, by one char reads, from - * possibly multiple events: - */ - StringBuffer sb = new StringBuffer(); - while (type == CHARACTERS) { - char[] buf = new char[5]; - int offset = 0; - int count; - - while (true) { // let's use 2 different size of requests... - int start, len; - - if ((offset & 1) == 0) { - start = 2; - len = 1; - } else { - start = 0; - len = buf.length; - } - count = sr.getTextCharacters(offset, buf, start, len); - if (count > 0) { - sb.append(buf, start, count); - offset += count; - } - if (count < len) { - break; - } - } - - type = sr.next(); - } - - assertEquals(TEXT, sb.toString()); - assertTokenType(END_ELEMENT, type); - } - - /* - //////////////////////////////////////// - // Private methods, common test code - //////////////////////////////////////// - */ - - private void doTest(boolean ns, boolean coalescing, boolean autoEntity) - throws Exception - { - // This is bit hacky, but speeds up testing... - if (sXmlInput == null) { - initData(); - } - - // And let's also check using different buffer sizes: - for (int sz = 0; sz < 3; ++sz) { - // Let's test different input methods too: - for (int j = 0; j < 3; ++j) { - - XMLInputFactory f = getFactory(ns, coalescing, autoEntity); - XMLStreamReader sr; - - switch (j) { - case 0: // simple StringReader: - sr = constructStreamReader(f, sXmlInput); - break; - case 1: // via InputStream and auto-detection - /* It shouldn't really contain anything outside ISO-Latin; - * however, detection may be tricky.. so let's just - * test with UTF-8, for now? - */ - { - ByteArrayInputStream bin = new ByteArrayInputStream - (sXmlInput.getBytes("UTF-8")); - sr = f.createXMLStreamReader(bin); - } - break; - case 2: // explicit UTF-8 stream - { - ByteArrayInputStream bin = new ByteArrayInputStream - (sXmlInput.getBytes("UTF-8")); - Reader br = new InputStreamReader(bin, "UTF-8"); - sr = f.createXMLStreamReader(br); - } - break; - default: throw new Error("Internal error"); - } - - char[] cbuf; - - if (sz == 0) { - cbuf = new char[23]; - } else if (sz == 1) { - cbuf = new char[384]; - } else { - cbuf = new char[4005]; - } - - assertTokenType(START_ELEMENT, sr.next()); - int segCount = 0; - int totalLen = sExpResult.length(); - StringBuffer totalBuf = new StringBuffer(totalLen); - - /* Ok; for each segment let's test separately first, - * and then combine all the results together as well - */ - while (sr.next() == CHARACTERS) { - // Where are we within the whole String? - int segOffset = totalBuf.length(); - - ++segCount; - // Should not get multiple when coalescing... - if (coalescing && segCount > 1) { - fail("Didn't expect multiple CHARACTERS segments when coalescing: first segment contained "+segOffset+" chars from the whole expected "+totalLen+" chars"); - } - StringBuffer sb = new StringBuffer(); - int count; - int offset = 0; - int readCount = 0; - - while ((count = sr.getTextCharacters(offset, cbuf, 0, cbuf.length)) > 0) { - ++readCount; - sb.append(cbuf, 0, count); - offset += count; - } - int expLen = sr.getTextLength(); - - // Sanity check #1: should get matching totals - assertEquals - ("Expected segment #"+segOffset+" (one-based; read with "+readCount+" reads) to have length of " - +expLen+"; reported to have gotten just "+offset+" chars", - expLen, offset); - - // Sanity check #2: and string buf should have it too - assertEquals - ("Expected segment #"+segOffset+" (one-based; read with "+readCount+" reads) to get " - +expLen+" chars; StringBuffer only has "+sb.length(), - expLen, sb.length()); - - totalBuf.append(sb); - } - assertTokenType(END_ELEMENT, sr.getEventType()); - - // Ok; all gotten, does it match? - assertEquals("Expected total of "+totalLen+" chars, got "+totalBuf.length(), - sExpResult.length(), totalBuf.length()); - - // Lengths are ok, but how about content? - if (!sExpResult.equals(totalBuf.toString())) { - // TODO: indicate where they differ? - String str1 = sExpResult; - String str2 = totalBuf.toString(); - int len = str1.length(); - int i = 0; - char c1 = 'x', c2 = 'x'; - - for (; i < len; ++i) { - c1 = str1.charAt(i); - c2 = str2.charAt(i); - if (c1 != c2) { - break; - } - } - fail("Expected Strings to equal; differed at character #"+i+" (length "+len+" was correct); expected '"+c1+"' ("+((int) c1)+"), got '"+c2+"' ("+((int) c2)+")"); - - sr.close(); - } - } - } - } - - /* - //////////////////////////////////////// - // Private methods, other - //////////////////////////////////////// - */ - - private XMLInputFactory getFactory(boolean nsAware, - boolean coalescing, boolean autoEntity) - throws XMLStreamException - { - XMLInputFactory f = getInputFactory(); - setNamespaceAware(f, nsAware); - setCoalescing(f, coalescing); - setReplaceEntities(f, autoEntity); - - setSupportDTD(f, true); - setValidating(f, false); - return f; - } - - private void initData() - throws XMLStreamException - { - StringBuffer sb = new StringBuffer(""); - sb.append(""); - - /* Let's create a ~64kchar text segment for testing, first; and one - * including stuff like linefeeds and (pre-defined) entities. - */ - while (sb.length() < 65000) { - sb.append("abcd efgh\r\nijkl & mnop < > qrst\n uvwx\r yz A"); - } - - sb.append(""); - final String XML = sb.toString(); - - /* But more than that, let's also see what we should get - * as a result... - */ - XMLInputFactory f = getFactory(true, false, true); - XMLStreamReader sr = constructStreamReader(f, XML); - assertTokenType(START_ELEMENT, sr.next()); - StringBuffer sb2 = new StringBuffer(XML.length()); - while (sr.next() == CHARACTERS) { - sb2.append(sr.getText()); - } - - sXmlInput = XML; - sExpResult = sb2.toString(); - } -} diff -Nru libwoodstox-java-4.1.3/src/test/org/codehaus/stax/test/stream/TestLinefeeds.java libwoodstox-java-5.1.0/src/test/org/codehaus/stax/test/stream/TestLinefeeds.java --- libwoodstox-java-4.1.3/src/test/org/codehaus/stax/test/stream/TestLinefeeds.java 2012-04-24 04:38:21.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/org/codehaus/stax/test/stream/TestLinefeeds.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,298 +0,0 @@ -package org.codehaus.stax.test.stream; - -import javax.xml.stream.*; - -/** - * Unit test suite that tests linefeed normalization features of parsers. - */ -public class TestLinefeeds - extends BaseStreamTest -{ - final String IN_SPACES1 = " \r \n \r\n "; - final String OUT_SPACES1 = " \n \n \n "; - - final String IN_SPACES2 = "\r\r \n \r"; - final String OUT_SPACES2 = "\n\n \n \n"; - - final String IN_SPACES3 = " \r\n \r\n \r\n"; - final String OUT_SPACES3 = " \n \n \n"; - - final String IN_MIXED1 = "Something\nwonderful (?)\rhas...\r\r\n happened "; - final String OUT_MIXED1 = "Something\nwonderful (?)\nhas...\n\n happened "; - - public TestLinefeeds(String name) { - super(name); - } - - /** - * Test that checks that if ignorable whitespace is reported from - * epilog and/or prolog, it will be properly normalized. - */ - public void testLfInEpilog() - throws XMLStreamException - { - final String contents = IN_SPACES1+""+IN_SPACES2; - - for (int i = 0; i < 4; ++i) { - XMLInputFactory f = getInputFactory(); - boolean coal = ((i & 1) == 0); - boolean ns = ((i & 2) == 0); - setCoalescing(f, coal); - setNamespaceAware(f, ns); - XMLStreamReader sr = constructStreamReader(f, contents); - - /* Since reporting (ignorable) white space is optional, have to - * be careful... - */ - int type = sr.next(); - if (type == SPACE) { // ok - String str = getAndVerifyText(sr); - while ((type = sr.next()) == SPACE) { - str += getAndVerifyText(sr); - } - assertEquals(printable(OUT_SPACES1), printable(str)); - } - - // Either way, needs to have the root element now - assertEquals(START_ELEMENT, type); - assertEquals("root", sr.getLocalName()); - assertNoPrefix(sr); - - // And then matching virtual close - assertEquals(END_ELEMENT, sr.next()); - assertEquals("root", sr.getLocalName()); - assertNoPrefix(sr); - - // And then we may get more whitespace: - type = sr.next(); - if (type == SPACE) { // ok - String str = getAndVerifyText(sr); - while ((type = sr.next()) == SPACE) { - str += getAndVerifyText(sr); - } - if (!str.equals(OUT_SPACES2)) { - String exp = printable(OUT_SPACES2); - String act = printable(str); - fail("Failed (coalesce: "+coal+", ns-aware: "+ns+"); expected '"+exp+"', got '"+act+"'."); - } - } - - assertEquals(END_DOCUMENT, type); - } - } - - public void testLfInCData() - throws XMLStreamException - { - /* Split into separate calls, to make it easier to see which - * combination failed (from stack trace) - */ - doTestLfInCData(false, false); - doTestLfInCData(false, true); - doTestLfInCData(true, false); - doTestLfInCData(true, true); - } - - private void doTestLfInCData(boolean ns, boolean coalescing) - throws XMLStreamException - { - final String contents = ""; - - XMLInputFactory f = getInputFactory(); - setCoalescing(f, coalescing); - setNamespaceAware(f, ns); - XMLStreamReader sr = constructStreamReader(f, contents); - - // Then should get the root element: - // Either way, needs to have the root element now - assertEquals(START_ELEMENT, sr.next()); - assertEquals("root", sr.getLocalName()); - assertNoPrefix(sr); - - /* Then we will get either CDATA or CHARACTERS type; let's - * NOT do thorough check here -- that'll be up to specific - * CDATA unit tests on a separate suite. - */ - int type = sr.next(); - - assertTrue("Expected either CDATA or CHARACTERS event, got "+type, - (type == CDATA || type == CHARACTERS)); - - String str = getAndVerifyText(sr); - /* If we are not coalescing, data can (in theory) be split - * up... - */ - if (coalescing) { - type = sr.next(); - } else { - while (true) { - type = sr.next(); - if (type != CDATA && type != CHARACTERS) { - break; - } - str += getAndVerifyText(sr); - } - } - - String exp = OUT_SPACES1+OUT_SPACES2; - if (!str.equals(exp)) { - fail("Failed (coalesce: "+coalescing+", ns-aware: "+ns+"); expected '" - +printable(exp)+"', got '"+printable(str)+"'."); - } - - // Plus, should get the close element too - assertEquals(END_ELEMENT, type); - assertEquals("root", sr.getLocalName()); - assertNoPrefix(sr); - - // And then the end doc - assertEquals(END_DOCUMENT, sr.next()); - } - - public void testLfInProcInstr() - throws XMLStreamException - { - /* Since exact handling of the white space between target and - * data is not well-defined by the specs, let's just add markers - * and trim such white space out... - */ - final String contents = "" - +""; - - /* There really shouldn't be any difference between coalescing/non - * or namespace aware/non-ns modes, let's try out the combinations - * just in case - */ - for (int i = 0; i < 4; ++i) { - XMLInputFactory f = getInputFactory(); - setCoalescing(f, ((i & 1) == 0)); - setNamespaceAware(f, ((i & 2) == 0)); - - XMLStreamReader sr = constructStreamReader(f, contents); - - // Then should get the root element: - // Either way, needs to have the root element now - assertEquals(START_ELEMENT, sr.next()); - assertEquals("root", sr.getLocalName()); - assertNoPrefix(sr); - - assertEquals(PROCESSING_INSTRUCTION, sr.next()); - assertEquals("target", sr.getPITarget()); - - // Ok, how about the contents: - String data = sr.getPIData(); - String exp = "["+OUT_SPACES1+OUT_SPACES2+"]"; - - assertEquals(printable(exp), printable(data)); - - // And some more white space + lf handling: - assertEquals(PROCESSING_INSTRUCTION, sr.next()); - assertEquals("target", sr.getPITarget()); - - data = sr.getPIData(); - exp = "["+OUT_SPACES3+"]"; - assertEquals(printable(exp), printable(data)); - - // Plus, should get the close element too - assertEquals(END_ELEMENT, sr.next()); - assertEquals("root", sr.getLocalName()); - assertNoPrefix(sr); - - // And then the end doc - assertEquals(END_DOCUMENT, sr.next()); - } - } - - public void testLfInComment() - throws XMLStreamException - { - final String contents = "" - +"" - +"" - +"" - +"" - +""; - - /* There really shouldn't be any difference between coalescing/non - * or namespace aware/non-ns modes, but let's try out the combinations - * just in case (some implementations may internally have differing - * handling) - */ - for (int i = 0; i < 4; ++i) { - XMLInputFactory f = getInputFactory(); - setCoalescing(f, ((i & 1) == 0)); - setNamespaceAware(f, ((i & 2) == 0)); - - XMLStreamReader sr = constructStreamReader(f, contents); - - // Then should get the root element: - // Either way, needs to have the root element now - assertEquals(START_ELEMENT, sr.next()); - assertEquals("root", sr.getLocalName()); - assertNoPrefix(sr); - - assertEquals(COMMENT, sr.next()); - assertEquals(printable(OUT_SPACES1), printable(sr.getText())); - assertEquals(COMMENT, sr.next()); - assertEquals(printable(OUT_SPACES2), printable(sr.getText())); - assertEquals(COMMENT, sr.next()); - assertEquals(printable(OUT_SPACES3), printable(sr.getText())); - assertEquals(COMMENT, sr.next()); - assertEquals(printable(OUT_MIXED1), printable(sr.getText())); - - // Plus, should get the close element too - assertEquals(END_ELEMENT, sr.next()); - assertEquals("root", sr.getLocalName()); - assertNoPrefix(sr); - - // And then the end doc - assertEquals(END_DOCUMENT, sr.next()); - } - } - - public void testLfInText() - throws XMLStreamException - { - final String contents = ""+IN_SPACES1+IN_SPACES2+""; - - for (int i = 0; i < 4; ++i) { // to test coalescing and non-coalescing - XMLInputFactory f = getInputFactory(); - boolean coalescing = ((i & 1) == 0); - setCoalescing(f, coalescing); - setNamespaceAware(f, ((i & 2) == 0)); - XMLStreamReader sr = constructStreamReader(f, contents); - - assertEquals(START_ELEMENT, sr.next()); - assertEquals(CHARACTERS, sr.next()); - - int type; - String str = getAndVerifyText(sr); - - /* If we are not coalescing, data can be split - * up... (but in practice would probably need longer input - * text?) - */ - if (coalescing) { - type = sr.next(); - } else { - while (true) { - type = sr.next(); - if (type != CDATA && type != CHARACTERS) { - break; - } - str += getAndVerifyText(sr); - } - } - - assertEquals(printable(OUT_SPACES1+OUT_SPACES2), - printable(str)); - - // Plus, should get the close element too - assertEquals(END_ELEMENT, type); - // And then the end doc - assertEquals(END_DOCUMENT, sr.next()); - } - } -} diff -Nru libwoodstox-java-4.1.3/src/test/org/codehaus/stax/test/stream/TestMisc.java libwoodstox-java-5.1.0/src/test/org/codehaus/stax/test/stream/TestMisc.java --- libwoodstox-java-4.1.3/src/test/org/codehaus/stax/test/stream/TestMisc.java 2012-04-24 04:38:21.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/org/codehaus/stax/test/stream/TestMisc.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,424 +0,0 @@ -package org.codehaus.stax.test.stream; - -import java.util.Random; - -import javax.xml.stream.*; - -/** - * Unit test suite that tests miscellaneous stream reader methods, such - * as require(), getElementText() and nextTag() - * @author Tatu Saloranta - */ -public class TestMisc - extends BaseStreamTest -{ - public void testRequire() - throws XMLStreamException - { - String XML = - "" - +"" - +"Text" - +"" - +"" - +"" - ; - - XMLStreamReader sr = getReader(XML, true, true); - - sr.require(START_DOCUMENT, null, null); - - assertTokenType(START_ELEMENT, sr.next()); - - assertTokenType(COMMENT, sr.next()); - sr.require(COMMENT, null, null); - try { // should get an exception due to comments not having names - sr.require(COMMENT, null, "tag"); - fail("Should have thrown an exception when checking local name of a COMMENT"); - } catch (XMLStreamException e) { - ; // good - } catch (IllegalStateException ise) { - ; // likewise this is ok, as getName() can throw it - } - - assertTokenType(PROCESSING_INSTRUCTION, sr.next()); - sr.require(PROCESSING_INSTRUCTION, null, null); - - assertTokenType(START_ELEMENT, sr.next()); - sr.require(START_ELEMENT, null, "tag"); - - String nsURI = sr.getNamespaceURI(); - try { - sr.require(START_ELEMENT, "", "tag"); - } catch (XMLStreamException e) { - fail("Did not expect problems with match (current ns URI as reported by stream reader = '"+nsURI+"'), got: "+e.getMessage()); - } - - try { // should get an exception due to incorrect ns URI - sr.require(START_ELEMENT, "http://foo", "tag"); - fail("Should have thrown an exception for incorrect NS URI"); - } catch (XMLStreamException e) { - ; // good - } - - assertTokenType(CHARACTERS, sr.next()); - sr.require(CHARACTERS, null, null); - - assertTokenType(END_ELEMENT, sr.next()); - sr.require(END_ELEMENT, null, "tag"); - sr.require(END_ELEMENT, "", "tag"); - - assertTokenType(START_ELEMENT, sr.next()); - - /* Will get CHARACTERS instead of CDATA, because it's a - * coalescing reader... - */ - assertTokenType(CHARACTERS, sr.next()); - sr.require(CHARACTERS, null, null); - - assertTokenType(END_ELEMENT, sr.next()); - - assertTokenType(START_ELEMENT, sr.next()); // empty - sr.require(START_ELEMENT, "http://foo", "empty"); - assertTokenType(END_ELEMENT, sr.next()); - sr.require(END_ELEMENT, "http://foo", "empty"); - sr.require(END_ELEMENT, "http://foo", null); - sr.require(END_ELEMENT, null, "empty"); - - assertTokenType(END_ELEMENT, sr.next()); - sr.require(END_ELEMENT, "", "root"); - - assertTokenType(END_DOCUMENT, sr.next()); - sr.require(END_DOCUMENT, null, null); - } - - public void testGetElementText() - throws XMLStreamException - { - _testGetElementText(false); - _testGetElementText(true); - } - - private void _testGetElementText(boolean textual) - throws XMLStreamException - { - String XML = "" - +"Got some text 'n stuff!" - +"more " - +"abcde" - +"" - ; - // Special: let's verify using both utf-8 and text-based readers - XMLInputFactory f = getInputFactory(); - setNamespaceAware(f, true); - - XMLStreamReader sr = textual ? constructCharStreamReader(f, XML) - : constructUtf8StreamReader(f, XML); - - // First 2 valid cases: - assertTokenType(START_ELEMENT, sr.next()); - assertTokenType(START_ELEMENT, sr.next()); - assertEquals("Got some text 'n stuff!", sr.getElementText()); - assertTokenType(END_ELEMENT, sr.getEventType()); - assertTokenType(START_ELEMENT, sr.next()); - assertEquals("more stuff ", sr.getElementText()); - assertTokenType(END_ELEMENT, sr.getEventType()); - assertTokenType(START_ELEMENT, sr.next()); - assertEquals("abcde", sr.getElementText()); - assertTokenType(END_ELEMENT, sr.getEventType()); - - assertTokenType(END_ELEMENT, sr.next()); - sr.close(); - } - - public void testGetElementTextInvalid() - throws XMLStreamException - { - String XML = "Invalid: (no kids allowed!)"; - XMLStreamReader sr = getReader(XML, true, false); - assertTokenType(START_ELEMENT, sr.next()); - - // And then should get proper exception - try { - String str = sr.getElementText(); - fail("Expected an exception for nested start element"); - } catch (XMLStreamException ex) { - ; // ok! (would be nice to check error message but...) - } - } - - /** - * Alternative test that tries to verify that handling of long - * and non-contiguous text segment also works acceptably. - */ - public void testGetElementTextLong() - throws XMLStreamException - { - /* Let's do multiple passes, starting with shorter Strings; - * easier to troubleshoot with shorter, better coverage with - * longer - */ - - int[] lengths = new int[] { 50, 190, 2400, 9300, 42000 }; - - for (int i = 0; i < lengths.length; ++i) { - int len = lengths[i]; - StringBuffer input = new StringBuffer(len * 3 / 2); - StringBuffer output = new StringBuffer(len + 100); - - Random r = new Random(i); - - while (output.length() < len) { - String str = null; - switch (Math.abs(r.nextInt()) % 7) { - case 0: - { - int nr = r.nextInt(); - // note: linefeed normalization - input.append(" ").append(nr).append("\r\n"); - output.append(" ").append(nr).append("\n"); - } - break; - case 1: - input.append("&"); - output.append("&"); - break; - case 2: - input.append(""); - break; - case 3: - input.append(""); - break; - case 4: - str = "abc "+((char) ('A' + i))+" xyz"; - break; - case 5: - str = ">>> "; - break; - case 6: - str = "; ?? (\u00A0, \u1123)"; - break; - } - if (str != null) { - if ((r.nextInt() & 0x3) == 1) { - input.append(""); - } else { - input.append(str); - } - output.append(str); - } - } - - final String XML = ""+input.toString()+""; - XMLStreamReader sr = getReader(XML, true, false); - - assertTokenType(START_ELEMENT, sr.next()); - String act = sr.getElementText(); - String exp = output.toString(); - assertEquals(exp, act); - sr.close(); - } - } - - /** - * Additional simple test that verifies that element text for - * an empty element is returned as empty String. - */ - public void testGetElementTextEmpty() - throws XMLStreamException - { - // First simple case - - String XML = ""; - XMLStreamReader sr = getReader(XML, true, false); - - assertTokenType(START_ELEMENT, sr.next()); - assertEquals("", sr.getElementText()); - // and then invalid - assertTokenType(END_ELEMENT, sr.getEventType()); - assertEquals("root", sr.getLocalName()); - assertTokenType(END_DOCUMENT, sr.next()); - sr.close(); - - // Then similar but longer - XML = ""; - sr = getReader(XML, true, false); - - assertTokenType(START_ELEMENT, sr.next()); // root - - assertTokenType(START_ELEMENT, sr.next()); - assertEquals("a", sr.getLocalName()); - assertEquals("", sr.getElementText()); - // and then invalid - assertTokenType(END_ELEMENT, sr.getEventType()); - - assertTokenType(START_ELEMENT, sr.next()); - assertEquals("b", sr.getLocalName()); - assertEquals("", sr.getElementText()); - // and then invalid - assertTokenType(END_ELEMENT, sr.getEventType()); - - assertTokenType(END_ELEMENT, sr.next()); - assertEquals("root", sr.getLocalName()); - assertTokenType(END_DOCUMENT, sr.next()); - } - - public void testNextTag() - throws XMLStreamException - { - String XML = - " " - +" " - +" " - +"text" - ; - XMLStreamReader sr = getReader(XML, true, false); - // First valid cases: - assertTokenType(START_ELEMENT, sr.nextTag()); - assertEquals("root", sr.getLocalName()); - assertTokenType(START_ELEMENT, sr.nextTag()); - assertTokenType(END_ELEMENT, sr.nextTag()); - assertEquals("tag", sr.getLocalName()); - - assertTokenType(START_ELEMENT, sr.nextTag()); - assertEquals("tag", sr.getLocalName()); - - assertTokenType(START_ELEMENT, sr.nextTag()); - assertEquals("leaf", sr.getLocalName()); - - assertTokenType(END_ELEMENT, sr.nextTag()); - assertEquals("leaf", sr.getLocalName()); - - assertTokenType(END_ELEMENT, sr.nextTag()); - assertEquals("tag", sr.getLocalName()); - - // And then invalid: - assertTokenType(START_ELEMENT, sr.nextTag()); - assertEquals("tag", sr.getLocalName()); - try { - int type = sr.nextTag(); - fail("Expected an exception for non-whitespace text"); - } catch (XMLStreamException ex) { - ; // ok! - } - } - - public void testNextTagWithCommentsAndPIs() - throws XMLStreamException - { - String XML = - " \n" - +"\n" - +" \n" - +"\n" - +"" - ; - XMLStreamReader sr = getReader(XML, true, false); - - assertTokenType(START_ELEMENT, sr.nextTag()); - assertEquals("root", sr.getLocalName()); - - // First, an empty 'leaf' element - assertTokenType(START_ELEMENT, sr.nextTag()); - assertEquals("leaf", sr.getLocalName()); - assertTokenType(END_ELEMENT, sr.nextTag()); - assertEquals("leaf", sr.getLocalName()); - - // Then one with a single PI in it - assertTokenType(START_ELEMENT, sr.nextTag()); - assertEquals("leaf", sr.getLocalName()); - assertTokenType(END_ELEMENT, sr.nextTag()); - assertEquals("leaf", sr.getLocalName()); - - // Then one with multiple comments - assertTokenType(START_ELEMENT, sr.nextTag()); - assertEquals("leaf", sr.getLocalName()); - assertTokenType(END_ELEMENT, sr.nextTag()); - assertEquals("leaf", sr.getLocalName()); - - // Then one with a mix: - assertTokenType(START_ELEMENT, sr.nextTag()); - assertEquals("leaf", sr.getLocalName()); - assertTokenType(END_ELEMENT, sr.nextTag()); - assertEquals("leaf", sr.getLocalName()); - - // And then the closing root tag - assertTokenType(END_ELEMENT, sr.nextTag()); - assertEquals("root", sr.getLocalName()); - } - - /** - * Test that checks that stream reader's behavior at the end of - * input is compliant. Specifically, an exception should be thrown - * if one tries to access events beyond END_DOCUMENT. - */ - public void testEndOfStream() - throws XMLStreamException - { - String XML = "x"; - XMLStreamReader sr = getReader(XML, true, true); - - assertTokenType(START_DOCUMENT, sr.getEventType()); - assertTokenType(START_ELEMENT, sr.next()); - assertTokenType(CHARACTERS, sr.next()); - assertTokenType(END_ELEMENT, sr.next()); - assertTokenType(END_DOCUMENT, sr.next()); - assertFalse(sr.hasNext()); - - try { - int type = sr.next(); - fail("Expected NoSuchElementException when trying to access events after END_DOCUMENT returned (but received event "+tokenTypeDesc(type)+")"); - } catch (java.util.NoSuchElementException ne) { - // good - } catch (XMLStreamException e) { // wrong exception - fail("Expected NoSuchElementException; received (type "+e.getClass()+"): "+e); - } - } - - /** - * Simple test case to verify an edge case with isWhiteSpace(). - */ - public void testIsWhiteSpace() - throws XMLStreamException - { - // First, simplest possible - XMLStreamReader sr = getReader("A?", true, true); - assertTokenType(START_DOCUMENT, sr.getEventType()); - assertTokenType(START_ELEMENT, sr.next()); - assertTokenType(CHARACTERS, sr.next()); - if (sr.isWhiteSpace()) { - fail("XMLStreamReader.isWhiteSpace() should return false, text = '"+sr.getText()+"'"); - } - sr.close(); - - // Then just bit more complex - sr = getReader("\nA?", true, true); - assertTokenType(START_DOCUMENT, sr.getEventType()); - assertTokenType(START_ELEMENT, sr.nextTag()); - assertTokenType(START_ELEMENT, sr.nextTag()); - assertTokenType(CHARACTERS, sr.next()); - if (sr.isWhiteSpace()) { - fail("XMLStreamReader.isWhiteSpace() should return false, text = '"+sr.getText()+"'"); - } - sr.close(); - } - - /* - //////////////////////////////////////// - // Private methods, other - //////////////////////////////////////// - */ - - private XMLStreamReader getReader(String contents, boolean nsAware, - boolean coalescing) - throws XMLStreamException - { - XMLInputFactory f = getInputFactory(); - setNamespaceAware(f, nsAware); - setSupportDTD(f, true); - setCoalescing(f, coalescing); - setReplaceEntities(f, true); - setValidating(f, false); - return constructStreamReader(f, contents); - } -} diff -Nru libwoodstox-java-4.1.3/src/test/org/codehaus/stax/test/stream/TestNamespaces.java libwoodstox-java-5.1.0/src/test/org/codehaus/stax/test/stream/TestNamespaces.java --- libwoodstox-java-4.1.3/src/test/org/codehaus/stax/test/stream/TestNamespaces.java 2012-04-24 04:38:21.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/org/codehaus/stax/test/stream/TestNamespaces.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,693 +0,0 @@ -package org.codehaus.stax.test.stream; - -import java.util.Iterator; - -import javax.xml.XMLConstants; -import javax.xml.namespace.*; -import javax.xml.stream.*; - -/** - * Unit test suite that tests handling of the namespace declarations, - * both in namespace aware and non-namespace modes. - * - * @author Tatu Saloranta - */ -public class TestNamespaces - extends BaseStreamTest -{ - final String VALID_NS_XML - = "" - +"" - +"" - +"" - +""; - - public void testValidNs() - throws XMLStreamException - { - XMLStreamReader sr = getNsReader(VALID_NS_XML, true); - assertEquals(START_ELEMENT, sr.next()); - assertEquals(1, sr.getNamespaceCount()); - assertEquals(2, sr.getAttributeCount()); - // element properties: - assertNoPrefix(sr); - assertEquals("root", sr.getLocalName()); - assertNoNsURI(sr); - // ns/attr properties: - assertEquals("value", sr.getAttributeValue(null, "attr1")); - assertEquals("", sr.getAttributeValue("myurl", "attr1")); - - checkIllegalAttributeIndexes(sr); - - // Shouldn't be able to use prefix, just URI: - assertNull(sr.getAttributeValue("xmlns", "a")); - assertEquals("myurl", sr.getNamespaceURI("a")); - assertNull(sr.getNamespaceURI("myurl")); - /* 07-Sep-2007, TSa: This is a tough call, but I do believe - * we should expect "no namespace" as the answer (== ""), not - * "unbound" (null). - */ - //assertNull(sr.getNamespaceURI("")); - assertEquals("", sr.getNamespaceURI("")); - - assertNull(sr.getNamespaceURI("nosuchurl")); - - NamespaceContext nc = sr.getNamespaceContext(); - assertNotNull(nc); - assertEquals(XMLConstants.XML_NS_URI, nc.getNamespaceURI(XMLConstants.XML_NS_PREFIX)); - assertEquals(XMLConstants.XML_NS_PREFIX, nc.getPrefix(XMLConstants.XML_NS_URI)); - assertEquals(XMLConstants.XMLNS_ATTRIBUTE_NS_URI, nc.getNamespaceURI(XMLConstants.XMLNS_ATTRIBUTE)); - assertEquals(XMLConstants.XMLNS_ATTRIBUTE, nc.getPrefix(XMLConstants.XMLNS_ATTRIBUTE_NS_URI)); - - assertEquals("myurl", nc.getNamespaceURI("a")); - assertEquals("a", nc.getPrefix("myurl")); - Iterator it = nc.getPrefixes("foobar"); - // Hmmmh. Can it be null or not? For now let's allow null too - if (it == null) { - ; - } else { - assertFalse(it.hasNext()); - } - it = nc.getPrefixes("myurl"); - assertNotNull(it); - assertTrue(it.hasNext()); - assertEquals("a", (String) it.next()); - assertFalse(it.hasNext()); - - // // Ok, then the second element: - - assertEquals(START_ELEMENT, sr.next()); - assertEquals(2, sr.getNamespaceCount()); - assertEquals(1, sr.getAttributeCount()); - assertEquals("a", sr.getPrefix()); - assertEquals("branch", sr.getLocalName()); - - assertEquals("whatever", sr.getNamespaceURI()); - assertEquals("value", sr.getAttributeValue(null, "attr")); - assertEquals("value", sr.getAttributeValue(0)); - - assertEquals("someurl", sr.getNamespaceURI("")); - - // // And finally the third - - assertEquals(START_ELEMENT, sr.next()); - assertEquals(0, sr.getNamespaceCount()); - assertEquals(2, sr.getAttributeCount()); - assertEquals("leaf", sr.getLocalName()); - assertNoPrefix(sr); - assertEquals("yyy", sr.getAttributeValue("whatever", "a")); - assertEquals("xxx", sr.getAttributeValue(null, "a")); - - assertEquals(END_ELEMENT, sr.next()); - assertEquals(0, sr.getNamespaceCount()); - assertEquals("leaf", sr.getLocalName()); - assertNoPrefix(sr); - - assertEquals(END_ELEMENT, sr.next()); - assertEquals(2, sr.getNamespaceCount()); - assertEquals("a", sr.getPrefix()); - assertEquals("branch", sr.getLocalName()); - - assertEquals(END_ELEMENT, sr.next()); - assertEquals(1, sr.getNamespaceCount()); - assertNoNsURI(sr); - assertEquals("root", sr.getLocalName()); - - assertEquals(END_DOCUMENT, sr.next()); - assertFalse(sr.hasNext()); - } - - final String VALID_NS_XML2 - ="" - +"text" - +""; - - /** - * Another unit test that checks that valid namespace declarations - * are handled properly. - */ - public void testMultipleValidNs() - throws XMLStreamException - { - XMLStreamReader sr = getNsReader(VALID_NS_XML2, true); - assertEquals(START_ELEMENT, sr.next()); - - // Let's thoroughly check the root elem - assertEquals(2, sr.getNamespaceCount()); - assertEquals(0, sr.getAttributeCount()); - assertNoPrefix(sr); - assertEquals("root", sr.getLocalName()); - assertEquals("http://foo", sr.getNamespaceURI()); - assertEquals("myurl", sr.getNamespaceURI("a")); - - // first empty elem - while (sr.next() == CHARACTERS) { } - assertTokenType(START_ELEMENT, sr.getEventType()); - assertEquals(0, sr.getNamespaceCount()); - assertEquals(1, sr.getAttributeCount()); - assertNoPrefix(sr); - assertEquals("empty", sr.getLocalName()); - assertEquals("http://foo", sr.getNamespaceURI()); - assertEquals("myurl", sr.getNamespaceURI("a")); - assertNoAttrNamespace(sr.getAttributeNamespace(0)); - assertNoAttrPrefix(sr.getAttributePrefix(0)); - assertEquals("&", sr.getAttributeValue(0)); - assertTokenType(END_ELEMENT, sr.next()); - - // second empty elem - assertTokenType(START_ELEMENT, sr.next()); - assertEquals(0, sr.getNamespaceCount()); - assertEquals(0, sr.getAttributeCount()); - assertEquals("empty", sr.getLocalName()); - assertEquals("a", sr.getPrefix()); - assertEquals("myurl", sr.getNamespaceURI()); - assertEquals("myurl", sr.getNamespaceURI("a")); - assertEquals("http://foo", sr.getNamespaceURI("")); - assertTokenType(END_ELEMENT, sr.next()); - - // And closing 'root' - assertTokenType(END_ELEMENT, sr.next()); - assertEquals("root", sr.getLocalName()); - assertEquals("http://foo", sr.getNamespaceURI()); - - assertTokenType(END_DOCUMENT, sr.next()); - } - - /** - * Test proper handling of valid xml content in non-namespace aware mode. - * Since not all implementations (like the ref. impl.) support non-ns - * aware mode, this unit test is skipped if not applicable. - */ - public void testValidNonNs() - throws XMLStreamException - { - XMLStreamReader sr = getNsReader(VALID_NS_XML, false); - if (sr == null) { - reportNADueToNS("testValidNonNs"); - return; - } - - assertEquals(START_ELEMENT, sr.next()); - assertEquals(0, sr.getNamespaceCount()); - assertEquals(3, sr.getAttributeCount()); - // element properties: - assertNoPrefix(sr); - assertEquals("root", sr.getLocalName()); - - assertNoNsURI(sr); - // ns/attr properties: - - assertEquals("value", sr.getAttributeValue(null, "attr1")); - assertEquals(null, sr.getAttributeValue(null, "foobar")); - - checkIllegalAttributeIndexes(sr); - - /* ... not sure if how namespace access should work, ie. is it ok - * to throw an exception, return null or what - */ - - // // Ok, then the second element: - - assertEquals(START_ELEMENT, sr.next()); - assertEquals(0, sr.getNamespaceCount()); - assertEquals(3, sr.getAttributeCount()); - assertEquals("a:branch", sr.getLocalName()); - assertNoPrefix(sr); - - // // And finally the third - - assertEquals(START_ELEMENT, sr.next()); - assertEquals(0, sr.getNamespaceCount()); - assertEquals(2, sr.getAttributeCount()); - assertEquals("leaf", sr.getLocalName()); - assertNoPrefix(sr); - assertEquals("xxx", sr.getAttributeValue(null, "a")); - assertEquals("yyy", sr.getAttributeValue(null, "a:a")); - - // // And then the end elements - - assertEquals(END_ELEMENT, sr.next()); - assertEquals(0, sr.getNamespaceCount()); - assertEquals("leaf", sr.getLocalName()); - assertNoPrefix(sr); - - assertEquals(END_ELEMENT, sr.next()); - assertEquals(0, sr.getNamespaceCount()); - assertEquals("a:branch", sr.getLocalName()); - assertNoPrefix(sr); - - assertEquals(END_ELEMENT, sr.next()); - assertEquals(0, sr.getNamespaceCount()); - assertNoPrefix(sr); - assertEquals("root", sr.getLocalName()); - - assertEquals(END_DOCUMENT, sr.next()); - assertFalse(sr.hasNext()); - } - - public void testInvalidNs() - throws XMLStreamException - { - testPotentiallyInvalid(true, "testInvalidNs"); - } - - public void testInvalidNonNs() - throws XMLStreamException - { - // Some things are ok, some not, when namespace support is not enabled: - testPotentiallyInvalid(false, "testInvalidNonNs"); - } - - public void testInvalidStandardBindings() - throws XMLStreamException - { - doTestXmlBinding(true, "testInvalidStandardBindings"); - doTestXmlnsBinding(true, "testInvalidStandardBindings"); - } - - public void testInvalidStandardBindingsNonNs() - throws XMLStreamException - { - doTestXmlBinding(false, "testInvalidStandardBindingsNonNs"); - doTestXmlnsBinding(false, "testInvalidStandardBindingsNonNs"); - } - - public void testDefaultNs() - throws XMLStreamException - { - String XML = ""; - - XMLStreamReader sr = getNsReader(XML, true); - assertEquals(START_ELEMENT, sr.next()); - assertEquals("root", sr.getLocalName()); - assertEquals("url", sr.getNamespaceURI()); - assertNoPrefix(sr); - NamespaceContext ctxt = sr.getNamespaceContext(); - assertEquals(1, sr.getNamespaceCount()); - assertEquals("url", sr.getNamespaceURI(0)); - assertNoAttrPrefix(sr.getNamespacePrefix(0)); - - assertEquals("url", ctxt.getNamespaceURI("")); - assertEquals("", ctxt.getPrefix("url")); - assertNull(ctxt.getNamespaceURI("b")); - assertNull(ctxt.getPrefix("ns:b")); - - - XML = ""; - - sr = getNsReader(XML, true); - assertEquals(START_ELEMENT, sr.next()); - assertEquals("root", sr.getLocalName()); - assertNoPrefix(sr); - assertNoNsURI(sr); - assertEquals(1, sr.getNamespaceCount()); - assertEquals("url", sr.getNamespaceURI(0)); - assertEquals("a", sr.getNamespacePrefix(0)); - } - - /** - * Test case that verifies that namespaces properly nest, and - * inner definitions (ns in child element) can mask outer - * definitions (ns in parent element) - */ - public void testMaskingNs() - throws XMLStreamException - { - final String XML = - ""; - - XMLStreamReader sr = getNsReader(XML, true); - assertEquals(START_ELEMENT, sr.next()); - assertEquals("root", sr.getLocalName()); - assertEquals("a", sr.getPrefix()); - assertEquals("ns:a", sr.getNamespaceURI()); - NamespaceContext ctxt = sr.getNamespaceContext(); - assertEquals("ns:a", ctxt.getNamespaceURI("a")); - assertNull(ctxt.getNamespaceURI("b")); - assertEquals("a", ctxt.getPrefix("ns:a")); - assertNull(ctxt.getPrefix("ns:b")); - - assertEquals(START_ELEMENT, sr.next()); - assertEquals("child", sr.getLocalName()); - assertEquals("a", sr.getPrefix()); - assertEquals("ns:b", sr.getNamespaceURI()); - - ctxt = sr.getNamespaceContext(); - assertEquals("ns:b", ctxt.getNamespaceURI("a")); - assertEquals("a", ctxt.getPrefix("ns:b")); - assertNull(ctxt.getNamespaceURI("b")); - - // This is testing of actual masking, using NamespaceContext - { - // Previous binding should be masked by now! - String prefix = ctxt.getPrefix("ns:a"); - if (prefix != null) { - fail("Failed: second declaration for prefix 'a' should have masked previous one; and there should not be a prefix for 'ns:a'. Instead, prefix '"+prefix+"' was considered to (still) be bound"); - } - } - } - - /** - * Unit test that verifies that the default namespace masking works - * as expected. - */ - public void testMaskingDefaultNs() - throws XMLStreamException - { - final String XML = - "" - +"" - +"" - ; - - XMLStreamReader sr = getNsReader(XML, true); - assertEquals(START_ELEMENT, sr.next()); - assertEquals("root", sr.getLocalName()); - assertNoPrefix(sr); - assertEquals("someurl", sr.getNamespaceURI()); - assertEquals(1, sr.getNamespaceCount()); - - assertEquals(START_ELEMENT, sr.next()); - assertEquals("branch", sr.getLocalName()); - assertNoPrefix(sr); - assertNoNsURI(sr); - assertEquals(1, sr.getNamespaceCount()); - - assertEquals(START_ELEMENT, sr.next()); - assertEquals("leaf", sr.getLocalName()); - assertNoPrefix(sr); - assertNoNsURI(sr); - assertEquals(0, sr.getNamespaceCount()); - assertEquals(END_ELEMENT, sr.next()); // leaf - assertEquals(0, sr.getNamespaceCount()); - - assertEquals(START_ELEMENT, sr.next()); - assertEquals("leaf", sr.getLocalName()); - assertNoPrefix(sr); - assertEquals("anotherurl", sr.getNamespaceURI()); - assertEquals(1, sr.getNamespaceCount()); - assertEquals(END_ELEMENT, sr.next()); // leaf - assertEquals(1, sr.getNamespaceCount()); - - assertEquals(END_ELEMENT, sr.next()); // branch - assertEquals(1, sr.getNamespaceCount()); - - assertEquals(END_ELEMENT, sr.next()); // root - assertEquals(1, sr.getNamespaceCount()); - } - - /** - * This specialized test case verifies that there are no - * unbinding of explict namespace prefixes in xml 1.0 - * documents. While namespaces 1.1 (and hence, xml 1.0) - * makes such use legal, xml 1.0 does not allow it. - */ - public void testUnbindingInvalindInXml10() - throws XMLStreamException - { - final String XML = - ""; - - XMLStreamReader sr = getNsReader(XML, true); - assertEquals(START_ELEMENT, sr.next()); - assertEquals("root", sr.getLocalName()); - assertNoPrefix(sr); - - try { - sr.next(); // start_element, usually throws exc her - sr.next(); // but if not, at least should do it before end element - fail("Expected an exception when trying to unbind namespace mapping for prefix 'ns': not legal in xml 1.0 documents"); - } catch (XMLStreamException e) { - // good - } - sr.close(); - } - - /** - * Unit test that verifies that the namespace with prefix 'xml' is - * always predefined without further work. - */ - public void testPredefinedXmlNs() - throws XMLStreamException - { - final String XML = ""; - - XMLStreamReader sr = getNsReader(XML, true); - assertEquals(START_ELEMENT, sr.next()); - assertEquals("xml", sr.getAttributePrefix(0)); - assertEquals("lang", sr.getAttributeLocalName(0)); - assertEquals(XMLConstants.XML_NS_URI, sr.getAttributeNamespace(0)); - assertEquals(START_ELEMENT, sr.next()); - assertEquals("xml", sr.getPrefix()); - assertEquals("a", sr.getLocalName()); - assertEquals(XMLConstants.XML_NS_URI, sr.getNamespaceURI()); - assertEquals(END_ELEMENT, sr.next()); - assertEquals(END_ELEMENT, sr.next()); - } - - /** - * This test verifies that "no namespace" is correctly reported. At - * this point definition of correct handling is not complete, so - * it'll only test cases for which there is clear consensus. - */ - public void testNoNamespace() - throws XMLStreamException - { - String XML = "xyz"; - XMLStreamReader sr = getNsReader(XML, true); - assertEquals(START_ELEMENT, sr.next()); - assertEquals(1, sr.getNamespaceCount()); - - /* 21-Jul-2006, TSa: - * URI returned for namespace declarations (different from URI - * of the element, or attributes) should be the lexical value, - * that is, for "no namespace" it should be "", not null. - */ - assertEquals("", sr.getNamespaceURI(0)); - - /* Too bad there's no consensus on what actual element URI - * should be: both null and "" have their supporters... ;-) - */ - sr.close(); - } - - /* - //////////////////////////////////////// - // Private methods, shared test code - //////////////////////////////////////// - */ - - private void checkIllegalAttributeIndexes(XMLStreamReader sr) - throws XMLStreamException - { - /* 26-Jan-2008, TSa: Javadocs/stax specs do not actually specify - * what should happen if an illegal index is given. - * So while it seems logical that we'd throw an exception, - * we can not count on that. Let's rather just check that - * we either get an exception, or empty (null or "") value; - * and if latter, just warn. - */ - try { - String str = sr.getAttributeValue(-1); - if (str != null) { - if (str.length() > 0) { - fail("Did not expect to find a non-empty value when trying to access attribute #-1, got '"+str+"'"); - } - } - warn("Did not get an exception when calling sr.getAttributeValue(-1): seems odd, but legal?"); - } catch (Exception e) { } - - int count = sr.getAttributeCount(); - try { - String str = sr.getAttributeValue(count); - if (str != null) { - if (str.length() > 0) { - fail("Did not expect to find a non-empty value when trying to access attribute #"+count+" [with element only having "+count+" attribute(s)], got '"+str+"'"); - } - } - warn("Did not get an exception when calling sr.getAttributeValue("+count+"): [with element only having "+count+" attribute(s)] seems odd, but legal?"); - } catch (Exception e) { } - } - - private void testPotentiallyInvalid(boolean nsAware, String method) - throws XMLStreamException - { - // First, check that undeclared namespace prefixes are not kosher - try { - XMLStreamReader sr = getNsReader("", nsAware); - if (sr == null) { - reportNADueToNS(method); - return; - } - - streamThrough(sr); - if (nsAware) { - fail("Was expecting an exception for content that uses undeclared namespace prefix."); - } - } catch (Exception e) { - if (!nsAware) { - fail("Was not expecting an exception for undeclared namespace when namespaces support not enabled: "+e); - } - } - - // Plus, can't redeclare default namespace - try { - XMLStreamReader sr = getNsReader("", - nsAware); - streamThrough(sr); - fail("Was expecting an exception for content that has duplicate declaration of the default namespace."); - } catch (Exception e) { - ; // both should get here - } - - // Nor other prefixes - try { - XMLStreamReader sr = getNsReader("", - nsAware); - streamThrough(sr); - fail("Was expecting an exception for content that has duplicate declaration for a prefix."); - } catch (Exception e) { - ; // both should get here - } - - /* And then, two attribute names may be equivalent if prefixes - * point to same URI; but only in namespace-aware mode - */ - try { - XMLStreamReader sr = getNsReader - ("", - nsAware); - streamThrough(sr); - if (nsAware) { - fail("Was expecting an exception for content that has duplicate attribute (even though prefixes differ, they point to the same URI)"); - } - } catch (Exception e) { - if (!nsAware) { - fail("Was NOT expecting an exception since in non-namespace mode attributes 'a:attr1' and 'b:attr1' are not equivalent: "+e); - } - } - } - - private void doTestXmlBinding(boolean nsAware, String method) - throws XMLStreamException - { - // And 'xml' can only be bound to its correct URI - { // this should be fine - XMLStreamReader sr = getNsReader("", nsAware); - if (sr == null) { - reportNADueToNS(method); - return; - } - streamThrough(sr); - } - - // But not to anything else: - try { - XMLStreamReader sr = getNsReader("", nsAware); - streamThrough(sr); - if (nsAware) { - fail("Was expecting an exception for content that tries to redeclare 'xml' to different URI."); - } - } catch (Exception e) { - if (!nsAware) { - fail("Was not expecting an exception for redeclaration of 'xml' when namespace support not enabled: "+e); - } - } - - // Also, nothing else can bind to that URI, neither explicit prefix - try { - XMLStreamReader sr = getNsReader("", nsAware); - streamThrough(sr); - if (nsAware) { - fail("Was expecting an exception for content that tries to bind prefix other than 'xml' to URI '"+XMLConstants.XML_NS_URI+"'"); - } - } catch (Exception e) { - if (!nsAware) { - fail("Was not expecting an exception for binding 'xml' URI"); - } - } - - // Nor default namespace - try { - XMLStreamReader sr = getNsReader("", nsAware); - streamThrough(sr); - if (nsAware) { - fail("Was expecting an exception for content that tries to bind the default namespace to 'xml' URI '"+XMLConstants.XML_NS_URI+"'"); - } - } catch (Exception e) { - if (!nsAware) { - fail("Was not expecting an exception for binding default namespace to 'xml' URI"); - } - } - } - - private void doTestXmlnsBinding(boolean nsAware, String method) - throws XMLStreamException - { - // Illegal to try to (re)declare 'xmlns' in any way - try { - XMLStreamReader sr = getNsReader("", nsAware); - if (sr == null) { - reportNADueToNS(method); - return; - } - streamThrough(sr); - if (nsAware) { - fail("Was expecting an exception for content that tries to redeclare 'xml' or 'xmlns' to different URI."); - } - } catch (Exception e) { - if (!nsAware) { - fail("Was not expecting an exception for redeclaration of 'xmlns' when namespace support not enabled: "+e); - } - } - - // Also, nothing else can bind to that URI, neither explicit prefix - try { - XMLStreamReader sr = getNsReader("", nsAware); - streamThrough(sr); - if (nsAware) { - fail("Was expecting an exception for content that tries to bind prefix other than 'xml' to URI '"+XMLConstants.XMLNS_ATTRIBUTE_NS_URI+"'"); - } - } catch (Exception e) { - if (!nsAware) { - fail("Was not expecting an exception for binding 'xml' URI"); - } - } - - // Nor default namespace - try { - XMLStreamReader sr = getNsReader("", nsAware); - streamThrough(sr); - if (nsAware) { - fail("Was expecting an exception for content that tries to bind the default namespace to 'xml' URI '"+XMLConstants.XMLNS_ATTRIBUTE_NS_URI+"'"); - } - } catch (Exception e) { - if (!nsAware) { - fail("Was not expecting an exception for binding default namespace to 'xml' URI"); - } - } - } - - /* - //////////////////////////////////////// - // Private methods, other - //////////////////////////////////////// - */ - - /** - * @return Stream reader constructed if initialization succeeded (all - * setting supported by the impl); null if some settings (namespace - * awareness) not supported. - */ - private XMLStreamReader getNsReader(String contents, boolean nsAware) - throws XMLStreamException - { - XMLInputFactory f = getInputFactory(); - if (!setNamespaceAware(f, nsAware)) { - return null; - } - setCoalescing(f, true); - setValidating(f, false); - return constructStreamReader(f, contents); - } -} diff -Nru libwoodstox-java-4.1.3/src/test/org/codehaus/stax/test/stream/TestProcInstrRead.java libwoodstox-java-5.1.0/src/test/org/codehaus/stax/test/stream/TestProcInstrRead.java --- libwoodstox-java-4.1.3/src/test/org/codehaus/stax/test/stream/TestProcInstrRead.java 2012-04-24 04:38:21.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/org/codehaus/stax/test/stream/TestProcInstrRead.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,283 +0,0 @@ -package org.codehaus.stax.test.stream; - -import javax.xml.stream.*; - -/** - * Unit test suite that tests handling of XML processing instructions (except - * for the linefeed normalization which is tested elsewhere); mostly just what - * properties is the stream reader returning when pointing to a comment. - */ -public class TestProcInstrRead - extends BaseStreamTest -{ - public TestProcInstrRead(String name) { - super(name); - } - - /** - * Method that checks properties of PROCESSING_INSTRUCTION - * returned by the stream reader are correct according to StAX specs. - */ - public void testProcInstrProperties() - throws XMLStreamException - { - /* Neither ns-awareness nor dtd-support should make any differnece, - * but let's double check them... - */ - doTestProperties(true, true); - doTestProperties(true, false); - doTestProperties(false, true); - doTestProperties(false, false); - } - - public void testSpaceHandling() - throws XMLStreamException - { - String CONTENT_TEXT = "some data "; - String CONTENT = " "+CONTENT_TEXT; - String XML = ""; - - for (int i = 0; i < 3; ++i) { - boolean ns = (i & 1) != 0; - boolean dtd = (i & 2) != 0; - XMLStreamReader sr = getReader(XML, ns, dtd); - assertTokenType(PROCESSING_INSTRUCTION, sr.next()); - assertEquals("target", sr.getPITarget()); - - String content = sr.getPIData(); - assertNotNull(content); - // Is content exactly as expected? - if (!content.equals(CONTENT_TEXT)) { - // Nope... but would it be without white space? - if (CONTENT_TEXT.trim().equals(content.trim())) { - fail("Proc. instr. white space handling not correct: expected data '" - +CONTENT_TEXT+"', got '"+content+"'"); - } - // Nah, totally wrong: - fail("Processing instruction data incorrect: expected '" - +CONTENT_TEXT+"', got '"+content+"'"); - } - } - } - - public void testInvalidProcInstr() - throws XMLStreamException - { - String XML = ""; - String XML2 = " "; - String XML3 = ""; - - for (int i = 0; i < 3; ++i) { - boolean ns = (i & 1) != 0; - boolean dtd = (i & 2) != 0; - - streamThroughFailing(getReader(XML, ns, dtd), - "invalid processing instruction target ('xml' [case-insensitive] not legal) [ns: "+ns+", dtd: "+dtd+"]"); - - streamThroughFailing(getReader(XML2, ns, dtd), - "invalid processing instruction; empty proc. instr (missing target)"); - - streamThroughFailing(getReader(XML3, ns, dtd), - "invalid processing instruction; ends with '?', not \"?>\""); - } - } - - public void testUnfinishedPI() - throws XMLStreamException - { - String XML = ""; - - for (int i = 0; i < 3; ++i) { - boolean ns = (i & 1) != 0; - streamThroughFailing(getReader(XML, ns, true), - "invalid proc. instr. (unfinished)"); - } - } - - /** - * This unit test checks that the parser does not allow split processing - * instructions; ones that start from within an entity expansion, but do - * not completely finish within entity expansion, but in the original - * input source that referenced the entity. - * Such markup is illegal according to XML specs. - */ - public void testRunawayProcInstr() - throws XMLStreamException - { - String XML = "\n" - +"]>" - + "π?>"; - - XMLStreamReader sr = getReader(XML, true, true); - - try { - // May get an exception when parsing entity declaration... ? - // (since it contains partial token) - assertTokenType(DTD, sr.next()); - assertTokenType(START_ELEMENT, sr.next()); - int type = sr.next(); - if (type != PROCESSING_INSTRUCTION) { - reportNADueToEntityExpansion("testRunawayProcInstr", type); - return; - } - type = sr.next(); - fail("Expected an exception for split/runaway processing instruction (instead got event "+tokenTypeDesc(type)+")"); - } catch (XMLStreamException sex) { - // good - } catch (RuntimeException rex) { - // some impls. throw lazy exceptions, too... - } - } - - /** - * Unit test based on a bug found in the Stax reference implementation. - */ - public void testLongerProcInstr() - throws XMLStreamException - { - String XML = "\n\n" -+"\n\n" -+"\n\n" -+"\n" -+"]>\n\n" -+"\n" -+" &eduni-errata2e;\n" - +"\n"; - - XMLStreamReader sr = getReader(XML, true, true); - - // May get an exception when parsing entity declaration... ? - // (since it contains partial token) - int type; - - while ((type = sr.next()) == SPACE) { } - assertTokenType(COMMENT, type); - while ((type = sr.next()) == SPACE) { } - assertTokenType(PROCESSING_INSTRUCTION, type); - assertEquals("xml-stylesheet", sr.getPITarget()); - while ((type = sr.next()) == SPACE) { } - assertTokenType(DTD, type); - while ((type = sr.next()) == SPACE) { } - assertTokenType(START_ELEMENT, type); - } - - /* - //////////////////////////////////////// - // Private methods, shared test code - //////////////////////////////////////// - */ - - private void doTestProperties(boolean ns, boolean dtd) - throws XMLStreamException - { - final String DATA = "data & more data (???) <>"; - XMLStreamReader sr = getReader("", ns, dtd); - - assertEquals(PROCESSING_INSTRUCTION, sr.next()); - - // Type info - assertEquals(false, sr.isStartElement()); - assertEquals(false, sr.isEndElement()); - assertEquals(false, sr.isCharacters()); - assertEquals(false, sr.isWhiteSpace()); - - // indirect type info - assertFalse("Processing instructions have no names; XMLStreamReader.hasName() should return false", sr.hasName()); - assertEquals(false, sr.hasText()); - - assertNotNull(sr.getLocation()); - if (ns) { - assertNotNull(sr.getNamespaceContext()); - } - - // And then let's check methods that should throw specific exception - for (int i = 0; i < 10; ++i) { - String method = ""; - - try { - Object result = null; - switch (i) { - case 0: - method = "getName"; - result = sr.getName(); - break; - case 1: - method = "getPrefix"; - result = sr.getPrefix(); - break; - case 2: - method = "getLocalName"; - result = sr.getLocalName(); - break; - case 3: - method = "getNamespaceURI"; - result = sr.getNamespaceURI(); - break; - case 4: - method = "getNamespaceCount"; - result = new Integer(sr.getNamespaceCount()); - break; - case 5: - method = "getAttributeCount"; - result = new Integer(sr.getAttributeCount()); - break; - case 6: - method = "getText"; - result = sr.getText(); - break; - case 7: - method = "getTextCharacters"; - result = sr.getTextCharacters(); - break; - case 8: - method = "getTextStart"; - result = new Integer(sr.getTextStart()); - break; - case 9: - method = "getTextLength"; - result = new Integer(sr.getTextLength()); - break; - } - fail("Expected IllegalStateException, when calling " - +method+"() for PROCESSING_INSTRUCTION"); - } catch (IllegalStateException iae) { - ; // good - } - } - - assertEquals("target", sr.getPITarget()); - - /* Now; specs are bit vague WRT white space handling between target - * and data; thus, let's just trim trailing/leading white space - */ - /* 13-Nov-2004, TSa: Actually, handling is to get rid - * of leading but not trailing white space, as per XML specs. - * StAX API is not clear, but another test will verify proper - * behaviour. - */ - assertEquals(DATA.trim(), sr.getPIData().trim()); - } - - /* - //////////////////////////////////////// - // Private methods, other - //////////////////////////////////////// - */ - - private XMLStreamReader getReader(String contents, boolean nsAware, - boolean supportDTD) - throws XMLStreamException - { - XMLInputFactory f = getInputFactory(); - setCoalescing(f, false); // shouldn't really matter - setNamespaceAware(f, nsAware); - setSupportDTD(f, supportDTD); - setValidating(f, false); - return constructStreamReader(f, contents); - } -} diff -Nru libwoodstox-java-4.1.3/src/test/org/codehaus/stax/test/stream/TestProperties.java libwoodstox-java-5.1.0/src/test/org/codehaus/stax/test/stream/TestProperties.java --- libwoodstox-java-4.1.3/src/test/org/codehaus/stax/test/stream/TestProperties.java 2012-04-24 04:38:21.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/org/codehaus/stax/test/stream/TestProperties.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,50 +0,0 @@ -package org.codehaus.stax.test.stream; - -import javax.xml.stream.*; - -/** - * Unit tests that verify handling of XMLInputFactory properties. - * This includes: - *

    - *
  • Property defaults as defined by Stax specs (see class javadocs for - * @link javax.xml.stream.XMLInputFactory} - *
  • - *
- * - * @author Tatu Saloranta - */ -public class TestProperties - extends BaseStreamTest -{ - public void testDefaultEntitySettings() - { - XMLInputFactory f = getNewInputFactory(); - assertEquals(Boolean.TRUE, f.getProperty(XMLInputFactory.IS_REPLACING_ENTITY_REFERENCES)); - Object o = f.getProperty(XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES); - if (!(o instanceof Boolean)) { - fail("Property value for XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES not of type Boolean, but "+((o == null) ? "[null]" : o.getClass().getName())); - } - } - - public void testDefaultValidationSettings() - { - XMLInputFactory f = getNewInputFactory(); - assertEquals(Boolean.FALSE, f.getProperty(XMLInputFactory.IS_VALIDATING)); - // A few impls might not support this, but it is the default... - assertEquals(Boolean.TRUE, f.getProperty(XMLInputFactory.SUPPORT_DTD)); - } - - public void testDefaultMiscSettings() - { - XMLInputFactory f = getNewInputFactory(); - - assertEquals(Boolean.TRUE, f.getProperty(XMLInputFactory.IS_NAMESPACE_AWARE)); - assertEquals(Boolean.FALSE, f.getProperty(XMLInputFactory.IS_COALESCING)); - // Shouldn't have default handlero objects either - assertNull(f.getProperty(XMLInputFactory.REPORTER)); - assertNull(f.getProperty(XMLInputFactory.RESOLVER)); - assertNull(f.getProperty(XMLInputFactory.ALLOCATOR)); - } - -} - diff -Nru libwoodstox-java-4.1.3/src/test/org/codehaus/stax/test/stream/TestRandomStream.java libwoodstox-java-5.1.0/src/test/org/codehaus/stax/test/stream/TestRandomStream.java --- libwoodstox-java-4.1.3/src/test/org/codehaus/stax/test/stream/TestRandomStream.java 2012-04-24 04:38:21.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/org/codehaus/stax/test/stream/TestRandomStream.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,376 +0,0 @@ -package org.codehaus.stax.test.stream; - -import java.io.*; -import java.util.Random; - -import javax.xml.stream.*; - -/** - * Unit test suite that ensures that independent of combinations of settings - * such as namespace-awareness, coalescing, automatic entity replacement, - * parsing results remain the same when they should. - */ -public class TestRandomStream - extends BaseStreamTest -{ - public TestRandomStream(String name) { - super(name); - } - - public void testCoalescingAutoEntity() - throws Exception - { - doTest(false, true, true); // non-ns - doTest(true, true, true); // ns-aware - } - - public void testNonCoalescingAutoEntity() - throws Exception - { - doTest(false, false, true); // non-ns - doTest(true, false, true); // ns-aware - } - - public void testCoalescingNonAutoEntity() - throws Exception - { - doTest(false, true, false); // non-ns - doTest(true, true, false); // ns-aware - } - - public void testNonCoalescingNonAutoEntity() - throws Exception - { - doTest(false, false, false); // non-ns - doTest(true, false, false); // ns-aware - } - - /* - //////////////////////////////////////// - // Private methods, common test code - //////////////////////////////////////// - */ - - private void doTest(boolean ns, boolean coalescing, boolean autoEntity) - throws Exception - { -//System.err.println("Ns: "+ns+", coal "+coalescing+" ent "+autoEntity); - // Let's generate seed from args so it's reproducible - long seed = 123457; - if (ns) { - seed ^= "ns".hashCode(); - } - if (coalescing) { - seed ^= "coalescing".hashCode(); - } - if (autoEntity) { - seed ^= "autoEntity".hashCode(); - } - Random r = new Random(seed); - - /* We can do multiple rounds, too, too get even wider coverage... - */ - final int ROUNDS = 5; - - for (int i = 0; i < ROUNDS; ++i) { - StringBuffer inputBuf = new StringBuffer(1000); - StringBuffer expOutBuf = new StringBuffer(1000); - generateData(r, inputBuf, expOutBuf, autoEntity); - String input = inputBuf.toString(); - String expOutput = expOutBuf.toString(); - - // Let's test different input methods too: - for (int j = 0; j < 3; ++j) { - XMLInputFactory f = getFactory(ns, coalescing, autoEntity); - XMLStreamReader sr; - - switch (j) { - case 0: // simple StringReader: - sr = constructStreamReader(f, input); - break; - case 1: // via InputStream and auto-detection - /* It shouldn't really contain anything outside ISO-Latin; - * however, detection may be tricky.. so let's just - * test with UTF-8, for now? - */ - { - ByteArrayInputStream bin = new ByteArrayInputStream - (input.getBytes("UTF-8")); - sr = f.createXMLStreamReader(bin); - } - break; - case 2: // explicit UTF-8 stream - { - ByteArrayInputStream bin = new ByteArrayInputStream - (input.getBytes("UTF-8")); - Reader br = new InputStreamReader(bin, "UTF-8"); - sr = f.createXMLStreamReader(br); - } - break; - default: throw new Error("Internal error"); - } - - String actual = null; - - try { - actual = runTest(sr); - } catch (Exception e) { - // For debugging uncomment: - /* - System.err.println("Error: "+e); - System.err.println("Ns: "+ns+", coalescing: "+coalescing+", auto-ent: "+autoEntity); - System.err.println("Input was '"+input+"'"); - */ - - throw e; - } - - // uncomment for debugging: - /* - if (!expOutput.equals(actual)) { - System.err.println("Input: '"+input+"'"); - System.err.println("Exp: '"+expOutput+"'"); - System.err.println("Actual: '"+actual+"'"); - } - */ - assertEquals(expOutput, actual); - } - } - } - - private String runTest(XMLStreamReader sr) - throws Exception - { - assertEquals(DTD, sr.next()); - - int type; - - while ((type = sr.next()) == SPACE) { - ; - } - assertEquals(START_ELEMENT, type); - - StringBuffer act = new StringBuffer(1000); - - do { - if (type == START_ELEMENT || type == END_ELEMENT) { - act.append('<'); - if (type == END_ELEMENT) { - act.append('/'); - } - String prefix = sr.getPrefix(); - if (prefix != null && prefix.length() > 0) { - act.append(prefix); - act.append(':'); - } - act.append(sr.getLocalName()); - act.append('>'); - } else if (type == CHARACTERS || type == SPACE || type == CDATA) { - // No quoting, doesn't have to result in legal XML - try { // note: entity expansion may fail... - act.append(getAndVerifyText(sr)); - } catch (XMLStreamException xse) { - fail("Expected succesful entity expansion, got: "+xse); - } catch (RuntimeException rex) { - /* 28-Oct-2006, TSa: since getText() may not be able - * to throw XMLStreamException, let's see if we got - * a runtime excpetion with root cause of stream exc - */ - if (rex.getCause() instanceof XMLStreamException) { - fail("Expected succesful entity expansion, got: "+rex); - } else { - throw rex; - } - } - } else if (type == COMMENT) { - act.append(""); - } else if (type == ENTITY_REFERENCE) { - act.append(sr.getText()); - } else { - fail("Unexpected event type "+type); - } - try { - type = sr.next(); - } catch (XMLStreamException xse) { - fail("Parse problem: "+xse); - } - } while (type != END_DOCUMENT); - - return act.toString(); - } - - private void generateData(Random r, StringBuffer input, - StringBuffer output, boolean autoEnt) - { - final String PREAMBLE = - "" - +"\n" - +" \n" - +" \n" - +"]>"; - - /* Ok; template will use '*' chars as placeholders, to be replaced - * by pseudo-randomly selected choices. - */ - final String TEMPLATE = - "" - - // Short one for trouble shooting: - /* - +" * Text ****\n" - */ - - // Real one for regression testing: - +" * Text ****\n" - +"** * xx\n" - +"Text ******\n" - +"*......**" - +"******" - +"***" - +"***" - +"a*b*c*d*e*f*g*h*i*j*k" - +"
" - - ; - - input.append(TEMPLATE); - output.append(TEMPLATE); - - for (int i = TEMPLATE.length(); --i >= 0; ) { - char c = TEMPLATE.charAt(i); - - if (c == '*') { - replaceEntity(input, output, autoEnt, r, i); - } - } - - // Let's also insert preamble into input now - input.insert(0, PREAMBLE); - } - - private void replaceEntity(StringBuffer input, StringBuffer output, - boolean autoEnt, - Random r, int index) - { - String in, out; - - switch (Math.abs(r.nextInt()) % 5) { - case 0: // Let's use one of pre-def'd entities: - switch (Math.abs(r.nextInt()) % 5) { - case 0: - in = "&"; - out = "&"; - break; - case 1: - in = "'"; - out = "'"; - break; - case 2: - in = "<"; - out = "<"; - break; - case 3: - in = ">"; - out = ">"; - break; - case 4: - in = """; - out = "\""; - break; - default: throw new Error("Internal error!"); - } - break; - case 1: // How about some CDATA? - switch (Math.abs(r.nextInt()) % 4) { - case 0: - in = "]]>"; - out = "]] >"; - break; - case 1: - in = ""; - out = "xyz&abc"; - break; - case 2: - in = ""; - out = ""; - break; - case 3: - in = ""; - out = " "; - break; - default: throw new Error("Internal error!"); - } - break; - case 2: // Char entities? - switch (Math.abs(r.nextInt()) % 4) { - case 0: - in = "#"; - out = "#"; - break; - case 1: - in = "$"; - out = "$"; - break; - case 2: - in = "©"; // above US-Ascii, copyright symbol - out = "\u00A9"; - break; - case 3: - in = "Ä"; // Upper-case a with umlauts - out = "\u00C4"; - break; - default: throw new Error("Internal error!"); - } - break; - case 3: // Full entities - switch (Math.abs(r.nextInt()) % 3) { - case 0: - in = "&ent1;"; - out = "ent1Value"; - break; - case 1: - in = "&x;"; - out = "Y"; - break; - case 2: - in = "&both;"; - out = autoEnt ? "ent1ValueY" : "&ent1;&x;"; - break; - default: throw new Error("Internal error!"); - } - break; - - case 4: // Plain text, ISO-Latin chars: - in = out = "(\u00A9)"; // copyright symbol - break; - - default: - throw new Error("Internal error!"); - } - input.replace(index, index+1, in); - output.replace(index, index+1, out); - } - - /* - //////////////////////////////////////// - // Private methods, other - //////////////////////////////////////// - */ - - private XMLInputFactory getFactory(boolean nsAware, - boolean coalescing, boolean autoEntity) - throws XMLStreamException - { - XMLInputFactory f = getInputFactory(); - setNamespaceAware(f, nsAware); - setCoalescing(f, coalescing); - setReplaceEntities(f, autoEntity); - - setSupportDTD(f, true); - setValidating(f, false); - return f; - } -} diff -Nru libwoodstox-java-4.1.3/src/test/org/codehaus/stax/test/stream/TestStreaming.java libwoodstox-java-5.1.0/src/test/org/codehaus/stax/test/stream/TestStreaming.java --- libwoodstox-java-4.1.3/src/test/org/codehaus/stax/test/stream/TestStreaming.java 2012-04-24 04:38:21.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/org/codehaus/stax/test/stream/TestStreaming.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,84 +0,0 @@ -package org.codehaus.stax.test.stream; - -import java.io.*; - -import javax.xml.stream.*; - -/** - * Unit test suite that tests that the stream is really fully streaming: - * that is, it doesn't need to fill buffers completely before being - * able to return events for things for which it has already read - * text. Tests were added after reports that some implementations did - * in fact have problems with such buffering, and as a result using - * such readers on network (http, tcp) streams wasn't working as well - * as it should. - *

- * Note: should we test Ascii or ISO-Latin, or only UTF-8 (since that's - * the only encoding XML parsers HAVE to understand)? Most parsers handle - * them all. Also; is sub-optimal behaviour (blocking too early) really - * a bug, or just sub-standard implementation? - */ -public class TestStreaming - extends BaseStreamTest -{ - public TestStreaming(String name) { - super(name); - } - - public void testAscii() - throws XMLStreamException, UnsupportedEncodingException - { - testWith("US-ASCII"); - } - - public void testISOLatin() - throws XMLStreamException, UnsupportedEncodingException - { - testWith("ISO-8859-1"); - } - - public void testUTF8() - throws XMLStreamException, UnsupportedEncodingException - { - testWith("UTF-8"); - } - - /* - //////////////////////////////////////// - // Private methods, tests - //////////////////////////////////////// - */ - - private void testWith(String enc) - throws XMLStreamException, UnsupportedEncodingException - { - BlockingStream bs = getStream(enc); - XMLStreamReader sr = getReader(bs); - assertTokenType(START_ELEMENT, sr.next()); - if (bs.hasBlocked()) { - fail("Stream reader causes blocking before returning START_ELEMENT event that should be parsed before blocking"); - } - } - - /* - //////////////////////////////////////// - // Private methods, other - //////////////////////////////////////// - */ - - private BlockingStream getStream(String enc) - throws XMLStreamException, UnsupportedEncodingException - { - String contents = "Some test"; - byte[] data = contents.getBytes(enc); - return new BlockingStream(new ByteArrayInputStream(data)); - } - - private XMLStreamReader getReader(BlockingStream in) - throws XMLStreamException - { - XMLInputFactory f = getInputFactory(); - setValidating(f, false); - return f.createXMLStreamReader((InputStream) in); - } -} diff -Nru libwoodstox-java-4.1.3/src/test/org/codehaus/stax/test/stream/TestTextCoalescing.java libwoodstox-java-5.1.0/src/test/org/codehaus/stax/test/stream/TestTextCoalescing.java --- libwoodstox-java-4.1.3/src/test/org/codehaus/stax/test/stream/TestTextCoalescing.java 2012-04-24 04:38:21.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/org/codehaus/stax/test/stream/TestTextCoalescing.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,162 +0,0 @@ -package org.codehaus.stax.test.stream; - -import javax.xml.stream.*; - -/** - * Unit test suite that tests that the stream reader does in fact - * coalesce adjacent text/CDATA segments when told to do so. - */ -public class TestTextCoalescing - extends BaseStreamTest -{ - final static String VALID_XML = "Text /that's all!"; - - public TestTextCoalescing(String name) { - super(name); - } - - public void testCoalescing() - throws XMLStreamException - { - XMLStreamReader sr = getReader(VALID_XML, true, true); - assertTokenType(START_ELEMENT, sr.next()); - assertTokenType(CHARACTERS, sr.next()); - - String act = getAndVerifyText(sr); - String exp = "Text cdata\nin two lines!/that's all!"; - - if (!exp.equals(act)) { - failStrings("Coalescing failed", exp, act); - } - - assertTokenType(END_ELEMENT, sr.next()); - assertTokenType(END_DOCUMENT, sr.next()); - } - - /** - * Test that ensures that even when just skipping (ie not accessing - * any data), we'll still see just one event for the whole text - */ - public void testCoalescingSkipping() - throws XMLStreamException - { - XMLStreamReader sr = getReader(VALID_XML, true, true); - assertTokenType(START_ELEMENT, sr.next()); - assertTokenType(CHARACTERS, sr.next()); - assertTokenType(END_ELEMENT, sr.next()); - assertTokenType(END_DOCUMENT, sr.next()); - } - - public void testNonCoalescing() - throws XMLStreamException - { - // VALID_XML = "Text /that's all!"; - - XMLStreamReader sr = getReader(VALID_XML, true, false); - assertTokenType(START_ELEMENT, sr.next()); - - /* Can not assume that all events are returned in one call... - * so let's play it safe: - */ - sr.next(); - checkText(sr, CHARACTERS, "Text "); - int count = checkText(sr, CDATA, "cdata\nin two lines!"); - if (count < 2) { - // Can't easily check boundaries... well, could but... - fail("Expected at least two CDATA events; parser coalesced them"); - } - checkText(sr, CHARACTERS, "/that's all!"); - - assertTokenType(END_ELEMENT, sr.getEventType()); - assertTokenType(END_DOCUMENT, sr.next()); - } - - public void testNonCoalescingSkipping() - throws XMLStreamException - { - // VALID_XML = "Text /that's all!"; - - XMLStreamReader sr = getReader(VALID_XML, true, false); - assertTokenType(START_ELEMENT, sr.next()); - - assertTokenType(CHARACTERS, sr.next()); - - /* ugh. Since implementations are allowed to return CHARACTERS, - * instead of CDATA, we can only check that we get at least - * 4 segments of any type... - */ - // Now, we may get more than one CHARACTERS - int count = 1; - StringBuffer sb = new StringBuffer(); - sb.append('['); - sb.append(sr.getText()); - sb.append(']'); - int type; - - while (true) { - type = sr.next(); - if (type != CHARACTERS && type != CDATA) { - break; - } - ++count; - sb.append('['); - sb.append(sr.getText()); - sb.append(']'); - } - if (count < 4) { - fail("Expected at least 4 separate segments (CDATA/CHARACTERS), in non-coalescing mode, got "+count+" (text: "+sb+")"); - } - - assertTokenType(END_ELEMENT, type); - assertTokenType(END_DOCUMENT, sr.next()); - } - - public void testInvalidTextWithCDataEndMarker() - throws XMLStreamException - { - String XML = " ]]> "; - - streamThroughFailing(getReader(XML, true, true), - "text content that has ']]>' in it."); - } - - /* - //////////////////////////////////////// - // Private methods, other - //////////////////////////////////////// - */ - - private XMLStreamReader getReader(String contents, boolean nsAware, - boolean coalescing) - throws XMLStreamException - { - XMLInputFactory f = getInputFactory(); - setNamespaceAware(f, nsAware); - setSupportDTD(f, true); - setCoalescing(f, coalescing); - setReplaceEntities(f, true); - setValidating(f, false); - // 13-Mar-2006, TSa: Let's try to get accurate CDATA reporting... - setReportCData(f, true); - return constructStreamReader(f, contents); - } - - private int checkText(XMLStreamReader sr, int expType, String exp) - throws XMLStreamException - { - assertTokenType(expType, sr.getEventType()); - //if (expType != sr.getEventType()) System.err.println("WARN: expected "+tokenTypeDesc(expType)+", got "+tokenTypeDesc(sr.getEventType())); - StringBuffer sb = new StringBuffer(getAndVerifyText(sr)); - int count = 1; - while ((sr.next()) == expType) { - ++count; - sb.append(getAndVerifyText(sr)); - } - String act = sb.toString(); - if (!exp.equals(act)) { - failStrings("Incorrect text contents", act, exp); - } - return count; - } -} diff -Nru libwoodstox-java-4.1.3/src/test/org/codehaus/stax/test/stream/TestXmlDecl.java libwoodstox-java-5.1.0/src/test/org/codehaus/stax/test/stream/TestXmlDecl.java --- libwoodstox-java-4.1.3/src/test/org/codehaus/stax/test/stream/TestXmlDecl.java 2012-04-24 04:38:21.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/org/codehaus/stax/test/stream/TestXmlDecl.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,221 +0,0 @@ -package org.codehaus.stax.test.stream; - -import java.io.*; - -import javax.xml.stream.*; - -/** - * Unit test suite that tests handling of the xml declaration. - */ -public class TestXmlDecl - extends BaseStreamTest -{ - public TestXmlDecl(String name) { - super(name); - } - - final String VALID_XML1 - = ""; - - final String VALID_XML_UTF8 - = ""; - - /** - * Method that verifies properties that should be active when - * START_DOCUMENT is the current event (ie before iterating), ie. - * right after xml declaration has been read - */ - public void testProperties() - throws XMLStreamException - { - doTestProperties(false); - doTestProperties(true); - } - - public void testValidDecl() - throws XMLStreamException, IOException - { - doTestValid(false); - doTestValid(true); - } - - public void testValidStandaloneDecls() - throws XMLStreamException, IOException - { - String XML = ""; - XMLStreamReader sr = getReader(XML, true); - - assertEquals("1.0", sr.getVersion()); - assertTrue("XMLStreamReader.standalonSet() should be true", sr.standaloneSet()); - assertTrue("XMLStreamReader.isStandalone() should be true", sr.isStandalone()); - - - XML = ""; - sr = getReader(XML, true); - - assertEquals("1.0", sr.getVersion()); - assertTrue("XMLStreamReader.standalonSet() should be true", sr.standaloneSet()); - assertFalse("XMLStreamReader.isStandalone() should be false", sr.isStandalone()); - - // And then all of it: - - XML = ""; - sr = getReader(XML, true); - - assertEquals("1.0", sr.getVersion()); - assertTrue("XMLStreamReader.standalonSet() should be true", sr.standaloneSet()); - assertTrue("XMLStreamReader.isStandalone() should be true", sr.isStandalone()); - assertEquals("US-ASCII", sr.getCharacterEncodingScheme()); - } - - public void testInvalidDecl() - throws XMLStreamException - { - doTestInvalid(false); - doTestInvalid(true); - } - - /* - //////////////////////////////////////// - // Private methods, shared test code - //////////////////////////////////////// - */ - - private void doTestProperties(boolean nsAware) - throws XMLStreamException - { - XMLStreamReader sr = getReader(VALID_XML1, nsAware); - assertEquals(START_DOCUMENT, sr.getEventType()); - // Type info - assertEquals(false, sr.isStartElement()); - assertEquals(false, sr.isEndElement()); - assertEquals(false, sr.isCharacters()); - assertEquals(false, sr.isWhiteSpace()); - - // indirect type info - assertEquals(false, sr.hasName()); - assertEquals(false, sr.hasText()); - - /* Now... how about location and namespace context? Are they really - * guaranteed to exist at this point? Since API doesn't indicate - * otherwise, let's assume this is the case, for now. - */ - assertNotNull(sr.getLocation()); - if (nsAware) { - assertNotNull(sr.getNamespaceContext()); - } - - // And then let's check methods that should throw specific exception - for (int i = 0; i < 8; ++i) { - String method = ""; - - try { - Object result = null; - switch (i) { - case 0: - method = "getName"; - result = sr.getName(); - break; - case 1: - method = "getPrefix"; - result = sr.getPrefix(); - break; - case 2: - method = "getLocalName"; - result = sr.getLocalName(); - break; - case 3: - method = "getNamespaceURI"; - result = sr.getNamespaceURI(); - break; - case 4: - method = "getNamespaceCount"; - result = new Integer(sr.getNamespaceCount()); - break; - case 5: - method = "getAttributeCount"; - result = new Integer(sr.getAttributeCount()); - break; - case 6: - method = "getPITarget"; - result = sr.getPITarget(); - break; - case 7: - method = "getPIData"; - result = sr.getPIData(); - break; - } - fail("Expected IllegalStateException, when calling " - +method+"() for XML declaration (START_DOCUMENT)"); - } catch (IllegalStateException iae) { - ; // good - } - } - } - - private void doTestValid(boolean nsAware) - throws XMLStreamException, IOException - { - XMLStreamReader sr = getReader(VALID_XML1, nsAware); - - /* First, let's ensure that version is ok, and whether - * stand-alone pseudo-attr was set: - */ - assertEquals("1.0", sr.getVersion()); - assertFalse(sr.standaloneSet()); - - // Then, encoding passed via factory method: - sr = getUTF8StreamReader(VALID_XML1, nsAware); - assertEquals("UTF-8", sr.getEncoding()); - - // Then, automatic detection of encoding: - sr = getReader(VALID_XML_UTF8, nsAware); - assertEquals("1.0", sr.getVersion()); - assertEquals("UTF-8", sr.getCharacterEncodingScheme()); - } - - private void doTestInvalid(boolean nsAware) - throws XMLStreamException - { - String XML = ""; - streamThroughFailing(getFactory(nsAware), XML, - "invalid XML declaration (missing version)"); - - XML = ""; - streamThroughFailing(getFactory(nsAware), XML, - "invalid XML declaration (mismatch of quotes)"); - } - - /* - //////////////////////////////////////// - // Private methods, other - //////////////////////////////////////// - */ - - private XMLInputFactory getFactory(boolean nsAware) - throws XMLStreamException - { - XMLInputFactory f = getInputFactory(); - setCoalescing(f, false); // shouldn't matter - setNamespaceAware(f, nsAware); - setValidating(f, false); - return f; - } - - private XMLStreamReader getReader(String contents, boolean nsAware) - throws XMLStreamException - { - return constructStreamReader(getFactory(nsAware), contents); - } - - private XMLStreamReader getUTF8StreamReader(String contents, boolean nsAware) - throws XMLStreamException, UnsupportedEncodingException - { - XMLInputFactory f = getInputFactory(); - setCoalescing(f, false); // shouldn't matter - setNamespaceAware(f, nsAware); - setValidating(f, false); - InputStream in = new ByteArrayInputStream(contents.getBytes("UTF-8")); - return f.createXMLStreamReader(in, "UTF-8"); - } -} diff -Nru libwoodstox-java-4.1.3/src/test/org/codehaus/stax/test/vstream/BaseVStreamTest.java libwoodstox-java-5.1.0/src/test/org/codehaus/stax/test/vstream/BaseVStreamTest.java --- libwoodstox-java-4.1.3/src/test/org/codehaus/stax/test/vstream/BaseVStreamTest.java 2012-04-24 04:38:21.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/org/codehaus/stax/test/vstream/BaseVStreamTest.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,48 +0,0 @@ -package org.codehaus.stax.test.vstream; - -import javax.xml.stream.XMLInputFactory; -import javax.xml.stream.XMLStreamException; -import javax.xml.stream.XMLStreamReader; - -import org.codehaus.stax.test.stream.BaseStreamTest; - -/** - * Base class for all StaxTest unit tests that test validation-dependant - * parts of stream (cursor) API functionality. - * - * @author Tatu Saloranta - */ -abstract class BaseVStreamTest - extends BaseStreamTest -{ - protected BaseVStreamTest() { super(); } - - protected BaseVStreamTest(String name) { - super(name); - } - - protected XMLStreamReader getValidatingReader(String contents) - throws XMLStreamException - { - return getValidatingReader(contents, true); - } - - protected XMLStreamReader getValidatingReader(String contents, boolean nsAware) - throws XMLStreamException - { - XMLInputFactory f = getValidatingFactory(nsAware); - return constructStreamReader(f, contents); - } - - protected XMLInputFactory getValidatingFactory(boolean nsAware) - throws XMLStreamException - { - XMLInputFactory f = getInputFactory(); - setCoalescing(f, false); // shouldn't really matter - setNamespaceAware(f, nsAware); - setSupportDTD(f, true); - // Let's make sure DTD is really parsed? - setValidating(f, true); - return f; - } -} diff -Nru libwoodstox-java-4.1.3/src/test/org/codehaus/stax/test/vstream/TestAttrRead.java libwoodstox-java-5.1.0/src/test/org/codehaus/stax/test/vstream/TestAttrRead.java --- libwoodstox-java-4.1.3/src/test/org/codehaus/stax/test/vstream/TestAttrRead.java 2012-04-24 04:38:21.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/org/codehaus/stax/test/vstream/TestAttrRead.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,237 +0,0 @@ -package org.codehaus.stax.test.vstream; - -import javax.xml.stream.*; - -/** - * Unit test suite that tests basic handling of attributes; aspects - * that do not depend on actual concrete type. - */ -public class TestAttrRead - extends BaseVStreamTest -{ - public TestAttrRead(String name) { - super(name); - } - - /* - /////////////////////////////////////// - // Attribute declaration tests: - /////////////////////////////////////// - */ - - /** - * Simple tests for generic valid attribute declarations; using - * some constructs that can be warned about, but that are not - * erroneous. - */ - public void testValidAttrDecl() - throws XMLStreamException - { - /* First; declaring attributes for non-declared elements is - * not an error - */ - String XML = "\n" - +"\n" - +"]>\n"; - streamThrough(getValidatingReader(XML, true)); - - /* Then, declaring same attribute more than once is not an - * error; first one is binding (note: should test that this - * indeed happens, via attribute property inspection?) - */ - XML = "\n" - +"\n" - +"\n" - +"\n" - +"]>\n"; - streamThrough(getValidatingReader(XML, true)); - } - - /** - * Unit test that verifies that the attribute type declaration information - * is properly parsed and accessible via stream reader. - */ - public void testAttributeTypes() - throws XMLStreamException - { - String XML = "\n" - +"\n" - +"\n" - +"\n" - +"\n" - +"]>" - +""; - /* Could/should extend to cover all types... but this should be - * enough to at least determined reader does pass through the - * type info (instead of always returning CDATA) - */ - XMLStreamReader sr = getValidatingReader(XML, true); - - assertTokenType(DTD, sr.next()); - assertTokenType(START_ELEMENT, sr.next()); - - assertEquals(4, sr.getAttributeCount()); - for (int i = 0; i < 4; ++i) { - String ln = sr.getAttributeLocalName(i); - String type = sr.getAttributeType(i); - String expType = ln.toUpperCase(); - assertNotNull("Attribute type should never be null; CDATA should be returned if information not known/available"); - assertEquals("Incorrect attribute type for attribute '"+ln+"'", - expType, type); - } - assertTokenType(END_ELEMENT, sr.next()); - } - - public void testValidRequiredAttr() - throws XMLStreamException - { - // this should be valid: - String XML = "\n" - +"\n" - +"]>"; - XMLStreamReader sr = getValidatingReader(XML, true); - assertTokenType(DTD, sr.next()); - assertTokenType(START_ELEMENT, sr.next()); - - assertEquals(1, sr.getAttributeCount()); - assertEquals("attr", sr.getAttributeLocalName(0)); - assertEquals("value", sr.getAttributeValue(0)); - } - - public void testInvalidRequiredAttr() - throws XMLStreamException - { - // Invalid as it's missing the required attribute - String XML = "\n" - +"\n" - +"]>\n"; - streamThroughFailing(getValidatingReader(XML, true), - "Missing required attribute value"); - } - - public void testOkFixedAttr() - throws XMLStreamException - { - // Ok to omit altogether - String XML = "\n" - +"\n" - +"]>"; - // But if so, should get the default value - XMLStreamReader sr = getValidatingReader(XML, true); - assertTokenType(DTD, sr.next()); - assertTokenType(START_ELEMENT, sr.next()); - assertEquals("Should have 1 attribute; 'elem' had #FIXED default value", 1, sr.getAttributeCount()); - assertEquals("attr", sr.getAttributeLocalName(0)); - assertEquals("fixed", sr.getAttributeValue(0)); - assertTokenType(END_ELEMENT, sr.next()); - sr.close(); - - // Or to use fixed value - XML = "\n" - +"\n" - +"]>"; - sr = getValidatingReader(XML, true); - assertTokenType(DTD, sr.next()); - assertTokenType(START_ELEMENT, sr.next()); - assertEquals(1, sr.getAttributeCount()); - assertEquals("attr", sr.getAttributeLocalName(0)); - assertEquals("fixed", sr.getAttributeValue(0)); - assertTokenType(END_ELEMENT, sr.next()); - } - - public void testInvalidFixedAttr() - throws XMLStreamException - { - // Not ok to have any other value, either completely different - String XML = "\n" - +"\n" - +"]>\n"; - streamThroughFailing(getValidatingReader(XML), - "fixed attribute value not matching declaration"); - - // Or one with extra white space (CDATA won't get fully normalized) - XML = "\n" - +"\n" - +"]>\n"; - streamThroughFailing(getValidatingReader(XML), - "fixed attribute value not matching declaration"); - } - - /** - * Unit test that verifies that the default attribute values are properly - * used on validating mode. - */ - public void testDefaultAttr() - throws XMLStreamException - { - // Let's verify we get default value - String XML = "\n" - +"\n" - +"]>"; - XMLStreamReader sr = getValidatingReader(XML, true); - assertTokenType(DTD, sr.next()); - assertTokenType(START_ELEMENT, sr.next()); - - assertEquals(1, sr.getAttributeCount()); - assertEquals("attr", sr.getAttributeLocalName(0)); - assertEquals("default", sr.getAttributeValue(0)); - } - - /** - * Test for proper handling for multiple attribute declarations for - * a single attribute. This is legal, although discouraged (ie. parser - * can issue a non-fatal warning): but if used, the first definition - * should stick. Let's test for both default values and types. - */ - public void testMultipleDeclForSingleAttr() - throws XMLStreamException - { - // Let's verify we get the right default value - String XML = "\n" - +"\n" - +"\n" - +"]>"; - XMLStreamReader sr = getValidatingReader(XML, true); - assertTokenType(DTD, sr.next()); - assertTokenType(START_ELEMENT, sr.next()); - assertEquals(1, sr.getAttributeCount()); - assertEquals("attr", sr.getAttributeLocalName(0)); - assertEquals("val1", sr.getAttributeValue(0)); - - // And then let's test that the type is correct as well - XML = "\n" - +"\n" - +"\n" - +"]>"; - sr = getValidatingReader(XML, true); - assertTokenType(DTD, sr.next()); - assertTokenType(START_ELEMENT, sr.next()); - assertEquals(1, sr.getAttributeCount()); - assertEquals("attr", sr.getAttributeLocalName(0)); - assertEquals("valX", sr.getAttributeValue(0)); - assertEquals("NMTOKEN", sr.getAttributeType(0)); - } - - /* - //////////////////////////////////////// - // Private methods - //////////////////////////////////////// - */ -} diff -Nru libwoodstox-java-4.1.3/src/test/org/codehaus/stax/test/vstream/TestAttrTypes.java libwoodstox-java-5.1.0/src/test/org/codehaus/stax/test/vstream/TestAttrTypes.java --- libwoodstox-java-4.1.3/src/test/org/codehaus/stax/test/vstream/TestAttrTypes.java 2012-04-24 04:38:21.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/org/codehaus/stax/test/vstream/TestAttrTypes.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,106 +0,0 @@ -package org.codehaus.stax.test.vstream; - -import java.util.HashMap; - -import javax.xml.stream.*; - -/** - * Unit test suite that tests that attribute type information returned - * for all recognized types is as expected - */ -public class TestAttrTypes - extends BaseVStreamTest -{ - public TestAttrTypes(String name) { - super(name); - } - - /* - /////////////////////////////////////// - // Test cases - /////////////////////////////////////// - */ - - public void testAttrTypes() - throws XMLStreamException - { - // Let's verify we get default value - String XML = "\n" - +"\n" - +"]>" - +""; - XMLStreamReader sr = getValidatingReader(XML, true); - assertTokenType(DTD, sr.next()); - assertTokenType(START_ELEMENT, sr.next()); - int count = sr.getAttributeCount(); - assertEquals(7, count); - - HashMap seen = new HashMap(); - for (int i = 0; i < count; ++i) { - String name = sr.getAttributeLocalName(i); - String value = sr.getAttributeValue(i); - String old = (String) seen.put(name, value); - if (old != null) { - fail("Duplicate attribute '"+name+"': previous value: '"+value+"'"); - } - String type = sr.getAttributeType(i); - if (name.equals("attrCData")) { - assertEquals("CDATA", type); - } else if (name.equals("attrId")) { - assertEquals("ID", type); - } else if (name.equals("attrIdref")) { - assertEquals("IDREF", type); - } else if (name.equals("attrIdrefs")) { - assertEquals("IDREFS", type); - } else if (name.equals("attrEnum")) { - /* 25-Apr-2005, TSa: Not quite sure what would be the - * "official" name for the enumerated type? - */ - assertEquals("ENUMERATED", type); - } else if (name.equals("attrName")) { - assertEquals("NMTOKEN", type); - } else if (name.equals("attrNames")) { - assertEquals("NMTOKENS", type); - } else { - fail("Unexpected attribute '"+name+"'"); - } - } - } - - /* - //////////////////////////////////////// - // Private methods - //////////////////////////////////////// - */ - - private XMLStreamReader getReader(String contents) - throws XMLStreamException - { - XMLInputFactory f = getInputFactory(); - setCoalescing(f, false); // shouldn't really matter - //setNamespaceAware(f, nsAware); - setSupportDTD(f, true); - // Let's make sure DTD is really parsed? - setValidating(f, true); - return constructStreamReader(f, contents); - } -} diff -Nru libwoodstox-java-4.1.3/src/test/org/codehaus/stax/test/vstream/TestDTDElemRead.java libwoodstox-java-5.1.0/src/test/org/codehaus/stax/test/vstream/TestDTDElemRead.java --- libwoodstox-java-4.1.3/src/test/org/codehaus/stax/test/vstream/TestDTDElemRead.java 2012-04-24 04:38:21.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/org/codehaus/stax/test/vstream/TestDTDElemRead.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,112 +0,0 @@ -package org.codehaus.stax.test.vstream; - -import javax.xml.stream.*; - -/** - * Unit test suite that tests handling of DTD element declarations. - */ -public class TestDTDElemRead - extends BaseVStreamTest -{ - public TestDTDElemRead(String name) { - super(name); - } - - /* - /////////////////////////////////////// - // Element declaration tests: - /////////////////////////////////////// - */ - - public void testValidElementDecl() - throws XMLStreamException - { - /* Following should be ok; it is not an error to refer to - * undeclared elements... although it is to encounter such - * undeclared elements in content. - */ - String XML = "\n" - +"]>\n"; - streamThrough(getVReader(XML)); - } - - public void testInvalidElementDecl() - throws XMLStreamException - { - /* Then let's make sure that duplicate element declarations - * are caught (as they are errors): - */ - String XML = "\n" - +"\n" - +"\n" - +"]>\n"; - try { - streamThrough(getVReader(XML)); - fail("Expected an exception for duplicate ELEMENT declaration."); - } catch (XMLStreamException ex) { // good - } catch (RuntimeException ex2) { // ok - } catch (Throwable t) { // not so good - fail("Expected an XMLStreamException or RuntimeException for duplicate ELEMENT declaration, not: "+t); - } - } - - /** - * Let's ensure basic simple notation declarations are parsed - * succesfully. - */ - public void testValidNotationDecl() - throws XMLStreamException - { - // Will need a simple content model, too, since we are validating... - String XML = "\n" - +"\n" - +"\n" - +"]>"; - streamThrough(getVReader(XML)); - } - - /** - * This unit test checks that there are no duplicate notation declarations - */ - public void testInvalidDupNotationDecl() - throws XMLStreamException - { - /* Then let's make sure that duplicate element declarations - * are caught (as they are errors): - */ - String XML = "\n" - +"\n" - +"\n" - +"]>"; - try { - streamThrough(getVReader(XML)); - fail("Expected an exception for duplicate NOTATION declaration."); - } catch (XMLStreamException ex) { // good - } catch (RuntimeException ex2) { // ok - } catch (Throwable t) { // not so good - fail("Expected an XMLStreamException or RuntimeException for duplicate NOTATION declaration, not: "+t); - } - } - - /* - //////////////////////////////////////// - // Private methods - //////////////////////////////////////// - */ - - private XMLStreamReader getVReader(String contents) - throws XMLStreamException - { - XMLInputFactory f = getInputFactory(); - setCoalescing(f, false); // shouldn't really matter - //setNamespaceAware(f, nsAware); - setSupportDTD(f, true); - // Let's make sure DTD is really parsed? - setValidating(f, true); - return constructStreamReader(f, contents); - } -} diff -Nru libwoodstox-java-4.1.3/src/test/org/codehaus/stax/test/vstream/TestEntityAttrRead.java libwoodstox-java-5.1.0/src/test/org/codehaus/stax/test/vstream/TestEntityAttrRead.java --- libwoodstox-java-4.1.3/src/test/org/codehaus/stax/test/vstream/TestEntityAttrRead.java 2012-04-24 04:38:21.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/org/codehaus/stax/test/vstream/TestEntityAttrRead.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,200 +0,0 @@ -package org.codehaus.stax.test.vstream; - -import javax.xml.stream.*; - -/** - * Unit test suite that tests handling of attributes that are declared - * by DTD to be of type NOTATION. - * - * @author Tatu Saloranta - */ -public class TestEntityAttrRead - extends BaseVStreamTest -{ - /* - /////////////////////////////////////// - // Test cases - /////////////////////////////////////// - */ - - public void testValidEntityAttrDecl() - throws XMLStreamException - { - // Following should be ok; notations have been declared ok - String XML = "\n" - +"\n" - +"\n" - +"\n" - +"]>\n"; - streamThrough(getValidatingReader(XML)); - - // Likewise for default values - XML = "\n" - +"\n" - +"\n" - +"\n" - +"]>\n"; - streamThrough(getValidatingReader(XML)); - } - - public void testValidUnorderedEntityAttrDecl() - throws XMLStreamException - { - // Following should be ok even though ordering is reversed - String XML = "\n" - +"\n" - +"\n" - +"\n" - +"]>\n"; - try { - streamThrough(getValidatingReader(XML)); - } catch (XMLStreamException e) { - fail("Entity declaration order should not matter, but failed due to: "+e.getMessage()); - } - } - - public void testValidEntitiesAttrDecl() - throws XMLStreamException - { - // Following should be ok; notations have been declared ok - String XML = "\n" - +"\n" - +"\n" - +"\n" - +"]>\n"; - streamThrough(getValidatingReader(XML)); - - // and for default values - XML = "\n" - +"\n" - +"\n" - +"\n" - +"\n" - +"\n" - +"\n" - +"]>\n"; - streamThrough(getValidatingReader(XML)); - } - - public void testInvalidEntityAttrDecl() - throws XMLStreamException - { - // First, let's check that undeclared notation throws an exception - String XML = "\n" - +"\n" - +"\n" - +"\n" - +"]>\n"; - streamThroughFailing(getValidatingReader(XML), - "undeclared notation for ENTITY attribute"); - - // Similarly, undeclared entity via default value - XML = "\n" - +"\n" - +"\n" - +"\n" - +"]>\n"; - streamThroughFailing(getValidatingReader(XML), - "undeclared entity for ENTITY default value"); - } - - public void testInvalidEntitiesAttrDecl() - throws XMLStreamException - { - // First, let's check that undeclared notation throws an exception - String XML = "\n" - +"\n" - +"\n" - +"\n" - +"]>\n"; - streamThroughFailing(getValidatingReader(XML), - "undeclared notation for ENTITIES attribute"); - - // Similarly, undeclared entity via default value - XML = "\n" - +"\n" - +"\n" - +"\n" - +"]>\n"; - streamThroughFailing(getValidatingReader(XML), - "undeclared entity for ENTITIES default value"); - - XML = "\n" - +"\n" - +"\n" - +"\n" - +"]>\n"; - streamThroughFailing(getValidatingReader(XML), - "undeclared entity for ENTITIES default value"); - } - - public void testValidEntityAttrUse() - throws XMLStreamException - { - // Following should be ok; notations have been declared ok - String XML = "\n" - +"\n" - +"\n" - +"\n" - +"\n" - +"\n" - +"]>"; - - XMLStreamReader sr = getValidatingReader(XML); - // Let's ensure white space normalization too: - assertTokenType(DTD, sr.next()); - assertTokenType(START_ELEMENT, sr.next()); - assertEquals(1, sr.getAttributeCount()); - assertEquals("unpEnt2", sr.getAttributeValue(0)); - } - - public void testValidEntitiesAttrUse() - throws XMLStreamException - { - // Following should be ok; notations have been declared ok - String XML = "\n" - +"\n" - +"\n" - +"\n" - +"\n" - +"\n" - +"\n" - +"\n" - +"]>"; - streamThrough(getValidatingReader(XML)); - - XMLStreamReader sr = getValidatingReader(XML); - // Let's ensure white space normalization too: - assertTokenType(DTD, sr.next()); - assertTokenType(START_ELEMENT, sr.next()); - assertEquals(1, sr.getAttributeCount()); - assertEquals("unpEnt2 unpEnt3 unpEnt1", sr.getAttributeValue(0)); - } - - /* - public void testInvalidEntityAttrUse() - throws XMLStreamException - { - } - */ - - /* - public void testInvalidEntitiesAttrUse() - throws XMLStreamException - { - } - */ - -} diff -Nru libwoodstox-java-4.1.3/src/test/org/codehaus/stax/test/vstream/TestEnumAttrRead.java libwoodstox-java-5.1.0/src/test/org/codehaus/stax/test/vstream/TestEnumAttrRead.java --- libwoodstox-java-4.1.3/src/test/org/codehaus/stax/test/vstream/TestEnumAttrRead.java 2012-04-24 04:38:21.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/org/codehaus/stax/test/vstream/TestEnumAttrRead.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,129 +0,0 @@ -package org.codehaus.stax.test.vstream; - -import javax.xml.stream.*; - -/** - * Unit test suite that tests handling of attributes that are declared - * by DTD to be of type NOTATION. - */ -public class TestEnumAttrRead - extends BaseVStreamTest -{ - public TestEnumAttrRead(String name) { - super(name); - } - - /* - /////////////////////////////////////// - // Test cases - /////////////////////////////////////// - */ - - public void testValidAttrDecl() - throws XMLStreamException - { - // Ok, just a simple declaration... - String XML = "\n" - +"\n" - +"]>\n"; - streamThrough(getValidatingReader(XML, true)); - } - - - public void testValidAttrDecl2() - throws XMLStreamException - { - /* Following should be ok, only problematic if DTD parser is - * either trying to match SGML comments, or otherwise unhappy - * about hyphen starting an NMTOKEN. - */ - String XML = "\n" - +"\n" - +"]>\n"; - streamThrough(getReader(XML)); - } - - public void testInvalidAttrDecl() - throws XMLStreamException - { - // Duplicates are not allowed - String XML = "\n" - +"\n" - +"]>\n"; - streamThroughFailing(getValidatingReader(XML, true), - "duplicate enumeration in attribute declaration"); - } - - public void testValidAttrUse() - throws XMLStreamException - { - // Ok, just a simple declaration... - String XML = "\n" - +"\n" - +"]>"; - - XMLStreamReader sr = getValidatingReader(XML, true); - assertTokenType(DTD, sr.next()); - assertTokenType(START_ELEMENT, sr.next()); - - assertEquals(1, sr.getAttributeCount()); - assertEquals("attr2", sr.getAttributeLocalName(0)); - assertEquals("enum2", sr.getAttributeValue(0)); - } - - /** - * Unit test that verifies that values of attributes of type ID - * will get properly normalized. - */ - public void testEnumAttrNormalization() - throws XMLStreamException - { - String XML = "\n" - +"\n" - +"]>" - +"" - +"" - +"" - +""; - ; - XMLStreamReader sr = getValidatingReader(XML); - assertTokenType(DTD, sr.next()); - assertTokenType(START_ELEMENT, sr.next()); - assertEquals(1, sr.getAttributeCount()); - assertEquals("enum2", sr.getAttributeValue(0)); - assertTokenType(START_ELEMENT, sr.next()); - assertEquals(1, sr.getAttributeCount()); - assertEquals("enum", sr.getAttributeValue(0)); - assertTokenType(END_ELEMENT, sr.next()); - assertTokenType(START_ELEMENT, sr.next()); - assertEquals(1, sr.getAttributeCount()); - assertEquals("last", sr.getAttributeValue(0)); - assertTokenType(END_ELEMENT, sr.next()); - assertTokenType(END_ELEMENT, sr.next()); - } - - /* - //////////////////////////////////////// - // Private methods - //////////////////////////////////////// - */ - - private XMLStreamReader getReader(String contents) - throws XMLStreamException - { - XMLInputFactory f = getInputFactory(); - setCoalescing(f, false); // shouldn't really matter - //setNamespaceAware(f, nsAware); - setSupportDTD(f, true); - // Let's make sure DTD is really parsed? - setValidating(f, true); - return constructStreamReader(f, contents); - } -} diff -Nru libwoodstox-java-4.1.3/src/test/org/codehaus/stax/test/vstream/TestExternalSubset.java libwoodstox-java-5.1.0/src/test/org/codehaus/stax/test/vstream/TestExternalSubset.java --- libwoodstox-java-4.1.3/src/test/org/codehaus/stax/test/vstream/TestExternalSubset.java 2012-04-24 04:38:21.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/org/codehaus/stax/test/vstream/TestExternalSubset.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,80 +0,0 @@ -package org.codehaus.stax.test.vstream; - -import javax.xml.stream.*; - -import org.codehaus.stax.test.SimpleResolver; - -/** - * Unit test suite that verifies that external subsets can be used, and - * also tests some of features only legal in there (include/exclude, - * parameter entities within declarations) - * - * @author Tatu Saloranta - */ -public class TestExternalSubset - extends BaseVStreamTest -{ - public void testSimpleValidExternalSubset() - throws XMLStreamException - { - String XML = "" - +"text"; - String EXT_ENTITY_VALUE = "just testing"; - String EXT_SUBSET = - "\n" - +""; - - XMLStreamReader sr = getReader(XML, true, - new SimpleResolver(EXT_SUBSET)); - assertTokenType(DTD, sr.next()); - assertTokenType(START_ELEMENT, sr.next()); - assertEquals("root", sr.getLocalName()); - assertTokenType(CHARACTERS, sr.next()); - assertEquals("text", getAndVerifyText(sr)); - assertTokenType(END_ELEMENT, sr.next()); - sr.close(); - } - - public void testEntityInExternalSubset() - throws XMLStreamException - { - String XML = "" - +"&extEnt;"; - String EXT_ENTITY_VALUE = "just testing"; - String EXT_SUBSET = - "\n" - +"\n"; - - XMLStreamReader sr = getReader(XML, true, - new SimpleResolver(EXT_SUBSET)); - assertTokenType(DTD, sr.next()); - assertTokenType(START_ELEMENT, sr.next()); - assertEquals("root", sr.getLocalName()); - assertTokenType(CHARACTERS, sr.next()); - assertEquals(EXT_ENTITY_VALUE, getAndVerifyText(sr)); - assertTokenType(END_ELEMENT, sr.next()); - sr.close(); - } - - /* - //////////////////////////////////////// - // Private methods, other - //////////////////////////////////////// - */ - - private XMLStreamReader getReader(String contents, boolean nsAware, - XMLResolver resolver) - throws XMLStreamException - { - XMLInputFactory f = getInputFactory(); - setCoalescing(f, false); // shouldn't really matter - setNamespaceAware(f, nsAware); - setSupportDTD(f, true); - setValidating(f, true); - // This shouldn't be required but let's play it safe: - setSupportExternalEntities(f, true); - setResolver(f, resolver); - return constructStreamReader(f, contents); - } -} - diff -Nru libwoodstox-java-4.1.3/src/test/org/codehaus/stax/test/vstream/TestIdAttrRead.java libwoodstox-java-5.1.0/src/test/org/codehaus/stax/test/vstream/TestIdAttrRead.java --- libwoodstox-java-4.1.3/src/test/org/codehaus/stax/test/vstream/TestIdAttrRead.java 2012-04-24 04:38:21.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/org/codehaus/stax/test/vstream/TestIdAttrRead.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,234 +0,0 @@ -package org.codehaus.stax.test.vstream; - -import javax.xml.stream.*; - -/** - * Unit test suite that tests handling of attributes that are declared - * by DTD to be of type ID, IDREF or IDREFS; such information is only - * guranteed to be available in validation mode. - */ -public class TestIdAttrRead - extends BaseVStreamTest -{ - public TestIdAttrRead(String name) { - super(name); - } - - /* - /////////////////////////////////////// - // Test cases - /////////////////////////////////////// - */ - - /** - * Test case that verifies behaviour of valid ID/IDREF/IDREF - * attribute declarations. - */ - public void testValidIdAttrDecl() - throws XMLStreamException - { - // Following should be ok - String XML = "\n" - +"\n" - +"\n" - +"]>\n"; - streamThrough(getValidatingReader(XML)); - } - - /** - * Test case that verifies behaviour of invalid ID/IDREF/IDREF - * attribute declarations. - */ - public void testInvalidIdAttrDecl() - throws XMLStreamException - { - /* First, let's check couple of invalid id attr declarations - */ - - // Can not have default value for id attr - String XML = "\n" - +"\n" - +"]>\n"; - XMLStreamReader sr = getValidatingReader(XML); - streamThroughFailing(sr, "invalid attribute id (default value not allowed)"); - - // Nor require fixed value - sr = getValidatingReader("\n" - +"\n" - +"]>\n"); - streamThroughFailing(sr, "invalid id attribute (fixed value not allowed)"); - - // Only one attr id per element - sr = getValidatingReader("\n" - +"\n" - +"]>\n"); - streamThroughFailing(sr, "more than one attribute id per element"); - } - - public void testInvalidIdRefAttrDecl() - throws XMLStreamException - { - // IDREF default value needs to be valid id - XMLStreamReader sr = getValidatingReader("\n" - +"\n" - +"]>\n"); - streamThroughFailing(sr, "invalid IDREF default value ('#' not allowed)"); - sr = getValidatingReader("\n" - +"\n" - +"]>\n"); - streamThroughFailing(sr, "invalid (missing) IDREF default value"); - - // IDREFS default value needs to be non-empty set of valid ids - sr = getValidatingReader("\n" - +"\n" - +"]>\n"); - streamThroughFailing(sr, "invalid IDREFS default value ('?' not allowed)"); - sr = getValidatingReader("\n" - +"\n" - +"]>\n"); - streamThroughFailing(sr, "invalid (missing) IDREFS default value"); - } - - public void testValidIdAttrUse() - throws XMLStreamException - { - // Following should be ok; all ids are defined - String XML = "\n" - +"\n" - +"\n" - +"]>\n "; - streamThrough(getValidatingReader(XML)); - } - - public void testInvalidIdAttrUse() - throws XMLStreamException - { - // Error: undefined id 'someId' - String XML = "\n" - +"\n" - +"\n" - +"]>\n"; - streamThroughFailing(getValidatingReader(XML), - "undefined id reference for 'someId'"); - - // Error: empty idref value - XML = "\n" - +"\n" - +"\n" - +"]>\n"; - streamThroughFailing(getValidatingReader(XML), - "empty IDREF value"); - } - - public void testValidIdAttrsUse() - throws XMLStreamException - { - // Following should be ok; all ids are defined - String XML = "\n" - +"\n" - +"\n" - +"]>\n\n" - +"\n" - +""; - streamThrough(getValidatingReader(XML)); - } - - public void testInvalidIdAttrsUse() - throws XMLStreamException - { - // Error: undefined id 'someId' - String XML = "\n" - +"\n" - +"\n" - +"]>\n"; - streamThroughFailing(getValidatingReader(XML), - "undefined id reference for 'someId'"); - - // Error: empty idrefs value - XML = "\n" - +"\n" - +"\n" - +"]>\n"; - streamThroughFailing(getValidatingReader(XML), - "empty IDREFS value"); - } - - /** - * Unit test that verifies that values of attributes of type ID - * will get properly normalized. - */ - public void testIdAttrNormalization() - throws XMLStreamException - { - String XML = "\n" - +"\n" - +"\n" - +"]>" - +"" - +"" - +""; - ; - XMLStreamReader sr = getValidatingReader(XML); - assertTokenType(DTD, sr.next()); - assertTokenType(START_ELEMENT, sr.next()); - assertEquals(1, sr.getAttributeCount()); - assertEquals("someId", sr.getAttributeValue(0)); - assertTokenType(START_ELEMENT, sr.next()); - assertEquals(1, sr.getAttributeCount()); - assertEquals("otherId", sr.getAttributeValue(0)); - assertTokenType(END_ELEMENT, sr.next()); - assertTokenType(END_ELEMENT, sr.next()); - } - - public void testIdRefAttrNormalization() - throws XMLStreamException - { - String XML = "\n" - +"\n" - +"\n" - +"\n" - +"]>" - +"" - +"" - +"" - +""; - ; - - XMLStreamReader sr = getValidatingReader(XML); - assertTokenType(DTD, sr.next()); - assertTokenType(START_ELEMENT, sr.next()); - assertTokenType(START_ELEMENT, sr.next()); - assertEquals(2, sr.getAttributeCount()); - assertEquals("id2", sr.getAttributeValue(0)); - assertEquals("someId", sr.getAttributeValue(1)); - assertTokenType(END_ELEMENT, sr.next()); - assertTokenType(START_ELEMENT, sr.next()); - assertEquals(1, sr.getAttributeCount()); - assertEquals("id2 someId", sr.getAttributeValue(0)); - assertTokenType(END_ELEMENT, sr.next()); - assertTokenType(END_ELEMENT, sr.next()); - } - - /* - //////////////////////////////////////// - // Private methods - //////////////////////////////////////// - */ -} diff -Nru libwoodstox-java-4.1.3/src/test/org/codehaus/stax/test/vstream/TestIncludes.java libwoodstox-java-5.1.0/src/test/org/codehaus/stax/test/vstream/TestIncludes.java --- libwoodstox-java-4.1.3/src/test/org/codehaus/stax/test/vstream/TestIncludes.java 2012-04-24 04:38:21.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/org/codehaus/stax/test/vstream/TestIncludes.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,133 +0,0 @@ -package org.codehaus.stax.test.vstream; - -import java.io.StringReader; - -import javax.xml.stream.*; - -import org.codehaus.stax.test.SimpleResolver; - -/** - * Simple unit tests to check and verify that DTD handler properly deals - * with conditional sections. - * - * @author Tatu Saloranta - */ -public class TestIncludes - extends BaseVStreamTest -{ - public void testSimpleInclude() - throws XMLStreamException - { - final String XML = - "&myent;"; - ; - final String EXT_DTD = - "\n" - +"" - +"]]>\n" - ; - - XMLInputFactory f = getValidatingFactory(true); - setResolver(f, new SimpleResolver(EXT_DTD)); - XMLStreamReader sr = f.createXMLStreamReader(new StringReader(XML)); - assertTokenType(DTD, sr.next()); - assertTokenType(START_ELEMENT, sr.next()); - assertTokenType(CHARACTERS, sr.next()); - assertEquals("value", getAndVerifyText(sr)); - assertTokenType(END_ELEMENT, sr.next()); - } - - public void testSimpleIgnore() - throws XMLStreamException - { - final String XML = - "&myent;"; - ; - - /* Let's add something that'd be invalid in there... - */ - final String EXT_DTD = - "\n" - +" " - +"]]>\n" - +"" - ; - - XMLInputFactory f = getValidatingFactory(true); - setResolver(f, new SimpleResolver(EXT_DTD)); - XMLStreamReader sr = f.createXMLStreamReader(new StringReader(XML)); - assertTokenType(DTD, sr.next()); - assertTokenType(START_ELEMENT, sr.next()); - assertTokenType(CHARACTERS, sr.next()); - assertEquals("value", getAndVerifyText(sr)); - assertTokenType(END_ELEMENT, sr.next()); - } - - /** - * Conditional sections can NOT be used in the internal subset -- - * let's quickly verify this. - */ - public void testFailingInIntSubset() - throws XMLStreamException - { - // first inclusion: - String XML = - "" - +"]]>" - +"]>\n" - ; - streamThroughFailing(getValidatingReader(XML), - "Condition INCLUDE not allowed in internal DTD subset"); - - // Then IGNORE: - XML = - "" - +"]]>" - +" " - +"]>\n" - ; - streamThroughFailing(getValidatingReader(XML), - "Condition INCLUDE not allowed in internal DTD subset"); - } - - /** - * Ok, and then we better consider parameter entity expanded variations - * of INCLUDE/IGNORE directives (see example under XML 1.0.3 section 3.4 - * for a sample) - */ - public void testPEIncludeAndIgnore() - throws XMLStreamException - { - final String XML = "&myent;"; - ; - final String EXT_DTD = - "\n" - +"\n" - +"\n" - +"]]>\n" - +"\n" - +"]]>\n" - +"\n" - ; - - XMLInputFactory f = getValidatingFactory(true); - setResolver(f, new SimpleResolver(EXT_DTD)); - XMLStreamReader sr = f.createXMLStreamReader(new StringReader(XML)); - assertTokenType(DTD, sr.next()); - assertTokenType(START_ELEMENT, sr.next()); - assertTokenType(CHARACTERS, sr.next()); - String text = getAndVerifyText(sr); - if (!text.equals("include")) { - fail("Expected 'myent' to expand to 'include', not '"+text+"'"); - } - assertTokenType(END_ELEMENT, sr.next()); - } -} diff -Nru libwoodstox-java-4.1.3/src/test/org/codehaus/stax/test/vstream/TestInvalidDTD.java libwoodstox-java-5.1.0/src/test/org/codehaus/stax/test/vstream/TestInvalidDTD.java --- libwoodstox-java-4.1.3/src/test/org/codehaus/stax/test/vstream/TestInvalidDTD.java 2012-04-24 04:38:21.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/org/codehaus/stax/test/vstream/TestInvalidDTD.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,103 +0,0 @@ -package org.codehaus.stax.test.vstream; - -import javax.xml.stream.*; - -/** - * Simple unit test suite that checks for set of well-formedness problems - * with DTDs - * - * @author Tatu Saloranta - */ -public class TestInvalidDTD - extends BaseVStreamTest -{ - public void testInvalidDirectives() - throws XMLStreamException - { - String XML = "\n" - +"]>\n"; - streamThroughFailing(getValidatingReader(XML), "invalid directive ''"); - - XML = "\n" - +"\n" - +"]>\n"; - streamThroughFailing(getValidatingReader(XML), "invalid directive ''"); - } - - public void testInvalidGE() - throws XMLStreamException - { - // Need space between name, content - String XML = "\n" - +"]>\n"; - streamThroughFailing(getValidatingReader(XML), - "missing space between general entity name and value"); - } - - public void testInvalidPE() - throws XMLStreamException - { - // Need space between name, content - String XML = "\n" - +"\n" - +"]>\n"; - streamThroughFailing(getValidatingReader(XML), "missing space between parameter entity name and value"); - - // As well as before and after percent sign - XML = "\n" - +"\n" - +"]>\n"; - streamThroughFailing(getValidatingReader(XML), "missing space between parameter entity percent sign and name"); - XML = "\n" - +"\n" - +"]>"; - streamThroughFailing(getValidatingReader(XML), "missing space between ENTITY and parameter entity percent sign"); - - // and finally, no NDATA allowed for PEs - XML = "\n" - +"\n" - +"\n" - +"]>\n"; - streamThroughFailing(getValidatingReader(XML), "PEs can not be unparsed external (ie. have NDATA reference)"); - } - - public void testInvalidComment() - throws XMLStreamException - { - String XML = "\n" - +"\n" - +"]>"; - streamThroughFailing(getValidatingReader(XML), "invalid directive ''"); - } - - public void testInvalidPI() - throws XMLStreamException - { - String XML = "\n" - +"\n" - +"]>"; - streamThroughFailing(getValidatingReader(XML), "invalid processing instruction in DTD; can not have target 'xml'"); - } - - /** - * CDATA directive not allowed in DTD subsets. - */ - public void testInvalidCData() - throws XMLStreamException - { - String XML = "\n" - +"\n" - +"]>"; - streamThroughFailing(getValidatingReader(XML), "invalid CDATA directive in int. DTD subset"); - } -} diff -Nru libwoodstox-java-4.1.3/src/test/org/codehaus/stax/test/vstream/TestNmTokenAttrRead.java libwoodstox-java-5.1.0/src/test/org/codehaus/stax/test/vstream/TestNmTokenAttrRead.java --- libwoodstox-java-4.1.3/src/test/org/codehaus/stax/test/vstream/TestNmTokenAttrRead.java 2012-04-24 04:38:21.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/org/codehaus/stax/test/vstream/TestNmTokenAttrRead.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,136 +0,0 @@ -package org.codehaus.stax.test.vstream; - -import javax.xml.stream.*; - -/** - * Unit test suite that tests handling of attributes that are declared - * by DTD to be of type NMTOKEN or NMTOKENS; such information is only - * guranteed to be available in validation mode. - */ -public class TestNmTokenAttrRead - extends BaseVStreamTest -{ - /* - /////////////////////////////////////// - // Test cases - /////////////////////////////////////// - */ - - /** - * Test case that verifies behaviour of valid NMTOKEN/NMTOKENS - * attribute declarations. - */ - public void testValidNmTokenAttrDecl() - throws XMLStreamException - { - // Following should be ok - String XML = "\n" - +"\n" - +"]>\n"; - streamThrough(getValidatingReader(XML)); - } - - /** - * Test case that verifies behaviour of invalid NMTOKEN/NMTOKENS - * attribute declarations. - */ - public void testInvalidNmTokenAttrDecl() - throws XMLStreamException - { - // ??? Are there any such cases? - } - - public void testValidNmTokenAttrUse() - throws XMLStreamException - { - String XML = "\n" - +"\n" - +"\n" - +"]>\n "; - streamThrough(getValidatingReader(XML)); - } - - public void testInvalidNmTokenAttrUse() - throws XMLStreamException - { - // Error: invalid NMTOKEN, ? not valid - String XML = "\n" - +"\n" - +"]>\n"; - streamThroughFailing(getValidatingReader(XML), - "invalid char ('?') in NMTOKEN"); - - // Error: invalid NMTOKENS, / not valid - XML = "\n" - +"\n" - +"]>\n"; - streamThroughFailing(getValidatingReader(XML), - "invalid char ('/') in NMTOKENS"); - } - - /** - * Unit test that verifies that values of attributes of type NMTOKEN and - * NMTOKENS will get properly normalized. - */ - public void testNmTokenAttrNormalization() - throws XMLStreamException - { - String XML = "\n" - +"\n" - +"\n" - +"\n" - +"\n" - +"\n" - +"\n" - +"]>" - +"" - +"" - +"" - +"" - +""; - ; - XMLStreamReader sr = getValidatingReader(XML); - assertTokenType(DTD, sr.next()); - assertTokenType(START_ELEMENT, sr.next()); - assertEquals("elem", sr.getLocalName()); - assertEquals(1, sr.getAttributeCount()); - assertEquals("nmToken", sr.getAttributeValue(0)); - assertTokenType(START_ELEMENT, sr.next()); - assertEquals(1, sr.getAttributeCount()); - assertEquals("name", sr.getAttributeValue(0)); - assertTokenType(END_ELEMENT, sr.next()); - assertTokenType(START_ELEMENT, sr.next()); - assertEquals(1, sr.getAttributeCount()); - assertEquals("first_name second last", sr.getAttributeValue(0)); - assertTokenType(END_ELEMENT, sr.next()); - - // then the defaults - assertTokenType(START_ELEMENT, sr.next()); - assertEquals("elem2", sr.getLocalName()); - assertEquals(1, sr.getAttributeCount()); - assertEquals("name", sr.getAttributeLocalName(0)); - assertEquals("somename", sr.getAttributeValue(0)); - assertTokenType(END_ELEMENT, sr.next()); - - assertTokenType(START_ELEMENT, sr.next()); - assertEquals("elem3", sr.getLocalName()); - assertEquals(1, sr.getAttributeCount()); - assertEquals("names", sr.getAttributeLocalName(0)); - assertEquals("name1 name2 name3", sr.getAttributeValue(0)); - assertTokenType(END_ELEMENT, sr.next()); - - assertTokenType(END_ELEMENT, sr.next()); - } - - /* - //////////////////////////////////////// - // Private methods - //////////////////////////////////////// - */ -} diff -Nru libwoodstox-java-4.1.3/src/test/org/codehaus/stax/test/vstream/TestNotationAttrRead.java libwoodstox-java-5.1.0/src/test/org/codehaus/stax/test/vstream/TestNotationAttrRead.java --- libwoodstox-java-4.1.3/src/test/org/codehaus/stax/test/vstream/TestNotationAttrRead.java 2012-04-24 04:38:21.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/org/codehaus/stax/test/vstream/TestNotationAttrRead.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,163 +0,0 @@ -package org.codehaus.stax.test.vstream; - -import javax.xml.stream.*; - -/** - * Unit test suite that tests handling of attributes that are declared - * by DTD to be of type NOTATION. - * - * @author Tatu Saloranta - */ -public class TestNotationAttrRead - extends BaseVStreamTest -{ - /* - /////////////////////////////////////// - // Test cases - /////////////////////////////////////// - */ - - public void testValidAttrDecl() - throws XMLStreamException - { - // Following should be ok; notations have been declared ok - String XML = "\n" - +"\n" - +"\n" - +"" - +"]>\n"; - streamThrough(getValidatingReader(XML)); - - // Likewise for default values - XML = "\n" - +"\n" - +"\n" - +"" - +"]>\n"; - streamThrough(getValidatingReader(XML)); - } - - /** - * This unit test verifies that the ordering of ATTLIST declaration - * and NOTATION(s) it refers to need not be done in a specific - * order. - */ - public void testValidUnorderedAttrDecl() - throws XMLStreamException - { - String XML = "\n" - +"" - +"\n" - +"]>\n"; - try { - streamThrough(getValidatingReader(XML)); - } catch (XMLStreamException e) { - fail("Notation declaration order should not matter, but failed due to: "+e.getMessage()); - } - - // Likewise for default values - XML = "\n" - +"" - +"\n" - +"]>\n"; - try { - streamThrough(getValidatingReader(XML)); - } catch (XMLStreamException e) { - fail("Notation declaration order should not matter, but failed due to: "+e.getMessage()); - } - } - - public void testInvalidAttrDecl() - throws XMLStreamException - { - // First, let's check that undeclared notation throws an exception - String XML = "\n" - +"" - +"]>\n"; - - XMLStreamReader sr = getValidatingReader(XML); - streamThroughFailing(sr, "undeclared notation"); - - // And then that only one attribute of type NOTATION is allowed per element - XML = "\n" - +"\n" - +"\n" - +"]>\n"; - - sr = getValidatingReader(XML); - streamThroughFailing(sr, "more than one notation attribute per element"); - - // Also, notation ids can not be duplicates - XML = "\n" - +"\n" - +"\n" - +"\n" - +"]>\n"; - - sr = getValidatingReader(XML); - streamThroughFailing(sr, "duplicate notation values enumerated for attribute"); - } - - public void testValidAttrUse() - throws XMLStreamException - { - // Following should be ok, everything defined as required... - String XML = "\n" - +"\n" - +"\n" - +"\n" - +"]>\n"; - streamThrough(getReader(XML)); - } - - public void testInvalidAttrUse() - throws XMLStreamException - { - // Shouldn't work, undefined notation... - String XML = "\n" - +"\n" - +"\n" - +"]>\n"; - - XMLStreamReader sr = getValidatingReader(XML); - streamThroughFailing(sr, "reference to notation that is not enumerated"); - - // and same using default values - XML = "\n" - +"\n" - +"\n" - +"]>\n"; - - sr = getValidatingReader(XML); - streamThroughFailing(sr, "reference to notation (via default value) that is not enumerated"); - } - - /* - //////////////////////////////////////// - // Private methods - //////////////////////////////////////// - */ - - private XMLStreamReader getReader(String contents) - throws XMLStreamException - { - XMLInputFactory f = getInputFactory(); - setCoalescing(f, false); // shouldn't really matter - //setNamespaceAware(f, nsAware); - setSupportDTD(f, true); - // Let's make sure DTD is really parsed? - setValidating(f, true); - return constructStreamReader(f, contents); - } -} diff -Nru libwoodstox-java-4.1.3/src/test/org/codehaus/stax/test/vstream/TestParamEntities.java libwoodstox-java-5.1.0/src/test/org/codehaus/stax/test/vstream/TestParamEntities.java --- libwoodstox-java-4.1.3/src/test/org/codehaus/stax/test/vstream/TestParamEntities.java 2012-04-24 04:38:21.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/org/codehaus/stax/test/vstream/TestParamEntities.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,59 +0,0 @@ -package org.codehaus.stax.test.vstream; - -import java.io.StringReader; -import java.util.*; - -import javax.xml.stream.*; - -import org.codehaus.stax.test.SimpleResolver; - -/** - * Unit test suite that tests various aspects of parameter entity resolution - * in the external DTD subset. - * - * @author Tatu Saloranta - */ -public class TestParamEntities - extends BaseVStreamTest -{ - /** - * Test similar to one in xmltest (valid/not-sa/003.xml, specifically) - */ - public void testExternalParamDeclViaPE() - throws XMLStreamException - { - HashMap m = new HashMap(); - m.put("ent1", "\n" - +"\n" - +""); - m.put("ent2", ""); - - // Following should be ok; notations have been declared ok - String XML = ""; - - XMLInputFactory f = getValidatingFactory(true); - setResolver(f, new MyResolver(m)); - XMLStreamReader sr = f.createXMLStreamReader(new StringReader(XML)); - - streamThrough(getValidatingReader(XML)); - } - - final static class MyResolver - implements XMLResolver - { - final Map mEntities; - - public MyResolver(Map entities) { - mEntities = entities; - } - - public Object resolveEntity(String publicID, String systemID, String baseURI, String namespace) - { - String str = (String) mEntities.get(publicID); - if (str == null) { - str = (String) mEntities.get(systemID); - } - return (str == null) ? null : new StringReader(str); - } - } -} diff -Nru libwoodstox-java-4.1.3/src/test/org/codehaus/stax/test/vstream/TestStructuralValidation.java libwoodstox-java-5.1.0/src/test/org/codehaus/stax/test/vstream/TestStructuralValidation.java --- libwoodstox-java-4.1.3/src/test/org/codehaus/stax/test/vstream/TestStructuralValidation.java 2012-04-24 04:38:21.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/org/codehaus/stax/test/vstream/TestStructuralValidation.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,448 +0,0 @@ -package org.codehaus.stax.test.vstream; - -import javax.xml.stream.*; - -/** - * Unit test suite that tests structural validation using DTD. - */ -public class TestStructuralValidation - extends BaseVStreamTest -{ - public TestStructuralValidation(String name) { - super(name); - // Uncomment to see if we get exceptions we should be getting: - //PRINT_EXP_EXCEPTION = true; - } - - public void testValidStructure() - throws XMLStreamException - { - for (int i = 0; i < 2; ++i) { - boolean nsAware = (i > 0); - String XML = "\n" - +"\n" - +"\n" - +"]>\n Text "; - streamThrough(getReader(XML, nsAware)); - } - } - - public void testValidStructure2() - throws XMLStreamException - { - for (int i = 0; i < 2; ++i) { - boolean nsAware = (i > 0); - String XML = "\n" - +"\n" - +"\n" - +"]>\n text"; - streamThrough(getReader(XML, nsAware)); - - // Ok, as leaf is optional... - XML = "\n" - +"\n" - +"]>\n"; - streamThrough(getReader(XML, nsAware)); - - XML = "\n" - +"\n" - +"]>\n text & and more"; - streamThrough(getReader(XML, nsAware)); - } - } - - public void testValidSimpleSeqStructure() - throws XMLStreamException - { - for (int i = 0; i < 2; ++i) { - boolean nsAware = (i > 0); - String XML = "\n" - +"\n" - +"\n" - +"\n" - +"\n" - +"]>\n" - +"\n" - +"" - +""; - streamThrough(getReader(XML, nsAware)); - } - } - - public void testInvalidSimpleSeqStructure() - throws XMLStreamException - { - for (int i = 0; i < 2; ++i) { - boolean nsAware = (i > 0); - String XML = "\n" - +"\n" - +"\n" - +"\n" - +"\n" - +"]>\n" - +"\n" - +"" - +""; - streamThroughFailing(getReader(XML, nsAware), - "invalid simple content sequence: missing 'a3' element"); - - XML = "\n" - +"\n" - +"\n" - +"\n" - +"\n" - +"]>\n" - +"\n" - +"" - +""; - streamThroughFailing(getReader(XML, nsAware), - "invalid simple content sequence: missing 'a4' element"); - } - } - - public void testValidSimpleChoiceStructure() - throws XMLStreamException - { - for (int i = 0; i < 2; ++i) { - boolean nsAware = (i > 0); - String XML = "\n" - +"\n" - +"\n" - +"\n" - +"\n" - +"\n" - +"\n" - +"\n" - +"\n" - +"\n" - +"]>\n" - +"\n" - +"" - +""; - streamThrough(getReader(XML, nsAware)); - } - } - - public void testInvalidSimpleChoiceStructure() - throws XMLStreamException - { - for (int i = 0; i < 2; ++i) { - boolean nsAware = (i > 0); - String XML = "\n" - +"\n" - +"\n" - +"\n" - +"\n" - +"]>\n" - +"\n" - +""; - streamThroughFailing(getReader(XML, nsAware), - "invalid choice content sequence: no children for root"); - - XML = "\n" - +"\n" - +"\n" - +"\n" - +"\n" - +"]>\n" - +"" - +""; - streamThroughFailing(getReader(XML, nsAware), - "invalid choice content sequence: more than one child"); - - XML = "\n" - +"\n" - +"\n" - +"\n" - +"]>\n" - +"" - +""; - streamThroughFailing(getReader(XML, nsAware), - "invalid choice content sequence: c1 not one of legal children for root"); - } - } - - public void testValidFullChoiceStructure() - throws XMLStreamException - { - for (int i = 0; i < 2; ++i) { - boolean nsAware = (i > 0); - String XML = "\n" - +"\n" - +"\n" - +"\n" - +"\n" - +"]>\n" - +"\n" - +"" - +""; - streamThrough(getReader(XML, nsAware)); - } - } - - public void testValidMixed() - throws XMLStreamException - { - for (int i = 0; i < 2; ++i) { - boolean nsAware = (i > 0); - String XML = "\n" - +"\n" - +"]>Text "; - streamThrough(getReader(XML, nsAware)); - } - } - - public void testInvalidWrongRoot() - throws XMLStreamException - { - for (int i = 0; i < 2; ++i) { - boolean nsAware = (i > 0); - String XML = " "; - streamThroughFailing(getReader(XML, nsAware), "wrong root element"); - } - } - - public void testInvalidMixed() - throws XMLStreamException - { - for (int i = 0; i < 2; ++i) { - boolean nsAware = (i > 0); - String XML = "\n" - +"\n" - +"]>Text "; - streamThroughFailing(getReader(XML, nsAware), - "invalid mixed content"); - - // same, but after a child elem... - XML = "\n" - +"\n" - +"]> x "; - streamThroughFailing(getReader(XML, nsAware), - "invalid mixed content"); - } - } - - public void testInvalidStructureRoot() - throws XMLStreamException - { - for (int i = 0; i < 2; ++i) { - boolean nsAware = (i > 0); - - // First, wrong root element - String XML = "\n" - +"\n" - +"\n" - +"]>\n"; - streamThroughFailing(getReader(XML, nsAware), - "wrong root element"); - - // Then undeclared (root) element - XML = "\n" - +"]>\n "; - streamThroughFailing(getReader(XML, nsAware), - "undeclared element"); - - // Then one wrong element content for root - XML = "\n" - +"\n" - +"\n" - +"]>\n "; - streamThroughFailing(getReader(XML, nsAware), - "wrong element content (expected branch+, end; got nothing) for root"); - } - } - - public void testInvalidStructure() - throws XMLStreamException - { - for (int i = 0; i < 2; ++i) { - boolean nsAware = (i > 0); - - // And then just wrong ordering of child elements - String XML = "\n" - +"\n" - +"\n" - +"]>\n "; - streamThroughFailing(getReader(XML, nsAware), - "wrong element content (ordering) for root"); - - XML = "\n" - +"\n" - +"\n" - +"]>\n xyz"; - streamThroughFailing(getReader(XML, nsAware), - "wrong element content (missing 'end' element) for root"); - - XML = "\n" - +"\n" - +"\n" - +"]>\n "; - streamThroughFailing(getReader(XML, nsAware), - "missing children for root"); - - XML = "\n" - +"\n" - +"\n" - +"\n" - +"]>\n "; - streamThroughFailing(getReader(XML, nsAware), - "wrong child element for branch"); - } - } - - final static String COMPLEX_DTD = - "\n" - +"\n" - +"\n" - +"\n" - +"\n" - +"\n" - +"\n" - +"\n" - +"\n" - +"\n" - ; - - public void testValidStructureComplex() - throws XMLStreamException - { - for (int i = 0; i < 2; ++i) { - boolean nsAware = (i > 0); - - // And then just wrong ordering of child elements - String XML = "" - +"" - +" " - +" " - +" " - +" " - +"" - ; - streamThrough(getReader(XML, nsAware)); - } - } - - public void testInvalidStructureComplex() - throws XMLStreamException - { - for (int i = 0; i < 2; ++i) { - boolean nsAware = (i > 0); - - // And then just wrong ordering of child elements - String XML = "" - +"" - +" " - +" " - // b is missing: - +" " - +" " - +"" - ; - streamThroughFailing(getReader(XML, nsAware), - "wrong element structure; missing element "); - } - } - - /** - * Unit test that checks that it's illegal to add any content (including - * comment, processing instructions or white space) within an element that has - * content declaration of EMPTY. - */ - public void testInvalidEmpty() - throws XMLStreamException - { - for (int i = 0; i < 2; ++i) { - boolean nsAware = (i > 0); - String XML = "\n" - +"]>"; - streamThroughFailing(getReader(XML, nsAware), - "comment within element that has EMPTY content type declaration"); - - XML = "\n" - +"]>"; - streamThroughFailing(getReader(XML, nsAware), - "processing instruction within element that has EMPTY content type declaration"); - - XML = "\n" - +"]> "; - streamThroughFailing(getReader(XML, nsAware), - "white space within element that has EMPTY content type declaration"); - - XML = "\n" - +"\n" - +"]>"; - streamThroughFailing(getReader(XML, nsAware), - "element within element that has EMPTY content type declaration"); - } - } - - public void testValidAny() - throws XMLStreamException - { - for (int i = 0; i < 2; ++i) { - boolean nsAware = (i > 0); - String XML = "\n" - +"\n" - +"\n" - +"]> "; - streamThrough(getReader(XML, nsAware)); - } - } - - public void testInvalidAny() - throws XMLStreamException - { - for (int i = 0; i < 2; ++i) { - boolean nsAware = (i > 0); - String XML = "\n" - +"]>"; - streamThroughFailing(getReader(XML, nsAware), - "undeclared element in element with ANY content type"); - } - } - - /* - //////////////////////////////////////// - // Private methods, other - //////////////////////////////////////// - */ - - private XMLStreamReader getReader(String contents, boolean nsAware) - throws XMLStreamException - { - XMLInputFactory f = getInputFactory(); - setCoalescing(f, false); // shouldn't really matter - setNamespaceAware(f, nsAware); - setSupportDTD(f, true); - setValidating(f, true); - return constructStreamReader(f, contents); - } -} diff -Nru libwoodstox-java-4.1.3/src/test/org/codehaus/stax/test/vstream/TestSubsetCombination.java libwoodstox-java-5.1.0/src/test/org/codehaus/stax/test/vstream/TestSubsetCombination.java --- libwoodstox-java-4.1.3/src/test/org/codehaus/stax/test/vstream/TestSubsetCombination.java 2012-04-24 04:38:21.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/org/codehaus/stax/test/vstream/TestSubsetCombination.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,96 +0,0 @@ -package org.codehaus.stax.test.vstream; - -import javax.xml.stream.*; - -import org.codehaus.stax.test.SimpleResolver; - -/** - * Unit test suite that tests how implementation handles combining of - * internal and external DTD subsets. - * - * @author Tatu Saloranta - */ -public class TestSubsetCombination - extends BaseVStreamTest -{ - /** - * This unit test checks that a DTD definition that is evenly split - * between subsets will be properly combined, and results in a usable - * definition for validation. - */ - public void testValidSubsets() - throws XMLStreamException - { - // Note: need to resolve using a custom resolver - String XML = - "\n" - +"\n" - +"\n" - +"]> Test entities: &ent1;, &ent2;" - +"..." - +""; - String EXT_DTD = - "\n" - +"\n" - +"\n" - ; - streamThrough(getReader(XML, true, EXT_DTD)); - // Let's also test that non-ns works, just in case it's different - streamThrough(getReader(XML, false, EXT_DTD)); - } - - /** - * This unit test checks that the internal subset has precedence - * for attribute definitions -- it's ok to declare attributes multiple - * times, but the first one sticks, and internal subset is considered - * to come before external subset - */ - public void testAttributePrecedence() - throws XMLStreamException - { - String XML = - "\n" - +"\n" - +"\n" - +"]>" - ; - String EXT_DTD = - "\n" - +"\n" - ; - XMLStreamReader sr = getReader(XML, true, EXT_DTD); - assertTokenType(DTD, sr.next()); - assertTokenType(START_ELEMENT, sr.next()); - assertEquals(1, sr.getAttributeCount()); - assertEquals("attr2", sr.getAttributeLocalName(0)); - assertEquals("intValue", sr.getAttributeValue(0)); - assertFalse(sr.isAttributeSpecified(0)); - } - - /* - //////////////////////////////////////// - // Non-test methods - //////////////////////////////////////// - */ - - private XMLStreamReader getReader(String contents, boolean nsAware, - String extSubset) - throws XMLStreamException - { - XMLInputFactory f = getInputFactory(); - setNamespaceAware(f, nsAware); - setSupportDTD(f, true); - setCoalescing(f, false); - setReplaceEntities(f, true); - setValidating(f, true); - if (extSubset != null) { - setResolver(f, new SimpleResolver(extSubset)); - } else { - setResolver(f, null); - } - return constructStreamReader(f, contents); - } -} - diff -Nru libwoodstox-java-4.1.3/src/test/org/codehaus/stax/test/wstream/BaseWriterTest.java libwoodstox-java-5.1.0/src/test/org/codehaus/stax/test/wstream/BaseWriterTest.java --- libwoodstox-java-4.1.3/src/test/org/codehaus/stax/test/wstream/BaseWriterTest.java 2012-04-24 04:38:21.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/org/codehaus/stax/test/wstream/BaseWriterTest.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,35 +0,0 @@ -package org.codehaus.stax.test.wstream; - -import java.io.*; - -import javax.xml.stream.*; - -import org.codehaus.stax.test.BaseStaxTest; - -/** - * Base class for all StaxTest unit tests that test basic - * stream (cursor) writer API functionality. - * - * @author Tatu Saloranta - */ -abstract class BaseWriterTest - extends BaseStaxTest -{ - public XMLStreamWriter getRepairingWriter(Writer w) - throws XMLStreamException - { - XMLOutputFactory f = getOutputFactory(); - f.setProperty(XMLOutputFactory.IS_REPAIRING_NAMESPACES, - Boolean.TRUE); - return f.createXMLStreamWriter(w); - } - - public XMLStreamWriter getNonRepairingWriter(Writer w) - throws XMLStreamException - { - XMLOutputFactory f = getOutputFactory(); - f.setProperty(XMLOutputFactory.IS_REPAIRING_NAMESPACES, - Boolean.FALSE); - return f.createXMLStreamWriter(w); - } -} diff -Nru libwoodstox-java-4.1.3/src/test/org/codehaus/stax/test/wstream/TestOutputEncoding.java libwoodstox-java-5.1.0/src/test/org/codehaus/stax/test/wstream/TestOutputEncoding.java --- libwoodstox-java-4.1.3/src/test/org/codehaus/stax/test/wstream/TestOutputEncoding.java 2012-04-24 04:38:21.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/org/codehaus/stax/test/wstream/TestOutputEncoding.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,109 +0,0 @@ -package org.codehaus.stax.test.wstream; - -import javax.xml.stream.*; - -import java.io.*; - -/** - * Set of unit tests for verifying operation of {@link XMLStreamWriter} - * when outputting text nodes that contain characters that should - * be quoted. - * - * @author Tatu Saloranta - */ -public class TestOutputEncoding - extends BaseWriterTest -{ - final String ISO_LATIN_ENCODING = "ISO-8859-1"; - final String UTF8_ENCODING = "UTF-8"; - - public void testSimpleContentQuoting() - throws IOException, XMLStreamException - { - String TEXT = "&"; - doTestSimpleQuoting(ISO_LATIN_ENCODING, TEXT); - doTestSimpleQuoting(UTF8_ENCODING, TEXT); - - TEXT = "Need to quote this too: ]]>"; - doTestSimpleQuoting(ISO_LATIN_ENCODING, TEXT); - doTestSimpleQuoting(UTF8_ENCODING, TEXT); - - TEXT = "And nbsp: \u00A0."; - doTestSimpleQuoting(ISO_LATIN_ENCODING, TEXT); - doTestSimpleQuoting(UTF8_ENCODING, TEXT); - } - - public void testSimpleAttrQuoting() - throws IOException, XMLStreamException - { - String TEXT = "&"; - doTestSimpleAttr(ISO_LATIN_ENCODING, TEXT); - doTestSimpleAttr(UTF8_ENCODING, TEXT); - - // Plus, need to quote single/double quotes properly - TEXT = "'\"fab\"'"; - doTestSimpleAttr(ISO_LATIN_ENCODING, TEXT); - doTestSimpleAttr(UTF8_ENCODING, TEXT); - - // And let's test non-ascii char too: - TEXT = "Nbsp -> \u00A0."; - doTestSimpleAttr(ISO_LATIN_ENCODING, TEXT); - doTestSimpleAttr(UTF8_ENCODING, TEXT); - } - - /* - ///////////////////////////////////////////////////// - // Helper methods - ///////////////////////////////////////////////////// - */ - - private void doTestSimpleQuoting(String encoding, String content) - throws IOException, XMLStreamException - { - StringWriter strw = new StringWriter(); - XMLStreamWriter w = getNonRepairingWriter(strw); - - w.writeStartDocument(encoding, "1.0"); - w.writeStartElement("root"); - w.writeCharacters(content); - w.writeEndElement(); - w.writeEndDocument(); - w.close(); - - // And then let's parse and verify it all: - XMLStreamReader sr = constructNsStreamReader(strw.toString(), true); - assertTokenType(START_DOCUMENT, sr.getEventType()); - assertEquals(encoding, sr.getCharacterEncodingScheme()); - assertTokenType(START_ELEMENT, sr.next()); - - // May get multiple segments.. - assertTokenType(CHARACTERS, sr.next()); - assertEquals(content, getAllText(sr)); - assertTokenType(END_ELEMENT, sr.getEventType()); - assertTokenType(END_DOCUMENT, sr.next()); - } - - private void doTestSimpleAttr(String encoding, String attrValue) - throws IOException, XMLStreamException - { - StringWriter strw = new StringWriter(); - XMLStreamWriter w = getNonRepairingWriter(strw); - - w.writeStartDocument(encoding, "1.0"); - w.writeStartElement("root"); - w.writeAttribute("attr", attrValue); - w.writeEndElement(); - w.writeEndDocument(); - w.close(); - - // And then let's parse and verify it all: - XMLStreamReader sr = constructNsStreamReader(strw.toString(), true); - assertTokenType(START_DOCUMENT, sr.getEventType()); - assertEquals(encoding, sr.getCharacterEncodingScheme()); - assertTokenType(START_ELEMENT, sr.next()); - assertEquals(1, sr.getAttributeCount()); - assertEquals(attrValue, sr.getAttributeValue(0)); - assertTokenType(END_ELEMENT, sr.next()); - assertTokenType(END_DOCUMENT, sr.next()); - } -} diff -Nru libwoodstox-java-4.1.3/src/test/org/codehaus/stax/test/wstream/TestProperties.java libwoodstox-java-5.1.0/src/test/org/codehaus/stax/test/wstream/TestProperties.java --- libwoodstox-java-4.1.3/src/test/org/codehaus/stax/test/wstream/TestProperties.java 2012-04-24 04:38:21.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/org/codehaus/stax/test/wstream/TestProperties.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,25 +0,0 @@ -package org.codehaus.stax.test.wstream; - -import javax.xml.stream.*; - -/** - * Unit tests that verify handling of XMLOutputFactory properties. - * This includes: - *

- * - * @author Tatu Saloranta - */ -public class TestProperties - extends BaseWriterTest -{ - public void testDefaultSettings() - { - XMLOutputFactory f = getNewOutputFactory(); - assertEquals(Boolean.FALSE, f.getProperty(XMLOutputFactory.IS_REPAIRING_NAMESPACES)); - } - -} diff -Nru libwoodstox-java-4.1.3/src/test/org/codehaus/stax/test/wstream/TestRepairingWriter.java libwoodstox-java-5.1.0/src/test/org/codehaus/stax/test/wstream/TestRepairingWriter.java --- libwoodstox-java-4.1.3/src/test/org/codehaus/stax/test/wstream/TestRepairingWriter.java 2012-04-24 04:38:21.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/org/codehaus/stax/test/wstream/TestRepairingWriter.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,444 +0,0 @@ -package org.codehaus.stax.test.wstream; - -import java.io.*; - -import javax.xml.stream.*; - -/** - * Set of unit tests for verifying operation of {@link XMLStreamWriter} - * in "repairing" mode. - * - * @author Tatu Saloranta - */ -public class TestRepairingWriter - extends BaseWriterTest -{ - /** - * Test similar to the one in {@link TestSimpleWriter}. - */ - public void testElements() - throws IOException, XMLStreamException - { - StringWriter strw = new StringWriter(); - XMLStreamWriter w = getRepairingWriter(strw); - final String URL_P1 = "http://p1.org"; - final String URL_P2 = "http://ns.p2.net/yeehaw.html"; - final String URL_DEF = "urn:default"; - - final String TEXT = " some text\n"; - - w.writeStartDocument(); - - /* Calling setPrefix() should be optional; but if we call it, - * exceptation is that it does properly cause URL to be bound. - */ - w.setPrefix("p1", URL_P1); - w.writeStartElement(URL_P1, "test"); - - w.writeStartElement("p2", "branch", URL_P2); - - // And then a dynamically created prefix... - w.writeStartElement(URL_DEF, "leaf"); - - w.writeCharacters(TEXT); - - w.writeEndElement(); // first leaf - - w.writeEmptyElement(URL_P1, "leaf"); // second leaf - - w.writeStartElement("", "third"); // may need dynamic NS too - w.writeEndElement(); - - w.writeEndElement(); // branch - w.writeEndElement(); // root elem - w.writeEndDocument(); - w.close(); - - // And then let's parse and verify it all: - XMLStreamReader sr = constructNsStreamReader(strw.toString()); - assertTokenType(START_DOCUMENT, sr.getEventType(), sr); - - // root element - assertTokenType(START_ELEMENT, sr.next(), sr); - assertEquals("test", sr.getLocalName()); - // ??? is writer obligated to honor the prefix suggestion - assertEquals(URL_P1, sr.getNamespaceURI()); - /* note: can not really verify number of namespace bindings, since - * writer should be in charge... and it may output extra bindings, - * too (and use default ns or explicit ones etc) - */ - - // first branch: - assertTokenType(START_ELEMENT, sr.next(), sr); - assertEquals("branch", sr.getLocalName()); - assertEquals(URL_P2, sr.getNamespaceURI()); - - // first leaf - assertTokenType(START_ELEMENT, sr.next(), sr); - assertEquals("leaf", sr.getLocalName()); - assertEquals(URL_DEF, sr.getNamespaceURI()); - - assertTokenType(CHARACTERS, sr.next(), sr); - assertEquals(TEXT, getAllText(sr)); - // not: getAllText ^^^ moves cursor! - - assertTokenType(END_ELEMENT, sr.getEventType(), sr); - assertEquals("leaf", sr.getLocalName()); - assertEquals(URL_DEF, sr.getNamespaceURI()); - - // another leaf: - assertTokenType(START_ELEMENT, sr.next(), sr); - assertEquals("leaf", sr.getLocalName()); - assertEquals(URL_P1, sr.getNamespaceURI()); - - assertTokenType(END_ELEMENT, sr.next(), sr); - assertEquals("leaf", sr.getLocalName()); - assertEquals(URL_P1, sr.getNamespaceURI()); - - // "third" - /* Adding explicit catching to print more diagnostics, as one - * of the tested impls did fail here: - */ - try { - assertTokenType(START_ELEMENT, sr.next(), sr); - } catch (XMLStreamException e) { - fail("Unexpected problems when parsing document [\""+strw.toString()+"\"], expecting element 'third': "+e.getMessage()); - throw e; - } - assertEquals("third", sr.getLocalName()); - assertNoNsURI(sr); - assertTokenType(END_ELEMENT, sr.next(), sr); - assertEquals("third", sr.getLocalName()); - assertNoNsURI(sr); - - // (close) branch - assertTokenType(END_ELEMENT, sr.next(), sr); - assertEquals("branch", sr.getLocalName()); - assertEquals(URL_P2, sr.getNamespaceURI()); - - // closing root element - assertTokenType(END_ELEMENT, sr.next(), sr); - assertEquals("test", sr.getLocalName()); - assertEquals(URL_P1, sr.getNamespaceURI()); - - assertTokenType(END_DOCUMENT, sr.next(), sr); - } - - public void testAttributeSimple() - throws IOException, XMLStreamException - { - StringWriter strw = new StringWriter(); - XMLStreamWriter w = getRepairingWriter(strw); - final String URL_P1 = "http://p1.org"; - final String ATTR_VALUE = "'value'&\"another\""; - - w.writeStartDocument(); - w.writeStartElement("", "test"); - w.writeAttribute(URL_P1, "attr", ATTR_VALUE); - w.writeEndElement(); - w.writeEndDocument(); - w.close(); - -//System.err.println("testAttributeSimple: doc = '"+strw+"'"); - - // And then let's parse and verify it all: - XMLStreamReader sr = constructNsStreamReader(strw.toString()); - assertTokenType(START_DOCUMENT, sr.getEventType(), sr); - - // root element - assertTokenType(START_ELEMENT, sr.next(), sr); - assertEquals("test", sr.getLocalName()); - assertNoNsURI(sr); - - assertEquals(1, sr.getAttributeCount()); - assertEquals("attr", sr.getAttributeLocalName(0)); - assertEquals(URL_P1, sr.getAttributeNamespace(0)); - assertEquals(ATTR_VALUE, sr.getAttributeValue(0)); - - assertTokenType(END_ELEMENT, sr.next(), sr); - assertEquals("test", sr.getLocalName()); - assertNoNsURI(sr); - - assertTokenType(END_DOCUMENT, sr.next(), sr); - } - - public void testAttributes() - throws IOException, XMLStreamException - { - StringWriter strw = new StringWriter(); - XMLStreamWriter w = getRepairingWriter(strw); - final String URL_P1 = "http://p1.org"; - final String URL_DEF = "urn:default"; - final String ATTR_VALUE = "'value\""; - final String ATTR_VALUE2 = ""; - - w.writeStartDocument(); - - /* Calling this method should be optional; but if we call it, - * exceptation is that it does properly bind the prefix and URL - * as the 'preferred' combination. In this case we'll just try - * to make URL bound as the default namespace - */ - w.setDefaultNamespace(URL_DEF); - w.writeStartElement(URL_DEF, "test"); - - /* And let's further make element and attribute(s) belong to that - * same namespace - */ - w.writeStartElement("", "leaf", URL_DEF); - w.writeAttribute(URL_DEF, "attr", ATTR_VALUE); - w.writeEndElement(); - - w.writeEmptyElement("", "leaf"); // in empty/no namespace! - - w.writeStartElement(URL_DEF, "leaf"); - w.writeAttribute("", "attr2", ATTR_VALUE2); // in empty/no namespace - w.writeEndElement(); - - w.writeEndElement(); // root elem - w.writeEndDocument(); - w.close(); - - // And then let's parse and verify it all: - //System.err.println("testAttributes: doc = '"+strw+"'"); - - XMLStreamReader sr = constructNsStreamReader(strw.toString()); - assertTokenType(START_DOCUMENT, sr.getEventType(), sr); - - // root element - assertTokenType(START_ELEMENT, sr.next(), sr); - assertEquals("test", sr.getLocalName()); - assertEquals(URL_DEF, sr.getNamespaceURI()); - - // first leaf: - assertTokenType(START_ELEMENT, sr.next(), sr); - assertEquals("leaf", sr.getLocalName()); - assertEquals(URL_DEF, sr.getNamespaceURI()); - assertEquals(1, sr.getAttributeCount()); - assertEquals("attr", sr.getAttributeLocalName(0)); - - String uri = sr.getAttributeNamespace(0); - if (!URL_DEF.equals(uri)) { - fail("Expected attribute 'attr' to have NS '"+URL_DEF+"', was "+valueDesc(uri)+"; input = '"+strw+"'"); - } - assertEquals(ATTR_VALUE, sr.getAttributeValue(0)); - assertTokenType(END_ELEMENT, sr.next(), sr); - assertEquals("leaf", sr.getLocalName()); - assertEquals(URL_DEF, sr.getNamespaceURI()); - - // empty leaf - assertTokenType(START_ELEMENT, sr.next(), sr); - assertEquals("leaf", sr.getLocalName()); - assertNoNsURI(sr); - assertTokenType(END_ELEMENT, sr.next(), sr); - assertEquals("leaf", sr.getLocalName()); - assertNoNsURI(sr); - - // third leaf - assertTokenType(START_ELEMENT, sr.next(), sr); - assertEquals("leaf", sr.getLocalName()); - assertEquals(URL_DEF, sr.getNamespaceURI()); - - assertEquals(1, sr.getAttributeCount()); - assertEquals("attr2", sr.getAttributeLocalName(0)); - assertNoAttrNamespace(sr.getAttributeNamespace(0)); - assertEquals(ATTR_VALUE2, sr.getAttributeValue(0)); - - assertTokenType(END_ELEMENT, sr.next(), sr); - assertEquals("leaf", sr.getLocalName()); - assertEquals(URL_DEF, sr.getNamespaceURI()); - - // closing root element - assertTokenType(END_ELEMENT, sr.next(), sr); - assertEquals("test", sr.getLocalName()); - assertEquals(URL_DEF, sr.getNamespaceURI()); - - assertTokenType(END_DOCUMENT, sr.next(), sr); - } - - /** - * This test specifically checks that namespace bindings for - * sub-trees do not "leak" into following sibling elements or - * trees. - */ - public void testSiblingNsBinding() - throws IOException, XMLStreamException - { - StringWriter strw = new StringWriter(); - XMLStreamWriter w = getRepairingWriter(strw); - final String URL_P1 = "http://p1.org"; - - w.writeStartDocument(); - w.writeStartElement("root"); - - // First leaf: - w.writeStartElement("leaf1"); - w.writeAttribute(URL_P1, "attr1", "1"); - w.writeEndElement(); - - // Second leaf: - w.writeStartElement("leaf2"); - w.writeAttribute(URL_P1, "attr2", "2"); - w.writeEndElement(); - - w.writeEndDocument(); - w.close(); - -//System.err.println("doc = '"+strw+"'"); - - XMLStreamReader sr = constructNsStreamReader(strw.toString()); - // root element - assertTokenType(START_ELEMENT, sr.next(), sr); - assertEquals("root", sr.getLocalName()); - - // First leaf: - assertTokenType(START_ELEMENT, sr.next(), sr); - assertEquals("leaf1", sr.getLocalName()); - assertEquals(1, sr.getAttributeCount()); - assertEquals("attr1", sr.getAttributeLocalName(0)); - assertEquals("1", sr.getAttributeValue(0)); - assertEquals(URL_P1, sr.getAttributeNamespace(0)); - assertEquals(1, sr.getNamespaceCount()); - assertTokenType(END_ELEMENT, sr.next(), sr); - assertEquals(URL_P1, sr.getNamespaceURI(0)); - - // Second leaf: - assertTokenType(START_ELEMENT, sr.next(), sr); - assertEquals("leaf2", sr.getLocalName()); - assertEquals(1, sr.getAttributeCount()); - assertEquals("attr2", sr.getAttributeLocalName(0)); - assertEquals("2", sr.getAttributeValue(0)); - assertEquals(URL_P1, sr.getAttributeNamespace(0)); - assertEquals(1, sr.getNamespaceCount()); - assertTokenType(END_ELEMENT, sr.next(), sr); - assertEquals(URL_P1, sr.getNamespaceURI(0)); - - assertTokenType(END_ELEMENT, sr.next(), sr); - assertTokenType(END_DOCUMENT, sr.next(), sr); - } - - public void testSiblingNs2() - throws IOException, XMLStreamException - { - StringWriter strw = new StringWriter(); - XMLStreamWriter w = getRepairingWriter(strw); - - String ns1 = "urn://namespace1"; - String ns2 = "urn://namespace2"; - w.writeStartDocument(); - w.writeStartElement(ns1, "root"); - w.writeStartElement(ns2, "first"); - w.writeEndElement(); - w.writeStartElement(ns2, "second"); - w.writeEndElement(); - w.writeEndElement(); - w.writeEndDocument(); - w.close(); - - // And then let's parse and verify it all: - XMLStreamReader sr = constructNsStreamReader(strw.toString()); - assertTokenType(START_DOCUMENT, sr.getEventType(), sr); - - assertTokenType(START_ELEMENT, sr.next(), sr); - assertEquals("root", sr.getLocalName()); - // Can't assume anything about prefix assigned (if any), just ns uri - assertEquals(ns1, sr.getNamespaceURI()); - assertEquals(0, sr.getAttributeCount()); - - assertTokenType(START_ELEMENT, sr.next(), sr); - assertEquals("first", sr.getLocalName()); - assertEquals(ns2, sr.getNamespaceURI()); - assertEquals(0, sr.getAttributeCount()); - assertTokenType(END_ELEMENT, sr.next(), sr); - assertEquals("first", sr.getLocalName()); - - assertTokenType(START_ELEMENT, sr.next(), sr); - assertEquals("second", sr.getLocalName()); - assertEquals(ns2, sr.getNamespaceURI()); - assertEquals(0, sr.getAttributeCount()); - assertTokenType(END_ELEMENT, sr.next(), sr); - assertEquals("second", sr.getLocalName()); - assertTokenType(END_ELEMENT, sr.next(), sr); - assertEquals("root", sr.getLocalName()); - } - - /** - * Although repairing writers are allowed to output any number of - * namespace declarations they want to, let's still check that - * unnecessary ones are not output in simple cases. While doing - * that is not strictly an error, it seems reasonable fail the - * test, to let implementors know about sub-optimal behavior. - */ - public void testOptimalDefaultNsDecls() - throws IOException, XMLStreamException - { - StringWriter strw = new StringWriter(); - XMLStreamWriter w = getRepairingWriter(strw); - final String URL_P1 = "http://p1.org"; - - w.writeStartDocument(); - // Let's try to enforce using of the default ns by passing empty prefix - // (writer is not required to honor that request though) - w.writeStartElement("", "test", URL_P1); - w.writeStartElement("", "leaf", URL_P1); - w.writeEndElement(); - w.writeEndElement(); - w.writeEndDocument(); - w.close(); - -//System.err.println("DEBUG: doc = '"+strw+"'"); - // And then let's parse and verify it all: - XMLStreamReader sr = constructNsStreamReader(strw.toString()); - assertTokenType(START_DOCUMENT, sr.getEventType(), sr); - - // root element - assertTokenType(START_ELEMENT, sr.next(), sr); - assertEquals("test", sr.getLocalName()); - assertEquals(URL_P1, sr.getNamespaceURI()); - assertEquals(1, sr.getNamespaceCount()); - assertEquals(URL_P1, sr.getNamespaceURI(0)); - - // leaf: should be able to use parent's namespace decl - assertTokenType(START_ELEMENT, sr.next(), sr); - assertEquals("leaf", sr.getLocalName()); - assertEquals(URL_P1, sr.getNamespaceURI()); - assertEquals(0, sr.getNamespaceCount()); - - sr.close(); - } - - public void testOptimalNonDefaultNsDecls() - throws IOException, XMLStreamException - { - StringWriter strw = new StringWriter(); - XMLStreamWriter w = getRepairingWriter(strw); - final String URL_P1 = "http://p1.org"; - - w.writeStartDocument(); - w.writeStartElement(URL_P1, "test"); - w.writeStartElement(URL_P1, "leaf"); - w.writeEndElement(); - w.writeEndElement(); - w.writeEndDocument(); - w.close(); - - // And then let's parse and verify it all: - XMLStreamReader sr = constructNsStreamReader(strw.toString()); - assertTokenType(START_DOCUMENT, sr.getEventType(), sr); - - // root element - assertTokenType(START_ELEMENT, sr.next(), sr); - assertEquals("test", sr.getLocalName()); - assertEquals(URL_P1, sr.getNamespaceURI()); - assertEquals(1, sr.getNamespaceCount()); - assertEquals(URL_P1, sr.getNamespaceURI(0)); - - // leaf: should be able to use parent's namespace decl - assertTokenType(START_ELEMENT, sr.next(), sr); - assertEquals("leaf", sr.getLocalName()); - assertEquals(URL_P1, sr.getNamespaceURI()); - assertEquals(0, sr.getNamespaceCount()); - - sr.close(); - } -} diff -Nru libwoodstox-java-4.1.3/src/test/org/codehaus/stax/test/wstream/TestSimpleWriter.java libwoodstox-java-5.1.0/src/test/org/codehaus/stax/test/wstream/TestSimpleWriter.java --- libwoodstox-java-4.1.3/src/test/org/codehaus/stax/test/wstream/TestSimpleWriter.java 2012-04-24 04:38:21.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/org/codehaus/stax/test/wstream/TestSimpleWriter.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,724 +0,0 @@ -package org.codehaus.stax.test.wstream; - -import javax.xml.stream.*; - -import java.io.*; - -/** - * Set of unit tests for verifying operation of {@link XMLStreamWriter} - * in "non-repairing" mode. It also includes writer tests for things - * for which repair/non-repair modes should not matter (comments, PIs - * etc). - * - * @author Tatu Saloranta - */ -public class TestSimpleWriter - extends BaseWriterTest -{ - final String ISO_LATIN_ENCODING = "ISO-8859-1"; - - public void testProlog() - throws IOException, XMLStreamException - { - StringWriter strw = new StringWriter(); - XMLStreamWriter w = getNonRepairingWriter(strw); - - w.writeStartDocument(); - w.writeCharacters("\r\n "); - w.writeEmptyElement("test"); - w.writeCharacters(" \r"); - w.writeEndDocument(); - w.close(); - - /* And then let's parse and verify it all. But are we guaranteed - * to get SPACE? Let's not assume that - */ - XMLStreamReader sr = constructNsStreamReader(strw.toString(), true); - assertTokenType(START_DOCUMENT, sr.getEventType()); - - int type = sr.next(); - if (type != START_ELEMENT) { - assertTokenType(SPACE, type); - assertEquals("\n ", getAndVerifyText(sr)); - assertTokenType(START_ELEMENT, sr.next()); - } - assertEquals("test", sr.getLocalName()); - assertTokenType(END_ELEMENT, sr.next()); - assertEquals("test", sr.getLocalName()); - // Another SPACE? - type = sr.next(); - if (type != END_DOCUMENT) { - assertTokenType(SPACE, type); - assertEquals(" \n", getAndVerifyText(sr)); - assertTokenType(END_DOCUMENT, sr.next()); - } - } - - public void testCData() - throws IOException, XMLStreamException - { - StringWriter strw = new StringWriter(); - XMLStreamWriter w = getNonRepairingWriter(strw); - - final String CDATA_TEXT = "Let's test it with some ]] ]> data; s and && chars and all!"; - - w.writeStartDocument(); - w.writeStartElement("test"); - w.writeCData(CDATA_TEXT); - w.writeEndElement(); - w.writeEndDocument(); - w.close(); - - // And then let's parse and verify it all: - - XMLStreamReader sr = constructNsStreamReader(strw.toString(), true); - assertTokenType(START_DOCUMENT, sr.getEventType()); - assertTokenType(START_ELEMENT, sr.next()); - - // Now, parsers are allowed to report CHARACTERS or CDATA - int tt = sr.next(); - if (tt != CHARACTERS && tt != CDATA) { - assertTokenType(CDATA, tt); // to cause failure - } - assertFalse(sr.isWhiteSpace()); - assertEquals(CDATA_TEXT, getAndVerifyText(sr)); - assertTokenType(END_ELEMENT, sr.next()); - assertTokenType(END_DOCUMENT, sr.next()); - } - - public void testCharacters() - throws IOException, XMLStreamException - { - StringWriter strw = new StringWriter(); - XMLStreamWriter w = getNonRepairingWriter(strw); - - final String TEXT = "Ok; some content\nwith linefeeds and stuff (let's leave encoding as is though, no entities)\n"; - - w.writeStartDocument(); - w.writeStartElement("test"); - w.writeCharacters(TEXT); - w.writeStartElement("leaf"); - // Let's also test the other method... - char[] tmp = new char[TEXT.length() + 4]; - TEXT.getChars(0, TEXT.length(), tmp, 2); - w.writeCharacters(tmp, 2, TEXT.length()); - w.writeEndElement(); - w.writeEndElement(); - w.writeEndDocument(); - w.close(); - - // And then let's parse and verify it all: - - XMLStreamReader sr = constructNsStreamReader(strw.toString(), true); - assertTokenType(START_DOCUMENT, sr.getEventType()); - assertTokenType(START_ELEMENT, sr.next()); - assertTokenType(CHARACTERS, sr.next()); - assertFalse(sr.isWhiteSpace()); - assertEquals(TEXT, getAndVerifyText(sr)); - assertTokenType(START_ELEMENT, sr.next()); - assertTokenType(CHARACTERS, sr.next()); - assertFalse(sr.isWhiteSpace()); - assertEquals(TEXT, getAndVerifyText(sr)); - assertTokenType(END_ELEMENT, sr.next()); - assertTokenType(END_ELEMENT, sr.next()); - assertTokenType(END_DOCUMENT, sr.next()); - } - - public void testComment() - throws IOException, XMLStreamException - { - StringWriter strw = new StringWriter(); - XMLStreamWriter w = getNonRepairingWriter(strw); - final String COMMENT1 = "comments are cool"; - final String COMMENT2 = " some more\ncomments & other stuff"; - final String COMMENT3 = "Hah: "; - final String COMMENT4 = " - - - \t - - \t"; - - w.writeStartDocument(); - - // Let's start with a comment - w.writeComment(COMMENT1); - - w.writeStartElement("root"); - w.writeCharacters(" "); - w.writeComment(COMMENT2); - - w.writeStartElement("branch"); - w.writeEndElement(); - w.writeStartElement("branch"); - w.writeComment(COMMENT3); - w.writeEndElement(); - - w.writeEndElement(); - // and trailing comment too - w.writeComment(COMMENT4); - - w.writeEndDocument(); - w.close(); - - // And then let's parse and verify it all: - XMLStreamReader sr = constructNsStreamReader(strw.toString()); - assertTokenType(START_DOCUMENT, sr.getEventType()); - - // First, PI with just target: - assertTokenType(COMMENT, sr.next()); - assertEquals(COMMENT1, sr.getText()); - - // start root element: - assertTokenType(START_ELEMENT, sr.next()); - assertEquals("root", sr.getLocalName()); - - int tt = sr.next(); - if (tt != CHARACTERS && tt != SPACE) { - fail("Expected a single space (CHARACTERS or SPACE), got " - +tokenTypeDesc(tt)); - } - - assertTokenType(COMMENT, sr.next()); - assertEquals(COMMENT2, sr.getText()); - - // empty element ('branch') - assertTokenType(START_ELEMENT, sr.next()); - assertEquals("branch", sr.getLocalName()); - assertTokenType(END_ELEMENT, sr.next()); - assertEquals("branch", sr.getLocalName()); - - // another 'branch' element: - assertTokenType(START_ELEMENT, sr.next()); - assertEquals("branch", sr.getLocalName()); - assertTokenType(COMMENT, sr.next()); - assertEquals(COMMENT3, sr.getText()); - assertTokenType(END_ELEMENT, sr.next()); - assertEquals("branch", sr.getLocalName()); - - // closing root element - assertTokenType(END_ELEMENT, sr.next()); - assertEquals("root", sr.getLocalName()); - - // trailing (prolog) comment: - assertTokenType(COMMENT, sr.next()); - assertEquals(COMMENT4, sr.getText()); - - assertTokenType(END_DOCUMENT, sr.next()); - } - - public void testDTD() - throws IOException, XMLStreamException - { - // !!! TBI - } - - /** - * Unit test that tests how element writing works, including - * checks for the namespace output. - */ - public void testElements() - throws IOException, XMLStreamException - { - StringWriter strw = new StringWriter(); - XMLStreamWriter w = getNonRepairingWriter(strw); - final String URL_P1 = "http://p1.org"; - final String URL_P2 = "http://ns.p2.net/yeehaw.html"; - final String URL_DEF = "urn:default"; - - final String TEXT = " some text\n"; - - w.writeStartDocument(); - - w.setPrefix("p1", URL_P1); - w.writeStartElement("test"); - w.writeNamespace("p1", URL_P1); - - w.setDefaultNamespace(URL_DEF); - w.setPrefix("p2", URL_P2); - w.writeStartElement("", "branch", URL_DEF); - w.writeDefaultNamespace(URL_DEF); - w.writeNamespace("p2", URL_P2); - - // Ok, let's see that we can also clear out the def ns: - w.setDefaultNamespace(""); - w.writeStartElement("", "leaf", ""); - w.writeDefaultNamespace(""); - - w.writeCharacters(TEXT); - - w.writeEndElement(); // first leaf - - w.writeEmptyElement(URL_P1, "leaf"); // second leaf - - w.writeEndElement(); // branch - w.writeEndElement(); // root elem - w.writeEndDocument(); - w.close(); - - // And then let's parse and verify it all: - XMLStreamReader sr = constructNsStreamReader(strw.toString()); - assertTokenType(START_DOCUMENT, sr.getEventType()); - - // root element - assertTokenType(START_ELEMENT, sr.next()); - assertEquals("test", sr.getLocalName()); - assertNoPrefixOrNs(sr); - assertEquals(1, sr.getNamespaceCount()); - assertEquals("p1", sr.getNamespacePrefix(0)); - assertEquals(URL_P1, sr.getNamespaceURI(0)); - - // first branch: - assertTokenType(START_ELEMENT, sr.next()); - assertEquals("branch", sr.getLocalName()); - assertEquals(2, sr.getNamespaceCount()); - assertNoPrefix(sr); - assertEquals(URL_DEF, sr.getNamespaceURI()); - - // leaf - assertTokenType(START_ELEMENT, sr.next()); - assertEquals("leaf", sr.getLocalName()); - assertEquals(1, sr.getNamespaceCount()); - assertNoPrefix(sr); - - assertTokenType(CHARACTERS, sr.next()); - assertEquals(TEXT, getAllText(sr)); - // not: getAllText ^^^ moves cursor! - - assertTokenType(END_ELEMENT, sr.getEventType()); - assertEquals("leaf", sr.getLocalName()); - assertNoPrefixOrNs(sr); - - // another leaf: - assertTokenType(START_ELEMENT, sr.next()); - assertEquals("leaf", sr.getLocalName()); - assertEquals(0, sr.getNamespaceCount()); - assertEquals("p1", sr.getPrefix()); - assertEquals(URL_P1, sr.getNamespaceURI()); - - assertTokenType(END_ELEMENT, sr.next()); - assertEquals("leaf", sr.getLocalName()); - assertEquals("p1", sr.getPrefix()); - assertEquals(URL_P1, sr.getNamespaceURI()); - - // (close) branch - try { // catching exception to add more info to failure msg... - assertTokenType(END_ELEMENT, sr.next()); - } catch (XMLStreamException sex) { - fail("Failed when trying to match (input '"+strw+"'): "+sex); - } - assertEquals("branch", sr.getLocalName()); - assertNoPrefix(sr); - - // closing root element - assertTokenType(END_ELEMENT, sr.next()); - assertEquals("test", sr.getLocalName()); - assertNoPrefixOrNs(sr); - - assertTokenType(END_DOCUMENT, sr.next()); - } - - /** - * Unit tests for documents that just do not use namespaces (independent - * of whether namespace support is enabled for the writer or not) - */ - public void testNonNsElements() - throws IOException, XMLStreamException - { - StringWriter strw = new StringWriter(); - XMLStreamWriter w = getNonRepairingWriter(strw); - final String TEXT = "Just some text..."; - final String TEXT_SPACE = "\n "; - - w.writeStartDocument(); - - w.writeStartElement("doc"); - w.writeCharacters(TEXT); - - w.writeStartElement("branch"); - w.writeEndElement(); - w.writeCharacters(TEXT_SPACE); - w.writeStartElement("branch.2"); - w.writeCData(TEXT); - w.writeEndElement(); - w.writeEmptyElement("_empty"); - - w.writeEndElement(); - w.writeEndDocument(); - w.close(); - - // And then let's parse and verify it all: - XMLStreamReader sr = constructNsStreamReader(strw.toString()); - assertTokenType(START_DOCUMENT, sr.getEventType()); - - // opening doc element - assertTokenType(START_ELEMENT, sr.next()); - assertEquals("doc", sr.getLocalName()); - assertNoPrefixOrNs(sr); - - assertTokenType(CHARACTERS, sr.next()); - assertEquals(TEXT, getAllText(sr)); - // not: getAllText ^^^ moves cursor! - - // branch elements: - assertTokenType(START_ELEMENT, sr.getEventType()); - assertEquals("branch", sr.getLocalName()); - assertNoPrefixOrNs(sr); - assertTokenType(END_ELEMENT, sr.next()); - assertEquals("branch", sr.getLocalName()); - assertNoPrefixOrNs(sr); - - assertTokenType(CHARACTERS, sr.next()); - assertEquals(TEXT_SPACE, getAllText(sr)); - - assertTokenType(START_ELEMENT, sr.getEventType()); - assertEquals("branch.2", sr.getLocalName()); - assertNoPrefixOrNs(sr); - assertTextualTokenType(sr.next()); - assertEquals(TEXT, getAllText(sr)); - assertTokenType(END_ELEMENT, sr.getEventType()); - assertEquals("branch.2", sr.getLocalName()); - assertNoPrefixOrNs(sr); - - assertTokenType(START_ELEMENT, sr.next()); - assertEquals("_empty", sr.getLocalName()); - assertNoPrefixOrNs(sr); - assertTokenType(END_ELEMENT, sr.next()); - assertEquals("_empty", sr.getLocalName()); - assertNoPrefixOrNs(sr); - - // closing doc element - try { - assertTokenType(END_ELEMENT, sr.next()); - } catch (XMLStreamException sex) { - fail("Failed when trying to match (input '"+strw+"'): "+sex); - } - assertEquals("doc", sr.getLocalName()); - assertNoPrefixOrNs(sr); - - assertTokenType(END_DOCUMENT, sr.next()); - } - - public void testEmptyElements() - throws IOException, XMLStreamException - { - StringWriter strw = new StringWriter(); - XMLStreamWriter w = getNonRepairingWriter(strw); - - w.writeStartDocument(); - - w.writeStartElement("root"); - w.writeStartElement("branch"); - w.writeEmptyElement("leaf"); - - w.writeEndElement(); // branch - w.writeComment("comment"); // should be at same level as branch - w.writeEndElement(); // root elem - w.writeEndDocument(); - w.close(); - - // And then let's parse and verify it all: - XMLStreamReader sr = constructNsStreamReader(strw.toString()); - assertTokenType(START_DOCUMENT, sr.getEventType()); - - // root element - assertTokenType(START_ELEMENT, sr.next()); - assertEquals("root", sr.getLocalName()); - // branch: - assertTokenType(START_ELEMENT, sr.next()); - assertEquals("branch", sr.getLocalName()); - // leaf - assertTokenType(START_ELEMENT, sr.next()); - assertEquals("leaf", sr.getLocalName()); - assertTokenType(END_ELEMENT, sr.next()); - assertEquals("leaf", sr.getLocalName()); - assertTokenType(END_ELEMENT, sr.next()); - assertEquals("branch", sr.getLocalName()); - - assertTokenType(COMMENT, sr.next()); - assertEquals("comment", getAndVerifyText(sr)); - - assertTokenType(END_ELEMENT, sr.next()); - assertEquals("root", sr.getLocalName()); - - assertTokenType(END_DOCUMENT, sr.next()); - } - - public void testEntityRef() - throws IOException, XMLStreamException - { - // !!! TBI - } - - public void testProcInstr() - throws IOException, XMLStreamException - { - StringWriter strw = new StringWriter(); - XMLStreamWriter w = getNonRepairingWriter(strw); - final String LONG_DATA = "content & spaces ... \t "; - final String LONG_DATA2 = "? >? ? > "; - - w.writeStartDocument(); - - // Let's start with a proc instr: - w.writeProcessingInstruction("my_target"); - - w.writeStartElement("root"); - w.writeCharacters("x"); - w.writeProcessingInstruction("target", "data"); - - w.writeStartElement("branch"); - w.writeEndElement(); - w.writeStartElement("branch"); - w.writeProcessingInstruction("t", LONG_DATA); - w.writeEndElement(); - - w.writeEndElement(); - // and trailing proc instr too - w.writeProcessingInstruction("xxx", LONG_DATA2); - - w.writeEndDocument(); - w.close(); - - // And then let's parse and verify it all: - XMLStreamReader sr = constructNsStreamReader(strw.toString()); - assertTokenType(START_DOCUMENT, sr.getEventType()); - - // First, PI with just target: - assertTokenType(PROCESSING_INSTRUCTION, sr.next()); - assertEquals("my_target", sr.getPITarget()); - String data = sr.getPIData(); - if (data != null && data.length() > 0) { - fail("Expected empty (or null) data; got '"+data+"'"); - } - // start root element: - assertTokenType(START_ELEMENT, sr.next()); - assertEquals("root", sr.getLocalName()); - - assertTokenType(CHARACTERS, sr.next()); - assertEquals("x", sr.getText()); - - // 'full' PI: - assertTokenType(PROCESSING_INSTRUCTION, sr.next()); - assertEquals("target", sr.getPITarget()); - assertEquals("data", sr.getPIData()); - - // empty element ('branch') - assertTokenType(START_ELEMENT, sr.next()); - assertEquals("branch", sr.getLocalName()); - assertTokenType(END_ELEMENT, sr.next()); - assertEquals("branch", sr.getLocalName()); - - // another 'branch' element: - assertTokenType(START_ELEMENT, sr.next()); - assertEquals("branch", sr.getLocalName()); - assertTokenType(PROCESSING_INSTRUCTION, sr.next()); - assertEquals("t", sr.getPITarget()); - assertEquals(LONG_DATA, sr.getPIData()); - assertTokenType(END_ELEMENT, sr.next()); - assertEquals("branch", sr.getLocalName()); - - // closing root element - assertTokenType(END_ELEMENT, sr.next()); - assertEquals("root", sr.getLocalName()); - - // trailing (prolog) PI: - assertTokenType(PROCESSING_INSTRUCTION, sr.next()); - assertEquals("xxx", sr.getPITarget()); - assertEquals(LONG_DATA2, sr.getPIData()); - - assertTokenType(END_DOCUMENT, sr.next()); - } - - - public void testXmlDeclImplicit() - throws IOException, XMLStreamException - { - doTextXmlDecl(3); - } - - public void testXmlDecl0args() - throws IOException, XMLStreamException - { - doTextXmlDecl(0); - } - - public void testXmlDecl1arg() - throws IOException, XMLStreamException - { - doTextXmlDecl(1); - } - - public void testXmlDecl2args() - throws IOException, XMLStreamException - { - doTextXmlDecl(2); - } - - /** - * This simple unit tests checks handling of namespace prefix - * information in non-repairing mode, wrt explictly defined - * bindings. - */ - public void testExplicitNsPrefixes() - throws XMLStreamException - { - XMLStreamWriter writer = getNonRepairingWriter(new StringWriter()); - final String NS1 = "http://foo.com"; - final String NS2 = "http://bar.com"; - - writer.writeStartDocument(); - writer.writeStartElement("root"); - - // First, explicit binding: - writer.writeStartElement("branch1"); - writer.setPrefix("ns", NS1); - writer.setDefaultNamespace(NS2); - assertEquals("ns", writer.getPrefix(NS1)); - assertEquals("", writer.getPrefix(NS2)); - // and just for fun, let's check they are not mixed up - assertNull(writer.getPrefix("ns")); - assertNull(writer.getPrefix("nosuchPrefix")); - writer.writeEndElement(); - - // these should be element scoped, and not exist any more - assertNull(writer.getPrefix(NS1)); - assertNull(writer.getPrefix(NS2)); - - // Next: should we check NamespaceContext? - /* For now, let's not: it's unclear if that should - * be unmodified "root" context, or live version - */ - - writer.writeEndElement(); // root - writer.writeEndDocument(); - } - - /** - * This simple unit tests checks handling of namespace prefix - * information in non-repairing mode, wrt implied - * bindings, generated by namespace output method. - * Since information in 1.0 - * specs and associated Javadocs are sparse, these are based - * on consensus on stax_builders list, as well as information - * from Stax TCK unit tests. - */ - public void testImplicitNsPrefixes() - throws XMLStreamException - { - XMLStreamWriter writer = getNonRepairingWriter(new StringWriter()); - final String NS1 = "http://foo.com"; - final String NS2 = "http://bar.com"; - - writer.writeStartDocument(); - writer.writeStartElement("root"); - - /* And then, implicit binding(s). It is not obvious - * whether such should be generated, from the specs, - * but TCK indicates they should. - */ - writer.writeNamespace("ns", NS2); - writer.writeDefaultNamespace(NS1); - - assertEquals("", writer.getPrefix(NS1)); - assertEquals("ns", writer.getPrefix(NS2)); - - /* Not quite sure if these should/need be scoped? - * Probably? - */ - writer.writeEndElement(); - assertNull(writer.getPrefix(NS1)); - assertNull(writer.getPrefix(NS2)); - - writer.writeEndDocument(); - } - - /* - ////////////////////////////////// - // Private methods - ////////////////////////////////// - */ - - private void doTextXmlDecl(int i) - throws IOException, XMLStreamException - { - /* 4 modes: writeStartDocument with 0 args, 1 arg, 2 args, - * and without a call - */ - StringWriter strw = new StringWriter(); - XMLStreamWriter w = getNonRepairingWriter(strw); - - switch (i) { - case 0: - w.writeStartDocument(); - break; - case 1: - /* Might well be ok to output other than 1.0, but the - * reader may choke on others (like 1.1)? - */ - w.writeStartDocument("1.0"); - break; - case 2: - w.writeStartDocument(ISO_LATIN_ENCODING, "1.0"); - break; - case 3: - // No output (shouldn't print out xml decl) - break; - } - w.writeEmptyElement("root"); - w.writeEndDocument(); - w.close(); - - XMLStreamReader sr = constructNsStreamReader(strw.toString()); - assertTokenType(START_DOCUMENT, sr.getEventType()); - - // correct version? - if (i == 3) { - // Shouldn't have output anything: - String ver = sr.getVersion(); - if (ver != null && ver.length() > 0) { - fail("Non-null/empty version ('"+ver+"') when no START_DOCUMENT written explicitly"); - } - } else { - assertEquals("1.0", sr.getVersion()); - } - - // encoding? - String enc = sr.getCharacterEncodingScheme(); - switch (i) { - case 0: - /* Not sure why the encoding has to default to utf-8... would - * make sense to rather leave it out - */ - /* quick note: the proper usage (as per xml specs) would be to - * use UTF-8; Stax 1.0 mentions "utf-8", so let's accept - * both for now (but let's not accept mixed cases) - */ - if (!"utf-8".equals(enc) && !"UTF-8".equals(enc)) { - fail("Expected either 'UTF-8' (xml specs) or 'utf-8' (stax specs) as the encoding output with no-arg 'writeStartDocument()' call (result doc = '"+strw.toString()+"')"); - } - break; - case 1: - /* Interestingly enough, API comments do not indicate an encoding - * default for 1-arg method! - */ - assertNull(enc); - break; - case 2: - assertEquals(ISO_LATIN_ENCODING, enc); - break; - case 3: - assertNull(enc); - break; - } - - // What should sr.getEncoding() return? null? can't check... - - /* but stand-alone we can check; specifically: - */ - assertFalse("XMLStreamReader.standalonSet() should return false if pseudo-attr not found", - sr.standaloneSet()); - - /* now... it's too bad there's no way to explicitly specify - * stand-alone value... so probably can not really test the - * other method - */ - //assertFalse("XMLStreamReader.isStandalone() should return false if pseudo-attr not found", sr.isStandalone()); - sr.close(); - } -} diff -Nru libwoodstox-java-4.1.3/src/test/org/codehaus/stax/test/wstream/TestWriterClosing.java libwoodstox-java-5.1.0/src/test/org/codehaus/stax/test/wstream/TestWriterClosing.java --- libwoodstox-java-4.1.3/src/test/org/codehaus/stax/test/wstream/TestWriterClosing.java 2012-04-24 04:38:21.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/org/codehaus/stax/test/wstream/TestWriterClosing.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,42 +0,0 @@ -package org.codehaus.stax.test.wstream; - -import javax.xml.stream.*; - -import java.io.*; - -/** - * Simple unit tests for ensuring that the Stax implementation does not - * close the underlying output stream when XMLStreamWriter.close() is - * called. - * - * @author Tatu Saloranta - * @author Matt Solnit - */ -public class TestWriterClosing - extends BaseWriterTest -{ - public void testClosing() - throws IOException, XMLStreamException - { - File f = File.createTempFile("wstxtest", null); - f.deleteOnExit(); - OutputStream stream = new FileOutputStream(f); - OutputStreamWriter strw = new OutputStreamWriter(stream, "UTF-8"); - XMLStreamWriter xsw = getNonRepairingWriter(strw); - xsw.writeStartDocument(); - xsw.writeStartElement("root"); - xsw.writeEndElement(); - xsw.writeEndDocument(); - xsw.close(); - - /* If impl called stream.close() above, we'll get an IOEXception - * here... - */ - try { - strw.write(""); - } catch (IOException ioe) { - fail("Should not have gotten IOException, impl. probably called stream.close(): "+ioe); - } - stream.close(); - } -} diff -Nru libwoodstox-java-4.1.3/src/test/org/codehaus/stax2/ri/TestStax2ReaderAdapter.java libwoodstox-java-5.1.0/src/test/org/codehaus/stax2/ri/TestStax2ReaderAdapter.java --- libwoodstox-java-4.1.3/src/test/org/codehaus/stax2/ri/TestStax2ReaderAdapter.java 2012-04-24 04:38:21.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/org/codehaus/stax2/ri/TestStax2ReaderAdapter.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,141 +0,0 @@ -package org.codehaus.stax2.ri; - -import java.io.*; - -import javax.xml.stream.*; - -import stax2.BaseStax2Test; - -/** - * @author tsaloranta - * - * @since 4.1 - */ -public class TestStax2ReaderAdapter extends BaseStax2Test -{ - public void testSimple() throws Exception - { - final String XML = "xyzabc
"; - XMLInputFactory f = getInputFactory(); - XMLStreamReader reader1 = f.createXMLStreamReader(new StringReader(XML)); - Stax2ReaderAdapter adapter = new Stax2ReaderAdapter(reader1); - assertTokenType(START_DOCUMENT, adapter.getEventType()); - assertEquals(0, adapter.getDepth()); - - assertTokenType(START_ELEMENT, adapter.next()); - assertEquals("root", adapter.getLocalName()); - assertEquals(1, adapter.getDepth()); - - assertTokenType(START_ELEMENT, adapter.next()); - assertEquals(2, adapter.getDepth()); - assertEquals("a", adapter.getLocalName()); - assertTokenType(CHARACTERS, adapter.next()); - assertEquals(2, adapter.getDepth()); - assertEquals("xyz", adapter.getText()); - assertTokenType(END_ELEMENT, adapter.next()); - assertEquals(2, adapter.getDepth()); - assertEquals("a", adapter.getLocalName()); - - assertTokenType(START_ELEMENT, adapter.next()); - assertEquals(2, adapter.getDepth()); - assertEquals("b", adapter.getLocalName()); - assertTokenType(CHARACTERS, adapter.next()); - assertEquals(2, adapter.getDepth()); - assertEquals("abc", adapter.getText()); - assertTokenType(END_ELEMENT, adapter.next()); - assertEquals(2, adapter.getDepth()); - assertEquals("b", adapter.getLocalName()); - - assertTokenType(END_ELEMENT, adapter.next()); - assertEquals("root", adapter.getLocalName()); - assertEquals(1, adapter.getDepth()); - - assertTokenType(END_DOCUMENT, adapter.next()); - assertEquals(0, adapter.getDepth()); - } - - public void testSimpleWithTypedText() throws Exception - { - final String XML = "xyzabc"; - XMLInputFactory f = getInputFactory(); - XMLStreamReader reader1 = f.createXMLStreamReader(new StringReader(XML)); - Stax2ReaderAdapter adapter = new Stax2ReaderAdapter(reader1); - assertTokenType(START_DOCUMENT, adapter.getEventType()); - assertEquals(0, adapter.getDepth()); - - assertTokenType(START_ELEMENT, adapter.next()); - assertEquals("root", adapter.getLocalName()); - assertEquals(1, adapter.getDepth()); - - assertTokenType(START_ELEMENT, adapter.next()); - assertEquals(2, adapter.getDepth()); - assertEquals("a", adapter.getLocalName()); - assertEquals("xyz", adapter.getElementText()); - assertTokenType(END_ELEMENT, adapter.getEventType()); - assertEquals(2, adapter.getDepth()); - assertEquals("a", adapter.getLocalName()); - - assertTokenType(START_ELEMENT, adapter.next()); - assertEquals(2, adapter.getDepth()); - assertEquals("b", adapter.getLocalName()); - assertEquals("abc", adapter.getElementText()); - assertTokenType(END_ELEMENT, adapter.getEventType()); - assertEquals(2, adapter.getDepth()); - assertEquals("b", adapter.getLocalName()); - - assertTokenType(END_ELEMENT, adapter.next()); - assertEquals(1, adapter.getDepth()); - assertEquals("root", adapter.getLocalName()); - - assertTokenType(END_DOCUMENT, adapter.next()); - assertEquals(0, adapter.getDepth()); - } - - /** - * Test actually copied from 'stax2.stream.TestXMLStreamReader2' - */ - public void testWithDepthAndStuff() throws Exception - { - final String XML = "xxx"; - XMLInputFactory f = getInputFactory(); - XMLStreamReader reader1 = f.createXMLStreamReader(new StringReader(XML)); - Stax2ReaderAdapter sr = new Stax2ReaderAdapter(reader1); - - assertTokenType(START_DOCUMENT, sr.getEventType()); - assertEquals(0, sr.getDepth()); - assertFalse(sr.isEmptyElement()); - - assertTokenType(START_ELEMENT, sr.next()); - assertEquals("root", sr.getLocalName()); - assertEquals(1, sr.getDepth()); - assertFalse(sr.isEmptyElement()); - - assertTokenType(START_ELEMENT, sr.next()); - assertEquals("child", sr.getLocalName()); - assertEquals(2, sr.getDepth()); - - assertTokenType(END_ELEMENT, sr.next()); - assertEquals("child", sr.getLocalName()); - assertEquals(2, sr.getDepth()); - - assertTokenType(START_ELEMENT, sr.next()); - assertEquals("child2", sr.getLocalName()); - assertEquals(2, sr.getDepth()); - - assertTokenType(CHARACTERS, sr.next()); - assertEquals("xxx", getAndVerifyText(sr)); - assertEquals(2, sr.getDepth()); - - assertTokenType(END_ELEMENT, sr.next()); - assertEquals("child2", sr.getLocalName()); - assertEquals(2, sr.getDepth()); - - assertTokenType(END_ELEMENT, sr.next()); - assertEquals("root", sr.getLocalName()); - assertEquals(1, sr.getDepth()); - - assertTokenType(END_DOCUMENT, sr.next()); - assertEquals(0, sr.getDepth()); - } - -} diff -Nru libwoodstox-java-4.1.3/src/test/resources/org/codehaus/stax/test/evt/surrogate-pairs.xml libwoodstox-java-5.1.0/src/test/resources/org/codehaus/stax/test/evt/surrogate-pairs.xml --- libwoodstox-java-4.1.3/src/test/resources/org/codehaus/stax/test/evt/surrogate-pairs.xml 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/resources/org/codehaus/stax/test/evt/surrogate-pairs.xml 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,4 @@ + + +

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec justo nulla, consequat et laoreet sit amet, pharetra sed lectus. Fusce sed elit a diam iaculis mollis a a leo. Proin ipsum justo, bibendum id pharetra accumsan, tempor eu metus. Nulla facilisi. Proin mattis dui sed diam tincidunt sit amet accumsan est congue. Nullam venenatis elementum tristique. Vivamus magna erat, euismod sed posuere at, blandit non metus. Nam scelerisque pellentesque tempus. Cras ut dolor sed massa dictum porta. Duis felis quam, congue quis porta a, aliquam blandit elit. Nunc bibendum cursus magna, vitae pharetra orci tristique a. Proin vitae massa metus, a tempor nisi. Duis mollis ultrices tellus. Pellentesque vitae consectetur risus. Sed volutpat turpis ut odio ultrices mollis. Aliquam erat volutpat. Suspendisse dapibus cursus vestibulum. Aliquam fringilla placerat pharetra. Duis ac massa nisl, vel gravida est. Nullam sit amet lectus a lacus pharetra scelerisque. Proin posuere dolor ac arcu lacinia aliquam. Curabitur interdum congue metus sit amet consectetur. Fusce dictum risus ac purus blandit nec pharetra lacus tristique. Morbi condimentum lacinia urna, id tristique mi fringilla eu. Praesent lectus dolor, sagittis sit amet pulvinar eget, tristique a libero. Nunc libero dui, venenatis a dictum nec, molestie sed felis. Aenean feugiat rhoncus justo vitae condimentum. Sed iaculis placerat elit mollis tempor. Nulla at porttitor diam. Phasellus pharetra neque imperdiet metus dictum molestie. Aliquam nec justo eget mauris gravida vestibulum. Cras quis est interdum lorem egestas tincidunt. Donec non libero vel metus aliquam dapibus. Aenean purus dolor, congue vel placerat eu, mattis in dolor. Sed nec orci lacus, egestas convallis nulla. Vivamus id orci ac dolor lobortis lacinia. Quisque euismod arcu vel diam bibendum sit amet ultrices magna vestibulum. Pellentesque pellentesque aliquam dolor id ultrices. Nam auctor lorem quis quam commodo facilisis. Duis lorem diam, viverra nec placerat id, consequat sit amet risus. Vestibulum non ipsum elit. Nulla blandit mi condimentum tortor viverra pulvinar. Aenean fringilla nunc in libero malesuada sagittis. Quisque pellentesque, lorem ut pellentesque 𐅅 dapibus, ipsum ante tempor nisi, et lacinia lacus libero ut lorem. Quisque nunc lacus, convallis non rhoncus eu, molestie in dui. Maecenas dapibus lectus sit amet lorem tempor at adipiscing neque molestie. Curabitur in elementum erat. Integer mattis, sem at hendrerit auctor, dolor tellus faucibus arcu, at dignissim felis felis eu neque. Praesent eget lectus odio. Nulla lobortis felis vel erat luctus dignissim. Morbi id odio neque, eget interdum mi. Suspendisse elementum felis at nulla vulputate tempor. Proin vitae tellus lectus, vel gravida turpis. Cras id enim velit. Sed sit amet quam arcu, id pharetra metus. Aliquam laoreet felis facilisis tellus semper eu elementum libero ullamcorper. Nullam sem libero, consectetur in volutpat a, condimentum non libero. Aenean id leo quis lectus sed.

+
\ No newline at end of file diff -Nru libwoodstox-java-4.1.3/src/test/resources/org/codehaus/stax/test/stream/issue294.xml libwoodstox-java-5.1.0/src/test/resources/org/codehaus/stax/test/stream/issue294.xml --- libwoodstox-java-4.1.3/src/test/resources/org/codehaus/stax/test/stream/issue294.xml 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/resources/org/codehaus/stax/test/stream/issue294.xml 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,43 @@ + + + + + + + + diff -Nru libwoodstox-java-4.1.3/src/test/resources/wstxtest/msv/test.wsdl libwoodstox-java-5.1.0/src/test/resources/wstxtest/msv/test.wsdl --- libwoodstox-java-4.1.3/src/test/resources/wstxtest/msv/test.wsdl 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/resources/wstxtest/msv/test.wsdl 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,51 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff -Nru libwoodstox-java-4.1.3/src/test/stax2/BaseStax2Test.java libwoodstox-java-5.1.0/src/test/stax2/BaseStax2Test.java --- libwoodstox-java-4.1.3/src/test/stax2/BaseStax2Test.java 2012-04-24 04:38:21.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/stax2/BaseStax2Test.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,698 +0,0 @@ -package stax2; - -import java.io.*; -import java.util.HashMap; - -import junit.framework.TestCase; - -import javax.xml.stream.*; -import javax.xml.stream.events.XMLEvent; - -import org.codehaus.stax2.*; -import org.codehaus.stax2.evt.*; - -import org.codehaus.stax2.ri.Stax2ReaderAdapter; - -/** - * Base unit test class to be inherited by all unit tests that test - * StAX2 API compatibility. - */ -public abstract class BaseStax2Test - extends TestCase - implements XMLStreamConstants -{ - /** - * Value that should be reported by stax(2) impl to denote "no prefix" - * for elements - */ - final static String ELEM_NO_PREFIX = ""; - - /** - * Value that should be reported by stax(2) impl to denote "no prefix" - * for attributes - */ - final static String ATTR_NO_PREFIX = ""; - - final static HashMap mTokenTypes = new HashMap(); - static { - mTokenTypes.put(new Integer(START_ELEMENT), "START_ELEMENT"); - mTokenTypes.put(new Integer(END_ELEMENT), "END_ELEMENT"); - mTokenTypes.put(new Integer(START_DOCUMENT), "START_DOCUMENT"); - mTokenTypes.put(new Integer(END_DOCUMENT), "END_DOCUMENT"); - mTokenTypes.put(new Integer(CHARACTERS), "CHARACTERS"); - mTokenTypes.put(new Integer(CDATA), "CDATA"); - mTokenTypes.put(new Integer(COMMENT), "COMMENT"); - mTokenTypes.put(new Integer(PROCESSING_INSTRUCTION), "PROCESSING_INSTRUCTION"); - mTokenTypes.put(new Integer(DTD), "DTD"); - mTokenTypes.put(new Integer(SPACE), "SPACE"); - mTokenTypes.put(new Integer(ENTITY_REFERENCE), "ENTITY_REFERENCE"); - } - - /** - * Switch that can be turned on to verify to display ALL exact Exceptions - * thrown when Exceptions are expected. This is sometimes necessary - * when debugging, since it's impossible to automatically verify - * that Exception is exactly the right one, since there is no - * strict Exception type hierarchy for StAX problems. - *

- * Note: Not made 'final static', so that compiler won't inline - * it. Makes possible to do partial re-compilations. - * Note: Since it's only used as the default value, sub-classes - * can separately turn it off as necessary - */ - //protected static boolean DEF_PRINT_EXP_EXCEPTION = true; - protected static boolean DEF_PRINT_EXP_EXCEPTION = false; - - protected boolean PRINT_EXP_EXCEPTION = DEF_PRINT_EXP_EXCEPTION; - - /* - /////////////////////////////////////////////////////////// - // Lazy-loaded thingies - /////////////////////////////////////////////////////////// - */ - - XMLInputFactory2 mInputFactory = null; - XMLOutputFactory2 mOutputFactory = null; - XMLEventFactory2 mEventFactory = null; - - /* - /////////////////////////////////////////////////////////// - // Factory methods - /////////////////////////////////////////////////////////// - */ - - protected XMLInputFactory2 getInputFactory() - { - if (mInputFactory == null) { - /* Shouldn't try to set these here, if these tests are - * to be reusable. Rather, junit (ant) task should - * define system properties if necessary. - */ - //System.setProperty("javax.xml.stream.XMLInputFactory", "..."); - mInputFactory = getNewInputFactory(); - } - return mInputFactory; - } - - protected XMLStreamReader2 constructNsStreamReader(String content, boolean coal) - throws XMLStreamException - { - XMLInputFactory f = getInputFactory(); - setNamespaceAware(f, true); - setCoalescing(f, coal); - return (XMLStreamReader2) f.createXMLStreamReader(new StringReader(content)); - } - - protected XMLStreamReader2 constructNsStreamReader(InputStream in, boolean coal) - throws XMLStreamException - { - XMLInputFactory f = getInputFactory(); - setNamespaceAware(f, true); - setCoalescing(f, coal); - return (XMLStreamReader2) f.createXMLStreamReader(in); - } - - protected XMLEventFactory2 getEventFactory() - { - if (mEventFactory == null) { - /* Shouldn't try to set these here, if these tests are - * to be reusable. Rather, junit (ant) task should - * define system properties if necessary. - */ - //System.setProperty("javax.xml.stream.XMLEventFactory", "..."); - mEventFactory = (XMLEventFactory2) XMLEventFactory.newInstance(); - } - return mEventFactory; - } - - protected static XMLInputFactory2 getNewInputFactory() - { - return (XMLInputFactory2) XMLInputFactory.newInstance(); - } - - protected XMLOutputFactory2 getOutputFactory() - { - if (mOutputFactory == null) { - //System.setProperty("javax.xml.stream.XMLOutputFactory", "..."); - mOutputFactory = getNewOutputFactory(); - } - return mOutputFactory; - } - - protected static XMLOutputFactory2 getNewOutputFactory() - { - return (XMLOutputFactory2) XMLOutputFactory.newInstance(); - } - - protected static XMLStreamReader2 constructStreamReader(XMLInputFactory f, String content) - throws XMLStreamException - { - return (XMLStreamReader2) f.createXMLStreamReader(new StringReader(content)); - } - - protected static XMLStreamReader2 constructStreamReader(XMLInputFactory f, byte[] data) - throws XMLStreamException - { - return (XMLStreamReader2) f.createXMLStreamReader(new ByteArrayInputStream(data)); - } - - protected static XMLStreamReader2 constructStreamReaderForFile(XMLInputFactory f, String filename) - throws IOException, XMLStreamException - { - File inf = new File(filename); - XMLStreamReader sr = f.createXMLStreamReader(inf.toURL().toString(), - new FileReader(inf)); - assertEquals(sr.getEventType(), START_DOCUMENT); - return (XMLStreamReader2) sr; - } - - protected static XMLEventReader2 constructEventReader(XMLInputFactory f, String content) - throws XMLStreamException - { - return (XMLEventReader2) f.createXMLEventReader(new StringReader(content)); - } - - protected XMLStreamReader2 constructNonNsStreamReader(String content, boolean coal) - throws XMLStreamException - { - XMLInputFactory f = getInputFactory(); - setNamespaceAware(f, false); - setCoalescing(f, coal); - return (XMLStreamReader2) f.createXMLStreamReader(new StringReader(content)); - } - - /** - * Method to force constructing a wrapper for given stream reader. - * Have to use this method to work around natural resistance by - * the wrapper to apply itself on what it considered "unnecessary" - * target. - */ - protected XMLStreamReader2 wrapWithAdapter(XMLStreamReader sr) - { - return new ForcedAdapter(sr); - } - - /* - /////////////////////////////////////////////////////////// - // Configuring input factory - /////////////////////////////////////////////////////////// - */ - - protected static boolean setNamespaceAware(XMLInputFactory f, boolean state) - throws XMLStreamException - { - /* Let's not assert, but see if it sticks. Some implementations - * might choose to silently ignore setting, at least for 'false'? - */ - try { - f.setProperty(XMLInputFactory.IS_NAMESPACE_AWARE, state ? Boolean.TRUE : Boolean.FALSE); - return (isNamespaceAware(f) == state); - } catch (IllegalArgumentException e) { - /* Let's assume, then, that the property (or specific value for it) - * is NOT supported... - */ - return false; - } - } - - protected static boolean isNamespaceAware(XMLInputFactory f) - throws XMLStreamException - { - return ((Boolean) f.getProperty(XMLInputFactory.IS_NAMESPACE_AWARE)).booleanValue(); - } - - protected static void setCoalescing(XMLInputFactory f, boolean state) - throws XMLStreamException - { - f.setProperty(XMLInputFactory.IS_COALESCING, Boolean.valueOf(state)); - } - - protected static void setValidating(XMLInputFactory f, boolean state) - throws XMLStreamException - { - f.setProperty(XMLInputFactory.IS_VALIDATING, Boolean.valueOf(state)); - } - - protected static boolean setSupportDTD(XMLInputFactory f, boolean state) - throws XMLStreamException - { - try { - f.setProperty(XMLInputFactory.SUPPORT_DTD, Boolean.valueOf(state)); - return (willSupportDTD(f) == state); - } catch (IllegalArgumentException e) { - // Let's assume that the property (or specific value) is NOT supported... - return false; - } - } - - protected static boolean willSupportDTD(XMLInputFactory f) - throws XMLStreamException - { - return ((Boolean) f.getProperty(XMLInputFactory.SUPPORT_DTD)).booleanValue(); - } - - protected static void setReplaceEntities(XMLInputFactory f, boolean state) - throws XMLStreamException - { - f.setProperty(XMLInputFactory.IS_REPLACING_ENTITY_REFERENCES, - state ? Boolean.TRUE : Boolean.FALSE); - } - - protected static void setSupportExternalEntities(XMLInputFactory f, boolean state) - throws XMLStreamException - { - f.setProperty(XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES, - state ? Boolean.TRUE : Boolean.FALSE); - } - - protected static void setLazyParsing(XMLInputFactory f, boolean state) - throws XMLStreamException - { - f.setProperty(XMLInputFactory2.P_LAZY_PARSING, - state ? Boolean.TRUE : Boolean.FALSE); - } - - /* - /////////////////////////////////////////////////////////// - // Configuring output factory - /////////////////////////////////////////////////////////// - */ - - protected static void setRepairing(XMLOutputFactory f, boolean state) - { - f.setProperty(XMLOutputFactory.IS_REPAIRING_NAMESPACES, - Boolean.valueOf(state)); - } - - protected static boolean setNamespaceAware(XMLOutputFactory f, boolean state) - throws XMLStreamException - { - /* Let's not assert, but see if it sticks. Some implementations - * might choose to silently ignore setting, at least for 'false'? - */ - try { - f.setProperty(XMLStreamProperties.XSP_NAMESPACE_AWARE, state ? Boolean.TRUE : Boolean.FALSE); - return (isNamespaceAware(f) == state); - } catch (IllegalArgumentException e) { - /* Let's assume, then, that the property (or specific value for it) - * is NOT supported... - */ - return false; - } - } - - protected static boolean isNamespaceAware(XMLOutputFactory f) - throws XMLStreamException - { - return ((Boolean) f.getProperty(XMLStreamProperties.XSP_NAMESPACE_AWARE)).booleanValue(); - } - - /* - /////////////////////////////////////////////////////////// - // Higher-level test methods - /////////////////////////////////////////////////////////// - */ - - /** - * Method that will iterate through contents of an XML document - * using specified stream reader; will also access some of data - * to make sure reader reads most of lazy-loadable data. - * Method is usually called to try to get an exception for invalid - * content. - * - * @return Dummy value calculated on contents; used to make sure - * no dead code is eliminated - */ - protected int streamThrough(XMLStreamReader sr) - throws XMLStreamException - { - int result = 0; - - while (sr.hasNext()) { - int type = sr.next(); - result += type; - if (sr.hasText()) { - /* will also do basic verification for text content, to - * see that all text accessor methods return same content - */ - result += getAndVerifyText(sr).hashCode(); - } - if (sr.hasName()) { - result += sr.getName().hashCode(); - } - } - - return result; - } - - protected int streamThroughFailing(XMLInputFactory f, String contents, - String msg) - throws XMLStreamException - { - int result = 0; - try { - XMLStreamReader sr = constructStreamReader(f, contents); - result = streamThrough(sr); - } catch (XMLStreamException ex) { // good - if (PRINT_EXP_EXCEPTION) { - System.out.println("Expected failure: '"+ex.getMessage()+"' " - +"(matching message: '"+msg+"')"); - } - return 0; - } catch (RuntimeException ex2) { // ok - if (PRINT_EXP_EXCEPTION) { - System.out.println("Expected failure: '"+ex2.getMessage()+"' " - +"(matching message: '"+msg+"')"); - } - return 0; - } catch (Throwable t) { // not so good - fail("Expected an XMLStreamException or RuntimeException for "+msg - +", got: "+t); - } - - fail("Expected an exception for "+msg); - return result; // never gets here - } - - protected int streamThroughFailing(XMLStreamReader sr, String msg) - throws XMLStreamException - { - int result = 0; - try { - result = streamThrough(sr); - } catch (XMLStreamException ex) { // good - if (PRINT_EXP_EXCEPTION) { - System.out.println("Expected failure: '"+ex.getMessage()+"' " - +"(matching message: '"+msg+"')"); - } - return 0; - } catch (RuntimeException ex2) { // ok - if (PRINT_EXP_EXCEPTION) { - System.out.println("Expected failure: '"+ex2.getMessage()+"' " - +"(matching message: '"+msg+"')"); - } - return 0; - } catch (Throwable t) { // not so good - fail("Expected an XMLStreamException or RuntimeException for "+msg - +", got: "+t); - } - - fail("Expected an exception for "+msg); - return result; // never gets here - } - - /* - /////////////////////////////////////////////////////////// - // Assertions - /////////////////////////////////////////////////////////// - */ - - protected static String tokenTypeDesc(int tt) - { - String desc = (String) mTokenTypes.get(new Integer(tt)); - return (desc == null) ? ("["+tt+"]") : desc; - } - - protected static void assertTokenType(int expType, XMLEvent evt) - { - assertTokenType(expType, evt.getEventType()); - } - - protected static void assertTokenType(int expType, int actType) - { - if (expType != actType) { - String expStr = tokenTypeDesc(expType); - String actStr = tokenTypeDesc(actType); - - if (expStr == null) { - expStr = ""+expType; - } - if (actStr == null) { - actStr = ""+actType; - } - fail("Expected token "+expStr+"; got "+actStr+"."); - } - } - - /** - * Helper assertion that assert that the String is either null or - * empty (""). - */ - protected static void assertNullOrEmpty(String str) - { - if (str != null && str.length() > 0) { - fail("Expected String to be empty or null; was '"+str+"' (length " - +str.length()+")"); - } - } - - protected static void assertNotNullOrEmpty(String str) - { - if (str == null || str.length() == 0) { - fail("Expected String to be non-empty; got " - +((str == null) ? "NULL" : "\"\"")); - } - } - - /** - * Method that can be used to verify that the current element - * pointed to by the stream reader has no prefix. - */ - protected static void assertNoElemPrefix(XMLStreamReader sr) - throws XMLStreamException - { - String prefix = sr.getPrefix(); - if (prefix != ELEM_NO_PREFIX) { - fail("Element that does not have a prefix should be indicated with <"+ELEM_NO_PREFIX+">, not <"+prefix+">"); - } - } - - /** - * Helper method for ensuring that the given return value for - * attribute prefix accessor has returned a value that - * represents "no prefix" value. - *

- * Current thinking (early 2008) is that empty string is the - * expected value here. - */ - protected static void assertNoAttrPrefix(String attrPrefix) - throws XMLStreamException - { - if (attrPrefix != ATTR_NO_PREFIX) { - fail("Attribute that does not have a prefix should be indicated with <"+ATTR_NO_PREFIX+">, not <"+attrPrefix+">"); - } - } - - /** - * Method that can be used to verify that the current element - * pointed to by the stream reader does not belong to a namespace. - */ - protected static void assertElemNotInNamespace(XMLStreamReader sr) - throws XMLStreamException - { - String uri = sr.getNamespaceURI(); - if (uri == null) { - fail("Excepted empty String to indicate \"no namespace\": got null"); - } else if (uri.length() != 0) { - fail("Excepted no (null) namespace URI: got '"+uri+"'"); - } - } - - protected static void assertNoAttrNamespace(String attrNsURI) - throws XMLStreamException - { - if (attrNsURI == null) { - fail("Expected empty String to indicate \"no namespace\" (for attribute): got null"); - } else if (attrNsURI.length() != 0) { - fail("Expected empty String to indicate \"no namespace\" (for attribute): got '"+attrNsURI+"'"); - } - } - - protected static void failStrings(String msg, String exp, String act) - { - // !!! TODO: Indicate position where Strings differ - fail(msg+": expected "+quotedPrintable(exp)+", got " - +quotedPrintable(act)); - } - - /** - * Method that not only gets currently available text from the - * reader, but also checks that its consistenly accessible using - * different (basic) StAX methods. - */ - protected static String getAndVerifyText(XMLStreamReader sr) - throws XMLStreamException - { - /* 05-Apr-2006, TSa: Although getText() is available for DTD - * and ENTITY_REFERENCE, getTextXxx() are not. Thus, can not - * do more checks for those types. - */ - int type = sr.getEventType(); - if (type == ENTITY_REFERENCE || type == DTD) { - return sr.getText(); - } - - int expLen = sr.getTextLength(); - /* Hmmh. It's only ok to return empty text for DTD event... well, - * maybe also for CDATA, since empty CDATA blocks are legal? - */ - /* !!! 01-Sep-2004, TSa: - * note: theoretically, in coalescing mode, it could be possible - * to have empty CDATA section(s) get converted to CHARACTERS, - * which would be empty... may need to enhance this to check that - * mode is not coalescing? Or something - */ - if (type == CHARACTERS) { - assertTrue("Stream reader should never return empty Strings.", (expLen > 0)); - } - String text = sr.getText(); - assertNotNull("getText() should never return null.", text); - assertEquals("Expected text length of "+expLen+", got "+text.length(), - expLen, text.length()); - char[] textChars = sr.getTextCharacters(); - int start = sr.getTextStart(); - String text2 = new String(textChars, start, expLen); - assertEquals(text, text2); - return text; - } - - protected void verifyException(Throwable e, String match) - { - String msg = e.getMessage(); - String lmsg = msg.toLowerCase(); - String lmatch = match.toLowerCase(); - if (lmsg.indexOf(lmatch) < 0) { - fail("Expected an exception with sub-string \""+match+"\": got one with message \""+msg+"\""); - } - } - - /* - /////////////////////////////////////////////////////////// - // Debug/output helpers - /////////////////////////////////////////////////////////// - */ - - public static void warn(String msg) - { - System.err.println("WARN: "+msg); - } - - public static String printable(char ch) - { - if (ch == '\n') { - return "\\n"; - } - if (ch == '\r') { - return "\\r"; - } - if (ch == '\t') { - return "\\t"; - } - if (ch == ' ') { - return "_"; - } - if (ch > 127 || ch < 32) { - StringBuffer sb = new StringBuffer(6); - sb.append("\\u"); - String hex = Integer.toHexString((int)ch); - for (int i = 0, len = 4 - hex.length(); i < len; i++) { - sb.append('0'); - } - sb.append(hex); - return sb.toString(); - } - return null; - } - - public static String printableWithSpaces(char ch) - { - if (ch == '\n') { - return "\\n"; - } - if (ch == '\r') { - return "\\r"; - } - if (ch == '\t') { - return "\\t"; - } - if (ch > 127 || ch < 32) { - StringBuffer sb = new StringBuffer(6); - sb.append("\\u"); - String hex = Integer.toHexString((int)ch); - for (int i = 0, len = 4 - hex.length(); i < len; i++) { - sb.append('0'); - } - sb.append(hex); - return sb.toString(); - } - return null; - } - - public static String printable(String str) - { - if (str == null || str.length() == 0) { - return str; - } - - int len = str.length(); - StringBuffer sb = new StringBuffer(len + 64); - for (int i = 0; i < len; ++i) { - char c = str.charAt(i); - String res = printable(c); - if (res == null) { - sb.append(c); - } else { - sb.append(res); - } - } - return sb.toString(); - } - - public static String printableWithSpaces(String str) - { - if (str == null || str.length() == 0) { - return str; - } - - int len = str.length(); - StringBuffer sb = new StringBuffer(len + 64); - for (int i = 0; i < len; ++i) { - char c = str.charAt(i); - String res = printableWithSpaces(c); - if (res == null) { - sb.append(c); - } else { - sb.append(res); - } - } - return sb.toString(); - } - - protected static String quotedPrintable(String str) - { - if (str == null || str.length() == 0) { - return "[0]''"; - } - return "[len: "+str.length()+"] '"+printable(str)+"'"; - } - - /* - /////////////////////////////////////////////////////////// - // Helper classes - /////////////////////////////////////////////////////////// - */ - - /** - * Need a dummy base class to be able to access protected - * constructor for testing purposes. - */ - final static class ForcedAdapter - extends Stax2ReaderAdapter - { - public ForcedAdapter(XMLStreamReader sr) - { - super(sr); - } - } -} - diff -Nru libwoodstox-java-4.1.3/src/test/stax2/dom/TestDomCompat.java libwoodstox-java-5.1.0/src/test/stax2/dom/TestDomCompat.java --- libwoodstox-java-4.1.3/src/test/stax2/dom/TestDomCompat.java 2012-04-24 04:38:21.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/stax2/dom/TestDomCompat.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,389 +0,0 @@ -package stax2.dom; - -import java.io.*; - -import javax.xml.parsers.*; -import javax.xml.namespace.NamespaceContext; -import javax.xml.namespace.QName; -import javax.xml.stream.*; -import javax.xml.transform.dom.DOMSource; - -import org.xml.sax.InputSource; -import org.w3c.dom.Document; -import org.w3c.dom.DocumentFragment; - -import org.codehaus.stax2.*; - -import stax2.BaseStax2Test; - -/** - * Unit test suite that checks that input-side DOM-compatibility - * features (DOMSource as input) are implemented as expected. - *

- * This test is part of stax2test suite because a reference implementation - * of DOM-wrapping/adapting reader is included, and hence it is - * reasonable to expect that Stax2 implementations would implement - * this part of DOM interoperability support. - */ -public class TestDomCompat - extends BaseStax2Test -{ - public void testSimpleDomInput() throws Exception - { - final String XML = - "" - +"" - +"" - +"" - +"\nAnd some text" - +"" - ; - - XMLStreamReader sr = createDomBasedReader(XML, true); - - assertTokenType(COMMENT, sr.next()); - assertEquals("prolog", getAndVerifyText(sr)); - - // 10-Sep-2010, tatu: Verify [WSTX-246] - assertNotNull(sr.getLocation()); - - assertTokenType(START_ELEMENT, sr.next()); - assertEquals("root", sr.getLocalName()); - assertEquals("ns", sr.getPrefix()); - assertEquals("http://foo", sr.getNamespaceURI()); - QName n = sr.getName(); - assertNotNull(n); - assertEquals("root", n.getLocalPart()); - - assertEquals(1, sr.getAttributeCount()); - assertEquals("attr", sr.getAttributeLocalName(0)); - assertEquals("", sr.getAttributePrefix(0)); - assertEquals("", sr.getAttributeNamespace(0)); - n = sr.getAttributeName(0); - assertNotNull(n); - assertEquals("attr", n.getLocalPart()); - assertEquals("value", sr.getAttributeValue(0)); - - assertEquals(1, sr.getNamespaceCount()); - assertEquals("ns", sr.getNamespacePrefix(0)); - assertEquals("http://foo", sr.getNamespaceURI(0)); - - NamespaceContext nsCtxt = sr.getNamespaceContext(); - assertNotNull(nsCtxt); - /* 28-Apr-2006, TSa: Alas, namespace access is only fully - * implemented in DOM Level 3 (JDK 1.5+)... thus, can't check: - */ - /* - assertEquals("ns", nsCtxt.getPrefix("http://foo")); - assertEquals("http://foo", nsCtxt.getNamespaceURI("ns")); - assertNull(nsCtxt.getPrefix("http://whatever")); - assertNull(nsCtxt.getNamespaceURI("nsX")); - */ - - assertTokenType(START_ELEMENT, sr.next()); - assertEquals("leaf", sr.getLocalName()); - assertEquals("", sr.getPrefix()); - assertEquals("", sr.getNamespaceURI()); - assertEquals(1, sr.getAttributeCount()); - assertEquals("attr", sr.getAttributeLocalName(0)); - assertEquals("ns", sr.getAttributePrefix(0)); - assertEquals("http://foo", sr.getAttributeNamespace(0)); - assertEquals(0, sr.getNamespaceCount()); - - assertTokenType(END_ELEMENT, sr.next()); - assertEquals("leaf", sr.getLocalName()); - assertEquals("", sr.getPrefix()); - assertEquals("", sr.getNamespaceURI()); - assertEquals(0, sr.getNamespaceCount()); - - assertTokenType(PROCESSING_INSTRUCTION, sr.next()); - assertEquals("proc", sr.getPITarget()); - assertEquals("instr", sr.getPIData()); - - assertTokenType(COMMENT, sr.next()); - assertEquals("comment", getAndVerifyText(sr)); - - assertTokenType(CHARACTERS, sr.next()); - // yeah yeah, could be split... - assertEquals("\nAnd some text", getAndVerifyText(sr)); - - assertTokenType(END_ELEMENT, sr.next()); - assertEquals("root", sr.getLocalName()); - assertEquals("ns", sr.getPrefix()); - assertEquals("http://foo", sr.getNamespaceURI()); - - assertEquals(1, sr.getNamespaceCount()); - assertEquals("ns", sr.getNamespacePrefix(0)); - assertEquals("http://foo", sr.getNamespaceURI(0)); - - assertTokenType(PROCESSING_INSTRUCTION, sr.next()); - assertEquals("pi-in", sr.getPITarget()); - assertEquals("epilog", sr.getPIData()); - - assertTokenType(END_DOCUMENT, sr.next()); - - assertFalse(sr.hasNext()); - sr.close(); - } - - /** - * Test added to verify that [WSTX-134] is fixed properly - */ - public void testDomWhitespace() - throws Exception - { - final String XML = - " \n\t x "; - XMLStreamReader sr = createDomBasedReader(XML, true); - - assertTokenType(START_ELEMENT, sr.next()); - assertEquals("root", sr.getLocalName()); - assertTokenType(CHARACTERS, sr.next()); - assertTrue(sr.isWhiteSpace()); - assertEquals(" \n", getAndVerifyText(sr)); - assertTokenType(START_ELEMENT, sr.next()); - assertEquals("leaf", sr.getLocalName()); - assertTokenType(CHARACTERS, sr.next()); - assertTrue(sr.isWhiteSpace()); - assertEquals("\t", getAndVerifyText(sr)); - assertTokenType(END_ELEMENT, sr.next()); - assertEquals("leaf", sr.getLocalName()); - assertTokenType(CHARACTERS, sr.next()); - assertFalse(sr.isWhiteSpace()); - assertEquals(" x ", getAndVerifyText(sr)); - assertTokenType(END_ELEMENT, sr.next()); - assertEquals("root", sr.getLocalName()); - assertTokenType(END_DOCUMENT, sr.next()); - sr.close(); - } - - /** - * Test to verify that [WSTX-145] is properly fixed - */ - public void testDomCoalescingText() - throws Exception - { - final String XML = - "Some in cdata"; - - Document doc = parseDomDoc(XML, true); - XMLInputFactory2 ifact = getInputFactory(); - setCoalescing(ifact, true); - XMLStreamReader sr = ifact.createXMLStreamReader(new DOMSource(doc)); - assertTokenType(START_DOCUMENT, sr.getEventType()); - assertTokenType(START_ELEMENT, sr.next()); - assertEquals("root", sr.getLocalName()); - assertTokenType(CHARACTERS, sr.next()); - assertEquals("Some content in cdata", getAndVerifyText(sr)); - - assertTokenType(END_ELEMENT, sr.next()); - assertTokenType(END_DOCUMENT, sr.next()); - } - - public void testDomCoalescingType() - throws Exception - { - final String XML = - ""; - ; - Document doc = parseDomDoc(XML, true); - XMLInputFactory2 ifact = getInputFactory(); - setCoalescing(ifact, true); - XMLStreamReader sr = ifact.createXMLStreamReader(new DOMSource(doc)); - assertTokenType(START_ELEMENT, sr.next()); - assertEquals("root", sr.getLocalName()); - // Should always be of type CHARACTERS, even if underlying event is CDATA - assertTokenType(CHARACTERS, sr.next()); - assertEquals("...", getAndVerifyText(sr)); - - assertTokenType(END_ELEMENT, sr.next()); - assertTokenType(END_DOCUMENT, sr.next()); - } - - /** - * First test regarding [WSTX-162], let's check that we can - * actually enable/disable interning on reader instances - * (independent of whether settings take effect or not) - */ - public void testDomInternProperties() - throws Exception - { - Document doc = parseDomDoc("", true); - XMLInputFactory2 ifact = getInputFactory(); - XMLStreamReader2 sr = (XMLStreamReader2) ifact.createXMLStreamReader(new DOMSource(doc)); - - boolean okSet = sr.setProperty(XMLInputFactory2.P_INTERN_NAMES, Boolean.TRUE); - assertTrue(okSet); - assertEquals(Boolean.TRUE, sr.getProperty(XMLInputFactory2.P_INTERN_NAMES)); - okSet = sr.setProperty(XMLInputFactory2.P_INTERN_NAMES, Boolean.FALSE); - assertTrue(okSet); - assertEquals(Boolean.FALSE, sr.getProperty(XMLInputFactory2.P_INTERN_NAMES)); - - okSet = sr.setProperty(XMLInputFactory2.P_INTERN_NS_URIS, Boolean.TRUE); - assertTrue(okSet); - assertEquals(Boolean.TRUE, sr.getProperty(XMLInputFactory2.P_INTERN_NS_URIS)); - okSet = sr.setProperty(XMLInputFactory2.P_INTERN_NS_URIS, Boolean.FALSE); - assertTrue(okSet); - assertEquals(Boolean.FALSE, sr.getProperty(XMLInputFactory2.P_INTERN_NS_URIS)); - } - - /** - * Test for checking that [WSTX-162] has been addressed, - * regarding names. - */ - public void testDomInternNames() - throws Exception - { - final String ELEM = "root"; - final String PREFIX = "ns"; - final String ATTR = "attr"; - final String URI = "http://foo"; - final String XML = "<"+PREFIX+":"+ELEM+" attr='1' xmlns:"+PREFIX+"='"+URI+"' />"; - Document doc = parseDomDoc(XML, true); - XMLInputFactory2 ifact = getInputFactory(); - - /* Ok, so: let's first ensure that local names ARE intern()ed - * when we request them to be: - */ - ifact.setProperty(XMLInputFactory2.P_INTERN_NAMES, Boolean.TRUE); - XMLStreamReader sr = ifact.createXMLStreamReader(new DOMSource(doc)); - assertTokenType(START_ELEMENT, sr.next()); - assertEquals(ELEM, sr.getLocalName()); - assertSame(ELEM, sr.getLocalName()); - - assertEquals(ATTR, sr.getAttributeLocalName(0)); - assertSame(ATTR, sr.getAttributeLocalName(0)); - - assertEquals(PREFIX, sr.getPrefix()); - assertSame(PREFIX, sr.getPrefix()); - sr.close(); - - /* And then also that the impl does honor disabling of - * the feature: while optional, ref. impl. makes this - * easy so there's no excuse not to. - */ - ifact.setProperty(XMLInputFactory2.P_INTERN_NAMES, Boolean.FALSE); - sr = ifact.createXMLStreamReader(new DOMSource(doc)); - assertTokenType(START_ELEMENT, sr.next()); - assertEquals(ELEM, sr.getLocalName()); - // Xerces won't force intern() of element names - assertNotSame(ELEM, sr.getLocalName()); - - // But does intern attribute names - /* - assertEquals(ATTR, sr.getAttributeLocalName(0)); - assertNotSame(ATTR, sr.getAttributeLocalName(0)); - */ - - assertEquals(PREFIX, sr.getPrefix()); - assertNotSame(PREFIX, sr.getPrefix()); - sr.close(); - } - - /** - * Test for checking that [WSTX-162] has been addressed, - * regarding names. - */ - public void testDomInternNsURIs() - throws Exception - { - final String ELEM = "root"; - final String URI = "http://foo"; - final String XML = "<"+ELEM+" xmlns='"+URI+"' />"; - Document doc = parseDomDoc(XML, true); - XMLInputFactory2 ifact = getInputFactory(); - - /* Ok, so: let's first ensure that URIs are intern()ed - * when we request them to be: - */ - ifact.setProperty(XMLInputFactory2.P_INTERN_NS_URIS, Boolean.TRUE); - XMLStreamReader sr = ifact.createXMLStreamReader(new DOMSource(doc)); - assertTokenType(START_ELEMENT, sr.next()); - assertEquals(ELEM, sr.getLocalName()); - assertEquals(URI, sr.getNamespaceURI()); - assertSame(URI, sr.getNamespaceURI()); - sr.close(); - - /* Beyond this we can't say much: it all depends on whether - * the backing DOM impl uses intern() or not. - */ - ifact.setProperty(XMLInputFactory2.P_INTERN_NS_URIS, Boolean.FALSE); - sr = ifact.createXMLStreamReader(new DOMSource(doc)); - assertTokenType(START_ELEMENT, sr.next()); - assertEquals(ELEM, sr.getLocalName()); - assertEquals(URI, sr.getNamespaceURI()); - - // Ok, looks like Xerces does intern namespace URIs? Weird... - /* - assertNotSame(URI, sr.getNamespaceURI()); - */ - - sr.close(); - } - - // [WSTX-244] - public void testGetElementTExt() throws Exception - { - final String XML = - "Sometext"; - ; - - XMLInputFactory2 ifact = getInputFactory(); - XMLStreamReader sr; - - // First, non-coalescing: - setCoalescing(ifact, false); - sr = ifact.createXMLStreamReader(new DOMSource(parseDomDoc(XML, true))); - assertTokenType(START_ELEMENT, sr.next()); - assertEquals("Some text", sr.getElementText()); - assertTokenType(END_ELEMENT, sr.getEventType()); - assertTokenType(END_DOCUMENT, sr.next()); - sr.close(); - - // then coalescing - setCoalescing(ifact, true); - sr = ifact.createXMLStreamReader(new DOMSource(parseDomDoc(XML, true))); - assertTokenType(START_ELEMENT, sr.next()); - assertEquals("Some text", sr.getElementText()); - assertTokenType(END_ELEMENT, sr.getEventType()); - assertTokenType(END_DOCUMENT, sr.next()); - sr.close(); - } - - // [WSTX-259] - public void testEmptyFragment() throws Exception - { - DocumentFragment fragment = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument().createDocumentFragment(); - - XMLStreamReader sr = XMLInputFactory.newInstance().createXMLStreamReader(new DOMSource(fragment)); - assertTokenType(START_DOCUMENT, sr.getEventType()); - assertTokenType(END_DOCUMENT, sr.next()); - assertFalse(sr.hasNext()); - } - - /* - /////////////////////////////////////////////////////////// - // Helper methods - /////////////////////////////////////////////////////////// - */ - - private XMLStreamReader2 createDomBasedReader(String content, boolean nsAware) - throws Exception - { - XMLInputFactory2 ifact = getInputFactory(); - XMLStreamReader2 sr = (XMLStreamReader2) ifact.createXMLStreamReader(new DOMSource(parseDomDoc(content, nsAware))); - // Let's also check it's properly initialized - assertTokenType(START_DOCUMENT, sr.getEventType()); - return sr; - } - - private Document parseDomDoc(String content, boolean nsAware) - throws Exception - { - // First, need to parse using JAXP DOM: - DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); - dbf.setNamespaceAware(nsAware); - DocumentBuilder db = dbf.newDocumentBuilder(); - return db.parse(new InputSource(new StringReader(content))); - } -} diff -Nru libwoodstox-java-4.1.3/src/test/stax2/dom/TestDomNamespaces.java libwoodstox-java-5.1.0/src/test/stax2/dom/TestDomNamespaces.java --- libwoodstox-java-4.1.3/src/test/stax2/dom/TestDomNamespaces.java 2012-04-24 04:38:21.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/stax2/dom/TestDomNamespaces.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,58 +0,0 @@ -package stax2.dom; - -import java.io.StringReader; - -import javax.xml.parsers.DocumentBuilder; -import javax.xml.parsers.DocumentBuilderFactory; -import javax.xml.stream.*; -import javax.xml.transform.dom.DOMSource; - -import org.w3c.dom.Document; -import org.xml.sax.InputSource; - -import stax2.BaseStax2Test; - -/** - * Additional reader-side tests for namespace handling with DOM input - */ -public class TestDomNamespaces - extends BaseStax2Test -{ - private String xml = "" - +"" - +"" - +"321" - +"" - +"" - +""; - - public void testDOMSource() throws Exception - { - DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); - factory.setNamespaceAware(true); - DocumentBuilder builder = factory.newDocumentBuilder(); - - InputSource source = new InputSource(new StringReader(xml)); - Document doc = builder.parse(source); - - //Fails when using DOMWrappingReader - XMLStreamReader reader = getInputFactory().createXMLStreamReader(new DOMSource(doc)); - - reader.next(); //root - assertEquals(0, reader.getAttributeCount()); - assertEquals(1, reader.getNamespaceCount()); - assertEquals("http://testnamespace/", reader.getNamespaceURI()); - assertEquals("ns2", reader.getPrefix()); - assertEquals("root", reader.getLocalName()); - - reader.next(); //arg0 - reader.next(); //obj - - assertEquals("obj", reader.getLocalName()); - assertEquals("ns2:mycomplextype", reader.getAttributeValue("http://www.w3.org/2001/XMLSchema-instance", "type")); - assertEquals("http://testnamespace/", reader.getNamespaceURI("ns2")); - assertEquals("http://testnamespace/", reader.getNamespaceContext().getNamespaceURI("ns2")); - - assertEquals("ns2", reader.getNamespaceContext().getPrefix("http://testnamespace/")); - } -} diff -Nru libwoodstox-java-4.1.3/src/test/stax2/dom/TestDomResultHandling.java libwoodstox-java-5.1.0/src/test/stax2/dom/TestDomResultHandling.java --- libwoodstox-java-4.1.3/src/test/stax2/dom/TestDomResultHandling.java 2012-04-24 04:38:21.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/stax2/dom/TestDomResultHandling.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,88 +0,0 @@ -package stax2.dom; - -import javax.xml.parsers.*; -import javax.xml.stream.*; -import javax.xml.transform.dom.DOMResult; - -import org.w3c.dom.*; - -import stax2.wstream.BaseWriterTest; - -/** - * Unit tests initially written to verify [WSTX-183], problems with - * using DOM Element for DOMResult (instead of DOM Document). - * - * @author Christopher Paul Simmons (original tests) - * @author Tatu Saloranta (slight modifications) - */ -public class TestDomResultHandling - extends BaseWriterTest -{ - public void testWriteToDocument() throws Exception - { - // First: write to a regular DOM document - createXMLEventWriter(createDomDoc(true)); - } - - public void testWriteToRootElementNotInDOM() throws Exception - { - // let's try outputting under specified element - Document doc = createDomDoc(true); - Element root = doc.createElementNS("ns", "my:root"); - createXMLEventWriter(root); - /* Should not (try to) attach the element to creating document; - * that is up to caller to do - */ - assertNull(doc.getDocumentElement()); - } - - public void testWriteToRootElementInDOM() throws Exception - { - Document doc = createDomDoc(true); - Element root = doc.createElementNS("ns", "my:root"); - doc.appendChild(root); - createXMLEventWriter(root); - } - - public void testWriteBeforeSibling() throws Exception - { - Document doc = createDomDoc(true); - Element root = doc.createElementNS("ns", "my:root"); - doc.appendChild(root); - Element insertBefore = doc.createElementNS("ns", "my:beforeMe"); - root.appendChild(insertBefore); - createXMLEventWriter(root, insertBefore); - } - - /* - /////////////////////////////////////////////////////////// - // Helper methods - /////////////////////////////////////////////////////////// - */ - - private XMLEventWriter createXMLEventWriter(final Node parent, final Node insertBefore) - throws XMLStreamException - { - XMLOutputFactory f = getOutputFactory(); - return f.createXMLEventWriter(new DOMResult(parent, insertBefore)); - } - - /** - * @param resultNode The node to write to. - * @return The result. - * @throws XMLStreamException On error. - */ - private XMLEventWriter createXMLEventWriter(final Node resultNode) - throws XMLStreamException - { - return createXMLEventWriter(resultNode, null); - } - - private Document createDomDoc(boolean nsAware) - throws Exception - { - DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); - dbf.setNamespaceAware(nsAware); - return dbf.newDocumentBuilder().newDocument(); - } -} diff -Nru libwoodstox-java-4.1.3/src/test/stax2/dom/TestDomWrite.java libwoodstox-java-5.1.0/src/test/stax2/dom/TestDomWrite.java --- libwoodstox-java-4.1.3/src/test/stax2/dom/TestDomWrite.java 2012-04-24 04:38:21.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/stax2/dom/TestDomWrite.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,263 +0,0 @@ -package stax2.dom; - -import javax.xml.parsers.*; -import javax.xml.stream.*; -import javax.xml.transform.dom.DOMResult; - -import org.w3c.dom.*; - -import org.codehaus.stax2.typed.TypedXMLStreamWriter; - -import stax2.wstream.BaseWriterTest; - -/** - * Unit test suite that checks that output-side DOM-compatibility - * features (DOMResult for output) are implemented as expected. - */ -public class TestDomWrite - extends BaseWriterTest -{ - final static int TYPE_NON_NS = 0; - final static int TYPE_NS = 1; - final static int TYPE_NS_REPAIRING = 2; - - public void testNonNsOutput() throws Exception - { - /* 23-Dec-2008, TSa: Not all Stax2 impls support non-namespace-aware - * modes: need to first ensure one tested does... - */ - XMLOutputFactory of = getFactory(TYPE_NON_NS); - if (of == null) { - System.err.println("Skipping "+getClass().getName()+"#testNonNsOutput: non-namespace-aware mode not supported"); - return; - } - - Document doc = createDomDoc(false); - XMLStreamWriter sw = of.createXMLStreamWriter(new DOMResult(doc)); - - sw.writeStartDocument(); - sw.writeStartElement("root"); - sw.writeAttribute("attr", "value"); - sw.writeAttribute("ns:attr2", "value2"); - sw.writeEmptyElement("leaf"); - sw.writeCharacters("text?"); - sw.writeEndElement(); - sw.writeEndDocument(); - sw.close(); - - Element root = doc.getDocumentElement(); - - assertNotNull(root); - assertEquals("root", root.getTagName()); - NamedNodeMap attrs = root.getAttributes(); - assertEquals(2, attrs.getLength()); - assertEquals("value", root.getAttribute("attr")); - assertEquals("value2", root.getAttribute("ns:attr2")); - - Node child = root.getFirstChild(); - assertNotNull(child); - assertEquals(Node.ELEMENT_NODE, child.getNodeType()); - Element elem = (Element) child; - assertEquals("leaf", elem.getTagName()); - attrs = elem.getAttributes(); - assertEquals(0, attrs.getLength()); - - child = child.getNextSibling(); - assertNotNull(child); - assertEquals(Node.TEXT_NODE, child.getNodeType()); - // Alas, getTextContent() is DOM 3 (Jdk 1.5+) - //assertEquals("text?", child.getTextContent()); - // ... so we'll use less refined method - assertEquals("text?", child.getNodeValue()); - } - - public void testMiscOutput() throws Exception - { - XMLOutputFactory of = getFactory(TYPE_NON_NS); - if (of == null) { - System.err.println("Skipping "+getClass().getName()+"#testNonNsOutput: non-namespace-aware mode not supported"); - return; - } - Document doc = createDomDoc(false); - XMLStreamWriter sw = of.createXMLStreamWriter(new DOMResult(doc)); - - sw.writeStartDocument(); - sw.writeStartElement("root"); - sw.writeComment("comment!"); - sw.writeCData("cdata!"); - sw.writeEndElement(); - sw.writeEndDocument(); - sw.close(); - - Element root = doc.getDocumentElement(); - - assertNotNull(root); - assertEquals("root", root.getTagName()); - - Node child = root.getFirstChild(); - assertNotNull(child); - assertEquals(Node.COMMENT_NODE, child.getNodeType()); - assertEquals("comment!", child.getNodeValue()); - - child = child.getNextSibling(); - assertNotNull(child); - assertEquals(Node.CDATA_SECTION_NODE, child.getNodeType()); - assertEquals("cdata!", child.getNodeValue()); - assertNull(child.getNextSibling()); - } - - public void testNsOutput() - throws Exception - { - Document doc = createDomDoc(false); - XMLOutputFactory of = getFactory(TYPE_NS); - XMLStreamWriter sw = of.createXMLStreamWriter(new DOMResult(doc)); - final String NS_URI = "http://foo"; - - sw.writeStartDocument(); - sw.writeStartElement("ns", "root", NS_URI); - sw.writeNamespace("ns", NS_URI); - sw.writeAttribute("ns", NS_URI, "attr", "value"); - sw.writeCharacters("..."); - sw.writeEndElement(); - sw.writeEndDocument(); - sw.close(); - - Element root = doc.getDocumentElement(); - - assertNotNull(root); - assertEquals("ns:root", root.getTagName()); - NamedNodeMap attrs = root.getAttributes(); - // DOM includes ns decls as attributes, hence 2: - assertEquals(2, attrs.getLength()); - assertEquals(NS_URI, root.getAttribute("xmlns:ns")); - assertEquals("value", root.getAttribute("ns:attr")); - - Node child = root.getFirstChild(); - assertNotNull(child); - assertEquals(Node.TEXT_NODE, child.getNodeType()); - // Alas, getTextContent() is DOM 3 (Jdk 1.5+) - //assertEquals("text?", child.getTextContent()); - // ... so we'll use less refined method - assertEquals("...", child.getNodeValue()); - } - - public void testRepairingNsOutput() - throws Exception - { - final String URI1 = "urn:1"; - final String URI2 = "urn:2"; - - Document doc = createDomDoc(false); - XMLOutputFactory of = getFactory(TYPE_NS_REPAIRING); - XMLStreamWriter sw = of.createXMLStreamWriter(new DOMResult(doc)); - - sw.writeStartDocument(); - sw.writeStartElement(URI1, "root"); - sw.writeAttribute("attr", "x"); - sw.writeEmptyElement(URI2, "leaf"); - sw.writeStartElement(URI2, "leaf2"); - sw.writeAttribute(URI2, "attr2", ""); - sw.writeEndElement(); - sw.writeEndElement(); - sw.writeEndDocument(); - sw.close(); - - Element root = doc.getDocumentElement(); - - //System.err.println("DOC -> "+((org.w3c.dom.ls.DOMImplementationLS) doc.getImplementation()).createLSSerializer().writeToString(doc)); - - assertNotNull(root); - assertEquals("root", root.getLocalName()); - assertEquals(URI1, root.getNamespaceURI()); - NamedNodeMap attrs = root.getAttributes(); - // 1 attribute, 1 ns decl: - assertEquals(2, attrs.getLength()); - // interesting -- as per javadocs, must pass null for "no namespace" - assertEquals("x", root.getAttributeNS(null, "attr")); - - Node child = root.getFirstChild(); - assertNotNull(child); - assertEquals(Node.ELEMENT_NODE, child.getNodeType()); - Element elem = (Element) child; - assertEquals("leaf", elem.getLocalName()); - attrs = elem.getAttributes(); - // 1 ns decl: - assertEquals(1, attrs.getLength()); - - child = child.getNextSibling(); - assertNotNull(child); - assertEquals(Node.ELEMENT_NODE, child.getNodeType()); - elem = (Element) child; - assertEquals("leaf2", elem.getLocalName()); - attrs = elem.getAttributes(); - /* At least 1 attribute, 1 ns decl; but depending on - * how writer chooses to do it, may be 2 ns decls. So... - */ - int count = attrs.getLength(); - if (count < 2 || count > 3) { - fail("Expected 2 or 3 attributes (including namespace declarations), got "+count); - } - assertEquals("", elem.getAttributeNS(URI2, "attr2")); - } - - public void testTypedOutputInt() - throws Exception - { - Document doc = createDomDoc(false); - // let's use namespace-aware just because some impls might not support non-ns - XMLOutputFactory of = getFactory(TYPE_NS); - TypedXMLStreamWriter sw = (TypedXMLStreamWriter) of.createXMLStreamWriter(new DOMResult(doc)); - - sw.writeStartDocument(); - sw.writeStartElement("root"); - sw.writeIntAttribute(null, null, "attr", -900); - sw.writeInt(123); - sw.writeEndElement(); - sw.writeEndDocument(); - sw.close(); - - Element root = doc.getDocumentElement(); - - assertNotNull(root); - assertEquals("root", root.getTagName()); - NamedNodeMap attrs = root.getAttributes(); - assertEquals(1, attrs.getLength()); - assertEquals("-900", root.getAttribute("attr")); - - Node child = root.getFirstChild(); - assertNotNull(child); - assertEquals(Node.TEXT_NODE, child.getNodeType()); - assertEquals("123", child.getNodeValue()); - } - - /* - /////////////////////////////////////////////////////////// - // Helper methods - /////////////////////////////////////////////////////////// - */ - - private Document createDomDoc(boolean nsAware) - throws Exception - { - DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); - dbf.setNamespaceAware(nsAware); - return dbf.newDocumentBuilder().newDocument(); - } - - private XMLOutputFactory getFactory(int type) - throws Exception - { - XMLOutputFactory f = getOutputFactory(); - // type 0 -> non-ns, 1 -> ns, non-repairing, 2 -> ns, repairing - boolean ns = (type > 0); - /* 23-Dec-2008, TSa: Not all Stax2 impls support non-namespace-aware - * modes: need to first ensure one tested does... - */ - if (!setNamespaceAware(f, ns) && !ns) { - return null; - } - setRepairing(f, type > 1); - return f; - } -} diff -Nru libwoodstox-java-4.1.3/src/test/stax2/dom/TestFragments.java libwoodstox-java-5.1.0/src/test/stax2/dom/TestFragments.java --- libwoodstox-java-4.1.3/src/test/stax2/dom/TestFragments.java 2012-04-24 04:38:21.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/stax2/dom/TestFragments.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,49 +0,0 @@ -package stax2.dom; - -import javax.xml.parsers.DocumentBuilderFactory; -import javax.xml.stream.*; -import javax.xml.transform.dom.DOMResult; -import javax.xml.transform.dom.DOMSource; - -import org.w3c.dom.DocumentFragment; - -import stax2.BaseStax2Test; - -public class TestFragments extends BaseStax2Test -{ - // [WSTX-257] - public void testFragmentIssue257() throws Exception - { - DocumentFragment fragment = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument().createDocumentFragment(); - XMLStreamWriter xmlWriter = getOutputFactory().createXMLStreamWriter(new DOMResult(fragment)); - // create equivalent of "value1value2" - xmlWriter.writeStartElement("a"); - xmlWriter.writeCharacters("value1"); - xmlWriter.writeEndElement(); - xmlWriter.writeStartElement("b"); - xmlWriter.writeCharacters("value2"); - xmlWriter.writeEndElement(); - xmlWriter.close(); - - XMLStreamReader sr = getInputFactory().createXMLStreamReader(new DOMSource(fragment)); - assertTokenType(START_DOCUMENT, sr.getEventType()); - - assertTokenType(START_ELEMENT, sr.next()); - assertEquals("a", sr.getLocalName()); - assertTokenType(CHARACTERS, sr.next()); - assertEquals("value1", sr.getText()); - assertTokenType(END_ELEMENT, sr.next()); - assertEquals("a", sr.getLocalName()); - - assertTokenType(START_ELEMENT, sr.next()); - assertEquals("b", sr.getLocalName()); - assertTokenType(CHARACTERS, sr.next()); - assertEquals("value2", sr.getText()); - assertTokenType(END_ELEMENT, sr.next()); - assertEquals("b", sr.getLocalName()); - - assertTokenType(END_DOCUMENT, sr.next()); - assertFalse(sr.hasNext()); - } - -} diff -Nru libwoodstox-java-4.1.3/src/test/stax2/dtd/TestDefaultAttrs.java libwoodstox-java-5.1.0/src/test/stax2/dtd/TestDefaultAttrs.java --- libwoodstox-java-4.1.3/src/test/stax2/dtd/TestDefaultAttrs.java 2012-04-24 04:38:21.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/stax2/dtd/TestDefaultAttrs.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,59 +0,0 @@ -package stax2.dtd; - -import javax.xml.stream.XMLStreamException; - -import org.codehaus.stax2.*; - -import stax2.BaseStax2Test; - -/** - * Test class that checks whether namespace declarations gained via - * attribute defaulting work. - */ -public class TestDefaultAttrs - extends BaseStax2Test -{ - public void testValidNsFromDefaultAttrs() - throws XMLStreamException - { - final String XML = - "\n" - +"\n" - +"\n" - +"\n" - +"]>" - ; - - XMLStreamReader2 sr = getReader(XML, true); - assertTokenType(DTD, sr.next()); - assertTokenType(START_ELEMENT, sr.next()); - assertEquals("node", sr.getLocalName()); - assertEquals(3, sr.getAttributeCount()); - assertEquals("xyz", sr.getAttributeValue("", "attr1")); - assertEquals("xyz", sr.getAttributeValue(null, "attr1")); - assertEquals("123", sr.getAttributeValue("", "attr3")); - assertEquals("123", sr.getAttributeValue(null, "attr3")); - assertEquals("abc", sr.getAttributeValue("", "attr2")); - assertEquals("abc", sr.getAttributeValue(null, "attr2")); - - // and non existing... - assertNull(sr.getAttributeValue("http://foo", "attr1")); - } - - /* - //////////////////////////////////////// - // Private methods - //////////////////////////////////////// - */ - - private XMLStreamReader2 getReader(String contents, boolean nsAware) - throws XMLStreamException - { - XMLInputFactory2 f = getInputFactory(); - setNamespaceAware(f, nsAware); - setSupportDTD(f, true); - setValidating(f, true); - return constructStreamReader(f, contents); - } -} diff -Nru libwoodstox-java-4.1.3/src/test/stax2/dtd/TestDTDInfo.java libwoodstox-java-5.1.0/src/test/stax2/dtd/TestDTDInfo.java --- libwoodstox-java-4.1.3/src/test/stax2/dtd/TestDTDInfo.java 2012-04-24 04:38:21.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/stax2/dtd/TestDTDInfo.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,68 +0,0 @@ -package stax2.dtd; - -import javax.xml.stream.*; - -import org.codehaus.stax2.*; -import org.codehaus.stax2.validation.DTDValidationSchema; - -import stax2.BaseStax2Test; - -/** - * Set of unit tests that checks that the {@link AttributeInfo} implementation - * works as expected. - */ -public class TestDTDInfo - extends BaseStax2Test -{ - final static String TEST_DOC = - "" - +"\n" - +"\n" // param entity - +"\n" // general internal parsed entity - +"\n" // gen. ext. parsed entity - +"\n" - +"\n" - +"\n" // gen. ext. unparsed - +"]>" - +"" - ; - - public void testDTDInfo() - throws XMLStreamException - { - XMLStreamReader2 sr = getReader(TEST_DOC); - - assertTokenType(DTD, sr.next()); - - DTDInfo info = sr.getDTDInfo(); - assertNotNull(info); - DTDValidationSchema dtd = info.getProcessedDTDSchema(); - assertNotNull(dtd); - - // 4 entities, but one is parameter entity... - assertEquals(3, dtd.getEntityCount()); - - // 2 notations: - assertEquals(2, dtd.getNotationCount()); - - // Also, don't want a creepy exception afterwards... - assertTokenType(START_ELEMENT, sr.next()); - } - - /* - //////////////////////////////////////// - // Private methods - //////////////////////////////////////// - */ - - private XMLStreamReader2 getReader(String contents) - throws XMLStreamException - { - XMLInputFactory f = getInputFactory(); - // Need dtd support, may need validation... - setSupportDTD(f, true); - setValidating(f, true); - return (XMLStreamReader2) constructStreamReader(f, contents); - } -} diff -Nru libwoodstox-java-4.1.3/src/test/stax2/dtd/TestExternalDTD.java libwoodstox-java-5.1.0/src/test/stax2/dtd/TestExternalDTD.java --- libwoodstox-java-4.1.3/src/test/stax2/dtd/TestExternalDTD.java 2012-04-24 04:38:21.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/stax2/dtd/TestExternalDTD.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,259 +0,0 @@ -package stax2.dtd; - -import java.io.*; -import java.net.URL; - -import javax.xml.stream.*; -import javax.xml.transform.stream.StreamSource; - -import org.codehaus.stax2.*; - -import stax2.BaseStax2Test; - -/** - * Unit tests that verify that external DTD subsets are properly - * referenced and accessed when using various input factory methods - * that give enough information to reference relative paths (or explicitly - * pass the whole path) - */ -public class TestExternalDTD - extends BaseStax2Test -{ - final String EXTERNAL_FILENAME1 = "external1.xml"; - final String EXTERNAL_FILENAME2 = "external2.xml"; - - final static String DTD1 = "external.dtd"; - - final String EXTERNAL_XML1 = - "" - +"&simpleEntity;" - ; - - final String EXTERNAL_XML2 = - "" - +"&simpleEntity;" - ; - - final String SIMPLE_EXT_ENTITY_TEXT = "simple textual content"; - - /** - * This tests the basic dereferencing when giving an input stream - * and system id (to use for figuring out the base); basic Stax 1.0 - * feature - */ - public void testStreamWithSystemId() - throws IOException, XMLStreamException - { - for (int i = 0; i < 2; ++i) { - String filename = (i == 0) ? EXTERNAL_FILENAME1 : EXTERNAL_FILENAME2; - String sysId = constructSystemId(resolveFile(filename)); - String XML = (i == 0) ? EXTERNAL_XML1 : EXTERNAL_XML2; - XMLInputFactory2 f = getFactory(); - XMLStreamReader sr; - try { - sr = f.createXMLStreamReader(sysId, utf8StreamFromString(XML)); - } catch (XMLStreamException xse) { - fail("Failed to construct a SystemID-based stream reader: "+xse); - return; // never gets here - } - try { - assertTokenType(DTD, sr.next()); - assertTokenType(START_ELEMENT, sr.next()); - assertTokenType(CHARACTERS, sr.next()); - assertEquals(SIMPLE_EXT_ENTITY_TEXT, getAndVerifyText(sr)); - assertTokenType(END_ELEMENT, sr.next()); - } catch (XMLStreamException xse) { - fail("Failed to process content using SystemID-based stream reader: "+xse); - } - } - } - - /** - * This tests the basic dereferencing when giving a Reader - * and system id (to use for figuring out the base); basic Stax 1.0 - * feature - */ - public void testReaderWithSystemId() - throws IOException, XMLStreamException - { - for (int i = 0; i < 2; ++i) { - String filename = (i == 0) ? EXTERNAL_FILENAME1 : EXTERNAL_FILENAME2; - String sysId = constructSystemId(resolveFile(filename)); - String XML = (i == 0) ? EXTERNAL_XML1 : EXTERNAL_XML2; - XMLInputFactory2 f = getFactory(); - XMLStreamReader sr; - try { - sr = f.createXMLStreamReader(sysId, new StringReader(XML)); - } catch (XMLStreamException xse) { - fail("Failed to construct a SystemID-based String reader: "+xse); - return; // never gets here - } - try { - assertTokenType(DTD, sr.next()); - assertTokenType(START_ELEMENT, sr.next()); - assertTokenType(CHARACTERS, sr.next()); - assertEquals(SIMPLE_EXT_ENTITY_TEXT, getAndVerifyText(sr)); - assertTokenType(END_ELEMENT, sr.next()); - } catch (XMLStreamException xse) { - fail("Failed to process content using SystemID-based String reader: "+xse); - } - } - } - - /** - * This tests the basic dereferencing when giving an stream source - * with both system id and input source; Stax 1.0 feature. - */ - public void testStreamWithStreamSource() - throws IOException, XMLStreamException - { - // First, using input source + sys id: - for (int i = 0; i < 2; ++i) { - String filename = (i == 0) ? EXTERNAL_FILENAME1 : EXTERNAL_FILENAME2; - String sysId = constructSystemId(resolveFile(filename)); - String XML = (i == 0) ? EXTERNAL_XML1 : EXTERNAL_XML2; - StreamSource src = new StreamSource(utf8StreamFromString(XML), sysId); - XMLInputFactory2 f = getFactory(); - XMLStreamReader sr; - try { - sr = f.createXMLStreamReader(src); - } catch (XMLStreamException xse) { - fail("Failed to construct a StreamSource-based stream reader: "+xse); - return; // never gets here - } - try { - assertTokenType(DTD, sr.next()); - assertTokenType(START_ELEMENT, sr.next()); - assertTokenType(CHARACTERS, sr.next()); - assertEquals(SIMPLE_EXT_ENTITY_TEXT, getAndVerifyText(sr)); - assertTokenType(END_ELEMENT, sr.next()); - } catch (XMLStreamException xse) { - fail("Failed to process content using StreamSource-based stream reader: "+xse); - } - } - - // Then just passing File: - for (int i = 0; i < 2; ++i) { - String filename = (i == 0) ? EXTERNAL_FILENAME1 : EXTERNAL_FILENAME2; - File file = resolveFile(filename); - StreamSource src = new StreamSource(file); - XMLInputFactory2 f = getFactory(); - XMLStreamReader sr; - try { - sr = f.createXMLStreamReader(src); - } catch (XMLStreamException xse) { - fail("Failed to construct a StreamSource/file-based stream reader: "+xse); - return; // never gets here - } - try { - assertTokenType(DTD, sr.next()); - assertTokenType(START_ELEMENT, sr.next()); - assertTokenType(CHARACTERS, sr.next()); - assertEquals(SIMPLE_EXT_ENTITY_TEXT, getAndVerifyText(sr)); - assertTokenType(END_ELEMENT, sr.next()); - } catch (XMLStreamException xse) { - fail("Failed to process content using StreamSource/file-based stream reader: "+xse); - } - } - } - - /** - * Deref'ing with Stax2 factory method that takes a {@link java.net.URL}. - */ - public void testURL() - throws IOException, XMLStreamException - { - for (int i = 0; i < 2; ++i) { - String filename = (i == 0) ? EXTERNAL_FILENAME1 : EXTERNAL_FILENAME2; - URL src = resolveFile(filename).toURL(); - XMLInputFactory2 f = getFactory(); - XMLStreamReader sr; - - try { - sr = f.createXMLStreamReader(src); - } catch (XMLStreamException xse) { - fail("Failed to construct an URL-based stream reader: "+xse); - return; // never gets here - } - assertTokenType(DTD, sr.next()); - assertTokenType(START_ELEMENT, sr.next()); - assertTokenType(CHARACTERS, sr.next()); - assertEquals(SIMPLE_EXT_ENTITY_TEXT, getAndVerifyText(sr)); - assertTokenType(END_ELEMENT, sr.next()); - } - } - - /** - * Deref'ing with Stax2 factory method that takes a {@link java.io.File} - */ - public void testFile() - throws IOException, XMLStreamException - { - for (int i = 0; i < 2; ++i) { - String filename = (i == 0) ? EXTERNAL_FILENAME1 : EXTERNAL_FILENAME2; - File file = resolveFile(filename); - XMLInputFactory2 f = getFactory(); - XMLStreamReader sr; - try { - sr = f.createXMLStreamReader(file); - } catch (XMLStreamException xse) { - fail("Failed to construct a file-based stream reader: "+xse); - return; // never gets here - } - assertTokenType(DTD, sr.next()); - assertTokenType(START_ELEMENT, sr.next()); - assertTokenType(CHARACTERS, sr.next()); - assertEquals(SIMPLE_EXT_ENTITY_TEXT, getAndVerifyText(sr)); - assertTokenType(END_ELEMENT, sr.next()); - } - } - - /* - //////////////////////////////////////// - // Private methods - //////////////////////////////////////// - */ - - private XMLInputFactory2 getFactory() - throws XMLStreamException - { - // Let's prevent DTD caching... - XMLInputFactory2 f = getNewInputFactory(); - // Need to support all entities - setReplaceEntities(f, true); - setSupportExternalEntities(f, true); - // Need dtd support but not validation - setSupportDTD(f, true); - setValidating(f, false); - // And to make test robust, coalescing - setCoalescing(f, true); - return f; - } - - /** - * Could/should make this more robust (refer as a resource via - * class loader or such), but for now this should work: - */ - private File resolveFile(String relName) - throws IOException - { - File f = new File("src"); - f = new File(f, "test"); - f = new File(f, "stax2"); - f = new File(f, "stream"); - f = new File(f, relName); - return f.getAbsoluteFile(); - } - - private String constructSystemId(File f) - { - return f.getAbsolutePath(); - } - - private InputStream utf8StreamFromString(String str) - throws java.io.UnsupportedEncodingException - { - byte[] bytes = str.getBytes("UTF-8"); - return new ByteArrayInputStream(bytes); - } -} diff -Nru libwoodstox-java-4.1.3/src/test/stax2/dtd/TestNonValidatingDtdAware.java libwoodstox-java-5.1.0/src/test/stax2/dtd/TestNonValidatingDtdAware.java --- libwoodstox-java-4.1.3/src/test/stax2/dtd/TestNonValidatingDtdAware.java 2012-04-24 04:38:21.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/stax2/dtd/TestNonValidatingDtdAware.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,136 +0,0 @@ -package stax2.dtd; - -import javax.xml.stream.XMLStreamException; - -import org.codehaus.stax2.*; - -import stax2.BaseStax2Test; - -public class TestNonValidatingDtdAware - extends BaseStax2Test -{ - public void testSpaceNs() - throws XMLStreamException - { - doTestWS(true, false); - doTestWS(true, true); - } - - public void testSpaceNonNs() - throws XMLStreamException - { - doTestWS(false, false); - doTestWS(false, true); - } - - public void testFalseSpace() - throws XMLStreamException - { - doTestFalseWS(true, false); - doTestFalseWS(true, true); - doTestFalseWS(false, false); - doTestFalseWS(false, true); - } - - /* - //////////////////////////////////////// - // Private methods, shared test code - //////////////////////////////////////// - */ - - public void doTestWS(boolean ns, boolean coalesce) - throws XMLStreamException - { - final String XML = "\n" - +"\n" - +"]>" - +"\n" - +" \n" - +""; - XMLStreamReader2 sr = getReader(XML, ns, coalesce); - - assertTokenType(START_DOCUMENT, sr.getEventType()); - assertTokenType(DTD, sr.next()); - - assertTokenType(START_ELEMENT, sr.next()); - assertEquals("root", sr.getLocalName()); - - assertTokenType(SPACE, sr.next()); - assertEquals("\n ", getAndVerifyText(sr)); - - assertTokenType(START_ELEMENT, sr.next()); - assertEquals("leaf", sr.getLocalName()); - assertTokenType(END_ELEMENT, sr.next()); - assertEquals("leaf", sr.getLocalName()); - - assertTokenType(SPACE, sr.next()); - assertEquals("\n", getAndVerifyText(sr)); - - assertTokenType(END_ELEMENT, sr.next()); - assertEquals("root", sr.getLocalName()); - - assertTokenType(END_DOCUMENT, sr.next()); - } - - public void doTestFalseWS(boolean ns, boolean coalesce) - throws XMLStreamException - { - final String XML = "\n" - +"\n" - +"]>" - +"\n" - +" Foobar" - +""; - XMLStreamReader2 sr = getReader(XML, ns, coalesce); - - assertTokenType(START_DOCUMENT, sr.getEventType()); - assertTokenType(DTD, sr.next()); - - assertTokenType(START_ELEMENT, sr.next()); - assertEquals("root", sr.getLocalName()); - - /* not 100% if this is expected in coalescing mode too, - * but it is the way it's implemented, and kind of makes - * sense even though there are alternatives - */ - assertTokenType(SPACE, sr.next()); - assertEquals("\n ", getAndVerifyText(sr)); - assertTokenType(CHARACTERS, sr.next()); - assertEquals("Foo", getAndVerifyText(sr)); - - assertTokenType(START_ELEMENT, sr.next()); - assertEquals("leaf", sr.getLocalName()); - assertTokenType(END_ELEMENT, sr.next()); - assertEquals("leaf", sr.getLocalName()); - - assertTokenType(CHARACTERS, sr.next()); - assertEquals("bar", getAndVerifyText(sr)); - - assertTokenType(END_ELEMENT, sr.next()); - assertEquals("root", sr.getLocalName()); - - assertTokenType(END_DOCUMENT, sr.next()); - } - - - /* - //////////////////////////////////////// - // Private methods, other - //////////////////////////////////////// - */ - - private XMLStreamReader2 getReader(String contents, boolean nsAware, - boolean coal) - throws XMLStreamException - { - XMLInputFactory2 f = getInputFactory(); - setNamespaceAware(f, nsAware); - setCoalescing(f, coal); - setSupportDTD(f, true); - setValidating(f, false); - return constructStreamReader(f, contents); - } -} - diff -Nru libwoodstox-java-4.1.3/src/test/stax2/dtd/TestNsDefaults.java libwoodstox-java-5.1.0/src/test/stax2/dtd/TestNsDefaults.java --- libwoodstox-java-4.1.3/src/test/stax2/dtd/TestNsDefaults.java 2012-04-24 04:38:21.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/stax2/dtd/TestNsDefaults.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,83 +0,0 @@ -package stax2.dtd; - -import javax.xml.stream.XMLStreamException; - -import org.codehaus.stax2.*; - -import stax2.BaseStax2Test; - -/** - * Test class that checks whether namespace declarations gained via - * attribute defaulting work. - */ -public class TestNsDefaults - extends BaseStax2Test -{ - public void testValidNsFromDefaultAttrs() - throws XMLStreamException - { - final String XML = - "\n" - +"\n" - +"]>" - +"" - ; - - XMLStreamReader2 sr = getReader(XML, true); - assertTokenType(DTD, sr.next()); - assertTokenType(START_ELEMENT, sr.next()); - assertEquals("node", sr.getLocalName()); - assertElemNotInNamespace(sr); - assertNoElemPrefix(sr); - assertEquals(1, sr.getAttributeCount()); - assertEquals(1, sr.getNamespaceCount()); - - assertEquals("ns", sr.getNamespacePrefix(0)); - assertEquals("http://expl", sr.getNamespaceURI(0)); - - assertEquals("attr", sr.getAttributeLocalName(0)); - assertEquals("ns", sr.getAttributePrefix(0)); - assertEquals("http://expl", sr.getAttributeNamespace(0)); - assertEquals("123", sr.getAttributeValue(0)); - - assertTokenType(START_ELEMENT, sr.next()); - assertEquals("node", sr.getLocalName()); - assertElemNotInNamespace(sr); - assertNoElemPrefix(sr); - - assertEquals(1, sr.getAttributeCount()); - assertEquals(1, sr.getNamespaceCount()); - - assertEquals("ns", sr.getNamespacePrefix(0)); - assertEquals("http://default", sr.getNamespaceURI(0)); - - assertEquals("attr", sr.getAttributeLocalName(0)); - assertNoAttrPrefix(sr.getAttributePrefix(0)); - assertNoAttrNamespace(sr.getAttributeNamespace(0)); - assertEquals("456", sr.getAttributeValue(0)); - - assertTokenType(END_ELEMENT, sr.next()); - assertEquals("node", sr.getLocalName()); - - assertTokenType(END_ELEMENT, sr.next()); - assertEquals("node", sr.getLocalName()); - } - - /* - //////////////////////////////////////// - // Private methods - //////////////////////////////////////// - */ - - private XMLStreamReader2 getReader(String contents, boolean nsAware) - throws XMLStreamException - { - XMLInputFactory2 f = getInputFactory(); - setNamespaceAware(f, nsAware); - setCoalescing(f, false); - setSupportDTD(f, true); - setValidating(f, false); - return constructStreamReader(f, contents); - } -} diff -Nru libwoodstox-java-4.1.3/src/test/stax2/dtd/TestReaderWithDTD.java libwoodstox-java-5.1.0/src/test/stax2/dtd/TestReaderWithDTD.java --- libwoodstox-java-4.1.3/src/test/stax2/dtd/TestReaderWithDTD.java 2012-04-24 04:38:21.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/stax2/dtd/TestReaderWithDTD.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,74 +0,0 @@ -package stax2.dtd; - -import javax.xml.stream.XMLStreamException; - -import org.codehaus.stax2.XMLInputFactory2; -import org.codehaus.stax2.XMLStreamReader2; - -import stax2.BaseStax2Test; - -public class TestReaderWithDTD extends BaseStax2Test -{ - public void testGetPrefixedName() throws XMLStreamException - { - doTestGetPrefixedName(false); - doTestGetPrefixedName(true); - } - - /* - /////////////////////////////////////////////////////////////////////// - // Helper methods - /////////////////////////////////////////////////////////////////////// - */ - - public void doTestGetPrefixedName(boolean ns) - throws XMLStreamException - { - final String XML = - "'>\n" - +"]>" - +"" - +"" - +"&intEnt;" - +"" - ; - XMLStreamReader2 sr = getReader(XML, ns); - try { - assertTokenType(DTD, sr.next()); - assertEquals("root", sr.getPrefixedName()); - assertTokenType(START_ELEMENT, sr.next()); - assertEquals("root", sr.getPrefixedName()); - assertTokenType(START_ELEMENT, sr.next()); - assertEquals("xy:elem", sr.getPrefixedName()); - assertTokenType(PROCESSING_INSTRUCTION, sr.next()); - assertEquals("proc", sr.getPrefixedName()); - assertTokenType(START_ELEMENT, sr.next()); - assertEquals("leaf", sr.getPrefixedName()); - assertTokenType(END_ELEMENT, sr.next()); - assertEquals("leaf", sr.getPrefixedName()); - assertTokenType(START_ELEMENT, sr.next()); - assertEquals("another:x", sr.getPrefixedName()); - assertTokenType(END_ELEMENT, sr.next()); - assertEquals("another:x", sr.getPrefixedName()); - assertTokenType(END_ELEMENT, sr.next()); - assertEquals("xy:elem", sr.getPrefixedName()); - assertTokenType(END_ELEMENT, sr.next()); - assertEquals("root", sr.getPrefixedName()); - assertTokenType(END_DOCUMENT, sr.next()); - } catch (XMLStreamException xse) { - fail("Did not expect any problems during parsing, but got: "+xse); - } - } - - private XMLStreamReader2 getReader(String contents, boolean nsAware) - throws XMLStreamException - { - XMLInputFactory2 f = getInputFactory(); - setCoalescing(f, true); - setSupportDTD(f, true); - setNamespaceAware(f, nsAware); - setValidating(f, false); - return constructStreamReader(f, contents); - } -} diff -Nru libwoodstox-java-4.1.3/src/test/stax2/evt/TestDTDEvent.java libwoodstox-java-5.1.0/src/test/stax2/evt/TestDTDEvent.java --- libwoodstox-java-4.1.3/src/test/stax2/evt/TestDTDEvent.java 2012-04-24 04:38:21.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/stax2/evt/TestDTDEvent.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,75 +0,0 @@ -package stax2.evt; - -import java.io.StringWriter; - -import javax.xml.namespace.QName; -import javax.xml.stream.*; -import javax.xml.stream.events.*; - -import org.codehaus.stax2.*; -import org.codehaus.stax2.evt.*; - -import stax2.BaseStax2Test; - -/** - * Set of unit tests that checks that {@link {@link AttributeInfo} - * implementation works as expected. - */ -public class TestDTDEvent - extends BaseStax2Test -{ - public void testDTDCreation() - throws XMLStreamException - { - final String COMMENT = ""; - - XMLOutputFactory f = getOutputFactory(); - StringWriter strw = new StringWriter(); - XMLEventWriter w = f.createXMLEventWriter(strw); - - XMLEventFactory2 evtf = getEventFactory(); - - w.add(evtf.createStartDocument()); - w.add(evtf.createDTD("root", "sysid", "pubid", COMMENT)); - w.add(evtf.createStartElement("", "", "root")); - w.add(evtf.createEndElement("", "", "root")); - w.add(evtf.createEndDocument()); - - w.close(); - - String xmlContent = strw.toString(); - XMLInputFactory f2 = getInputFactory(); - - /* Hmmh. This is bit problematic: we don't want to read an - * external subset... yet it'd be good to test that system - * and public ids are properly parsed. For now, let's see if - * this works: - */ - setSupportDTD(f2, false); - XMLEventReader2 er = (XMLEventReader2) constructEventReader(f2, xmlContent); - - assertTokenType(START_DOCUMENT, er.nextEvent().getEventType()); - XMLEvent evt = er.nextEvent(); - assertTokenType(DTD, evt.getEventType()); - - // Check that all properties are correct: - DTD2 dtd = (DTD2) evt; - assertEquals("root", dtd.getRootName()); - assertEquals("pubid", dtd.getPublicId()); - assertEquals("sysid", dtd.getSystemId()); - String intss = dtd.getInternalSubset().trim(); - assertEquals(COMMENT, intss); - - evt = er.nextEvent(); - assertTokenType(START_ELEMENT, evt.getEventType()); - StartElement start = evt.asStartElement(); - QName name = start.getName(); - assertEquals("root", name.getLocalPart()); - - // just to test hasNextEvent()... - assertTrue(er.hasNextEvent()); - - assertTokenType(END_ELEMENT, er.nextEvent().getEventType()); - assertTokenType(END_DOCUMENT, er.nextEvent().getEventType()); - } -} diff -Nru libwoodstox-java-4.1.3/src/test/stax2/evt/TestEventEquality.java libwoodstox-java-5.1.0/src/test/stax2/evt/TestEventEquality.java --- libwoodstox-java-4.1.3/src/test/stax2/evt/TestEventEquality.java 2012-04-24 04:38:21.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/stax2/evt/TestEventEquality.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,44 +0,0 @@ -package stax2.evt; - -import javax.xml.stream.*; -import javax.xml.stream.events.XMLEvent; - -import stax2.BaseStax2Test; - -/** - * As of Stax2 v3 (~= Woodstox 4.0), XMLEvent instances are expected - * to implement simple equality comparison. Stax2 reference implementation - * implements this for all event types. This test suite verifies that - * equality checks work for simple cases. - */ -public class TestEventEquality - extends BaseStax2Test -{ - public void testSimple() - throws XMLStreamException - { - XMLInputFactory f = getInputFactory(); - setNamespaceAware(f, true); - String XML = - "Text..." - +"\r\n" - +"\n" - +"" - ; - - XMLEventReader er1 = constructEventReader(f, XML); - XMLEventReader er2 = constructEventReader(f, XML); - - while (er1.hasNext()) { - XMLEvent e1 = er1.nextEvent(); - XMLEvent e2 = er2.nextEvent(); - - if (!e1.equals(e2) || !e2.equals(e1)) { - fail("Event 1 (type "+e1.getEventType()+") differs from Event2 (type "+e2.getEventType()+"), location "+e1.getLocation()); - } - if (e1.hashCode() != e2.hashCode()) { - fail("Hash codes differ for events (type: "+e2.getEventType()+"), location "+e1.getLocation()); - } - } - } -} diff -Nru libwoodstox-java-4.1.3/src/test/stax2/evt/TestEventTypes.java libwoodstox-java-5.1.0/src/test/stax2/evt/TestEventTypes.java --- libwoodstox-java-4.1.3/src/test/stax2/evt/TestEventTypes.java 2012-04-24 04:38:21.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/stax2/evt/TestEventTypes.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,58 +0,0 @@ -package stax2.evt; - -import java.io.*; - -import javax.xml.stream.*; - -import org.codehaus.stax2.*; -import org.codehaus.stax2.evt.*; - -import stax2.BaseStax2Test; - -/** - * Set of unit tests that checks that new Stax2 features work (generically) - * for event instances. - */ -public class TestEventTypes - extends BaseStax2Test -{ - /** - * This unit test does some crude checking to ensure that the usual - * events can be output to the specified writer. Events are here - * constructed using event factory. - */ - public void testEventObjectOutput() - throws XMLStreamException - { - XMLEventFactory2 evtf = getEventFactory(); - XMLOutputFactory2 f = getOutputFactory(); - StringWriter strw = new StringWriter(); - XMLStreamWriter2 sw = (XMLStreamWriter2) f.createXMLStreamWriter(strw, "UTF-8"); - - XMLEvent2 evt = (XMLEvent2) evtf.createStartDocument(); - evt.writeUsing(sw); - - // Let's output root element with no attrs - ((XMLEvent2) evtf.createStartElement("", "", "root")).writeUsing(sw); - ((XMLEvent2) evtf.createEndElement("", "", "root")).writeUsing(sw); - - ((XMLEvent2) evtf.createEndDocument()).writeUsing(sw); - - sw.close(); - - // Ok, parsing: - XMLInputFactory f2 = getInputFactory(); - XMLStreamReader sr = f2.createXMLStreamReader(new StringReader(strw.toString())); - assertTokenType(START_DOCUMENT, sr.getEventType()); - assertTokenType(START_ELEMENT, sr.next()); - assertTokenType(END_ELEMENT, sr.next()); - assertTokenType(END_DOCUMENT, sr.next()); - sr.close(); - } - - /* - //////////////////////////////////////// - // Non-test methods - //////////////////////////////////////// - */ -} diff -Nru libwoodstox-java-4.1.3/src/test/stax2/evt/TestStartElementEvent.java libwoodstox-java-5.1.0/src/test/stax2/evt/TestStartElementEvent.java --- libwoodstox-java-4.1.3/src/test/stax2/evt/TestStartElementEvent.java 2012-04-24 04:38:21.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/stax2/evt/TestStartElementEvent.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,106 +0,0 @@ -package stax2.evt; - -import java.io.*; -import java.util.*; - -import javax.xml.namespace.QName; -import javax.xml.stream.*; -import javax.xml.stream.events.*; - -import stax2.BaseStax2Test; - -/** - * Set of unit tests that checks that {@link {@link StartElement} - * implementation works as expected. - */ -public class TestStartElementEvent - extends BaseStax2Test -{ - /** - * This test was inspired by Woodstox bug [WSTX-188]... - */ - public void testStartEventAttrs() - throws XMLStreamException - { - final String DOC = "" - +"some content" - +"some content" - +""; - XMLInputFactory f = getNewInputFactory(); - XMLEventReader er = f.createXMLEventReader(new StringReader(DOC)); - - ArrayList/**/ elemEvents = new ArrayList/**/(); - - assertTokenType(START_DOCUMENT, er.nextEvent()); - XMLEvent evt = er.nextEvent(); - assertTokenType(START_ELEMENT, evt); - elemEvents.add(evt.asStartElement()); - evt = er.nextEvent(); - assertTokenType(START_ELEMENT, evt); - elemEvents.add(evt.asStartElement()); - - assertTokenType(CHARACTERS, er.nextEvent()); - assertTokenType(END_ELEMENT, er.nextEvent()); - evt = er.nextEvent(); - assertTokenType(START_ELEMENT, evt); - elemEvents.add(evt.asStartElement()); - - assertTokenType(CHARACTERS, er.nextEvent()); - assertTokenType(END_ELEMENT, er.nextEvent()); - assertTokenType(END_ELEMENT, er.nextEvent()); - er.close(); - - /* Ok, got 3 start elements, and accessing the SECOND one triggers - * the problem - */ - _verifyAttrCount((StartElement) elemEvents.get(1), 4, true); - } - - /* - ///////////////////////////////////////////////// - // Helper methods - ///////////////////////////////////////////////// - */ - - private void _verifyAttrCount(StartElement start, int expCount, boolean hasProb) - { - // First things first: do we have the 'problem' attribute? - Attribute probAttr = start.getAttributeByName(new QName("problem")); - if (hasProb) { - assertNotNull(probAttr); - } else { - assertNull(probAttr); - } - - Iterator it = start.getAttributes(); - int count = 0; - Map/**/ attrs = new HashMap/**/(); - - // First, collect the attributes - while (it.hasNext()) { - ++count; - Attribute attr = (Attribute) it.next(); - attrs.put(attr.getName(), attr.getValue()); - } - - assertEquals(expCount, attrs.size()); - - // Then verify we can access them ok - //for (Map.Entry en : attrs) { - - Iterator it2 = attrs.entrySet().iterator(); - while (it2.hasNext()) { - Map.Entry en = (Map.Entry) it2.next(); - QName key = (QName) en.getKey(); - String value = (String) en.getValue(); - - // should find it via StartElement too - Attribute attr = start.getAttributeByName(key); - assertNotNull(attr); - assertEquals(value, attr.getValue()); - - // .. how about a bogus name? - assertNull(start.getAttributeByName(new QName("bogus+"+key.getLocalPart()))); - } - } -} diff -Nru libwoodstox-java-4.1.3/src/test/stax2/stream/entity-from-ext.xml libwoodstox-java-5.1.0/src/test/stax2/stream/entity-from-ext.xml --- libwoodstox-java-4.1.3/src/test/stax2/stream/entity-from-ext.xml 2012-04-24 04:38:21.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/stax2/stream/entity-from-ext.xml 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ - - - diff -Nru libwoodstox-java-4.1.3/src/test/stax2/stream/external1.xml libwoodstox-java-5.1.0/src/test/stax2/stream/external1.xml --- libwoodstox-java-4.1.3/src/test/stax2/stream/external1.xml 2012-04-24 04:38:21.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/stax2/stream/external1.xml 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -&simpleEntity; \ No newline at end of file diff -Nru libwoodstox-java-4.1.3/src/test/stax2/stream/external2.xml libwoodstox-java-5.1.0/src/test/stax2/stream/external2.xml --- libwoodstox-java-4.1.3/src/test/stax2/stream/external2.xml 2012-04-24 04:38:21.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/stax2/stream/external2.xml 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -&simpleEntity; \ No newline at end of file diff -Nru libwoodstox-java-4.1.3/src/test/stax2/stream/external.dtd libwoodstox-java-5.1.0/src/test/stax2/stream/external.dtd --- libwoodstox-java-4.1.3/src/test/stax2/stream/external.dtd 2012-04-24 04:38:21.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/stax2/stream/external.dtd 1970-01-01 00:00:00.000000000 +0000 @@ -1,11 +0,0 @@ - - - - - - - - - - - diff -Nru libwoodstox-java-4.1.3/src/test/stax2/stream/TestAttrBasic.java libwoodstox-java-5.1.0/src/test/stax2/stream/TestAttrBasic.java --- libwoodstox-java-4.1.3/src/test/stax2/stream/TestAttrBasic.java 2012-04-24 04:38:21.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/stax2/stream/TestAttrBasic.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,31 +0,0 @@ -package stax2.stream; - -import javax.xml.stream.*; - -import stax2.BaseStax2Test; - -public class TestAttrBasic - extends BaseStax2Test -{ - public void testNormalization() - throws XMLStreamException - { - String[] LFs = new String[] { "\n", "\r", "\r\n" }; - for (int i = 0; i < LFs.length; ++i) { - XMLStreamReader sr = constructNsStreamReader("", true); - assertTokenType(START_DOCUMENT, sr.getEventType()); - assertTokenType(START_ELEMENT, sr.next()); - assertEquals(1, sr.getAttributeCount()); - // line feeds to be normalized into space - assertEquals(" ", sr.getAttributeValue(0)); - assertTokenType(END_ELEMENT, sr.next()); - assertTokenType(END_DOCUMENT, sr.next()); - } - - XMLStreamReader sr = constructNsStreamReader("", true); - assertTokenType(START_ELEMENT, sr.next()); - assertEquals(1, sr.getAttributeCount()); - // entity as is, \n as space - assertEquals("\r ", sr.getAttributeValue(0)); - } -} diff -Nru libwoodstox-java-4.1.3/src/test/stax2/stream/TestAttrInfo.java libwoodstox-java-5.1.0/src/test/stax2/stream/TestAttrInfo.java --- libwoodstox-java-4.1.3/src/test/stax2/stream/TestAttrInfo.java 2012-04-24 04:38:21.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/stax2/stream/TestAttrInfo.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,233 +0,0 @@ -package stax2.stream; - -import javax.xml.stream.*; - -import org.codehaus.stax2.*; - -import stax2.BaseStax2Test; - -/** - * Set of unit tests that checks that the {@link AttributeInfo} implementation - * works as expected. - * - * @author Tatu Saloranta - */ -public class TestAttrInfo - extends BaseStax2Test -{ - final static String DEFAULT_VALUE = "default value"; - - final static String TEST_DOC_BASIC = - "" - +"" - +""; - - final static String TEST_DOC_DTD = - "" - +"\n" - +"\n" - +"\n" - +"\n" - +"\n" - +"\n" - +"\n" - +"\n" - +"\n" - +"\n" - +"\n" - +"]>" - +"" - +""; - - /** - * Baseline test case that does not use any information originating - * from DTDs. - */ - public void testAttrFindBasic() - throws XMLStreamException - { - XMLStreamReader2 sr = getAttrReader(TEST_DOC_BASIC); - - // Let's verify basic facts... - assertEquals(4, sr.getAttributeCount()); - - AttributeInfo info = sr.getAttributeInfo(); - assertNotNull(info); - - // And then see if we can find the attributes - { - int ix = info.findAttributeIndex(null, "textAttr"); - if (ix < 0) { - fail("Failed to find index of attribute 'textAttr'"); - } - assertEquals("value", sr.getAttributeValue(ix)); - - ix = info.findAttributeIndex(null, "textAttr2"); - if (ix >= 0) { - fail("Found a phantom index for (missing) attribute 'textAttr2'"); - } - - ix = info.findAttributeIndex(null, "textAttr3"); - if (ix < 0) { - fail("Failed to find index of attribute 'textAttr3'"); - } - assertEquals("1", sr.getAttributeValue(ix)); - } - - // Notation attr? - { - int ix = info.findAttributeIndex(null, "notation"); - if (ix < 0) { - fail("Failed to find index of attribute 'notation'"); - } - assertEquals("not2", sr.getAttributeValue(ix)); - // No DTD info available, should NOT find via this: - - int notIx = info.getNotationAttributeIndex(); - if (notIx >= 0) { - fail("Found a bogus notation attribute index ("+notIx+")"); - } - } - - // Ok, how about the id attr? - { - int ix = info.findAttributeIndex(null, "idAttr"); - if (ix < 0) { - fail("Failed to find index of attribute 'id'"); - } - assertEquals("idValue", sr.getAttributeValue(ix)); - - // .. but not by type, as that depends on DTD or Xml:id - } - - // Ok; but how about of non-existing ones? - assertEquals(-1, info.findAttributeIndex(null, "foo")); - assertEquals(-1, info.findAttributeIndex("http://foo", "id")); - - // and then the other (empty) element: - assertTokenType(START_ELEMENT, sr.next()); - assertEquals(0, sr.getAttributeCount()); - assertEquals(-1, info.findAttributeIndex(null, "dummyAttr")); - - finishAttrReader(sr); - } - - /** - * More complex test case, in which information from DTD - * (like attribute default values, notations) are needed. - */ - public void testAttrFindDTD() - throws XMLStreamException - { - XMLStreamReader2 sr = getAttrReader(TEST_DOC_DTD); - - // Let's verify basic facts... - assertEquals(5, sr.getAttributeCount()); - - AttributeInfo info = sr.getAttributeInfo(); - assertNotNull(info); - - // And then see if we can find the attributes - { - int ix = info.findAttributeIndex(null, "textAttr"); - if (ix < 0) { - fail("Failed to find index of attribute 'textAttr'"); - } - assertEquals("value", sr.getAttributeValue(ix)); - - ix = info.findAttributeIndex(null, "textAttr2"); - if (ix >= 0) { - fail("Found a phantom index for (missing) attribute 'textAttr2'"); - } - - ix = info.findAttributeIndex(null, "textAttr3"); - if (ix < 0) { - fail("Failed to find index of attribute 'textAttr3'"); - } - assertEquals("1", sr.getAttributeValue(ix)); - } - - // Notation attr? - { - int ix = info.findAttributeIndex(null, "notation"); - if (ix < 0) { - fail("Failed to find index of attribute 'notation'"); - } - int notIx = info.getNotationAttributeIndex(); - if (notIx < 0) { - fail("Failed to find index of the notation attribute"); - } - assertEquals(ix, notIx); - assertEquals("not2", sr.getAttributeValue(notIx)); - } - - // Ok, how about the id attr? - { - int ix = info.findAttributeIndex(null, "idAttr"); - if (ix < 0) { - fail("Failed to find index of attribute 'id'"); - } - int idIx = info.getIdAttributeIndex(); - if (idIx < 0) { - fail("Failed to find index of the id attribute"); - } - assertEquals(ix, idIx); - assertEquals("idValue", sr.getAttributeValue(idIx)); - } - - // Ok; but how about of non-existing ones? - assertEquals(-1, info.findAttributeIndex(null, "foo")); - assertEquals(-1, info.findAttributeIndex("http://foo", "id")); - - // and then the other (empty) element: - assertTokenType(START_ELEMENT, sr.next()); - assertEquals(0, sr.getAttributeCount()); - assertEquals(-1, info.findAttributeIndex(null, "dummyAttr")); - - finishAttrReader(sr); - } - - /* - //////////////////////////////////////// - // Private methods - //////////////////////////////////////// - */ - - private XMLStreamReader2 getAttrReader(String str) - throws XMLStreamException - { - XMLStreamReader2 sr = getReader(str); - assertTokenType(START_DOCUMENT, sr.getEventType()); - int type = sr.next(); - if (type == DTD) { - type = sr.next(); - } - assertTokenType(START_ELEMENT, type); - return sr; - } - - private void finishAttrReader(XMLStreamReader sr) - throws XMLStreamException - { - while (sr.getEventType() != END_DOCUMENT) { - sr.next(); - } - } - - private XMLStreamReader2 getReader(String contents) - throws XMLStreamException - { - XMLInputFactory f = getInputFactory(); - setCoalescing(f, false); // shouldn't really matter - setNamespaceAware(f, true); - setSupportDTD(f, true); - /* Probably need to enable validation, to get all the attribute - * type info processed and accessible? - */ - setValidating(f, true); - return (XMLStreamReader2) constructStreamReader(f, contents); - } -} diff -Nru libwoodstox-java-4.1.3/src/test/stax2/stream/TestClosing.java libwoodstox-java-5.1.0/src/test/stax2/stream/TestClosing.java --- libwoodstox-java-4.1.3/src/test/stax2/stream/TestClosing.java 2012-04-24 04:38:21.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/stax2/stream/TestClosing.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,277 +0,0 @@ -package stax2.stream; - -import java.io.*; -import javax.xml.stream.*; -import javax.xml.transform.stream.StreamSource; - -import org.codehaus.stax2.*; -import org.codehaus.stax2.io.Stax2Source; -import org.codehaus.stax2.io.Stax2StringSource; - -import stax2.BaseStax2Test; - -/** - * This unit test suite verifies that the auto-closing feature works - * as expected (both explicitly, and via Source object being passed). - * - * @author Tatu Saloranta - * - * @since 3.0 - */ -public class TestClosing - extends BaseStax2Test -{ - /** - * This unit test checks the default behaviour; with no auto-close, no - * automatic closing should occur, nor explicit one unless specific - * forcing method is used. - */ - public void testNoAutoCloseReader() - throws XMLStreamException - { - final String XML = "..."; - - XMLInputFactory2 f = getFactory(false); - MyReader input = new MyReader(XML); - XMLStreamReader2 sr = (XMLStreamReader2) f.createXMLStreamReader(input); - // shouldn't be closed to begin with... - assertFalse(input.isClosed()); - assertTokenType(START_ELEMENT, sr.next()); - assertFalse(input.isClosed()); - - // nor closed half-way through with basic close() - sr.close(); - assertFalse(input.isClosed()); - - // ok, let's finish it up: - streamThrough(sr); - // still not closed - assertFalse(input.isClosed()); - - // except when forced to: - sr.closeCompletely(); - assertTrue(input.isClosed()); - - // ... and should be ok to call it multiple times: - sr.closeCompletely(); - sr.closeCompletely(); - assertTrue(input.isClosed()); - } - - public void testNoAutoCloseStream() - throws XMLStreamException, IOException - { - final String XML = "..."; - - XMLInputFactory2 f = getFactory(false); - MyStream input = new MyStream(XML.getBytes("UTF-8")); - XMLStreamReader2 sr = (XMLStreamReader2) f.createXMLStreamReader(input); - // shouldn't be closed to begin with... - assertFalse(input.isClosed()); - assertTokenType(START_ELEMENT, sr.next()); - assertFalse(input.isClosed()); - - // nor closed half-way through with basic close() - sr.close(); - assertFalse(input.isClosed()); - - // ok, let's finish it up: - streamThrough(sr); - // still not closed - assertFalse(input.isClosed()); - - // except when forced to: - sr.closeCompletely(); - assertTrue(input.isClosed()); - - // ... and should be ok to call it multiple times: - sr.closeCompletely(); - assertTrue(input.isClosed()); - } - - /** - * This unit test checks that when auto-closing option is set, the - * passed in input stream does get properly closed both when EOF - * is hit, and when we call close() prior to EOF. - */ - public void testAutoCloseEnabled() - throws XMLStreamException - { - final String XML = "..."; - - // First, explicit close: - XMLInputFactory2 f = getFactory(true); - MyReader input = new MyReader(XML); - XMLStreamReader2 sr = (XMLStreamReader2) f.createXMLStreamReader(input); - assertFalse(input.isClosed()); - assertTokenType(START_ELEMENT, sr.next()); - assertFalse(input.isClosed()); - sr.close(); - assertTrue(input.isClosed()); - // also, let's verify we can call more than once: - sr.close(); - sr.close(); - assertTrue(input.isClosed()); - - // Then implicit close (real auto-close): - input = new MyReader(XML); - sr = (XMLStreamReader2) f.createXMLStreamReader(input); - assertFalse(input.isClosed()); - streamThrough(sr); - assertTrue(input.isClosed()); - - // And then similarly for Source abstraction for streams - MySource src = MySource.createFor(XML); - sr = (XMLStreamReader2) f.createXMLStreamReader(src); - assertFalse(src.isClosed()); - assertTokenType(START_ELEMENT, sr.next()); - streamThrough(sr); - assertTrue(input.isClosed()); - } - - /** - * This unit test checks what happens when we use Result abstraction - * for passing in result stream/writer. Their handling differs depending - * on whether caller is considered to have access to the underlying - * physical object or not. - */ - public void testAutoCloseImplicit() - throws XMLStreamException - { - final String XML = "..."; - - // Factory with auto-close disabled: - XMLInputFactory2 f = getFactory(false); - - /* Ok, first: with regular (InputStream, Reader) streams no auto-closing - * because caller does have access: StreamSource retains given - * stream/reader as is. - */ - MySource input = MySource.createFor(XML); - XMLStreamReader2 sr = (XMLStreamReader2) f.createXMLStreamReader(input); - - assertFalse(input.isClosed()); - assertTokenType(START_ELEMENT, sr.next()); - assertFalse(input.isClosed()); - sr.close(); - assertFalse(input.isClosed()); - // also, let's verify we can call more than once: - sr.close(); - sr.close(); - assertFalse(input.isClosed()); - - /* And then more interesting case; verifying that Stax2Source - * sub-classes are implicitly auto-closed: they need to be, because - * they do not (necessarily) expose underlying physical stream. - * We can test this by using any Stax2Source impl. - */ - MyStringSource src = new MyStringSource(XML); - sr = (XMLStreamReader2) f.createXMLStreamReader((Stax2Source) src); - - assertFalse(src.isClosed()); - assertTokenType(START_ELEMENT, sr.next()); - assertFalse(src.isClosed()); - streamThrough(sr); - assertTrue(src.isClosed()); - - // similarly, let's verify plain old close would do it - src = new MyStringSource(XML); - sr = (XMLStreamReader2) f.createXMLStreamReader(src); - assertFalse(src.isClosed()); - assertTokenType(START_ELEMENT, sr.next()); - assertFalse(src.isClosed()); - sr.close(); - assertTrue(src.isClosed()); - } - - /* - //////////////////////////////////////// - // Non-test methods - //////////////////////////////////////// - */ - - XMLInputFactory2 getFactory(boolean autoClose) - { - XMLInputFactory2 f = getInputFactory(); - f.setProperty(XMLInputFactory2.P_AUTO_CLOSE_INPUT, - Boolean.valueOf(autoClose)); - return f; - } - - /* - //////////////////////////////////////// - // Helper mock classes - //////////////////////////////////////// - */ - - final static class MyReader extends StringReader - { - boolean mIsClosed = false; - - public MyReader(String contents) { - super(contents); - } - - public void close() { - mIsClosed = true; - super.close(); - } - - public boolean isClosed() { return mIsClosed; } - } - - final static class MyStream extends ByteArrayInputStream - { - boolean mIsClosed = false; - - public MyStream(byte[] data) { - super(data); - } - - public void close() throws IOException { - mIsClosed = true; - super.close(); - } - - public boolean isClosed() { return mIsClosed; } - } - - final static class MySource - extends StreamSource - { - final MyReader mReader; - - private MySource(MyReader reader) { - super(reader); - mReader = reader; - } - - public static MySource createFor(String content) { - MyReader r = new MyReader(content); - return new MySource(r); - } - - public boolean isClosed() { - return mReader.isClosed(); - } - - public Reader getReader() { - return mReader; - } - } - - private final static class MyStringSource - extends Stax2StringSource - { - MyReader mReader; - - public MyStringSource(String s) { super(s); } - - public Reader constructReader() { - mReader = new MyReader(getText()); - return mReader; - } - - public boolean isClosed() { return mReader.isClosed(); } - } -} diff -Nru libwoodstox-java-4.1.3/src/test/stax2/stream/TestConfig.java libwoodstox-java-5.1.0/src/test/stax2/stream/TestConfig.java --- libwoodstox-java-4.1.3/src/test/stax2/stream/TestConfig.java 2012-04-24 04:38:21.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/stax2/stream/TestConfig.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,75 +0,0 @@ -package stax2.stream; - -import javax.xml.stream.*; - -import org.codehaus.stax2.*; - -import stax2.BaseStax2Test; - -/** - * Set of unit tests that checks that configuring of - * {@link XMLInputFactory2} works ok. - */ -public class TestConfig - extends BaseStax2Test -{ - public void testForXmlConformanceProfile() - throws XMLStreamException - { - // configureForXmlConformance - XMLInputFactory2 ifact = getNewInputFactory(); - ifact.configureForXmlConformance(); - assertEquals(Boolean.TRUE, ifact.getProperty(XMLInputFactory.SUPPORT_DTD)); - assertEquals(Boolean.TRUE, ifact.getProperty(XMLInputFactory.IS_NAMESPACE_AWARE)); - assertEquals(Boolean.TRUE, ifact.getProperty(XMLInputFactory.IS_REPLACING_ENTITY_REFERENCES)); - assertEquals(Boolean.TRUE, ifact.getProperty(XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES)); - } - - public void testForConvenienceProfile() - throws XMLStreamException - { - // configureForConvenience - XMLInputFactory2 ifact = getNewInputFactory(); - ifact.configureForConvenience(); - assertEquals(Boolean.TRUE, ifact.getProperty(XMLInputFactory.IS_COALESCING)); - assertEquals(Boolean.TRUE, ifact.getProperty(XMLInputFactory.IS_REPLACING_ENTITY_REFERENCES)); - assertEquals(Boolean.FALSE, ifact.getProperty(XMLInputFactory2.P_REPORT_PROLOG_WHITESPACE)); - assertEquals(Boolean.FALSE, ifact.getProperty(XMLInputFactory2.P_REPORT_CDATA)); - assertEquals(Boolean.TRUE, ifact.getProperty(XMLInputFactory2.P_PRESERVE_LOCATION)); - } - - public void testForSpeedProfile() - throws XMLStreamException - { - // configureForSpeed - XMLInputFactory2 ifact = getNewInputFactory(); - ifact.configureForSpeed(); - assertEquals(Boolean.FALSE, ifact.getProperty(XMLInputFactory.IS_COALESCING)); - assertEquals(Boolean.FALSE, ifact.getProperty(XMLInputFactory2.P_PRESERVE_LOCATION)); - assertEquals(Boolean.FALSE, ifact.getProperty(XMLInputFactory2.P_REPORT_PROLOG_WHITESPACE)); - assertEquals(Boolean.TRUE, ifact.getProperty(XMLInputFactory2.P_INTERN_NAMES)); - assertEquals(Boolean.TRUE, ifact.getProperty(XMLInputFactory2.P_INTERN_NS_URIS)); - } - - public void testForLowMemProfile() - throws XMLStreamException - { - // configureForLowMemUsage - XMLInputFactory2 ifact = getNewInputFactory(); - ifact.configureForLowMemUsage(); - assertEquals(Boolean.FALSE, ifact.getProperty(XMLInputFactory.IS_COALESCING)); - assertEquals(Boolean.FALSE, ifact.getProperty(XMLInputFactory2.P_PRESERVE_LOCATION)); - } - - public void testForRoundTrippingProfile() - throws XMLStreamException - { - // configureForRoundTripping - XMLInputFactory2 ifact = getNewInputFactory(); - ifact.configureForRoundTripping(); - assertEquals(Boolean.FALSE, ifact.getProperty(XMLInputFactory.IS_COALESCING)); - assertEquals(Boolean.FALSE, ifact.getProperty(XMLInputFactory.IS_REPLACING_ENTITY_REFERENCES)); - assertEquals(Boolean.TRUE, ifact.getProperty(XMLInputFactory2.P_REPORT_CDATA)); - assertEquals(Boolean.TRUE, ifact.getProperty(XMLInputFactory2.P_REPORT_PROLOG_WHITESPACE)); - } -} diff -Nru libwoodstox-java-4.1.3/src/test/stax2/stream/TestGetElement.java libwoodstox-java-5.1.0/src/test/stax2/stream/TestGetElement.java --- libwoodstox-java-4.1.3/src/test/stax2/stream/TestGetElement.java 2012-04-24 04:38:21.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/stax2/stream/TestGetElement.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,177 +0,0 @@ -package stax2.stream; - -import java.io.*; -import java.util.*; - -import javax.xml.stream.*; - -import stax2.BaseStax2Test; - -/** - * Unit test(s) that verify correct functioning of - * {@link XMLStreamReader#getElementText}. This might actually - * belong more to the core StaxTest, but as bug was found from - * Woodstox, let's start by just adding them here first. - * - * @author Tatu Saloranta - * - * @since 3.0 - */ -public class TestGetElement - extends BaseStax2Test -{ - public void testLargeDocCoalesce() throws XMLStreamException - { - _testLargeDoc(true); - } - - public void testLargeDocNonCoalesce() throws XMLStreamException - { - _testLargeDoc(false); - } - - public void testLongSegmentCoalesce() throws XMLStreamException - { - _testLongSegment(true); - } - - public void testLongSegmentNonCoalesce() throws XMLStreamException - { - _testLongSegment(false); - } - - /* - /////////////////////////////////////////////////////////////////////// - // Second level test methods - /////////////////////////////////////////////////////////////////////// - */ - - private void _testLargeDoc(boolean coalesce) - throws XMLStreamException - { - final int LEN = 7258000; - final long SEED = 72; - - ByteArrayOutputStream bos = new ByteArrayOutputStream(LEN+2000); - int rowCount = generateDoc(SEED, LEN, bos); - XMLInputFactory f = getInputFactory(); - byte[] docData = bos.toByteArray(); - - // Let's test both coalescing and non-coalescing: - setCoalescing(f, coalesce); - XMLStreamReader sr = f.createXMLStreamReader(new ByteArrayInputStream(docData)); - assertTokenType(START_ELEMENT, sr.next()); - assertEquals("data", sr.getLocalName()); - int actRowCount = 0; - Random r = new Random(SEED); - - while (sr.nextTag() == START_ELEMENT) { // - ++actRowCount; - assertEquals("row", sr.getLocalName()); - expectElemText(sr, "a", String.valueOf(r.nextInt())); - expectElemText(sr, "b", String.valueOf(r.nextLong())); - expectElemText(sr, "c", String.valueOf(r.nextBoolean())); - assertTokenType(END_ELEMENT, sr.nextTag()); // match - } - assertEquals(rowCount, actRowCount); - } - - private void _testLongSegment(boolean coalesce) - throws XMLStreamException - { - final int LEN = 129000; - Random r = new Random(17); - - StringBuilder sb = new StringBuilder(LEN + 2000); - while (sb.length() < LEN) { - switch (r.nextInt() & 7) { - case 0: - sb.append("123"); - break; - case 1: - sb.append("foo\nbar"); - break; - case 2: - sb.append("rock & roll!"); - break; - default: - sb.append(sb.length()); - break; - } - } - - String contentStr = sb.toString(); - StringWriter strw = new StringWriter(LEN + 4000); - XMLStreamWriter sw = getOutputFactory().createXMLStreamWriter(strw); - - sw.writeStartDocument(); - sw.writeStartElement("data"); - sw.writeCharacters(contentStr); - sw.writeEndElement(); - sw.writeEndDocument(); - sw.close(); - - XMLInputFactory f = getInputFactory(); - setCoalescing(f, coalesce); - XMLStreamReader sr = f.createXMLStreamReader(new StringReader(strw.toString())); - assertTokenType(START_ELEMENT, sr.next()); - assertEquals("data", sr.getLocalName()); - String actStr = sr.getElementText(); - assertEquals(contentStr, actStr); - assertTokenType(END_ELEMENT, sr.getEventType()); - assertTokenType(END_DOCUMENT, sr.next()); - } - - /* - /////////////////////////////////////////////////////////////////////// - // Helper methods - /////////////////////////////////////////////////////////////////////// - */ - - private int generateDoc(long SEED, int LEN, ByteArrayOutputStream out) - throws XMLStreamException - { - XMLStreamWriter sw = getOutputFactory().createXMLStreamWriter(out, "UTF-8"); - Random r = new Random(SEED); - - sw.writeStartDocument(); - sw.writeStartElement("data"); - - int rowCount = 0; - - while (out.size() < LEN) { - sw.writeStartElement("row"); - - sw.writeStartElement("a"); - sw.writeCharacters(String.valueOf(r.nextInt())); - sw.writeEndElement(); - sw.writeStartElement("b"); - sw.writeCharacters(String.valueOf(r.nextLong())); - sw.writeEndElement(); - sw.writeStartElement("c"); - sw.writeCharacters(String.valueOf(r.nextBoolean())); - sw.writeEndElement(); - sw.writeCharacters("\n"); // to make debugging easier - - sw.writeEndElement(); - sw.flush(); - ++rowCount; - } - sw.writeEndElement(); - sw.writeEndDocument(); - sw.close(); - return rowCount; - } - - private void expectElemText(XMLStreamReader sr, String elem, String value) - throws XMLStreamException - { - assertTokenType(START_ELEMENT, sr.nextTag()); - assertEquals(elem, sr.getLocalName()); - String actValue = sr.getElementText(); - if (!value.equals(actValue)) { - fail("Expected value '"+value+"' (for element '"+elem+"'), got '"+actValue+"' (len "+actValue.length()+"): location "+sr.getLocation()); - } - assertTokenType(END_ELEMENT, sr.getEventType()); - } -} diff -Nru libwoodstox-java-4.1.3/src/test/stax2/stream/TestLocationInfo.java libwoodstox-java-5.1.0/src/test/stax2/stream/TestLocationInfo.java --- libwoodstox-java-4.1.3/src/test/stax2/stream/TestLocationInfo.java 2012-04-24 04:38:21.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/stax2/stream/TestLocationInfo.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,224 +0,0 @@ -package stax2.stream; - -import javax.xml.stream.*; - -import org.codehaus.stax2.*; - -import stax2.BaseStax2Test; - -/** - * Set of unit tests that checks that the {@link LocationInfo} implementation - * works as expected, provides proper values or -1 to indicate "don't know". - */ -public class TestLocationInfo - extends BaseStax2Test -{ - final static String TEST_DTD_DOC = - "" - +"\n" // fc: 38; row 2 - +"foo'>\n" // fc: 66; row 4 - +"]>\n" // fc: 98; row 5 - +"Entity: " // fc: 101; row 6 - +"&ent; " // fc: 115; row 6 - +"\r\n" // fc: 121; row 6 - +"&ent2;" // fc: 137; row 7 - +""; // fc: 144; row 7 - // EOF, fc: 150; row 7 - - /** - * This document fragment tries ensure that linefeed handling works ok - * as well. - */ - final static String TEST_LF_DOC = - "\n" // row 1 - +"\r\n" // row 2 - +" \r" // row 3 - +"\t\t\n" // row 4 - +" \r\n" // row 5 - +"\t "// row 6 - +""; // row6 - ; - - public void testInitialLocationNoDecl() - throws XMLStreamException - { - // First, let's test 'missing' start doc: - XMLStreamReader2 sr = getReader("", false); - LocationInfo loc = sr.getLocationInfo(); - assertLocation(sr, loc.getStartLocation(), 1, 1, - 0, loc.getStartingByteOffset(), - 0, loc.getStartingCharOffset()); - assertLocation(sr, loc.getEndLocation(), 1, 1, - 0, loc.getEndingByteOffset(), - 0, loc.getEndingCharOffset()); - sr.close(); - } - - public void testInitialLocationWithDecl() - throws XMLStreamException - { - // and then a real one - XMLStreamReader2 sr = getReader("", false); - LocationInfo loc = sr.getLocationInfo(); - assertLocation(sr, loc.getStartLocation(), 1, 1, - 0, loc.getStartingByteOffset(), - 0, loc.getStartingCharOffset()); - assertLocation(sr, loc.getEndLocation(), 3, 2, - 23, loc.getEndingByteOffset(), - 23, loc.getEndingCharOffset()); - sr.close(); - } - - public void testRowAccuracy() - throws XMLStreamException - { - XMLStreamReader2 sr = getReader(TEST_LF_DOC, false); - - assertRow(sr, 1, 1); // (missing) xml decl - - assertTokenType(START_ELEMENT, sr.next()); - assertEquals("root", sr.getLocalName()); - assertRow(sr, 1, 1); - assertTokenType(CHARACTERS, sr.next()); - assertRow(sr, 1, 2); // lf - - assertTokenType(START_ELEMENT, sr.next()); - assertEquals("branch", sr.getLocalName()); - assertRow(sr, 2, 2); - assertTokenType(CHARACTERS, sr.next()); - assertRow(sr, 2, 3); // lf - - assertTokenType(START_ELEMENT, sr.next()); - assertEquals("branch2", sr.getLocalName()); - assertRow(sr, 3, 3); - assertTokenType(CHARACTERS, sr.next()); - assertRow(sr, 3, 4); // lf - - assertTokenType(START_ELEMENT, sr.next()); - assertEquals("leaf", sr.getLocalName()); - assertRow(sr, 4, 4); - assertTokenType(END_ELEMENT, sr.next()); - assertEquals("leaf", sr.getLocalName()); - assertRow(sr, 4, 4); - assertTokenType(CHARACTERS, sr.next()); - assertRow(sr, 4, 5); // lf - - assertTokenType(END_ELEMENT, sr.next()); - assertEquals("branch2", sr.getLocalName()); - assertRow(sr, 5, 5); - assertTokenType(CHARACTERS, sr.next()); - assertRow(sr, 5, 6); - - assertTokenType(END_ELEMENT, sr.next()); - assertEquals("branch", sr.getLocalName()); - assertRow(sr, 6, 6); - assertTokenType(CHARACTERS, sr.next()); - assertRow(sr, 6, 6); - - assertTokenType(END_ELEMENT, sr.next()); - assertEquals("root", sr.getLocalName()); - assertRow(sr, 6, 6); - - sr.close(); - } - - /** - * Test that uses a document with internal DTD subset, to verify that - * location info is still valid. - */ - public void testLocationsWithDTD() - throws XMLStreamException - { - XMLStreamReader2 sr = getReader(TEST_DTD_DOC, true); - // will return null if SUPPORT_DTD fails: - if (sr == null) { - System.err.println("WARN: SupportDTD can not be enabled, need to skip test"); - return; - } - - LocationInfo loc = sr.getLocationInfo(); - assertLocation(sr, loc.getStartLocation(), 1, 1, - 0, loc.getStartingByteOffset(), - 0, loc.getStartingCharOffset()); - assertLocation(sr, loc.getEndLocation(), 22, 1, - 21, loc.getEndingByteOffset(), - 21, loc.getEndingCharOffset()); - - assertTokenType(DTD, sr.next()); - loc = sr.getLocationInfo(); - assertLocation(sr, loc.getStartLocation(), 22, 1, - 21, loc.getStartingByteOffset(), - 21, loc.getStartingCharOffset()); - assertLocation(sr, loc.getEndLocation(), 3, 5, - 100, loc.getEndingByteOffset(), - 100, loc.getEndingCharOffset()); - - // Let's ignore text/space, if there is one: - while (sr.next() != START_ELEMENT) { - ; - } - - loc = sr.getLocationInfo(); - assertLocation(sr, loc.getStartLocation(), 1, 6, - 101, loc.getStartingByteOffset(), - 101, loc.getStartingCharOffset()); - assertLocation(sr, loc.getEndLocation(), 7, 6, - 107, loc.getEndingByteOffset(), - 107, loc.getEndingCharOffset()); - - // !!! TBI - } - - /* - //////////////////////////////////////// - // Private methods - //////////////////////////////////////// - */ - - private void assertRow(XMLStreamReader2 sr, int startRow, int endRow) - throws XMLStreamException - { - LocationInfo li = sr.getLocationInfo(); - Location startLoc = li.getStartLocation(); - assertEquals("Incorrect starting row for event "+tokenTypeDesc(sr.getEventType()), startRow, startLoc.getLineNumber()); - Location endLoc = li.getEndLocation(); - assertEquals("Incorrect ending row for event "+tokenTypeDesc(sr.getEventType()), endRow, endLoc.getLineNumber()); - } - - private void assertLocation(XMLStreamReader sr, XMLStreamLocation2 loc, - int expCol, int expRow, - int expByteOffset, long actByteOffset, - int expCharOffset, long actCharOffset) - { - assertEquals("Incorrect column for "+tokenTypeDesc(sr.getEventType()), - expCol, loc.getColumnNumber()); - assertEquals("Incorrect row for "+tokenTypeDesc(sr.getEventType()), - expRow, loc.getLineNumber()); - - if (actByteOffset == -1) { // no info, that's fine - ; - } else { - assertEquals(expByteOffset, actByteOffset); - } - if (actCharOffset == -1) { // no info, that's fine - ; - } else { - assertEquals(expCharOffset, actCharOffset); - } - } - - private XMLStreamReader2 getReader(String contents, boolean needDTD) - throws XMLStreamException - { - XMLInputFactory f = getInputFactory(); - setCoalescing(f, false); // shouldn't really matter - setNamespaceAware(f, true); - if (!setSupportDTD(f, true)) { - return null; - } - // No need to validate, just need entities - setValidating(f, false); - return (XMLStreamReader2) constructStreamReader(f, contents); - } -} diff -Nru libwoodstox-java-4.1.3/src/test/stax2/stream/TestNamespaces.java libwoodstox-java-5.1.0/src/test/stax2/stream/TestNamespaces.java --- libwoodstox-java-4.1.3/src/test/stax2/stream/TestNamespaces.java 2012-04-24 04:38:21.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/stax2/stream/TestNamespaces.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,103 +0,0 @@ -package stax2.stream; - -import javax.xml.namespace.NamespaceContext; -import javax.xml.stream.*; - -import org.codehaus.stax2.*; - -/** - * Unit test suite that tests additional StAX2 namespace information - * accessors. - */ -public class TestNamespaces - extends stax2.BaseStax2Test -{ - public void testNonTransientNsCtxt() - throws XMLStreamException - { - String XML = - "" - +"" - +"" - +"" - +""; - XMLStreamReader2 sr = getNsReader(XML, true); - - assertEquals(START_ELEMENT, sr.next()); - assertEquals("root", sr.getLocalName()); - NamespaceContext curr = sr.getNamespaceContext(); - assertNotNull(curr); - checkValidityOfNs1(curr); - NamespaceContext nc1 = sr.getNonTransientNamespaceContext(); - assertNotNull(nc1); - checkValidityOfNs1(nc1); - - assertEquals(START_ELEMENT, sr.next()); - assertEquals("branch", sr.getLocalName()); - curr = sr.getNamespaceContext(); - // ok, this should have different settings: - assertNull(curr.getPrefix("nosuchurl")); - assertNull(curr.getNamespaceURI("xyz")); - // bindings from parent: - assertEquals("a", curr.getPrefix("whatever")); - assertEquals("whatever", curr.getNamespaceURI("a")); - assertEquals("b", curr.getPrefix("urlforb")); - assertEquals("urlforb", curr.getNamespaceURI("b")); - // and new ones: - assertEquals("", curr.getPrefix("someurl")); - assertEquals("c", curr.getPrefix("yetanotherurl")); - assertEquals("someurl", curr.getNamespaceURI("")); - assertEquals("yetanotherurl", curr.getNamespaceURI("c")); - - // but nc1 should be non-transient... - checkValidityOfNs1(nc1); - - assertEquals(START_ELEMENT, sr.next()); - assertEquals("leaf", sr.getLocalName()); - // should be non-transient... - checkValidityOfNs1(nc1); - - assertEquals(END_ELEMENT, sr.next()); - assertEquals(END_ELEMENT, sr.next()); - assertEquals(END_ELEMENT, sr.next()); - - // and nc1 should persist still - checkValidityOfNs1(nc1); - } - - /* - ////////////////////////////////////////////////////// - // Internal methods - ////////////////////////////////////////////////////// - */ - - private void checkValidityOfNs1(NamespaceContext nc) - throws XMLStreamException - { - // Ok, we have just 2 bindings here. - // First, let's check some non-existing bindings - assertNull(nc.getPrefix("someurl")); - assertNull(nc.getPrefix("whatever")); - assertNull(nc.getNamespaceURI("c")); - // default can be empty or null - String defNs = nc.getNamespaceURI(""); - if (defNs != null && defNs.length() > 0) { - fail("Expected default namespace to be null or empty, was '"+defNs+"'"); - } - // And then the ones that do exist - assertEquals("a", nc.getPrefix("myurl")); - assertEquals("myurl", nc.getNamespaceURI("a")); - assertEquals("b", nc.getPrefix("urlforb")); - assertEquals("urlforb", nc.getNamespaceURI("b")); - } - - private XMLStreamReader2 getNsReader(String contents, boolean coalesce) - throws XMLStreamException - { - XMLInputFactory f = getInputFactory(); - setNamespaceAware(f, true); - setCoalescing(f, coalesce); - setValidating(f, false); - return (XMLStreamReader2) constructStreamReader(f, contents); - } -} diff -Nru libwoodstox-java-4.1.3/src/test/stax2/stream/TestReaderConstruction.java libwoodstox-java-5.1.0/src/test/stax2/stream/TestReaderConstruction.java --- libwoodstox-java-4.1.3/src/test/stax2/stream/TestReaderConstruction.java 2012-04-24 04:38:21.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/stax2/stream/TestReaderConstruction.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,139 +0,0 @@ -package stax2.stream; - -import java.io.*; -import java.net.URL; - -import javax.xml.stream.*; - -import org.codehaus.stax2.*; -import org.codehaus.stax2.io.*; - -/** - * Unit test suite that tests additional StAX2 stream reader construction - * methods. - */ -public class TestReaderConstruction - extends stax2.BaseStax2Test -{ - public void testCreateWithFile() - throws IOException, XMLStreamException - { - File f = writeToTempFile("file"); - XMLInputFactory2 ifact = getInputFactory(); - setCoalescing(ifact, true); - verifyXML(ifact.createXMLStreamReader(f), "file"); - } - - public void testCreateWithURL() - throws IOException, XMLStreamException - { - File f = writeToTempFile("URL"); - XMLInputFactory2 ifact = getInputFactory(); - setCoalescing(ifact, true); - URL url = f.toURL(); - verifyXML(ifact.createXMLStreamReader(url), "URL"); - } - - public void testCreateWithFileSource() - throws IOException, XMLStreamException - { - File f = writeToTempFile("Filesource"); - XMLInputFactory2 ifact = getInputFactory(); - setCoalescing(ifact, true); - verifyXML(ifact.createXMLStreamReader(new Stax2FileSource(f)), - "Filesource"); - } - - public void testCreateWithURLSource() - throws IOException, XMLStreamException - { - File f = writeToTempFile("URLSource"); - XMLInputFactory2 ifact = getInputFactory(); - setCoalescing(ifact, true); - URL url = f.toURL(); - verifyXML(ifact.createXMLStreamReader(new Stax2URLSource(url)), - "URLSource"); - } - - public void testCreateWithStringSource() - throws XMLStreamException - { - XMLInputFactory2 ifact = getInputFactory(); - setCoalescing(ifact, true); - String xml = generateXML("Stringsource"); - verifyXML(ifact.createXMLStreamReader(new Stax2StringSource(xml)), - "Stringsource"); - } - - public void testCreateWithCharArraySource() - throws XMLStreamException - { - XMLInputFactory2 ifact = getInputFactory(); - setCoalescing(ifact, true); - String xml = generateXML("CharArraySource"); - char[] ch = xml.toCharArray(); - verifyXML(ifact.createXMLStreamReader(new Stax2CharArraySource(ch, 0, ch.length)), "CharArraySource"); - } - - public void testCreateWithByteArraySource() - throws XMLStreamException, IOException - { - XMLInputFactory2 ifact = getInputFactory(); - setCoalescing(ifact, true); - String xml = generateXML("ByteArraySource"); - byte[] orig = xml.getBytes("UTF-8"); - byte[] b = (byte[]) orig.clone(); - verifyXML(ifact.createXMLStreamReader(new Stax2ByteArraySource(b, 0, b.length)), "ByteArraySource"); - - // Also: let's check that non-0 offset works... - final int OFFSET = 29; - final int DOCLEN = b.length; - byte[] b2 = new byte[OFFSET + DOCLEN + 50]; - System.arraycopy(b, 0, b2, OFFSET, DOCLEN); - verifyXML(ifact.createXMLStreamReader(new Stax2ByteArraySource(b2, OFFSET, DOCLEN)), "ByteArraySource"); - } - - /* - //////////////////////////////////////////////// - // Internal methods - //////////////////////////////////////////////// - */ - - public void verifyXML(XMLStreamReader sr, String textValue) - throws XMLStreamException - { - /* No need to check thoroughly: mostly it's just checking that - * the referenced doc can be found at all - */ - assertTokenType(START_DOCUMENT, sr.getEventType()); - assertTokenType(START_ELEMENT, sr.next()); - assertEquals("root", sr.getLocalName()); - assertTokenType(CHARACTERS, sr.next()); - String str = getAndVerifyText(sr); - assertEquals(textValue, str); - assertTokenType(END_ELEMENT, sr.next()); - assertEquals("root", sr.getLocalName()); - assertTokenType(END_DOCUMENT, sr.next()); - sr.close(); - } - - String generateXML(String text) - { - StringBuffer sb = new StringBuffer(""); - sb.append(text); - sb.append(""); - return sb.toString(); - } - - File writeToTempFile(String text) - throws IOException - { - File f = File.createTempFile("stax2test", null); - Writer w = new OutputStreamWriter(new FileOutputStream(f), "UTF-8"); - w.write(generateXML(text)); - w.flush(); - w.close(); - f.deleteOnExit(); - return f; - } -} diff -Nru libwoodstox-java-4.1.3/src/test/stax2/stream/TestStreamReader.java libwoodstox-java-5.1.0/src/test/stax2/stream/TestStreamReader.java --- libwoodstox-java-4.1.3/src/test/stax2/stream/TestStreamReader.java 2012-04-24 04:38:21.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/stax2/stream/TestStreamReader.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,59 +0,0 @@ -package stax2.stream; - -import java.io.ByteArrayInputStream; - -import javax.xml.stream.*; - -import org.codehaus.stax2.*; - -import stax2.BaseStax2Test; - -public class TestStreamReader - extends BaseStax2Test -{ - /** - * Unit test to verify fixing of (and guard against regression of) - * [WSTX-201]. - */ - public void testIsCharacters() throws Exception - { - XMLInputFactory2 f = getInputFactory(); - setNamespaceAware(f, true); - setCoalescing(f, true); - XMLStreamReader sr = constructStreamReader(f, ""); - assertTokenType(START_ELEMENT, sr.next()); - assertEquals("root", sr.getLocalName()); - // should both return CHARACTERS - assertTokenType(CHARACTERS, sr.next()); - // and be considered of characters... - assertEquals(CHARACTERS, sr.getEventType()); - assertTrue(sr.isCharacters()); - assertTokenType(END_ELEMENT, sr.next()); - } - - /** - * Unit test related to [WSTX-274] - */ - public void testCData() throws Exception - { - XMLInputFactory2 f = getInputFactory(); - setNamespaceAware(f, true); - setCoalescing(f, true); - String strMessage = "" + - "" + - "" + - "outside cdata inside cdata]]>" + - "" + - "" + - ""; - XMLStreamReader reader = f.createXMLStreamReader(new ByteArrayInputStream(strMessage.getBytes("UTF-8"))); - assertTokenType(START_ELEMENT, reader.next()); - assertTokenType(START_ELEMENT, reader.next()); - assertTokenType(START_ELEMENT, reader.next()); - assertTokenType(START_ELEMENT, reader.next()); - // since we are coalescing, must be reported as CHARACTERS, not CDATA - assertTokenType(CHARACTERS, reader.next()); - String cdata = new String(reader.getTextCharacters(), reader.getTextStart(), reader.getTextLength()); - assertEquals("outside cdata inside cdata", cdata); - } -} diff -Nru libwoodstox-java-4.1.3/src/test/stax2/stream/TestStreamSource.java libwoodstox-java-5.1.0/src/test/stax2/stream/TestStreamSource.java --- libwoodstox-java-4.1.3/src/test/stax2/stream/TestStreamSource.java 2012-04-24 04:38:21.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/stax2/stream/TestStreamSource.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,43 +0,0 @@ -package stax2.stream; - -import java.io.*; -import javax.xml.stream.*; -import javax.xml.transform.stream.StreamSource; - -import stax2.BaseStax2Test; - -/** - * This unit test suite verifies use of {@link StreamSource} as input - * for {@link XMLInputFactory}. - * - * @author Tatu Saloranta - * - * @since 3.0 - */ -public class TestStreamSource - extends BaseStax2Test -{ - /** - * This test is related to problem reported as [WSTX-182], inability - * to use SystemId alone as source. - */ - public void testCreateUsingSystemId() - throws IOException, XMLStreamException - { - File tmpF = File.createTempFile("staxtest", ".xml"); - tmpF.deleteOnExit(); - - // First, need to write contents to the file - Writer w = new OutputStreamWriter(new FileOutputStream(tmpF), "UTF-8"); - w.write(""); - w.close(); - - XMLInputFactory f = getInputFactory(); - StreamSource src = new StreamSource(); - src.setSystemId(tmpF); - XMLStreamReader sr = f.createXMLStreamReader(src); - assertTokenType(START_ELEMENT, sr.next()); - assertTokenType(END_ELEMENT, sr.next()); - sr.close(); - } -} diff -Nru libwoodstox-java-4.1.3/src/test/stax2/stream/TestXMLStreamReader2.java libwoodstox-java-5.1.0/src/test/stax2/stream/TestXMLStreamReader2.java --- libwoodstox-java-4.1.3/src/test/stax2/stream/TestXMLStreamReader2.java 2012-04-24 04:38:21.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/stax2/stream/TestXMLStreamReader2.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,252 +0,0 @@ -package stax2.stream; - -import java.io.*; -import javax.xml.stream.*; - -import org.codehaus.stax2.*; - -import stax2.BaseStax2Test; - -public class TestXMLStreamReader2 - extends BaseStax2Test -{ - public void testPropertiesNative() - throws XMLStreamException - { - doTestProperties(false, false); - doTestProperties(true, false); - } - - public void testPropertiesWrapped() - throws XMLStreamException - { - doTestProperties(false, true); - doTestProperties(true, true); - } - - public void testSkipElement() - throws XMLStreamException - { - doTestSkipElement(false); - doTestSkipElement(true); - } - - public void testGetPrefixedName() - throws XMLStreamException - { - doTestGetPrefixedName(false); - doTestGetPrefixedName(true); - } - - public void testReportCData() throws XMLStreamException - { - _testCData(false, false); - _testCData(false, true); - _testCData(true, false); - _testCData(true, true); - } - - /** - * Test inspired by [WSTX-211] - */ - public void testLongerCData() throws Exception - { - String SRC_TEXT = -"\r\n123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678\r\n" -+"Woodstox 4.0.5 does not like this embedded element. However, if you take\r\n" -+"out one or more characters from the really long line (so that less than 500 characters come between\r\n" -+"'CDATA[' and the opening of the embeddedElement tag (including LF), then Woodstox will instead\r\n" - +"complain that the CDATA section wasn't ended."; - String DST_TEXT = SRC_TEXT.replace("\r\n", "\n"); - String XML = "\r\n" -+""; - // Hmmh. Seems like we need the BOM... - ByteArrayOutputStream bos = new ByteArrayOutputStream(); - bos.write(0xEF); - bos.write(0xBB); - bos.write(0xBF); - bos.write(XML.getBytes("UTF-8")); - byte[] bytes = bos.toByteArray(); - XMLInputFactory2 f = getInputFactory(); - // important: don't force coalescing, that'll convert CDATA to CHARACTERS - setCoalescing(f, false); - - XMLStreamReader sr = f.createXMLStreamReader(new ByteArrayInputStream(bytes)); - assertTokenType(START_DOCUMENT, sr.getEventType()); - assertTokenType(START_ELEMENT, sr.next()); - assertEquals("test", sr.getLocalName()); - // This should still work, although with linefeed replacements - assertEquals(DST_TEXT, sr.getElementText()); - assertTokenType(END_ELEMENT, sr.getEventType()); - sr.close(); - } - - /* - /////////////////////////////////////////////////////////////////////// - // Private methods, shared test code - /////////////////////////////////////////////////////////////////////// - */ - - public void _testCData(boolean wrapped, boolean report) throws XMLStreamException - { - final String XML = ""; - - XMLInputFactory2 f = getInputFactory(); - // important: don't force coalescing, that'll convert CDATA to CHARACTERS - setCoalescing(f, false); - f.setProperty(XMLInputFactory2.P_REPORT_CDATA, new Boolean(report)); - XMLStreamReader sr = f.createXMLStreamReader(new StringReader(XML)); - if (wrapped) { - sr = wrapWithAdapter(sr); - } - assertTokenType(START_ELEMENT, sr.next()); - int t = sr.next(); - assertEquals("test", getAndVerifyText(sr)); - if (report) { - assertTokenType(CDATA, t); - } else { - assertTokenType(CHARACTERS, t); - } - assertTokenType(END_ELEMENT, sr.next()); - sr.close(); - } - - /** - * @param wrapped If true, will use Stax2ReaderAdapter to - * wrap the stream reader implementation - */ - public void doTestProperties(boolean ns, boolean wrapped) - throws XMLStreamException - { - final String XML = "xxx"; - XMLStreamReader2 sr = getReader(XML, ns); - if (wrapped) { - sr = wrapWithAdapter(sr); - } - - assertTokenType(START_DOCUMENT, sr.getEventType()); - assertEquals(0, sr.getDepth()); - assertFalse(sr.isEmptyElement()); - - assertTokenType(START_ELEMENT, sr.next()); - assertEquals("root", sr.getLocalName()); - assertEquals(1, sr.getDepth()); - assertFalse(sr.isEmptyElement()); - - assertTokenType(START_ELEMENT, sr.next()); - assertEquals("child", sr.getLocalName()); - assertEquals(2, sr.getDepth()); - - /* Can only test this for native readers; adapter has no way - * of implementing it reliably for Stax1 impls: - */ - if (!wrapped) { - assertTrue(sr.isEmptyElement()); - } - assertTokenType(END_ELEMENT, sr.next()); - assertEquals("child", sr.getLocalName()); - assertEquals(2, sr.getDepth()); - if (!wrapped) { // as above, only for non-wrapped - assertFalse(sr.isEmptyElement()); - } - - assertTokenType(START_ELEMENT, sr.next()); - assertEquals("child2", sr.getLocalName()); - assertEquals(2, sr.getDepth()); - if (!wrapped) { // as above, only for non-wrapped - assertFalse(sr.isEmptyElement()); - } - - assertTokenType(CHARACTERS, sr.next()); - assertEquals("xxx", getAndVerifyText(sr)); - assertEquals(2, sr.getDepth()); - // note: shouldn't cause an exception - if (!wrapped) { - assertFalse(sr.isEmptyElement()); - } - - assertTokenType(END_ELEMENT, sr.next()); - assertEquals("child2", sr.getLocalName()); - assertEquals(2, sr.getDepth()); - if (!wrapped) { - assertFalse(sr.isEmptyElement()); - } - - assertTokenType(END_ELEMENT, sr.next()); - assertEquals("root", sr.getLocalName()); - assertEquals(1, sr.getDepth()); - if (!wrapped) { - assertFalse(sr.isEmptyElement()); - } - - assertTokenType(END_DOCUMENT, sr.next()); - assertEquals(0, sr.getDepth()); - if (!wrapped) { - assertFalse(sr.isEmptyElement()); - } - } - - public void doTestSkipElement(boolean ns) - throws XMLStreamException - { - final String XML = "xxx"; - XMLStreamReader2 sr = getReader(XML, ns); - assertTokenType(START_DOCUMENT, sr.getEventType()); - - assertTokenType(START_ELEMENT, sr.next()); - assertEquals("root", sr.getLocalName()); - sr.skipElement(); - assertTokenType(END_ELEMENT, sr.getEventType()); - assertEquals("root", sr.getLocalName()); - assertTokenType(END_DOCUMENT, sr.next()); - } - - public void doTestGetPrefixedName(boolean ns) - throws XMLStreamException - { - final String XML = - "" - +"..." - +"" - ; - XMLStreamReader2 sr = getReader(XML, ns); - try { - assertTokenType(START_ELEMENT, sr.next()); - assertEquals("root", sr.getPrefixedName()); - assertTokenType(START_ELEMENT, sr.next()); - assertEquals("xy:elem", sr.getPrefixedName()); - assertTokenType(PROCESSING_INSTRUCTION, sr.next()); - assertEquals("proc", sr.getPrefixedName()); - assertTokenType(CHARACTERS, sr.next()); - assertTokenType(START_ELEMENT, sr.next()); - assertEquals("another:x", sr.getPrefixedName()); - assertTokenType(END_ELEMENT, sr.next()); - assertEquals("another:x", sr.getPrefixedName()); - assertTokenType(END_ELEMENT, sr.next()); - assertEquals("xy:elem", sr.getPrefixedName()); - assertTokenType(END_ELEMENT, sr.next()); - assertEquals("root", sr.getPrefixedName()); - assertTokenType(END_DOCUMENT, sr.next()); - } catch (XMLStreamException xse) { - fail("Did not expect any problems during parsing, but got: "+xse); - } - } - - /* - /////////////////////////////////////////////////////////////////////// - // Private methods, other - /////////////////////////////////////////////////////////////////////// - */ - - private XMLStreamReader2 getReader(String contents, boolean nsAware) - throws XMLStreamException - { - XMLInputFactory2 f = getInputFactory(); - setCoalescing(f, true); - setSupportDTD(f, true); - setNamespaceAware(f, nsAware); - setValidating(f, false); - return constructStreamReader(f, contents); - } -} - diff -Nru libwoodstox-java-4.1.3/src/test/stax2/TestFactories.java libwoodstox-java-5.1.0/src/test/stax2/TestFactories.java --- libwoodstox-java-4.1.3/src/test/stax2/TestFactories.java 2012-04-24 04:38:21.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/stax2/TestFactories.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,127 +0,0 @@ -package stax2; - -import java.io.*; - -import javax.xml.stream.*; - -import org.codehaus.stax2.XMLStreamReader2; -import org.codehaus.stax2.XMLStreamWriter2; - -/** - * Unit tests to verify expected handling of property accessors and - * modifiers with Stax2 input and output factories, as well as - * simple readers and writers. - * These are mostly related to issue [WSTX-243] - */ -public class TestFactories extends BaseStax2Test -{ - private final String NO_SUCH_PROPERTY = "noSuchProperty"; - - // [WSTX-243]; verify exception for input factory - public void testPropertiesInputFactory() throws XMLStreamException - { - XMLInputFactory f = getInputFactory(); - // First, verify property is indeed unsupported - assertFalse(f.isPropertySupported(NO_SUCH_PROPERTY)); - - // First: error for trying to access unknown - try { - f.getProperty(NO_SUCH_PROPERTY); - fail("Expected exception"); - } catch (IllegalArgumentException e) { - verifyException(e, NO_SUCH_PROPERTY); - } - - // Ditto for trying to set such property - try { - f.setProperty(NO_SUCH_PROPERTY, "foobar"); - fail("Expected exception"); - } catch (IllegalArgumentException e) { - verifyException(e, NO_SUCH_PROPERTY); - } - } - - public void testPropertiesStreamReader() throws XMLStreamException - { - XMLInputFactory f = getInputFactory(); - XMLStreamReader2 r = (XMLStreamReader2) f.createXMLStreamReader(new StringReader("")); - - // First, verify property is indeed unsupported - assertFalse(r.isPropertySupported(NO_SUCH_PROPERTY)); - - /* Ok: as of Woodstox 4.0, behavior is such that no exception is thrown, - * because javadocs do not indicate that it should be done (save for case - * where property name is null). Whether this is right interpretation or not - * is open to discussion; but for now we will verify that behavior does not - * change from 4.0 without explicit decision. - */ - /* - try { - Object ob = r.getProperty(NO_SUCH_PROPERTY); - fail("Expected exception, instead got result: "+ob); - } catch (IllegalArgumentException e) { - verifyException(e, NO_SUCH_PROPERTY); - } - */ - Object ob = r.getProperty(NO_SUCH_PROPERTY); - assertNull(ob); - - // And although setter is specified by Stax2, it too fails on unrecognized: - try { - r.setProperty(NO_SUCH_PROPERTY, "foobar"); - fail("Expected exception"); - } catch (IllegalArgumentException e) { - verifyException(e, NO_SUCH_PROPERTY); - } - } - - // [WSTX-243]; verify exception for input factory - public void testPropertiesOutputFactory() throws XMLStreamException - { - XMLOutputFactory f = getOutputFactory(); - // First, verify property is indeed unsupported - assertFalse(f.isPropertySupported(NO_SUCH_PROPERTY)); - - // First: error for trying to access unknown - try { - f.getProperty(NO_SUCH_PROPERTY); - fail("Expected exception"); - } catch (IllegalArgumentException e) { - verifyException(e, NO_SUCH_PROPERTY); - } - - // Ditto for trying to set such property - try { - f.setProperty(NO_SUCH_PROPERTY, "foobar"); - fail("Expected exception"); - } catch (IllegalArgumentException e) { - verifyException(e, NO_SUCH_PROPERTY); - } - } - - public void testPropertiesStreamWriter() throws XMLStreamException - { - XMLOutputFactory f = getOutputFactory(); - XMLStreamWriter2 w = (XMLStreamWriter2) f.createXMLStreamWriter(new StringWriter()); - - // First, verify property is indeed unsupported - assertFalse(w.isPropertySupported(NO_SUCH_PROPERTY)); - - // First: error for trying to access unknown, as per Stax 1.0 spec: - try { - w.getProperty(NO_SUCH_PROPERTY); - fail("Expected exception"); - } catch (IllegalArgumentException e) { - verifyException(e, NO_SUCH_PROPERTY); - } - - // And although setter is specified by Stax2, it too fails on unrecognized: - try { - w.setProperty(NO_SUCH_PROPERTY, "foobar"); - fail("Expected exception"); - } catch (IllegalArgumentException e) { - verifyException(e, NO_SUCH_PROPERTY); - } - } - -} diff -Nru libwoodstox-java-4.1.3/src/test/stax2/typed/ReaderArrayTestBase.java libwoodstox-java-5.1.0/src/test/stax2/typed/ReaderArrayTestBase.java --- libwoodstox-java-4.1.3/src/test/stax2/typed/ReaderArrayTestBase.java 2012-04-24 04:38:21.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/stax2/typed/ReaderArrayTestBase.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,569 +0,0 @@ -package stax2.typed; - -import java.lang.reflect.Array; -import java.util.Random; - -import javax.xml.stream.*; - -import org.codehaus.stax2.*; -import org.codehaus.stax2.typed.*; - -import stax2.BaseStax2Test; - -/** - * Base class that contains set of simple unit tests to verify implementation - * of {@link TypedXMLStreamReader}. Concrete sub-classes are used to - * test both native and wrapped Stax2 implementations. - * - * @author Tatu Saloranta - */ -public abstract class ReaderArrayTestBase - extends BaseStax2Test -{ - // Let's test variable length arrays - final static int[] COUNTS_ELEM = new int[] { - 7, 39, 116, 900, 5003 - }; - final static int[] COUNTS_ATTR = new int[] { - 5, 17, 59, 357, 1920 - }; - - /* - //////////////////////////////////////// - // Abstract methods - //////////////////////////////////////// - */ - - protected abstract XMLStreamReader2 getReader(String contents) - throws XMLStreamException; - - /* - //////////////////////////////////////// - // Test methods, elem, valid - //////////////////////////////////////// - */ - - public void testSimpleIntArrayElem() throws XMLStreamException - { - _testSimpleIntArrayElem(false); - } - public void testSimpleIntArrayElemWithNoise() throws XMLStreamException - { - _testSimpleIntArrayElem(true); - } - - private void _testSimpleIntArrayElem(boolean withNoise) - throws XMLStreamException - { - for (int i = 0; i < COUNTS_ELEM.length; ++i) { - int len = COUNTS_ELEM[i]; - int[] data = intArray(len); - String XML = buildDoc(data, withNoise); - - // First, full read - verifyInts(XML, data, len); - // Then one by one - verifyInts(XML, data, 1); - // And finally, random - verifyInts(XML, data, -1); - } - } - - public void testSimpleLongArrayElem() - throws XMLStreamException - { - _testSimpleLongArrayElem(false); - } - public void testSimpleLongArrayElemWithNoise() - throws XMLStreamException - { - _testSimpleLongArrayElem(true); - } - - private void _testSimpleLongArrayElem(boolean withNoise) - throws XMLStreamException - { - for (int i = 0; i < COUNTS_ELEM.length; ++i) { - int len = COUNTS_ELEM[i]; - long[] data = longArray(len); - String XML = buildDoc(data, withNoise); - - // First, full read - verifyLongs(XML, data, len); - // Then one by one - verifyLongs(XML, data, 1); - // And finally, random - verifyLongs(XML, data, -1); - } - } - - public void testSimpleFloatArrayElem() - throws XMLStreamException - { - _testSimpleFloatArrayElem(false); - } - public void testSimpleFloatArrayElemWithNoise() - throws XMLStreamException - { - _testSimpleFloatArrayElem(true); - } - - private void _testSimpleFloatArrayElem(boolean withNoise) - throws XMLStreamException - { - for (int i = 0; i < COUNTS_ELEM.length; ++i) { - int len = COUNTS_ELEM[i]; - float[] data = floatArray(len); - String XML = buildDoc(data, withNoise); - - // First, full read - verifyFloats(XML, data, len); - // Then one by one - verifyFloats(XML, data, 1); - // And finally, random - verifyFloats(XML, data, -1); - } - } - - public void testSimpleDoubleArrayElem() - throws XMLStreamException - { - _testSimpleDoubleArrayElem(false); - } - public void testSimpleDoubleArrayElemWithNoise() - throws XMLStreamException - { - _testSimpleDoubleArrayElem(true); - } - - private void _testSimpleDoubleArrayElem(boolean withNoise) - throws XMLStreamException - { - for (int i = 0; i < COUNTS_ELEM.length; ++i) { - int len = COUNTS_ELEM[i]; - double[] data = doubleArray(len); - String XML = buildDoc(data, withNoise); - - // First, full read - verifyDoubles(XML, data, len); - // Then one by one - verifyDoubles(XML, data, 1); - // And finally, random - verifyDoubles(XML, data, -1); - } - } - - public void testEmptyElems() - throws XMLStreamException - { - // And then some edge cases too - for (int i = 0; i < 4; ++i) { - XMLStreamReader2 sr = getReader(""); - assertTokenType(START_ELEMENT, sr.next()); - int count; - - switch (i) { - case 0: - count = sr.readElementAsIntArray(new int[1], 0, 1); - break; - case 1: - count = sr.readElementAsLongArray(new long[1], 0, 1); - break; - case 2: - count = sr.readElementAsFloatArray(new float[1], 0, 1); - break; - default: - count = sr.readElementAsDoubleArray(new double[1], 0, 1); - break; - } - sr.close(); - assertEquals(-1, count); - } - } - - /* - //////////////////////////////////////// - // Test methods, elem, invalid - //////////////////////////////////////// - */ - - public void testInvalidIntArrayElem() - throws XMLStreamException - { - XMLStreamReader2 sr; - - for (int i = 0; i < 4; ++i) { - sr = getReader("1 2"); - // Can't call on START_DOCUMENT - try { - switch (i) { - case 0: - sr.readElementAsIntArray(new int[3], 0, 1); - fail("Expected an exception when trying to read at START_DOCUMENT"); - case 1: - sr.readElementAsLongArray(new long[3], 0, 1); - fail("Expected an exception when trying to read at START_DOCUMENT"); - case 2: - sr.readElementAsFloatArray(new float[3], 0, 1); - fail("Expected an exception when trying to read at START_DOCUMENT"); - default: - sr.readElementAsDoubleArray(new double[3], 0, 1); - fail("Expected an exception when trying to read at START_DOCUMENT"); - } - } catch (IllegalStateException ise) { } - - sr = getReader(""); - sr.next(); - assertTokenType(COMMENT, sr.next()); - - /* Hmmh. Should it be illegal to call on COMMENT? - * Let's assume it should - */ - /* - try { - switch (i) { - case 0: - sr.readElementAsIntArray(new int[3], 0, 1); - fail("Expected an exception when trying to read at COMMENT"); - case 1: - sr.readElementAsLongArray(new long[3], 0, 1); - fail("Expected an exception when trying to read at COMMENT"); - case 2: - sr.readElementAsFloatArray(new float[3], 0, 1); - fail("Expected an exception when trying to read at COMMENT"); - default: - sr.readElementAsDoubleArray(new double[3], 0, 1); - fail("Expected an exception when trying to read at COMMENT"); - } - } catch (IllegalStateException ise) { } - */ - } - } - - /* - //////////////////////////////////////// - // Test methods, attr, valid - //////////////////////////////////////// - */ - - public void testSimpleIntArrayAttr() - throws XMLStreamException - { - for (int i = 0; i < COUNTS_ATTR.length; ++i) { - int len = COUNTS_ATTR[i]; - int[] data = intArray(len); - String XML = buildAttrDoc(data); - verifyIntsAttr(XML, data); - } - } - - public void testSimpleLongArrayAttr() - throws XMLStreamException - { - for (int i = 0; i < COUNTS_ATTR.length; ++i) { - int len = COUNTS_ATTR[i]; - long[] data = longArray(len); - String XML = buildAttrDoc(data); - verifyLongsAttr(XML, data); - } - } - - public void testSimpleFloatArrayAttr() - throws XMLStreamException - { - for (int i = 0; i < COUNTS_ATTR.length; ++i) { - int len = COUNTS_ATTR[i]; - float[] data = floatArray(len); - String XML = buildAttrDoc(data); - verifyFloatsAttr(XML, data); - } - } - - public void testSimpleDoubleArrayAttr() - throws XMLStreamException - { - for (int i = 0; i < COUNTS_ATTR.length; ++i) { - int len = COUNTS_ATTR[i]; - double[] data = doubleArray(len); - String XML = buildAttrDoc(data); - verifyDoublesAttr(XML, data); - } - } - - /* - //////////////////////////////////////// - // Helper methods - //////////////////////////////////////// - */ - - private int[] intArray(int count) - { - Random r = new Random(count); - int[] result = new int[count]; - for (int i = 0; i < count; ++i) { - int base = r.nextInt(); - int shift = (r.nextInt() % 24); - result[i] = (base >> shift); - } - return result; - } - - private long[] longArray(int count) - { - Random r = new Random(count); - long[] result = new long[count]; - for (int i = 0; i < count; ++i) { - long base = r.nextLong(); - int shift = (r.nextInt() % 56); - result[i] = (base >> shift); - } - return result; - } - - private float[] floatArray(int count) - { - Random r = new Random(count); - float[] result = new float[count]; - for (int i = 0; i < count; ++i) { - float f = r.nextFloat(); - result[i] = r.nextBoolean() ? -f : f; - } - return result; - } - - private double[] doubleArray(int count) - { - Random r = new Random(count); - double[] result = new double[count]; - for (int i = 0; i < count; ++i) { - double d = r.nextDouble(); - result[i] = r.nextBoolean() ? -d : d; - } - return result; - } - - private String buildDoc(Object dataArray, boolean addNoise) - { - int len = Array.getLength(dataArray); - StringBuilder sb = new StringBuilder(len * 8); - sb.append(""); - Random r = new Random(Array.get(dataArray, 0).hashCode()); - for (int i = 0; i < len; ++i) { - Object value = Array.get(dataArray, i).toString(); - sb.append(value); - // Let's add 25% of time - if (addNoise && r.nextBoolean() && r.nextBoolean()) { - if (r.nextBoolean()) { - sb.append(""); - } else { - sb.append(""); - } - } - sb.append(' '); - } - sb.append(""); - return sb.toString(); - } - - private String buildAttrDoc(Object dataArray) - { - int len = Array.getLength(dataArray); - StringBuilder sb = new StringBuilder(len * 8); - sb.append(""); - return sb.toString(); - } - - private void assertArraysEqual(Object expArray, Object actArray, int actLen) - { - int expLen = Array.getLength(expArray); - if (expLen != actLen) { - fail("Expected number of entries "+expLen+", got "+actLen); - } - for (int i = 0; i < expLen; ++i) { - Object e1 = Array.get(expArray, i); - Object e2 = Array.get(actArray, i); - if (!e1.equals(e2)) { - fail("Elements at #"+i+" (len "+expLen+") differ: expected "+e1+", got "+e2); - } - } - } - - private void verifyInts(String doc, int[] data, int blockLen) - throws XMLStreamException - { - Random r = new Random(blockLen); - int[] buffer = new int[Math.max(blockLen, 256+16)]; - int[] result = new int[data.length]; - int entries = 0; - - XMLStreamReader2 sr = getReader(doc); - sr.next(); - assertTokenType(START_ELEMENT, sr.getEventType()); - - while (true) { - int readLen = (r == null) ? blockLen : (1 + (r.nextInt() & 0xFF)); - int offset = (r.nextInt() & 0xF); - int got; - - try { - got = sr.readElementAsIntArray(buffer, offset, readLen); - if (got < 0) { - break; - } - } catch (XMLStreamException xse) { - fail("Did not expect a failure (readLen "+readLen+", offset "+offset+", total exp elems "+data.length+"), problem: "+xse.getMessage()); - got = 0; // never gets here, but compiler doesn't know - } - if ((entries + got) > result.length) { - // Is that all, or would we get more? - int total = entries+got; - int more = sr.readElementAsIntArray(buffer, 0, 256); - - if (more > 0) { - fail("Expected only "+result.length+" entries, total now "+total+", plus "+more+" more with next call"); - } else { - fail("Expected only "+result.length+" entries, got "+total+" (and that's all)"); - } - } - System.arraycopy(buffer, offset, result, entries, got); - entries += got; - } - assertArraysEqual(data, result, entries); - sr.close(); - } - - private void verifyLongs(String doc, long[] data, int blockLen) - throws XMLStreamException - { - Random r = (blockLen < 0) ? new Random(blockLen) : null; - long[] buffer = new long[Math.max(blockLen, 256)]; - long[] result = new long[data.length]; - int entries = 0; - - XMLStreamReader2 sr = getReader(doc); - sr.next(); - assertTokenType(START_ELEMENT, sr.getEventType()); - - while (true) { - int readLen = (r == null) ? blockLen : (1 + r.nextInt() & 0xFF); - int got = sr.readElementAsLongArray(buffer, 0, readLen); - if (got < 0) { - break; - } - if ((entries + got) > result.length) { - fail("Expected only "+result.length+" entries, already got "+(entries+got)); - } - System.arraycopy(buffer, 0, result, entries, got); - entries += got; - } - assertArraysEqual(data, result, entries); - sr.close(); - } - - private void verifyFloats(String doc, float[] data, int blockLen) - throws XMLStreamException - { - Random r = (blockLen < 0) ? new Random(blockLen) : null; - float[] buffer = new float[Math.max(blockLen, 256)]; - float[] result = new float[data.length]; - int entries = 0; - - XMLStreamReader2 sr = getReader(doc); - sr.next(); - assertTokenType(START_ELEMENT, sr.getEventType()); - - while (true) { - int readLen = (r == null) ? blockLen : (1 + r.nextInt() & 0xFF); - int got = sr.readElementAsFloatArray(buffer, 0, readLen); - if (got < 0) { - break; - } - if ((entries + got) > result.length) { - fail("Expected only "+result.length+" entries, already got "+(entries+got)); - } - System.arraycopy(buffer, 0, result, entries, got); - entries += got; - } - assertArraysEqual(data, result, entries); - sr.close(); - } - - private void verifyDoubles(String doc, double[] data, int blockLen) - throws XMLStreamException - { - Random r = (blockLen < 0) ? new Random(blockLen) : null; - double[] buffer = new double[Math.max(blockLen, 256)]; - double[] result = new double[data.length]; - int entries = 0; - - XMLStreamReader2 sr = getReader(doc); - sr.next(); - assertTokenType(START_ELEMENT, sr.getEventType()); - - while (true) { - int readLen = (r == null) ? blockLen : (1 + r.nextInt() & 0xFF); - int got = sr.readElementAsDoubleArray(buffer, 0, readLen); - if (got < 0) { - break; - } - if ((entries + got) > result.length) { - fail("Expected only "+result.length+" entries, already got "+(entries+got)); - } - System.arraycopy(buffer, 0, result, entries, got); - entries += got; - } - assertArraysEqual(data, result, entries); - sr.close(); - } - - private void verifyIntsAttr(String doc, int[] data) - throws XMLStreamException - { - XMLStreamReader2 sr = getReader(doc); - sr.next(); - assertTokenType(START_ELEMENT, sr.getEventType()); - int[] result = sr.getAttributeAsIntArray(0); - assertArraysEqual(data, result, result.length); - sr.close(); - } - - private void verifyLongsAttr(String doc, long[] data) - throws XMLStreamException - { - XMLStreamReader2 sr = getReader(doc); - sr.next(); - assertTokenType(START_ELEMENT, sr.getEventType()); - long[] result = sr.getAttributeAsLongArray(0); - assertArraysEqual(data, result, result.length); - sr.close(); - } - - private void verifyFloatsAttr(String doc, float[] data) - throws XMLStreamException - { - XMLStreamReader2 sr = getReader(doc); - sr.next(); - assertTokenType(START_ELEMENT, sr.getEventType()); - float[] result = sr.getAttributeAsFloatArray(0); - assertArraysEqual(data, result, result.length); - sr.close(); - } - - private void verifyDoublesAttr(String doc, double[] data) - throws XMLStreamException - { - XMLStreamReader2 sr = getReader(doc); - sr.next(); - assertTokenType(START_ELEMENT, sr.getEventType()); - double[] result = sr.getAttributeAsDoubleArray(0); - assertArraysEqual(data, result, result.length); - sr.close(); - } -} - diff -Nru libwoodstox-java-4.1.3/src/test/stax2/typed/ReaderBinaryTestBase.java libwoodstox-java-5.1.0/src/test/stax2/typed/ReaderBinaryTestBase.java --- libwoodstox-java-4.1.3/src/test/stax2/typed/ReaderBinaryTestBase.java 2012-04-24 04:38:21.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/stax2/typed/ReaderBinaryTestBase.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,744 +0,0 @@ -package stax2.typed; - -import java.util.Random; -import javax.xml.stream.*; - -import org.codehaus.stax2.*; -import org.codehaus.stax2.ri.typed.AsciiValueEncoder; -import org.codehaus.stax2.ri.typed.ValueEncoderFactory; -import org.codehaus.stax2.typed.*; - -import stax2.BaseStax2Test; - -/** - * Base class that contains set of simple unit tests to verify implementation - * of parts {@link TypedXMLStreamReader} that deal with base64 encoded - * binary data. - * Concrete sub-classes are used to test both native and wrapped Stax2 - * implementations. - * - * @author Tatu Saloranta - */ -public abstract class ReaderBinaryTestBase - extends BaseStax2Test -{ - /** - * For good testing let's try all alternative variants, in addition - * to the default one (MIME) - */ - final static Base64Variant[] sBase64Variants = new Base64Variant[] { - Base64Variants.MIME, - Base64Variants.PEM, - Base64Variants.MODIFIED_FOR_URL - }; - - final static Base64Variant[] sPaddingVariants = new Base64Variant[] { - Base64Variants.MIME, - Base64Variants.PEM - }; - - final static Base64Variant[] sNonPaddingVariants = new Base64Variant[] { - Base64Variants.MODIFIED_FOR_URL - }; - - // Let's test variable length arrays - final static int[] LEN_ELEM = new int[] { - 1, 2, 3, 4, 7, 39, 116, 400, 900, 5003, 17045, 125000, 499999 - }; - final static int[] LEN_ATTR = new int[] { - 1, 2, 3, 5, 17, 59, 357, 1920, 9000, 63000, 257010 - }; - - final static int[] LEN_ELEM_MULTIPLE = new int[] { - 4, 7, 16, 99, 458, 3000, 12888, 79003, 145000 - }; - - final static int METHOD_SINGLE = 1; - final static int METHOD_FULL = 2; - final static int METHOD_2BYTES = 3; - final static int METHOD_SEGMENTED = 4; - final static int METHOD_FULL_CONVENIENT = 5; - - /** - * Padding characters are only legal as last one or two characters - * of 4-char units. - */ - final static String[] INVALID_PADDING = new String[] { - "AAAA====", "AAAAB===", "AA=A" - }; - - /** - * White space is only allowed between 4-char units, not within. - */ - final static String[] INVALID_WS = new String[] { - "AAA A", "AAAA BBBB C CCC", "ABCD ABCD AB CD" - }; - - /** - * And there are unlimited number of illegal characters within - * base64 sections, too - */ - final String[] INVALID_WEIRD_CHARS = new String[] { - "AAA?", "AAAA@@@@", "ABCD\u00A0BCD" - }; - - /* - /////////////////////////////////////////////////////////////////////// - // Abstract methods - /////////////////////////////////////////////////////////////////////// - */ - - protected abstract XMLStreamReader2 getReader(String contents) - throws XMLStreamException; - - protected XMLStreamReader2 getElemReader(String contents) - throws XMLStreamException - { - XMLStreamReader2 sr = getReader(contents); - assertTokenType(START_ELEMENT, sr.next()); - return sr; - } - - /* - /////////////////////////////////////////////////////////////////////// - // Test methods, elem, valid - /////////////////////////////////////////////////////////////////////// - */ - - public void testBinaryElemByteByByte() throws XMLStreamException - { - _testBinaryElem(METHOD_SINGLE, false); - _testBinaryElem(METHOD_SINGLE, true); - } - - public void testBinaryElemFull() throws XMLStreamException - { - _testBinaryElem(METHOD_FULL, false); - _testBinaryElem(METHOD_FULL, true); - } - - public void testBinaryElem2Bytes() throws XMLStreamException - { - _testBinaryElem(METHOD_2BYTES, false); - _testBinaryElem(METHOD_2BYTES, true); - } - - public void testBinaryElemSegmented() throws XMLStreamException - { - _testBinaryElem(METHOD_SEGMENTED, false); - _testBinaryElem(METHOD_SEGMENTED, true); - } - - public void testBinaryElemFullConvenient() throws XMLStreamException - { - _testBinaryElem(METHOD_FULL_CONVENIENT, false); - _testBinaryElem(METHOD_FULL_CONVENIENT, true); - } - - /** - * Unit test that verifies that decoding state is properly - * reset even if not all data is read. - * Access is done using supported method (i.e. starting with - * - */ - public void testMultipleBinaryElems() throws XMLStreamException - { - /* Let's try couple of sizes here too, but only check partial - * content; this to ensure content is properly cleared between - * calls - */ - final int REPS = 3; - - for (int bv = 0; bv < sBase64Variants.length; ++bv) { - Base64Variant b64variant = sBase64Variants[bv]; - for (int x = 0; x < LEN_ELEM_MULTIPLE.length; ++x) { - int size = LEN_ELEM_MULTIPLE[x]; - Random r = new Random(size+1); - byte[][] dataTable = generateDataTable(r, size, REPS); - String doc = buildMultiElemDoc(b64variant, dataTable); - // First, get access to root elem - XMLStreamReader2 sr = getElemReader(doc); - - // single-byte check should uncover problems - for (int i = 0; i < REPS; ++i) { - assertTokenType(START_ELEMENT, sr.next()); - _verifyElemData1(sr, b64variant, dataTable[i]); - // Should not have hit END_ELEMENT yet - if (sr.getEventType() == END_ELEMENT) { - fail("Should not have yet advanced to END_ELEMENT, when decoding not finished"); - } - // but needs to if we advance; can see CHARACTERS in between tho - while (CHARACTERS == sr.next()) { } - assertTokenType(END_ELEMENT, sr.getEventType()); - } - sr.close(); - } - } - } - - /** - * Test that uses 'mixed' segments (CHARACTERS and CDATA), in - * which base64 units (4 chars producing 3 bytes) can be split - * between segments. - *

- * It is not clear if and how non-padding variants could - * be mixed, so this test only covers padding variants - * (it is likely that mixing would make sense whatsoever; but - * at least additional spacing would have to be provided) - */ - public void testBinaryMixedSegments() throws XMLStreamException - { - // We'll do just one long test - Random r = new Random(123); - final int SIZE = 128000; - byte[] data = generateData(r, SIZE); - char[] buffer = new char[100]; - - /* 20-Nov-2008, tatus: Let's test all available base64 - * variants too: - */ - for (int bv = 0; bv < sPaddingVariants.length; ++bv) { - Base64Variant b64variant = sPaddingVariants[bv]; - StringBuffer b64 = new StringBuffer(data.length * 2); - - /* Ok, first, let's first just generate long String of base64 - * data: - */ - int ptr = 0; - do { - int chunkLen = 1 + (r.nextInt() & 0x7); - AsciiValueEncoder enc = new ValueEncoderFactory().getEncoder(b64variant, data, ptr, chunkLen); - ptr += chunkLen; - int len = enc.encodeMore(buffer, 0, buffer.length); - b64.append(buffer, 0, len); - } while (b64.length() < SIZE); - // And then create document, with split content - - final int byteLen = ptr; - String refDoc = ""+b64.toString()+""; - - // But first: let's verify content is encoded correctly: - { - XMLStreamReader2 sr = getElemReader(refDoc); - _verifyElemData(sr, b64variant, r, data, byteLen, METHOD_FULL); - sr.close(); - } - - StringBuffer sb = new StringBuffer(b64.length() * 2); - sb.append(""); - - ptr = 0; - boolean cdata = false; - - while (ptr < b64.length()) { - int segLen = 1 + (r.nextInt() & 0x7); - if (cdata) { - sb.append(""); - } - cdata = !cdata; - } - sb.append(""); - String actualDoc = sb.toString(); - - XMLStreamReader2 sr = getElemReader(actualDoc); - // should be enough to verify byte-by-byte? - _verifyElemData(sr, b64variant, r, data, byteLen, METHOD_SINGLE); - sr.close(); - } - } - - private void _testBinaryElem(int readMethod, boolean addNoise) - throws XMLStreamException - { - for (int bv = 0; bv < sBase64Variants.length; ++bv) { - Base64Variant b64variant = sBase64Variants[bv]; - for (int x = 0; x < LEN_ELEM.length; ++x) { - int size = LEN_ELEM[x]; - Random r = new Random(size); - byte[] data = generateData(r, size); - String doc = buildDoc(b64variant, r, data, addNoise); - XMLStreamReader2 sr = getElemReader(doc); - _verifyElemData(sr, b64variant, r, data, data.length, readMethod); - sr.close(); - } - } - } - - private void _verifyElemData(XMLStreamReader2 sr, Base64Variant b64variant, Random r, byte[] data, int dataLen, int readMethod) - throws XMLStreamException - { - switch (readMethod) { - case METHOD_SINGLE: // minimal reads, single byte at a time - { - byte[] buffer = new byte[5]; - int ptr = 0; - int count; - - while ((count = sr.readElementAsBinary(buffer, 2, 1, b64variant)) > 0) { - assertEquals(1, count); - if ((ptr+1) < dataLen) { - if (data[ptr] != buffer[2]) { - fail("(base64 variant "+b64variant+") Corrupt decode at #"+ptr+"/"+dataLen+", expected "+displayByte(data[ptr])+", got "+displayByte(buffer[2])); - } - } - ++ptr; - } - if (ptr != dataLen) { - fail("(base64 variant "+b64variant+") Expected to get "+dataLen+" bytes, got "+ptr); - } - } - break; - case METHOD_FULL: // full read - { - byte[] buffer = new byte[dataLen + 100]; - /* Let's assume reader will actually read it all: - * while not absolutely required, in practice it should - * happen. If this is not true, need to change unit - * test to reflect it. - */ - int count = sr.readElementAsBinary(buffer, 3, buffer.length-3, b64variant); - assertEquals(dataLen, count); - for (int i = 0; i < dataLen; ++i) { - if (buffer[3+i] != data[i]) { - fail("(base64 variant "+b64variant+") Corrupt decode at #"+i+", expected "+displayByte(data[i])+", got "+displayByte(buffer[3+i])); - } - } - } - break; - - case METHOD_FULL_CONVENIENT: // full read - { - byte[] result = sr.getElementAsBinary(b64variant); - assertEquals(dataLen, result.length); - for (int i = 0; i < dataLen; ++i) { - if (result[i] != data[i]) { - fail("(base64 variant "+b64variant+") Corrupt decode at #"+i+", expected "+displayByte(data[i])+", got "+displayByte(result[i])); - } - } - } - break; - - case METHOD_2BYTES: // 2 bytes at a time - default: // misc sizes - { - boolean random = (readMethod != METHOD_2BYTES); - - byte[] buffer = new byte[200]; - int ptr = 0; - - while (true) { - int len = random ? (20 + (r.nextInt() & 127)) : 2; - int count = sr.readElementAsBinary(buffer, 0, len, b64variant); - if (count < 0) { - break; - } - if ((ptr + count) > dataLen) { - ptr += count; - break; - } - for (int i = 0; i < count; ++i) { - if (data[ptr+i] != buffer[i]) { - fail("(base64 variant "+b64variant+") Corrupt decode at #"+(ptr+i)+"/"+dataLen+" (read len: "+len+"; got "+count+"), expected "+displayByte(data[ptr+i])+", got "+displayByte(buffer[i])); - } - } - ptr += count; - } - - if (ptr != dataLen) { - fail("(base64 variant "+b64variant+") Expected "+dataLen+" bytes, got "+ptr); - } - } - } - assertTokenType(END_ELEMENT, sr.getEventType()); - } - - private void _verifyElemData1(XMLStreamReader2 sr, Base64Variant b64variant, byte[] data) - throws XMLStreamException - { - byte[] buffer = new byte[5]; - assertEquals(1, sr.readElementAsBinary(buffer, 1, 1, b64variant)); - assertEquals(data[0], buffer[1]); - } - - /* - /////////////////////////////////////////////////////////////////////// - // Test methods, elem, invalid - /////////////////////////////////////////////////////////////////////// - */ - - /** - * Rules for padding are quite simple: you can use one or two padding - * characters, which indicate 1 or 2 bytes instead full 3 for the - * decode unit. - */ - public void testInvalidElemPadding() - throws XMLStreamException - { - // Let's try out couple of arbitrary broken ones... - final byte[] resultBuffer = new byte[20]; - - // Hmmh. Here we need to skip testing of non-padded variants... - // (ideally would also test non-padding ones, but using different method) - for (int bv = 0; bv < sPaddingVariants.length; ++bv) { - Base64Variant b64variant = sPaddingVariants[bv]; - for (int i = 0; i < INVALID_PADDING.length; ++i) { - String doc = ""+INVALID_PADDING[i]+""; - XMLStreamReader2 sr = getElemReader(doc); - try { - /*int count = */ sr.readElementAsBinary(resultBuffer, 0, resultBuffer.length, b64variant); - fail("Should have received an exception for invalid padding"); - } catch (TypedXMLStreamException ex) { - // any way to check that it's the excepted message? not right now - } - sr.close(); - } - } - } - - /** - * Whitespace is allowed within base64, but only to separate 4 characters - * base64 units. Ideally (and by the spec) they should be used every - * 76 characters (== every 19 units), but it'd be hard to enforce this - * as well as fail on much of existing supposedly base64 compliant - * systems. So, we will just verify that white space can not be used - * within 4 char units. - */ - public void testInvalidWhitespace() - throws XMLStreamException - { - // Let's try out couple of arbitrary broken ones... - final byte[] resultBuffer = new byte[20]; - - for (int bv = 0; bv < sBase64Variants.length; ++bv) { - Base64Variant b64variant = sBase64Variants[bv]; - for (int i = 0; i < INVALID_WS.length; ++i) { - String doc = ""+INVALID_WS[i]+""; - XMLStreamReader2 sr = getElemReader(doc); - try { - /*int count = */ sr.readElementAsBinary(resultBuffer, 0, resultBuffer.length, b64variant); - fail("Should have received an exception for white space used 'inside' 4-char base64 unit"); - } catch (TypedXMLStreamException ex) { - // any way to check that it's the excepted message? not right now - } - sr.close(); - } - } - } - - public void testInvalidWeirdChars() - throws XMLStreamException - { - final byte[] resultBuffer = new byte[20]; - - for (int bv = 0; bv < sBase64Variants.length; ++bv) { - Base64Variant b64variant = sBase64Variants[bv]; - for (int i = 0; i < INVALID_WEIRD_CHARS.length; ++i) { - String doc = ""+INVALID_WEIRD_CHARS[i]+""; - XMLStreamReader2 sr = getElemReader(doc); - try { - /*int count = */ sr.readElementAsBinary(resultBuffer, 0, resultBuffer.length, b64variant); - fail("Should have received an exception for invalid base64 character"); - } catch (TypedXMLStreamException ex) { - // any way to check that it's the excepted message? not right now - } - sr.close(); - } - } - } - - public void testIncompleteInvalidElem() - throws XMLStreamException - { - // Let's just try with short partial segments, data used doesn't matter - final byte[] data = new byte[6]; - final byte[] resultBuffer = new byte[20]; - // plus also skip non-padded variants, for now - - // So first we'll encode 1 to 6 bytes as base64 - for (int bv = 0; bv < sPaddingVariants.length; ++bv) { - Base64Variant b64variant = sPaddingVariants[bv]; - for (int i = 1; i <= data.length; ++i) { - AsciiValueEncoder enc = new ValueEncoderFactory().getEncoder(b64variant, data, 0, i); - char[] cbuf = new char[20]; - int clen = enc.encodeMore(cbuf, 0, cbuf.length); - - // and use all byte last 1, 2 or 3 chars - for (int j = 1; j <= 3; ++j) { - int testLen = clen-j; - StringBuffer sb = new StringBuffer(); - sb.append(""); - sb.append(cbuf, 0, testLen); - sb.append(""); - - XMLStreamReader2 sr = getElemReader(sb.toString()); - try { - /*int count = */ sr.readElementAsBinary(resultBuffer, 0, resultBuffer.length, b64variant); - fail("Should have received an exception for incomplete base64 unit"); - } catch (TypedXMLStreamException ex) { - // any way to check that it's the excepted message? not right now - } - sr.close(); - } - } - } - } - - /* - /////////////////////////////////////////////////////////////////////// - // Test methods, attr, valid - /////////////////////////////////////////////////////////////////////// - */ - - /** - * API to access attribute values is much simpler; hence fewer - * things need testing - */ - public void testBinaryAttrValid() throws XMLStreamException - { - final int REPS = 3; - for (int j = 0; j < REPS; ++j) { - for (int bv = 0; bv < sBase64Variants.length; ++bv) { - Base64Variant b64variant = sBase64Variants[bv]; - for (int i = 0; i < LEN_ATTR.length; ++i) { - int size = LEN_ATTR[i]; - byte[] data = generateData(new Random(size), size); - char[] buffer = new char[4 + (data.length * 3 / 2)]; - AsciiValueEncoder enc = new ValueEncoderFactory().getEncoder(b64variant, data, 0, data.length); - int len = enc.encodeMore(buffer, 0, buffer.length); - StringBuilder sb = new StringBuilder(buffer.length + 32); - sb.append(""); - XMLStreamReader2 sr = getElemReader(sb.toString()); - byte[] actData = null; - try { - actData = sr.getAttributeAsBinary(0, b64variant); - } catch (TypedXMLStreamException e) { - fail("Failed for variant "+b64variant+", input '"+e.getLexical()+"': "+e.getMessage()); - } - - assertNotNull(actData); - assertEquals(data.length, actData.length); - for (int x = 0; x < data.length; ++x) { - if (data[x] != actData[x]) { - fail("Corrupt decode at #"+x+"/"+data.length+", expected "+displayByte(data[x])+", got "+displayByte(actData[x])); - } - } - } - } - } - } - - /* - /////////////////////////////////////////////////////////////////////// - // Test methods, attr, invalid - /////////////////////////////////////////////////////////////////////// - */ - - public void testInvalidAttrPadding() - throws XMLStreamException - { - // Hmmh. Here we need to skip testing of non-padded variants... - for (int bv = 0; bv < sPaddingVariants.length; ++bv) { - Base64Variant b64variant = sPaddingVariants[bv]; - - for (int i = 0; i < INVALID_PADDING.length; ++i) { - String doc = ""; - XMLStreamReader2 sr = getElemReader(doc); - try { - /*byte[] data = */ sr.getAttributeAsBinary(0, b64variant); - fail("Should have received an exception for invalid padding"); - } catch (TypedXMLStreamException ex) { - // any way to check that it's the excepted message? not right now - } - sr.close(); - } - } - } - - public void testInvalidAttrWhitespace() - throws XMLStreamException - { - for (int bv = 0; bv < sBase64Variants.length; ++bv) { - Base64Variant b64variant = sBase64Variants[bv]; - for (int i = 0; i < INVALID_WS.length; ++i) { - String doc = ""; - XMLStreamReader2 sr = getElemReader(doc); - try { - /*byte[] data = */ sr.getAttributeAsBinary(0, b64variant); - fail("Should have received an exception for white space used 'inside' 4-char base64 unit"); - } catch (TypedXMLStreamException ex) { - // any way to check that it's the excepted message? not right now - } - sr.close(); - } - } - } - - public void testInvalidAttrWeirdChars() - throws XMLStreamException - { - for (int bv = 0; bv < sBase64Variants.length; ++bv) { - Base64Variant b64variant = sBase64Variants[bv]; - for (int i = 0; i < INVALID_WEIRD_CHARS.length; ++i) { - String doc = ""; - XMLStreamReader2 sr = getElemReader(doc); - try { - /*byte[] data = */ sr.getAttributeAsBinary(0, b64variant); - fail("Should have received an exception for invalid base64 character"); - } catch (TypedXMLStreamException ex) { - // any way to check that it's the excepted message? not right now - } - sr.close(); - } - } - } - - public void testInvalidAttrIncomplete() - throws XMLStreamException - { - // Let's just try with short partial segments, data used doesn't matter - final byte[] data = new byte[6]; - // plus also skip non-padded variants, for now - - for (int bv = 0; bv < sPaddingVariants.length; ++bv) { - Base64Variant b64variant = sPaddingVariants[bv]; - - // So first we'll encode 1 to 6 bytes as base64 - for (int i = 1; i <= data.length; ++i) { - AsciiValueEncoder enc = new ValueEncoderFactory().getEncoder(b64variant, data, 0, i); - char[] cbuf = new char[20]; - int clen = enc.encodeMore(cbuf, 0, cbuf.length); - - // and use all byte last 1, 2 or 3 chars - for (int j = 1; j <= 3; ++j) { - int testLen = clen-j; - StringBuffer sb = new StringBuffer(); - sb.append(""); - XMLStreamReader2 sr = getElemReader(sb.toString()); - try { - /*byte[] data = */ sr.getAttributeAsBinary(0, b64variant); - fail("Should have received an exception for incomplete base64 unit"); - } catch (TypedXMLStreamException ex) { - // any way to check that it's the excepted message? not right now - } - sr.close(); - } - } - } - } - - /* - /////////////////////////////////////////////////////////////////////// - // Helper methods - /////////////////////////////////////////////////////////////////////// - */ - - private byte[] generateData(Random r, int size) - { - byte[] result = new byte[size]; - r.nextBytes(result); - return result; - } - - private byte[][] generateDataTable(Random r, int size, int reps) - { - byte[][] table = new byte[reps][]; - for (int i = 0; i < reps; ++i) { - table[i] = generateData(r, size); - } - return table; - } - - private String buildDoc(Base64Variant b64variant, Random r, byte[] data, boolean addNoise) - { - // Let's use base64 codec from RI here: - AsciiValueEncoder enc = new ValueEncoderFactory().getEncoder(b64variant, data, 0, data.length); - - StringBuffer sb = new StringBuffer(data.length * 2); - sb.append(""); - - // Without noise it's quite easy, just need enough space: - if (!addNoise) { - // Base64 adds 33% overhead, but let's be generous - char[] buffer = new char[4 + (data.length * 3 / 2)]; - int len = enc.encodeMore(buffer, 0, buffer.length); - sb.append(buffer, 0, len); - } else { - // but with noise, need bit different approach - char[] buffer = new char[300]; - - while (!enc.isCompleted()) { - int offset = r.nextInt() & 0xF; - int len; - int rn = r.nextInt() & 15; - - switch (rn) { - case 1: - case 2: - case 3: - case 4: - len = rn; - break; - case 5: - case 6: - case 7: - len = 3 + (r.nextInt() & 15); - break; - default: - len = 20 + (r.nextInt() & 127); - break; - } - int end = enc.encodeMore(buffer, offset, offset+len); - - // regular or CDATA? - boolean cdata = r.nextBoolean() && r.nextBoolean(); - - if (cdata) { - sb.append(""); - } - - // Let's add noise 25% of time - if (r.nextBoolean() && r.nextBoolean()) { - sb.append(""); - } else { - sb.append(""); - } - } - } - sb.append(""); - return sb.toString(); - } - - private String buildMultiElemDoc(Base64Variant b64variant, byte[][] dataTable) - { - StringBuffer sb = new StringBuffer(16 + dataTable.length * dataTable[0].length); - sb.append(""); - for (int i = 0; i < dataTable.length; ++i) { - byte[] data = dataTable[i]; - char[] buffer = new char[4 + (data.length * 3 / 2)]; - AsciiValueEncoder enc = new ValueEncoderFactory().getEncoder(b64variant, data, 0, data.length); - int len = enc.encodeMore(buffer, 0, buffer.length); - sb.append(""); - sb.append(buffer, 0, len); - sb.append(""); - } - sb.append(""); - return sb.toString(); - } - - final static String displayByte(byte b) { - return "0x"+Integer.toHexString((int) b & 0xFF); - } -} diff -Nru libwoodstox-java-4.1.3/src/test/stax2/typed/ReaderTestBase.java libwoodstox-java-5.1.0/src/test/stax2/typed/ReaderTestBase.java --- libwoodstox-java-4.1.3/src/test/stax2/typed/ReaderTestBase.java 2012-04-24 04:38:21.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/stax2/typed/ReaderTestBase.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,884 +0,0 @@ -package stax2.typed; - -import java.math.BigDecimal; -import java.math.BigInteger; -import java.util.Random; - -import javax.xml.namespace.QName; -import javax.xml.stream.*; - -import org.codehaus.stax2.*; -import org.codehaus.stax2.typed.*; - -import stax2.BaseStax2Test; - -/** - * Base class that contains set of simple unit tests to verify implementation - * of {@link TypedXMLStreamReader}. Concrete sub-classes are used to - * test both native and wrapped Stax2 implementations. - * - * @author Tatu Saloranta - */ -public abstract class ReaderTestBase - extends BaseStax2Test -{ - final static long TOO_BIG_FOR_INT = ((long) Integer.MAX_VALUE)+1L; - final static long TOO_SMALL_FOR_INT = ((long) Integer.MIN_VALUE)-1L; - - final static BigInteger TOO_BIG_FOR_LONG = BigInteger.valueOf(Long.MAX_VALUE).add(BigInteger.valueOf(123)); - final static BigInteger TOO_SMALL_FOR_LONG = BigInteger.valueOf(Long.MIN_VALUE).subtract(BigInteger.valueOf(123)); - - /* - //////////////////////////////////////// - // Tests for boolean, integral numbers - //////////////////////////////////////// - */ - - public void testSimpleBooleanElem() - throws Exception - { - // simple boolean - checkBooleanElem("true", true); - // with white space normalization - checkBooleanElem("\tfalse\n\r", false); - // Then non9-canonical alternatives - checkBooleanElem("0 \t", false); - checkBooleanElem("\r1", true); - - // And finally invalid ones - checkBooleanElemException("yes"); - /* Although "01" would be valid integer equal to "1", - * it's not a legal boolean nonetheless (as per my reading - * of W3C Schema specs) - */ - checkBooleanElemException("01"); - } - - public void testSimpleBooleanAttr() - throws Exception - { - checkBooleanAttr("", true); - checkBooleanAttr("", false); - checkBooleanAttr("", false); - checkBooleanAttr("", true); - - checkBooleanAttrException(""); - checkBooleanAttrException(""); - } - - public void testMultipleBooleanAttr() - throws Exception - { - XMLStreamReader2 sr = getRootReader(""); - assertEquals(3, sr.getAttributeCount()); - int ix1 = sr.getAttributeIndex("", "a1"); - int ix2 = sr.getAttributeIndex("", "b"); - int ix3 = sr.getAttributeIndex("", "third"); - if (ix1 < 0 || ix2 < 0 || ix3 < 0) { - fail("Couldn't find indexes of attributes: a1="+ix1+", b="+ix2+", third="+ix3); - } - assertTrue(sr.getAttributeAsBoolean(ix1)); - assertFalse(sr.getAttributeAsBoolean(ix2)); - assertFalse(sr.getAttributeAsBoolean(ix3)); - - sr.close(); - } - - public void testSimpleIntElem() - throws Exception - { - checkIntElem("000000000000000000000000012", 12); - - - checkIntElem("0", 0); - // with white space normalization - checkIntElem("291\t", 291); - checkIntElem(" \t1", 1); - checkIntElem("3 ", 3); - checkIntElem(" -7 ", -7); - // with signs, spacing etc - checkIntElem("-1234", -1234); - checkIntElem("+3", 3); - checkIntElem("-0", 0); - checkIntElem("-0000", 0); - checkIntElem("-001", -1); - checkIntElem("+0", 0); - checkIntElem("+0 ", 0); - checkIntElem("+00", 0); - checkIntElem("000000000000000000000000012", 12); - checkIntElem("-00000000", 0); - int v = 1200300400; - checkIntElem(" \r\n+"+v+"", v); - checkIntElem(" "+Integer.MAX_VALUE+"", Integer.MAX_VALUE); - checkIntElem(" "+Integer.MIN_VALUE+"", Integer.MIN_VALUE); - - // And finally invalid ones - checkIntElemException("12a3"); - checkIntElemException("5000100200"); // overflow - checkIntElemException("3100200300"); // overflow - checkIntElemException("-4100200300"); // underflow - checkIntElemException(""+TOO_BIG_FOR_INT+""); // overflow as well - checkIntElemException(""+TOO_SMALL_FOR_INT+""); // underflow as well - checkIntElemException("- "); - checkIntElemException("+"); - checkIntElemException(" -"); - } - - public void testSimpleIntAttr() - throws Exception - { - checkIntAttr("", 0); - checkIntAttr("", 13); - checkIntAttr("", 123); - checkIntAttr("", -12); - checkIntAttr("", 0); - checkIntAttr("", 0); - checkIntAttr("", -12345); - checkIntAttr("", Integer.MAX_VALUE); - checkIntAttr("", Integer.MIN_VALUE); - - checkIntAttrException(""); - checkIntAttrException(""); - checkIntAttrException(""); - checkIntAttrException(""); - checkIntAttrException(""); - checkIntAttrException(""); - } - - public void testMultipleIntAttr() - throws Exception - { - XMLStreamReader2 sr = getRootReader(""); - assertEquals(3, sr.getAttributeCount()); - int ix1 = sr.getAttributeIndex("", "a1"); - int ix2 = sr.getAttributeIndex("", "b"); - int ix3 = sr.getAttributeIndex("", "third"); - if (ix1 < 0 || ix2 < 0 || ix3 < 0) { - fail("Couldn't find indexes of attributes: a1="+ix1+", b="+ix2+", third="+ix3); - } - assertEquals(123456789, sr.getAttributeAsInt(ix1)); - assertEquals(-123456789, sr.getAttributeAsInt(ix2)); - assertEquals(0, sr.getAttributeAsInt(ix3)); - - sr.close(); - } - - public void testSimpleLongElem() - throws Exception - { - checkLongElem("000000000000000000000000012", 12); - - - checkLongElem("0", 0); - // with white space normalization - checkLongElem("10091\t", 10091); - checkLongElem(" \t-1", -1); - checkLongElem("39876 ", 39876); - checkLongElem(" 0701 ", 701); - // with signs, spacing etc - checkLongElem("-1234", -1234); - checkLongElem("+3", 3); - checkLongElem("-0", 0); - checkLongElem("-001", -1); - checkLongElem("+0", 0); - checkLongElem("0000000000000001234567890", 1234567890L); - checkLongElem("-00000000", 0); - long v = 1200300400500600L; - checkLongElem(" \r"+v+"", v); - checkLongElem(" \r\n+"+v+"", v); - v = -1234567890123456789L; - checkLongElem(" \r\n"+v+"", v); - checkLongElem(" "+Long.MAX_VALUE+"", Long.MAX_VALUE); - checkLongElem(" "+Long.MIN_VALUE+"", Long.MIN_VALUE); - - // And finally invalid ones - checkLongElemException("12a3"); - checkLongElemException(""+TOO_BIG_FOR_LONG+""); // overflow as well - checkLongElemException(""+TOO_SMALL_FOR_LONG+""); // underflow as well - checkLongElemException("- "); - checkLongElemException("+"); - checkLongElemException(" -"); - } - - public void testSimpleLongAttr() - throws Exception - { - checkLongAttr("", 0); - checkLongAttr("", 13); - checkLongAttr("", 123); - checkLongAttr("", -12); - checkLongAttr("", 0); - checkLongAttr("", 0); - checkLongAttr("", -12345); - checkLongAttr("", Long.MAX_VALUE); - checkLongAttr("", Long.MIN_VALUE); - - checkLongAttrException(""); - checkLongAttrException(""); - checkLongAttrException(""); - checkLongAttrException(""); - checkLongAttrException(""); - checkLongAttrException(""); - } - - public void testMultipleLongAttr() - throws Exception - { - XMLStreamReader2 sr = getRootReader(""); - assertEquals(3, sr.getAttributeCount()); - int ix1 = sr.getAttributeIndex("", "a1"); - int ix2 = sr.getAttributeIndex("", "b"); - int ix3 = sr.getAttributeIndex("", "third"); - if (ix1 < 0 || ix2 < 0 || ix3 < 0) { - fail("Couldn't find indexes of attributes: a1="+ix1+", b="+ix2+", third="+ix3); - } - assertEquals(12345678900L, sr.getAttributeAsLong(ix1)); - assertEquals(-12345678900L, sr.getAttributeAsLong(ix2)); - assertEquals(0L, sr.getAttributeAsLong(ix3)); - - sr.close(); - } - - /* - //////////////////////////////////////// - // Tests for floating point numbers - //////////////////////////////////////// - */ - - public void testSimpleFloatElem() - throws Exception - { - checkFloatElem("0.0", 0.0f); - checkFloatElem("0", 0.0f); - // with white space normalization - checkFloatElem("1.0\t", 1.0f); - checkFloatElem(" \t-0.1", -0.1f); - checkFloatElem("+.001 ", 0.001f); - checkFloatElem(" -3.1415 ", -3.1415f); - checkFloatElem("27.3E-01", 2.73e-01f); - checkFloatElem(" "+Float.MAX_VALUE+"", Float.MAX_VALUE); - checkFloatElem(" "+Float.MIN_VALUE+"", Float.MIN_VALUE); - checkFloatElem(" NaN", Float.NaN); - checkFloatElem("INF ", Float.POSITIVE_INFINITY); - checkFloatElem("\t-INF\t", Float.NEGATIVE_INFINITY); - - // And finally invalid ones - checkFloatElemException("abcd"); - checkFloatElemException("- "); - checkFloatElemException("+"); - checkFloatElemException(" -"); - checkFloatElemException("1e"); - } - - public void testSimpleFloatAttr() - throws Exception - { - checkFloatAttr("", 0.1f); - checkFloatAttr("", 13.23f); - checkFloatAttr("", 0.123f); - checkFloatAttr("", -12.03f); - checkFloatAttr("", 0.0f); - checkFloatAttr("", 0.0f); - checkFloatAttr("", -12345f); - checkFloatAttr("", Float.MAX_VALUE); - checkFloatAttr("", Float.MIN_VALUE); - checkFloatAttr("", Float.NaN); - checkFloatAttr("", Float.POSITIVE_INFINITY); - checkFloatAttr("", Float.NEGATIVE_INFINITY); - - checkFloatAttrException(""); - checkFloatAttrException(""); - checkFloatAttrException(""); - checkFloatAttrException(""); - } - - public void testMultipleFloatAttr() - throws Exception - { - XMLStreamReader2 sr = getRootReader(""); - assertEquals(3, sr.getAttributeCount()); - int ix1 = sr.getAttributeIndex("", "a1"); - int ix2 = sr.getAttributeIndex("", "b"); - int ix3 = sr.getAttributeIndex("", "third"); - if (ix1 < 0 || ix2 < 0 || ix3 < 0) { - fail("Couldn't find indexes of attributes: a1="+ix1+", b="+ix2+", third="+ix3); - } - assertEquals(-123.456f, sr.getAttributeAsFloat(ix1)); - assertEquals(0.003f, sr.getAttributeAsFloat(ix2)); - assertEquals(-0.0f, sr.getAttributeAsFloat(ix3)); - - sr.close(); - } - - public void testSimpleDoubleElem() - throws Exception - { - checkDoubleElem("0.0", 0.0f); - checkDoubleElem("0", 0.0f); - // with white space normalization - checkDoubleElem("1.0\t", 1.0f); - checkDoubleElem(" \t-0.1", -0.1f); - checkDoubleElem("+.001 ", 0.001f); - checkDoubleElem(" -3.1415 ", -3.1415f); - checkDoubleElem("27.3E-01", 2.73e-01f); - checkDoubleElem(" "+Double.MAX_VALUE+"", Double.MAX_VALUE); - checkDoubleElem(" "+Double.MIN_VALUE+"", Double.MIN_VALUE); - checkDoubleElem(" NaN", Double.NaN); - checkDoubleElem("INF ", Double.POSITIVE_INFINITY); - checkDoubleElem("\t-INF\t", Double.NEGATIVE_INFINITY); - - // And finally invalid ones - checkDoubleElemException("abcd"); - checkDoubleElemException("- "); - checkDoubleElemException("+"); - checkDoubleElemException(" -"); - checkDoubleElemException("1e"); - } - - public void testSimpleDoubleAttr() - throws Exception - { - checkDoubleAttr("", 0.1f); - checkDoubleAttr("", 13.23f); - checkDoubleAttr("", 0.123f); - checkDoubleAttr("", -12.03f); - checkDoubleAttr("", 0.0f); - checkDoubleAttr("", 0.0f); - checkDoubleAttr("", -12345f); - checkDoubleAttr("", Double.MAX_VALUE); - checkDoubleAttr("", Double.MIN_VALUE); - checkDoubleAttr("", Double.NaN); - checkDoubleAttr("", Double.POSITIVE_INFINITY); - checkDoubleAttr("", Double.NEGATIVE_INFINITY); - - checkDoubleAttrException(""); - checkDoubleAttrException(""); - checkDoubleAttrException(""); - checkDoubleAttrException(""); - } - - public void testMultipleDoubleAttr() - throws Exception - { - XMLStreamReader2 sr = getRootReader(""); - assertEquals(3, sr.getAttributeCount()); - int ix1 = sr.getAttributeIndex("", "a1"); - int ix2 = sr.getAttributeIndex("", "b"); - int ix3 = sr.getAttributeIndex("", "third"); - if (ix1 < 0 || ix2 < 0 || ix3 < 0) { - fail("Couldn't find indexes of attributes: a1="+ix1+", b="+ix2+", third="+ix3); - } - assertEquals(-123.456f, sr.getAttributeAsDouble(ix1)); - assertEquals(0.003f, sr.getAttributeAsDouble(ix2)); - assertEquals(-0.0f, sr.getAttributeAsDouble(ix3)); - - sr.close(); - } - - /* - //////////////////////////////////////// - // Tests for "big" numbers - //////////////////////////////////////// - */ - - /** - * With unlimited length BigInteger, it's easier to just generate - * very big (long) numbers, and test variability that way. - */ - public void testBigInteger() - throws Exception - { - /* Let's just generate reasonably big (up to 200 digits) - * numbers, and test some variations - */ - BigInteger I = BigInteger.valueOf(3); - Random rnd = new Random(1); - for (int i = 1; i < 200; ++i) { - // First, regular elem content - String doc; - String istr = I.toString(); - - switch (i % 4) { // some white space variations - case 0: - istr = " \t "+istr; - break; - case 1: - istr = istr+"\r"; - break; - case 2: - istr = "\n"+istr+" "; - break; - } - XMLStreamReader2 sr = getRootReader(""+istr+""); - assertEquals(I, sr.getElementAsInteger()); - sr.close(); - // Then attribute - doc = ""; - sr = getRootReader(doc); - assertEquals(I, sr.getAttributeAsInteger(0)); - sr.close(); - - // And finally, invalid - istr = I.toString(); - - switch (i % 3) { - case 0: - istr = "ab"+istr; - break; - case 1: - istr = istr+"!"; - break; - case 2: - istr = istr+".0"; - break; - } - - sr = getRootReader(""+istr+""); - try { - sr.getElementAsInteger(); - fail("Expected exception for invalid input ["+doc+"]"); - } catch (TypedXMLStreamException xse) { ; // good - } - sr.close(); - - sr = getRootReader(""); - try { - sr.getAttributeAsInteger(0); - fail("Expected exception for invalid input ["+doc+"]"); - } catch (TypedXMLStreamException xse) { ; // good - } - sr.close(); - - // And then, let's just multiply by 10, add a new digit - I = I.multiply(BigInteger.valueOf(10)).add(BigInteger.valueOf(rnd.nextInt() & 0xF)); - - // Plus switch sign every now and then - if ((i % 3) == 0) { - I = I.negate(); - } - } - } - - /** - * As with BigInteger, we better use number generation with - * BigDecimal. - */ - public void testBigDecimal() - throws Exception - { - BigDecimal D = BigDecimal.valueOf(1L); - Random rnd = new Random(6); - // 200 digits seems ok here too - for (int i = 1; i < 200; ++i) { - // First, regular elem content - String doc; - String istr = D.toString(); - - switch (i % 4) { // some white space variations - case 0: - istr = "\t"+istr; - break; - case 1: - istr = istr+" "; - break; - case 2: - istr = " "+istr+"\r"; - break; - } - XMLStreamReader2 sr = getRootReader(""+istr+""); - assertEquals(D, sr.getElementAsDecimal()); - sr.close(); - // Then attribute - doc = ""; - sr = getRootReader(doc); - assertEquals(D, sr.getAttributeAsDecimal(0)); - sr.close(); - - // And finally, invalid - istr = D.toString(); - - switch (i % 3) { - case 0: - istr = "_x"+istr; - break; - case 1: - istr = istr+"?"; - break; - case 2: - istr = istr+"e"; - break; - } - - sr = getRootReader(""+istr+""); - try { - sr.getElementAsDecimal(); - fail("Expected exception for invalid input ["+doc+"]"); - } catch (TypedXMLStreamException xse) { ; // good - } - sr.close(); - - sr = getRootReader(""); - try { - sr.getAttributeAsDecimal(0); - fail("Expected exception for invalid input ["+doc+"]"); - } catch (TypedXMLStreamException xse) { ; // good - } - sr.close(); - - // Ok, then, add a small integer, divide by 10 to generate digits - D = D.add(BigDecimal.valueOf(rnd.nextInt() & 0xF)).divide(BigDecimal.valueOf(10L)); - - // Plus switch sign every now and then - if ((i % 3) == 0) { - D = D.negate(); - } - } - } - - /* - //////////////////////////////////////// - // Tests for name type(s) - //////////////////////////////////////// - */ - - public void testValidQNameElem() - throws Exception - { - String URI = "http://test.org/"; - String XML = "ns:name "; - XMLStreamReader2 sr = getRootReader(XML); - QName n = sr.getElementAsQName(); - assertNotNull(n); - assertEquals("name", n.getLocalPart()); - assertEquals("ns", n.getPrefix()); - assertEquals(URI, n.getNamespaceURI()); - sr.close(); - } - - public void testInvalidQNameElemUnbound() - throws Exception - { - XMLStreamReader2 sr = getRootReader("ns:name "); - // First, unbound namespace prefix - try { - /*QName n =*/ sr.getElementAsQName(); - fail("Expected an exception for unbound QName prefix"); - } catch (TypedXMLStreamException tex) { } - sr.close(); - } - - public void testInvalidQNameElemBadChars() - throws Exception - { - XMLStreamReader2 sr = getRootReader("ns:na?me"); - try { - /*QName n =*/ sr.getElementAsQName(); - fail("Expected an exception for invalid QName (non-xml-name char in the middle)"); - } catch (TypedXMLStreamException tex) { } - sr.close(); - } - - public void testValidQNameAttr() - throws Exception - { - String URI = "http://test.org/"; - String XML = ""; - XMLStreamReader2 sr = getRootReader(XML); - QName n = sr.getAttributeAsQName(0); - assertNotNull(n); - assertEquals("x1", n.getLocalPart()); - assertEquals("abc", n.getPrefix()); - assertEquals(URI, n.getNamespaceURI()); - sr.close(); - } - - public void testInvalidQNameAttrUnbound() - throws Exception - { - XMLStreamReader2 sr = getRootReader(""); - // First, unbound namespace prefix - try { - /*QName n =*/ sr.getAttributeAsQName(0); - fail("Expected an exception for unbound QName prefix"); - } catch (TypedXMLStreamException tex) { } - sr.close(); - } - - public void testInvalidQNameAttrBadChars() - throws Exception - { - XMLStreamReader2 sr = getRootReader(""); - try { - /*QName n =*/ sr.getAttributeAsQName(0); - fail("Expected an exception for invalid QName (non-xml-name char in the middle)"); - } catch (TypedXMLStreamException tex) { } - sr.close(); - } - - /* - //////////////////////////////////////// - // Private methods, second-level tests - //////////////////////////////////////// - */ - - private void checkBooleanElem(String doc, boolean expState) - throws XMLStreamException - { - XMLStreamReader2 sr = getRootReader(doc); - assertEquals(expState, sr.getElementAsBoolean()); - sr.close(); - } - - private void checkBooleanAttr(String doc, boolean expState) - throws XMLStreamException - { - XMLStreamReader2 sr = getRootReader(doc); - // Assumption is that there's just one attribute... - boolean actState = sr.getAttributeAsBoolean(0); - assertEquals(expState, actState); - sr.close(); - } - - private void checkBooleanElemException(String doc) - throws XMLStreamException - { - XMLStreamReader2 sr = getRootReader(doc); - try { - /*boolean b =*/ sr.getElementAsBoolean(); - fail("Expected exception for invalid input ["+doc+"]"); - } catch (TypedXMLStreamException xse) { - ; // good - } - } - - private void checkBooleanAttrException(String doc) - throws XMLStreamException - { - XMLStreamReader2 sr = getRootReader(doc); - try { - /*boolean b =*/ sr.getAttributeAsBoolean(0); - fail("Expected exception for invalid input ["+doc+"]"); - } catch (TypedXMLStreamException xse) { - ; // good - } - } - - private void checkIntElem(String doc, int expState) - throws XMLStreamException - { - XMLStreamReader2 sr = getRootReader(doc); - assertEquals(expState, sr.getElementAsInt()); - sr.close(); - } - - private void checkIntAttr(String doc, int expState) - throws XMLStreamException - { - XMLStreamReader2 sr = getRootReader(doc); - // Assumption is that there's just one attribute... - int actState = sr.getAttributeAsInt(0); - assertEquals(expState, actState); - sr.close(); - } - - private void checkIntElemException(String doc) - throws XMLStreamException - { - XMLStreamReader2 sr = getRootReader(doc); - try { - /*int b =*/ sr.getElementAsInt(); - fail("Expected exception for invalid input ["+doc+"]"); - } catch (TypedXMLStreamException xse) { - ; // good - } - } - - private void checkIntAttrException(String doc) - throws XMLStreamException - { - XMLStreamReader2 sr = getRootReader(doc); - try { - /*int b =*/ sr.getAttributeAsInt(0); - fail("Expected exception for invalid input ["+doc+"]"); - } catch (TypedXMLStreamException xse) { - ; // good - } - } - - private void checkLongElem(String doc, long expState) - throws XMLStreamException - { - XMLStreamReader2 sr = getRootReader(doc); - assertEquals(expState, sr.getElementAsLong()); - sr.close(); - } - - private void checkLongAttr(String doc, long expState) - throws XMLStreamException - { - XMLStreamReader2 sr = getRootReader(doc); - // Assumption is that there's just one attribute... - long actState = sr.getAttributeAsLong(0); - assertEquals(expState, actState); - sr.close(); - } - - private void checkLongElemException(String doc) - throws XMLStreamException - { - XMLStreamReader2 sr = getRootReader(doc); - try { - /*long b =*/ sr.getElementAsLong(); - fail("Expected exception for invalid input ["+doc+"]"); - } catch (TypedXMLStreamException xse) { - ; // good - } - } - - private void checkLongAttrException(String doc) - throws XMLStreamException - { - XMLStreamReader2 sr = getRootReader(doc); - try { - /*long b =*/ sr.getAttributeAsLong(0); - fail("Expected exception for invalid input ["+doc+"]"); - } catch (TypedXMLStreamException xse) { - ; // good - } - } - - private void checkFloatElem(String doc, float expState) - throws XMLStreamException - { - XMLStreamReader2 sr = getRootReader(doc); - assertEquals(expState, sr.getElementAsFloat()); - sr.close(); - } - - private void checkFloatAttr(String doc, float expState) - throws XMLStreamException - { - XMLStreamReader2 sr = getRootReader(doc); - // Assumption is that there's just one attribute... - float actState = sr.getAttributeAsFloat(0); - assertEquals(expState, actState); - sr.close(); - } - - private void checkFloatElemException(String doc) - throws XMLStreamException - { - XMLStreamReader2 sr = getRootReader(doc); - try { - /*float b =*/ sr.getElementAsFloat(); - fail("Expected exception for invalid input ["+doc+"]"); - } catch (TypedXMLStreamException xse) { - ; // good - } - } - - private void checkFloatAttrException(String doc) - throws XMLStreamException - { - XMLStreamReader2 sr = getRootReader(doc); - try { - /*float b =*/ sr.getAttributeAsFloat(0); - fail("Expected exception for invalid input ["+doc+"]"); - } catch (TypedXMLStreamException xse) { - ; // good - } - } - - private void checkDoubleElem(String doc, double expState) - throws XMLStreamException - { - XMLStreamReader2 sr = getRootReader(doc); - assertEquals(expState, sr.getElementAsDouble()); - sr.close(); - } - - private void checkDoubleAttr(String doc, double expState) - throws XMLStreamException - { - XMLStreamReader2 sr = getRootReader(doc); - // Assumption is that there's just one attribute... - double actState = sr.getAttributeAsDouble(0); - assertEquals(expState, actState); - sr.close(); - } - - private void checkDoubleElemException(String doc) - throws XMLStreamException - { - XMLStreamReader2 sr = getRootReader(doc); - try { - /*double b =*/ sr.getElementAsDouble(); - fail("Expected exception for invalid input ["+doc+"]"); - } catch (TypedXMLStreamException xse) { - ; // good - } - } - - private void checkDoubleAttrException(String doc) - throws XMLStreamException - { - XMLStreamReader2 sr = getRootReader(doc); - try { - /*double b =*/ sr.getAttributeAsDouble(0); - fail("Expected exception for invalid input ["+doc+"]"); - } catch (TypedXMLStreamException xse) { - ; // good - } - } - - /* - //////////////////////////////////////// - // Abstract methods - //////////////////////////////////////// - */ - - protected abstract XMLStreamReader2 getReader(String contents) - throws Exception; - - /* - //////////////////////////////////////// - // Private methods - //////////////////////////////////////// - */ - - private void assertEquals(float a, float b) - { - if (Float.isNaN(a)) { - assertTrue(Float.isNaN(b)); - } else if (a != b) { - assertEquals(a, b, 1000.0f); // just to make it fail - } - } - - private void assertEquals(double a, double b) - { - if (Double.isNaN(a)) { - assertTrue(Double.isNaN(b)); - } else if (a != b) { - assertEquals(a, b, 1000.0f); // just to make it fail - } - } - - // XMLStreamReader2 extends TypedXMLStreamReader - protected XMLStreamReader2 getRootReader(String str) - throws XMLStreamException - { - XMLStreamReader2 sr; - try { - sr = getReader(str); - } catch (XMLStreamException xse) { - throw xse; - } catch (Exception e) { - throw new XMLStreamException(e); - } - assertTokenType(START_DOCUMENT, sr.getEventType()); - while (sr.next() != START_ELEMENT) { } - assertTokenType(START_ELEMENT, sr.getEventType()); - return sr; - } -} diff -Nru libwoodstox-java-4.1.3/src/test/stax2/typed/TestBinaryRoundTrip.java libwoodstox-java-5.1.0/src/test/stax2/typed/TestBinaryRoundTrip.java --- libwoodstox-java-4.1.3/src/test/stax2/typed/TestBinaryRoundTrip.java 2012-04-24 04:38:21.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/stax2/typed/TestBinaryRoundTrip.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,108 +0,0 @@ -package stax2.typed; - -import java.io.*; -import java.util.Arrays; - -import javax.xml.stream.*; - -import org.codehaus.stax2.*; -import org.codehaus.stax2.typed.*; - -import stax2.BaseStax2Test; - -public class TestBinaryRoundTrip - extends BaseStax2Test -{ - /** - * Test to verify [WSTX-224]. Note that problems occur only when - * in coalescing mode. - */ - public void testWstx224() throws Exception - { - Base64Variant bv = Base64Variants.MIME; - ByteArrayOutputStream bos = new ByteArrayOutputStream(); - XMLStreamWriter2 writer = getTypedWriter(bos); - byte[] data = new byte[2990]; - // contents shouldn't matter a lot, but: - Arrays.fill(data, (byte) 33); - - writer.writeStartDocument(); - writer.writeStartElement("doc"); - writer.writeStartElement("data"); - writer.writeBinary(bv, data, 0, data.length); - - writer.writeEndElement(); - writer.writeEndElement(); - - writer.writeEndDocument(); - writer.close(); - - byte[] xml = bos.toByteArray(); - - // First: using explicit reads - _doTest224(data, xml, bv, false); - _doTest224(data, xml, bv, true); - } - - private void _doTest224(byte[] data, byte[] xml, Base64Variant bv, boolean useConvAccessor) - throws XMLStreamException - { - XMLStreamReader2 reader = getReader(xml); - byte[] result = null; - while (reader.hasNext()) { - if (reader.next() == XMLStreamConstants.START_ELEMENT && "data".equals(reader.getLocalName())) { - result = _readBinary(reader, bv, xml.length, useConvAccessor); - break; - } - } - assertNotNull(result); - assertEquals(data.length, result.length); - for (int i = 0; i < data.length; ++i) { - if (data[i] != result[i]) { - fail("Data differs at offset #"+i+"; expected "+data[i]+", got "+result[i]); - } - } - } - - private byte[] _readBinary(XMLStreamReader2 sr, Base64Variant bv, - int expSize, - boolean useConvenienceMethod) - throws XMLStreamException - { - // Simplest: just use aggregating... - if (useConvenienceMethod) { - return sr.getElementAsBinary(bv); - } - - byte[] buffer = new byte[expSize+100]; - int offset = 0; - - while (offset < buffer.length) { - int count = sr.readElementAsBinary(buffer, offset, buffer.length-offset, bv); - if (count < 0) { - break; - } - offset += count; - } - byte[] result = new byte[offset]; - System.arraycopy(buffer, 0, result, 0, offset); - return result; - } - - private XMLStreamReader2 getReader(byte[] data) - throws XMLStreamException - { - XMLInputFactory f = getInputFactory(); - setCoalescing(f, true); - setNamespaceAware(f, true); - return (XMLStreamReader2) f.createXMLStreamReader(new ByteArrayInputStream(data)); - } - - protected XMLStreamWriter2 getTypedWriter(ByteArrayOutputStream out) - throws XMLStreamException - { - XMLOutputFactory outf = getOutputFactory(); - return (XMLStreamWriter2) outf.createXMLStreamWriter(out, "UTF-8"); - } -} - diff -Nru libwoodstox-java-4.1.3/src/test/stax2/typed/TestDOMArrayReader.java libwoodstox-java-5.1.0/src/test/stax2/typed/TestDOMArrayReader.java --- libwoodstox-java-4.1.3/src/test/stax2/typed/TestDOMArrayReader.java 2012-04-24 04:38:21.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/stax2/typed/TestDOMArrayReader.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,41 +0,0 @@ -package stax2.typed; - -import java.io.StringReader; - -import javax.xml.parsers.*; -import javax.xml.stream.*; -import javax.xml.transform.dom.DOMSource; - -import org.w3c.dom.Document; -import org.xml.sax.InputSource; - -import org.codehaus.stax2.XMLStreamReader2; - -/** - * Stax2 Typed Access API basic reader tests for array handling, - * using native Stax2 typed reader implementation. - */ -public class TestDOMArrayReader - extends ReaderArrayTestBase -{ - protected XMLStreamReader2 getReader(String contents) - throws XMLStreamException - { - try { - XMLInputFactory f = getInputFactory(); - setCoalescing(f, false); // shouldn't really matter - setNamespaceAware(f, true); - - // First, need to parse using JAXP DOM: - DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); - dbf.setNamespaceAware(true); - DocumentBuilder db = dbf.newDocumentBuilder(); - Document doc = db.parse(new InputSource(new StringReader(contents))); - - return (XMLStreamReader2) f.createXMLStreamReader(new DOMSource(doc)); - } catch (Exception e) { - throw new XMLStreamException(e); - } - } -} - diff -Nru libwoodstox-java-4.1.3/src/test/stax2/typed/TestDOMBinaryReader.java libwoodstox-java-5.1.0/src/test/stax2/typed/TestDOMBinaryReader.java --- libwoodstox-java-4.1.3/src/test/stax2/typed/TestDOMBinaryReader.java 2012-04-24 04:38:21.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/stax2/typed/TestDOMBinaryReader.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,41 +0,0 @@ -package stax2.typed; - -import java.io.StringReader; - -import javax.xml.parsers.*; -import javax.xml.stream.*; -import javax.xml.transform.dom.DOMSource; - -import org.w3c.dom.Document; -import org.xml.sax.InputSource; - -import org.codehaus.stax2.XMLStreamReader2; - -/** - * Stax2 Typed Access API basic reader tests for binary content handling - * using DOM-backed Stax2 typed reader implementation. - */ -public class TestDOMBinaryReader - extends ReaderBinaryTestBase -{ - protected XMLStreamReader2 getReader(String contents) - throws XMLStreamException - { - try { - XMLInputFactory f = getInputFactory(); - setCoalescing(f, false); // shouldn't really matter - setNamespaceAware(f, true); - - // First, need to parse using JAXP DOM: - DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); - dbf.setNamespaceAware(true); - DocumentBuilder db = dbf.newDocumentBuilder(); - Document doc = db.parse(new InputSource(new StringReader(contents))); - - return (XMLStreamReader2) f.createXMLStreamReader(new DOMSource(doc)); - } catch (Exception e) { - throw new XMLStreamException(e); - } - } -} - diff -Nru libwoodstox-java-4.1.3/src/test/stax2/typed/TestDOMReader.java libwoodstox-java-5.1.0/src/test/stax2/typed/TestDOMReader.java --- libwoodstox-java-4.1.3/src/test/stax2/typed/TestDOMReader.java 2012-04-24 04:38:21.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/stax2/typed/TestDOMReader.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,83 +0,0 @@ -package stax2.typed; - -import java.io.StringReader; - -import javax.xml.parsers.*; -import javax.xml.stream.*; -import javax.xml.transform.dom.DOMSource; - -import org.w3c.dom.Document; -import org.xml.sax.InputSource; - -import org.codehaus.stax2.XMLStreamReader2; - -/** - * Stax2 Typed Access API basic reader tests, using DOM-backed - * implementation. - */ -public class TestDOMReader - extends ReaderTestBase -{ - protected XMLStreamReader2 getReader(String contents) - throws Exception - { - XMLInputFactory f = getInputFactory(); - setCoalescing(f, false); // shouldn't really matter - setNamespaceAware(f, true); - - // First, need to parse using JAXP DOM: - DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); - dbf.setNamespaceAware(true); - DocumentBuilder db = dbf.newDocumentBuilder(); - Document doc = db.parse(new InputSource(new StringReader(contents))); - - return (XMLStreamReader2) f.createXMLStreamReader(new DOMSource(doc)); - } - - /* - /////////////////////////////////////////////////////////////// - // Need to mask some tests, won't work with current DOM wrapper - /////////////////////////////////////////////////////////////// - */ - - // @Override - public void testValidQNameElem() - { - // Ugh: due to missing NS lookups, even this would fail... - warn("(skipping TestDOMReader.testValidQNameElem()"); - } - - // @Override - public void testInvalidQNameElemBadChars() - { - warn("(skipping TestDOMReader.testInvalidQNameElemBadChars)"); - } - - // @Override - public void testInvalidQNameElemUnbound() - { - // Need DOM3 to support namespace lookups - warn("(skipping TestDOMReader.testInvalidQNameElemUnbound()"); - } - - // @Override - public void testValidQNameAttr() - { - warn("(skipping TestDOMReader.testValidQNameAttr()"); - } - - // @Override - public void testInvalidQNameAttrBadChars() - { - warn("(skipping TestDOMReader.testInvalidQNameAttrBadChars)"); - } - - // @Override - public void testInvalidQNameAttrUnbound() - { - // Need DOM3 to support namespace lookups - warn("(skipping TestDOMReader.testInvalidQNameAttrUnbound()"); - } -} - - diff -Nru libwoodstox-java-4.1.3/src/test/stax2/typed/TestDOMWriter.java libwoodstox-java-5.1.0/src/test/stax2/typed/TestDOMWriter.java --- libwoodstox-java-4.1.3/src/test/stax2/typed/TestDOMWriter.java 2012-04-24 04:38:21.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/stax2/typed/TestDOMWriter.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,75 +0,0 @@ -package stax2.typed; - -import java.io.*; - -import javax.xml.parsers.*; -import javax.xml.stream.*; -import javax.xml.transform.Transformer; -import javax.xml.transform.TransformerFactory; -import javax.xml.transform.dom.DOMResult; -import javax.xml.transform.dom.DOMSource; -import javax.xml.transform.stream.StreamResult; - -import org.w3c.dom.*; - -import org.codehaus.stax2.*; - -/** - * Stax2 Typed Access API basic reader tests, using DOM-backed - * typed writer implementation. - *

- * Note: currently some functionality is only supported with native - * writers - */ -public class TestDOMWriter - extends WriterTestBase -{ - /** - * Nasty hack: we need to remember DOM document we are serializing into, - * to be able to fetch back the results. - */ - Document mDoc; - - protected XMLStreamWriter2 getTypedWriter(ByteArrayOutputStream out, - boolean repairing) - throws XMLStreamException - { - out.reset(); - XMLOutputFactory outf = getOutputFactory(); - mDoc = createDOMDoc(true); - setRepairing(outf, repairing); - return (XMLStreamWriter2) outf.createXMLStreamWriter(new DOMResult(mDoc)); - } - - protected byte[] closeWriter(XMLStreamWriter sw, ByteArrayOutputStream out) - throws XMLStreamException - { - sw.close(); - - // Let's use Trax identity "transformer" - try { - Transformer t = TransformerFactory.newInstance().newTransformer(); - t.transform(new DOMSource(mDoc), new StreamResult(out)); - } catch (Exception e) { - throw new RuntimeException(e); - } - return out.toByteArray(); - } - - /* - /////////////////////////////////////////////////////// - // Helper methods - /////////////////////////////////////////////////////// - */ - - private Document createDOMDoc(boolean nsAware) - { - try { - DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); - dbf.setNamespaceAware(nsAware); - return dbf.newDocumentBuilder().newDocument(); - } catch (Exception e) { - throw new RuntimeException(e); - } - } -} diff -Nru libwoodstox-java-4.1.3/src/test/stax2/typed/TestNativeArrayReader.java libwoodstox-java-5.1.0/src/test/stax2/typed/TestNativeArrayReader.java --- libwoodstox-java-4.1.3/src/test/stax2/typed/TestNativeArrayReader.java 2012-04-24 04:38:21.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/stax2/typed/TestNativeArrayReader.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,23 +0,0 @@ -package stax2.typed; - -import javax.xml.stream.*; - -import org.codehaus.stax2.XMLStreamReader2; - -/** - * Stax2 Typed Access API basic reader tests for array handling, - * using native Stax2 typed reader implementation. - */ -public class TestNativeArrayReader - extends ReaderArrayTestBase -{ - protected XMLStreamReader2 getReader(String contents) - throws XMLStreamException - { - XMLInputFactory f = getInputFactory(); - setCoalescing(f, false); // shouldn't really matter - setNamespaceAware(f, true); - return (XMLStreamReader2) constructStreamReader(f, contents); - } -} - diff -Nru libwoodstox-java-4.1.3/src/test/stax2/typed/TestNativeBinaryReader.java libwoodstox-java-5.1.0/src/test/stax2/typed/TestNativeBinaryReader.java --- libwoodstox-java-4.1.3/src/test/stax2/typed/TestNativeBinaryReader.java 2012-04-24 04:38:21.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/stax2/typed/TestNativeBinaryReader.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,23 +0,0 @@ -package stax2.typed; - -import javax.xml.stream.*; - -import org.codehaus.stax2.XMLStreamReader2; - -/** - * Stax2 Typed Access API basic reader tests for binary content handling - * using native Stax2 typed reader implementation. - */ -public class TestNativeBinaryReader - extends ReaderBinaryTestBase -{ - protected XMLStreamReader2 getReader(String contents) - throws XMLStreamException - { - XMLInputFactory f = getInputFactory(); - setCoalescing(f, false); // shouldn't really matter - setNamespaceAware(f, true); - return (XMLStreamReader2) constructStreamReader(f, contents); - } -} - diff -Nru libwoodstox-java-4.1.3/src/test/stax2/typed/TestNativeReader.java libwoodstox-java-5.1.0/src/test/stax2/typed/TestNativeReader.java --- libwoodstox-java-4.1.3/src/test/stax2/typed/TestNativeReader.java 2012-04-24 04:38:21.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/stax2/typed/TestNativeReader.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,26 +0,0 @@ -package stax2.typed; - -import javax.xml.stream.*; - -import org.codehaus.stax2.XMLStreamReader2; - -/** - * Stax2 Typed Access API basic reader tests, using native Stax2 - * typed reader implementation. - *

- * Note: currently some functionality is only supported with native - * readers - */ -public class TestNativeReader - extends ReaderTestBase -{ - protected XMLStreamReader2 getReader(String contents) - throws XMLStreamException - { - XMLInputFactory f = getInputFactory(); - setCoalescing(f, false); // shouldn't really matter - setNamespaceAware(f, true); - return (XMLStreamReader2) constructStreamReader(f, contents); - } -} - diff -Nru libwoodstox-java-4.1.3/src/test/stax2/typed/TestNativeWriter.java libwoodstox-java-5.1.0/src/test/stax2/typed/TestNativeWriter.java --- libwoodstox-java-4.1.3/src/test/stax2/typed/TestNativeWriter.java 2012-04-24 04:38:21.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/stax2/typed/TestNativeWriter.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,35 +0,0 @@ -package stax2.typed; - -import java.io.*; - -import javax.xml.stream.*; - -import org.codehaus.stax2.*; - -/** - * Stax2 Typed Access API basic reader tests, using native Stax2 - * typed writer implementation. - *

- * Note: currently some functionality is only supported with native - * writers - */ -public class TestNativeWriter - extends WriterTestBase -{ - protected XMLStreamWriter2 getTypedWriter(ByteArrayOutputStream out, - boolean repairing) - throws XMLStreamException - { - out.reset(); - XMLOutputFactory outf = getOutputFactory(); - setRepairing(outf, repairing); - return (XMLStreamWriter2) outf.createXMLStreamWriter(out, "UTF-8"); - } - - protected byte[] closeWriter(XMLStreamWriter sw, ByteArrayOutputStream out) - throws XMLStreamException - { - sw.close(); - return out.toByteArray(); - } -} diff -Nru libwoodstox-java-4.1.3/src/test/stax2/typed/TestWrappedArrayReader.java libwoodstox-java-5.1.0/src/test/stax2/typed/TestWrappedArrayReader.java --- libwoodstox-java-4.1.3/src/test/stax2/typed/TestWrappedArrayReader.java 2012-04-24 04:38:21.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/stax2/typed/TestWrappedArrayReader.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,42 +0,0 @@ -package stax2.typed; - -import javax.xml.stream.*; - -import org.codehaus.stax2.XMLStreamReader2; -import org.codehaus.stax2.ri.Stax2ReaderAdapter; - -/** - * Stax2 Typed Access API basic reader tests for array handling, - * using native Stax2 typed reader implementation. - */ -public class TestWrappedArrayReader - extends ReaderArrayTestBase -{ - protected XMLStreamReader2 getReader(String contents) - throws XMLStreamException - { - XMLInputFactory f = getInputFactory(); - setCoalescing(f, false); // shouldn't really matter - setNamespaceAware(f, true); - - /* Twist: let's wrap, as if it was a regular stax1 reader; - * let's force wrapping via constructor - * (i.e. not call "wrapIfNecessary") - */ - return new MyAdapter(constructStreamReader(f, contents)); - } - - /** - * Need a dummy base class to be able to access protected - * constructor for testing purposes. - */ - final static class MyAdapter - extends Stax2ReaderAdapter - { - public MyAdapter(XMLStreamReader sr) - { - super(sr); - } - } -} - diff -Nru libwoodstox-java-4.1.3/src/test/stax2/typed/TestWrappedBinaryReader.java libwoodstox-java-5.1.0/src/test/stax2/typed/TestWrappedBinaryReader.java --- libwoodstox-java-4.1.3/src/test/stax2/typed/TestWrappedBinaryReader.java 2012-04-24 04:38:21.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/stax2/typed/TestWrappedBinaryReader.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,42 +0,0 @@ -package stax2.typed; - -import javax.xml.stream.*; - -import org.codehaus.stax2.XMLStreamReader2; -import org.codehaus.stax2.ri.Stax2ReaderAdapter; - -/** - * Stax2 Typed Access API basic reader tests for binary content handling - * using wrapped Stax2 typed reader implementation. - */ -public class TestWrappedBinaryReader - extends ReaderBinaryTestBase -{ - protected XMLStreamReader2 getReader(String contents) - throws XMLStreamException - { - XMLInputFactory f = getInputFactory(); - setCoalescing(f, false); // shouldn't really matter - setNamespaceAware(f, true); - - /* Twist: let's wrap, as if it was a regular stax1 reader; - * let's force wrapping via constructor - * (i.e. not call "wrapIfNecessary") - */ - return new MyAdapter(constructStreamReader(f, contents)); - } - - /** - * Need a dummy base class to be able to access protected - * constructor for testing purposes. - */ - final static class MyAdapter - extends Stax2ReaderAdapter - { - public MyAdapter(XMLStreamReader sr) - { - super(sr); - } - } -} - diff -Nru libwoodstox-java-4.1.3/src/test/stax2/typed/TestWrappedReader.java libwoodstox-java-5.1.0/src/test/stax2/typed/TestWrappedReader.java --- libwoodstox-java-4.1.3/src/test/stax2/typed/TestWrappedReader.java 2012-04-24 04:38:21.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/stax2/typed/TestWrappedReader.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,49 +0,0 @@ -package stax2.typed; - -import javax.xml.stream.*; - -import org.codehaus.stax2.XMLStreamReader2; - -/** - * Stax2 Typed Access API basic reader tests, using Stax2 adapter - * which implements Stax2 functionality non-natively, on top of - * any regular Stax 1.0 implementation. - */ -public class TestWrappedReader - extends ReaderTestBase -{ - protected XMLStreamReader2 getReader(String contents) - throws XMLStreamException - { - XMLInputFactory f = getInputFactory(); - setCoalescing(f, false); // shouldn't really matter - setNamespaceAware(f, true); - - /* Twist: let's wrap, as if it was a regular stax1 reader; - * let's force wrapping via constructor - * (i.e. not call "wrapIfNecessary") - */ - return wrapWithAdapter(constructStreamReader(f, contents)); - } - - /* - /////////////////////////////////////////////////////////////// - // Need to mask some tests, won't work with current wrapper - /////////////////////////////////////////////////////////////// - */ - - // @Override - public void testInvalidQNameElemBadChars() - throws Exception - { - System.out.println("(skipping TestWrappedReader.testInvalidQNameElemBadChars)"); - } - - // @Override - public void testInvalidQNameAttrBadChars() - { - System.out.println("(skipping TestWrappedReader.testInvalidQNameAttrBadChars)"); - } -} - - diff -Nru libwoodstox-java-4.1.3/src/test/stax2/typed/TestWrappedWriter.java libwoodstox-java-5.1.0/src/test/stax2/typed/TestWrappedWriter.java --- libwoodstox-java-4.1.3/src/test/stax2/typed/TestWrappedWriter.java 2012-04-24 04:38:21.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/stax2/typed/TestWrappedWriter.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,53 +0,0 @@ -package stax2.typed; - -import java.io.*; - -import javax.xml.stream.*; - -import org.codehaus.stax2.*; -import org.codehaus.stax2.ri.Stax2WriterAdapter; - -/** - * Stax2 Typed Access API basic reader tests, using Stax2 adapter - * which implements Stax2 functionality non-natively, on top of - * any regular Stax 1.0 implementation. - */ -public class TestWrappedWriter - extends WriterTestBase -{ - protected XMLStreamWriter2 getTypedWriter(ByteArrayOutputStream out, - boolean repairing) - throws XMLStreamException - { - out.reset(); - XMLOutputFactory outf = getOutputFactory(); - setRepairing(outf, repairing); - return new MyAdapter(outf.createXMLStreamWriter(out, "UTF-8")); - } - - protected byte[] closeWriter(XMLStreamWriter sw, ByteArrayOutputStream out) - throws XMLStreamException - { - sw.close(); - return out.toByteArray(); - } - - /* - //////////////////////////////////////// - // Helper class - //////////////////////////////////////// - */ - - /** - * Need a dummy base class to be able to access protected - * constructor for testing purposes. - */ - final static class MyAdapter - extends Stax2WriterAdapter - { - public MyAdapter(XMLStreamWriter sw) - { - super(sw); - } - } -} diff -Nru libwoodstox-java-4.1.3/src/test/stax2/typed/WriterTestBase.java libwoodstox-java-5.1.0/src/test/stax2/typed/WriterTestBase.java --- libwoodstox-java-4.1.3/src/test/stax2/typed/WriterTestBase.java 2012-04-24 04:38:21.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/stax2/typed/WriterTestBase.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,1022 +0,0 @@ -package stax2.typed; - -import java.io.*; -import java.math.BigDecimal; -import java.math.BigInteger; -import java.util.Random; -import java.util.StringTokenizer; - -import javax.xml.namespace.QName; -import javax.xml.stream.*; - -import org.codehaus.stax2.*; -import org.codehaus.stax2.typed.*; - -import stax2.BaseStax2Test; - -/** - * Base class that contains set of simple unit tests to verify implementation - * of {@link TypedXMLStreamWriter}. Concrete sub-classes are used to - * test both native and wrapped Stax2 implementations. - * - * @author Tatu Saloranta - */ -public abstract class WriterTestBase - extends BaseStax2Test -{ - final static int[] ARRAY_TEST_LENGTHS = new int[] { - 3, 8, 25, 120, 16, 99, 253, 1099, 37242 - }; - - /* - //////////////////////////////////////// - // Tests for numeric/enum types - //////////////////////////////////////// - */ - - public void testSimpleBooleanElem() - throws XMLStreamException - { - ByteArrayOutputStream bos = new ByteArrayOutputStream(); - XMLStreamWriter2 w = getTypedWriter(bos); - writeBooleanElem(w, true); - byte[] data = closeWriter(w, bos); - checkBooleanElem(data, true); - - w = getTypedWriter(bos); - writeBooleanElem(w, false); - data = closeWriter(w, bos); - checkBooleanElem(data, false); - } - - public void testSimpleBooleanAttr() - throws XMLStreamException - { - ByteArrayOutputStream bos = new ByteArrayOutputStream(); - XMLStreamWriter2 w = getTypedWriter(bos); - writeBooleanAttr(w, true); - byte[] data = closeWriter(w, bos); - checkBooleanAttr(data, true); - - w = getTypedWriter(bos); - writeBooleanAttr(w, false); - data = closeWriter(w, bos); - checkBooleanAttr(data, false); - } - - public void testMultipleBooleanAttr() - throws XMLStreamException - { - ByteArrayOutputStream bos = new ByteArrayOutputStream(); - XMLStreamWriter2 w = getTypedWriter(bos); - - w.writeStartDocument(); - w.writeStartElement("root"); - - w.writeBooleanAttribute(null, null, "a1", true); - w.writeBooleanAttribute(null, null, "xyz", false); - w.writeBooleanAttribute(null, null, "_attr3", true); - - w.writeEndElement(); - w.writeEndDocument(); - - byte[] data = closeWriter(w, bos); - XMLStreamReader2 sr = getRootReader(data); - assertEquals(3, sr.getAttributeCount()); - int ix1 = sr.getAttributeIndex("", "a1"); - int ix2 = sr.getAttributeIndex("", "xyz"); - int ix3 = sr.getAttributeIndex("", "_attr3"); - if (ix1 < 0 || ix2 < 0 || ix3 < 0) { - fail("Couldn't find indexes of attributes: a1="+ix1+", xyz="+ix2+", _attr3="+ix3); - } - assertTrue(sr.getAttributeAsBoolean(ix1)); - assertFalse(sr.getAttributeAsBoolean(ix2)); - assertTrue(sr.getAttributeAsBoolean(ix3)); - - sr.close(); - } - - public void testSimpleIntElem() - throws XMLStreamException - { - int[] values = new int[] { - 0, 3, -9, 999, -77, 1000000000, -1000000000, - Integer.MIN_VALUE, Integer.MAX_VALUE - }; - for (int i = 0; i < values.length; ++i) { - int value = values[i]; - assertXML(""+value+"", writeIntElemDoc("root", value)); - } - } - - public void testSimpleIntAttr() - throws XMLStreamException - { - int[] values = new int[] { - 0, 3, -7, 123, -102, 1000000, -999999, - Integer.MIN_VALUE, Integer.MAX_VALUE - }; - for (int i = 0; i < values.length; ++i) { - int value = values[i]; - assertXML("", writeIntAttrDoc("a", "attr", value)); - } - } - - public void testMultipleIntAttr() - throws XMLStreamException - { - ByteArrayOutputStream bos = new ByteArrayOutputStream(); - XMLStreamWriter2 w = getTypedWriter(bos); - - w.writeStartDocument(); - w.writeStartElement("root"); - - w.writeIntAttribute(null, null, "a", 0); - w.writeIntAttribute(null, null, "bz", Integer.MAX_VALUE); - w.writeIntAttribute(null, null, "___", -1200300400); - - w.writeEndElement(); - w.writeEndDocument(); - - byte[] data = closeWriter(w, bos); - XMLStreamReader2 sr = getRootReader(data); - assertEquals(3, sr.getAttributeCount()); - int ix1 = sr.getAttributeIndex("", "a"); - int ix2 = sr.getAttributeIndex("", "bz"); - int ix3 = sr.getAttributeIndex("", "___"); - if (ix1 < 0 || ix2 < 0 || ix3 < 0) { - fail("Couldn't find indexes of attributes: a="+ix1+", bz="+ix2+", ___="+ix3); - } - assertEquals(0, sr.getAttributeAsInt(ix1)); - assertEquals(Integer.MAX_VALUE, sr.getAttributeAsInt(ix2)); - assertEquals(-1200300400, sr.getAttributeAsInt(ix3)); - - sr.close(); - } - - public void testSimpleLongElem() - throws XMLStreamException - { - long[] values = new long[] { - 0, 3, -9, 999, -77, 1000000000, -1000000000, - 123456789012345678L, - -987654321098765423L, - Long.MIN_VALUE, Long.MAX_VALUE - }; - for (int i = 0; i < values.length; ++i) { - long value = values[i]; - assertXML(""+value+"", writeLongElemDoc("root", value)); - } - } - - public void testSimpleLongAttr() - throws XMLStreamException - { - long[] values = new long[] { - 0, 3, -9, 999, -77, 1000000002, -2000000004, - 123456789012345678L, - -987654321098765423L, - Long.MIN_VALUE, Long.MAX_VALUE - }; - for (int i = 0; i < values.length; ++i) { - long value = values[i]; - assertXML("", writeLongAttrDoc("a", "attr", value)); - } - } - - public void testMultipleLongAttr() - throws XMLStreamException - { - ByteArrayOutputStream bos = new ByteArrayOutputStream(); - XMLStreamWriter2 w = getTypedWriter(bos); - - w.writeStartDocument(); - w.writeStartElement("root"); - - w.writeLongAttribute(null, null, "a", 0L); - w.writeLongAttribute(null, null, "bz", Long.MAX_VALUE); - w.writeLongAttribute(null, null, "___", -1200300400L); - - w.writeEndElement(); - w.writeEndDocument(); - - byte[] data = closeWriter(w, bos); - XMLStreamReader2 sr = getRootReader(data); - assertEquals(3, sr.getAttributeCount()); - int ix1 = sr.getAttributeIndex("", "a"); - int ix2 = sr.getAttributeIndex("", "bz"); - int ix3 = sr.getAttributeIndex("", "___"); - if (ix1 < 0 || ix2 < 0 || ix3 < 0) { - fail("Couldn't find indexes of attributes: a="+ix1+", bz="+ix2+", ___="+ix3); - } - assertEquals(0L, sr.getAttributeAsLong(ix1)); - assertEquals(Long.MAX_VALUE, sr.getAttributeAsLong(ix2)); - assertEquals(-1200300400L, sr.getAttributeAsLong(ix3)); - - sr.close(); - } - - public void testSimpleFloatElem() - throws XMLStreamException - { - float[] values = new float[] { - 0.0f, 10.47f, (float) (1.0 / 3.0), -0.25f, - Float.MIN_VALUE, Float.MAX_VALUE, - Float.NaN, Float.POSITIVE_INFINITY, Float.NEGATIVE_INFINITY - }; - for (int i = 0; i < values.length; ++i) { - float value = values[i]; - assertXML(""+value+"", writeFloatElemDoc("root", value)); - } - } - - public void testSimpleFloatAttr() - throws XMLStreamException - { - float[] values = new float[] { - 0.0f, 10.47f, (float) (1.0 / 3.0), -0.25f, - Float.MIN_VALUE, Float.MAX_VALUE, - Float.NaN, Float.POSITIVE_INFINITY, Float.NEGATIVE_INFINITY - }; - for (int i = 0; i < values.length; ++i) { - float value = values[i]; - assertXML("", writeFloatAttrDoc("a", "attr", value)); - } - } - - public void testSimpleDoubleElem() - throws XMLStreamException - { - double[] values = new double[] { - 0.0f, 10.47f, (double) (1.0 / 3.0), -0.25f, - Double.MIN_VALUE, Double.MAX_VALUE, - Double.NaN, Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY - }; - for (int i = 0; i < values.length; ++i) { - double value = values[i]; - assertXML(""+value+"", writeDoubleElemDoc("root", value)); - } - } - - public void testSimpleDoubleAttr() - throws XMLStreamException - { - double[] values = new double[] { - 0.0f, 10.47f, (double) (1.0 / 3.0), -0.25f, - Double.MIN_VALUE, Double.MAX_VALUE, - Double.NaN, Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY - }; - for (int i = 0; i < values.length; ++i) { - double value = values[i]; - assertXML("", writeDoubleAttrDoc("a", "attr", value)); - } - } - - public void testBigInteger() - throws XMLStreamException - { - BigInteger I = BigInteger.valueOf(3); - Random rnd = new Random(2); - for (int i = 1; i < 200; ++i) { - assertXML(""+I+"", writeIntegerElemDoc("root", I)); - assertXML("", writeIntegerAttrDoc("a", "attr", I)); - I = I.multiply(BigInteger.valueOf(10)).add(BigInteger.valueOf(rnd.nextInt() & 0xF)); - } - } - - public void testBigDecimal() - throws XMLStreamException - { - BigDecimal D = BigDecimal.valueOf(1L); - Random rnd = new Random(9); - for (int i = 1; i < 200; ++i) { - assertXML(""+D+"", writeDecimalElemDoc("root", D)); - assertXML("", writeDecimalAttrDoc("a", "attr", D)); - // Ok, then, add a small integer, divide by 10 to generate digits - D = D.add(BigDecimal.valueOf(rnd.nextInt() & 0xF)).divide(BigDecimal.valueOf(10L)); - } - } - - public void testQNameNonRepairing() - throws XMLStreamException - { - doTestQName(false); - } - - public void testQNameRepairing() - throws XMLStreamException - { - doTestQName(true); - } - - private void doTestQName(boolean repairing) - throws XMLStreamException - { - final String URI = "http://my.uri"; - QName n = new QName(URI, "elem", "ns"); - - assertXML("ns:elem", writeQNameElemDoc("root", n, repairing)); - assertXML("", - writeQNameAttrDoc("root", "attr", n, repairing)); - } - - public void testIntArraysElem() - throws XMLStreamException - { - doTestIntArrays(false); - } - - public void testIntArraysAttr() - throws XMLStreamException - { - doTestIntArrays(true); - } - - private void doTestIntArrays(boolean testAttr) - throws XMLStreamException - { - for (int i = 0; i <= ARRAY_TEST_LENGTHS.length; ++i) { - int[] data; - if (i == 0) { - data = new int[] { - 0, -139, 29, Integer.MAX_VALUE, 1, Integer.MIN_VALUE }; - } else { - Random rnd = new Random(9); - int len = ARRAY_TEST_LENGTHS[i-1]; - data = new int[len]; - for (int ix = 0; ix < len; ++ix) { - data[ix] = rnd.nextInt(); - } - } - String contents; - if (testAttr) { - contents = getAttributeContent(writeIntArrayAttrDoc("root", "attr", data)); - } else { - contents = getElementContent(writeIntArrayElemDoc("root", data)); - } - StringTokenizer st = new StringTokenizer(contents); - int count = 0; - while (st.hasMoreTokens()) { - String exp = String.valueOf(data[count]); - String act = st.nextToken(); - - if (!exp.equals(act)) { - fail("Incorrect entry #"+count+"/"+data.length+": act = '"+act+"' (exp '"+exp+"')"); - } - ++count; - } - assertEquals(data.length, count); - } - } - - public void testLongArraysElem() - throws XMLStreamException - { - doTestLongArrays(false); - } - - public void testLongArraysAttr() - throws XMLStreamException - { - doTestLongArrays(true); - } - - private void doTestLongArrays(boolean testAttr) - throws XMLStreamException - { - for (int i = 0; i <= ARRAY_TEST_LENGTHS.length; ++i) { - long[] data; - if (i == 0) { - data = new long[] { - 0, -139, 29, Long.MAX_VALUE, 1, Long.MIN_VALUE }; - } else { - Random rnd = new Random(9); - int len = ARRAY_TEST_LENGTHS[i-1]; - data = new long[len]; - for (int ix = 0; ix < len; ++ix) { - data[ix] = rnd.nextLong(); - } - } - String contents; - if (testAttr) { - contents = getAttributeContent(writeLongArrayAttrDoc("root", "attr", data)); - } else { - contents = getElementContent(writeLongArrayElemDoc("root", data)); - } - StringTokenizer st = new StringTokenizer(contents); - int count = 0; - while (st.hasMoreTokens()) { - String exp = String.valueOf(data[count]); - String act = st.nextToken(); - - if (!exp.equals(act)) { - fail("Incorrect entry #"+count+"/"+data.length+": act = '"+act+"' (exp '"+exp+"')"); - } - ++count; - } - assertEquals(data.length, count); - } - } - - public void testFloatArraysElem() - throws XMLStreamException - { - doTestFloatArrays(false); - } - - public void testFloatArraysAttr() - throws XMLStreamException - { - doTestFloatArrays(true); - } - - private void doTestFloatArrays(boolean testAttr) - throws XMLStreamException - { - for (int i = 0; i <= ARRAY_TEST_LENGTHS.length; ++i) { - float[] data; - if (i == 0) { - data = new float[] { - 0, -139, 29, Float.MAX_VALUE, 1, Float.MIN_VALUE }; - } else { - Random rnd = new Random(9); - int len = ARRAY_TEST_LENGTHS[i-1]; - data = new float[len]; - for (int ix = 0; ix < len; ++ix) { - // Need to scale: nextFloat is [0.0, 1.0[ - float value = rnd.nextFloat(); - if (rnd.nextBoolean()) { - value = (float) (value * rnd.nextInt()); - } - if (rnd.nextBoolean()) { - value = -value; - } - data[ix] = value; - } - } - String contents; - if (testAttr) { - contents = getAttributeContent(writeFloatArrayAttrDoc("root", "attr", data)); - } else { - contents = getElementContent(writeFloatArrayElemDoc("root", data)); - } - StringTokenizer st = new StringTokenizer(contents); - int count = 0; - while (st.hasMoreTokens()) { - String exp = String.valueOf(data[count]); - String act = st.nextToken(); - - if (!exp.equals(act)) { - fail("Incorrect entry #"+count+"/"+data.length+": act = '"+act+"' (exp '"+exp+"')"); - } - ++count; - } - assertEquals(data.length, count); - } - } - - public void testDoubleArraysElem() - throws XMLStreamException - { - doTestDoubleArrays(false); - } - - public void testDoubleArraysAttr() - throws XMLStreamException - { - doTestDoubleArrays(true); - } - - private void doTestDoubleArrays(boolean testAttr) - throws XMLStreamException - { - for (int i = 0; i <= ARRAY_TEST_LENGTHS.length; ++i) { - double[] data; - if (i == 0) { - data = new double[] { - 0, -139, 29, Double.MAX_VALUE, 1, Double.MIN_VALUE }; - } else { - Random rnd = new Random(9); - int len = ARRAY_TEST_LENGTHS[i-1]; - data = new double[len]; - for (int ix = 0; ix < len; ++ix) { - // Need to scale: nextDouble is [0.0, 1.0[ - double value = rnd.nextDouble(); - if (rnd.nextBoolean()) { - value = (double) (value * rnd.nextLong()); - } - if (rnd.nextBoolean()) { - value = -value; - } - data[ix] = value; - } - } - String contents; - if (testAttr) { - contents = getAttributeContent(writeDoubleArrayAttrDoc("root", "attr", data)); - } else { - contents = getElementContent(writeDoubleArrayElemDoc("root", data)); - } - StringTokenizer st = new StringTokenizer(contents); - int count = 0; - while (st.hasMoreTokens()) { - String exp = String.valueOf(data[count]); - String act = st.nextToken(); - - if (!exp.equals(act)) { - fail("Incorrect entry #"+count+"/"+data.length+": act = '"+act+"' (exp '"+exp+"')"); - } - ++count; - } - assertEquals(data.length, count); - } - } - - /* - //////////////////////////////////////// - // Private methods, checking typed doc - //////////////////////////////////////// - */ - - private void checkBooleanElem(byte[] data, boolean expState) - throws XMLStreamException - { - XMLStreamReader2 sr = getRootReader(data); - assertEquals(expState, sr.getElementAsBoolean()); - sr.close(); - } - - private void checkBooleanAttr(byte[] data, boolean expState) - throws XMLStreamException - { - XMLStreamReader2 sr = getRootReader(data); - assertEquals(expState, sr.getAttributeAsBoolean(0)); - sr.close(); - } - - private void writeBooleanElem(TypedXMLStreamWriter sw, boolean b) - throws XMLStreamException - { - sw.writeStartDocument(); - sw.writeStartElement("root"); - sw.writeBoolean(b); - sw.writeEndElement(); - sw.writeEndDocument(); - } - - private void writeBooleanAttr(TypedXMLStreamWriter sw, boolean b) - throws XMLStreamException - { - sw.writeStartDocument(); - sw.writeStartElement("root"); - sw.writeBooleanAttribute(null, null, "attr", b); - sw.writeEndElement(); - sw.writeEndDocument(); - } - - private String writeIntElemDoc(String elem, int value) - throws XMLStreamException - { - ByteArrayOutputStream bos = new ByteArrayOutputStream(); - XMLStreamWriter2 sw = getTypedWriter(bos); - // Let's not write start doc, to avoid getting xml declaration - //sw.writeStartDocument(); - sw.writeStartElement(elem); - sw.writeInt(value); - sw.writeEndElement(); - sw.writeEndDocument(); - return getUTF8(sw, bos); - } - - private String writeIntAttrDoc(String elem, String attr, int value) - throws XMLStreamException - { - ByteArrayOutputStream bos = new ByteArrayOutputStream(); - XMLStreamWriter2 sw = getTypedWriter(bos); - // Let's not write start doc, to avoid getting xml declaration - //sw.writeStartDocument(); - sw.writeStartElement(elem); - sw.writeIntAttribute(null, null, attr, value); - sw.writeCharacters(""); // to avoid empty elem - sw.writeEndElement(); - sw.writeEndDocument(); - String str = getUTF8(sw, bos); - // One twist: need to ensure quotes are single-quotes (for the test) - return str.replace('"', '\''); - } - - private String writeLongElemDoc(String elem, long value) - throws XMLStreamException - { - ByteArrayOutputStream bos = new ByteArrayOutputStream(); - XMLStreamWriter2 sw = getTypedWriter(bos); - // Let's not write start doc, to avoid getting xml declaration - //sw.writeStartDocument(); - sw.writeStartElement(elem); - sw.writeLong(value); - sw.writeEndElement(); - sw.writeEndDocument(); - return getUTF8(sw, bos); - } - - private String writeLongAttrDoc(String elem, String attr, long value) - throws XMLStreamException - { - ByteArrayOutputStream bos = new ByteArrayOutputStream(); - XMLStreamWriter2 sw = getTypedWriter(bos); - // Let's not write start doc, to avoid getting xml declaration - //sw.writeStartDocument(); - sw.writeStartElement(elem); - sw.writeLongAttribute(null, null, attr, value); - sw.writeCharacters(""); // to avoid empty elem - sw.writeEndElement(); - sw.writeEndDocument(); - String str = getUTF8(sw, bos); - // One twist: need to ensure quotes are single-quotes (for the test) - return str.replace('"', '\''); - } - - private String writeFloatElemDoc(String elem, float value) - throws XMLStreamException - { - ByteArrayOutputStream bos = new ByteArrayOutputStream(); - XMLStreamWriter2 sw = getTypedWriter(bos); - // Let's not write start doc, to avoid getting xml declaration - //sw.writeStartDocument(); - sw.writeStartElement(elem); - sw.writeFloat(value); - sw.writeEndElement(); - sw.writeEndDocument(); - return getUTF8(sw, bos); - } - - private String writeFloatAttrDoc(String elem, String attr, float value) - throws XMLStreamException - { - ByteArrayOutputStream bos = new ByteArrayOutputStream(); - XMLStreamWriter2 sw = getTypedWriter(bos); - // Let's not write start doc, to avoid getting xml declaration - //sw.writeStartDocument(); - sw.writeStartElement(elem); - sw.writeFloatAttribute(null, null, attr, value); - sw.writeCharacters(""); // to avoid empty elem - sw.writeEndElement(); - sw.writeEndDocument(); - String str = getUTF8(sw, bos); - // One twist: need to ensure quotes are single-quotes (for the test) - return str.replace('"', '\''); - } - - private String writeDoubleElemDoc(String elem, double value) - throws XMLStreamException - { - ByteArrayOutputStream bos = new ByteArrayOutputStream(); - XMLStreamWriter2 sw = getTypedWriter(bos); - sw.writeStartElement(elem); - sw.writeDouble(value); - sw.writeEndElement(); - sw.writeEndDocument(); - return getUTF8(sw, bos); - } - - private String writeDoubleAttrDoc(String elem, String attr, double value) - throws XMLStreamException - { - ByteArrayOutputStream bos = new ByteArrayOutputStream(); - XMLStreamWriter2 sw = getTypedWriter(bos); - sw.writeStartElement(elem); - sw.writeDoubleAttribute(null, null, attr, value); - sw.writeCharacters(""); // to avoid empty elem - sw.writeEndElement(); - sw.writeEndDocument(); - String str = getUTF8(sw, bos); - // One twist: need to ensure quotes are single-quotes (for the test) - return str.replace('"', '\''); - } - - private String writeIntegerElemDoc(String elem, BigInteger value) - throws XMLStreamException - { - ByteArrayOutputStream bos = new ByteArrayOutputStream(); - XMLStreamWriter2 sw = getTypedWriter(bos); - sw.writeStartElement(elem); - sw.writeInteger(value); - sw.writeEndElement(); - sw.writeEndDocument(); - return getUTF8(sw, bos); - } - - private String writeIntegerAttrDoc(String elem, String attr, BigInteger value) - throws XMLStreamException - { - ByteArrayOutputStream bos = new ByteArrayOutputStream(); - XMLStreamWriter2 sw = getTypedWriter(bos); - sw.writeStartElement(elem); - sw.writeIntegerAttribute(null, null, attr, value); - sw.writeCharacters(""); // to avoid empty elem - sw.writeEndElement(); - sw.writeEndDocument(); - String str = getUTF8(sw, bos); - // One twist: need to ensure quotes are single-quotes (for the test) - return str.replace('"', '\''); - } - - private String writeDecimalElemDoc(String elem, BigDecimal value) - throws XMLStreamException - { - ByteArrayOutputStream bos = new ByteArrayOutputStream(); - XMLStreamWriter2 sw = getTypedWriter(bos); - sw.writeStartElement(elem); - sw.writeDecimal(value); - sw.writeEndElement(); - sw.writeEndDocument(); - return getUTF8(sw, bos); - } - - private String writeDecimalAttrDoc(String elem, String attr, BigDecimal value) - throws XMLStreamException - { - ByteArrayOutputStream bos = new ByteArrayOutputStream(); - XMLStreamWriter2 sw = getTypedWriter(bos); - sw.writeStartElement(elem); - sw.writeDecimalAttribute(null, null, attr, value); - sw.writeCharacters(""); // to avoid empty elem - sw.writeEndElement(); - sw.writeEndDocument(); - String str = getUTF8(sw, bos); - // One twist: need to ensure quotes are single-quotes (for the test) - return str.replace('"', '\''); - } - - private String writeQNameElemDoc(String elem, QName n, boolean repairing) - throws XMLStreamException - { - ByteArrayOutputStream bos = new ByteArrayOutputStream(); - XMLStreamWriter2 sw = getTypedWriter(bos, repairing); - sw.writeStartElement(elem); - if (!repairing) { - sw.writeNamespace(n.getPrefix(), n.getNamespaceURI()); - } - sw.writeQName(n); - sw.writeEndElement(); - sw.writeEndDocument(); - String str = getUTF8(sw, bos); - return str.replace('"', '\''); - } - - private String writeQNameAttrDoc(String elem, String attr, QName n, boolean repairing) - throws XMLStreamException - { - ByteArrayOutputStream bos = new ByteArrayOutputStream(); - XMLStreamWriter2 sw = getTypedWriter(bos, repairing); - sw.writeStartElement(elem); - if (!repairing) { - sw.writeNamespace(n.getPrefix(), n.getNamespaceURI()); - } - sw.writeQNameAttribute(null, null, attr, n); - sw.writeCharacters(""); // to avoid empty elem - sw.writeEndElement(); - sw.writeEndDocument(); - String str = getUTF8(sw, bos); - return str.replace('"', '\''); - } - - private byte[] writeIntArrayElemDoc(String elem, int[] values) - throws XMLStreamException - { - ByteArrayOutputStream bos = new ByteArrayOutputStream(); - XMLStreamWriter2 sw = getTypedWriter(bos); - sw.writeStartElement(elem); - if ((values.length % 2) == 1) { // odd -> single write - sw.writeIntArray(values, 0, values.length); - } else { // even -> split in halves - int offset = values.length / 2; - sw.writeIntArray(values, 0, offset); - sw.writeIntArray(values, offset, values.length - offset); - } - sw.writeEndElement(); - sw.writeEndDocument(); - return closeWriter(sw, bos); - } - - private byte[] writeIntArrayAttrDoc(String elem, String attr, int[] values) - throws XMLStreamException - { - ByteArrayOutputStream bos = new ByteArrayOutputStream(); - XMLStreamWriter2 sw = getTypedWriter(bos); - sw.writeStartElement(elem); - sw.writeIntArrayAttribute(null, null, attr, values); - sw.writeEndElement(); - sw.writeEndDocument(); - return closeWriter(sw, bos); - } - - private byte[] writeLongArrayElemDoc(String elem, long[] values) - throws XMLStreamException - { - ByteArrayOutputStream bos = new ByteArrayOutputStream(); - XMLStreamWriter2 sw = getTypedWriter(bos); - sw.writeStartElement(elem); - if ((values.length % 2) == 1) { // odd -> single write - sw.writeLongArray(values, 0, values.length); - } else { // even -> split in halves - int offset = values.length / 2; - sw.writeLongArray(values, 0, offset); - sw.writeLongArray(values, offset, values.length - offset); - } - sw.writeEndElement(); - sw.writeEndDocument(); - return closeWriter(sw, bos); - } - - private byte[] writeLongArrayAttrDoc(String elem, String attr, long[] values) - throws XMLStreamException - { - ByteArrayOutputStream bos = new ByteArrayOutputStream(); - XMLStreamWriter2 sw = getTypedWriter(bos); - sw.writeStartElement(elem); - sw.writeLongArrayAttribute(null, null, attr, values); - sw.writeEndElement(); - sw.writeEndDocument(); - return closeWriter(sw, bos); - } - - private byte[] writeFloatArrayElemDoc(String elem, float[] values) - throws XMLStreamException - { - ByteArrayOutputStream bos = new ByteArrayOutputStream(); - XMLStreamWriter2 sw = getTypedWriter(bos); - sw.writeStartElement(elem); - if ((values.length % 2) == 1) { // odd -> single write - sw.writeFloatArray(values, 0, values.length); - } else { // even -> split in halves - int offset = values.length / 2; - sw.writeFloatArray(values, 0, offset); - sw.writeFloatArray(values, offset, values.length - offset); - } - sw.writeEndElement(); - sw.writeEndDocument(); - return closeWriter(sw, bos); - } - - private byte[] writeFloatArrayAttrDoc(String elem, String attr, float[] values) - throws XMLStreamException - { - ByteArrayOutputStream bos = new ByteArrayOutputStream(); - XMLStreamWriter2 sw = getTypedWriter(bos); - sw.writeStartElement(elem); - sw.writeFloatArrayAttribute(null, null, attr, values); - sw.writeEndElement(); - sw.writeEndDocument(); - return closeWriter(sw, bos); - } - - private byte[] writeDoubleArrayElemDoc(String elem, double[] values) - throws XMLStreamException - { - ByteArrayOutputStream bos = new ByteArrayOutputStream(); - XMLStreamWriter2 sw = getTypedWriter(bos); - sw.writeStartElement(elem); - if ((values.length % 2) == 1) { // odd -> single write - sw.writeDoubleArray(values, 0, values.length); - } else { // even -> split in halves - int offset = values.length / 2; - sw.writeDoubleArray(values, 0, offset); - sw.writeDoubleArray(values, offset, values.length - offset); - } - sw.writeEndElement(); - sw.writeEndDocument(); - return closeWriter(sw, bos); - } - - private byte[] writeDoubleArrayAttrDoc(String elem, String attr, double[] values) - throws XMLStreamException - { - ByteArrayOutputStream bos = new ByteArrayOutputStream(); - XMLStreamWriter2 sw = getTypedWriter(bos); - sw.writeStartElement(elem); - sw.writeDoubleArrayAttribute(null, null, attr, values); - sw.writeEndElement(); - sw.writeEndDocument(); - return closeWriter(sw, bos); - } - - /* - //////////////////////////////////////// - // Abstract methods - //////////////////////////////////////// - */ - - protected abstract XMLStreamWriter2 getTypedWriter(ByteArrayOutputStream out, - boolean repairing) - throws XMLStreamException; - - protected abstract byte[] closeWriter(XMLStreamWriter sw, ByteArrayOutputStream out) - throws XMLStreamException; - - /* - //////////////////////////////////////// - // Private methods, constructing writers - //////////////////////////////////////// - */ - - private XMLStreamWriter2 getTypedWriter(ByteArrayOutputStream out) - throws XMLStreamException - { - return getTypedWriter(out, false); - } - - // XMLStreamReader2 extends TypedXMLStreamReader - private XMLStreamReader2 getRootReader(byte[] data) - throws XMLStreamException - { - XMLStreamReader2 sr = getReader(data); - assertTokenType(START_DOCUMENT, sr.getEventType()); - while (sr.next() != START_ELEMENT) { } - assertTokenType(START_ELEMENT, sr.getEventType()); - return sr; - } - - private XMLStreamReader2 getReader(byte[] data) - throws XMLStreamException - { - XMLInputFactory f = getInputFactory(); - setCoalescing(f, false); // shouldn't really matter - setNamespaceAware(f, true); - return (XMLStreamReader2) f.createXMLStreamReader(new ByteArrayInputStream(data)); - } - - private String getUTF8(XMLStreamWriter sw, ByteArrayOutputStream bos) - throws XMLStreamException - { - byte[] data = closeWriter(sw, bos); - try { - return new String(data, "UTF-8"); - } catch (IOException ioe) { - throw new IllegalArgumentException(ioe); - } - } - - private String getElementContent(byte[] data) - throws XMLStreamException - { - XMLStreamReader sr = getReader(data); - assertTokenType(START_DOCUMENT, sr.getEventType()); - while (sr.next() != START_ELEMENT) { } - assertTokenType(START_ELEMENT, sr.getEventType()); - String content = sr.getElementText(); - sr.close(); - return content; - } - - private String getAttributeContent(byte[] data) - throws XMLStreamException - { - XMLStreamReader sr = getReader(data); - assertTokenType(START_DOCUMENT, sr.getEventType()); - while (sr.next() != START_ELEMENT) { } - assertTokenType(START_ELEMENT, sr.getEventType()); - assertEquals(1, sr.getAttributeCount()); - String content = sr.getAttributeValue(0); - sr.close(); - return content; - } - - /** - * Helper method to contain modifications we may need to - * reliably compare equivalency of result xml to expected - * results. - */ - void assertXML(String exp, String act) - { - // First: let's trim out xml decl, if any - act = act.trim(); - if (act.startsWith(""); - act = act.substring(ix+2); - } - // Usually this is enough: - if (exp.equals(act)) { - return; - } - /* If not, let's see if we can still find them equal; - * given simplicity of docs, we only need to be concerned - * with '' -> '' change it seems. Expected - * results seem to only differ by that much, for now... - */ - int ix = act.indexOf("/>"); - if (ix > 0) { - // ugh. this is ugly, yes... if it breaks, should just rewrite completely - String prefix = act.substring(0, ix).trim(); - String suffix = act.substring(ix+2); // probably empty tho - - ix = prefix.lastIndexOf("<"); - int ix2 = prefix.indexOf(' ', ix); - // If it was just name it'd be simpler, but there may be attr(s) - String name = (ix2 < 0) ? prefix.substring(ix+1) : prefix.substring(ix+1, ix2); - - act = prefix + ">"+suffix; - } - assertEquals(exp, act); - } -} diff -Nru libwoodstox-java-4.1.3/src/test/stax2/vwstream/BaseOutputTest.java libwoodstox-java-5.1.0/src/test/stax2/vwstream/BaseOutputTest.java --- libwoodstox-java-4.1.3/src/test/stax2/vwstream/BaseOutputTest.java 2012-04-24 04:38:21.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/stax2/vwstream/BaseOutputTest.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,31 +0,0 @@ -package stax2.vwstream; - -import java.io.*; -import javax.xml.stream.*; - -import org.codehaus.stax2.*; -import org.codehaus.stax2.validation.*; - -import stax2.BaseStax2Test; - -abstract class BaseOutputTest - extends BaseStax2Test -{ - public XMLStreamWriter2 getDTDValidatingWriter(Writer w, String dtdSrc, - boolean nsAware, boolean repairing) - throws XMLStreamException - { - XMLOutputFactory2 outf = getOutputFactory(); - outf.setProperty(XMLStreamProperties.XSP_NAMESPACE_AWARE, new Boolean(nsAware)); - outf.setProperty(XMLOutputFactory.IS_REPAIRING_NAMESPACES, new Boolean(repairing)); - - XMLStreamWriter2 strw = (XMLStreamWriter2)outf.createXMLStreamWriter(w); - XMLValidationSchemaFactory vd = XMLValidationSchemaFactory.newInstance(XMLValidationSchema.SCHEMA_ID_DTD); - - XMLValidationSchema schema = vd.createSchema(new StringReader(dtdSrc)); - - strw.validateAgainst(schema); - strw.writeStartDocument(); - return strw; - } -} diff -Nru libwoodstox-java-4.1.3/src/test/stax2/vwstream/TestAttributeValidation.java libwoodstox-java-5.1.0/src/test/stax2/vwstream/TestAttributeValidation.java --- libwoodstox-java-4.1.3/src/test/stax2/vwstream/TestAttributeValidation.java 2012-04-24 04:38:21.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/stax2/vwstream/TestAttributeValidation.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,255 +0,0 @@ -package stax2.vwstream; - -import java.io.*; - -import javax.xml.stream.*; - -import org.codehaus.stax2.XMLStreamWriter2; -import org.codehaus.stax2.validation.*; - -/** - * Unit tests for testing handling of attribute value validation, mostly - * focusing on default value modifiers (#FIXED, #REQUIRED). - * Validation for specific types are in type-specific additional tests. - */ -public class TestAttributeValidation - extends BaseOutputTest -{ - final String NS_PREFIX = "ns"; - final String NS_PREFIX2 = "ns2"; - final String NS_URI = "http://ns"; - - final String FIXED_DTD_STR = "\n" - +"\n"; - final String REQUIRED_DTD_STR = "\n" - +"\n"; - final String IMPLIED_NS_DTD_STR = "\n" - +"\n"; - - public void testValidFixedAttr() - throws XMLStreamException - { - for (int i = 0; i < 3; ++i) { - boolean nsAware = (i >= 1); - boolean repairing = (i == 2); - StringWriter strw = new StringWriter(); - - // Ok either without being added: - XMLStreamWriter2 sw = getDTDValidatingWriter(strw, FIXED_DTD_STR, nsAware, repairing); - sw.writeStartElement("root"); - sw.writeEndElement(); - sw.writeEndDocument(); - sw.close(); - - sw = getDTDValidatingWriter(strw, FIXED_DTD_STR, nsAware, repairing); - sw.writeEmptyElement("root"); - sw.writeEndDocument(); - sw.close(); - - // or by using the exact same value - sw = getDTDValidatingWriter(strw, FIXED_DTD_STR, nsAware, repairing); - sw.writeStartElement("root"); - sw.writeAttribute("fixAttr", "fixedValue"); - sw.writeEndElement(); - sw.writeEndDocument(); - sw.close(); - } - } - - public void testInvalidFixedAttr() - throws XMLStreamException - { - for (int i = 0; i < 3; ++i) { - boolean nsAware, repairing; - String modeDesc; - - switch (i) { - case 0: - modeDesc = "[non-namespace-aware]"; - nsAware = repairing = false; - break; - case 1: - modeDesc = "[namespace-aware, non-repairing]"; - nsAware = true; - repairing = false; - break; - default: - modeDesc = "[namespace-aware, repairing]"; - nsAware = repairing = true; - break; - } - - // Invalid case, trying to add some other value: - - // non-empty but not same - StringWriter strw = new StringWriter(); - XMLStreamWriter2 sw = getDTDValidatingWriter(strw, FIXED_DTD_STR, nsAware, repairing); - sw.writeStartElement("root"); - try { - sw.writeAttribute("fixAttr", "otherValue"); - fail(modeDesc+" Expected a validation exception when trying to add a #FIXED attribute with 'wrong' value"); - } catch (XMLValidationException vex) { - // expected... - } - // Should not close, since stream is invalid now... - - // empty is not the same as leaving it out: - strw = new StringWriter(); - sw = getDTDValidatingWriter(strw, FIXED_DTD_STR, nsAware, repairing); - sw.writeStartElement("root"); - try { - sw.writeAttribute("fixAttr", ""); - fail(modeDesc+" Expected a validation exception when trying to add a #FIXED attribute with an empty value"); - } catch (XMLValidationException vex) { - // expected... - } - - // And finally, same for empty elem in case impl. is different - strw = new StringWriter(); - sw = getDTDValidatingWriter(strw, FIXED_DTD_STR, nsAware, repairing); - sw.writeEmptyElement("root"); - try { - sw.writeAttribute("fixAttr", "foobar"); - fail(modeDesc+" Expected a validation exception when trying to add a #FIXED attribute with an empty value"); - } catch (XMLValidationException vex) { - // expected... - } - } - } - - public void testValidRequiredAttr() - throws XMLStreamException - { - for (int i = 0; i < 3; ++i) { - boolean nsAware = (i >= 1); - boolean repairing = (i == 2); - StringWriter strw = new StringWriter(); - - // Ok if value is added: - XMLStreamWriter2 sw = getDTDValidatingWriter(strw, REQUIRED_DTD_STR, nsAware, repairing); - sw.writeStartElement("root"); - sw.writeAttribute("reqAttr", "value"); - sw.writeEndElement(); - sw.writeEndDocument(); - sw.close(); - - // ... even if with empty value (for CDATA type, at least) - sw = getDTDValidatingWriter(strw, REQUIRED_DTD_STR, nsAware, repairing); - sw.writeStartElement("root"); - sw.writeAttribute("reqAttr", ""); - sw.writeEndElement(); - sw.writeEndDocument(); - sw.close(); - - // and ditto for empty element: - sw = getDTDValidatingWriter(strw, REQUIRED_DTD_STR, nsAware, repairing); - sw.writeEmptyElement("root"); - sw.writeAttribute("reqAttr", "hii & haa"); - sw.writeEndDocument(); - sw.close(); - } - } - - public void testInvalidRequiredAttr() - throws XMLStreamException - { - for (int i = 0; i < 3; ++i) { - boolean nsAware, repairing; - String modeDesc; - - switch (i) { - case 0: - modeDesc = "[non-namespace-aware]"; - nsAware = repairing = false; - break; - case 1: - modeDesc = "[namespace-aware, non-repairing]"; - nsAware = true; - repairing = false; - break; - default: - modeDesc = "[namespace-aware, repairing]"; - nsAware = repairing = true; - break; - } - - // Invalid case: leaving the required attr out: - StringWriter strw = new StringWriter(); - XMLStreamWriter2 sw = getDTDValidatingWriter(strw, REQUIRED_DTD_STR, nsAware, repairing); - sw.writeStartElement("root"); - try { - sw.writeEndElement(); - fail(modeDesc+" Expected a validation exception when omitting a #REQUIRED attribute"); - } catch (XMLValidationException vex) { - // expected... - } - // Should not close, since stream is invalid now... - } - } - - /** - * Test to ensure that the namespace-prefix mapping works (to the degree - * it can... wrt dtd-non-ns-awareness) with attributes. - */ - public void testValidNsAttr() - throws XMLStreamException - { - for (int i = 0; i < 2; ++i) { - boolean repairing = (i > 0); - StringWriter strw = new StringWriter(); - - /* Ok, as long as we use the right ns prefix... better also - * output namespace declaration, in non-repairing mode. - */ - XMLStreamWriter2 sw = getDTDValidatingWriter(strw, IMPLIED_NS_DTD_STR, true, repairing); - sw.writeStartElement("root"); - if (!repairing) { - sw.writeNamespace(NS_PREFIX, NS_URI); - } - // prefix, uri, localname (for attrs!) - sw.writeAttribute(NS_PREFIX, NS_URI, "attr", "value"); - sw.writeEndElement(); - sw.writeEndDocument(); - sw.close(); - } - } - - public void testInvalidNsAttr() - throws XMLStreamException - { - for (int i = 0; i < 2; ++i) { - boolean repairing; - String modeDesc; - - switch (i) { - case 0: - modeDesc = "[namespace-aware, non-repairing]"; - repairing = false; - break; - default: - modeDesc = "[namespace-aware, repairing]"; - repairing = true; - break; - } - - // Invalid case, trying to use "wrong" prefix: - - StringWriter strw = new StringWriter(); - XMLStreamWriter2 sw = getDTDValidatingWriter(strw, IMPLIED_NS_DTD_STR, true, repairing); - sw.writeStartElement("root"); - if (!repairing) { - sw.writeNamespace(NS_PREFIX, NS_URI); - } - // prefix, uri, localname (for attrs!) - try { - sw.writeAttribute(NS_PREFIX2, NS_URI, "attr", "value"); - fail(modeDesc+" Expected a validation exception when trying to add an attribute with wrong ns prefix"); - } catch (XMLValidationException vex) { - // expected... - } - // Should not close, since stream is invalid now... - } - } - -} - diff -Nru libwoodstox-java-4.1.3/src/test/stax2/vwstream/TestOutputValidation.java libwoodstox-java-5.1.0/src/test/stax2/vwstream/TestOutputValidation.java --- libwoodstox-java-4.1.3/src/test/stax2/vwstream/TestOutputValidation.java 2012-04-24 04:38:21.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/stax2/vwstream/TestOutputValidation.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,320 +0,0 @@ -package stax2.vwstream; - -import java.io.*; - -import javax.xml.stream.*; - -import org.codehaus.stax2.XMLStreamWriter2; -import org.codehaus.stax2.validation.*; - -/** - * Unit test suite that test basic aspects of (DTD validation, - * mostly regarding specialized content types (EMPTY, ANY, #PCDATA) - * - */ -public class TestOutputValidation - extends BaseOutputTest -{ - public void testValidMixedContent() - throws XMLStreamException - { - final String dtdStr = - "\n" - +"\n" - ; - - for (int i = 0; i < 3; ++i) { - boolean nsAware = (i >= 1); - boolean repairing = (i == 2); - StringWriter strw = new StringWriter(); - XMLStreamWriter2 sw = getDTDValidatingWriter(strw, dtdStr, nsAware, repairing); - sw.writeStartElement("root"); - // Should be fine now - sw.writeCharacters("Text that should be ok"); - sw.writeStartElement("branch"); - // Also, all-whitespace is ok in non-mixed too - sw.writeCharacters("\t \t \r \n"); - sw.writeEndElement(); - sw.writeEndElement(); - sw.writeEndDocument(); - } - } - - public void testInvalidMixedContent() - throws XMLStreamException - { - final String dtdStr = - "\n" - +"\n" - ; - - for (int i = 0; i < 3; ++i) { - boolean nsAware = (i >= 1); - boolean repairing = (i == 2); - StringWriter strw = new StringWriter(); - XMLStreamWriter2 sw = getDTDValidatingWriter(strw, dtdStr, nsAware, repairing); - sw.writeStartElement("root"); - // Should get validation exception here: - try { - sw.writeCharacters("Illegal text!"); - fail("Expected a validation exception for non-whitespace text output on non-mixed element content"); - } catch (XMLValidationException vex) { - // expected... - } - } - } - - public void testValidEmptyContent() - throws XMLStreamException - { - final String dtdStr = "\n" - +"\n"; - - for (int i = 0; i < 3; ++i) { - boolean nsAware = (i >= 1); - boolean repairing = (i == 2); - StringWriter strw = new StringWriter(); - - XMLStreamWriter2 sw = getDTDValidatingWriter(strw, dtdStr, nsAware, repairing); - - sw.writeStartElement("root"); - // No content whatsoever is allowed... - sw.writeEndElement(); - sw.writeEndDocument(); - sw.close(); - - // Next; same but with an attribute - sw = getDTDValidatingWriter(strw, dtdStr, nsAware, repairing); - - sw.writeStartElement("root"); - // no content, but attribute is fine - sw.writeAttribute("attr", "value"); - - sw.writeEndElement(); - sw.writeEndDocument(); - sw.close(); - - // And then using empty element write method(s) - sw = getDTDValidatingWriter(strw, dtdStr, nsAware, repairing); - sw.writeEmptyElement("root"); - // note: empty element need/can not be closed - sw.writeEndDocument(); - sw.close(); - - // and finally empty with attribute - sw = getDTDValidatingWriter(strw, dtdStr, nsAware, repairing); - sw.writeEmptyElement("root"); - sw.writeAttribute("attr", "otherValue"); - sw.writeEndDocument(); - sw.close(); - } - } - - public void testInvalidEmptyContent() - throws XMLStreamException - { - final String dtdStr = "\n" - +"\n" - +"\n" - ; - - for (int i = 0; i < 3; ++i) { - boolean nsAware, repairing; - String modeDesc; - - switch (i) { - case 0: - modeDesc = "[non-namespace-aware]"; - nsAware = repairing = false; - break; - case 1: - modeDesc = "[namespace-aware, non-repairing]"; - nsAware = true; - repairing = false; - break; - default: - modeDesc = "[namespace-aware, repairing]"; - nsAware = repairing = true; - break; - } - - StringWriter strw = new StringWriter(); - - // No content whatsoever is allowed with EMPTY. - // Let's first test with a regualr child element: - - XMLStreamWriter2 sw = getDTDValidatingWriter(strw, dtdStr, nsAware, repairing); - sw.writeStartElement("root"); - try { - sw.writeStartElement("leaf"); - fail(modeDesc+" Expected a validation exception when trying to add an element into EMPTY content model"); - } catch (XMLValidationException vex) { - // expected... - } - sw.close(); - - // Then with an empty child - sw = getDTDValidatingWriter(strw, dtdStr, nsAware, repairing); - sw.writeStartElement("root"); - try { - sw.writeEmptyElement("leaf"); - fail(modeDesc+" Expected a validation exception when trying to add an element into EMPTY content model"); - } catch (XMLValidationException vex) { - // expected... - } - sw.close(); - - // Then with any text (even just white space): - sw = getDTDValidatingWriter(strw, dtdStr, nsAware, repairing); - sw.writeStartElement("root"); - try { - sw.writeCharacters(" "); - fail(modeDesc+" Expected a validation exception when trying to any text into EMPTY content model"); - } catch (XMLValidationException vex) { } - sw.close(); - - // Then CDATA - sw = getDTDValidatingWriter(strw, dtdStr, nsAware, repairing); - sw.writeStartElement("root"); - try { - sw.writeCData("foo"); - fail(modeDesc+" Expected a validation exception when trying to add CDATA into EMPTY content model"); - } catch (XMLValidationException vex) { } - sw.close(); - - // Then ENTITY - sw = getDTDValidatingWriter(strw, dtdStr, nsAware, repairing); - sw.writeStartElement("root"); - try { - sw.writeEntityRef("amp"); - fail(modeDesc+" Expected a validation exception when trying to add CDATA into EMPTY content model"); - } catch (XMLValidationException vex) { } - sw.close(); - - // Then comment - sw = getDTDValidatingWriter(strw, dtdStr, nsAware, repairing); - sw.writeStartElement("root"); - try { - sw.writeComment("comment"); - fail(modeDesc+" Expected a validation exception when trying to add comment into EMPTY content model"); - } catch (XMLValidationException vex) { } - sw.close(); - - // Then proc. instr. - sw = getDTDValidatingWriter(strw, dtdStr, nsAware, repairing); - sw.writeStartElement("root"); - try { - sw.writeProcessingInstruction("target", "data"); - fail(modeDesc+" Expected a validation exception when trying to add processing instruction into EMPTY content model"); - } catch (XMLValidationException vex) { } - sw.close(); - } - } - - public void testValidAnyContent() - throws XMLStreamException - { - final String dtdStr = "\n" - +"\n" - +"\n" - ; - - for (int i = 0; i < 3; ++i) { - boolean nsAware = (i >= 1); - boolean repairing = (i == 2); - StringWriter strw = new StringWriter(); - - // First simplest case - XMLStreamWriter2 sw = getDTDValidatingWriter(strw, dtdStr, nsAware, repairing); - sw.writeStartElement("root"); - sw.writeStartElement("leaf"); - sw.writeCharacters("whatever"); - sw.writeEndElement(); - sw.writeEndElement(); - sw.writeEndDocument(); - sw.close(); - - // Then one with no content - sw = getDTDValidatingWriter(strw, dtdStr, nsAware, repairing); - sw.writeStartElement("root"); - sw.writeEndElement(); - sw.writeEndDocument(); - sw.close(); - - // Then one with explicitly empty elem - sw = getDTDValidatingWriter(strw, dtdStr, nsAware, repairing); - sw.writeStartElement("root"); - sw.writeEmptyElement("leaf"); - sw.writeEndElement(); - sw.writeEndDocument(); - sw.close(); - - // Then one with an attribute - sw = getDTDValidatingWriter(strw, dtdStr, nsAware, repairing); - sw.writeStartElement("root"); - sw.writeAttribute("attr", "value"); - sw.writeStartElement("leaf"); - sw.writeEndElement(); - sw.writeEndElement(); - sw.writeEndDocument(); - sw.close(); - } - } - - public void testInvalidAnyContent() - throws XMLStreamException - { - final String dtdStr = "\n" - +"\n" - +"\n"; - - for (int i = 0; i < 3; ++i) { - boolean nsAware, repairing; - String modeDesc; - - switch (i) { - case 0: - modeDesc = "[non-namespace-aware]"; - nsAware = repairing = false; - break; - case 1: - modeDesc = "[namespace-aware, non-repairing]"; - nsAware = true; - repairing = false; - break; - default: - modeDesc = "[namespace-aware, repairing]"; - nsAware = repairing = true; - break; - } - - StringWriter strw = new StringWriter(); - - XMLStreamWriter2 sw = getDTDValidatingWriter(strw, dtdStr, nsAware, repairing); - - /* The only obviously invalid cases are using non-declared - * elements or attributes... so let's test them here (these - * may be redundant to some degree) - */ - sw.writeStartElement("root"); - try { - sw.writeStartElement("unknown"); - fail(modeDesc+" Expected a validation exception when trying to add an undeclared element"); - } catch (XMLValidationException vex) { - // expected... - } - sw.close(); - - // undecl attr: - sw = getDTDValidatingWriter(strw, dtdStr, nsAware, repairing); - sw.writeStartElement("root"); - try { - sw.writeAttribute("unknown", "value"); - fail(modeDesc+" Expected a validation exception when trying to add an undeclared attribute"); - } catch (XMLValidationException vex) { - // expected... - } - sw.close(); - } - } -} diff -Nru libwoodstox-java-4.1.3/src/test/stax2/vwstream/TestStructuralValidation.java libwoodstox-java-5.1.0/src/test/stax2/vwstream/TestStructuralValidation.java --- libwoodstox-java-4.1.3/src/test/stax2/vwstream/TestStructuralValidation.java 2012-04-24 04:38:21.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/stax2/vwstream/TestStructuralValidation.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,263 +0,0 @@ -package stax2.vwstream; - -import java.io.*; - -import javax.xml.stream.*; - -import org.codehaus.stax2.XMLStreamWriter2; -import org.codehaus.stax2.validation.*; - -/** - * Unit tests for testing structural validation (except for test for - * special content types like EMPTY and ANY). - */ -public class TestStructuralValidation - extends BaseOutputTest -{ - final String NS_PREFIX = "ns"; - final String NS_PREFIX2 = "ns2"; - final String NS_URI = "http://ns"; - - final String SIMPLE_DTD = - "\n" - +"\n" - +"\n" - +"\n" - ; - - final String SIMPLE_NS_DTD = - "\n" - +"\n" - ; - - public void testInvalidRootElem() - throws XMLStreamException - { - for (int i = 0; i < 3; ++i) { - boolean nsAware, repairing; - String modeDesc; - - switch (i) { - case 0: - modeDesc = "[non-namespace-aware]"; - nsAware = repairing = false; - break; - case 1: - modeDesc = "[namespace-aware, non-repairing]"; - nsAware = true; - repairing = false; - break; - default: - modeDesc = "[namespace-aware, repairing]"; - nsAware = repairing = true; - break; - } - - StringWriter strw = new StringWriter(); - - /* Ok; can test for "wrong" root element only if we explicitly - * output DOCTYPE declaration with specific name... - */ - XMLStreamWriter2 sw = getDTDValidatingWriter(strw, SIMPLE_DTD, nsAware, repairing); - sw.writeDTD("root", "http://foo", "public-id", SIMPLE_DTD); - try { - sw.writeStartElement("branch"); - fail(modeDesc+" Expected a validation exception when trying to write wrong root element"); - } catch (XMLValidationException vex) { - // expected... - } - // should not continue after exception; state may not be valid - - // And then undeclared root: - sw = getDTDValidatingWriter(strw, SIMPLE_DTD, nsAware, repairing); - try { - sw.writeStartElement("undefined"); - fail(modeDesc+" Expected a validation exception when trying to write an undefined root element"); - } catch (XMLValidationException vex) { - // expected... - } - - // and same for explicitly empty element; wrong root - sw = getDTDValidatingWriter(strw, SIMPLE_DTD, nsAware, repairing); - sw.writeDTD("root", "http://foo", "public-id", SIMPLE_DTD); - try { - sw.writeEmptyElement("branch"); - fail(modeDesc+" Expected a validation exception when trying to write wrong root element"); - } catch (XMLValidationException vex) { - // expected... - } - } - } - - public void testValidStructure() - throws XMLStreamException - { - for (int i = 0; i < 3; ++i) { - boolean nsAware = (i >= 1); - boolean repairing = (i == 2); - - StringWriter strw = new StringWriter(); - XMLStreamWriter2 sw = getDTDValidatingWriter(strw, SIMPLE_DTD, nsAware, repairing); - sw.writeStartElement("root"); - sw.writeCharacters(" "); // imitating indentation - sw.writeStartElement("branch"); - sw.writeEndElement(); - sw.writeStartElement("branch"); - sw.writeCharacters("test"); - sw.writeComment("comment"); - sw.writeEndElement(); - sw.writeEmptyElement("branch"); - sw.writeEmptyElement("end"); - sw.writeAttribute("endAttr", "value"); - sw.writeCharacters("\n"); // imitating indentation - sw.writeEndElement(); // for root - } - } - - public void testInvalidStructure() - throws XMLStreamException - { - for (int i = 0; i < 3; ++i) { - boolean nsAware, repairing; - String modeDesc; - - switch (i) { - case 0: - modeDesc = "[non-namespace-aware]"; - nsAware = repairing = false; - break; - case 1: - modeDesc = "[namespace-aware, non-repairing]"; - nsAware = true; - repairing = false; - break; - default: - modeDesc = "[namespace-aware, repairing]"; - nsAware = repairing = true; - break; - } - - StringWriter strw = new StringWriter(); - - // Let's try omitting the end element, first... - - XMLStreamWriter2 sw = getDTDValidatingWriter(strw, SIMPLE_DTD, nsAware, repairing); - sw.writeStartElement("root"); - sw.writeCharacters(" "); // imitating indentation - sw.writeStartElement("branch"); - sw.writeEndElement(); - sw.writeStartElement("branch"); - sw.writeCharacters("test"); - sw.writeComment("comment"); - sw.writeEndElement(); - sw.writeEmptyElement("branch"); - sw.writeCharacters("\n"); // imitating indentation - try { - sw.writeEndElement(); // for root - fail(modeDesc+" Expected a validation exception when omitting non-optional element"); - } catch (XMLValidationException vex) { - // expected... - } - // should not continue after exception; state may not be valid - - // And then leaving out branch... - sw = getDTDValidatingWriter(strw, SIMPLE_DTD, nsAware, repairing); - sw.writeStartElement("root"); - sw.writeCharacters(" "); // imitating indentation - sw.writeComment("comment"); - try { - sw.writeEmptyElement("end"); - fail(modeDesc+" Expected a validation exception when omitting non-optional element"); - } catch (XMLValidationException vex) { - // expected... - } - } - } - - public void testValidNsElem() - throws XMLStreamException - { - for (int i = 0; i < 3; ++i) { - boolean repairing = (i == 2); - StringWriter strw = new StringWriter(); - - XMLStreamWriter2 sw = getDTDValidatingWriter(strw, SIMPLE_NS_DTD, true, repairing); - // prefix, local name, uri (for elems) - sw.writeStartElement(NS_PREFIX, "root", NS_URI); - if (!repairing) { - sw.writeNamespace(NS_PREFIX, NS_URI); - } - sw.writeEndElement(); - sw.writeEndDocument(); - sw.close(); - - // and same with empty elem - sw = getDTDValidatingWriter(strw, SIMPLE_NS_DTD, true, repairing); - sw.writeEmptyElement(NS_PREFIX, "root", NS_URI); - if (!repairing) { - sw.writeNamespace(NS_PREFIX, NS_URI); - } - sw.writeEndDocument(); - sw.close(); - } - } - - /** - * Let's also do quick testing on structure that would be ok but - * where namespace prefix is not what dtd expects... - */ - public void testInvalidNsElem() - throws XMLStreamException - { - for (int i = 0; i < 2; ++i) { - boolean repairing; - String modeDesc; - - switch (i) { - case 0: - modeDesc = "[namespace-aware, non-repairing]"; - repairing = false; - break; - default: - modeDesc = "[namespace-aware, repairing]"; - repairing = true; - break; - } - - StringWriter strw = new StringWriter(); - - // Let's try omitting the end element, first... - - XMLStreamWriter2 sw = getDTDValidatingWriter(strw, SIMPLE_NS_DTD, true, repairing); - // prefix, local name, uri (for elems) - try { - sw.writeStartElement(NS_PREFIX2, "root", NS_URI); - fail(modeDesc+" Expected a validation exception when passing wrong (unexpected) ns for element"); - } catch (XMLValidationException vex) { - // expected... - } - // should not continue after exception; state may not be valid - - // and then the same for empty elem - sw = getDTDValidatingWriter(strw, SIMPLE_NS_DTD, true, repairing); - // prefix, local name, uri (for elems) - try { - sw.writeEmptyElement(NS_PREFIX2, NS_URI, "root"); - fail(modeDesc+" Expected a validation exception when passing wrong (unexpected) ns for element"); - } catch (XMLValidationException vex) { - // expected... - } - - // Oh, and finally, using non-ns DTD: - sw = getDTDValidatingWriter(strw, SIMPLE_DTD, true, repairing); - // prefix, local name, uri (for elems) - try { - sw.writeEmptyElement(NS_PREFIX, NS_URI, "root"); - fail(modeDesc+" Expected a validation exception when passing wrong (unexpected) ns for element"); - } catch (XMLValidationException vex) { - // expected... - } - } - } -} - diff -Nru libwoodstox-java-4.1.3/src/test/stax2/wstream/BaseWriterTest.java libwoodstox-java-5.1.0/src/test/stax2/wstream/BaseWriterTest.java --- libwoodstox-java-4.1.3/src/test/stax2/wstream/BaseWriterTest.java 2012-04-24 04:38:21.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/stax2/wstream/BaseWriterTest.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,70 +0,0 @@ -package stax2.wstream; - -import java.io.*; - -import javax.xml.stream.*; - -import org.codehaus.stax2.*; - -/** - * Base class for all StaxTest unit tests that test basic - * stream (cursor) writer API functionality. - * - * @author Tatu Saloranta - */ -public abstract class BaseWriterTest - extends stax2.BaseStax2Test -{ - public XMLStreamWriter2 getRepairingWriter(Writer w) - throws XMLStreamException - { - XMLOutputFactory f = getOutputFactory(); - f.setProperty(XMLStreamProperties.XSP_NAMESPACE_AWARE, Boolean.TRUE); - f.setProperty(XMLOutputFactory.IS_REPAIRING_NAMESPACES, - Boolean.TRUE); - return (XMLStreamWriter2) f.createXMLStreamWriter(w); - } - - public XMLStreamWriter2 getRepairingWriter(Writer w, String enc) - throws XMLStreamException - { - XMLOutputFactory2 f = getOutputFactory(); - f.setProperty(XMLStreamProperties.XSP_NAMESPACE_AWARE, Boolean.TRUE); - f.setProperty(XMLOutputFactory.IS_REPAIRING_NAMESPACES, - Boolean.TRUE); - return (XMLStreamWriter2) f.createXMLStreamWriter(w, enc); - } - - public XMLStreamWriter2 getNonRepairingWriter(Writer w, boolean nsAware) - throws XMLStreamException - { - XMLOutputFactory f = getOutputFactory(); - f.setProperty(XMLOutputFactory.IS_REPAIRING_NAMESPACES, - Boolean.FALSE); - f.setProperty(XMLStreamProperties.XSP_NAMESPACE_AWARE, - Boolean.valueOf(nsAware)); - return (XMLStreamWriter2) f.createXMLStreamWriter(w); - } - - public XMLStreamWriter2 getNonRepairingWriter(Writer w, String enc, boolean nsAware) - throws XMLStreamException - { - XMLOutputFactory2 f = getOutputFactory(); - f.setProperty(XMLOutputFactory.IS_REPAIRING_NAMESPACES, - Boolean.FALSE); - f.setProperty(XMLStreamProperties.XSP_NAMESPACE_AWARE, - Boolean.valueOf(nsAware)); - return (XMLStreamWriter2) f.createXMLStreamWriter(w, enc); - } - - public XMLStreamWriter2 getNonRepairingWriter(OutputStream os, String enc, boolean nsAware) - throws XMLStreamException - { - XMLOutputFactory2 f = getOutputFactory(); - f.setProperty(XMLOutputFactory.IS_REPAIRING_NAMESPACES, - Boolean.FALSE); - f.setProperty(XMLStreamProperties.XSP_NAMESPACE_AWARE, - Boolean.valueOf(nsAware)); - return (XMLStreamWriter2) f.createXMLStreamWriter(os, enc); - } -} diff -Nru libwoodstox-java-4.1.3/src/test/stax2/wstream/TestClosing.java libwoodstox-java-5.1.0/src/test/stax2/wstream/TestClosing.java --- libwoodstox-java-4.1.3/src/test/stax2/wstream/TestClosing.java 2012-04-24 04:38:21.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/stax2/wstream/TestClosing.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,236 +0,0 @@ -package stax2.wstream; - -import java.io.*; -import javax.xml.stream.*; -import javax.xml.transform.stream.StreamResult; - -import org.codehaus.stax2.*; -import org.codehaus.stax2.io.Stax2BlockResult; - -/** - * This unit test suite verifies that the auto-closing feature works - * as expected (both explicitly, and via Result object being passed). - */ -public class TestClosing - extends BaseWriterTest -{ - /** - * This unit test checks the default behaviour; with no auto-close, no - * automatic closing should occur, nor explicit one unless specific - * forcing method is used. - */ - public void testNoAutoCloseWriter() - throws XMLStreamException - { - XMLOutputFactory2 f = getFactory(false); - MyWriter output = new MyWriter(); - XMLStreamWriter2 sw = (XMLStreamWriter2) f.createXMLStreamWriter(output); - // shouldn't be closed to begin with... - assertFalse(output.isClosed()); - writeDoc(sw); - assertFalse(output.isClosed()); - - // nor closed half-way through with basic close() - sw.close(); - assertFalse(output.isClosed()); - - // but needs to close when forced to: - sw.closeCompletely(); - assertTrue(output.isClosed()); - - // ... and should be ok to call it multiple times: - sw.closeCompletely(); - sw.closeCompletely(); - assertTrue(output.isClosed()); - } - - public void testNoAutoCloseStream() - throws XMLStreamException - { - XMLOutputFactory2 f = getFactory(false); - MyStream output = new MyStream(); - XMLStreamWriter2 sw = (XMLStreamWriter2) f.createXMLStreamWriter(output, "UTF-8"); - // shouldn't be closed to begin with... - assertFalse(output.isClosed()); - writeDoc(sw); - assertFalse(output.isClosed()); - - // nor closed half-way through with basic close() - sw.close(); - assertFalse(output.isClosed()); - - // but needs to close when forced to: - sw.closeCompletely(); - assertTrue(output.isClosed()); - - // ... and should be ok to call it multiple times: - sw.closeCompletely(); - sw.closeCompletely(); - assertTrue(output.isClosed()); - } - - /** - * This unit test checks that when auto-closing option is set, the - * passed in output stream does get properly closed - * when we call close(), as well as when do writeEndDocument(). - */ - public void testEnabledAutoClose() - throws XMLStreamException - { - // First, explicit close: - XMLOutputFactory2 f = getFactory(true); - MyWriter output = new MyWriter(); - XMLStreamWriter2 sw = (XMLStreamWriter2) f.createXMLStreamWriter(output); - assertFalse(output.isClosed()); - - writeDoc(sw); - - sw.close(); - assertTrue(output.isClosed()); - - // also, let's verify we can call more than once: - sw.close(); - sw.close(); - assertTrue(output.isClosed()); - - // Then implicit close: - output = new MyWriter(); - sw = (XMLStreamWriter2) f.createXMLStreamWriter(output); - writeDoc(sw); - assertTrue(output.isClosed()); - } - - /** - * This unit test checks what happens when we use Result abstraction - * for passing in result stream/writer. Their handling differs depending - * on whether caller is considered to have access to the underlying - * physical object or not. - */ - public void testAutoCloseImplicit() - throws XMLStreamException - { - XMLOutputFactory2 f = getFactory(false); // auto-close disabled - - /* Ok, first: with regular (OutputStream, Writer) results not auto-closing - * because caller does have access: StreamResult does retain given - * stream/writer as is. - */ - MyResult output = new MyResult(); - XMLStreamWriter2 sw = (XMLStreamWriter2) f.createXMLStreamWriter(output); - assertFalse(output.isClosed()); - writeDoc(sw); - sw.close(); - assertFalse(output.isClosed()); - - /* And then more interesting case; verifying that Stax2Source - * sub-classes are implicitly auto-closed: they need to be, because - * they do not (necessarily) expose underlying physical stream. - * We can test this by using any Stax2Source impl. - */ - MyStringResult result = new MyStringResult(); - sw = (XMLStreamWriter2) f.createXMLStreamWriter(result); - // closed if we write end doc - writeDoc(sw); - assertTrue(result.isClosed()); - - // as well as if we just call regular close - result = new MyStringResult(); - sw = (XMLStreamWriter2) f.createXMLStreamWriter(result); - sw.writeStartDocument(); - sw.writeEmptyElement("test"); - // no call to write end doc, so writer can't yet close; but we do call close: - sw.close(); - assertTrue(result.isClosed()); - } - - /* - //////////////////////////////////////// - // Non-test methods - //////////////////////////////////////// - */ - - XMLOutputFactory2 getFactory(boolean autoClose) - { - XMLOutputFactory2 f = getOutputFactory(); - f.setProperty(XMLOutputFactory2.P_AUTO_CLOSE_OUTPUT, Boolean.valueOf(autoClose)); - return f; - } - - void writeDoc(XMLStreamWriter sw) throws XMLStreamException - { - sw.writeStartDocument(); - sw.writeEmptyElement("root"); - sw.writeEndDocument(); - } - - /* - //////////////////////////////////////// - // Helper mock classes - //////////////////////////////////////// - */ - - final static class MyWriter - extends StringWriter - { - boolean mIsClosed = false; - - public MyWriter() { } - - public void close() throws IOException { - mIsClosed = true; - super.close(); - } - - public boolean isClosed() { return mIsClosed; } - } - - final static class MyStream - extends ByteArrayOutputStream - { - boolean mIsClosed = false; - - public MyStream() { } - - public void close() throws IOException { - mIsClosed = true; - super.close(); - } - public boolean isClosed() { return mIsClosed; } - } - - final static class MyResult - extends StreamResult - { - final MyWriter mWriter; - - private MyResult() { - super(); - mWriter = new MyWriter(); - setWriter(mWriter); - } - - public boolean isClosed() { - return mWriter.isClosed(); - } - } - - /** - * Need a helper class to verify whether resources (OutputStream, Writer) - * created via Stax2Result instances are (auto)closed or not. - */ - private final static class MyStringResult - extends Stax2BlockResult - { - MyWriter mWriter; - - public MyStringResult() { super(); } - - public Writer constructWriter() { - mWriter = new MyWriter(); - return mWriter; - } - public OutputStream constructOutputStream() { return null; } - - public boolean isClosed() { return mWriter.isClosed(); } - } -} diff -Nru libwoodstox-java-4.1.3/src/test/stax2/wstream/TestConfig.java libwoodstox-java-5.1.0/src/test/stax2/wstream/TestConfig.java --- libwoodstox-java-4.1.3/src/test/stax2/wstream/TestConfig.java 2012-04-24 04:38:21.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/stax2/wstream/TestConfig.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,32 +0,0 @@ -package stax2.wstream; - -import javax.xml.stream.*; - -import org.codehaus.stax2.*; - -/** - * Set of unit tests that checks that configuring of - * {@link XMLOutputFactory2} works ok. - *

- * Note: for now there isn't much meat in this unit test: it's mostly - * used to do simple smoke testing for profile setters. - */ -public class TestConfig - extends BaseWriterTest -{ - public void testProfiles() - throws XMLStreamException - { - // configureForXmlConformance - XMLOutputFactory2 ofact = getNewOutputFactory(); - ofact.configureForXmlConformance(); - - // configureForRobustness - ofact = getNewOutputFactory(); - ofact.configureForRobustness(); - - // configureForSpeed - ofact = getNewOutputFactory(); - ofact.configureForSpeed(); - } -} diff -Nru libwoodstox-java-4.1.3/src/test/stax2/wstream/TestEscaping.java libwoodstox-java-5.1.0/src/test/stax2/wstream/TestEscaping.java --- libwoodstox-java-4.1.3/src/test/stax2/wstream/TestEscaping.java 2012-04-24 04:38:21.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/stax2/wstream/TestEscaping.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,133 +0,0 @@ -package stax2.wstream; - -import java.io.*; - -import javax.xml.stream.*; - -import org.codehaus.stax2.*; - -/** - * This test checks to see that text/attribute value escaping is - * working properly. - */ -public class TestEscaping - extends BaseWriterTest -{ - /** - * This test checks that even though it's 'wrong' to use non-URL/URI - * namespace URIs, it's not a fatal error; and that the 'uri' value - * should come back as it was written out. - */ - public void testBrokenNsURLs() - throws XMLStreamException - { - final String BROKEN_URL1 = ""; - final String BROKEN_URL2 = "\""; - final String BROKEN_URL3 = "x&"; - - StringWriter strw = new StringWriter(); - XMLStreamWriter2 w = getNonRepairingWriter(strw, true); - - w.writeStartDocument(); - w.writeStartElement("", "test", ""); - w.writeNamespace("ns", BROKEN_URL1); - w.writeStartElement("", "test", ""); - w.writeNamespace("ns", BROKEN_URL2); - w.writeStartElement("", "test", ""); - w.writeNamespace("ns", BROKEN_URL3); - - w.writeEndElement(); - w.writeEndElement(); - w.writeEndElement(); - - w.writeEndDocument(); - w.close(); - - // And then let's parse and verify it all: - - String input = strw.toString(); - - XMLStreamReader sr = constructNsStreamReader(input, true); - assertTokenType(START_DOCUMENT, sr.getEventType()); - - assertTokenType(START_ELEMENT, sr.next()); - assertEquals("test", sr.getLocalName()); - assertEquals(1, sr.getNamespaceCount()); - assertEquals("ns", sr.getNamespacePrefix(0)); - assertEquals(BROKEN_URL1, sr.getNamespaceURI(0)); - - assertTokenType(START_ELEMENT, sr.next()); - assertEquals("test", sr.getLocalName()); - assertEquals(1, sr.getNamespaceCount()); - assertEquals("ns", sr.getNamespacePrefix(0)); - assertEquals(BROKEN_URL2, sr.getNamespaceURI(0)); - - assertTokenType(START_ELEMENT, sr.next()); - assertEquals("test", sr.getLocalName()); - assertEquals(1, sr.getNamespaceCount()); - assertEquals("ns", sr.getNamespacePrefix(0)); - assertEquals(BROKEN_URL3, sr.getNamespaceURI(0)); - - assertTokenType(END_ELEMENT, sr.next()); - assertTokenType(END_ELEMENT, sr.next()); - assertTokenType(END_ELEMENT, sr.next()); - - assertTokenType(END_DOCUMENT, sr.next()); - - sr.close(); - } - - public void testLatin1Quoting() - throws XMLStreamException - { - final String TEXT = "ab\u00A0cd\tef\u00D8gh\u3c00..."; - - ByteArrayOutputStream bos = new ByteArrayOutputStream(); - XMLStreamWriter2 w = getNonRepairingWriter(bos, "ISO-8859-1", true); - - w.writeStartDocument(); - w.writeStartElement("root"); - w.writeCharacters(TEXT); - w.writeEndElement(); - w.writeEndDocument(); - w.close(); - - InputStream in = new ByteArrayInputStream(bos.toByteArray()); - XMLStreamReader sr = constructNsStreamReader(in, true); - assertTokenType(START_DOCUMENT, sr.getEventType()); - assertTokenType(START_ELEMENT, sr.next()); - assertEquals("root", sr.getLocalName()); - assertTokenType(CHARACTERS, sr.next()); - - assertEquals(TEXT, sr.getText()); - - assertTokenType(END_ELEMENT, sr.next()); - } - - public void testAsciiQuoting() - throws XMLStreamException - { - final String TEXT = "ab\u00A0cd\tef\u00D8gh\u3c00..."; - - ByteArrayOutputStream bos = new ByteArrayOutputStream(); - XMLStreamWriter2 w = getNonRepairingWriter(bos, "US-ASCII", true); - - w.writeStartDocument(); - w.writeStartElement("root"); - w.writeCharacters(TEXT); - w.writeEndElement(); - w.writeEndDocument(); - w.close(); - - InputStream in = new ByteArrayInputStream(bos.toByteArray()); - XMLStreamReader sr = constructNsStreamReader(in, true); - assertTokenType(START_DOCUMENT, sr.getEventType()); - assertTokenType(START_ELEMENT, sr.next()); - assertEquals("root", sr.getLocalName()); - assertTokenType(CHARACTERS, sr.next()); - - assertEquals(TEXT, sr.getText()); - - assertTokenType(END_ELEMENT, sr.next()); - } -} diff -Nru libwoodstox-java-4.1.3/src/test/stax2/wstream/TestNamespaceCopying.java libwoodstox-java-5.1.0/src/test/stax2/wstream/TestNamespaceCopying.java --- libwoodstox-java-4.1.3/src/test/stax2/wstream/TestNamespaceCopying.java 2012-04-24 04:38:21.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/stax2/wstream/TestNamespaceCopying.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,70 +0,0 @@ -package stax2.wstream; - -import java.io.*; -import java.util.*; - -import javax.xml.parsers.DocumentBuilderFactory; -import javax.xml.parsers.ParserConfigurationException; -import javax.xml.stream.*; -import javax.xml.transform.dom.DOMResult; - -import org.w3c.dom.Document; -import org.w3c.dom.Element; - -/** - * Tests that namespaces are written to the output stream in namespace - * repairing mode. See [WSTX-193] for details. - * - * @author Christopher Paul Simmons - */ -public class TestNamespaceCopying - extends BaseWriterTest -{ - XMLInputFactory _inputFactory; - XMLOutputFactory _outputFactory; - XMLEventFactory _eventFactory; - - protected void setUp() throws Exception { - _outputFactory = getOutputFactory(); - setRepairing(_outputFactory, true); - _eventFactory = getEventFactory(); - _inputFactory = getInputFactory(); - } - - public void testStreamXMLNSDeclaration() throws Exception { - final StringWriter stringWriter = new StringWriter(); - XMLEventWriter xmlWriter = _outputFactory.createXMLEventWriter(stringWriter); - xmlWriter.add(_eventFactory.createStartDocument("UFT-8")); - List l = new ArrayList(); - l.add(_eventFactory.createNamespace("bar", "barNS")); - xmlWriter.add(_eventFactory.createStartElement("foo", "fooNS", "root", Collections.EMPTY_LIST.iterator(), l.iterator())); - xmlWriter.add(_eventFactory.createNamespace("baz", "bazNS")); - xmlWriter.add(_eventFactory.createCharacters("bar:qname")); - xmlWriter.add(_eventFactory.createEndElement("foo", "fooNS", "root")); - xmlWriter.add(_eventFactory.createEndDocument()); - - // The document is just to inspect the result. - final Document document = buildDocument(stringWriter.toString()); - - Element documentElement = document.getDocumentElement(); - assertEquals("fooNS", getNamespaceForPrefix(documentElement, "foo")); - // This line fails in 3.2.7 - assertEquals("barNS", getNamespaceForPrefix(documentElement, "bar")); - assertEquals("bazNS", getNamespaceForPrefix(documentElement, "baz")); - } - - private String getNamespaceForPrefix(final Element element, final String prefix) { - return element.getAttributeNS("http://www.w3.org/2000/xmlns/", prefix); - } - - private Document buildDocument(final String string) throws XMLStreamException, ParserConfigurationException { - // Less painful to do this using XMLUnit if you use it. - XMLEventReader reader = _inputFactory.createXMLEventReader(new StringReader(string)); - final DocumentBuilderFactory documentBuilder = DocumentBuilderFactory.newInstance(); - documentBuilder.setNamespaceAware(true); - final Document document = documentBuilder.newDocumentBuilder().newDocument(); - XMLEventWriter writer = _outputFactory.createXMLEventWriter(new DOMResult(document)); - writer.add(reader); - return document; - } -} diff -Nru libwoodstox-java-4.1.3/src/test/stax2/wstream/TestStreamResult.java libwoodstox-java-5.1.0/src/test/stax2/wstream/TestStreamResult.java --- libwoodstox-java-4.1.3/src/test/stax2/wstream/TestStreamResult.java 2012-04-24 04:38:21.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/stax2/wstream/TestStreamResult.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,49 +0,0 @@ -package stax2.wstream; - -import java.io.*; -import javax.xml.stream.*; -import javax.xml.transform.stream.StreamResult; - -import org.codehaus.stax2.XMLInputFactory2; - -import stax2.BaseStax2Test; - -/** - * This unit test suite verifies use of {@link StreamResult} as output - * for {@link XMLOutputFactory}. - * - * @author Tatu Saloranta - * - * @since 3.0 - */ -public class TestStreamResult - extends BaseStax2Test -{ - /** - * This test is related to problem reported as [WSTX-182], inability - * to use SystemId alone as source. - */ - public void testCreateUsingSystemId() - throws IOException, XMLStreamException - { - File tmpF = File.createTempFile("staxtest", ".xml"); - tmpF.deleteOnExit(); - - XMLOutputFactory f = getOutputFactory(); - StreamResult dst = new StreamResult(); - dst.setSystemId(tmpF); - XMLStreamWriter sw = f.createXMLStreamWriter(dst); - - sw.writeStartDocument(); - sw.writeEmptyElement("root"); - sw.writeEndDocument(); - sw.close(); - - // plus let's read and check it - XMLInputFactory2 inf = getInputFactory(); - XMLStreamReader sr = inf.createXMLStreamReader(tmpF); - assertTokenType(START_ELEMENT, sr.next()); - assertTokenType(END_ELEMENT, sr.next()); - sr.close(); - } -} diff -Nru libwoodstox-java-4.1.3/src/test/stax2/wstream/TestStreamWriter.java libwoodstox-java-5.1.0/src/test/stax2/wstream/TestStreamWriter.java --- libwoodstox-java-4.1.3/src/test/stax2/wstream/TestStreamWriter.java 2012-04-24 04:38:22.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/stax2/wstream/TestStreamWriter.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,428 +0,0 @@ -package stax2.wstream; - -import java.io.*; - -import javax.xml.stream.*; - -import org.codehaus.stax2.*; - -/** - * Unit test suite that focuses on testing additional methods that - * StAX2 has for stream writers. - */ -public class TestStreamWriter - extends BaseWriterTest -{ - /* - ////////////////////////////////////////////////////////// - // First tests for simple accessors - ////////////////////////////////////////////////////////// - */ - - public void testGetEncoding() - throws XMLStreamException - { - // Let's test with US-ASCII for fun - final String ENC = "US-ASCII"; - - for (int isWriter = 0; isWriter < 2; ++isWriter) { - for (int i = 0; i < 3; ++i) { - boolean ns = (i > 0); - boolean repairing = (i == 2); - XMLOutputFactory2 of = getFactory(ns, repairing); - XMLStreamWriter2 w; - - if (isWriter > 0) { - StringWriter strw = new StringWriter(); - w = (XMLStreamWriter2)of.createXMLStreamWriter(strw, ENC); - } else { - ByteArrayOutputStream bos = new ByteArrayOutputStream(); - w = (XMLStreamWriter2)of.createXMLStreamWriter(bos, ENC); - } - assertEquals(ENC, w.getEncoding()); - // Need to output something, otherwise it'll be empty doc - w.writeEmptyElement("root"); - w.close(); - - /* Ok good, but how about the case where it's only - * passed for writeStartDocument()? Note: when wrapping - * a stream, factory has to use default (UTF-8). - */ - if (isWriter > 0) { - StringWriter strw = new StringWriter(); - w = (XMLStreamWriter2)of.createXMLStreamWriter(strw); - w.writeStartDocument(ENC, "1.0"); - assertEquals(ENC, w.getEncoding()); - } else { - ByteArrayOutputStream bos = new ByteArrayOutputStream(); - w = (XMLStreamWriter2)of.createXMLStreamWriter(bos); - w.writeStartDocument(ENC, "1.0"); - assertEquals("UTF-8", w.getEncoding()); - } - w.writeEmptyElement("root"); - w.close(); - } - } - } - - /** - * Additional tests based on [WSTX-146]; JDK may report legacy - * encoding names, we shouldn't report those but rather IANA - * approved canonical equivalents. - */ - public void testLegacyEncodings() - throws Exception - { - String[] encs = new String[] { "UTF-8", "US-ASCII", "ISO-8859-1" }; - - XMLOutputFactory2 outf = getFactory(true, false); - XMLInputFactory2 inf = getNewInputFactory(); - - for (int i = 0; i < encs.length; ++i) { - String enc = encs[i]; - ByteArrayOutputStream os = new ByteArrayOutputStream(); - XMLStreamWriter sw = outf.createXMLStreamWriter(new OutputStreamWriter(os, enc)); - sw.writeStartDocument("1.0"); - sw.writeEmptyElement("foo"); - sw.writeEndDocument(); - // Parse it and check the encoding - XMLStreamReader sr = inf.createXMLStreamReader(new ByteArrayInputStream(os.toByteArray())); - String act = sr.getCharacterEncodingScheme(); - if (!enc.equals(act)) { - fail("Expected encoding to be returned correctly as \""+enc+"\", got \""+act+"\""); - } - } - } - - /** - * Since Woodstox doesn't yet actually implement the method, we'll - * just call the method and do not expect and exception. Returned - * object (or lack thereof) is not inspected - */ - public void testGetLocation() - throws XMLStreamException - { - for (int i = 0; i < 3; ++i) { - boolean ns = (i > 0); - boolean repairing = (i == 2); - XMLOutputFactory2 of = getFactory(ns, repairing); - StringWriter strw = new StringWriter(); - XMLStreamWriter2 w = (XMLStreamWriter2)of.createXMLStreamWriter(strw); - XMLStreamLocation2 loc = w.getLocation(); - assertNotNull(loc); - // Need to output something, otherwise it'll be empty doc - w.writeEmptyElement("root"); - w.close(); - } - } - - /* - ////////////////////////////////////////////////////////// - // Then new output methods, or improved existing ones - ////////////////////////////////////////////////////////// - */ - - public void testCData() - throws XMLStreamException - { - final String CDATA_TEXT = "Let's test it with some ] ]> data; s and && chars and all!"; - - for (int i = 0; i < 2; ++i) { - boolean ns = (i > 0); - StringWriter strw = new StringWriter(); - XMLStreamWriter2 w = getNonRepairingWriter(strw, ns); - - w.writeStartDocument(); - w.writeStartElement("test"); - - char[] cbuf = new char[CDATA_TEXT.length() + 10]; - CDATA_TEXT.getChars(0, CDATA_TEXT.length(), cbuf, 3); - w.writeCData(cbuf, 3, CDATA_TEXT.length()); - w.writeEndElement(); - w.writeEndDocument(); - w.close(); - - // And then let's parse and verify it all: - - XMLStreamReader sr = constructNsStreamReader(strw.toString(), true); - assertTokenType(START_DOCUMENT, sr.getEventType()); - assertTokenType(START_ELEMENT, sr.next()); - - // Now, parsers are allowed to report CHARACTERS or CDATA - int tt = sr.next(); - if (tt != CHARACTERS && tt != CDATA) { - assertTokenType(CDATA, tt); // to cause failure - } - assertFalse(sr.isWhiteSpace()); - assertEquals(CDATA_TEXT, getAndVerifyText(sr)); - assertTokenType(END_ELEMENT, sr.next()); - assertTokenType(END_DOCUMENT, sr.next()); - } - } - - /** - * This test was inspired by a failing regression test: it required - * long enough COMMENT content to trigger buffar boundary problems - */ - public void testLongerComment() - throws XMLStreamException - { - doTestLonger(COMMENT, false, false, "UTF-8"); - doTestLonger(COMMENT, false, false, "ISO-8859-1"); - doTestLonger(COMMENT, false, false, "US-ASCII"); - doTestLonger(COMMENT, true, false, "UTF-8"); - doTestLonger(COMMENT, true, false, "ISO-8859-1"); - doTestLonger(COMMENT, true, false, "US-ASCII"); - doTestLonger(COMMENT, true, true, "UTF-8"); - doTestLonger(COMMENT, true, true, "ISO-8859-1"); - doTestLonger(COMMENT, true, true, "US-ASCII"); - } - - public void testLongerPI() - throws XMLStreamException - { - doTestLonger(PROCESSING_INSTRUCTION, false, false, "UTF-8"); - doTestLonger(PROCESSING_INSTRUCTION, false, false, "ISO-8859-1"); - doTestLonger(PROCESSING_INSTRUCTION, false, false, "US-ASCII"); - doTestLonger(PROCESSING_INSTRUCTION, true, false, "UTF-8"); - doTestLonger(PROCESSING_INSTRUCTION, true, false, "ISO-8859-1"); - doTestLonger(PROCESSING_INSTRUCTION, true, false, "US-ASCII"); - doTestLonger(PROCESSING_INSTRUCTION, true, true, "UTF-8"); - doTestLonger(PROCESSING_INSTRUCTION, true, true, "ISO-8859-1"); - doTestLonger(PROCESSING_INSTRUCTION, true, true, "US-ASCII"); - } - - public void testCopy() - throws XMLStreamException - { - final String XML = - "\n" - +" ]>\n" - +"\n" - +"" - +"Text: & " - +" there you have it!]]>" - +"" - ; - - for (int i = 0; i < 2; ++i) { - boolean ns = (i > 0); - //boolean repairing = (i == 2); - boolean repairing = (i == 1); - XMLStreamReader2 sr = constructNsStreamReader(XML, ns); - StringWriter strw = new StringWriter(); - XMLStreamWriter2 w; - - if (repairing) { - w = getRepairingWriter(strw); - } else { - w = getNonRepairingWriter(strw, ns); - } - - while (sr.hasNext()) { - sr.next(); - w.copyEventFromReader(sr, false); - } - sr.close(); - w.close(); - String xmlOut = strw.toString(); - - // And let's parse it to verify it's still well-formed... - // (should also verify its accuracy...) - sr = constructNsStreamReader(xmlOut, ns); - streamThrough(sr); - } - } - - /** - * Unit test for verifyin that writeRaw() works as expected. - */ - public void testRaw() - throws XMLStreamException - { - String RAW2 = "foo&bar"; - - for (int i = 0; i < 3; ++i) { - boolean ns = (i > 0); - StringWriter strw = new StringWriter(); - XMLStreamWriter2 w = (i == 2) ? getRepairingWriter(strw) - : getNonRepairingWriter(strw, ns); - w.writeStartDocument(); - w.writeStartElement("test"); - w.writeAttribute("attr", "value"); - w.writeRaw("this or 'that'"); - char[] cbuf = new char[RAW2.length() + 10]; - RAW2.getChars(0, RAW2.length(), cbuf, 3); - w.writeRaw(cbuf, 3, RAW2.length()); - w.writeEndElement(); - w.writeEndDocument(); - w.close(); - - // And then let's parse and verify it all: - XMLStreamReader sr = constructNsStreamReader(strw.toString(), true); - assertTokenType(START_DOCUMENT, sr.getEventType()); - assertTokenType(START_ELEMENT, sr.next()); - assertEquals("test", sr.getLocalName()); - assertEquals(1, sr.getAttributeCount()); - assertEquals("attr", sr.getAttributeLocalName(0)); - assertEquals("value", sr.getAttributeValue(0)); - assertTokenType(CHARACTERS, sr.next()); - assertEquals("this or 'that'", getAndVerifyText(sr)); - assertTokenType(START_ELEMENT, sr.next()); - assertEquals("elem", sr.getLocalName()); - assertTokenType(CHARACTERS, sr.next()); - assertEquals("foo&bar", getAndVerifyText(sr)); - assertTokenType(END_ELEMENT, sr.next()); - assertEquals("elem", sr.getLocalName()); - assertTokenType(END_ELEMENT, sr.next()); - assertEquals("test", sr.getLocalName()); - assertTokenType(END_DOCUMENT, sr.next()); - } - } - - /* - ////////////////////////////////////////////////////////// - // Then custom quoting/escaping writers - ////////////////////////////////////////////////////////// - */ - - /** - * First a simplish testing of how exotic characters are escaped - * in attribute values. - */ - public void testAttrValueWriterSimple() - throws IOException, XMLStreamException - { - // Let's just ensure escaping is done for chars that need it - //String IN = "Ok, lessee \u00A0; -- \t and this: \u0531."; - String IN = "Ok, nbsp: \u00A0; and 'quotes' and \"doubles\" too; and multi-bytes too: [\u0531]"; - doTestAttrValueWriter("ISO-8859-1", IN); - doTestAttrValueWriter("UTF-8", IN); - doTestAttrValueWriter("US-ASCII", IN); - } - - /** - * And then bit more advanced test for things that need special - * support for round-tripping - */ - public void testAttrValueWriterTabsEtc() - throws IOException, XMLStreamException - { - String IN = "How about tabs: [\t] or cr+lf [\r\n]"; - doTestAttrValueWriter("ISO-8859-1", IN); - doTestAttrValueWriter("UTF-8", IN); - doTestAttrValueWriter("US-ASCII", IN); - } - - /* - ////////////////////////////////////////////////////////// - // Non-test methods: - ////////////////////////////////////////////////////////// - */ - - public XMLOutputFactory2 getFactory(boolean nsAware, boolean repairing) - throws XMLStreamException - { - XMLOutputFactory2 f = getOutputFactory(); - f.setProperty(XMLStreamProperties.XSP_NAMESPACE_AWARE, - Boolean.valueOf(nsAware)); - f.setProperty(XMLOutputFactory.IS_REPAIRING_NAMESPACES, - Boolean.valueOf(repairing)); - return f; - } - - private void doTestAttrValueWriter(String enc, String IN) - throws IOException, XMLStreamException - { - // First, let's explicitly pass the encoding... - XMLOutputFactory of = getFactory(false, false); - ByteArrayOutputStream out = new ByteArrayOutputStream(); - Writer w = new OutputStreamWriter(out, enc); - /* 26-Mar-2008, tatus: Note: we may get legacy encoding - * names from here (like "ASCII" over "US-ASCII" etc). - * Additionally, should we count on output factory knowing - * how to find underlying encoding from OutputStreamWriter? - * Could (should?) explicitly pass encoding instead. - */ - XMLStreamWriter sw = of.createXMLStreamWriter(w); - - // So shouldn't we do this? - //XMLStreamWriter sw = of.createXMLStreamWriter(w, enc); - - sw.writeStartDocument(enc, "1.0"); - sw.writeStartElement("elem"); - sw.writeAttribute("attr", IN); - sw.writeEndElement(); - sw.writeEndDocument(); - sw.close(); - w.close(); - - // Can we parse it ok? - XMLInputFactory ifact = getInputFactory(); - XMLStreamReader sr = ifact.createXMLStreamReader(new ByteArrayInputStream(out.toByteArray()), enc); - - // First, let's ensure we see the encoding: - assertTokenType(START_DOCUMENT, sr.getEventType()); - assertEquals(enc, sr.getCharacterEncodingScheme()); - - assertTokenType(START_ELEMENT, sr.next()); - assertEquals(1, sr.getAttributeCount()); - String attrValue = sr.getAttributeValue(0); - if (!IN.equals(attrValue)) { - failStrings("Incorrect writing/reading of attribute value (encoding '"+enc+"')", - IN, attrValue); - } - assertTokenType(END_ELEMENT, sr.next()); - assertTokenType(END_DOCUMENT, sr.next()); - sr.close(); - } - - public void doTestLonger(int type, boolean ns, boolean repair, String enc) - throws XMLStreamException - { - final String TEXT = -" Table of types of doubts\n" -+"doubt: specific error or issue with the test case\n" -+"extension: uses an extension feature\n" -+"gray-area: the spec does not give enough precision to distinguish correct behavior on the indicated detail\n" -+"processor-specific: processors are required to provide a unique value (should be marked as \"manual\" compare in catalog)\n" -+"serial: processor has options regarding serialization (This doubt only used for detail issues, not general discretion about encoding.)" - ; - - for (int i = 0; i < 2; ++i) { - StringWriter strw = new StringWriter(); - XMLStreamWriter2 w; - if (repair) { - w = getRepairingWriter(strw, enc); - } else { - w = getNonRepairingWriter(strw, enc, ns); - } - w.writeStartDocument(enc, "1.0"); - if (type == COMMENT) { - w.writeComment(TEXT); - } else { - w.writeProcessingInstruction("pi", TEXT); - } - w.writeEmptyElement("root"); - w.writeEndDocument(); - w.close(); - - // And then let's parse and verify the contents: - XMLStreamReader sr = constructNsStreamReader(strw.toString(), true); - assertTokenType(START_DOCUMENT, sr.getEventType()); - - if (type == COMMENT) { - assertTokenType(COMMENT, sr.next()); - assertEquals(TEXT, getAndVerifyText(sr)); - } else { - assertTokenType(PROCESSING_INSTRUCTION, sr.next()); - // PI data excludes leading space... need to trim - assertEquals(TEXT.trim(), sr.getPIData().trim()); - } - assertTokenType(START_ELEMENT, sr.next()); - assertTokenType(END_ELEMENT, sr.next()); - assertTokenType(END_DOCUMENT, sr.next()); - sr.close(); - } - } -} diff -Nru libwoodstox-java-4.1.3/src/test/stax2/wstream/TestWriterConstruction.java libwoodstox-java-5.1.0/src/test/stax2/wstream/TestWriterConstruction.java --- libwoodstox-java-4.1.3/src/test/stax2/wstream/TestWriterConstruction.java 2012-04-24 04:38:22.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/stax2/wstream/TestWriterConstruction.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,79 +0,0 @@ -package stax2.wstream; - -import java.io.*; - -import javax.xml.stream.*; - -import org.codehaus.stax2.*; -import org.codehaus.stax2.io.*; - -/** - * Unit test suite that tests additional StAX2 stream writer construction - * methods. - */ -public class TestWriterConstruction - extends BaseWriterTest -{ - public void testCreateWithFileSource() - throws IOException, XMLStreamException - { - XMLOutputFactory2 outf = getOutputFactory(); - File f = createTempFile(); - XMLStreamWriter sw = outf.createXMLStreamWriter(new Stax2FileResult(f)); - writeAndVerify(sw, f, "withFileSource"); - } - - public void testCreateWithFileStreamReader() - throws IOException, XMLStreamException - { - // Doesn't do much, yet... just constructs, for now - StringWriter strw = new StringWriter(); - XMLStreamWriter sw = getNonRepairingWriter(strw, true); - XMLEventWriter ew = getOutputFactory().createXMLEventWriter(sw); - - assertNotNull(ew); - - // TODO: try it out... - } - - /* - //////////////////////////////////////////////// - // Internal methods - //////////////////////////////////////////////// - */ - - File createTempFile() - throws IOException - { - File f = File.createTempFile("stax2test", null); - f.deleteOnExit(); - return f; - } - - private void writeAndVerify(XMLStreamWriter sw, File f, String text) - throws XMLStreamException - { - /* No need to write elaborate doc, just to ensure creation and - * later access work ok. - */ - sw.writeStartDocument("UTF-8", "1.0"); - sw.writeStartElement("write"); - sw.writeCharacters(text); - sw.writeEndElement(); - sw.writeEndDocument(); - sw.close(); - - // And then reader - XMLInputFactory2 ifact = getInputFactory(); - setCoalescing(ifact, true); - XMLStreamReader sr = ifact.createXMLStreamReader(new Stax2FileSource(f)); - assertTokenType(START_ELEMENT, sr.next()); - assertEquals("write", sr.getLocalName()); - assertTokenType(CHARACTERS, sr.next()); - assertEquals(text, getAndVerifyText(sr)); - assertTokenType(END_ELEMENT, sr.next()); - assertEquals("write", sr.getLocalName()); - assertTokenType(END_DOCUMENT, sr.next()); - sr.close(); - } -} diff -Nru libwoodstox-java-4.1.3/src/test/wstxtest/BaseWstxTest.java libwoodstox-java-5.1.0/src/test/wstxtest/BaseWstxTest.java --- libwoodstox-java-4.1.3/src/test/wstxtest/BaseWstxTest.java 2012-04-24 04:38:22.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/wstxtest/BaseWstxTest.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,586 +0,0 @@ -package wstxtest; - -import java.io.*; -import java.util.HashMap; - -import javax.xml.stream.*; - -import org.codehaus.stax2.*; -import org.codehaus.stax2.evt.*; - -import com.ctc.wstx.api.WstxInputProperties; -import com.ctc.wstx.api.WstxOutputProperties; -import com.ctc.wstx.cfg.XmlConsts; -import com.ctc.wstx.stax.WstxInputFactory; -import com.ctc.wstx.stax.WstxOutputFactory; - -import stax2.BaseStax2Test; - -public abstract class BaseWstxTest - extends BaseStax2Test - implements XMLStreamConstants -{ - final static HashMap mTokenTypes = new HashMap(); - static { - mTokenTypes.put(new Integer(START_ELEMENT), "START_ELEMENT"); - mTokenTypes.put(new Integer(END_ELEMENT), "END_ELEMENT"); - mTokenTypes.put(new Integer(START_DOCUMENT), "START_DOCUMENT"); - mTokenTypes.put(new Integer(END_DOCUMENT), "END_DOCUMENT"); - mTokenTypes.put(new Integer(CHARACTERS), "CHARACTERS"); - mTokenTypes.put(new Integer(CDATA), "CDATA"); - mTokenTypes.put(new Integer(COMMENT), "COMMENT"); - mTokenTypes.put(new Integer(PROCESSING_INSTRUCTION), "PROCESSING_INSTRUCTION"); - mTokenTypes.put(new Integer(DTD), "DTD"); - mTokenTypes.put(new Integer(SPACE), "SPACE"); - mTokenTypes.put(new Integer(ENTITY_REFERENCE), "ENTITY_REFERENCE"); - } - - /** - * Switch that can be turned on to verify to display ALL exact Exceptions - * thrown when Exceptions are expected. This is sometimes necessary - * when debugging, since it's impossible to automatically verify - * that Exception is exactly the right one, since there is no - * strict Exception type hierarchy for StAX problems. - *

- * Note: Not made 'final static', so that compiler won't inline - * it. Makes possible to do partial re-compilations. - * Note: Since it's only used as the default value, sub-classes - * can separately turn it off as necessary - */ - //protected static boolean DEF_PRINT_EXP_EXCEPTION = true; - protected static boolean DEF_PRINT_EXP_EXCEPTION = false; - - protected boolean PRINT_EXP_EXCEPTION = DEF_PRINT_EXP_EXCEPTION; - - /* - /////////////////////////////////////////////////// - // Lazy-loaded thingies - /////////////////////////////////////////////////// - */ - - XMLInputFactory2 mInputFactory = null; - XMLOutputFactory2 mOutputFactory = null; - XMLEventFactory2 mEventFactory = null; - - /* - ////////////////////////////////////////////////// - // Factory methods - ////////////////////////////////////////////////// - */ - - protected XMLInputFactory2 getInputFactory() - { - if (mInputFactory == null) { - /* 29-Nov-2004, TSa: Better ensure we get the right - * implementation... - */ - System.setProperty("javax.xml.stream.XMLInputFactory", - "com.ctc.wstx.stax.WstxInputFactory"); - mInputFactory = getNewInputFactory(); - } - return mInputFactory; - } - - protected XMLEventFactory2 getEventFactory() - { - if (mEventFactory == null) { - System.setProperty("javax.xml.stream.XMLEventFactory", - "com.ctc.wstx.stax.WstxEventFactory"); - mEventFactory = (XMLEventFactory2) XMLEventFactory.newInstance(); - } - return mEventFactory; - } - - protected WstxInputFactory getWstxInputFactory() { - return (WstxInputFactory) getInputFactory(); - } - - protected static XMLInputFactory2 getNewInputFactory() - { - return (XMLInputFactory2) XMLInputFactory.newInstance(); - } - - protected XMLOutputFactory2 getOutputFactory() - { - if (mOutputFactory == null) { - System.setProperty("javax.xml.stream.XMLOutputFactory", - "com.ctc.wstx.stax.WstxOutputFactory"); - mOutputFactory = getNewOutputFactory(); - } - return mOutputFactory; - } - - protected WstxOutputFactory getWstxOutputFactory() { - return (WstxOutputFactory) getOutputFactory(); - } - - protected static XMLOutputFactory2 getNewOutputFactory() - { - return (XMLOutputFactory2) XMLOutputFactory.newInstance(); - } - - protected static XMLStreamReader2 constructStreamReader(XMLInputFactory f, String content) - throws XMLStreamException - { - return (XMLStreamReader2) f.createXMLStreamReader(new StringReader(content)); - } - - protected static XMLStreamReader2 constructStreamReaderForFile(XMLInputFactory f, String filename) - throws IOException, XMLStreamException - { - File inf = new File(filename); - XMLStreamReader sr = f.createXMLStreamReader(inf.toURL().toString(), - new FileReader(inf)); - assertEquals(sr.getEventType(), START_DOCUMENT); - return (XMLStreamReader2) sr; - } - - protected static XMLEventReader2 constructEventReader(XMLInputFactory f, String content) - throws XMLStreamException - { - return (XMLEventReader2) f.createXMLEventReader(new StringReader(content)); - } - - protected XMLStreamReader2 constructNsStreamReader(String content, boolean coal) - throws XMLStreamException - { - XMLInputFactory f = getInputFactory(); - setNamespaceAware(f, true); - setCoalescing(f, coal); - return (XMLStreamReader2) f.createXMLStreamReader(new StringReader(content)); - } - - protected XMLStreamReader2 constructNsStreamReader(InputStream in, boolean coal) - throws XMLStreamException - { - XMLInputFactory f = getInputFactory(); - setNamespaceAware(f, true); - setCoalescing(f, coal); - return (XMLStreamReader2) f.createXMLStreamReader(in); - } - - protected XMLStreamReader2 constructNonNsStreamReader(String content, boolean coal) - throws XMLStreamException - { - XMLInputFactory f = getInputFactory(); - setNamespaceAware(f, false); - setCoalescing(f, coal); - return (XMLStreamReader2) f.createXMLStreamReader(new StringReader(content)); - } - - /* - ////////////////////////////////////////////////// - // Configuring input factory - ////////////////////////////////////////////////// - */ - - protected static void setLazyParsing(XMLInputFactory f, boolean state) - throws XMLStreamException - { - f.setProperty(XMLInputFactory2.P_LAZY_PARSING, - state ? Boolean.TRUE : Boolean.FALSE); - } - - protected static void setMinTextSegment(XMLInputFactory f, int len) - throws XMLStreamException - { - f.setProperty(WstxInputProperties.P_MIN_TEXT_SEGMENT, new Integer(len)); - } - - /* - ////////////////////////////////////////////////// - // Configuring output factory - ////////////////////////////////////////////////// - */ - - protected static void setRepairing(XMLOutputFactory f, boolean state) - { - f.setProperty(XMLOutputFactory.IS_REPAIRING_NAMESPACES, - Boolean.valueOf(state)); - } - - protected static void setValidateStructure(XMLOutputFactory f, boolean state) - { - f.setProperty(WstxOutputProperties.P_OUTPUT_VALIDATE_STRUCTURE, - Boolean.valueOf(state)); - } - - protected static void setValidateContent(XMLOutputFactory f, boolean state) - { - f.setProperty(WstxOutputProperties.P_OUTPUT_VALIDATE_CONTENT, - Boolean.valueOf(state)); - } - - protected static void setValidateNames(XMLOutputFactory f, boolean state) - { - f.setProperty(WstxOutputProperties.P_OUTPUT_VALIDATE_NAMES, - Boolean.valueOf(state)); - } - - protected static void setValidateAll(XMLOutputFactory f, boolean state) - { - setValidateStructure(f, state); - setValidateContent(f, state); - setValidateNames(f, state); - } - - protected static void setFixContent(XMLOutputFactory f, boolean state) - { - f.setProperty(WstxOutputProperties.P_OUTPUT_FIX_CONTENT, - Boolean.valueOf(state)); - } - - /* - ////////////////////////////////////////////////// - // Higher-level test methods - ////////////////////////////////////////////////// - */ - - /** - * Method that will iterate through contents of an XML document - * using specified stream reader; will also access some of data - * to make sure reader reads most of lazy-loadable data. - * Method is usually called to try to get an exception for invalid - * content. - * - * @return Dummy value calculated on contents; used to make sure - * no dead code is eliminated - */ - protected int streamThrough(XMLStreamReader sr) - throws XMLStreamException - { - int result = 0; - - while (sr.hasNext()) { - int type = sr.next(); - result += type; - if (sr.hasText()) { - /* will also do basic verification for text content, to - * see that all text accessor methods return same content - */ - result += getAndVerifyText(sr).hashCode(); - } - if (sr.hasName()) { - result += sr.getName().hashCode(); - } - } - - return result; - } - - protected int streamThroughFailing(XMLInputFactory f, String contents, - String msg) - throws XMLStreamException - { - int result = 0; - try { - XMLStreamReader sr = constructStreamReader(f, contents); - result = streamThrough(sr); - } catch (XMLStreamException ex) { // good - if (PRINT_EXP_EXCEPTION) { - System.out.println("Expected failure: '"+ex.getMessage()+"' " - +"(matching message: '"+msg+"')"); - } - return 0; - } catch (RuntimeException ex2) { // ok - if (PRINT_EXP_EXCEPTION) { - System.out.println("Expected failure: '"+ex2.getMessage()+"' " - +"(matching message: '"+msg+"')"); - } - return 0; - } catch (Throwable t) { // not so good - fail("Expected an XMLStreamException or RuntimeException for "+msg - +", got: "+t); - } - - fail("Expected an exception for "+msg); - return result; // never gets here - } - - protected int streamThroughFailing(XMLStreamReader sr, String msg) - throws XMLStreamException - { - int result = 0; - try { - result = streamThrough(sr); - } catch (XMLStreamException ex) { // good - if (PRINT_EXP_EXCEPTION) { - System.out.println("Expected failure: '"+ex.getMessage()+"' " - +"(matching message: '"+msg+"')"); - } - return 0; - } catch (RuntimeException ex2) { // ok - if (PRINT_EXP_EXCEPTION) { - System.out.println("Expected failure: '"+ex2.getMessage()+"' " - +"(matching message: '"+msg+"')"); - } - return 0; - } catch (Throwable t) { // not so good - fail("Expected an XMLStreamException or RuntimeException for "+msg - +", got: "+t); - } - - fail("Expected an exception for "+msg); - return result; // never gets here - } - - /* - ////////////////////////////////////////////////// - // Assertions - ////////////////////////////////////////////////// - */ - - protected static String tokenTypeDesc(int tt) - { - String desc = (String) mTokenTypes.get(new Integer(tt)); - return (desc == null) ? ("["+tt+"]") : desc; - } - - protected static void assertTokenType(int expType, int actType) - { - if (expType != actType) { - String expStr = tokenTypeDesc(expType); - String actStr = tokenTypeDesc(actType); - - if (expStr == null) { - expStr = ""+expType; - } - if (actStr == null) { - actStr = ""+actType; - } - fail("Expected token "+expStr+"; got "+actStr+"."); - } - } - - /** - * Helper assertion that assert that the String is either null or - * empty (""). - */ - protected static void assertNullOrEmpty(String str) - { - if (str != null && str.length() > 0) { - fail("Expected String to be empty or null; was '"+str+"' (length " - +str.length()+")"); - } - } - - protected static void assertNotNullOrEmpty(String str) - { - if (str == null || str.length() == 0) { - fail("Expected String to be non-empty; got " - +((str == null) ? "NULL" : "\"\"")); - } - } - - /** - * Method that can be used to verify that the current element - * pointed to by the stream reader has no prefix. - */ - protected static void assertNoElemPrefix(XMLStreamReader sr) - throws XMLStreamException - { - String prefix = sr.getPrefix(); - if (prefix != XmlConsts.ELEM_NO_PREFIX) { - fail("Element that does not have a prefix should be indicated with <"+XmlConsts.ELEM_NO_PREFIX+">, not <"+prefix+">"); - } - } - - /** - * Helper method for ensuring that the given return value for - * attribute prefix accessor has returned a value that - * represents "no prefix" value. - *

- * Current thinking (early 2008) is that empty string is the - * expected value here. - */ - protected static void assertNoAttrPrefix(String attrPrefix) - throws XMLStreamException - { - if (attrPrefix != XmlConsts.ATTR_NO_PREFIX) { - fail("Attribute that does not have a prefix should be indicated with <"+XmlConsts.ATTR_NO_PREFIX+">, not <"+attrPrefix+">"); - } - } - - /** - * Method that can be used to verify that the current element - * pointed to by the stream reader does not belong to a namespace. - */ - protected static void assertElemNotInNamespace(XMLStreamReader sr) - throws XMLStreamException - { - String uri = sr.getNamespaceURI(); - if (uri == null) { - fail("Excepted empty String to indicate \"no namespace\": got null"); - } else if (uri.length() != 0) { - fail("Excepted no (null) namespace URI: got '"+uri+"'"); - } - } - - protected static void assertNoAttrNamespace(String attrNsURI) - throws XMLStreamException - { - if (attrNsURI == null) { - fail("Expected empty String to indicate \"no namespace\" (for attribute): got null"); - } else if (attrNsURI.length() != 0) { - fail("Expected empty String to indicate \"no namespace\" (for attribute): got '"+attrNsURI+"'"); - } - } - - protected static void failStrings(String msg, String exp, String act) - { - // !!! TODO: Indicate position where Strings differ - fail(msg+": expected "+quotedPrintable(exp)+", got " - +quotedPrintable(act)); - } - - /** - * Method that not only gets currently available text from the - * reader, but also checks that its consistenly accessible using - * different (basic) StAX methods. - */ - protected static String getAndVerifyText(XMLStreamReader sr) - throws XMLStreamException - { - /* 05-Apr-2006, TSa: Although getText() is available for DTD - * and ENTITY_REFERENCE, getTextXxx() are not. Thus, can not - * do more checks for those types. - */ - int type = sr.getEventType(); - if (type == ENTITY_REFERENCE || type == DTD) { - return sr.getText(); - } - - int expLen = sr.getTextLength(); - /* Hmmh. It's only ok to return empty text for DTD event... well, - * maybe also for CDATA, since empty CDATA blocks are legal? - */ - /* !!! 01-Sep-2004, TSa: - * note: theoretically, in coalescing mode, it could be possible - * to have empty CDATA section(s) get converted to CHARACTERS, - * which would be empty... may need to enhance this to check that - * mode is not coalescing? Or something - */ - if (type == CHARACTERS) { - assertTrue("Stream reader should never return empty Strings.", (expLen > 0)); - } - String text = sr.getText(); - assertNotNull("getText() should never return null.", text); - assertEquals("Expected text length of "+expLen+", got "+text.length(), - expLen, text.length()); - char[] textChars = sr.getTextCharacters(); - int start = sr.getTextStart(); - String text2 = new String(textChars, start, expLen); - assertEquals(text, text2); - return text; - } - - /* - ////////////////////////////////////////////////// - // Debug/output helpers - ////////////////////////////////////////////////// - */ - - public static void warn(String msg) - { - System.err.println("WARN: "+msg); - } - - public static String printable(char ch) - { - if (ch == '\n') { - return "\\n"; - } - if (ch == '\r') { - return "\\r"; - } - if (ch == '\t') { - return "\\t"; - } - if (ch == ' ') { - return "_"; - } - if (ch > 127 || ch < 32) { - StringBuffer sb = new StringBuffer(6); - sb.append("\\u"); - String hex = Integer.toHexString((int)ch); - for (int i = 0, len = 4 - hex.length(); i < len; i++) { - sb.append('0'); - } - sb.append(hex); - return sb.toString(); - } - return null; - } - - public static String printableWithSpaces(char ch) - { - if (ch == '\n') { - return "\\n"; - } - if (ch == '\r') { - return "\\r"; - } - if (ch == '\t') { - return "\\t"; - } - if (ch > 127 || ch < 32) { - StringBuffer sb = new StringBuffer(6); - sb.append("\\u"); - String hex = Integer.toHexString((int)ch); - for (int i = 0, len = 4 - hex.length(); i < len; i++) { - sb.append('0'); - } - sb.append(hex); - return sb.toString(); - } - return null; - } - - public static String printable(String str) - { - if (str == null || str.length() == 0) { - return str; - } - - int len = str.length(); - StringBuffer sb = new StringBuffer(len + 64); - for (int i = 0; i < len; ++i) { - char c = str.charAt(i); - String res = printable(c); - if (res == null) { - sb.append(c); - } else { - sb.append(res); - } - } - return sb.toString(); - } - - public static String printableWithSpaces(String str) - { - if (str == null || str.length() == 0) { - return str; - } - - int len = str.length(); - StringBuffer sb = new StringBuffer(len + 64); - for (int i = 0; i < len; ++i) { - char c = str.charAt(i); - String res = printableWithSpaces(c); - if (res == null) { - sb.append(c); - } else { - sb.append(res); - } - } - return sb.toString(); - } - - protected static String quotedPrintable(String str) - { - if (str == null || str.length() == 0) { - return "[0]''"; - } - return "[len: "+str.length()+"] '"+printable(str)+"'"; - } -} diff -Nru libwoodstox-java-4.1.3/src/test/wstxtest/cfg/Configs.java libwoodstox-java-5.1.0/src/test/wstxtest/cfg/Configs.java --- libwoodstox-java-4.1.3/src/test/wstxtest/cfg/Configs.java 2012-04-24 04:38:22.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/wstxtest/cfg/Configs.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,218 +0,0 @@ -package wstxtest.cfg; - -import javax.xml.stream.XMLInputFactory; - -import com.ctc.wstx.stax.WstxInputFactory; - -public class Configs -{ - private Configs() { } - - // // // Configs for standard Woodstox properties - - public static void addAll(InputConfigIterator it) { - // First standard configs: - it.addConfig(getNamespaceConfig()) - .addConfig(getCoalescingConfig()) - .addConfig(getEntityExpansionConfig()); - - // Then woodstox-specific ones - it.addConfig(getLazyParsingConfig()) - .addConfig(getInputBufferSizeConfig()) - .addConfig(getMinTextSegmentConfig()); - } - - // // // Configs for standard Woodstox properties - - public static InputTestConfig getNamespaceConfig() { - return new NamespaceConfig(); - } - - public static InputTestConfig getCoalescingConfig() { - return new CoalescingConfig(); - } - - public static InputTestConfig getEntityExpansionConfig() { - return new EntityExpansionConfig(); - } - - // // // Configs for Woodstox properties - - public static InputTestConfig getLazyParsingConfig() { - return new LazyParsingConfig(); - } - - public static InputTestConfig getInputBufferSizeConfig() { - return new InputBufferSizeConfig(); - } - - public static InputTestConfig getMinTextSegmentConfig() { - return new TextSegmentConfig(); - } - - /* - ///////////////////////////////////////////////////// - // Config base class - ///////////////////////////////////////////////////// - */ - - abstract static class BaseConfig - implements InputTestConfig - { - final int mTotalCount; - - int mPos; - - BaseConfig(int count) { - mTotalCount = count; - mPos = -1; - } - - public boolean nextConfig(XMLInputFactory f) { - if (++mPos >= mTotalCount) { - return false; - } - config(f, mPos); - return true; - } - - public void firstConfig(XMLInputFactory f) { - mPos = 0; - config(f, 0); - } - - public String getDesc() { - return getDesc(mPos); - } - - public String toString() { return getDesc(); } - - public static boolean booleanFromInt(int i) { - return (i != 0); - } - - // // // Abstract methods for sub-classes - - public abstract String getDesc(int index); - - public abstract void config(XMLInputFactory f, int index); - } - - /* - ///////////////////////////////////////////////////// - // Actual config classes, std StAX properties - ///////////////////////////////////////////////////// - */ - - public static class NamespaceConfig - extends BaseConfig - { - NamespaceConfig() { - super(2); - } - - public String getDesc(int index) { - return "namespaces: "+booleanFromInt(index); - } - - public void config(XMLInputFactory f, int index) { - ((WstxInputFactory) f).getConfig().doSupportNamespaces(booleanFromInt(index)); - } - } - - public static class CoalescingConfig - extends BaseConfig - { - CoalescingConfig() { - super(2); - } - - public String getDesc(int index) { - return "coalescing: "+booleanFromInt(index); - } - - public void config(XMLInputFactory f, int index) { - ((WstxInputFactory) f).getConfig().doCoalesceText(booleanFromInt(index)); - } - } - - public static class EntityExpansionConfig - extends BaseConfig - { - EntityExpansionConfig() { - super(2); - } - - public String getDesc(int index) { - return "expand-entities: "+booleanFromInt(index); - } - - public void config(XMLInputFactory f, int index) { - ((WstxInputFactory) f).getConfig().doReplaceEntityRefs(booleanFromInt(index)); - } - } - - /* - ///////////////////////////////////////////////////// - // Actual config classes, Woodstox custom properties - ///////////////////////////////////////////////////// - */ - - public static class LazyParsingConfig - extends BaseConfig - { - LazyParsingConfig() { - super(2); - } - - public String getDesc(int index) { - return "lazy-parsing: "+booleanFromInt(index); - } - - public void config(XMLInputFactory f, int index) { - ((WstxInputFactory) f).getConfig().doParseLazily(booleanFromInt(index)); - } - } - - public static class InputBufferSizeConfig - extends BaseConfig - { - final static int[] mSizes = new int[] { - 8, 17, 200, 4000 - }; - - InputBufferSizeConfig() { - super(4); - } - - public String getDesc(int index) { - return "input-buffer: "+mSizes[index]; - } - - public void config(XMLInputFactory f, int index) { - ((WstxInputFactory) f).getConfig().setInputBufferLength(mSizes[index]); - } - } - - public static class TextSegmentConfig - extends BaseConfig - { - final static int[] mSizes = new int[] { - 6, 23, 100, 4000 - }; - - TextSegmentConfig() { - super(4); - } - - public String getDesc(int index) { - return "min-text-segment: "+mSizes[index]; - } - - public void config(XMLInputFactory f, int index) { - ((WstxInputFactory ) f).getConfig().setShortestReportedTextSegment(mSizes[index]); - } - } -} - - diff -Nru libwoodstox-java-4.1.3/src/test/wstxtest/cfg/InputConfigIterator.java libwoodstox-java-5.1.0/src/test/wstxtest/cfg/InputConfigIterator.java --- libwoodstox-java-4.1.3/src/test/wstxtest/cfg/InputConfigIterator.java 2012-04-24 04:38:22.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/wstxtest/cfg/InputConfigIterator.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,107 +0,0 @@ -package wstxtest.cfg; - -import java.util.*; - -import javax.xml.stream.XMLInputFactory; - -import wstxtest.cfg.InputTestConfig; - -/** - * Class that implements iteration over set of input configuration - * Objects, so that the input factory gets configured to all test - * values for each configuration, and a test method is called once - * per each configuration setting combination - */ -public class InputConfigIterator -{ - final ArrayList mConfigs = new ArrayList(); - - /* - ///////////////////////////////////////////////// - // Life-cycle (constructor, configuration) - ///////////////////////////////////////////////// - */ - - /** - * Index of the iteration step; may be used for debugging - */ - int mIndex; - - public InputConfigIterator() { - } - - public InputConfigIterator addConfig(InputTestConfig cfg) { - mConfigs.add(cfg); - return this; - } - - /* - ///////////////////////////////////////////////// - // Public API - ///////////////////////////////////////////////// - */ - - public void iterate(XMLInputFactory f, InputTestMethod callback) - throws Exception - { - mIndex = 0; - - // First need to initialize the factory with first settings: - final int len = mConfigs.size(); - for (int i = 0; i < len; ++i) { - ((InputTestConfig) mConfigs.get(i)).nextConfig(f); - } - - // And then the main iteration - while (true) { - // First let's call the test method - callback.runTest(f, this); - - // And then iterate to next configuration setting combo: - int i = 0; - for (; i < len; ++i) { - InputTestConfig cfg = (InputTestConfig) mConfigs.get(i); - // Still more settings for this config? Then let's break: - if (cfg.nextConfig(f)) { - break; - } - // Nope, need to reset this one, and continue for next: - cfg.firstConfig(f); - } - - // Got them all done? - if (i == len) { - break; - } - ++mIndex; - } - } - - public int getIndex() { - return mIndex; - } - - /* - ///////////////////////////////////////////////// - // Overridden standard methods: - ///////////////////////////////////////////////// - */ - - public String toString() - { - int len = mConfigs.size(); - StringBuffer sb = new StringBuffer(16 + (len << 4)); - sb.append('('); - sb.append(len); - sb.append(") "); - - for (int i = 0; i < len; ++i) { - if (i > 0) { - sb.append(", "); - } - sb.append(((InputTestConfig) mConfigs.get(i)).getDesc()); - } - return sb.toString(); - } -} - diff -Nru libwoodstox-java-4.1.3/src/test/wstxtest/cfg/InputTestConfig.java libwoodstox-java-5.1.0/src/test/wstxtest/cfg/InputTestConfig.java --- libwoodstox-java-4.1.3/src/test/wstxtest/cfg/InputTestConfig.java 2012-04-24 04:38:22.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/wstxtest/cfg/InputTestConfig.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,20 +0,0 @@ -package wstxtest.cfg; - -import javax.xml.stream.XMLInputFactory; - -public interface InputTestConfig -{ - public boolean nextConfig(XMLInputFactory f); - - /** - * Method that will reset iteration state to the initial, ie. state - * before any iteration - */ - public void firstConfig(XMLInputFactory f); - - /** - * @return String that describes current settings this configuration - * Object has (has set when {@link #nextConfig} was called) - */ - public String getDesc(); -} diff -Nru libwoodstox-java-4.1.3/src/test/wstxtest/cfg/InputTestMethod.java libwoodstox-java-5.1.0/src/test/wstxtest/cfg/InputTestMethod.java --- libwoodstox-java-4.1.3/src/test/wstxtest/cfg/InputTestMethod.java 2012-04-24 04:38:22.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/wstxtest/cfg/InputTestMethod.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,9 +0,0 @@ -package wstxtest.cfg; - -import javax.xml.stream.XMLInputFactory; - -public interface InputTestMethod -{ - public void runTest(XMLInputFactory f, InputConfigIterator it) - throws Exception; -} diff -Nru libwoodstox-java-4.1.3/src/test/wstxtest/evt/TestEventReader.java libwoodstox-java-5.1.0/src/test/wstxtest/evt/TestEventReader.java --- libwoodstox-java-4.1.3/src/test/wstxtest/evt/TestEventReader.java 2012-04-24 04:38:22.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/wstxtest/evt/TestEventReader.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,166 +0,0 @@ -package wstxtest.evt; - -import java.net.URL; -import java.util.*; - -import javax.xml.stream.*; -import javax.xml.stream.events.DTD; -import javax.xml.stream.events.XMLEvent; - -import org.codehaus.stax2.XMLEventReader2; -import org.codehaus.stax2.evt.NotationDeclaration2; - -import com.ctc.wstx.api.WstxInputProperties; -import com.ctc.wstx.exc.*; - -/** - * Set of unit tests that verify that Woodstox implementation of - * {@link XMLEventReader} does obey additional constraints Woodstox - * guarantees. Specifically: - *

- */ - -public class TestEventReader - extends wstxtest.BaseWstxTest -{ - public void testEventReaderNonLaziness() - throws XMLStreamException - { - /* We can test this by forcing coalescing to happen, and injecting - * an intentional error after first two segments. In lazy mode, - * coalescing is done not when event type is fetched, but only - * when getText() is called. In non-lazy mode, it's thrown right - * from next() method. Although the exact mechanism is hidden by - * the Event API, what we do see is the type of exception we get -- - * that should be XMLStreamException, NOT a runtime wrapper instead - * of it. - */ - final String XML = - "Some text and & &error;" - ; - XMLEventReader er = getReader(XML, true); - XMLEvent evt = er.nextEvent(); // start document - assertTrue(evt.isStartDocument()); - assertTrue(er.nextEvent().isStartElement()); - - // Ok, and now... - try { - evt = er.nextEvent(); - // should NOT get this far... - fail("Expected an exception for invalid content: coalescing not workig?"); - } catch (WstxParsingException wex) { - // This is correct... parsing exc for entity, hopefully - //System.err.println("GOOD: got "+wex.getClass()+": "+wex); - } catch (WstxException wex2) { - // Unexpected... not a catastrophe, but not right - fail("Should have gotten a non-lazy parsing exception; got non-lazy other wstx exception (why?): "+wex2); - } catch (WstxLazyException lex) { - // Not good... - fail("Should not get a lazy exception via (default) event reader; received: "+lex); - } catch (Throwable t) { - fail("Unexpected excpetion caught: "+t); - } - } - - public void testEventReaderLongSegments() - throws XMLStreamException - { - /* Ok. And here we should just check that we do not get 2 adjacent - * separate Characters event. We can try to trigger this by long - * segment and a set of char entities... - */ - final String XML = - "Some text and & also "quoted" stuff..." - +" not sure If we\r\nreally need anything much more but" - +" let's still make this longer" - +""; - ; - - // Need to disable coalescing though for test to work: - XMLEventReader er = getReader(XML, false); - XMLEvent evt = er.nextEvent(); // start document - assertTrue(evt.isStartDocument()); - assertTrue(er.nextEvent().isStartElement()); - assertTrue(er.nextEvent().isCharacters()); - - evt = er.nextEvent(); - if (evt.isEndElement()) { - ; // good - } else { - if (evt.isCharacters()) { - fail("Even in the absence of coalescing, event reader should not split CHARACTERS segments (Woodstox guarantee): did get 2 adjacent separate Characters events."); - } else { // hmmh. strange - fail("Unexpected event object type after CHARACTERS: "+evt.getClass()); - } - } - } - - /** - * As of Stax 3.0 (Woodstox 4.0+), there is additional info for - * NotationDeclarations (base URI). Let's verify it gets properly - * populated. - */ - public void testDtdNotations() - throws Exception - { - final String URI = "http://test"; - - /* Ok. And here we should just check that we do not get 2 adjacent - * separate Characters event. We can try to trigger this by long - * segment and a set of char entities... - */ - final String XML = "" - +"\n" - +"\n" - +"]>" - +""; - - // Need to disable coalescing though for test to work: - XMLEventReader2 er = getReader(XML, false); - // Need to set Base URI; can do it for factory or instance - er.setProperty(WstxInputProperties.P_BASE_URL, new URL(URI)); - assertTrue(er.nextEvent().isStartDocument()); - XMLEvent evt = er.nextEvent(); // DTD - assertTokenType(DTD, evt.getEventType()); - - DTD dtd = (DTD) evt; - List nots = dtd.getNotations(); - assertEquals(1, nots.size()); - NotationDeclaration2 notDecl = (NotationDeclaration2) nots.get(0); - - assertEquals(URI, notDecl.getBaseURI()); - } - - /* - ////////////////////////////////////////////////////// - // Internal methods - ////////////////////////////////////////////////////// - */ - - private XMLEventReader2 getReader(String contents, boolean coalescing) - throws XMLStreamException - { - XMLInputFactory f = getInputFactory(); - setNamespaceAware(f, true); - setCoalescing(f, coalescing); - setLazyParsing(f, true); // shouldn't have effect for event readers! - setMinTextSegment(f, 8); // likewise - return(XMLEventReader2) constructEventReader(f, contents); - } -} - - diff -Nru libwoodstox-java-4.1.3/src/test/wstxtest/io/TestUTF8Reader.java libwoodstox-java-5.1.0/src/test/wstxtest/io/TestUTF8Reader.java --- libwoodstox-java-4.1.3/src/test/wstxtest/io/TestUTF8Reader.java 2012-04-24 04:38:22.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/wstxtest/io/TestUTF8Reader.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,43 +0,0 @@ -package wstxtest.io; - -import java.io.*; - -import junit.framework.TestCase; - -import com.ctc.wstx.api.ReaderConfig; -import com.ctc.wstx.io.UTF8Reader; - -/** - * Unit test created to verify fix to - * WSTX-143. - * - * @author Matt Gormley - */ -public class TestUTF8Reader extends TestCase -{ - public void testDelAtBufferBoundary() throws IOException - { - final int BYTE_BUFFER_SIZE = 4; - final int CHAR_BUFFER_SIZE = 1 + BYTE_BUFFER_SIZE; - final int INPUT_SIZE = 4 * BYTE_BUFFER_SIZE; // could be of arbitrary size - final byte CHAR_FILLER = 32; // doesn't even matter, just need an ascii char - final byte CHAR_DEL = 127; - - // Create input that will cause the array index out of bounds exception - byte[] inputBytes = new byte[INPUT_SIZE]; - for (int i=0; i < inputBytes.length; i++) { - inputBytes[i] = CHAR_FILLER; - } - inputBytes[BYTE_BUFFER_SIZE - 1] = CHAR_DEL; - InputStream in = new ByteArrayInputStream(inputBytes); - - // Create the UTF8Reader - ReaderConfig cfg = ReaderConfig.createFullDefaults(); - byte[] byteBuffer = new byte[BYTE_BUFFER_SIZE]; - UTF8Reader reader = new UTF8Reader(cfg,in, byteBuffer, 0, 0, false); - - // Run the reader on the input - char[] charBuffer = new char[CHAR_BUFFER_SIZE]; - reader.read(charBuffer, 0, charBuffer.length); - } -} diff -Nru libwoodstox-java-4.1.3/src/test/wstxtest/msv/test-message.xml libwoodstox-java-5.1.0/src/test/wstxtest/msv/test-message.xml --- libwoodstox-java-4.1.3/src/test/wstxtest/msv/test-message.xml 2012-04-24 04:38:22.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/wstxtest/msv/test-message.xml 1970-01-01 00:00:00.000000000 +0000 @@ -1,8 +0,0 @@ - - - - - Here is text - - - \ No newline at end of file diff -Nru libwoodstox-java-4.1.3/src/test/wstxtest/msv/TestW3CDefaultValues.java libwoodstox-java-5.1.0/src/test/wstxtest/msv/TestW3CDefaultValues.java --- libwoodstox-java-4.1.3/src/test/wstxtest/msv/TestW3CDefaultValues.java 2012-04-24 04:38:22.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/wstxtest/msv/TestW3CDefaultValues.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,97 +0,0 @@ -package wstxtest.msv; - -import javax.xml.stream.*; - -import org.codehaus.stax2.*; - -import wstxtest.vstream.BaseValidationTest; - -/** - * Test for XML Schema value constraints (default, required) for - * elements and attributes. - */ -public class TestW3CDefaultValues - extends BaseValidationTest -{ - final static String SCHEMA_WITH_DEFAULTS = - "\n" - + "\n" - + " \n" - + " \n" - + " " - + " " - + " " - + " \n" - + " \n" - + "\n" - +"" - ; - - final static String SCHEMA_WITH_REQUIRED = ""; - - // Just to keep JUnit from failing, not finding any tests - public void testBogus() { } - - // 21-Apr-2012, tatu: Fails but can't be fixed for 4.1; hence comment out - /* - public void testAttributeDefault() throws Exception - { - XMLValidationSchema schema = parseW3CSchema(SCHEMA_WITH_DEFAULTS); - XMLStreamReader2 sr = getReader("129"); - sr.validateAgainst(schema); - // first: if explicitly defined, should show that value - assertTokenType(START_ELEMENT, sr.next()); - assertEquals("price", sr.getLocalName()); - assertEquals(1, sr.getAttributeCount()); - assertEquals("FIM", sr.getAttributeValue(null, "currency")); - sr.close(); - - // then, if missing, default to given default - sr = getReader("129"); - sr.validateAgainst(schema); - // first: if explicitly defined, should show that value - assertTokenType(START_ELEMENT, sr.next()); - assertEquals("price", sr.getLocalName()); - assertEquals(1, sr.getAttributeCount()); - assertEquals("USD", sr.getAttributeValue(null, "currency")); - sr.close(); - } - - public void testElementDefault() throws Exception - { - XMLValidationSchema schema = parseW3CSchema(SCHEMA_WITH_DEFAULTS); - XMLStreamReader2 sr = getReader("129"); - sr.validateAgainst(schema); - // first: if explicitly defined, should show that value - assertTokenType(START_ELEMENT, sr.next()); - assertEquals("price", sr.getLocalName()); - assertEquals("129", sr.getElementText()); - assertTokenType(END_ELEMENT, sr.getEventType()); - sr.close(); - - // then, if missing, default to given default - sr = getReader(""); - sr.validateAgainst(schema); - // first: if explicitly defined, should show that value - assertTokenType(START_ELEMENT, sr.next()); - assertEquals("price", sr.getLocalName()); - assertEquals("10", sr.getElementText()); - assertTokenType(END_ELEMENT, sr.getEventType()); - sr.close(); - } - */ - - /* - /////////////////////////////////////////////////////////////////////// - // Helper methods - /////////////////////////////////////////////////////////////////////// - */ - - XMLStreamReader2 getReader(String contents) throws XMLStreamException - { - XMLInputFactory2 f = getInputFactory(); - setValidating(f, false); - return constructStreamReader(f, contents); - } - -} diff -Nru libwoodstox-java-4.1.3/src/test/wstxtest/msv/TestW3CSchemaComplexTypes.java libwoodstox-java-5.1.0/src/test/wstxtest/msv/TestW3CSchemaComplexTypes.java --- libwoodstox-java-4.1.3/src/test/wstxtest/msv/TestW3CSchemaComplexTypes.java 2012-04-24 04:38:22.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/wstxtest/msv/TestW3CSchemaComplexTypes.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,76 +0,0 @@ -package wstxtest.msv; - -import javax.xml.stream.XMLStreamException; - -import org.codehaus.stax2.XMLInputFactory2; -import org.codehaus.stax2.XMLStreamReader2; -import org.codehaus.stax2.validation.XMLValidationException; -import org.codehaus.stax2.validation.XMLValidationSchema; - -import wstxtest.vstream.BaseValidationTest; - -public class TestW3CSchemaComplexTypes - extends BaseValidationTest -{ - public void testGithubIssue2() throws Exception - { - XMLValidationSchema schema = parseW3CSchema( -"" -+"" -+"" -+" " -+" " -+" " -+"" -+"" -+"" -+" " -+" " -+" " -+"" -+"" -+"" -+"" -+"" -+"" -+"" -+" " -+" " -+" " -+" " -+"" -+"" -+""); - XMLStreamReader2 sr = getReader("" - +"" - +"" - +""); - sr.validateAgainst(schema); - - try { - assertTokenType(START_ELEMENT, sr.next()); - assertEquals("Root", sr.getLocalName()); - assertTokenType(START_ELEMENT, sr.next()); - assertEquals("Child", sr.getLocalName()); - assertTokenType(END_ELEMENT, sr.next()); - assertTokenType(END_ELEMENT, sr.next()); - assertTokenType(END_DOCUMENT, sr.next()); - } catch (XMLValidationException vex) { - fail("Did not expect validation exception, got: " + vex); - } - assertTokenType(END_DOCUMENT, sr.getEventType()); - } - - /* - /////////////////////////////////////////////////////////////////////// - // Helper methods - /////////////////////////////////////////////////////////////////////// - */ - - XMLStreamReader2 getReader(String contents) throws XMLStreamException - { - XMLInputFactory2 f = getInputFactory(); - setValidating(f, false); - return constructStreamReader(f, contents); - } -} diff -Nru libwoodstox-java-4.1.3/src/test/wstxtest/msv/TestW3CSchema.java libwoodstox-java-5.1.0/src/test/wstxtest/msv/TestW3CSchema.java --- libwoodstox-java-4.1.3/src/test/wstxtest/msv/TestW3CSchema.java 2012-04-24 04:38:22.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/wstxtest/msv/TestW3CSchema.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,366 +0,0 @@ -package wstxtest.msv; - -import javax.xml.stream.*; - -import org.codehaus.stax2.*; -import org.codehaus.stax2.validation.*; - -import wstxtest.vstream.BaseValidationTest; - -/** - * This is a simple base-line "smoke test" that checks that W3C Schema - * validation works at least minimally. - */ -public class TestW3CSchema - extends BaseValidationTest -{ - /** - * Sample schema, using sample 'personal.xsd' found from the web - */ - final static String SIMPLE_NON_NS_SCHEMA = "\n" - + "\n" - + "\n" - + "\n" - + "\n" - + "\n" - + "\n" - + "\n" - + "\n" - + "\n" - + "\n" - + "\n" - + "\n" - + "\n" - + "\n" - + "\n" - + "\n" - + "\n" - + "\n" - + "\n" - + "\n" - + "\n" - + "\n" - + "\n" - + "\n" - + "\n" - + "\n" - + "\n" - + "\n" - + "\n" - + "\n" - + "\n" - + "\n" - + "\n" - + "\n" - + "\n" - + "\n" - + "\n" - + "\n" - + "\n" - + "\n" - + "\n" - + "\n" - + "\n" - + "\n" - + "\n" - + "\n" - + "\n" - + "\n" - + "\n" - + "\n" - - + "\n" - + "\n" - + "\n" - + "\n" - + "\n" + "\n" + "\n"; - - final static String SIMPLE_XML = "" - + "" + " " - + "FamilyFred" + " " - + " " + " " - + " " - + " BlowJoe" - + " " + " " + " " + ""; - - /** - * Test validation against a simple document valid according to a very - * simple W3C schema. - */ - public void testSimpleNonNs() throws XMLStreamException - { - XMLValidationSchema schema = parseW3CSchema(SIMPLE_NON_NS_SCHEMA); - XMLStreamReader2 sr = getReader(SIMPLE_XML); - sr.validateAgainst(schema); - - try { - assertTokenType(START_ELEMENT, sr.next()); - assertEquals("personnel", sr.getLocalName()); - - while (sr.hasNext()) { - /* int type = */sr.next(); - } - } catch (XMLValidationException vex) { - fail("Did not expect validation exception, got: " + vex); - } - assertTokenType(END_DOCUMENT, sr.getEventType()); - } - - public void testSimplePartialNonNs() throws XMLStreamException - { - XMLValidationSchema schema = parseW3CSchema(SIMPLE_NON_NS_SCHEMA); - XMLStreamReader2 sr = getReader(SIMPLE_XML); - - assertTokenType(START_ELEMENT, sr.next()); - assertEquals("personnel", sr.getLocalName()); - sr.validateAgainst(schema); - try { - assertTokenType(START_ELEMENT, sr.next()); - assertEquals("person", sr.getLocalName()); - while (sr.hasNext()) { - /* int type = */sr.next(); - } - } catch (XMLValidationException vex) { - fail("Did not expect validation exception, got: " + vex); - } - assertTokenType(END_DOCUMENT, sr.getEventType()); - } - - /** - * Test validation of a simple document that is invalid according to the - * simple test schema. - */ - public void testSimpleNonNsMissingId() throws XMLStreamException - { - XMLValidationSchema schema = parseW3CSchema(SIMPLE_NON_NS_SCHEMA); - String XML = "" - + "FG" - + ""; - verifyFailure(XML, schema, "missing id attribute", - "is missing \"id\" attribute"); - } - - public void testSimpleNonNsUndefinedId() throws XMLStreamException - { - XMLValidationSchema schema = parseW3CSchema(SIMPLE_NON_NS_SCHEMA); - String XML = "" - + "FG" - + ""; - verifyFailure(XML, schema, "undefined referenced id ('m3')", - "Undefined ID 'm3'"); - } - - public void testSimpleDataTypes() throws XMLStreamException - { - // Another sample schema, from - String SCHEMA = "\n" - + "\n" - + " \n" - + " \n" - + " " - + " " - + " " - + " " - + "" - + ""; - - XMLValidationSchema schema = parseW3CSchema(SCHEMA); - - // First, valid doc: - String XML = "3 \r\n4.05"; - XMLStreamReader2 sr = getReader(XML); - sr.validateAgainst(schema); - - try { - assertTokenType(START_ELEMENT, sr.next()); - assertEquals("item", sr.getLocalName()); - - assertTokenType(START_ELEMENT, sr.next()); - assertEquals("quantity", sr.getLocalName()); - String str = sr.getElementText(); - assertEquals("3", str.trim()); - - assertTokenType(START_ELEMENT, sr.next()); - assertEquals("price", sr.getLocalName()); - str = sr.getElementText(); - assertEquals("4.05", str.trim()); - - assertTokenType(END_ELEMENT, sr.next()); - assertTokenType(END_DOCUMENT, sr.next()); - } catch (XMLValidationException vex) { - fail("Did not expect validation exception, got: " + vex); - } - sr.close(); - - // Then invalid (wrong type for value) - XML = "34b1.00"; - sr.validateAgainst(schema); - verifyFailure(XML, schema, "invalid 'positive integer' datatype", - "does not satisfy the \"positiveInteger\""); - sr.close(); - - // Another invalid, empty value - XML = " 1.00"; - sr.validateAgainst(schema); - // 12-Nov-2008, TSa: still having MSV bug here, need to suppress failure - verifyFailure(XML, schema, "invalid (missing) positive integer value", - "does not satisfy the \"positiveInteger\"", false); - sr.close(); - - // Another invalid, missing value - XML = "1.00"; - sr.validateAgainst(schema); - // 12-Nov-2008, TSa: still having MSV bug here, need to suppress failure - verifyFailure(XML, schema, "invalid (missing) positive integer value", - "does not satisfy the \"positiveInteger\"", false); - sr.close(); - } - - public void testSimpleText() throws XMLStreamException - { - String SCHEMA = "\n" - + "\n" - + "" - + ""; - XMLValidationSchema schema = parseW3CSchema(SCHEMA); - - // First, 3 valid docs: - String XML = "xyz"; - XMLStreamReader2 sr = getReader(XML); - sr.validateAgainst(schema); - streamThrough(sr); - sr.close(); - - XML = ""; - sr = getReader(XML); - sr.validateAgainst(schema); - streamThrough(sr); - sr.close(); - - XML = ""; - sr = getReader(XML); - sr.validateAgainst(schema); - streamThrough(sr); - sr.close(); - - // Then invalid? - XML = ""; - sr = getReader(XML); - sr.validateAgainst(schema); - verifyFailure(XML, schema, "should warn about wrong root element", - "tag name \"foobar\" is not allowed", false); - } - - /** - * Test for reproducing [WSTX-191] - */ - public void testConstrainedText() throws XMLStreamException - { - String SCHEMA = "\n" - + "\n" - + " \n" - + " \n" - + " \n" - + " \n" - + " \n" + " \n" - + " \n" - + " \n" - + " \n" - + " \n" - + " \n" - + " \n" + " \n" - + " \n" + "\n"; - - XMLValidationSchema schema = parseW3CSchema(SCHEMA); - - // first cases where there is text, and 1 to 5 descs - _testValidDesc(schema, "Du Texte"); - _testValidDesc( - schema, - "123"); - _testValidDesc(schema, - ""); - _testValidDesc(schema, - "??"); - _testValidDesc(schema, ""); - _testValidDesc(schema, ""); - _testValidDesc(schema, ""); - } - - private void _testValidDesc(XMLValidationSchema schema, String descSnippet) throws XMLStreamException - { - // These should all be valid according to the schema - String XML = "" - + descSnippet + ""; - XMLStreamReader2 sr = getReader(XML); - sr.validateAgainst(schema); - streamThrough(sr); - sr.close(); - } - - public void testValidationHandler() throws XMLStreamException - { - String SCHEMA = "\n" - + "\n" - + "" - + ""; - XMLValidationSchema schema = parseW3CSchema(SCHEMA); - - // Then invalid? - String XML = ""; - XMLStreamReader2 sr = getReader(XML); - sr.setValidationProblemHandler(new ValidationProblemHandler() { - - public void reportProblem(XMLValidationProblem problem) - throws XMLValidationException { - throw new LocalValidationError(problem); - - } - }); - sr.validateAgainst(schema); - boolean threw = false; - try { - while (sr.hasNext()) { - /* int type = */sr.next(); - } - } catch (LocalValidationError lve) { - threw = true; - } - assertTrue(threw); - } - - /* - /////////////////////////////////////////////////////////////////////// - // Helper methods - /////////////////////////////////////////////////////////////////////// - */ - - XMLStreamReader2 getReader(String contents) throws XMLStreamException - { - XMLInputFactory2 f = getInputFactory(); - setValidating(f, false); - return constructStreamReader(f, contents); - } - - /* - /////////////////////////////////////////////////////////////////////// - // Helper classes - /////////////////////////////////////////////////////////////////////// - */ - - public static class LocalValidationError extends RuntimeException - { - private static final long serialVersionUID = 1L; - - protected XMLValidationProblem problem; - - LocalValidationError(XMLValidationProblem problem) { - this.problem = problem; - } - - public XMLValidationProblem getProblem() { - return problem; - } - } -} diff -Nru libwoodstox-java-4.1.3/src/test/wstxtest/msv/TestW3CSchemaTypes.java libwoodstox-java-5.1.0/src/test/wstxtest/msv/TestW3CSchemaTypes.java --- libwoodstox-java-4.1.3/src/test/wstxtest/msv/TestW3CSchemaTypes.java 2012-04-24 04:38:22.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/wstxtest/msv/TestW3CSchemaTypes.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,97 +0,0 @@ -package wstxtest.msv; - -import javax.xml.stream.*; - -import org.codehaus.stax2.*; -import org.codehaus.stax2.validation.*; - -import wstxtest.vstream.BaseValidationTest; - -/** - * Simple testing of W3C Schema datatypes. - * Added to test [WSTX-210]. - * - * @author Tatu Saloranta - */ -public class TestW3CSchemaTypes - extends BaseValidationTest -{ - final static String SCHEMA_INT = - "\n" - +"" - +"\n" - ; - - final static String SCHEMA_FLOAT = - "\n" - +"" - +"\n" - ; - - // // // First 'int' datatype - - public void testSimpleValidInt() throws Exception - { - XMLValidationSchema schema = parseW3CSchema(SCHEMA_INT); - XMLStreamReader2 sr = getReader("129"); - sr.validateAgainst(schema); - streamThrough(sr); - } - - public void testSimpleInvalidInt() throws Exception - { - XMLValidationSchema schema = parseW3CSchema(SCHEMA_INT); - verifyFailure("abc", schema, "invalid 'int' value", - "does not satisfy the \"int\" type"); - } - - // 21-Apr-2012, tatu: Fails but can't be fixed for 4.1; hence comment out -/* - public void testSimpleMissingInt() throws Exception - { - XMLValidationSchema schema = parseW3CSchema(SCHEMA_INT); - verifyFailure("", schema, "missing 'int' value", - "does not satisfy the \"int\" type"); - } - */ - - // // // Then 'float' datatype - - public void testSimpleValidFloat() throws Exception - { - XMLValidationSchema schema = parseW3CSchema(SCHEMA_FLOAT); - XMLStreamReader2 sr = getReader("1.00"); - sr.validateAgainst(schema); - streamThrough(sr); - } - - public void testSimpleInvalidFloat() throws Exception - { - XMLValidationSchema schema = parseW3CSchema(SCHEMA_FLOAT); - verifyFailure("abc", schema, "invalid 'float' value", - "does not satisfy the \"float\" type"); - } - - // 21-Apr-2012, tatu: Fails but can't be fixed for 4.1; hence comment out -/* - public void testSimpleMissingFloat() throws Exception - { - XMLValidationSchema schema = parseW3CSchema(SCHEMA_FLOAT); - verifyFailure("", schema, "missing 'float' value", - "Undefined ID 'm3'"); - } - */ - - /* - /////////////////////////////////////////////////////////////////////// - // Helper - /////////////////////////////////////////////////////////////////////// - */ - - XMLStreamReader2 getReader(String contents) throws XMLStreamException - { - XMLInputFactory2 f = getInputFactory(); - setValidating(f, false); - return constructStreamReader(f, contents); - } -} diff -Nru libwoodstox-java-4.1.3/src/test/wstxtest/msv/TestWsdlValidation.java libwoodstox-java-5.1.0/src/test/wstxtest/msv/TestWsdlValidation.java --- libwoodstox-java-4.1.3/src/test/wstxtest/msv/TestWsdlValidation.java 2012-04-24 04:38:22.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/wstxtest/msv/TestWsdlValidation.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,114 +0,0 @@ -/** - * - */ -package wstxtest.msv; - -import java.io.IOException; -import java.net.URL; - -import javax.xml.namespace.QName; -import javax.xml.parsers.DocumentBuilder; -import javax.xml.parsers.DocumentBuilderFactory; -import javax.xml.parsers.SAXParserFactory; -import javax.xml.stream.XMLStreamConstants; -import javax.xml.transform.dom.DOMSource; - -import org.codehaus.stax2.XMLInputFactory2; -import org.codehaus.stax2.XMLStreamReader2; -import org.w3c.dom.Document; -import org.w3c.dom.ls.LSResourceResolver; -import org.xml.sax.InputSource; -import org.xml.sax.Locator; -import org.xml.sax.SAXException; - -import stax2.BaseStax2Test; - -import com.ctc.wstx.msv.W3CSchema; -import com.sun.msv.grammar.xmlschema.XMLSchemaGrammar; -import com.sun.msv.reader.GrammarReaderController2; -import com.sun.msv.reader.xmlschema.WSDLSchemaReader; - -public class TestWsdlValidation extends BaseStax2Test { - - private static class LocalController implements GrammarReaderController2 { - - public LSResourceResolver getLSResourceResolver() { - return null; - } - - public void error(Locator[] locs, String errorMessage, Exception nestedException) { - StringBuffer errors = new StringBuffer(); - // need to use 1.4 loops, for now - for (int i = 0; i < locs.length; ++i) { - Locator loc = locs[i]; - errors.append("in " + loc.getSystemId() + " " + loc.getLineNumber() + ":" - + loc.getColumnNumber()); - } - throw new RuntimeException(errors.toString(), nestedException); - } - - public void warning(Locator[] locs, String errorMessage) { - StringBuffer errors = new StringBuffer(); - // need to use 1.4 loops, for now - for (int i = 0; i < locs.length; ++i) { - Locator loc = locs[i]; - errors.append("in " + loc.getSystemId() + " " + loc.getLineNumber() + ":" - + loc.getColumnNumber()); - } - // no warning allowed. - throw new RuntimeException("warning: " + errors.toString()); - } - - public InputSource resolveEntity(String publicId, String systemId) throws SAXException, IOException { - return null; - } - } - - private XMLSchemaGrammar wsdlgrammar; - private W3CSchema schema; - - /* (non-Javadoc) - * @see junit.framework.TestCase#setUp() - */ - protected void setUp() throws Exception { - super.setUp(); - DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance(); - documentBuilderFactory.setNamespaceAware(true); - DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder(); - URL wsdlUri = getClass().getResource("test.wsdl"); - Document wsdl = documentBuilder.parse(wsdlUri.openStream()); - String wsdlSystemId = wsdlUri.toExternalForm(); - DOMSource source = new DOMSource(wsdl); - source.setSystemId(wsdlSystemId); - - LocalController controller = new LocalController(); - SAXParserFactory factory = SAXParserFactory.newInstance(); - factory.setNamespaceAware(true); - wsdlgrammar = WSDLSchemaReader.read(source, factory, controller); - schema = new W3CSchema(wsdlgrammar); - } - - public void testWsdlValidation() throws Exception { - String runMe = System.getProperty("testWsdlValidation"); - if (runMe == null || "".equals(runMe)) { - return; - } - XMLInputFactory2 factory = getInputFactory(); - XMLStreamReader2 reader = (XMLStreamReader2) factory.createXMLStreamReader(getClass().getResourceAsStream("test-message.xml"), "utf-8"); - QName msgQName = new QName("http://server.hw.demo/", "sayHi"); - while (true) { - int what = reader.nextTag(); - if (what == XMLStreamConstants.START_ELEMENT) { - if (reader.getName().equals(msgQName)) { - reader.validateAgainst(schema); - } - } else if (what == XMLStreamConstants.END_ELEMENT) { - if (reader.getName().equals(msgQName)) { - reader.stopValidatingAgainst(schema); - } - } else if (what == XMLStreamConstants.END_DOCUMENT) { - break; - } - } - } -} diff -Nru libwoodstox-java-4.1.3/src/test/wstxtest/osgi/TestBasic.java libwoodstox-java-5.1.0/src/test/wstxtest/osgi/TestBasic.java --- libwoodstox-java-4.1.3/src/test/wstxtest/osgi/TestBasic.java 2012-04-24 04:38:22.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/wstxtest/osgi/TestBasic.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,42 +0,0 @@ -package wstxtest.osgi; - -import java.lang.reflect.InvocationHandler; -import java.lang.reflect.Method; -import java.lang.reflect.Proxy; - -import wstxtest.BaseWstxTest; - -import org.osgi.framework.*; - -import com.ctc.wstx.osgi.*; - -public class TestBasic - extends BaseWstxTest -{ - public void testBundleActivation() - { - // Hmmh. Context is a beastly class... let's just proxy it - InvocationHandler h = new ContextHandler(); - BundleContext ctxt = (BundleContext) Proxy.newProxyInstance(BundleContext.class.getClassLoader(), new Class[] { BundleContext.class }, h); - WstxBundleActivator act = new WstxBundleActivator(); - - // won't prove much... but at least there's noo fundamental flaw: - act.start(ctxt); - } - - /* - ////////////////////////////////////////// - // Helper classes - ////////////////////////////////////////// - */ - - final static class ContextHandler - implements InvocationHandler - { - public Object invoke(Object proxy, Method method, Object[] args) - { - // !!! TODO: make do something... - return null; - } - } -} diff -Nru libwoodstox-java-4.1.3/src/test/wstxtest/sax/TestBasicSax.java libwoodstox-java-5.1.0/src/test/wstxtest/sax/TestBasicSax.java --- libwoodstox-java-4.1.3/src/test/wstxtest/sax/TestBasicSax.java 2012-04-24 04:38:22.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/wstxtest/sax/TestBasicSax.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,183 +0,0 @@ -package wstxtest.sax; - -import java.io.*; - -import javax.xml.parsers.SAXParser; -import javax.xml.parsers.SAXParserFactory; - -import org.xml.sax.*; -import org.xml.sax.ext.DefaultHandler2; -import org.xml.sax.helpers.DefaultHandler; - -import com.ctc.wstx.sax.*; - -import wstxtest.BaseWstxTest; - -/** - * Simple unit tests to verify that most fundamental parsing functionality - * works via Woodstox SAX implementation. - */ -public class TestBasicSax - extends BaseWstxTest -{ - final static String XML = "\n" - +"" - +"" - +"rock'n "; - - public void testSimpleNs() - throws Exception - { - doTestSimple(true, false); - doTestSimple(true, true); - } - - public void testSimpleNonNs() - throws Exception - { - doTestSimple(false, false); - doTestSimple(false, true); - } - - /** - * Test for [WSTX-226]: ensure that given encoding is used - * as specified - */ - public void testEncoding() throws Exception - { - SAXParser parser = new WstxSAXParser(); - String encoding = "ISO-8859-1"; - String text = "mit hei\u00DFem Bem\u00FCh'n"; - byte[] content = ("" + text + "").getBytes(encoding); - InputSource is = new InputSource(new ByteArrayInputStream(content)); - is.setEncoding(encoding); - TextExtractor handler = new TextExtractor(); - parser.parse(is, handler); - assertEquals(text, handler.getText()); - - // And second time around, with declaration - /* 02-Jan-2010, tatu: Looks like we can NOT reuse parser... why? - * Is that a bug or unsupported way to use it. Hmmh. Need to check. - */ - parser = new WstxSAXParser(); - content = ("" + text + "").getBytes(encoding); - is = new InputSource(new ByteArrayInputStream(content)); - is.setEncoding(encoding); - handler = new TextExtractor(); - parser.parse(is, handler); - assertEquals(text, handler.getText()); - } - - /** - * Test for [WSTX_227] - */ - // 21-Apr-2012, tatu: Fails but can't be fixed for 4.1; hence comment out - /* - public void testCData() throws Exception - { - SAXParser parser = new WstxSAXParser(); - StringBuffer buffer = new StringBuffer(""); - CDATASectionCounter handler = new CDATASectionCounter(); - parser.setProperty("http://xml.org/sax/properties/lexical-handler", handler); - parser.parse(new InputSource(new StringReader(buffer.toString())), handler); - // Should get as many cdata sections as text segments - int cdatas = handler.getCDATASectionCount(); - int segments = handler.getSegmentCount(); - - assertEquals("Should only get a single CDATA segments, got "+cdatas+" (for "+segments+" text segments)", 1, cdatas); - } - */ - - /* - //////////////////////////////////////////////////// - // Helper methods - //////////////////////////////////////////////////// - */ - - public void doTestSimple(boolean ns, boolean useReader) - throws Exception - { - // no need to test JAXP introspection... - SAXParserFactory spf = new WstxSAXParserFactory(); - spf.setNamespaceAware(ns); - SAXParser sp = spf.newSAXParser(); - MyHandler h = new MyHandler(); - - InputSource src; - - if (useReader) { - src = new InputSource(new StringReader(XML)); - } else { - src = new InputSource(new ByteArrayInputStream(XML.getBytes("UTF-8"))); - } - - sp.parse(src, h); - assertEquals(2, h._elems); - assertEquals(1, h._attrs); - assertEquals(11, h._charCount); - } - - static class TextExtractor extends DefaultHandler { - private final StringBuffer buffer = new StringBuffer(); - public void characters(char[] ch, int start, int length) throws SAXException { - buffer.append(ch, start, length); - } - - public String getText() { - return buffer.toString(); - } - } - - final static class MyHandler - extends DefaultHandler - { - public int _elems, _attrs; - - public int _charCount; - - public void characters(char[] ch, int start, int length) { - _charCount += length; - } - - public void startElement(String uri, String ln, String qname, - Attributes a) - { - ++_elems; - int ac = a.getLength(); - _attrs += ac; - - for (int i = 0; i < ac; ++i) { - a.getLocalName(i); - a.getQName(i); - a.getURI(i); - a.getValue(i); - a.getType(i); - } - } - } - - static class CDATASectionCounter extends DefaultHandler2 { - private int cdataSectionCount; - private int segmentCount; - - public void startCDATA() throws SAXException { - cdataSectionCount++; - } - - public void characters(char[] ch, int start, int length) throws SAXException { - segmentCount++; - } - - public int getCDATASectionCount() { - return cdataSectionCount; - } - - public int getSegmentCount() { - return segmentCount; - } - } -} diff -Nru libwoodstox-java-4.1.3/src/test/wstxtest/sax/TestEntityResolver.java libwoodstox-java-5.1.0/src/test/wstxtest/sax/TestEntityResolver.java --- libwoodstox-java-4.1.3/src/test/wstxtest/sax/TestEntityResolver.java 2012-04-24 04:38:22.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/wstxtest/sax/TestEntityResolver.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,75 +0,0 @@ -package wstxtest.sax; - -import java.io.*; - -import javax.xml.parsers.SAXParser; -import javax.xml.parsers.SAXParserFactory; - -import org.xml.sax.*; -import org.xml.sax.helpers.DefaultHandler; - -import com.ctc.wstx.sax.WstxSAXParserFactory; - -import wstxtest.BaseWstxTest; - -/** - * Simple unit tests to verify that most fundamental parsing functionality - * works via Woodstox SAX implementation. - */ -public class TestEntityResolver - extends BaseWstxTest -{ - public void testWithDummyExtSubset() - throws Exception - { - final String XML = - "\n" - +"" - ; - - SAXParserFactory spf = new WstxSAXParserFactory(); - spf.setNamespaceAware(true); - SAXParser sp = spf.newSAXParser(); - DefaultHandler h = new DefaultHandler(); - - /* First: let's verify that we get an exception for - * unresolved reference... - */ - try { - sp.parse(new InputSource(new StringReader(XML)), h); - } catch (SAXException e) { - verifyException(e, "No such file or directory"); - } - - // And then with dummy resolver; should work ok now - sp = spf.newSAXParser(); - sp.getXMLReader().setEntityResolver(new MyResolver(" ")); - h = new DefaultHandler(); - try { - sp.parse(new InputSource(new StringReader(XML)), h); - } catch (SAXException e) { - fail("Should not have failed with entity resolver, got ("+e.getClass()+"): "+e.getMessage()); - } - } - - /* - /////////////////////////////////////////////////////// - // Helper classes - /////////////////////////////////////////////////////// - */ - - static class MyResolver - implements EntityResolver - { - final String mContents; - - public MyResolver(String c) { - mContents = c; - } - - public InputSource resolveEntity(String publicId, String systemId) - { - return new InputSource(new StringReader(mContents)); - } - } -} diff -Nru libwoodstox-java-4.1.3/src/test/wstxtest/stream/BaseStreamTest.java libwoodstox-java-5.1.0/src/test/wstxtest/stream/BaseStreamTest.java --- libwoodstox-java-4.1.3/src/test/wstxtest/stream/BaseStreamTest.java 2012-04-24 04:38:22.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/wstxtest/stream/BaseStreamTest.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,507 +0,0 @@ -package wstxtest.stream; - -import java.io.*; -import java.util.Random; - -import javax.xml.stream.*; - -import org.codehaus.stax2.XMLStreamReader2; - -import wstxtest.BaseWstxTest; -import wstxtest.cfg.*; - -public abstract class BaseStreamTest - extends BaseWstxTest -{ - protected BaseStreamTest() { super(); } - - /* - ////////////////////////////////////////////////// - // "Special" accessors - ////////////////////////////////////////////////// - */ - - /** - * Method that not only gets currently available text from the - * reader, but also checks that its consistenly accessible using - * different StAX methods. - */ - protected static String getAndVerifyText(XMLStreamReader sr) - throws XMLStreamException - { - int expLen = sr.getTextLength(); - // Hmmh. It's only ok to return empty text for DTD event - if (sr.getEventType() != DTD) { - assertTrue("Stream reader should never return empty Strings.", (expLen > 0)); - } - String text = sr.getText(); - assertNotNull("getText() should never return null.", text); - assertEquals(expLen, text.length()); - char[] textChars = sr.getTextCharacters(); - int start = sr.getTextStart(); - String text2 = new String(textChars, start, expLen); - assertEquals(text, text2); - return text; - } - - protected static String getStreamingText(XMLStreamReader sr) - throws IOException, XMLStreamException - { - StringWriter sw = new StringWriter(); - ((XMLStreamReader2) sr).getText(sw, false); - return sw.toString(); - } - - /* - ////////////////////////////////////////////////// - // Higher-level test methods - ////////////////////////////////////////////////// - */ - - /** - * Method that will iterate through contents of an XML document - * using specified stream reader; will also access some of data - * to make sure reader reads most of lazy-loadable data. - * Method is usually called to try to get an exception for invalid - * content. - * - * @return Dummy value calculated on contents; used to make sure - * no dead code is eliminated - */ - protected int streamThrough(XMLStreamReader sr) - throws XMLStreamException - { - int result = 0; - - while (sr.hasNext()) { - int type = sr.next(); - result += type; - if (sr.hasText()) { - /* will also do basic verification for text content, to - * see that all text accessor methods return same content - */ - result += sr.getText().hashCode(); - } - if (sr.hasName()) { - result += sr.getName().hashCode(); - } - } - - return result; - } - - protected int streamAndCheck(XMLInputFactory f, InputConfigIterator it, - String input, String expOutput, - boolean reallyStreaming) - throws IOException, XMLStreamException, UnsupportedEncodingException - { - int count = 0; - - // Let's loop couple of input methods - for (int m = 0; m < 3; ++m) { - XMLStreamReader sr; - - /* Contents shouldn't really contain anything - * outside ISO-Latin; however, detection may - * be tricky.. so let's just test with UTF-8, - * for now? - */ - - switch (m) { - case 0: // simple StringReader: - sr = constructStreamReader(f, input); - break; - case 1: // via InputStream and auto-detection - { - ByteArrayInputStream bin = new ByteArrayInputStream - (input.getBytes("UTF-8")); - sr = f.createXMLStreamReader(bin); - } - break; - case 2: // explicit UTF-8 stream - { - ByteArrayInputStream bin = new ByteArrayInputStream - (input.getBytes("UTF-8")); - Reader br = new InputStreamReader(bin, "UTF-8"); - sr = f.createXMLStreamReader(br); - } - break; - default: throw new Error("Internal error"); - } - - count += streamAndCheck(sr, it, input, expOutput, - reallyStreaming); - } - return count; - } - - protected int streamAndCheck(XMLStreamReader sr, InputConfigIterator it, - String input, String expOutput, - boolean reallyStreaming) - throws IOException, XMLStreamException - { - int type; - - /* Let's ignore leading white space and DTD; and stop on encountering - * something else - */ - do { - type = sr.next(); - } while ((type == SPACE) || (type == DTD)); - - StringBuffer act = new StringBuffer(1000); - int count = 0; - - do { - count += type; - if (type == START_ELEMENT || type == END_ELEMENT) { - act.append('<'); - if (type == END_ELEMENT) { - act.append('/'); - } - String prefix = sr.getPrefix(); - if (prefix != null && prefix.length() > 0) { - act.append(prefix); - act.append(':'); - } - act.append(sr.getLocalName()); - act.append('>'); - } else if (type == CHARACTERS || type == SPACE || type == CDATA) { - // No quoting, doesn't have to result in legal XML - if (reallyStreaming) { - StringWriter sw = new StringWriter(); - // important: false to indicate 'don't preserve contents' - int gotLen = ((XMLStreamReader2)sr).getText(sw, false); - String text = sw.toString(); - int textLen = text.length(); - if (textLen != gotLen) { - if (text.length() > 60) { - text = text.substring(0, 30) + "<...>" + text.substring(textLen-30); - } - assertEquals("Incorrect return value from streaming getText() for "+ - tokenTypeDesc(type)+" [string '"+text+"']", textLen, gotLen); - } - act.append(text); - } else { - act.append(sr.getText()); - } - } else if (type == COMMENT) { - act.append(""); - } else if (type == PROCESSING_INSTRUCTION) { - act.append(""); - } else if (type == ENTITY_REFERENCE) { - act.append(sr.getText()); - } else { - fail("Unexpected event type "+tokenTypeDesc(type)); - } - } while ((type = sr.next()) != END_DOCUMENT); - - String result = act.toString(); - if (!result.equals(expOutput)) { - String desc = it.toString(); - int round = it.getIndex(); - - // uncomment for debugging: - - /* - System.err.println("FAIL: round "+round+" ["+desc+"]"); - System.err.println("Input: '"+input.toString()+"'"); - System.err.println("Exp: '"+expOutput.toString()+"'"); - System.err.println("Actual: '"+act.toString()+"'"); - */ - - fail("Failure with '"+desc+"' (round #"+round+"):\n
" - +"Input : {"+printableWithSpaces(input)+"}\n
" - +"Output: {"+printableWithSpaces(result)+"}\n
" - +"Exp. : {"+printableWithSpaces(expOutput)+"}\n
"); - } - - return count; - } - - protected int streamAndSkip(XMLInputFactory f, InputConfigIterator it, - String input) - throws XMLStreamException, UnsupportedEncodingException - { - int count = 0; - - // Let's loop couple of input methods - for (int m = 0; m < 3; ++m) { - XMLStreamReader sr; - - switch (m) { - case 0: // simple StringReader: - sr = constructStreamReader(f, input); - break; - case 1: // via InputStream and auto-detection - { - ByteArrayInputStream bin = new ByteArrayInputStream - (input.getBytes("UTF-8")); - sr = f.createXMLStreamReader(bin); - } - break; - case 2: // explicit UTF-8 stream - { - ByteArrayInputStream bin = new ByteArrayInputStream - (input.getBytes("UTF-8")); - Reader br = new InputStreamReader(bin, "UTF-8"); - sr = f.createXMLStreamReader(br); - } - break; - default: throw new Error("Internal error"); - } - - count += streamAndSkip(sr, it, input); - } - return count; - } - - protected int streamAndSkip(XMLStreamReader sr, InputConfigIterator it, - String input) - throws XMLStreamException - { - int count = 0; - - while (sr.hasNext()) { - count += sr.next(); - } - return count; - } - - protected void generateData(Random r, StringBuffer input, - StringBuffer output, boolean autoEnt) - { - final String PREAMBLE = - "" - +"\n" - +" \n" - +" \n" - +"]>"; - - /* Ok; template will use '*' chars as placeholders, to be replaced - * by pseudo-randomly selected choices. - */ - final String TEMPLATE = - "" - - // Short one for trouble shooting: - /* - +" * Text ****\n" - */ - - // Real one for regression testing: - +" * Text ****\n" - +"** * xx\n" - +"Text ******\n" - +"*......**" - +"******" - +"*** ****" - +"* ***" - +"a*b*c*d*e*f*g*h*i*j*k" - +"
" - ; - - input.append(TEMPLATE); - output.append(TEMPLATE); - - for (int i = TEMPLATE.length(); --i >= 0; ) { - char c = TEMPLATE.charAt(i); - - if (c == '*') { - replaceEntity(input, output, autoEnt, r, i); - } - } - - // Let's also insert preamble into input now - input.insert(0, PREAMBLE); - } - - protected void replaceEntity(StringBuffer input, StringBuffer output, - boolean autoEnt, - Random r, int index) - { - String in, out; - - switch (Math.abs(r.nextInt()) % 6) { - case 0: // Let's use one of pre-def'd entities: - switch (Math.abs(r.nextInt()) % 5) { - case 0: - in = "&"; out = "&"; - break; - case 1: - in = "'"; out = "'"; - break; - case 2: - in = "<"; out = "<"; - break; - case 3: - in = ">"; out = ">"; - break; - case 4: - in = """; out = "\""; - break; - default: throw new Error("Internal error!"); - } - break; - case 1: // How about some CDATA? - switch (Math.abs(r.nextInt()) % 5) { - case 0: - in = "]]>"; - out = "]] >"; - break; - case 1: - in = ""; - out = "xyz&abc"; - break; - case 2: - in = ""; - out = " "; - break; - case 3: - in = ""; - out = ""; - break; - case 4: - in = ""; - out = " \nxyz"; - break; - default: throw new Error("Internal error!"); - } - - case 2: // and COMMENTS - switch (Math.abs(r.nextInt()) % 5) { - case 0: - in = ""; - out = ""; - break; - case 1: - in = out = ""; - break; - case 2: - in = out = ""; - break; - case 3: - //in = out = ""; - in = out = ""; - break; - case 4: - in = out = ""; - break; - default: throw new Error("Internal error!"); - } - break; - case 3: // Char entities? - switch (Math.abs(r.nextInt()) % 4) { - case 0: - in = "#"; - out = "#"; - break; - case 1: - in = "$"; - out = "$"; - break; - case 2: - in = "©"; // above US-Ascii, copyright symbol - out = "\u00A9"; - break; - case 3: - in = "Ä"; // Upper-case a with umlauts - out = "\u00C4"; - break; - default: throw new Error("Internal error!"); - } - break; - case 4: // Full entities - switch (Math.abs(r.nextInt()) % 3) { - case 0: - in = "&ent1;"; - out = "ent1Value"; - break; - case 1: - in = "&x;"; - out = "Y"; - break; - case 2: - in = "&both;"; - out = autoEnt ? "ent1ValueY" : "&ent1;&x;"; - break; - default: throw new Error("Internal error!"); - } - break; - - case 5: // Plain text, ISO-Latin chars: - in = out = "(\u00A9)"; // copyright symbol - break; - - case 6: // Proc. instr? - switch (Math.abs(r.nextInt()) % 5) { - case 0: - in = out = ""; - break; - case 1: - in = out = ""; - break; - case 2: - in = out = ""; - break; - case 3: - in = out = "? ?>"; - break; - case 4: - in = out = "two
\r\r\r"; - break; - default: throw new Error("Internal error!"); - } - - default: - throw new Error("Internal error!"); - } - input.replace(index, index+1, in); - output.replace(index, index+1, out); - } - - /** - * Method that will normalize all unnormalized LFs (\r, \r\n) into - * normalized one (\n). - */ - protected void normalizeLFs(StringBuffer input) - { - int len = input.length(); - for (int i = len; --i >= 0; ) { - char c = input.charAt(i); - if (c == '\r') { - if (i < (len-1) && input.charAt(i+1) == '\n') { - input.deleteCharAt(i); - } else { - input.setCharAt(i, '\n'); - } - } - } - } -} diff -Nru libwoodstox-java-4.1.3/src/test/wstxtest/stream/TestAttr.java libwoodstox-java-5.1.0/src/test/wstxtest/stream/TestAttr.java --- libwoodstox-java-4.1.3/src/test/wstxtest/stream/TestAttr.java 2012-04-24 04:38:22.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/wstxtest/stream/TestAttr.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,256 +0,0 @@ -package wstxtest.stream; - -import javax.xml.stream.*; - -import com.ctc.wstx.stax.WstxInputFactory; - -public class TestAttr - extends BaseStreamTest -{ - final static String XML_11_ATTRS = - ""; - - /** - * This test case was added after encountering a specific problem, which - * only occurs when many attributes were spilled from main hash area.... - * and that's why exact attribute names do matter. - */ - public void testManyAttrs() - throws Exception - { - // First non-NS - XMLStreamReader sr = getReader(XML_11_ATTRS, false); - streamThrough(sr); - // Then NS - sr = getReader(XML_11_ATTRS, true); - streamThrough(sr); - } - - /** - * Tests that the attributes are returned in the document order; - * an invariant Woodstox honors (even though not mandated by StAX 1.0). - */ - public void testAttributeOrder() - throws XMLStreamException - { - String XML = "" - +"\n" - +"\n" - +"\n" - +"\n" - +"\n" - +"\n" - +"]>" - +"" - ; - - final String[] EXP = { - "attr4", "4", - "attr3", "3", - "defAttr", "foobar", - "attr2", "2", - "realDef", "def", - }; - - for (int i = 0; i < 2; ++i) { - boolean ns = (i > 0); - // (May) need validating, to get default attribute values - XMLStreamReader sr = getValidatingReader(XML, ns); - - assertTokenType(START_DOCUMENT, sr.getEventType()); - assertTokenType(DTD, sr.next()); - assertTokenType(START_ELEMENT, sr.next()); - - assertEquals(5, sr.getAttributeCount()); - - for (int ix = 0, len = sr.getAttributeCount(); ix < len; ++ix) { - String lname = sr.getAttributeLocalName(ix); - assertEquals("Attr #"+ix+" name", EXP[ix+ix], lname); - assertEquals("Attr #"+ix+" value", - EXP[ix+ix+1], sr.getAttributeValue(ix)); - - assertEquals("Attribute '"+lname+"' wrongly identified WRT isSpecified: ", - !lname.equals("realDef"), - sr.isAttributeSpecified(ix)); - } - - assertTokenType(END_ELEMENT, sr.next()); - } - } - - final static String NESTED_XML = - "" - +"\n" - +"\n" - +"\n" - +"\n" - +"\n" - +"\n" - +"\n" - +"\n" - +"\n" - +"\n" - +"\n" - +"\n" - +"\n" - +"\n" - +"\n" - +"\n" - +"\n" - +"\n" - +"\n" - +"]>" - +"" - +"" - +"" - +"" - +"" - +"" - +"" - ; - - /** - * Test that verifies that the counts of attributes, values etc. - * are consistent within nested elements, and in the presence/absence - * of DTD default attributes. This is tested since attribute collectors - * are highly specialized for performance, and small problems might - * not manifest with simpler tests. - *

- * Note: one more implicit assumption tested: not only is the ordering - * of explicit attributes fixed, but so is that of defaulted attributes. - * Latter always come after explicit ones, and in the same order as - * they were declared in DTD. - */ - public void testNestedAttrsNs() - throws Exception - { - XMLStreamReader sr = getValidatingReader(NESTED_XML, true); - assertTokenType(DTD, sr.next()); - - // root elem: - assertTokenType(START_ELEMENT, sr.next()); - assertEquals(3, sr.getAttributeCount()); - assertEquals("123", sr.getAttributeValue(0)); // explicit - assertEquals("rootValue", sr.getAttributeValue(1)); // default - assertEquals("xyz", sr.getAttributeValue(2)); // default - - // 1st branch: - assertTokenType(START_ELEMENT, sr.next()); - assertEquals(2, sr.getAttributeCount()); - assertEquals("a", sr.getAttributePrefix(0)); - assertEquals("b", sr.getAttributeLocalName(0)); - assertEquals("ns", sr.getAttributeNamespace(0)); - assertEquals("ab", sr.getAttributeValue(0)); // explicit - assertEquals("branchValue", sr.getAttributeValue(1)); // default - - // and how about what should NOT be found? - assertNull(sr.getAttributeValue(null, "xyz")); - - // 2nd branch: - assertTokenType(START_ELEMENT, sr.next()); - assertEquals(5, sr.getAttributeCount()); - assertEquals("a", sr.getAttributeLocalName(0)); - assertEquals("value", sr.getAttributeValue(0)); // explicit - assertEquals("xyz", sr.getAttributeLocalName(1)); - assertEquals("456", sr.getAttributeValue(1)); // explicit - assertEquals("c", sr.getAttributeLocalName(2)); - assertEquals("1", sr.getAttributeValue(2)); // explicit - assertEquals("f", sr.getAttributeLocalName(3)); - assertEquals("", sr.getAttributeValue(3)); // explicit - assertEquals("a", sr.getAttributePrefix(4)); - assertEquals("ns", sr.getAttributeNamespace(4)); - assertEquals("b", sr.getAttributeLocalName(4)); - assertEquals("xyz", sr.getAttributeValue(4)); // default - - // 1st leaf: - assertTokenType(START_ELEMENT, sr.next()); - assertEquals(2, sr.getAttributeCount()); - assertEquals("leafValue", sr.getAttributeValue(0)); // default - assertEquals("123", sr.getAttributeValue(1)); // default - - // and how about what should not be found? - assertNull(sr.getAttributeValue(null, "foo")); - assertNull(sr.getAttributeValue(null, "a")); - assertNull(sr.getAttributeValue(null, "c")); - assertNull(sr.getAttributeValue(null, "f")); - assertNull(sr.getAttributeValue(null, "xyz")); - - // close leaf - assertTokenType(END_ELEMENT, sr.next()); - - // close 2nd branch - assertTokenType(END_ELEMENT, sr.next()); - - // close 1st branch - assertTokenType(END_ELEMENT, sr.next()); - - // close root - assertTokenType(END_ELEMENT, sr.next()); - - assertTokenType(END_DOCUMENT, sr.next()); - } - - /** - * This tests handling of ATTLIST declarations for "xmlns:xx" and "xmlns" - * attributes (that is, namespace declarations). Some legacy DTDs - * (most notably, XHTML dtd) do this, and Woodstox had some problems with - * this concept... - */ - public void testNsAttr() - throws XMLStreamException - { - String XML = - "\n" - +"\n" - +"]>" - ; - XMLStreamReader sr = getReader(XML, true); - - assertTokenType(DTD, sr.next()); - assertTokenType(START_ELEMENT, sr.next()); - assertEquals(1, sr.getNamespaceCount()); - assertEquals("ns", sr.getNamespacePrefix(0)); - assertEquals("foobar", sr.getNamespaceURI(0)); - /* This will be 2, if namespace attr declarations are not handled - * properly... - */ - assertEquals(1, sr.getAttributeCount()); - assertEquals("attr", sr.getAttributeLocalName(0)); - assertEquals("123", sr.getAttributeValue(0)); - sr.close(); - } - - /* - ////////////////////////////////////////////////////// - // Internal methods - ////////////////////////////////////////////////////// - */ - - private XMLStreamReader getReader(String contents, boolean nsAware) - throws XMLStreamException - { - WstxInputFactory f = getWstxInputFactory(); - f.getConfig().doValidateWithDTD(false); - f.getConfig().doSupportNamespaces(nsAware); - return constructStreamReader(f, contents); - } - - private XMLStreamReader getValidatingReader(String contents, boolean nsAware) - throws XMLStreamException - { - WstxInputFactory f = getWstxInputFactory(); - f.getConfig().doSupportNamespaces(nsAware); - f.getConfig().doSupportDTDs(true); - f.getConfig().doValidateWithDTD(true); - return constructStreamReader(f, contents); - } -} - diff -Nru libwoodstox-java-4.1.3/src/test/wstxtest/stream/TestBufferRecycling.java libwoodstox-java-5.1.0/src/test/wstxtest/stream/TestBufferRecycling.java --- libwoodstox-java-4.1.3/src/test/wstxtest/stream/TestBufferRecycling.java 2012-04-24 04:38:22.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/wstxtest/stream/TestBufferRecycling.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,74 +0,0 @@ -package wstxtest.stream; - -import java.io.StringReader; - -import javax.xml.stream.*; - -/** - * Simple unit tests to try to verify that underlying buffers are - * properly recycled. - *

- * Please note that due to arbitrary nature of GC and its interactions - * with soft reference, as well as the way JUnit may run its unit - * tests, these tests may not be as robust as they should be. - */ -public class TestBufferRecycling - extends BaseStreamTest -{ - final static String DOC = "text"; - - /** - * Test that verifies that the underlying character buffer should - * be reused between two parsing rounds - */ - public void testCharBufferRecycling() - throws Exception - { - XMLInputFactory f = getInputFactory(); - - char[] buf1 = getCharBuffer(f.createXMLStreamReader(new StringReader(DOC)), true); - char[] buf2 = getCharBuffer(f.createXMLStreamReader(new StringReader(DOC)), true); - - if (buf1 != buf2) { - fail("Expected underlying character buffer to be recycled"); - } - } - - /** - * Inverted test to verify that the buffers are NOT shared when they - * can not be. - */ - public void testCharBufferNonRecycling() - throws Exception - { - XMLInputFactory f = getInputFactory(); - - XMLStreamReader sr1 = f.createXMLStreamReader(new StringReader(DOC)); - XMLStreamReader sr2 = f.createXMLStreamReader(new StringReader(DOC)); - char[] buf1 = getCharBuffer(sr1, false); - char[] buf2 = getCharBuffer(sr2, false); - - sr1.close(); - sr2.close(); - - if (buf1 == buf2) { - fail("Should not have identical underlying character buffers when using concurrent stream readers"); - } - } - - /* - ////////////////////////////////////////////////////// - // Internal methods - ////////////////////////////////////////////////////// - */ - - char[] getCharBuffer(XMLStreamReader sr, boolean close) - throws XMLStreamException - { - assertTokenType(START_ELEMENT, sr.next()); - assertTokenType(CHARACTERS, sr.next()); - char[] buf = sr.getTextCharacters(); - sr.close(); - return buf; - } -} diff -Nru libwoodstox-java-4.1.3/src/test/wstxtest/stream/TestComments.java libwoodstox-java-5.1.0/src/test/wstxtest/stream/TestComments.java --- libwoodstox-java-4.1.3/src/test/wstxtest/stream/TestComments.java 2012-04-24 04:38:22.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/wstxtest/stream/TestComments.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,53 +0,0 @@ -package wstxtest.stream; - -import javax.xml.stream.*; - -import wstxtest.cfg.*; - -public class TestComments - extends BaseStreamTest - implements InputTestMethod -{ - InputConfigIterator mConfigs; - - public TestComments() { - super(); - mConfigs = new InputConfigIterator(); - Configs.addAll(mConfigs); - } - - public void testValid() - throws Exception - { - mConfigs.iterate(getInputFactory(), this); - } - - /* - ////////////////////////////////////////////////////// - // Internal methods - ////////////////////////////////////////////////////// - */ - - /** - * Method called via input config iterator, with all possible - * configurations - */ - public void runTest(XMLInputFactory f, InputConfigIterator it) - throws Exception - { - String XML = "" - +"\n" - +" " - +"" - +"\n" - +""; - XMLStreamReader sr = constructStreamReader(f, XML); - streamAndCheck(sr, it, XML, XML, false); - // Let's also test real streaming... - sr = constructStreamReader(f, XML); - streamAndCheck(sr, it, XML, XML, true); - } - -} - diff -Nru libwoodstox-java-4.1.3/src/test/wstxtest/stream/TestConfig.java libwoodstox-java-5.1.0/src/test/wstxtest/stream/TestConfig.java --- libwoodstox-java-4.1.3/src/test/wstxtest/stream/TestConfig.java 2012-04-24 04:38:22.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/wstxtest/stream/TestConfig.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,127 +0,0 @@ -package wstxtest.stream; - -import javax.xml.stream.*; - -import org.codehaus.stax2.XMLStreamProperties; - -import com.ctc.wstx.api.WstxInputProperties; - -/** - * Set of unit tests that check how Woodstox handles white space in - * prolog and/or epilog. - */ -public class TestConfig - extends BaseStreamTest -{ - final static String WSTX_NAME = "woodstox"; - - /* !!! 18-Dec-2006, TSa: This needs to be resolved some other way, - * shouldn't have repeat it here (against DRY principle) - */ - final static String WSTX_VERSION = "4.1"; - - public void testSettingResolvers() - throws XMLStreamException - { - XMLInputFactory ifact = getNewInputFactory(); - // Default should be "no custom resolvers" - assertNull(ifact.getProperty(WstxInputProperties.P_DTD_RESOLVER)); - assertNull(ifact.getProperty(WstxInputProperties.P_ENTITY_RESOLVER)); - - // But if and when they are set, they should stick for both factory: - XMLResolver dtdR = new DTDResolver(); - XMLResolver entityR = new EntityResolver(); - - ifact.setProperty(WstxInputProperties.P_DTD_RESOLVER, dtdR); - ifact.setProperty(WstxInputProperties.P_ENTITY_RESOLVER, entityR); - - Object gotDtdR = ifact.getProperty(WstxInputProperties.P_DTD_RESOLVER); - Object gotEntityR = ifact.getProperty(WstxInputProperties.P_ENTITY_RESOLVER); - assertTrue("DTD resolver set for factory should stick: didn't except value ["+gotDtdR+"]", - dtdR == gotDtdR); - assertTrue("Entity resolver set for factory should stick: didn't except value ["+gotEntityR+"]", - entityR == gotEntityR); - - // and for the instances as well: - XMLStreamReader sr = constructStreamReader(ifact, ""); - gotDtdR = sr.getProperty(WstxInputProperties.P_DTD_RESOLVER); - gotEntityR = sr.getProperty(WstxInputProperties.P_ENTITY_RESOLVER); - - assertTrue("DTD resolver set should be passed to instance by factory: didn't except value ["+gotDtdR+"]", - dtdR == gotDtdR); - assertTrue("Entity resolver set should be passed to instance by factory: didn't except value ["+gotEntityR+"]", - entityR == gotEntityR); - } - - /** - * Unit test that ensures that DTD resolver gets properly called - * when configured - */ - public void testUsingDTDResolver() - throws XMLStreamException - { - // !!! TBI - } - - /** - * Unit test that ensures that entity resolver gets properly called - * when configured - */ - public void testUsingEntityResolver() - throws XMLStreamException - { - // !!! TBI - } - - public void testReaderProperties() - throws XMLStreamException - { - XMLInputFactory ifact = getNewInputFactory(); - assertEquals(WSTX_NAME, ifact.getProperty(XMLStreamProperties.XSP_IMPLEMENTATION_NAME)); - assertEquals(WSTX_VERSION, ifact.getProperty(XMLStreamProperties.XSP_IMPLEMENTATION_VERSION)); - assertEquals(Boolean.TRUE, - ifact.getProperty(XMLStreamProperties.XSP_SUPPORTS_XML11)); - } - - public void testWriterProperties() - throws XMLStreamException - { - XMLOutputFactory ofact = getNewOutputFactory(); - assertEquals(WSTX_NAME, ofact.getProperty(XMLStreamProperties.XSP_IMPLEMENTATION_NAME)); - assertEquals(WSTX_VERSION, ofact.getProperty(XMLStreamProperties.XSP_IMPLEMENTATION_VERSION)); - assertEquals(Boolean.TRUE, - ofact.getProperty(XMLStreamProperties.XSP_SUPPORTS_XML11)); - } - - /* - ////////////////////////////////////////////////////// - // Internal methods - ////////////////////////////////////////////////////// - */ - - /* - ////////////////////////////////////////////////////// - // Helper classes: - ////////////////////////////////////////////////////// - */ - - private final static class DTDResolver - implements XMLResolver - { - public Object resolveEntity(String publicID, String systemID, - String baseURI, String namespace) - { - return null; - } - } - - private final static class EntityResolver - implements XMLResolver - { - public Object resolveEntity(String publicID, String systemID, - String baseURI, String namespace) - { - return null; - } - } -} diff -Nru libwoodstox-java-4.1.3/src/test/wstxtest/stream/TestDTD.java libwoodstox-java-5.1.0/src/test/wstxtest/stream/TestDTD.java --- libwoodstox-java-4.1.3/src/test/wstxtest/stream/TestDTD.java 2012-04-24 04:38:22.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/wstxtest/stream/TestDTD.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,40 +0,0 @@ -package wstxtest.stream; - -import javax.xml.stream.*; - -import org.codehaus.stax2.*; - -/** - * Set of unit tests that checks some additional invariants Woodstox - * guarantees with respect to DOCTYPE declaration handling. - */ -public class TestDTD - extends BaseStreamTest -{ - - /** - * Tests that the DOCTYPE declaration can be succesfully skipped in - * the non-DTD-support mode. - */ - public void testSkipping() - throws XMLStreamException - { - String XML = "\n" - +"\r\n" - +"" - +"" - +"]>" - +""; - - XMLInputFactory2 f = getInputFactory(); - setSupportDTD(f, false); - XMLStreamReader2 sr = constructStreamReader(f, XML); - assertTokenType(DTD, sr.next()); - - DTDInfo info = sr.getDTDInfo(); - assertNotNull(info); - - assertTokenType(START_ELEMENT, sr.next()); - } -} diff -Nru libwoodstox-java-4.1.3/src/test/wstxtest/stream/TestEncodingDetection.java libwoodstox-java-5.1.0/src/test/wstxtest/stream/TestEncodingDetection.java --- libwoodstox-java-4.1.3/src/test/wstxtest/stream/TestEncodingDetection.java 2012-04-24 04:38:22.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/wstxtest/stream/TestEncodingDetection.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,139 +0,0 @@ -package wstxtest.stream; - -import java.io.*; - -import javax.xml.stream.*; - -/** - * This set on unit tests checks that woodstox-specific invariants - * regarding automatic input encoding detection are maintained. Some - * of these might be required by stax specification too, but it is not - * quite certain, thus tests are included in woodstox-specific packages. - */ -public class TestEncodingDetection - extends BaseStreamTest -{ - final static String ENC_EBCDIC_IN_PREFIX = "cp"; - - final static String ENC_EBCDIC_OUT_PREFIX = "IBM"; - - public void testUtf8() - throws IOException, XMLStreamException - { - /* Default is, in absence of any other indications, UTF-8... - * let's check the shortest legal doc: - */ - String XML = ""; - byte[] b = XML.getBytes("UTF-8"); - XMLStreamReader sr = getReader(b); - assertTokenType(START_DOCUMENT, sr.getEventType()); - assertNull(sr.getCharacterEncodingScheme()); - assertEquals("UTF-8", sr.getEncoding()); - // let's iterate just for fun though - assertTokenType(START_ELEMENT, sr.next()); - sr.close(); - } - - public void testUtf16() - throws XMLStreamException - { - // Should be able to figure out encoding... - String XML = "."; - - /* Let's first check a somewhat common case; figuring out UTF-16 - * encoded doc (which has to have BOM, thus); first, big-endian - */ - StringBuffer sb = new StringBuffer(XML); - sb.setCharAt(0, (char) 0xFEFF); - - byte[] b = getUtf16Bytes(sb.toString(), true); - XMLStreamReader sr = getReader(b); - assertTokenType(START_DOCUMENT, sr.getEventType()); - assertNull(sr.getCharacterEncodingScheme()); - assertEquals("UTF-16BE", sr.getEncoding()); - // let's iterate just for fun though - assertTokenType(START_ELEMENT, sr.next()); - sr.close(); - - // and then little-endian - b = getUtf16Bytes(sb.toString(), false); - sr = getReader(b); - assertTokenType(START_DOCUMENT, sr.getEventType()); - assertNull(sr.getCharacterEncodingScheme()); - assertEquals("UTF-16LE", sr.getEncoding()); - assertTokenType(START_ELEMENT, sr.next()); - sr.close(); - } - - /** - * Testing for EBCDIC is tricky, mostly due to possible - * complexity of the things to support, as well as lack - * of sample documents and difficulty in reading ones - * that exist (it not being 7-bit ascii compatible). - * But let's try a straight-forward (naive?) test - * to verify that what is supposed to work does. - */ - public void testEBCDIC() - throws IOException, XMLStreamException - { - final String[] subtypes = new String[] { - "037", "277", "278", "280", "284", "285", "297", - "420", "424", "500", "870", "871", "918", - }; - - for (int i = 0; i < subtypes.length; ++i) { - String actEnc = ENC_EBCDIC_IN_PREFIX + subtypes[i]; - String xml = "" - +"rock & roll!"; - byte[] bytes = xml.getBytes(actEnc); - XMLStreamReader sr = getReader(bytes); - - assertTokenType(START_DOCUMENT, sr.getEventType()); - - // Declared encoding should match 100% - assertEquals(actEnc, sr.getCharacterEncodingScheme()); - - // Found encoding, though, can be changed - String expEnc = ENC_EBCDIC_OUT_PREFIX + subtypes[i]; - assertEquals(expEnc, sr.getEncoding()); - - assertTokenType(START_ELEMENT, sr.next()); - assertEquals("root", sr.getLocalName()); - assertTokenType(CHARACTERS, sr.next()); - assertEquals("rock & roll!", getAndVerifyText(sr)); - assertTokenType(COMMENT, sr.next()); - assertEquals(" comment ", getAndVerifyText(sr)); - assertTokenType(END_ELEMENT, sr.next()); - assertEquals("root", sr.getLocalName()); - sr.close(); - } - } - - - /* - ///////////////////////////////////////// - // Non-test methods - ///////////////////////////////////////// - */ - - private byte[] getUtf16Bytes(String input, boolean bigEndian) - { - int len = input.length(); - byte[] b = new byte[len+len]; - int offset = bigEndian ? 1 : 0; // offset for LSB - for (int i = 0; i < len; ++i) { - int c = input.charAt(i); - // BOM is 2-byte, others 1 byte... - b[i+i+offset] = (byte) (c & 0xFF); - b[i+i+(1 - offset)] = (byte) (c >> 8); - } - return b; - } - - private XMLStreamReader getReader(byte[] b) - throws XMLStreamException - { - XMLInputFactory f = getInputFactory(); - return f.createXMLStreamReader(new ByteArrayInputStream(b)); - } -} diff -Nru libwoodstox-java-4.1.3/src/test/wstxtest/stream/TestEntityRead.java libwoodstox-java-5.1.0/src/test/wstxtest/stream/TestEntityRead.java --- libwoodstox-java-4.1.3/src/test/wstxtest/stream/TestEntityRead.java 2012-04-24 04:38:22.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/wstxtest/stream/TestEntityRead.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,281 +0,0 @@ -package wstxtest.stream; - -import java.util.*; -import javax.xml.stream.*; - -import org.codehaus.stax2.*; - -import com.ctc.wstx.api.WstxInputProperties; -import com.ctc.wstx.ent.EntityDecl; -import com.ctc.wstx.exc.WstxLazyException; -import com.ctc.wstx.sr.BasicStreamReader; - -/** - * This unit test suite checks to see that Woodstox implementation dependant - * functionality works the way it's planned to. In some cases future StAX - * revisions may dictate exact behaviour expected, but for now expected - * behaviour is based on - * a combination of educated guessing and intuitive behaviour. - */ -public class TestEntityRead - extends BaseStreamTest -{ - /** - * This unit test checks that the information received as part of the - * event, in non-expanding mode, is as expected. - */ - public void testDeclaredInNonExpandingMode() - throws XMLStreamException - { - String XML = "\n" - +"]>text:&myent;more" - ; - - // Non-expanding, coalescing: - BasicStreamReader sr = getReader(XML, false, true); - assertTokenType(DTD, sr.next()); - DTDInfo dtd = sr.getDTDInfo(); - assertNotNull(dtd); - - assertTokenType(START_ELEMENT, sr.next()); - assertEquals("root", sr.getLocalName()); - - assertTokenType(CHARACTERS, sr.next()); - assertTokenType(ENTITY_REFERENCE, sr.next()); - assertEquals("myent", sr.getLocalName()); - EntityDecl ed = sr.getCurrentEntityDecl(); - assertNotNull(ed); - assertEquals("myent", ed.getName()); - assertEquals("value", ed.getReplacementText()); - - // The pure stax way: - assertEquals("value", sr.getText()); - - // Finally, let's see that location info is about right? - Location loc = ed.getLocation(); - assertNotNull(loc); - assertEquals(2, loc.getLineNumber()); - - /* Hmmh. Not 100% if this location makes sense, but... it's the - * current behaviour, so we can regression test it. - */ - assertEquals(3, loc.getColumnNumber()); - // don't care about offsets here... location tests catch them - - assertTokenType(CHARACTERS, sr.next()); - assertTokenType(END_ELEMENT, sr.next()); - assertEquals("root", sr.getLocalName()); - - assertTokenType(END_DOCUMENT, sr.next()); - sr.close(); - } - - /** - * This unit test checks that in non-expanding mode it is acceptable - * to refer to undeclared entities. - */ - public void testUndeclaredInNonExpandingMode() - throws Exception - { - String XML = "text:&myent;more" - ; - - // Non-expanding, coalescing: - BasicStreamReader sr = getReader(XML, false, true); - assertTokenType(DTD, sr.next()); - DTDInfo dtd = sr.getDTDInfo(); - assertNotNull(dtd); - - assertTokenType(START_ELEMENT, sr.next()); - assertEquals("root", sr.getLocalName()); - - assertTokenType(CHARACTERS, sr.next()); - - /* Exception would be a real possibility, so let's catch one (if - * any) for debugging purposes: - */ - - try { - assertTokenType(ENTITY_REFERENCE, sr.next()); - } catch (XMLStreamException sex) { - fail("Did not except a stream exception on undeclared entity in non-entity-expanding mode; got: "+sex); - } - - assertEquals("myent", sr.getLocalName()); - EntityDecl ed = sr.getCurrentEntityDecl(); - assertNull(ed); - - assertTokenType(CHARACTERS, sr.next()); - assertTokenType(END_ELEMENT, sr.next()); - assertEquals("root", sr.getLocalName()); - - assertTokenType(END_DOCUMENT, sr.next()); - sr.close(); - } - - /** - * This unit test verifies that it's possible to add a Map of - * expansions from Entity names to - */ - public void testUndeclaredUsingCustomMap() - throws XMLStreamException - { - // First, let's check actual usage: - - String XML = "ok: &myent;&myent2;"; - String EXP_TEXT = "ok: (simple)expand to ([text])"; - XMLInputFactory fact = getConfiguredFactory(true, true); - Map m = new HashMap(); - m.put("myent", "(simple)"); - m.put("myent3", "[text]"); - m.put("myent2", "expand to (&myent3;)"); - fact.setProperty(WstxInputProperties.P_CUSTOM_INTERNAL_ENTITIES, m); - XMLStreamReader sr = constructStreamReader(fact, XML); - assertTokenType(START_ELEMENT, sr.next()); - assertEquals("root", sr.getLocalName()); - assertTokenType(CHARACTERS, sr.next()); - assertEquals(EXP_TEXT, getAndVerifyText(sr)); - assertTokenType(END_ELEMENT, sr.next()); - sr.close(); - - /* And then see if we can query configured value and get expected - * types of results - */ - m = (Map) fact.getProperty(WstxInputProperties.P_CUSTOM_INTERNAL_ENTITIES); - assertNotNull(m); - assertEquals(3, m.size()); - Iterator it = m.entrySet().iterator(); - while (it.hasNext()) { - Map.Entry entry = (Map.Entry) it.next(); - String name = entry.getKey().toString(); - if (name.equals("myent") || name.equals("myent2") - || name.equals("myent3")) { - // fine, let's just verify the type - EntityDecl ed = (EntityDecl) entry.getValue(); - assertNotNull(ed); - } else { - fail("Unexpected entity '"+name+"' in the custom entity map"); - } - } - } - - /** - * This unit test checks that it is possible to deal with undeclared - * entities in resolving mode too, as long as a special resolver - * is used. - */ - public void testUndeclaredButResolved() - throws Exception - { - XMLInputFactory fact = getConfiguredFactory(true, true); - - for (int i = 0; i < 3; ++i) { - String XML, expText; - XMLResolver resolver; - - switch (i) { - case 0: - XML = "value: &myent;"; - resolver = new Resolver("myent", "value"); - expText = "value: value"; - break; - case 1: - XML = "expands to:&myent;..."; - resolver = new Resolver("myent", "X&Y"); - expText = "expands to:X&Y..."; - break; - default: - XML = "testing: &myent;"; - resolver = new Resolver("dummy", "foobar"); - expText = ""; // whatever; - break; - } - - fact.setProperty(WstxInputProperties.P_UNDECLARED_ENTITY_RESOLVER, - resolver); - XMLStreamReader sr = constructStreamReader(fact, XML); - assertTokenType(START_ELEMENT, sr.next()); - assertEquals("root", sr.getLocalName()); - - if (i == 2) { // Should throw an exception, then: - try { - sr.next(); - String text = sr.getText(); // to force parsing - fail("Expected an exception for undefined entity 'myent' that doesn't resolve via customer resolver"); - } catch (XMLStreamException sex) { - ; // good; - } catch (WstxLazyException lex) { - ; // likewise - } - } else { - try { - assertTokenType(CHARACTERS, sr.next()); - } catch (XMLStreamException sex) { - // only caught to provide more meaningful fail info: - fail("Did not expect an exception, since 'myent' should have resolved; got: "+sex); - } - assertEquals(expText, sr.getText()); - assertTokenType(END_ELEMENT, sr.next()); - assertEquals("root", sr.getLocalName()); - } - } - } - - /* - //////////////////////////////////////// - // Private methods, other - //////////////////////////////////////// - */ - - /** - * Note: all readers for this set of unit tests enable DTD handling; - * otherwise entity definitions wouldn't be read. Validation shouldn't - * need to be enabled just for that purpose. - */ - private BasicStreamReader getReader(String contents, boolean replEntities, - boolean coalescing) - throws XMLStreamException - { - XMLInputFactory f = getConfiguredFactory(replEntities, coalescing); - return (BasicStreamReader) constructStreamReader(f, contents); - } - - private XMLInputFactory getConfiguredFactory(boolean replEntities, boolean coalescing) - throws XMLStreamException - { - XMLInputFactory f = getInputFactory(); - setNamespaceAware(f, true); - setSupportDTD(f, true); - setValidating(f, false); - setReplaceEntities(f, replEntities); - setCoalescing(f, coalescing); - return f; - } - - /* - //////////////////////////////////////// - // Helper classes - //////////////////////////////////////// - */ - - final static class Resolver - implements XMLResolver - { - final String mKey, mValue; - - public Resolver(String key, String value) { - mKey = key; - mValue = value; - } - - public Object resolveEntity(String publicID, String systemID, String baseURI, String namespace) - { - if (mKey.equals(namespace)) { - return mValue; - } - return null; - } - } -} diff -Nru libwoodstox-java-4.1.3/src/test/wstxtest/stream/TestLocation.java libwoodstox-java-5.1.0/src/test/wstxtest/stream/TestLocation.java --- libwoodstox-java-4.1.3/src/test/wstxtest/stream/TestLocation.java 2012-04-24 04:38:22.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/wstxtest/stream/TestLocation.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,202 +0,0 @@ -package wstxtest.stream; - -import java.io.*; -import java.util.Random; -import javax.xml.stream.*; - -import org.codehaus.stax2.*; -import com.ctc.wstx.stax.WstxInputFactory; - -/** - * Unit tests for testing Woodstox-specific features of location - * tracking. - */ -public class TestLocation - extends BaseStreamTest -{ - public void testSimpleLocation() - throws XMLStreamException - { - final String XML = "\r\n \r\n "; - - XMLInputFactory f = getWstxInputFactory(); - XMLStreamReader2 sr = (XMLStreamReader2)f.createXMLStreamReader(new StringReader(XML)); - - int type = sr.next(); - if (type == XMLStreamConstants.SPACE) { - type = sr.next(); - } - assertTokenType(START_ELEMENT, type); - - Location loc = sr.getLocationInfo().getStartLocation(); - assertEquals(2, loc.getLineNumber()); - assertEquals(3, loc.getColumnNumber()); - assertEquals(4, loc.getCharacterOffset()); - - assertTokenType(CHARACTERS, sr.next()); - assertTokenType(END_ELEMENT, sr.next()); - loc = sr.getLocationInfo().getStartLocation(); - assertEquals(3, loc.getLineNumber()); - assertEquals(2, loc.getColumnNumber()); - assertEquals(13, loc.getCharacterOffset()); - } - - public void testLineNumbers() - throws XMLStreamException - { - final int SEED = 129; - final int ROWS = 1000; - - // First, let's create xml doc: - StringBuffer sb = new StringBuffer(); - sb.append(""); - Random r = new Random(SEED); - for (int i = 0; i < ROWS; ++i) { - switch (r.nextInt() % 3) { - case 0: - sb.append("\r"); - break; - case 1: - sb.append("\r\n"); - break; - default: - sb.append("\n"); - } - int ind = r.nextInt() % 7; - while (--ind >= 0) { - sb.append(' '); - } - sb.append(""); - } - sb.append(""); - - // And then we'll parse to ensure line numbers and offsets are ok - - WstxInputFactory f = getWstxInputFactory(); - // Need to shrink it to get faster convergence - f.getConfig().setInputBufferLength(23); - XMLStreamReader2 sr = (XMLStreamReader2) f.createXMLStreamReader(new StringReader(sb.toString())); - - assertTokenType(START_ELEMENT, sr.next()); - - int linenr = 1; - int col = 4; - int chars = 3; - - r = new Random(SEED); - while (true) { - // END_ELEM signals end... - int type = sr.next(); - if (type == END_ELEMENT) { - assertEquals("a", sr.getLocalName()); - break; - } - assertTokenType(type, type); - - Location loc = sr.getLocationInfo().getStartLocation(); - assertEquals(linenr, loc.getLineNumber()); - assertEquals(col, loc.getColumnNumber()); - assertEquals(chars, loc.getCharacterOffset()); - - sb = new StringBuffer(); - boolean offByOne = false; - switch (r.nextInt() % 3) { - case 1: - offByOne = true; // Since \r\n gets truncated to \n - } - sb.append("\n"); - int ind = r.nextInt() % 7; - while (--ind >= 0) { - sb.append(' '); - } - String ws = sb.toString(); - if (!ws.equals(sr.getText())) { - fail("Expected "+quotedPrintable(ws)+", got "+quotedPrintable(sr.getText())); - } - - /* Char offset refers to input chars, and thus includes original - * linefeed (which is longer than result, for \r\n) - */ - chars += ws.length(); - if (offByOne) { - ++chars; - } - ++linenr; - // Column won't, but since it's one-based, it'll still equal ws len - col = sb.length(); - - assertTokenType(START_ELEMENT, sr.next()); - assertEquals("b", sr.getLocalName()); - loc = sr.getLocationInfo().getStartLocation(); - assertEquals("Line number wrong", linenr, loc.getLineNumber()); - assertEquals("Column number wrong (line "+linenr+")", col, loc.getColumnNumber()); - assertEquals("Character offset wrong (line "+linenr+")", chars, loc.getCharacterOffset()); - assertTokenType(END_ELEMENT, sr.next()); - assertEquals("b", sr.getLocalName()); - - chars += 4; - col += 4; - } - } - - /** - * This test was added due to bug [WSTX-97]: although it is hard to - * verify exact offset calculation, it is quite straight-forward - * to verify that it's monotonically increasing, at least. - */ - public void testOffsetIncrementing() - throws XMLStreamException - { - doTestOffset(false, false); // non-coalesce - doTestOffset(false, true); // non-coalesce - - doTestOffset(true, false); // coalesce - doTestOffset(true, true); // coalesce - } - - /* - ///////////////////////////////////////////////////////// - // Helper methods: - ///////////////////////////////////////////////////////// - */ - - public void doTestOffset(boolean coal, boolean readAll) - throws XMLStreamException - { - // First, let's create some input... - StringBuffer inputBuf = new StringBuffer(); - StringBuffer expOut = new StringBuffer(); - generateData(new Random(123), inputBuf, expOut, true); - String inputStr = inputBuf.toString(); - - WstxInputFactory f = getWstxInputFactory(); - // Should shrink it to get faster convergence - f.getConfig().setInputBufferLength(17); - f.getConfig().doCoalesceText(coal); - XMLStreamReader2 sr = (XMLStreamReader2) f.createXMLStreamReader(new StringReader(inputStr)); - - int lastLine = 0; - int lastOffset = 0; - - while (sr.next() != XMLStreamConstants.END_DOCUMENT) { - Location loc = sr.getLocation(); - int line = loc.getLineNumber(); - int offset = loc.getCharacterOffset(); - - if (line < lastLine) { - fail("Location.getLineNumber() should increase steadily, old value: "+lastLine+", new: "+line); - } - if (offset < lastOffset) { - fail("Location.getCharacterOffset() should increase steadily, old value: "+lastOffset+", new: "+offset); - } - lastLine = line; - lastOffset = offset; - - if (readAll) { // read it, or just skip? - if (sr.hasText()) { - /*String text =*/ sr.getText(); - } - } - } - } -} diff -Nru libwoodstox-java-4.1.3/src/test/wstxtest/stream/TestParsingMode.java libwoodstox-java-5.1.0/src/test/wstxtest/stream/TestParsingMode.java --- libwoodstox-java-4.1.3/src/test/wstxtest/stream/TestParsingMode.java 2012-04-24 04:38:22.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/wstxtest/stream/TestParsingMode.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,146 +0,0 @@ -package wstxtest.stream; - -import javax.xml.stream.*; - -import com.ctc.wstx.api.WstxInputProperties; - -/** - * This unit tests verifies that different input parsing modes - * (set via property {@link WstxInputProperties#P_INPUT_PARSING_MODE}) - * behave as expected - */ -public class TestParsingMode - extends BaseStreamTest -{ - final static String XML_SINGLE_DOC = - "text" - ; - - final static String XML_MULTI_DOC = - "text\n" - +"text\n" - +"text" - +"text" - +"text" - +"text" - ; - - final static String XML_FRAGMENT = - "textmore" - ; - final static String XML_FRAGMENT2 = - "some text "; - ; - - final static String XML_UNBALANCED = - "text" - ; - - public void testSingleDocumentMode() - throws XMLStreamException - { - // First the valid case: - streamThrough(getReader(XML_SINGLE_DOC, - WstxInputProperties.PARSING_MODE_DOCUMENT)); - - // Others will fail though - streamThroughFailing(getReader(XML_FRAGMENT, - WstxInputProperties.PARSING_MODE_DOCUMENT), - "Expected an exception for fragment (non-single root) input, in single-document mode"); - streamThroughFailing(getReader(XML_FRAGMENT2, - WstxInputProperties.PARSING_MODE_DOCUMENT), - "Expected an exception for fragment (root-level text) input, in single-document mode"); - streamThroughFailing(getReader(XML_MULTI_DOC, - WstxInputProperties.PARSING_MODE_DOCUMENT), - "Expected an exception for multi-document input, in single-document mode"); - - - // As should the generally invalid ones: - streamThroughFailing(getReader(XML_UNBALANCED, - WstxInputProperties.PARSING_MODE_DOCUMENT), - "Expected an exception for unbalanced xml content"); - } - - public void testMultiDocumentMode() - throws XMLStreamException - { - // First the main valid case: - streamThroughOk(getReader(XML_MULTI_DOC, - WstxInputProperties.PARSING_MODE_DOCUMENTS), - "multi-doc input in multi-doc mode"); - - // But the alternate cases should actually work too: - streamThroughOk(getReader(XML_SINGLE_DOC, - WstxInputProperties.PARSING_MODE_DOCUMENTS), - "single-doc input in multi-doc mode"); - streamThroughOk(getReader(XML_FRAGMENT, - WstxInputProperties.PARSING_MODE_DOCUMENTS), - "fragment input in multi-doc mode"); - - - // Except for some fragment cases: - streamThroughFailing(getReader(XML_FRAGMENT2, - WstxInputProperties.PARSING_MODE_DOCUMENTS), - "Expected an exception for fragments with root-level textual content"); - - // And broken one not - streamThroughFailing(getReader(XML_UNBALANCED, - WstxInputProperties.PARSING_MODE_DOCUMENTS), - "Expected an exception for unbalanced xml content"); - } - - public void testFragmentMode() - throws XMLStreamException - { - // First the main valid case2: - streamThroughOk(getReader(XML_FRAGMENT, - WstxInputProperties.PARSING_MODE_FRAGMENT), - "fragment input in fragment mode"); - streamThroughOk(getReader(XML_FRAGMENT2, - WstxInputProperties.PARSING_MODE_FRAGMENT), - "fragment input in fragment mode"); - - /* The single doc case actually works, since the xml declaration - * gets handled by the bootstrapper... (kind of implementation - * side effect) - */ - streamThroughOk(getReader(XML_SINGLE_DOC, - WstxInputProperties.PARSING_MODE_FRAGMENT), - "single-doc input in fragment mode"); - - // But multi-doc will fail, due to second xml declaration - streamThroughFailing(getReader(XML_MULTI_DOC, - WstxInputProperties.PARSING_MODE_FRAGMENT), - "Expected an exception for multi-document input, in fragment mode"); - - - // But not the invalid one: - streamThroughFailing(getReader(XML_UNBALANCED, - WstxInputProperties.PARSING_MODE_FRAGMENT), - "Expected an exception for unbalanced xml content"); - } - - /* - //////////////////////////////////////// - // Private methods, other - //////////////////////////////////////// - */ - - private XMLStreamReader getReader(String contents, WstxInputProperties.ParsingMode mode) - throws XMLStreamException - { - XMLInputFactory f = getInputFactory(); - f.setProperty(WstxInputProperties.P_INPUT_PARSING_MODE, mode); - return constructStreamReader(f, contents); - } - - void streamThroughOk(XMLStreamReader sr, String type) - throws XMLStreamException - { - try { - streamThrough(sr); - } catch (XMLStreamException sex) { - fail("Did not expect and exception for "+type+"; got: "+sex); - } - } -} diff -Nru libwoodstox-java-4.1.3/src/test/wstxtest/stream/TestPrologWS.java libwoodstox-java-5.1.0/src/test/wstxtest/stream/TestPrologWS.java --- libwoodstox-java-4.1.3/src/test/wstxtest/stream/TestPrologWS.java 2012-04-24 04:38:22.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/wstxtest/stream/TestPrologWS.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,121 +0,0 @@ -package wstxtest.stream; - -import java.io.*; - -import javax.xml.stream.*; - -import com.ctc.wstx.stax.WstxInputFactory; - -import wstxtest.cfg.*; - -/** - * Set of unit tests that check how Woodstox handles white space in - * prolog and/or epilog. - */ -import com.ctc.wstx.api.ReaderConfig; - -public class TestPrologWS - extends BaseStreamTest -{ - final static String XML1 = " \n"; - final static String XML2 = "\n \n "; - - public void testReportPrologWS() - throws IOException, XMLStreamException - { - for (int i = 0; i < 8; ++i) { - boolean lazy = (i & 1) == 0; - boolean firstDoc = (i & 2) == 0; - String content = firstDoc ? XML1 : XML2; - boolean streaming = (i & 4) != 0; - XMLStreamReader sr = getReader(content, true, lazy); - - assertTokenType(START_DOCUMENT, sr.getEventType()); - - assertTokenType(SPACE, sr.next()); - String text = streaming ? getStreamingText(sr):getAndVerifyText(sr); - if (firstDoc) { - assertEquals(" ", text); - } else { - assertEquals("\n \n", text); - } - - assertTokenType(START_ELEMENT, sr.next()); - assertTokenType(END_ELEMENT, sr.next()); - - assertTokenType(SPACE, sr.next()); - - text = streaming ? getStreamingText(sr):getAndVerifyText(sr); - if (firstDoc) { - assertEquals("\n", text); - } else { - assertEquals(" ", text); - } - - assertTokenType(END_DOCUMENT, sr.next()); - } - } - - public void testIgnorePrologWS() - throws XMLStreamException - { - for (int i = 0; i < 4; ++i) { - boolean lazy = (i & 1) == 0; - String content = ((i & 2) == 0) ? XML1 : XML2; - XMLStreamReader sr = getReader(content, false, lazy); - - assertTokenType(START_DOCUMENT, sr.getEventType()); - - assertTokenType(START_ELEMENT, sr.next()); - assertEquals("root", sr.getLocalName()); - assertTokenType(END_ELEMENT, sr.next()); - - assertTokenType(END_DOCUMENT, sr.next()); - } - } - - /* - ////////////////////////////////////////////////////// - // Internal methods - ////////////////////////////////////////////////////// - */ - - /** - * Method called via input config iterator, with all possible - * configurations - */ - public void runTest(XMLInputFactory f, InputConfigIterator it) - throws Exception - { - String XML = "" - +"\n" - +" " - +"" - +"\n" - +""; - XMLStreamReader sr = constructStreamReader(f, XML); - - streamAndCheck(sr, it, XML, XML, false); - // Let's also try 'real' streaming... - streamAndCheck(sr, it, XML, XML, true); - } - - /* - //////////////////////////////////////// - // Private methods, other - //////////////////////////////////////// - */ - - private XMLStreamReader getReader(String contents, boolean prologWS, - boolean lazyParsing) - throws XMLStreamException - { - WstxInputFactory f = (WstxInputFactory) getInputFactory(); - ReaderConfig cfg = f.getConfig(); - cfg.doReportPrologWhitespace(prologWS); - cfg.doParseLazily(lazyParsing); - return constructStreamReader(f, contents); - } -} - diff -Nru libwoodstox-java-4.1.3/src/test/wstxtest/stream/TestRandomStream.java libwoodstox-java-5.1.0/src/test/wstxtest/stream/TestRandomStream.java --- libwoodstox-java-4.1.3/src/test/wstxtest/stream/TestRandomStream.java 2012-04-24 04:38:22.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/wstxtest/stream/TestRandomStream.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,161 +0,0 @@ -package wstxtest.stream; - -import java.util.Random; -import javax.xml.stream.*; - -import wstxtest.cfg.*; - -import com.ctc.wstx.api.ReaderConfig; -import com.ctc.wstx.stax.WstxInputFactory; - -/** - * Unit test suite that ensures that independent of combinations of settings - * such as namespace-awareness, coalescing, automatic entity replacement, - * parsing results remain the same when they should. - */ -public class TestRandomStream - extends BaseStreamTest - implements InputTestMethod -{ - InputConfigIterator mConfigs; - - public TestRandomStream() { - super(); - mConfigs = new InputConfigIterator(); - mConfigs.addConfig(Configs.getLazyParsingConfig()) - .addConfig(Configs.getInputBufferSizeConfig()) - .addConfig(Configs.getMinTextSegmentConfig()) - ; - } - - public void testCoalescingAutoEntity() - throws Exception - { - mReallyStreaming = false; - doTest(false, true, true); // non-ns - doTest(true, true, true); // ns-aware - } - - public void testCoalescingAutoEntityStreaming() - throws Exception - { - mReallyStreaming = true; - doTest(true, true, true); // ns-aware - } - - public void testNonCoalescingAutoEntity() - throws Exception - { - mReallyStreaming = false; - doTest(false, false, true); // non-ns - doTest(true, false, true); // ns-aware - } - - public void testNonCoalescingAutoEntityStreaming() - throws Exception - { - mReallyStreaming = true; - doTest(true, false, true); // ns-aware - } - - public void testCoalescingNonAutoEntity() - throws Exception - { - mReallyStreaming = false; - doTest(false, true, false); // non-ns - doTest(true, true, false); // ns-aware - } - - public void testCoalescingNonAutoEntityStreaming() - throws Exception - { - mReallyStreaming = true; - doTest(true, true, false); // ns-aware - } - - public void testNonCoalescingNonAutoEntity() - throws Exception - { - mReallyStreaming = false; - doTest(false, false, false); // non-ns - doTest(true, false, false); // ns-aware - } - - public void testNonCoalescingNonAutoEntityStreaming() - throws Exception - { - mReallyStreaming = true; - doTest(true, false, false); // ns-aware - } - - /* - //////////////////////////////////////// - // Private methods, common test code - //////////////////////////////////////// - */ - - String mInput; - String mExpOutputNorm; - - boolean mReallyStreaming = false; - boolean mNormalizeLFs = true; - - /** - * Main branching point has settings for standard features; it - * will further need to loop over Woodstox-specific settings. - */ - private void doTest(boolean ns, boolean coalescing, boolean autoEntity) - throws Exception - { - /* Let's generate seed from args so it's reproducible; String hash - * code only depend on text it contains, so it'll be fixed for - * specific String. - */ - String baseArgStr = "ns: "+ns+", coalesce: "+coalescing+", entityExp: "+autoEntity; - long seed = baseArgStr.hashCode(); - - WstxInputFactory f = (WstxInputFactory) getInputFactory(); - ReaderConfig cfg = f.getConfig(); - - // Settings we always need: - cfg.doSupportDTDs(true); - cfg.doValidateWithDTD(false); - - // Then variable ones we got settings for: - cfg.doSupportNamespaces(ns); - cfg.doCoalesceText(coalescing); - cfg.doReplaceEntityRefs(autoEntity); - - // How many random permutations do we want to try? - final int ROUNDS = 5; - - for (int round = 0; round < ROUNDS; ++round) { - Random r = new Random(seed+round); - StringBuffer inputBuf = new StringBuffer(1000); - StringBuffer expOutputBuf = new StringBuffer(1000); - - generateData(r, inputBuf, expOutputBuf, autoEntity); - - mInput = inputBuf.toString(); - normalizeLFs(expOutputBuf); - mExpOutputNorm = expOutputBuf.toString(); - mConfigs.iterate(f, this); - } - } - - /** - * Method called via input config iterator, with all possible - * configurations - */ - public void runTest(XMLInputFactory f, InputConfigIterator it) - throws Exception - { - String exp = mExpOutputNorm; - - // First, let's skip through it all - streamAndSkip(f, it, mInput); - - // and then the 'real' test: - streamAndCheck(f, it, mInput, exp, mReallyStreaming); - } -} diff -Nru libwoodstox-java-4.1.3/src/test/wstxtest/stream/TestStreaming.java libwoodstox-java-5.1.0/src/test/wstxtest/stream/TestStreaming.java --- libwoodstox-java-4.1.3/src/test/wstxtest/stream/TestStreaming.java 2012-04-24 04:38:22.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/wstxtest/stream/TestStreaming.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,158 +0,0 @@ -package wstxtest.stream; - -import java.io.*; - -import javax.xml.stream.*; - -import org.codehaus.stax2.XMLStreamReader2; - -import com.ctc.wstx.stax.WstxInputFactory; - -/** - * This test verifies that the "fully streaming" text access method(s) - * do not return partial text/CDATA segments no matter what the mode - * is. - *

- * Note that although this test should really be part of StAX2 test - * suite, currently there is no standard way to define properties that - * would make it more likely that the parser may return partial - * text segments; but Woodstox does. So, for now we can at least - * test that Woodstox is conformant... ;-) - */ -public class TestStreaming - extends BaseStreamTest -{ - public void testTextStreaming() - throws IOException, XMLStreamException - { - String CONTENT_IN = - "Some content\nthat will be " - +""streamed" & sliced" - +" and\nprocessed..."; - ; - String CONTENT_OUT = - "Some content\nthat will be " - +"\"streamed\" & sliced" - +" and\nprocessed..."; - ; - /* Let's also add trailing CDATA, to ensure no coalescing is done - * when not requested - */ - String XML = "" + CONTENT_IN + ""; - XMLStreamReader2 sr = getReader(XML, false); - assertTokenType(START_ELEMENT, sr.next()); - assertTokenType(CHARACTERS, sr.next()); - StringWriter sw = new StringWriter(); - sr.getText(sw, false); - String act = sw.toString(); - if (!act.equals(CONTENT_OUT)) { - if (CONTENT_OUT.startsWith(act)) { - fail("Streaming text accessors returned partial match; first " - +act.length()+" chars of the expected " - +CONTENT_OUT.length()+" chars"); - } - fail("Content accessed using streaming text accessor (len " - +act.length()+"; exp "+CONTENT_OUT.length()+" chars) wrong: " - +"expected ["+CONTENT_OUT+"], got ["+act+"]"); - } - - // And should get the following CDATA, then: - assertTokenType(CDATA, sr.next()); - // and then closing element; let's not check CDATA contents here - assertTokenType(END_ELEMENT, sr.next()); - } - - public void testCDataStreaming() - throws IOException, XMLStreamException - { - String CONTENT_INOUT = - "Some content\nthat will be stored in a\n" - +"CDATA Block <[*]>\n" - +" yet not be split in any way...." - ; - /* Let's also add trailing text, to ensure no coalescing is done - * when not requested - */ - String XML = "some text!"; - XMLStreamReader2 sr = getReader(XML, false); - assertTokenType(START_ELEMENT, sr.next()); - assertTokenType(CDATA, sr.next()); - StringWriter sw = new StringWriter(); - sr.getText(sw, false); - String act = sw.toString(); - if (!act.equals(CONTENT_INOUT)) { - if (CONTENT_INOUT.startsWith(act)) { - fail("Streaming text accessors returned partial match; first " - +act.length()+" chars of the expected " - +CONTENT_INOUT.length()+" chars"); - } - fail("Content accessed using streaming text accessor (len " - +act.length()+"; exp "+CONTENT_INOUT.length()+" chars) wrong: " - +"expected ["+CONTENT_INOUT+"], got ["+act+"]"); - } - - // And should get the following CHARACTERS then: - assertTokenType(CHARACTERS, sr.next()); - // and then closing element; let's not check text contents here - assertTokenType(END_ELEMENT, sr.next()); - } - - /** - * Let's also ensure that coalescing still works ok with streaming - * as well... - */ - public void testCoalescingStreaming() - throws IOException, XMLStreamException - { - String CONTENT_IN1 = - "First text\n cdata " - ; - String CONTENT_OUT1 = "First text\n and cdata ..."; - String CONTENT_IN2 = - " and textneat-o!"; - ; - String CONTENT_OUT2 = "Then CDATA and text...\nneat-o!"; - - for (int i = 0; i < 2; ++i) { - boolean first = (i == 0); - String XML = "" + (first ? CONTENT_IN1 : CONTENT_IN2) + ""; - XMLStreamReader2 sr = getReader(XML, true); - assertTokenType(START_ELEMENT, sr.next()); - assertTokenType(CHARACTERS, sr.next()); - StringWriter sw = new StringWriter(); - sr.getText(sw, false); - String act = sw.toString(); - String exp = first ? CONTENT_OUT1 : CONTENT_OUT2; - if (!act.equals(exp)) { - if (exp.startsWith(act)) { - fail("Streaming text accessors returned partial match; first " - +act.length()+" chars of the expected " - +exp.length()+" chars"); - } - fail("Content accessed using streaming text accessor (len " - +act.length()+"; exp "+exp.length()+" chars) wrong: " - +"expected ["+exp+"], got ["+act+"]"); - } - // and then closing element - assertTokenType(END_ELEMENT, sr.next()); - } - } - - /* - ////////////////////////////////////////////////////// - // Internal methods - ////////////////////////////////////////////////////// - */ - - private XMLStreamReader2 getReader(String contents, boolean coalesce) - throws XMLStreamException - { - WstxInputFactory f = getWstxInputFactory(); - f.getConfig().doSupportNamespaces(true); - f.getConfig().doCoalesceText(coalesce); - f.getConfig().setInputBufferLength(16); - f.getConfig().setShortestReportedTextSegment(4); - return (XMLStreamReader2) constructStreamReader(f, contents); - } - -} diff -Nru libwoodstox-java-4.1.3/src/test/wstxtest/stream/TestTreatCharRefAsEnts.java libwoodstox-java-5.1.0/src/test/wstxtest/stream/TestTreatCharRefAsEnts.java --- libwoodstox-java-4.1.3/src/test/wstxtest/stream/TestTreatCharRefAsEnts.java 2012-04-24 04:38:22.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/wstxtest/stream/TestTreatCharRefAsEnts.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,118 +0,0 @@ -/** - * $Id$ - * - * (c) 2006 acrolinx GmbH All rights reserved. - * - * Created on 09.04.2010 Last changed: $Date$ - * - * @author schwarz, last changed by $Author$ - * @version $Revision$ - */ - -package wstxtest.stream; - -import javax.xml.stream.Location; -import javax.xml.stream.XMLInputFactory; -import javax.xml.stream.XMLStreamException; - -import com.ctc.wstx.api.WstxInputProperties; -import com.ctc.wstx.ent.EntityDecl; -import com.ctc.wstx.sr.BasicStreamReader; - -/** - * @author schwarz - * - */ -public class TestTreatCharRefAsEnts - extends BaseStreamTest -{ - protected static void setTreatCharRefsAsEnts(XMLInputFactory f, boolean state) - throws XMLStreamException - { - f.setProperty(WstxInputProperties.P_TREAT_CHAR_REFS_AS_ENTS, - state ? Boolean.TRUE : Boolean.FALSE); - } - - public void testReturnEntityForCharReference() throws Exception - { - - String XML = "text & more"; - - BasicStreamReader sr = getReader(XML, true, true, 1); - - assertTokenType(START_ELEMENT, sr.next()); - assertEquals("root", sr.getLocalName()); - - assertTokenType(CHARACTERS, sr.next()); - - assertEquals("text ", sr.getText()); - - assertTokenType(ENTITY_REFERENCE, sr.next()); - assertEquals("amp", sr.getLocalName()); - EntityDecl ed = sr.getCurrentEntityDecl(); - assertNotNull(ed); - assertEquals("amp", ed.getName()); - assertEquals("&", ed.getReplacementText()); - - // The pure stax way: - assertEquals("&", sr.getText()); - - // Finally, let's see that location info is about right? - Location loc = sr.getCurrentLocation(); - assertNotNull(loc); - assertEquals(16, loc.getCharacterOffset()); - } - - public void testReturnCharsReference() throws Exception - { - String XML = "text & more"; - - // 64 is the default - BasicStreamReader sr = getReader(XML, true, false, 1); - - assertTokenType(START_ELEMENT, sr.next()); - assertEquals("root", sr.getLocalName()); - - assertTokenType(CHARACTERS, sr.next()); - assertEquals("text ", sr.getText()); - - assertTokenType(CHARACTERS, sr.next()); - assertEquals("& more", sr.getText()); - } - - public void testReturnCharsReferenceWithHighMinTextSegment() throws Exception - { - String XML = "text & more"; - - // 64 is the default - BasicStreamReader sr = getReader(XML, true, true, 64); - - assertTokenType(START_ELEMENT, sr.next()); - assertEquals("root", sr.getLocalName()); - - assertTokenType(CHARACTERS, sr.next()); - - assertEquals("text & more", sr.getText()); - } - - private BasicStreamReader getReader(String contents, boolean replEntities, - boolean treatCharRefsAsEnts, int minTextSegment) - throws XMLStreamException - { - XMLInputFactory f = getConfiguredFactory(replEntities, treatCharRefsAsEnts, minTextSegment); - return (BasicStreamReader) constructStreamReader(f, contents); - } - - private XMLInputFactory getConfiguredFactory(boolean replEntities, boolean treatCharRefsAsEnts, - int minTextSegment) - throws XMLStreamException - { - XMLInputFactory f = getInputFactory(); - setValidating(f, false); - setReplaceEntities(f, replEntities); - setTreatCharRefsAsEnts(f, treatCharRefsAsEnts); - setMinTextSegment(f, minTextSegment); - return f; - } - -} diff -Nru libwoodstox-java-4.1.3/src/test/wstxtest/stream/TestXml11.java libwoodstox-java-5.1.0/src/test/wstxtest/stream/TestXml11.java --- libwoodstox-java-4.1.3/src/test/wstxtest/stream/TestXml11.java 2012-04-24 04:38:22.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/wstxtest/stream/TestXml11.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,109 +0,0 @@ -package wstxtest.stream; - -import javax.xml.stream.*; - -/** - * This is a small test suite has some checks for features of xml 1.1 - * that are different from those of 1.0. - */ -public class TestXml11 - extends BaseStreamTest -{ - /** - * This test checks that it is illegal to try to unbind a prefix; - * only default namespace can be unbound. - */ - public void testInvalidUnbinding() - throws XMLStreamException - { - final String XML = - "" - +"" - +"" - ; - XMLStreamReader sr = getReader(XML); - assertTokenType(START_ELEMENT, sr.next()); - // This should result in an exception: - try { - /*int type =*/ sr.next(); // usually fails here - /*type =*/ sr.next(); // but if not, at least here (END_ELEMENT) - fail("Expected a stream exception due to namespace unbind for xml 1.0 document"); - } catch (XMLStreamException sex) { - ; //good - } - } - - /** - * Test case adapted from XMLTest (based on - * xmlconf/eduni/namespaces/1.1/004.xml) - */ - public void testValidRebinding() - throws XMLStreamException - { - final String XML = - "" -+"" -+"" -+"" -+"" -+"" - ; - XMLStreamReader sr = getReader(XML); - assertTokenType(START_ELEMENT, sr.next()); // foo - assertEquals("foo", sr.getLocalName()); - - assertTokenType(START_ELEMENT, sr.next()); // bar - assertEquals("bar", sr.getLocalName()); - - assertTokenType(START_ELEMENT, sr.next()); // foo (inner) - assertEquals("foo", sr.getLocalName()); - - assertTokenType(END_ELEMENT, sr.next()); // /foo (inner) - assertEquals("foo", sr.getLocalName()); - assertTokenType(END_ELEMENT, sr.next()); // /bar - assertEquals("bar", sr.getLocalName()); - assertTokenType(END_ELEMENT, sr.next()); // /foo - assertEquals("foo", sr.getLocalName()); - } - - /** - * Test case adapted from XMLTest (based on - * xmlconf/eduni/namespaces/1.1/005.xml) - */ - public void testInvalidUseOfUnbound() - throws XMLStreamException - { - final String XML = - "" - +"" - +"" - ; - XMLStreamReader sr = getReader(XML); - assertTokenType(START_ELEMENT, sr.next()); - // This should result in an exception: - try { - int type = sr.next(); // usually fails here - type = sr.next(); // but if not, at least here - fail("Expected a stream exception due to a reference to an explicitly unbound prefix 'a'"); - } catch (XMLStreamException sex) { - ; //good - } - } - - /* - ////////////////////////////////////////////////// - // Helper methods - ////////////////////////////////////////////////// - */ - - private XMLStreamReader getReader(String contents) - throws XMLStreamException - { - XMLInputFactory f = getWstxInputFactory(); - setNamespaceAware(f, true); - setCoalescing(f, false); - setValidating(f, false); - setSupportDTD(f, false); - return constructStreamReader(f, contents); - } -} diff -Nru libwoodstox-java-4.1.3/src/test/wstxtest/stream/TestXmlId.java libwoodstox-java-5.1.0/src/test/wstxtest/stream/TestXmlId.java --- libwoodstox-java-4.1.3/src/test/wstxtest/stream/TestXmlId.java 2012-04-24 04:38:22.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/wstxtest/stream/TestXmlId.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,207 +0,0 @@ -package wstxtest.stream; - -import javax.xml.stream.*; - -import org.codehaus.stax2.XMLInputFactory2; -import org.codehaus.stax2.XMLStreamReader2; -import org.codehaus.stax2.validation.XMLValidationException; - -/** - * Set of unit tests that check that Woodstox support for Xml:id works - * as expected. - */ -public class TestXmlId - extends BaseStreamTest -{ - final static String XML_WITH_XMLID = - "" - +"" - +"" - +"" - +"" - ; - - final static String XML_WITH_XMLID_INVALID = - "\n" - +"\n" - +"]>" - ; - - public void testXmlIdEnabledNs() - throws XMLStreamException - { - doTestXmlId(true, true, false); // xmlid enabled, non-coal - doTestXmlId(true, true, true); // xmlid enabled, coal - } - - public void testXmlIdDisabledNs() - throws XMLStreamException - { - doTestXmlId(false, true, false); // xmlid disabled, non-coal - doTestXmlId(false, true, true); // xmlid disabled, coal - } - - public void testXmlIdEnabledNonNs() - throws XMLStreamException - { - doTestXmlId(true, false, false); // xmlid enabled, non-coal - doTestXmlId(true, false, true); // xmlid enabled, coal - } - - public void testXmlIdDisabledNonNs() - throws XMLStreamException - { - doTestXmlId(false, false, false); // xmlid disabled, non-coal - doTestXmlId(false, false, true); // xmlid disabled, coal - } - - /** - * This unit test verifies that incorrect DTD attribute type for - * xml:id causes a validation exception - */ - public void testInvalidXmlIdNs() - throws XMLStreamException - { - doTestInvalid(true, false); - doTestInvalid(true, true); - } - - public void testInvalidXmlIdNonNs() - throws XMLStreamException - { - doTestInvalid(false, false); - doTestInvalid(false, true); - } - - public void testInvalidXmlIdDisabledNs() - throws XMLStreamException - { - doTestInvalidDisabled(true, false); - doTestInvalidDisabled(true, true); - } - - public void testInvalidXmlIdDisabledNonNs() - throws XMLStreamException - { - doTestInvalidDisabled(false, false); - doTestInvalidDisabled(false, true); - } - - /* - ///////////////////////////////////// - // - ///////////////////////////////////// - */ - - private void doTestXmlId(boolean xmlidEnabled, - boolean nsAware, boolean coal) - throws XMLStreamException - { - XMLStreamReader2 sr = getReader(XML_WITH_XMLID, xmlidEnabled, nsAware, coal); - final String xmlidType = xmlidEnabled ? "ID" : "CDATA"; - - // root: - assertTokenType(START_ELEMENT, sr.next()); - assertEquals(1, sr.getAttributeCount()); - assertEquals("id", sr.getAttributeLocalName(0)); - assertEquals("CDATA", sr.getAttributeType(0)); - assertEquals(-1, sr.getAttributeInfo().getIdAttributeIndex()); - - // leaf#1: - assertTokenType(START_ELEMENT, sr.next()); - assertEquals(1, sr.getAttributeCount()); - assertEquals("abc", sr.getAttributeValue(0)); - if (xmlidEnabled) { - assertEquals(0, sr.getAttributeInfo().getIdAttributeIndex()); - } else { - assertEquals(-1, sr.getAttributeInfo().getIdAttributeIndex()); - } - assertEquals(xmlidType, sr.getAttributeType(0)); - assertTokenType(END_ELEMENT, sr.next()); - - // leaf#2: - assertTokenType(START_ELEMENT, sr.next()); - assertEquals(1, sr.getAttributeCount()); - assertEquals("foobar", sr.getAttributeValue(0)); - assertEquals("id", sr.getAttributeLocalName(0)); - assertEquals(-1, sr.getAttributeInfo().getIdAttributeIndex()); - assertEquals("CDATA", sr.getAttributeType(0)); - assertTokenType(END_ELEMENT, sr.next()); - - // leaf#3: - assertTokenType(START_ELEMENT, sr.next()); - assertEquals(1, sr.getAttributeCount()); - assertEquals(xmlidType, sr.getAttributeType(0)); - if (xmlidEnabled) { - assertEquals(0, sr.getAttributeInfo().getIdAttributeIndex()); - } else { - assertEquals(-1, sr.getAttributeInfo().getIdAttributeIndex()); - } - - // also, should be normalized: - if (xmlidEnabled) { - assertEquals("_otherId", sr.getAttributeValue(0)); - } else { - assertEquals(" _otherId ", sr.getAttributeValue(0)); - } - assertTokenType(END_ELEMENT, sr.next()); - - sr.close(); - } - - private void doTestInvalid(boolean nsAware, boolean coal) - throws XMLStreamException - { - XMLStreamReader2 sr = getValidatingReader(XML_WITH_XMLID_INVALID, nsAware, coal); - try { - assertTokenType(DTD, sr.next()); - assertTokenType(START_ELEMENT, sr.next()); - fail("Expected a validation exception for invalid Xml:id attribute declaration"); - } catch (XMLValidationException vex) { - //System.err.println("VLD exc -> "+vex); - } - } - - private void doTestInvalidDisabled(boolean nsAware, boolean coal) - throws XMLStreamException - { - /* In non-validating mode, shouldn't matter: but just to make sure, - * let's also disable xml:id processing - */ - XMLStreamReader2 sr = getReader(XML_WITH_XMLID_INVALID, false, nsAware, coal); - assertTokenType(DTD, sr.next()); - assertTokenType(START_ELEMENT, sr.next()); - } - - private XMLStreamReader2 getReader(String contents, - boolean xmlidEnabled, - boolean nsAware, boolean coal) - throws XMLStreamException - { - XMLInputFactory2 f = getInputFactory(); - setSupportDTD(f, true); - setValidating(f, false); - setCoalescing(f, coal); - setNamespaceAware(f, nsAware); - f.setProperty(XMLInputFactory2.XSP_SUPPORT_XMLID, - xmlidEnabled - ? XMLInputFactory2.XSP_V_XMLID_TYPING - : XMLInputFactory2.XSP_V_XMLID_NONE); - return constructStreamReader(f, contents); - } - - private XMLStreamReader2 getValidatingReader(String contents, - boolean nsAware, boolean coal) - throws XMLStreamException - { - XMLInputFactory2 f = getInputFactory(); - setSupportDTD(f, true); - setValidating(f, true); - setCoalescing(f, coal); - setNamespaceAware(f, nsAware); - f.setProperty(XMLInputFactory2.XSP_SUPPORT_XMLID, - XMLInputFactory2.XSP_V_XMLID_TYPING); - return constructStreamReader(f, contents); - } -} diff -Nru libwoodstox-java-4.1.3/src/test/wstxtest/TestDefaultNamespacePrefix.java libwoodstox-java-5.1.0/src/test/wstxtest/TestDefaultNamespacePrefix.java --- libwoodstox-java-4.1.3/src/test/wstxtest/TestDefaultNamespacePrefix.java 2012-04-24 04:38:22.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/wstxtest/TestDefaultNamespacePrefix.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,34 +0,0 @@ - -package wstxtest; - -import java.io.StringReader; - -import javax.xml.stream.XMLInputFactory; -import javax.xml.stream.XMLStreamReader; -import javax.xml.stream.events.XMLEvent; - -import com.ctc.wstx.api.WstxInputProperties; - -/** - * @since 4.1.2 - */ -public class TestDefaultNamespacePrefix extends BaseWstxTest -{ - public void testDefaultNamespacePrefix() throws Exception { - String XML = "foo"; - System.setProperty("com.ctc.wstx.returnNullForDefaultNamespace", "true"); - XMLInputFactory factory = getInputFactory(); - XMLStreamReader r = factory.createXMLStreamReader(new StringReader(XML)); - while (r.hasNext()) { - r.next(); - if ((r.getEventType() == XMLEvent.START_ELEMENT) && (r.getLocalName().equals("blah"))) { - String prefix = r.getNamespacePrefix(0); - if (prefix != null) { - throw new Exception("Null value is not returned for the default namespace prefix while " - + WstxInputProperties.P_RETURN_NULL_FOR_DEFAULT_NAMESPACE + " is set true"); - } - break; - } - } - } -} diff -Nru libwoodstox-java-4.1.3/src/test/wstxtest/TestInputFactory.java libwoodstox-java-5.1.0/src/test/wstxtest/TestInputFactory.java --- libwoodstox-java-4.1.3/src/test/wstxtest/TestInputFactory.java 2012-04-24 04:38:22.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/wstxtest/TestInputFactory.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,65 +0,0 @@ -package wstxtest; - -import javax.xml.stream.*; - -import org.codehaus.stax2.*; - -import com.ctc.wstx.cfg.ErrorConsts; -import com.ctc.wstx.api.ReaderConfig; -import com.ctc.wstx.stax.WstxInputFactory; - -/** - * Simple test-driver that tries to exercise some of basic input factory - * settings, like instantiating various reader instances, checking for - * invalid arguments and so on. - */ -public class TestInputFactory - extends BaseWstxTest -{ - public void testConfig() - throws XMLStreamException - { - XMLInputFactory2 f = getNewInputFactory(); - - ReaderConfig cfg = ((WstxInputFactory) f).getConfig(); - assertNotNull(cfg); - - assertNull(f.getEventAllocator()); - assertNull(f.getXMLResolver()); - - assertNull(f.getXMLReporter()); - MyReporter rep = new MyReporter(); - f.setXMLReporter(rep); - assertEquals(rep, f.getXMLReporter()); - - assertFalse(f.isPropertySupported("foobar")); - } - - public void testMisc() - throws XMLStreamException - { - /* This is silly, but coverage testing is not happy that our - * error-constant-defining class is never constructed. - * So here we go, just to mark it off the list... - */ - ErrorConsts ec = new ErrorConsts(); - assertNotNull(ErrorConsts.tokenTypeDesc(XMLStreamConstants.START_DOCUMENT)); - assertNotNull(ErrorConsts.tokenTypeDesc(XMLStreamConstants.END_DOCUMENT)); - assertNotNull(ErrorConsts.tokenTypeDesc(XMLStreamConstants.ATTRIBUTE)); - } - - /* - //////////////////////////////////////////////////////////// - // Non-test methods etc - //////////////////////////////////////////////////////////// - */ - - final static class MyReporter - implements XMLReporter - { - public void report(String message, String errorType, Object relatedInformation, Location location) - { - // fine... - } - } -} diff -Nru libwoodstox-java-4.1.3/src/test/wstxtest/TestOutputFactory.java libwoodstox-java-5.1.0/src/test/wstxtest/TestOutputFactory.java --- libwoodstox-java-4.1.3/src/test/wstxtest/TestOutputFactory.java 2012-04-24 04:38:22.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/wstxtest/TestOutputFactory.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,82 +0,0 @@ -package wstxtest; - -import javax.xml.stream.*; - -import org.codehaus.stax2.*; - -import com.ctc.wstx.api.WriterConfig; -import com.ctc.wstx.api.WstxInputProperties; -import com.ctc.wstx.api.WstxOutputProperties; -import com.ctc.wstx.stax.WstxOutputFactory; - -/** - * Simple test-driver that tries to exercise some of basic output factory - * settings, like instantiating various writer instances, checking for - * invalid arguments and so on. - */ -public class TestOutputFactory - extends BaseWstxTest -{ - public void testConfig() - throws XMLStreamException - { - XMLOutputFactory2 f = getNewOutputFactory(); - - WriterConfig cfg = ((WstxOutputFactory) f).getConfig(); - assertNotNull(cfg); - - assertFalse(f.isPropertySupported("foobar")); - - // Let's just test some of known properties that should be supported... - assertTrue(f.isPropertySupported(WstxOutputProperties.P_OUTPUT_VALIDATE_STRUCTURE)); - assertTrue(f.isPropertySupported(WstxOutputProperties.P_OUTPUT_VALIDATE_CONTENT)); - - // And their default values? - assertEquals(Boolean.TRUE, f.getProperty(WstxOutputProperties.P_OUTPUT_VALIDATE_STRUCTURE)); - assertEquals(Boolean.TRUE, f.getProperty(WstxOutputProperties.P_OUTPUT_VALIDATE_CONTENT)); - - assertEquals(Boolean.FALSE, f.getProperty(WstxOutputProperties.P_OUTPUT_VALIDATE_ATTR)); - assertEquals(Boolean.FALSE, f.getProperty(WstxOutputProperties.P_OUTPUT_VALIDATE_NAMES)); - assertEquals(Boolean.FALSE, f.getProperty(WstxOutputProperties.P_OUTPUT_CDATA_AS_TEXT)); - assertEquals(Boolean.FALSE, f.getProperty(WstxOutputProperties.P_COPY_DEFAULT_ATTRS)); - - // As per [WSTX-120], default with Woodstox 4.0 is false: - assertEquals(Boolean.FALSE, f.getProperty(WstxOutputProperties.P_OUTPUT_FIX_CONTENT)); - assertEquals(Boolean.TRUE, f.getProperty(XMLOutputFactory2.P_AUTOMATIC_EMPTY_ELEMENTS)); - assertEquals(Boolean.TRUE, f.getProperty(XMLStreamProperties.XSP_NAMESPACE_AWARE)); - - assertNull(f.getProperty(XMLStreamProperties.XSP_PROBLEM_REPORTER)); - assertNull(f.getProperty(XMLOutputFactory2.P_TEXT_ESCAPER)); - assertNull(f.getProperty(XMLOutputFactory2.P_ATTR_VALUE_ESCAPER)); - - // ... which can be changed - f.setProperty(WstxOutputProperties.P_OUTPUT_VALIDATE_STRUCTURE, Boolean.FALSE); - assertEquals(Boolean.FALSE, f.getProperty(WstxOutputProperties.P_OUTPUT_VALIDATE_STRUCTURE)); - - f.setProperty(WstxOutputProperties.P_OUTPUT_VALIDATE_CONTENT, Boolean.FALSE); - assertEquals(Boolean.FALSE, f.getProperty(WstxOutputProperties.P_OUTPUT_VALIDATE_CONTENT)); - - f.setProperty(WstxOutputProperties.P_OUTPUT_VALIDATE_CONTENT, Boolean.FALSE); - assertEquals(Boolean.FALSE, f.getProperty(WstxOutputProperties.P_OUTPUT_VALIDATE_CONTENT)); - - f.setProperty(WstxOutputProperties.P_OUTPUT_VALIDATE_NAMES, Boolean.TRUE); - assertEquals(Boolean.TRUE, f.getProperty(WstxOutputProperties.P_OUTPUT_VALIDATE_NAMES)); - f.setProperty(WstxOutputProperties.P_OUTPUT_VALIDATE_ATTR, Boolean.TRUE); - assertEquals(Boolean.TRUE, f.getProperty(WstxOutputProperties.P_OUTPUT_VALIDATE_ATTR)); - } - - public void testMisc() - throws XMLStreamException - { - /* This is silly, but coverage testing is not happy that our - * constant-defining classes are never constructed. So here we go, - * just to mark it off the list... - */ - WstxInputProperties fooin = new WstxInputProperties(); - WstxOutputProperties fooout = new WstxOutputProperties(); - - // These just to keep compilers/FindBugs etc happy - assertNotNull(fooin); - assertNotNull(fooout); - } -} diff -Nru libwoodstox-java-4.1.3/src/test/wstxtest/util/TestArgUtil.java libwoodstox-java-5.1.0/src/test/wstxtest/util/TestArgUtil.java --- libwoodstox-java-4.1.3/src/test/wstxtest/util/TestArgUtil.java 2012-04-24 04:38:22.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/wstxtest/util/TestArgUtil.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,56 +0,0 @@ -package wstxtest.util; - -import java.util.*; - -import junit.framework.TestCase; - -import com.ctc.wstx.util.ArgUtil; - -/** - * Simple unit tests for testing methods in {@link ArgUtil}. - */ -public class TestArgUtil - extends TestCase -{ - public void testBoolean() - { - assertFalse(ArgUtil.convertToBoolean("test", "false")); - assertFalse(ArgUtil.convertToBoolean("test", "False")); - assertFalse(ArgUtil.convertToBoolean("test", "FALSE")); - assertTrue(ArgUtil.convertToBoolean("test", "true")); - assertTrue(ArgUtil.convertToBoolean("test", "True")); - assertTrue(ArgUtil.convertToBoolean("test", "TRUE")); - assertFalse(ArgUtil.convertToBoolean("test", null)); - - // and then errors: - try { - /*boolean b =*/ ArgUtil.convertToBoolean("test", new Integer(0)); - fail("Expected an IllegalArgumentException"); - } catch (IllegalArgumentException iae) { } - - try { - /*boolean b =*/ ArgUtil.convertToBoolean("test", "foobar"); - fail("Expected an IllegalArgumentException"); - } catch (IllegalArgumentException iae) { } - } - - public void testInt() - { - assertEquals(14, ArgUtil.convertToInt("test", "14", 0)); - assertEquals(14, ArgUtil.convertToInt("test", new Integer(14), 0)); - assertEquals(14, ArgUtil.convertToInt("test", new Long(14L), 0)); - assertEquals(14, ArgUtil.convertToInt("test", new Short((short) 14), 0)); - assertEquals(14, ArgUtil.convertToInt("test", new Byte((byte) 14), 0)); - - // and then errors: - try { - /*int x =*/ ArgUtil.convertToInt("test", new HashMap(), 0); - fail("Expected an IllegalArgumentException"); - } catch (IllegalArgumentException iae) { } - - try { - /*int x =*/ ArgUtil.convertToInt("test", "foobar", 0); - fail("Expected an IllegalArgumentException"); - } catch (IllegalArgumentException iae) { } - } -} diff -Nru libwoodstox-java-4.1.3/src/test/wstxtest/util/TestBijectiveNsMap.java libwoodstox-java-5.1.0/src/test/wstxtest/util/TestBijectiveNsMap.java --- libwoodstox-java-4.1.3/src/test/wstxtest/util/TestBijectiveNsMap.java 2012-04-24 04:38:22.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/wstxtest/util/TestBijectiveNsMap.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,51 +0,0 @@ -package wstxtest.util; - -import java.util.*; - -import junit.framework.TestCase; - -import com.ctc.wstx.util.BijectiveNsMap; - -/** - * Unit test to verify problem [WSTX-202]. - */ -public class TestBijectiveNsMap - extends TestCase -{ - public void testMaskingForFindPrefix() throws Exception - { - BijectiveNsMap nsMap = BijectiveNsMap.createEmpty(); - nsMap.addMapping("ns", "abc"); - assertEquals("ns", nsMap.findPrefixByUri("abc")); - // and then let's mask it - nsMap = nsMap.createChild(); - nsMap.addMapping("ns", "xyz"); - String uri = nsMap.findPrefixByUri("abc"); - if (uri != null) { - fail("Expected null for masked prefix, got '"+uri+"'"); - } - } - - public void testMaskingForGetBoundPrefixes() throws Exception - { - BijectiveNsMap nsMap = BijectiveNsMap.createEmpty(); - nsMap.addMapping("ns", "abc"); - List l = nsMap.getPrefixesBoundToUri("abc", null); - assertEquals(1, l.size()); - assertEquals("ns", l.iterator().next()); - - // and then let's mask it - nsMap = nsMap.createChild(); - nsMap.addMapping("ns", "xyz"); - assertEquals(0, nsMap.getPrefixesBoundToUri("abc", new ArrayList()).size()); - - // and finally, let's re-bind it - nsMap = nsMap.createChild(); - nsMap.addMapping("ns", "abc"); - assertEquals(1, nsMap.getPrefixesBoundToUri("abc", null).size()); - - // and add another similar binding - nsMap.addMapping("ns2", "abc"); - assertEquals(2, nsMap.getPrefixesBoundToUri("abc", null).size()); - } -} diff -Nru libwoodstox-java-4.1.3/src/test/wstxtest/util/TestDataUtil.java libwoodstox-java-5.1.0/src/test/wstxtest/util/TestDataUtil.java --- libwoodstox-java-4.1.3/src/test/wstxtest/util/TestDataUtil.java 2012-04-24 04:38:22.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/wstxtest/util/TestDataUtil.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,101 +0,0 @@ -package wstxtest.util; - -import java.util.*; - -import junit.framework.TestCase; - -import com.ctc.wstx.util.DataUtil; - -/** - * Simple unit tests for testing methods in {@link DataUtil}. - */ -public class TestDataUtil - extends TestCase -{ - public void testBasic() - { - char[] empty = DataUtil.getEmptyCharArray(); - assertEquals(0, empty.length); - } - - public void testContainment() - { - // First, no match: - - Collection c1 = new HashSet(); - c1.add("foo"); - c1.add(new String("bar")); - Collection c2 = new ArrayList(); - c2.add("foobar"); - c2.add(new Integer(3)); - - assertFalse(DataUtil.anyValuesInCommon(c1, c2)); - - // Then a match - c1.add(new Integer(3)); - assertTrue(DataUtil.anyValuesInCommon(c1, c2)); - - // And another one: - c2.clear(); - c2.add("bar"); - assertTrue(DataUtil.anyValuesInCommon(c1, c2)); - } - - public void testExpansion() - { - final int MAGIC_INDEX = 1; - - final int MAGIC_INT = 732; - final String MAGIC_STRING = "yeehaw"; - - int[] ia = new int[6]; - // let's also add a marker to test - ia[MAGIC_INDEX] = MAGIC_INT; - int[] ia2 = (int[]) DataUtil.growArrayBy50Pct(ia); - assertEquals(9, ia2.length); - assertEquals(MAGIC_INT, ia2[MAGIC_INDEX]); - ia2 = (int[]) DataUtil.growArrayToAtLeast(ia, 7); - if (ia2.length < 7) { - fail("Expected array to grow to at least 7, was "+ia.length); - } - assertEquals(MAGIC_INT, ia2[MAGIC_INDEX]); - ia2 = DataUtil.growArrayBy(ia, 2); - assertEquals(8, ia2.length); - assertEquals(MAGIC_INT, ia2[MAGIC_INDEX]); - ia2 = DataUtil.growArrayBy((int[])null, 4); - assertEquals(4, ia2.length); - // no magic value, should just have 0 - assertEquals(0, ia2[MAGIC_INDEX]); - - String[] s1 = new String[10]; - s1[MAGIC_INDEX] = MAGIC_STRING; - String[] s2 = (String[]) DataUtil.growArrayBy50Pct(s1); - assertEquals(15, s2.length); - assertEquals(MAGIC_STRING, s2[MAGIC_INDEX]); - s2 = (String[]) DataUtil.growArrayToAtLeast(s1, 19); - if (s2.length < 19) { - fail("Expected array to grow to at least 19, was "+s2.length); - } - s2 = DataUtil.growArrayBy(s1, 3); - assertEquals(13, s2.length); - assertEquals(MAGIC_STRING, s2[MAGIC_INDEX]); - s2 = DataUtil.growArrayBy((String[])null, 3); - assertEquals(3, s2.length); - // nothing to copy from - assertNull(s2[MAGIC_INDEX]); - - // And then exceptions... - try { - s2 = (String[]) DataUtil.growArrayBy50Pct((String[])null); - fail("Expected an IllegalArgumentException when passing null"); - } catch (IllegalArgumentException ie) { - ; // good - } - try { - s2 = (String[]) DataUtil.growArrayToAtLeast((String[])null, 5); - fail("Expected an IllegalArgumentException when passing null"); - } catch (IllegalArgumentException ie) { - ; // good - } - } -} diff -Nru libwoodstox-java-4.1.3/src/test/wstxtest/util/TestStringUtil.java libwoodstox-java-5.1.0/src/test/wstxtest/util/TestStringUtil.java --- libwoodstox-java-4.1.3/src/test/wstxtest/util/TestStringUtil.java 2012-04-24 04:38:22.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/wstxtest/util/TestStringUtil.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,96 +0,0 @@ -package wstxtest.util; - -import java.util.*; - -import com.ctc.wstx.util.StringUtil; - -/** - * Simple unit tests for testing methods of {@link StringUtil} utility - * class. - */ -public class TestStringUtil - extends wstxtest.BaseWstxTest -{ - public void testConcatEntries() - { - List l = new ArrayList(); - l.add("first"); - l.add("second"); - l.add("third"); - assertEquals("first, second and third", - StringUtil.concatEntries(l, ", ", " and ")); - - l = new ArrayList(); - l.add("the only"); - assertEquals("the only", - StringUtil.concatEntries(l, ", ", " and ")); - } - - public void testIsAllWhitespace() - { - assertTrue(StringUtil.isAllWhitespace(" \r \r\n \t")); - assertTrue(StringUtil.isAllWhitespace(" ")); - assertTrue(StringUtil.isAllWhitespace(" ".toCharArray(), 0, 1)); - assertTrue(StringUtil.isAllWhitespace("\r\n\t")); - assertTrue(StringUtil.isAllWhitespace("\r\n\t".toCharArray(), 0, 3)); - assertTrue(StringUtil.isAllWhitespace("x \t".toCharArray(), 1, 2)); - assertTrue(StringUtil.isAllWhitespace("")); - assertTrue(StringUtil.isAllWhitespace(new char[0], 0, 0)); - - assertFalse(StringUtil.isAllWhitespace("x")); - assertFalse(StringUtil.isAllWhitespace(" !")); - } - - public void testNormalizeSpaces() - { - String str = " my my"; - assertEquals("my my", StringUtil.normalizeSpaces(str.toCharArray(), 0, - str.length())); - - str = "foo bar"; - assertEquals("foo bar", StringUtil.normalizeSpaces(str.toCharArray(), 0, - str.length())); - - str = "my_my"; - assertFalse("my my".equals(StringUtil.normalizeSpaces(str.toCharArray(), - 0, str.length()))); - - str = "Xoh no Z!"; - assertEquals("oh no", - StringUtil.normalizeSpaces(str.toCharArray(), 1, - str.length() - 3)); - - - /* Also, how about other white-space; not to be normalized fully, - * so in this case should get null (no normalization done) - */ - str = "some \t text"; - String result = StringUtil.normalizeSpaces(str.toCharArray(), 0, str.length()); - if (result != null) { - fail("Expected , not '"+quotedPrintable(result)+"' when normalizing '"+quotedPrintable(str)+"'"); - } - } - - public void testEqualEncodings() - { - assertTrue(StringUtil.equalEncodings("utf-8", "utf-8")); - assertTrue(StringUtil.equalEncodings("UTF-8", "utf-8")); - assertTrue(StringUtil.equalEncodings("UTF-8", "utf8")); - assertTrue(StringUtil.equalEncodings("UTF8", "utf_8")); - assertTrue(StringUtil.equalEncodings("US_ASCII", "us-ascii")); - assertTrue(StringUtil.equalEncodings("utf 8", "Utf-8")); - - assertFalse(StringUtil.equalEncodings("utf-8", "utf-16")); - assertFalse(StringUtil.equalEncodings("isolatin", "iso-8859-1")); - assertFalse(StringUtil.equalEncodings("utf8", "utf")); - } - - public void testMatches() - { - String STR = "fooBar!"; - String STR2 = "foobar_"; - assertTrue(StringUtil.matches(STR, STR.toCharArray(), 0, STR.length())); - assertFalse(StringUtil.matches(STR, STR.toCharArray(), 0, STR.length()-1)); - assertFalse(StringUtil.matches(STR, STR2.toCharArray(), 0, STR2.length())); - } -} diff -Nru libwoodstox-java-4.1.3/src/test/wstxtest/util/TestStringVector.java libwoodstox-java-5.1.0/src/test/wstxtest/util/TestStringVector.java --- libwoodstox-java-4.1.3/src/test/wstxtest/util/TestStringVector.java 2012-04-24 04:38:22.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/wstxtest/util/TestStringVector.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,37 +0,0 @@ -package wstxtest.util; - -import junit.framework.TestCase; - -import com.ctc.wstx.util.StringVector; - -/** - * Simple unit tests for testing {@link StringVector}. - */ -public class TestStringVector - extends TestCase -{ - public void testBasic() - { - StringVector sv = new StringVector(2); - - sv.addString("foo"); - sv.addString("xyz"); - assertEquals(2, sv.size()); - sv.addStrings("bar", "foo2"); - assertEquals(4, sv.size()); - sv.setString(3, "foo3"); - assertEquals(4, sv.size()); - assertEquals("foo3", sv.getString(3)); - - sv.addString(new String("foo")); // so as to be different from entry 0 - sv.addString(new String("bar")); - assertEquals("foo", sv.getString(4)); - // this uses identity - assertEquals("xyz", sv.findLastFromMap("foo")); - // and this equality - assertEquals("bar", sv.findLastNonInterned("foo")); - - sv.clear(true); - assertEquals(0, sv.size()); - } -} diff -Nru libwoodstox-java-4.1.3/src/test/wstxtest/util/TestTextAccumulator.java libwoodstox-java-5.1.0/src/test/wstxtest/util/TestTextAccumulator.java --- libwoodstox-java-4.1.3/src/test/wstxtest/util/TestTextAccumulator.java 2012-04-24 04:38:22.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/wstxtest/util/TestTextAccumulator.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,45 +0,0 @@ -package wstxtest.util; - -import junit.framework.TestCase; - -import com.ctc.wstx.util.TextAccumulator; - -/** - * Simple unit tests for testing {@link TextAccumulator}. That class - * is generally used to try to minimize shuffling between char arrays, - * Strings and StringBuilders -- most common case being that only one - * instance is passed, before a String is needed. - */ -public class TestTextAccumulator - extends TestCase -{ - public void testBasic() - { - TextAccumulator acc = new TextAccumulator(); - - acc.addText("foo"); - assertEquals("foo", acc.getAndClear()); - - acc.addText("foo".toCharArray(), 0, 3); - acc.addText("bar"); - assertEquals("foobar", acc.getAndClear()); - } - - // as per [WSTX-349] - public void testBasicWithCharArray() - { - TextAccumulator acc = new TextAccumulator(); - - acc.addText("foobar".toCharArray(), 3, 5); - assertEquals("ba", acc.getAndClear()); - - acc.addText("xxfoo".toCharArray(), 2, 5); - acc.addText("bar".toCharArray(), 2, 3); - acc.addText(new char[] { '1', '2', '3' }, 2, 3); - assertEquals("foor3", acc.getAndClear()); - - acc.addText("a"); - acc.addText(new char[] { '1', '2', '3' }, 2, 3); - assertEquals("a3", acc.getAndClear()); - } -} diff -Nru libwoodstox-java-4.1.3/src/test/wstxtest/util/TestTextBuffer.java libwoodstox-java-5.1.0/src/test/wstxtest/util/TestTextBuffer.java --- libwoodstox-java-4.1.3/src/test/wstxtest/util/TestTextBuffer.java 2012-04-24 04:38:22.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/wstxtest/util/TestTextBuffer.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,44 +0,0 @@ -package wstxtest.util; - -import junit.framework.TestCase; - -import com.ctc.wstx.util.TextBuffer; - -/** - * Simple unit tests for testing {@link TextBuffer}. - */ -public class TestTextBuffer - extends TestCase -{ - public void testBasic() - { - String INPUT = "Whatever input text doesn't really matter but should have some content " - +"so as not to be too short"; - TextBuffer tb = TextBuffer.createTemporaryBuffer(); - final char[] ch = new char[1]; - for (int i = 0, len = INPUT.length(); i < len; ++i) { - if ((i & 1) != 0) { - ch[0] = INPUT.charAt(i); - tb.append(ch, 0, 1); - } else { - tb.append(INPUT.substring(i, i+1)); - } - } - - assertEquals(INPUT, tb.toString()); - assertEquals(INPUT, tb.contentsAsString()); - assertFalse(tb.endsWith("shor")); - assertTrue(tb.endsWith("so as not to be too short")); - assertFalse(tb.isAllWhitespace()); - - assertTrue(tb.equalsString(INPUT)); - - /* - tb.clear(); - - assertEquals("", tb.toString()); - assertEquals("", tb.contentsAsString()); - */ - } -} - diff -Nru libwoodstox-java-4.1.3/src/test/wstxtest/util/TestWordResolver.java libwoodstox-java-5.1.0/src/test/wstxtest/util/TestWordResolver.java --- libwoodstox-java-4.1.3/src/test/wstxtest/util/TestWordResolver.java 2012-04-24 04:38:22.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/wstxtest/util/TestWordResolver.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,106 +0,0 @@ -package wstxtest.util; - -import java.util.*; - -import junit.framework.TestCase; - -import com.ctc.wstx.util.WordResolver; - -/** - * Simple unit tests for testing {@link WordResolver}. - */ -public class TestWordResolver - extends TestCase -{ - public void testNormal() - { - checkResolver(new String[] { - "word", "123", "len", "length", - "leno", "1", "foobar", - }, new String[] { - "foo", "21", "__", "12", "lengt", - }); - } - - /** - * This unit test was created as a regression test, to check for - * a bug that was found during development. - */ - public void testSingle() - { - // this caused an arrayindexoutofbounds exception - checkResolver(new String[] { "CDATA" }, - new String[] { "value", "aaa", "ZZZ", "CDAT" }); - - checkResolver(new String[] { "somethingelse" }, - new String[] { "value", "aaa", "ZZZ", "CDAT" }); - } - - /** - * This unit test tries to verify that things work ok with even bigger - * word sets - */ - public void testLarge() - { - // this caused an arrayindexoutofbounds exception - checkResolver(new String[] { - "a", "a1", "a2", "a4", "a5", "a6", "ab", "az", "a9", "aa", "ax", - "c", "ca", "caa", "caaa", "caad", "caaa", - }, new String[] { - "a3", "aA", "a0", "b" - }); - } - - /* - /////////////////////////////////////////////////////// - // Private methods: - /////////////////////////////////////////////////////// - */ - - private void checkResolver(String[] words, String[] missingWords) - { - TreeSet set = new TreeSet(); - for (int i = 0, len = words.length; i < len; ++i) { - set.add(words[i]); - } - - WordResolver wr = WordResolver.constructInstance(set); - - assertEquals(wr.size(), set.size()); - - Iterator it = set.iterator(); - - // Let's first check if words that should be there, are: - while (it.hasNext()) { - String str = (String) it.next(); - - assertEquals(str, wr.find(str)); - // And then, let's make sure intern()ing isn't needed: - assertEquals(str, wr.find(""+str)); - - char[] strArr = str.toCharArray(); - char[] strArr2 = new char[strArr.length + 4]; - System.arraycopy(strArr, 0, strArr2, 3, strArr.length); - assertEquals(str, wr.find(strArr, 0, str.length())); - assertEquals(str, wr.find(strArr2, 3, str.length() + 3)); - } - - // And then that ones shouldn't be there aren't: - for (int i = 0, len = missingWords.length; i < len; ++i) { - checkNotFind(wr, missingWords[i]); - } - } - - private void checkNotFind(WordResolver wr, String str) - { - char[] strArr = str.toCharArray(); - char[] strArr2 = new char[strArr.length + 4]; - System.arraycopy(strArr, 0, strArr2, 1, strArr.length); - - assertNull(wr.find(str)); - assertNull(wr.find(strArr, 0, strArr.length)); - assertNull(wr.find(strArr2, 1, strArr.length + 1)); - } - -} - diff -Nru libwoodstox-java-4.1.3/src/test/wstxtest/util/TestWordSet.java libwoodstox-java-5.1.0/src/test/wstxtest/util/TestWordSet.java --- libwoodstox-java-4.1.3/src/test/wstxtest/util/TestWordSet.java 2012-04-24 04:38:22.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/wstxtest/util/TestWordSet.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,71 +0,0 @@ -package wstxtest.util; - -import java.util.*; - -import junit.framework.TestCase; - -import com.ctc.wstx.util.WordSet; - -/** - * Simple unit tests for testing {@link WordSet}. - */ -public class TestWordSet - extends TestCase -{ - public TestWordSet(String name) { - super(name); - } - - public void testNormal() - { - TreeSet set = new TreeSet(); - - set.add("word"); - set.add("123"); - set.add("len"); - set.add("length"); - set.add("leno"); - set.add("1"); - set.add("foobar"); - - WordSet ws = WordSet.constructSet(set); - Iterator it = set.iterator(); - - // Let's first check if words that should be there, are: - while (it.hasNext()) { - String str = (String) it.next(); - - assertTrue(ws.contains(str)); - // And then, let's make sure intern()ing isn't needed: - assertTrue(ws.contains(""+str)); - - char[] strArr = str.toCharArray(); - char[] strArr2 = new char[strArr.length + 4]; - System.arraycopy(strArr, 0, strArr2, 3, strArr.length); - assertTrue(ws.contains(strArr, 0, str.length())); - assertTrue(ws.contains(strArr2, 3, str.length() + 3)); - } - - // And then that ones shouldn't be there aren't: - checkNotFind(ws, "foo"); - - } - - /* - /////////////////////////////////////////////////////// - // Private methods: - /////////////////////////////////////////////////////// - */ - - private void checkNotFind(WordSet ws, String str) - { - char[] strArr = str.toCharArray(); - char[] strArr2 = new char[strArr.length + 4]; - System.arraycopy(strArr, 0, strArr2, 1, strArr.length); - - assertFalse(ws.contains(str)); - assertFalse(ws.contains(strArr, 0, strArr.length)); - assertFalse(ws.contains(strArr2, 1, strArr.length + 1)); - } -} - diff -Nru libwoodstox-java-4.1.3/src/test/wstxtest/util/TestXmlChars.java libwoodstox-java-5.1.0/src/test/wstxtest/util/TestXmlChars.java --- libwoodstox-java-4.1.3/src/test/wstxtest/util/TestXmlChars.java 2012-04-24 04:38:22.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/wstxtest/util/TestXmlChars.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,73 +0,0 @@ -package wstxtest.util; - -import junit.framework.TestCase; - -import com.ctc.wstx.io.WstxInputData; - -/** - * Simple unit tests for testing methods in {@link com.ctc.wstx.util.XmlChars} - * and {@link com.ctc.wstx.io.WstxInputData} - */ -public class TestXmlChars - extends TestCase -{ - public void testXml10Chars() - { - // First, 8-bit range: - assertTrue(WstxInputData.isNameStartChar('F', true, false)); - assertTrue(WstxInputData.isNameChar('F', true, false)); - assertTrue(WstxInputData.isNameStartChar('_', true, false)); - assertTrue(WstxInputData.isNameChar('_', true, false)); - assertTrue(WstxInputData.isNameChar('x', true, false)); - assertFalse(WstxInputData.isNameStartChar('-', true, false)); - assertTrue(WstxInputData.isNameChar('-', true, false)); - assertFalse(WstxInputData.isNameStartChar('.', true, false)); - assertTrue(WstxInputData.isNameChar('.', true, false)); - - // Then more exotic chars: - - assertTrue(WstxInputData.isNameStartChar((char) 0x03ce, true, false)); - assertTrue(WstxInputData.isNameChar((char) 0x03ce, true, false)); - assertTrue(WstxInputData.isNameStartChar((char) 0x0e21, true, false)); - assertTrue(WstxInputData.isNameChar((char) 0x0e21, true, false)); - assertTrue(WstxInputData.isNameStartChar((char) 0x3007, true, false)); - assertFalse(WstxInputData.isNameStartChar(' ', true, false)); - /* colon is NOT a start char for this method; although it is - * in xml specs -- reason has to do with namespace handling - */ - assertFalse(WstxInputData.isNameStartChar(':', true, false)); - - assertFalse(WstxInputData.isNameStartChar((char) 0x3008, true, false)); - assertFalse(WstxInputData.isNameChar((char) 0x3008, true, false)); - assertTrue(WstxInputData.isNameStartChar((char) 0x30ea, true, false)); - assertTrue(WstxInputData.isNameChar((char) 0x30ea, true, false)); - } - - public void testXml11NameStartChars() - { - // First, 8-bit range: - assertTrue(WstxInputData.isNameStartChar('F', true, true)); - assertTrue(WstxInputData.isNameChar('F', true, true)); - assertTrue(WstxInputData.isNameStartChar('_', true, true)); - assertTrue(WstxInputData.isNameChar('_', true, true)); - assertTrue(WstxInputData.isNameChar('x', true, true)); - assertFalse(WstxInputData.isNameStartChar('-', true, true)); - assertTrue(WstxInputData.isNameChar('-', true, true)); - assertFalse(WstxInputData.isNameStartChar('.', true, true)); - assertTrue(WstxInputData.isNameChar('.', true, true)); - - // Then more exotic chars: - - assertTrue(WstxInputData.isNameStartChar((char) 0x03ce, true, true)); - assertTrue(WstxInputData.isNameChar((char) 0x03ce, true, true)); - assertTrue(WstxInputData.isNameStartChar((char) 0x0e21, true, true)); - assertTrue(WstxInputData.isNameChar((char) 0x0e21, true, true)); - assertTrue(WstxInputData.isNameStartChar((char) 0x3007, true, true)); - assertFalse(WstxInputData.isNameStartChar(' ', true, true)); - /* colon is NOT a start char for this method; although it is - * in xml specs -- reason has to do with namespace handling - */ - assertFalse(WstxInputData.isNameStartChar(':', true, true)); - assertFalse(WstxInputData.isNameStartChar((char) 0x3000, true, true)); - } -} diff -Nru libwoodstox-java-4.1.3/src/test/wstxtest/vstream/BaseValidationTest.java libwoodstox-java-5.1.0/src/test/wstxtest/vstream/BaseValidationTest.java --- libwoodstox-java-4.1.3/src/test/wstxtest/vstream/BaseValidationTest.java 2012-04-24 04:38:22.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/wstxtest/vstream/BaseValidationTest.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,82 +0,0 @@ -package wstxtest.vstream; - -import java.io.StringReader; -import java.net.URL; - -import javax.xml.stream.XMLStreamException; - -import org.codehaus.stax2.XMLStreamReader2; -import org.codehaus.stax2.validation.*; - -public abstract class BaseValidationTest - extends wstxtest.stream.BaseStreamTest -{ - protected XMLValidationSchema parseSchema(String contents, String schemaType) - throws XMLStreamException - { - XMLValidationSchemaFactory schF = XMLValidationSchemaFactory.newInstance(schemaType); - return schF.createSchema(new StringReader(contents)); - } - - protected XMLValidationSchema parseSchema(URL ref, String schemaType) - throws XMLStreamException - { - XMLValidationSchemaFactory schF = XMLValidationSchemaFactory.newInstance(schemaType); - return schF.createSchema(ref); - } - - protected XMLValidationSchema parseRngSchema(String contents) - throws XMLStreamException - { - return parseSchema(contents, XMLValidationSchema.SCHEMA_ID_RELAXNG); - } - - protected XMLValidationSchema parseDTDSchema(String contents) - throws XMLStreamException - { - return parseSchema(contents, XMLValidationSchema.SCHEMA_ID_DTD); - } - - protected XMLValidationSchema parseW3CSchema(String contents) - throws XMLStreamException - { - return parseSchema(contents, XMLValidationSchema.SCHEMA_ID_W3C_SCHEMA); - } - - protected void verifyFailure(String xml, XMLValidationSchema schema, String failMsg, - String failPhrase) throws XMLStreamException - { - // default to strict handling: - verifyFailure(xml, schema, failMsg, failPhrase, true); - } - - protected void verifyFailure(String xml, XMLValidationSchema schema, String failMsg, - String failPhrase, boolean strict) throws XMLStreamException - { - XMLStreamReader2 sr = constructStreamReader(getInputFactory(), xml); - sr.validateAgainst(schema); - try { - while (sr.hasNext()) { - /* int type = */sr.next(); - } - fail("Expected validity exception for " + failMsg); - } catch (XMLValidationException vex) { - String origMsg = vex.getMessage(); - String msg = (origMsg == null) ? "" : origMsg.toLowerCase(); - if (msg.indexOf(failPhrase.toLowerCase()) < 0) { - String actualMsg = "Expected validation exception for " - + failMsg + ", containing phrase '" + failPhrase - + "': got '" + origMsg + "'"; - if (strict) { - fail(actualMsg); - } - warn("suppressing failure due to MSV bug, failure: '" - + actualMsg + "'"); - } - // should get this specific type; not basic stream exception - } catch (XMLStreamException sex) { - fail("Expected XMLValidationException for " + failMsg - + "; instead got " + sex.getMessage()); - } - } -} diff -Nru libwoodstox-java-4.1.3/src/test/wstxtest/vstream/TestDTD.java libwoodstox-java-5.1.0/src/test/wstxtest/vstream/TestDTD.java --- libwoodstox-java-4.1.3/src/test/wstxtest/vstream/TestDTD.java 2012-04-24 04:38:22.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/wstxtest/vstream/TestDTD.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,151 +0,0 @@ -package wstxtest.vstream; - -import java.io.*; -import java.net.*; - -import javax.xml.stream.*; - -import org.codehaus.stax2.XMLStreamReader2; -import org.codehaus.stax2.validation.*; - -/** - * This test suite should really be part of wstx-tools package, but since - * there is some supporting code within core Woodstox, it was added here. - * That way it is easier to check that no DTDFlatten functionality is - * broken by low-level changes. - */ -public class TestDTD - extends BaseValidationTest -{ - final static class MyReporter implements XMLReporter - { - public int count = 0; - - public void report(String message, String errorType, Object relatedInformation, Location location) - { - ++count; - } - } - - final static String SIMPLE_DTD = - "\n" - +"\n" - +"\n" - ; - - /** - * Test to show how [WSTX-190] occurs. - */ - public void testMissingAttrWithReporter() - throws XMLStreamException - { - String XML = "\n" - +"]>"; - MyReporter rep = new MyReporter(); - XMLStreamReader sr = getValidatingReader(XML, rep); - assertTokenType(DTD, sr.next()); - // and now should get a validation problem - assertTokenType(START_ELEMENT, sr.next()); - assertTokenType(END_ELEMENT, sr.next()); - sr.close(); - assertEquals(1, rep.count); - } - - public void testFullValidationOk() - throws XMLStreamException - { - String XML = ""; - XMLValidationSchema schema = parseDTDSchema(SIMPLE_DTD); - XMLStreamReader2 sr = getReader(XML); - sr.validateAgainst(schema); - while (sr.next() != END_DOCUMENT) { } - sr.close(); - } - - /** - * And then a test for validating starting when stream points - * to START_ELEMENT - */ - public void testPartialValidationOk() - throws XMLStreamException - { - String XML = ""; - XMLValidationSchema schema = parseDTDSchema(SIMPLE_DTD); - XMLStreamReader2 sr = getReader(XML); - assertTokenType(START_ELEMENT, sr.next()); - sr.validateAgainst(schema); - while (sr.next() != END_DOCUMENT) { } - sr.close(); - } - - /* - * Another test for checking that validation does end when - * sub-tree ends... - */ - /* 29-Apr-2009, TSa: Actually: not a valid test; as per - * Stax2 v3.0 javadocs, validation does NOT end with - * sub-tree... - */ - /* - public void testPartialValidationFollowedBy() - throws XMLStreamException - { - String XML = ""; - XMLValidationSchema schema = parseDTDSchema(SIMPLE_DTD); - XMLStreamReader2 sr = getReader(XML); - assertTokenType(START_ELEMENT, sr.next()); - assertEquals("x", sr.getLocalName()); - assertTokenType(START_ELEMENT, sr.next()); - assertEquals("root", sr.getLocalName()); - sr.validateAgainst(schema); - while (sr.next() != END_DOCUMENT) { } - sr.close(); - } - */ - - /** - * Test to verify [WSTX-207] - */ - public void testSchemaWithFunnyFilename() - throws Exception - { - // assuming CWD is the svn root - File f = new File("").getAbsoluteFile(); - f = new File(f, "src"); - f = new File(f, "test"); - f = new File(f, "wstxtest"); - f = new File(f, "empty and spaces.dtd"); - - URL url = f.toURI().toURL(); - - XMLValidationSchema sch = parseSchema(url, XMLValidationSchema.SCHEMA_ID_DTD); - assertNotNull(sch); - } - - /* - ////////////////////////////////////////////////////// - // Helper methods - ////////////////////////////////////////////////////// - */ - - private XMLStreamReader2 getReader(String contents) - throws XMLStreamException - { - XMLInputFactory f = getInputFactory(); - setValidating(f, false); - return constructStreamReader(f, contents); - } - - private XMLStreamReader getValidatingReader(String contents, XMLReporter rep) - throws XMLStreamException - { - XMLInputFactory f = getInputFactory(); - if (rep != null) { - f.setProperty(XMLInputFactory.REPORTER, rep); - } - setSupportDTD(f, true); - setValidating(f, true); - return constructStreamReader(f, contents); - } -} diff -Nru libwoodstox-java-4.1.3/src/test/wstxtest/vstream/TestFlattening.java libwoodstox-java-5.1.0/src/test/wstxtest/vstream/TestFlattening.java --- libwoodstox-java-4.1.3/src/test/wstxtest/vstream/TestFlattening.java 2012-04-24 04:38:22.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/wstxtest/vstream/TestFlattening.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,81 +0,0 @@ -package wstxtest.vstream; - -import java.io.*; - -import javax.xml.stream.*; - -import com.ctc.wstx.api.ReaderConfig; -import com.ctc.wstx.cfg.XmlConsts; -import com.ctc.wstx.dtd.DTDSubset; -import com.ctc.wstx.dtd.FullDTDReader; -import com.ctc.wstx.io.DefaultInputResolver; -import com.ctc.wstx.io.WstxInputSource; - -import wstxtest.stream.BaseStreamTest; - -/** - * This test suite should really be part of wstx-tools package, but since - * there is some supporting code within core Woodstox, it was added here. - * That way it is easier to check that no DTDFlatten functionality is - * broken by low-level changes. - */ -public class TestFlattening - extends BaseStreamTest -{ - public void testFlatteningInclusive() - throws IOException, XMLStreamException - { - /* Note: since we deal with this as an external resource, it may - * need encoding pseudo-attribute if there's xml declaration - */ - final String DTD = - "\n" - +"\n" - +"\n" - +"\n" - +"'>\n" - +"\n" - +"\n" - +"\n" - +"]]>\n" - +"\n" - +"%pe;\n" - +"\n" - +"\r\n" - ; - //StringReader strr = new StringReader(DTD); - ReaderConfig cfg = ReaderConfig.createFullDefaults(); - for (int i = 0; i < 8; ++i) { - boolean inclComments = (i & 4) != 0; - boolean inclConditionals = (i & 2) != 0; - boolean inclPEs = (i & 1) != 0; - WstxInputSource input = DefaultInputResolver.sourceFromString - (null, cfg, "[dtd]", /*xml version for compat checks*/ XmlConsts.XML_V_UNKNOWN, DTD); - StringWriter strw = new StringWriter(); - /*DTDSubset ss =*/ FullDTDReader.flattenExternalSubset - (input, strw, - inclComments, inclConditionals, inclPEs); - strw.flush(); - String output = strw.toString(); - - /* Ok, so... how do we test it? For now, let's actually - * just re-parse it to ensure it seems valid? And let's also - * compare second-time output. - */ - input = DefaultInputResolver.sourceFromString - (null, cfg, "[dtd]", /*xml version for compatibility checks*/ XmlConsts.XML_V_UNKNOWN, output); - - strw = new StringWriter(); - DTDSubset ss = FullDTDReader.flattenExternalSubset - (input, strw, inclComments, inclConditionals, inclPEs); - assertNotNull(ss); - strw.flush(); - String output2 = strw.toString(); - - assertEquals(output, output2); - } - } -} - diff -Nru libwoodstox-java-4.1.3/src/test/wstxtest/vstream/TestRelaxNG.java libwoodstox-java-5.1.0/src/test/wstxtest/vstream/TestRelaxNG.java --- libwoodstox-java-4.1.3/src/test/wstxtest/vstream/TestRelaxNG.java 2012-04-24 04:38:22.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/wstxtest/vstream/TestRelaxNG.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,591 +0,0 @@ -package wstxtest.vstream; - -import javax.xml.stream.*; - -import org.codehaus.stax2.*; -import org.codehaus.stax2.validation.*; - -/** - * This is a simple base-line "smoke test" that checks that RelaxNG - * validation works at least minimally. - */ -public class TestRelaxNG - extends BaseValidationTest -{ - final static String SIMPLE_RNG_SCHEMA = - "\n" - +" \n" - +" \n" - +" \n" - +" \n" - +" \n" - +" \n" - +" \n" - +" \n" - +" \n" - +" \n" - +" \n" - +" \n" - +"" - ; - - /** - * Similar schema, but one that uses namespaces - */ - final static String SIMPLE_RNG_NS_SCHEMA = - "\n" - +" \n" - +" \n" - +" \n" - +" \n" - +" \n" - +" \n" - +" \n" - +" \n" - +" \n" - +" \n" - +" \n" - +"" - ; - - /** - * Test validation against a simple document valid according - * to a simple RNG schema. - */ - public void testSimpleNonNs() - throws XMLStreamException - { - String XML = - "" - +"\n" - +" \n" - +" foobar\n" - +" Foo Bar\n" - +" " - +" \n" - +" fuzzy\n" - +" adjective\n" - +" " - +"" - ; - - XMLValidationSchema schema = parseRngSchema(SIMPLE_RNG_SCHEMA); - XMLStreamReader2 sr = getReader(XML); - sr.validateAgainst(schema); - - try { - assertTokenType(START_ELEMENT, sr.next()); - assertEquals("dict", sr.getLocalName()); - - while (sr.hasNext()) { - sr.next(); - } - } catch (XMLValidationException vex) { - fail("Did not expect validation exception, got: "+vex); - } - - assertTokenType(END_DOCUMENT, sr.getEventType()); - } - - /** - * This unit test checks for couple of simple validity problems - * against the simple rng schema. It does not use namespaces - * (a separate test is needed for ns handling). - */ - public void testInvalidNonNs() - throws XMLStreamException - { - XMLValidationSchema schema = parseRngSchema(SIMPLE_RNG_SCHEMA); - - // First, wrong root element: - String XML = "\n" - +" foobar\n" - +" Foo Bar\n" - +""; - verifyRngFailure(XML, schema, "wrong root element", - "is not allowed. Possible tag names are"); - - // Then, wrong child ordering: - XML = "\n" - +"\n" - +" Foo Bar\n" - +" foobar\n" - +""; - verifyRngFailure(XML, schema, "illegal child element ordering", - "tag name \"description\" is not allowed. Possible tag names are"); - - // Then, missing children: - XML = "\n" - +"\n" - +""; - verifyRngFailure(XML, schema, "missing children", - "uncompleted content model. expecting: "); - - XML = "\n" - +"\n" - +"word" - +""; - verifyRngFailure(XML, schema, "incomplete children", - "uncompleted content model. expecting: "); - - // Then illegal text in non-mixed element - XML = "\n" - +"No text allowed here" - +" foobar\n" - +" Foo Bar\n" - +""; - verifyRngFailure(XML, schema, "invalid non-whitespace text", - "Element has non-mixed content specification; can not contain non-white space text"); - - // missing attribute - XML = "\n" - +"" - +" foobar\n" - +" Foo Bar\n" - +""; - // Then undeclared attributes - XML = "\n" - +"" - +" foobar\n" - +" Foo Bar\n" - +""; - verifyRngFailure(XML, schema, "undeclared attribute", - "unexpected attribute \"attr\""); - XML = "\n" - +"" - +" foobar\n" - +" Foo Bar\n" - +""; - verifyRngFailure(XML, schema, "undeclared attribute", - "unexpected attribute \"type\""); - } - - public void testSimpleNs() - throws XMLStreamException - { - String XML = "\n" - +" \n" - +" \n" - +"" - ; - - XMLValidationSchema schema = parseRngSchema(SIMPLE_RNG_NS_SCHEMA); - XMLStreamReader2 sr = getReader(XML); - sr.validateAgainst(schema); - - try { - assertTokenType(START_ELEMENT, sr.next()); - assertEquals("root", sr.getLocalName()); - - while (sr.hasNext()) { - sr.next(); - } - } catch (XMLValidationException vex) { - fail("Did not expect validation exception, got: "+vex); - } - - assertTokenType(END_DOCUMENT, sr.getEventType()); - } - - /** - * Unit test checks that the namespace matching works as - * expected. - */ - public void testInvalidNs() - throws XMLStreamException - { - XMLValidationSchema schema = parseRngSchema(SIMPLE_RNG_NS_SCHEMA); - - // First, wrong root element: - String XML = "\n" - +"\n" - +""; - verifyRngFailure(XML, schema, "wrong root element", - "namespace URI of tag \"root\" is wrong"); - - // Wrong child namespace - XML = "\n" - +"\n" - +""; - verifyRngFailure(XML, schema, "wrong child element namespace", - "namespace URI of tag \"leaf\" is wrong."); - - // Wrong attribute namespace - XML = "\n" - +"\n" - +""; - verifyRngFailure(XML, schema, "wrong attribute namespace", - "unexpected attribute \"attr1\""); - } - - /** - * This unit test verifies that the validation can be stopped - * half-way through processing, so that sub-trees (for example) - * can be validated. In this case, we will verify this functionality - * by trying to validate invalid document up to the point where it - * is (or may) still be valid, stop validation, and then continue - * reading. This should not result in an exception. - */ - public void testSimplePartialNonNs() - throws XMLStreamException - { - String XML = - "" - +"" - +"" - +"" - +"" - ; - - XMLValidationSchema schema = parseRngSchema(SIMPLE_RNG_SCHEMA); - - XMLStreamReader2 sr = getReader(XML); - XMLValidator vtor = sr.validateAgainst(schema); - - assertTokenType(START_ELEMENT, sr.next()); - assertEquals("dict", sr.getLocalName()); - assertTokenType(START_ELEMENT, sr.next()); - assertEquals("term", sr.getLocalName()); - - /* So far so good; but here we'd get an exception... so - * let's stop validating - */ - assertSame(vtor, sr.stopValidatingAgainst(schema)); - try { - // And should be good to go - assertTokenType(START_ELEMENT, sr.next()); - assertEquals("invalid", sr.getLocalName()); - assertTokenType(END_ELEMENT, sr.next()); - assertEquals("invalid", sr.getLocalName()); - assertTokenType(END_ELEMENT, sr.next()); - assertEquals("term", sr.getLocalName()); - assertTokenType(END_ELEMENT, sr.next()); - assertEquals("dict", sr.getLocalName()); - assertTokenType(END_DOCUMENT, sr.next()); - } catch (XMLValidationException vex) { - fail("Did not expect validation exception after stopping validation, got: "+vex); - } - sr.close(); - - // And let's do the same, just using the other stopValidatingAgainst method - sr = getReader(XML); - vtor = sr.validateAgainst(schema); - - assertTokenType(START_ELEMENT, sr.next()); - assertEquals("dict", sr.getLocalName()); - assertTokenType(START_ELEMENT, sr.next()); - assertEquals("term", sr.getLocalName()); - - assertSame(vtor, sr.stopValidatingAgainst(vtor)); - try { - // And should be good to go - assertTokenType(START_ELEMENT, sr.next()); - assertEquals("invalid", sr.getLocalName()); - assertTokenType(END_ELEMENT, sr.next()); - assertEquals("invalid", sr.getLocalName()); - assertTokenType(END_ELEMENT, sr.next()); - assertEquals("term", sr.getLocalName()); - assertTokenType(END_ELEMENT, sr.next()); - assertEquals("dict", sr.getLocalName()); - assertTokenType(END_DOCUMENT, sr.next()); - } catch (XMLValidationException vex) { - fail("Did not expect validation exception after stopping validation, got: "+vex); - } - sr.close(); - } - - public void testSimpleEnumAttr() - throws XMLStreamException - { - final String schemaDef = - "\n" - +" \n" - +" \n" - +" value1\n" - +" another\n" - +" 42\n" - +" \n" - +" \n" - +"" - ; - XMLValidationSchema schema = parseRngSchema(schemaDef); - - // First, simple valid document - String XML = ""; - XMLStreamReader2 sr = getReader(XML); - sr.validateAgainst(schema); - while (sr.next() != END_DOCUMENT) { } - sr.close(); - - // And then invalid one, with unrecognized value - XML = ""; - verifyRngFailure(XML, schema, "enum attribute with unknown value", - "attribute \"enumAttr\" has a bad value"); - } - - /** - * Test case for testing handling ID/IDREF/IDREF attributes, using - * schema datatype library. - */ - public void testSimpleIdAttrs() - throws XMLStreamException - { - final String schemaDef = - "\n" - +" \n" - +" \n" - +" \n" - +" \n" - +" \n" - +" \n" - +" \n" - +" \n" - +" \n" - +" \n" - +" \n" - +"" - ; - - XMLValidationSchema schema = parseRngSchema(schemaDef); - - // First, a simple valid document - String XML = "" - +" \n" - +" \n" - +" \n" - +"" - ; - XMLStreamReader2 sr = getReader(XML); - sr.validateAgainst(schema); - while (sr.next() != END_DOCUMENT) { } - sr.close(); - - // Then one with malformed id - XML = ""; - verifyRngFailure(XML, schema, "malformed id", - "attribute \"id\" has a bad value"); - - // Then with malformed IDREF value (would be valid IDREFS) - XML = "" - +" \n" - +" \n" - +"" - ; - verifyRngFailure(XML, schema, "malformed id", - "attribute \"ref\" has a bad value"); - - // And then invalid one, with dangling ref - XML = "" - +" \n" - +"" - ; - verifyRngFailure(XML, schema, "reference to undefined id", - "Undefined ID"); - - // and another one with some of refs undefined - XML = "" - +" \n" - +"" - ; - verifyRngFailure(XML, schema, "reference to undefined id", - "Undefined ID"); - } - - public void testSimpleIntAttr() - throws XMLStreamException - { - final String schemaDef = - "\n" - +" \n" - +" \n" - +" \n" - +"" - ; - - XMLValidationSchema schema = parseRngSchema(schemaDef); - - // First, a simple valid document - XMLStreamReader2 sr = getReader(""); - sr.validateAgainst(schema); - while (sr.next() != END_DOCUMENT) { } - sr.close(); - - // Then one with invalid element value - verifyRngFailure("", - schema, "invalid integer attribute value", - "does not satisfy the \"integer\" type"); - // And missing attribute - verifyRngFailure("", - schema, "missing integer attribute value", - "is missing \"nr\" attribute"); - - // And then two variations of having empty value - verifyRngFailure("", - schema, "missing integer attribute value", - "does not satisfy the \"integer\" type"); - verifyRngFailure("", - schema, "missing integer attribute value", - "does not satisfy the \"integer\" type"); - } - - // 21-Apr-2012, tatu: Fails but can't be fixed for 4.1; hence comment out - /* - public void testSimpleBooleanElem() - throws XMLStreamException - { - final String schemaDef = - "\n" - +" \n" - +" \n" - +" \n" - +"" - ; - - XMLValidationSchema schema = parseRngSchema(schemaDef); - - // First, a simple valid document - XMLStreamReader2 sr = getReader("true"); - sr.validateAgainst(schema); - while (sr.next() != END_DOCUMENT) { } - sr.close(); - - // Then one with invalid element value - verifyRngFailure("foobar", - schema, "invalid boolean element value", - "does not satisfy the \"boolean\" type"); - - // And one with empty value - // 12-Nov-2008, TSa: still having MSV bug here, need to suppress failure - verifyRngFailure(" ", - schema, "missing boolean element value", - "does not satisfy the \"boolean\" type", true); - - // And then 2 variations of completely missing value - // 12-Nov-2008, TSa: still having MSV bug here, need to suppress failure - verifyRngFailure("", - schema, "missing boolean element value", - "does not satisfy the \"boolean\" type", true); - - // 12-Nov-2008, TSa: still having MSV bug here, need to suppress failure - verifyRngFailure("", - schema, "missing boolean element value", - "does not satisfy the \"boolean\" type", true); - } - */ - - /** - * Another test, but one that verifies that empty tags do not - * cause problems with validation - */ - public void testSimpleBooleanElem2() - throws XMLStreamException - { - final String schemaDef = - "\n" - +" \n" - +" \n" - +" \n" - +" \n" - +"" - ; - - XMLValidationSchema schema = parseRngSchema(schemaDef); - - // First, a simple valid document - XMLStreamReader2 sr = getReader("abctrue"); - sr.validateAgainst(schema); - while (sr.next() != END_DOCUMENT) { } - sr.close(); - - // Then another valid, but with empty tag for leaf1 - sr = getReader("false"); - sr.validateAgainst(schema); - while (sr.next() != END_DOCUMENT) { } - sr.close(); - - // And then one more invalid case - verifyRngFailure("true false", - schema, "missing boolean element value", - "does not satisfy the \"boolean\" type"); - } - - /** - * And then a test for validating starting when stream points - * to START_ELEMENT - */ - public void testPartialValidationOk() - throws XMLStreamException - { - /* Hmmh... RelaxNG does define expected root. So need to - * wrap the doc... - */ - String XML = - "\n" - +"\n" - +"\n" - +" foobar\n" - +" Foo Bar\n" - +"\n" - +"" - ; - XMLValidationSchema schema = parseRngSchema(SIMPLE_RNG_SCHEMA); - XMLStreamReader2 sr = getReader(XML); - assertTokenType(START_ELEMENT, sr.next()); - sr.validateAgainst(schema); - while (sr.next() != END_DOCUMENT) { } - sr.close(); - } - - - /* - ////////////////////////////////////////////////////////////// - // Helper methods - ////////////////////////////////////////////////////////////// - */ - - XMLStreamReader2 getReader(String contents) - throws XMLStreamException - { - XMLInputFactory2 f = getInputFactory(); - setValidating(f, false); - return constructStreamReader(f, contents); - } - - void verifyRngFailure(String xml, XMLValidationSchema schema, String failMsg, String failPhrase) - throws XMLStreamException - { - // By default, yes we are strict... - verifyRngFailure(xml, schema, failMsg, failPhrase, true); - } - - void verifyRngFailure(String xml, XMLValidationSchema schema, String failMsg, String failPhrase, - boolean strict) - throws XMLStreamException - { - XMLStreamReader2 sr = getReader(xml); - sr.validateAgainst(schema); - try { - while (sr.hasNext()) { - /*int type =*/ sr.next(); - } - fail("Expected validity exception for "+failMsg); - } catch (XMLValidationException vex) { - String origMsg = vex.getMessage(); - String msg = (origMsg == null) ? "" : origMsg.toLowerCase(); - if (msg.indexOf(failPhrase.toLowerCase()) < 0) { - String actualMsg = "Expected validation exception for "+failMsg+", containing phrase '"+failPhrase+"': got '"+origMsg+"'"; - if (strict) { - fail(actualMsg); - } - warn("suppressing failure due to MSV bug, failure: '"+actualMsg+"'"); - } - // should get this specific type; not basic stream exception - } catch (XMLStreamException sex) { - fail("Expected XMLValidationException for "+failMsg); - } - } -} diff -Nru libwoodstox-java-4.1.3/src/test/wstxtest/vstream/TestXmlId.java libwoodstox-java-5.1.0/src/test/wstxtest/vstream/TestXmlId.java --- libwoodstox-java-4.1.3/src/test/wstxtest/vstream/TestXmlId.java 2012-04-24 04:38:22.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/wstxtest/vstream/TestXmlId.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,60 +0,0 @@ -package wstxtest.vstream; - -import javax.xml.stream.*; - -import wstxtest.stream.BaseStreamTest; - -public class TestXmlId - extends BaseStreamTest -{ - /** - * This is a simple regression test -- at one point, last character - * of id attributes was dropped. - */ - public void testSimpleNonNs() - throws XMLStreamException - { - doTestSimple(false); - } - - public void testSimpleNs() - throws XMLStreamException - { - doTestSimple(true); - } - - /* - ////////////////////////////////////////////////// - // Helper methods - ////////////////////////////////////////////////// - */ - - private void doTestSimple(boolean ns) - throws XMLStreamException - { - final String XML = - "\n" - +"\n" - +"\n" - +"]>\n" - +"\n" - +"\n" - +"\n" - +"\n" - ; - XMLStreamReader sr = getReader(XML, ns); - // Should succeed - streamThrough(sr); - } - - private XMLStreamReader getReader(String xml, boolean nsAware) - throws XMLStreamException - { - XMLInputFactory f = getInputFactory(); - setNamespaceAware(f, nsAware); - setSupportDTD(f, true); - setValidating(f, true); - return constructStreamReader(f, xml); - } -} diff -Nru libwoodstox-java-4.1.3/src/test/wstxtest/vstream/TestXMLReporter.java libwoodstox-java-5.1.0/src/test/wstxtest/vstream/TestXMLReporter.java --- libwoodstox-java-4.1.3/src/test/wstxtest/vstream/TestXMLReporter.java 2012-04-24 04:38:22.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/wstxtest/vstream/TestXMLReporter.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,282 +0,0 @@ -package wstxtest.vstream; - -import javax.xml.stream.*; - -import org.codehaus.stax2.XMLReporter2; -import org.codehaus.stax2.validation.XMLValidationProblem; - -import wstxtest.stream.BaseStreamTest; - -/** - * Simple testing to ensure that {@link XMLReporter} works as - * expected with respect to validation errors. - *

- * As of Woodstox 4.0, we will be actually using {@link XMLReporter2} - * interface, both to test that the improved interface works, and - * to get access to more accurate information. - */ -public class TestXMLReporter - extends BaseStreamTest -{ - /** - * Basic unit test for verifying that XMLReporter gets validation - * errors reported. - */ - public void testValidationError() - throws XMLStreamException - { - String XML = - "\n" - +"]>..." - ; - testOldReporterProblems(XML, 0); - testNewReporterProblems(XML, null); - - // Then invalid, with one error - XML = - "\n" - +"]>"; - ; - testOldReporterProblems(XML, 1); - testNewReporterProblems(XML, "at least one element "); - } - - /** - * Test for specific validation error, mostly to verify - * fix to [WSTX-155] (and guard against regression) - */ - public void testMissingAttrError() - throws XMLStreamException - { - String XML = - "\n" - +" \n" - +"]>"; - ; - testOldReporterProblems(XML, 1); - testNewReporterProblems(XML, "Required attribute"); - } - - public void testInvalidFixedAttr() - throws XMLStreamException - { - // Not ok to have any other value, either completely different - String XML = "\n" - +"\n" - +"]>\n"; - testOldReporterProblems(XML, 1); - testNewReporterProblems(XML, "FIXED attribute"); - - // Or one with extra white space (CDATA won't get fully normalized) - XML = "\n" - +"\n" - +"]>\n"; - testOldReporterProblems(XML, 1); - testNewReporterProblems(XML, "FIXED attribute"); - } - - public void testInvalidIdAttr() - throws XMLStreamException - { - // Error: undefined id 'someId' - String XML = "\n" - +"\n" - +"\n" - +"]>\n"; - testOldReporterProblems(XML, 1); - testNewReporterProblems(XML, "Undefined id"); - - // Error: empty idref value - XML = "\n" - +"\n" - +"\n" - +"]>\n"; - testOldReporterProblems(XML, 1); - testNewReporterProblems(XML, "IDREF value"); - } - - public void testInvalidSimpleChoiceStructure() - throws XMLStreamException - { - String XML = "\n" - +"\n" - +"\n" - +"]>\n" - +""; - testOldReporterProblems(XML, 1); - testNewReporterProblems(XML, "Expected at least one of elements"); - } - - /** - * This test verifies that exception XMLReporter rethrows gets - * properly propagated. - */ - public void testErrorRethrow() - throws XMLStreamException - { - String XML = - "\n" - +"]>"; - ; - MyReporterOld rep = new MyReporterOld(); - rep.enableThrow(); - XMLStreamReader sr = getReader(XML, rep); - try { - streamThrough(sr); - fail("Expected a re-thrown exception for invalid content"); - } catch (XMLStreamException xse) { - ; - } - sr.close(); - assertEquals(1, rep.getCount()); - testNewReporterProblems(XML, "element "); - } - - /* - ////////////////////////////////////////////////// - // Helper methods - ////////////////////////////////////////////////// - */ - - private XMLStreamReader getReader(String xml, XMLReporter rep) - throws XMLStreamException - { - XMLInputFactory f = getInputFactory(); - setNamespaceAware(f, true); - setSupportDTD(f, true); - setValidating(f, true); - f.setXMLReporter(rep); - return constructStreamReader(f, xml); - } - - private void testOldReporterProblems(String XML, int expFails) - throws XMLStreamException - { - MyReporterOld rep = new MyReporterOld(); - XMLStreamReader sr = getReader(XML, rep); - - streamThrough(sr); - sr.close(); - int actFails = rep.getCount(); - assertEquals("Expected "+expFails+" fail(s), got "+actFails, - expFails, actFails); - } - - private void testNewReporterProblems(String XML, String expMsg) - throws XMLStreamException - { - MyReporter2 rep = new MyReporter2(); - XMLStreamReader sr = getReader(XML, rep); - - streamThrough(sr); - sr.close(); - int actFails = rep.getCount(); - int expFails = (expMsg == null) ? 0 : 1; - - assertEquals("Expected "+expFails+" fail(s), got "+actFails, - expFails, actFails); - if (expFails > 0) { - String actMsg = rep.getMessage(); - if (actMsg == null) { - actMsg = ""; - } - if (actMsg.indexOf(expMsg) < 0) { - fail("Expected failure to contain phrase '"+expMsg+"', did not, was: '"+actMsg+"'"); - } - } - } - - /* - ////////////////////////////////////////////////// - // Helper classes - ////////////////////////////////////////////////// - */ - - /** - * Base Report class, used to verify some aspects of using - * plain old XMLReporter class (for example that we do - * get 'relatedInfo' populated with XMLValidationProblem) - */ - static class MyReporterOld - implements XMLReporter - { - protected int _count = 0; - - protected String _firstMessage; - - protected boolean _doThrow = false; - - public MyReporterOld() { } - - public void enableThrow() { _doThrow = true; } - - public void report(String message, - String errorType, - Object relatedInfo, - Location location) - throws XMLStreamException - { - ++_count; - if (_firstMessage != null) { - _firstMessage = message; - } - if (_doThrow) { - throw new XMLStreamException(message, location); - } - /* 30-May-2008, TSa: Need to ensure that extraArg is of - * type XMLValidationProblem; new constraint for Woodstox - */ - if (relatedInfo == null) { - throw new IllegalArgumentException("relatedInformation null, should be an instance of XMLValidationProblem"); - } - if (!(relatedInfo instanceof XMLValidationProblem)) { - throw new IllegalArgumentException("relatedInformation not an instance of XMLValidationProblem (but "+relatedInfo.getClass().getName()+")"); - } - } - - public int getCount() { return _count; } - public String getMessage() { return _firstMessage; } - } - - static class MyReporter2 - extends MyReporterOld - implements XMLReporter2 - { - public MyReporter2() { super(); } - - public void report(String message, String errorType, - Object relatedInfo, Location location) - throws XMLStreamException - { - throw new Error("Should not get a call through old XMLReporter interface, when registering XMLReporter2"); - } - - public void report(XMLValidationProblem prob) - throws XMLStreamException - { - ++_count; - String msg = prob.getMessage(); - // Let's require a message here... for now - if (msg == null) { - throw new RuntimeException("Problem object missing 'message' property"); - } - if (_firstMessage == null) { - _firstMessage = msg; - } - if (_doThrow) { - throw prob.toException(); - } - } - } -} - - diff -Nru libwoodstox-java-4.1.3/src/test/wstxtest/vstream/TestXmlSpace.java libwoodstox-java-5.1.0/src/test/wstxtest/vstream/TestXmlSpace.java --- libwoodstox-java-4.1.3/src/test/wstxtest/vstream/TestXmlSpace.java 2012-04-24 04:38:22.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/wstxtest/vstream/TestXmlSpace.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,95 +0,0 @@ -package wstxtest.vstream; - -import javax.xml.stream.*; - -import org.codehaus.stax2.validation.*; - -import wstxtest.stream.BaseStreamTest; - -/** - * Simple test for ensuring handling of "xml:space" attribute. Not - * sure if this should go in the main StaxTest (or perhaps Stax2), since - * it's not 100% clear if the validity violations should result in - * XMLStreamException, or something else. - */ -public class TestXmlSpace - extends BaseStreamTest -{ - public void testSimpleNonNs() - throws XMLStreamException - { - // First, legal declarations: - for (int i = 0; i < 2; ++i) { - boolean nsAware = (i > 0); - - String XML = "\n" - +"\n" - +"]>"; - XMLStreamReader sr = getReader(XML, nsAware); - assertTokenType(DTD, sr.next()); - assertTokenType(START_ELEMENT, sr.next()); - assertTokenType(END_ELEMENT, sr.next()); - sr.close(); - - XML = "\n" - +"\n" - +"]>"; - sr = getReader(XML, nsAware); - assertTokenType(DTD, sr.next()); - assertTokenType(START_ELEMENT, sr.next()); - assertTokenType(END_ELEMENT, sr.next()); - sr.close(); - - // And then some non-legal ones: - XML = "\n" - +"\n" - +"]>"; - sr = getReader(XML, nsAware); - try { - int type = sr.next(); - assertTokenType(DTD, type); - type = sr.next(); - assertTokenType(START_ELEMENT, type); - fail("Expected a validity exception for invalid xml:space declaration (ns-aware: "+nsAware+")"); - } catch (XMLValidationException vex) { - ; // good - } - sr.close(); - - XML = "\n" - +"\n" - +"]>"; - sr = getReader(XML, nsAware); - try { - int type = sr.next(); - assertTokenType(DTD, type); - type = sr.next(); - assertTokenType(START_ELEMENT, type); - fail("Expected a validity exception for invalid xml:space declaration (ns-aware: "+nsAware+")"); - } catch (XMLValidationException vex) { - ; // good - } - sr.close(); - } - } - - /* - ////////////////////////////////////////////////// - // Helper methods - ////////////////////////////////////////////////// - */ - - private XMLStreamReader getReader(String xml, boolean nsAware) - throws XMLStreamException - { - XMLInputFactory f = getInputFactory(); - setNamespaceAware(f, nsAware); - setSupportDTD(f, true); - setValidating(f, true); - return constructStreamReader(f, xml); - } -} diff -Nru libwoodstox-java-4.1.3/src/test/wstxtest/wstream/BaseWriterTest.java libwoodstox-java-5.1.0/src/test/wstxtest/wstream/BaseWriterTest.java --- libwoodstox-java-4.1.3/src/test/wstxtest/wstream/BaseWriterTest.java 2012-04-24 04:38:22.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/wstxtest/wstream/BaseWriterTest.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,24 +0,0 @@ -package wstxtest.wstream; - -import java.io.*; - -import javax.xml.stream.*; - -import org.codehaus.stax2.XMLStreamReader2; - -import wstxtest.BaseWstxTest; - -abstract class BaseWriterTest - extends BaseWstxTest -{ - protected BaseWriterTest() { } - - protected XMLStreamReader2 constructNsStreamReader(String content, boolean coal) - throws XMLStreamException - { - XMLInputFactory f = getInputFactory(); - setNamespaceAware(f, true); - setCoalescing(f, coal); - return (XMLStreamReader2) f.createXMLStreamReader(new StringReader(content)); - } -} diff -Nru libwoodstox-java-4.1.3/src/test/wstxtest/wstream/TestAttrValidation.java libwoodstox-java-5.1.0/src/test/wstxtest/wstream/TestAttrValidation.java --- libwoodstox-java-4.1.3/src/test/wstxtest/wstream/TestAttrValidation.java 2012-04-24 04:38:22.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/wstxtest/wstream/TestAttrValidation.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,37 +0,0 @@ -package wstxtest.wstream; - -import java.io.*; - -import javax.xml.stream.*; - -import org.codehaus.stax2.*; - -/** - * This unit test suite verifies that output-side content validation - * works as expected, when enabled. - */ -public class TestAttrValidation - extends BaseWriterTest -{ - /** - * Unit test suite for testing violations of structural checks, when - * trying to output things in prolog/epilog. - */ - public void testSimpleAttrs() - throws Exception - { - XMLOutputFactory2 f = getOutputFactory(); - StringWriter w = new StringWriter(); - XMLStreamWriter sw = f.createXMLStreamWriter(w, "UTF-8"); - - sw.writeStartDocument(); - sw.writeEmptyElement("root"); - try { - sw.writeAttribute("foo", "Null is invalid: \0"); - fail("Expected an exception when trying to write attribute value with null character"); - } catch (XMLStreamException sex) { - ; - } - sw.writeEndDocument(); - } -} diff -Nru libwoodstox-java-4.1.3/src/test/wstxtest/wstream/TestAutoEndElems.java libwoodstox-java-5.1.0/src/test/wstxtest/wstream/TestAutoEndElems.java --- libwoodstox-java-4.1.3/src/test/wstxtest/wstream/TestAutoEndElems.java 2012-04-24 04:38:22.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/wstxtest/wstream/TestAutoEndElems.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,56 +0,0 @@ -package wstxtest.wstream; - -import java.io.*; - -import javax.xml.stream.*; - -import com.ctc.wstx.api.WstxOutputProperties; - -/** - * Unit tests for verifying that [WSTX-165] works ok. - */ -public class TestAutoEndElems - extends BaseWriterTest -{ - public void testAutomaticEndElemsEnabled() - throws XMLStreamException - { - StringWriter strw = new StringWriter(); - XMLStreamWriter sw = getFactory(true).createXMLStreamWriter(strw); - sw.writeStartElement("root"); - sw.writeStartElement("leaf"); - sw.writeCharacters(""); // to prevent empty elem, simplify testing - sw.close(); - - assertEquals("", strw.toString()); - } - - public void testAutomaticEndElemsDisabled() - throws XMLStreamException - { - StringWriter strw = new StringWriter(); - XMLStreamWriter sw = getFactory(false).createXMLStreamWriter(strw); - sw.writeStartElement("root"); - sw.writeStartElement("leaf"); - sw.writeCharacters(""); // to prevent empty elem, simplify testing - sw.close(); - - assertEquals("", strw.toString()); - } - - /* - //////////////////////////////////////////////////// - // Helper methods - //////////////////////////////////////////////////// - */ - - private XMLOutputFactory getFactory(boolean autoEndElems) - throws XMLStreamException - { - XMLOutputFactory f = getOutputFactory(); - // ns-awareness, repairing shouldn't matter, just whether automatic end elems enabled - f.setProperty(WstxOutputProperties.P_AUTOMATIC_END_ELEMENTS, autoEndElems ? Boolean.TRUE : Boolean.FALSE); - return f; - } - -} diff -Nru libwoodstox-java-4.1.3/src/test/wstxtest/wstream/TestContentValidation.java libwoodstox-java-5.1.0/src/test/wstxtest/wstream/TestContentValidation.java --- libwoodstox-java-4.1.3/src/test/wstxtest/wstream/TestContentValidation.java 2012-04-24 04:38:22.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/wstxtest/wstream/TestContentValidation.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,307 +0,0 @@ -package wstxtest.wstream; - -import java.io.*; - -import javax.xml.stream.*; - -import org.codehaus.stax2.*; - -/** - * This unit test suite verifies that output-side content validation - * works as expected, when enabled. - */ -public class TestContentValidation - extends BaseWriterTest -{ - final String COMMENT_CONTENT_IN = "can not have -- in there"; - final String COMMENT_CONTENT_OUT = "can not have - - in there"; - - final String CDATA_CONTENT_IN = "CData in: "; - final String CDATA_CONTENT_OUT = "CData in: "; - - final String PI_CONTENT_IN = "this should end PI: ?> shouldn't it?"; - final String PI_CONTENT_OUT = "this should end PI: ?> shouldn't it?"; - - /* - //////////////////////////////////////////////////// - // Main test methods - //////////////////////////////////////////////////// - */ - - public void testCommentChecking() - throws XMLStreamException - { - for (int i = 0; i <= 2; ++i) { - XMLOutputFactory2 f = getFactory(i, true, false); - for (int enc = 0; enc < 3; ++enc) { - XMLStreamWriter2 sw; - - if (enc == 0) { - StringWriter strw = new StringWriter(); - sw = (XMLStreamWriter2) f.createXMLStreamWriter(strw); - } else { - ByteArrayOutputStream bos = new ByteArrayOutputStream(); - String encStr = (enc == 1) ? "UTF-8" : "ISO-8859-1"; - sw = (XMLStreamWriter2) f.createXMLStreamWriter(bos, encStr); - } - sw.writeStartDocument(); - sw.writeStartElement("root"); - try { - sw.writeComment(COMMENT_CONTENT_IN); - fail("Expected an XMLStreamException for illegal comment content (contains '--') in checking + non-fixing mode (type "+i+")"); - } catch (XMLStreamException sex) { - // good - } catch (Throwable t) { - fail("Expected an XMLStreamException for illegal comment content (contains '--') in checking + non-fixing mode; got: "+t); - } - } - } - } - - public void testCommentFixing() - throws Exception - { - for (int i = 0; i <= 2; ++i) { - XMLOutputFactory2 f = getFactory(i, true, true); - - /* 24-Aug-2006, TSa: Let's also test with output stream-based - * output... writers may use different code - */ - for (int enc = 0; enc < 3; ++enc) { - XMLStreamWriter2 sw; - StringWriter strw = null; - ByteArrayOutputStream bos = null; - String encStr = null; - - if (enc == 0) { - strw = new StringWriter(); - sw = (XMLStreamWriter2) f.createXMLStreamWriter(strw); - } else { - bos = new ByteArrayOutputStream(); - encStr = (enc == 1) ? "UTF-8" : "ISO-8859-1"; - sw = (XMLStreamWriter2) f.createXMLStreamWriter(bos, encStr); - } - sw.writeStartDocument(); - sw.writeStartElement("root"); - /* now it should be ok, and result in one padded or - * 2 separate comments... - */ - sw.writeComment(COMMENT_CONTENT_IN); - sw.writeEndElement(); - sw.writeEndDocument(); - sw.close(); - - String output; - if (strw != null) { - output = strw.toString(); - } else { - output = new String(bos.toByteArray(), encStr); - } - - // so far so good; but let's ensure it also parses: - XMLStreamReader sr = getReader(output); - assertTokenType(START_ELEMENT, sr.next()); - assertTokenType(COMMENT, sr.next()); - StringBuffer sb = new StringBuffer(); - sb.append(getAndVerifyText(sr)); - - // May get another one too...? - int type; - - while ((type = sr.next()) == COMMENT) { - sb.append(getAndVerifyText(sr)); - } - - /* Ok... now, except for additional spaces, we should have - * about the same content: - */ - /* For now, since it's wstx-specific, let's just hard-code - * exactly what we are to get: - */ - String act = sb.toString(); - if (!COMMENT_CONTENT_OUT.equals(act)) { - failStrings("Failed to properly quote comment content (type "+i+")", - COMMENT_CONTENT_OUT, act); - } - assertTokenType(END_ELEMENT, type); - } - } - } - - public void testCDataChecking() - throws Exception - { - for (int i = 0; i <= 2; ++i) { - for (int itype = 0; itype < 2; ++itype) { - XMLOutputFactory2 f = getFactory(i, true, false); - - /* 24-Aug-2006, TSa: Let's also test with output stream-based - * output... writers may use different code - */ - for (int enc = 0; enc < 3; ++enc) { - XMLStreamWriter2 sw; - - if (enc == 0) { - StringWriter strw = new StringWriter(); - sw = (XMLStreamWriter2) f.createXMLStreamWriter(strw); - } else { - ByteArrayOutputStream bos = new ByteArrayOutputStream(); - sw = (XMLStreamWriter2) f.createXMLStreamWriter - (bos, (enc == 1) ? "UTF-8" : "ISO-8859-1"); - } - sw.writeStartDocument(); - sw.writeStartElement("root"); - try { - if (itype == 0) { - sw.writeCData(CDATA_CONTENT_IN); - } else { - char[] ch = CDATA_CONTENT_IN.toCharArray(); - sw.writeCData(ch, 0, ch.length); - } - fail("Expected an XMLStreamException for illegal CDATA content (contains ']]>') in checking + non-fixing mode (type "+i+", itype "+itype+")"); - } catch (XMLStreamException sex) { - // good - } catch (Exception t) { - fail("Expected an XMLStreamException for illegal CDATA content (contains ']]>') in checking + non-fixing mode; got: "+t); - } - } - } - } - } - - public void testCDataFixing() - throws Exception - { - for (int i = 0; i <= 2; ++i) { - for (int itype = 0; itype < 2; ++itype) { - XMLOutputFactory2 f = getFactory(i, true, true); - - /* 24-Aug-2006, TSa: Let's also test with output stream-based - * output... writers may use different code - */ - for (int enc = 0; enc < 3; ++enc) { - XMLStreamWriter2 sw; - StringWriter strw = null; - ByteArrayOutputStream bos = null; - String encStr = null; - - if (enc == 0) { - strw = new StringWriter(); - sw = (XMLStreamWriter2) f.createXMLStreamWriter(strw); - } else { - bos = new ByteArrayOutputStream(); - encStr = (enc == 1) ? "UTF-8" : "ISO-8859-1"; - sw = (XMLStreamWriter2) f.createXMLStreamWriter(bos, encStr); - } - - sw.writeStartDocument(); - sw.writeStartElement("root"); - /* now it should be ok, and result in two separate CDATA - * segments... - */ - if (itype == 0) { - sw.writeCData(CDATA_CONTENT_IN); - } else { - char[] ch = CDATA_CONTENT_IN.toCharArray(); - sw.writeCData(ch, 0, ch.length); - } - sw.writeEndElement(); - sw.writeEndDocument(); - sw.close(); - - String output; - if (strw != null) { - output = strw.toString(); - } else { - output = new String(bos.toByteArray(), encStr); - } - - // so far so good; but let's ensure it also parses: - XMLStreamReader sr = getReader(output); - assertTokenType(START_ELEMENT, sr.next()); - int type = sr.next(); - - assertTokenType(CDATA, type); - StringBuffer sb = new StringBuffer(); - sb.append(getAndVerifyText(sr)); - - // Should be getting one or more segments... - while ((type = sr.next()) == CDATA) { - sb.append(getAndVerifyText(sr)); - } - - String act = sb.toString(); - if (!CDATA_CONTENT_OUT.equals(act)) { - failStrings("Failed to properly quote CDATA content (type "+i+", itype "+itype+")", - CDATA_CONTENT_OUT, act); - } - assertTokenType(END_ELEMENT, type); - } - } - } - } - - public void testPIChecking() - throws Exception - { - for (int i = 0; i <= 2; ++i) { - XMLOutputFactory2 f = getFactory(i, true, false); - - /* 24-Aug-2006, TSa: Let's also test with output stream-based - * output... writers may use different code - */ - for (int enc = 0; enc < 3; ++enc) { - XMLStreamWriter2 sw; - - if (enc == 0) { - StringWriter strw = new StringWriter(); - sw = (XMLStreamWriter2) f.createXMLStreamWriter(strw); - } else { - ByteArrayOutputStream bos = new ByteArrayOutputStream(); - sw = (XMLStreamWriter2) f.createXMLStreamWriter - (bos, (enc == 1) ? "UTF-8" : "ISO-8859-1"); - } - sw.writeStartDocument(); - sw.writeStartElement("root"); - try { - sw.writeProcessingInstruction("target", PI_CONTENT_IN); - fail("Expected an XMLStreamException for illegal PI content (contains '?>') in checking + non-fixing mode (type "+enc+")"); - } catch (XMLStreamException sex) { - // good - } catch (Exception t) { - fail("Expected an XMLStreamException for illegal PI content (contains '?>') in checking + non-fixing mode; got: "+t); - } - } - } - } - - // // Note: no way (currently?) to fix PI content; thus, no test: - - - /* -//////////////////////////////////////////////////// -// Internal methods -//////////////////////////////////////////////////// -*/ - - private XMLOutputFactory2 getFactory(int type, boolean checkAll, boolean fixAll) - throws XMLStreamException - { - XMLOutputFactory2 f = getOutputFactory(); - // type 0 -> non-ns, 1 -> ns, non-repairing, 2 -> ns, repairing - setNamespaceAware(f, type > 0); - setRepairing(f, type > 1); - setValidateAll(f, checkAll); - setFixContent(f, fixAll); - return f; - } - - private XMLStreamReader getReader(String content) - throws XMLStreamException - { - XMLInputFactory2 f = getInputFactory(); - setCoalescing(f, false); - return f.createXMLStreamReader(new StringReader(content)); - } -} - diff -Nru libwoodstox-java-4.1.3/src/test/wstxtest/wstream/TestEmptyElementWriter.java libwoodstox-java-5.1.0/src/test/wstxtest/wstream/TestEmptyElementWriter.java --- libwoodstox-java-4.1.3/src/test/wstxtest/wstream/TestEmptyElementWriter.java 2012-04-24 04:38:22.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/wstxtest/wstream/TestEmptyElementWriter.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,77 +0,0 @@ -package wstxtest.wstream; - -import java.io.*; -import java.util.*; - -import javax.xml.stream.*; - -import com.ctc.wstx.api.EmptyElementHandler; -import com.ctc.wstx.api.WstxOutputProperties; - -/** - * Unit tests to verify that [WSTX-252] (ability to control whether - * an empty element can be written using empty element instead of - * separate start/end tags) has been completely implemented. - * - * @since 4.1 - */ -public class TestEmptyElementWriter - extends BaseWriterTest -{ - public void testDefaults() throws Exception - { - XMLOutputFactory f = getOutputFactory(); - // by default, empty elements can be used for everything - StringWriter sw = new StringWriter(); - XMLStreamWriter w = f.createXMLStreamWriter(sw); - w.writeStartElement("root"); - w.writeStartElement("a"); - w.writeEndElement(); - w.writeStartElement("b"); - w.writeEndElement(); - w.writeEndElement(); - w.writeEndDocument(); - w.close(); - assertEquals("", sw.toString()); - } - - public void testSimple() throws Exception - { - XMLOutputFactory f = getOutputFactory(); - // test with simple handler that lists explicitly all tags to close - Set tags = new HashSet(); - tags.add("a"); - f.setProperty(WstxOutputProperties.P_OUTPUT_EMPTY_ELEMENT_HANDLER, - new EmptyElementHandler.SetEmptyElementHandler(tags)); - StringWriter sw = new StringWriter(); - XMLStreamWriter w = f.createXMLStreamWriter(sw); - w.writeStartElement("root"); - w.writeStartElement("a"); - w.writeEndElement(); - w.writeStartElement("b"); - w.writeEndElement(); - w.writeEndElement(); - w.writeEndDocument(); - w.close(); - assertEquals("", sw.toString()); - } - - public void testHTML() throws Exception - { - XMLOutputFactory f = getOutputFactory(); - f.setProperty(WstxOutputProperties.P_OUTPUT_EMPTY_ELEMENT_HANDLER, - EmptyElementHandler.HtmlEmptyElementHandler.getInstance()); - StringWriter sw = new StringWriter(); - XMLStreamWriter w = f.createXMLStreamWriter(sw); - w.writeStartElement("root"); - w.writeStartElement("a"); - w.writeEndElement(); - w.writeStartElement("br"); - w.writeEndElement(); - w.writeEndElement(); - w.writeEndDocument(); - w.close(); - assertEquals("
", sw.toString()); - } - -} diff -Nru libwoodstox-java-4.1.3/src/test/wstxtest/wstream/TestEscaping.java libwoodstox-java-5.1.0/src/test/wstxtest/wstream/TestEscaping.java --- libwoodstox-java-4.1.3/src/test/wstxtest/wstream/TestEscaping.java 2012-04-24 04:38:22.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/wstxtest/wstream/TestEscaping.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,110 +0,0 @@ -package wstxtest.wstream; - -import java.io.*; - -import javax.xml.stream.*; - -import org.codehaus.stax2.*; - -import com.ctc.wstx.api.WstxOutputProperties; - -/** - * This unit test suite verifies Woodstox-specific output-side - * character escaping options - */ -public class TestEscaping - extends BaseWriterTest -{ - public void testCrHandlingEscaping() - throws XMLStreamException - { - doTestCrHandling(true, "Cr: \r.", "Cr: \r.", "Cr: \r."); - doTestCrHandling(true, "CrLF: \r\n.", "CrLF: \r\n.", "CrLF: \r\n."); - } - - public void testCrHandlingNonEscaping() - throws XMLStreamException - { - doTestCrHandling(false, "Cr: \r.", "Cr: \n.", "Cr: ."); - // attribute output is same, but parser handling differs, so: - doTestCrHandling(false, "CrLF: \r\n.", "CrLF: \n.", "CrLF: \n."); - } - - /* - //////////////////////////////////////////////////// - // Helper methods - //////////////////////////////////////////////////// - */ - - private void doTestCrHandling(boolean escaping, String input, - String elemOutput, String attrOutput) - throws XMLStreamException - { - // Let's try out 2 main encoding types: - String[] ENC = new String[] { "UTF-8", "ISO-8859-1", "US-ASCII" }; - for (int encIx = 0; encIx < ENC.length; ++encIx) { - // And 3 writer types: - for (int type = 0; type < 3; ++type) { - String enc = ENC[encIx]; - XMLOutputFactory2 f = getFactory(type, escaping); - ByteArrayOutputStream out = new ByteArrayOutputStream(); - XMLStreamWriter sw = f.createXMLStreamWriter(out, enc); - writeDoc(sw, input); - sw.close(); - - // Ok, do we get what we should? - verifyDoc(escaping, enc, out.toByteArray(), - elemOutput, attrOutput, sw); - } - } - } - - private void writeDoc(XMLStreamWriter sw, String text) - throws XMLStreamException - { - sw.writeStartDocument(); - sw.writeStartElement("root"); - sw.writeAttribute("attr", text); - sw.writeCharacters(text); - sw.writeEndElement(); - sw.writeEndDocument(); - } - - private void verifyDoc(boolean escaping, String encoding, byte[] data, - String expElem, String expAttr, XMLStreamWriter sw) - throws XMLStreamException - { - XMLStreamReader2 sr = constructNsStreamReader(new ByteArrayInputStream(data), true); - String actualText; - assertTokenType(START_ELEMENT, sr.next()); - assertEquals("root", sr.getLocalName()); - - assertEquals(1, sr.getAttributeCount()); - actualText = sr.getAttributeValue(0); - if (!expAttr.equals(actualText)) { - failStrings("Attribute value incorrect (CR-escaping: "+escaping+", encoding: "+encoding+"; writer: "+sw+")", expAttr, actualText); - } - - assertTokenType(CHARACTERS, sr.next()); - actualText = getAndVerifyText(sr); - if (!expElem.equals(actualText)) { - failStrings("Element value incorrect (CR-escaping: "+escaping+", encoding: "+encoding+", writer "+sw+")", expElem, actualText); - } - assertTokenType(END_ELEMENT, sr.next()); - assertEquals("root", sr.getLocalName()); - } - - private XMLOutputFactory2 getFactory(int type, boolean escapeCr) - throws XMLStreamException - { - XMLOutputFactory2 f = getOutputFactory(); - // type 0 -> non-ns, 1 -> ns, non-repairing, 2 -> ns, repairing - setNamespaceAware(f, type > 0); - setRepairing(f, type > 1); - - f.setProperty(WstxOutputProperties.P_OUTPUT_ESCAPE_CR, escapeCr ? Boolean.TRUE : Boolean.FALSE); - - return f; - } -} - diff -Nru libwoodstox-java-4.1.3/src/test/wstxtest/wstream/TestImplicitStartDoc.java libwoodstox-java-5.1.0/src/test/wstxtest/wstream/TestImplicitStartDoc.java --- libwoodstox-java-4.1.3/src/test/wstxtest/wstream/TestImplicitStartDoc.java 2012-04-24 04:38:22.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/wstxtest/wstream/TestImplicitStartDoc.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,39 +0,0 @@ -package wstxtest.wstream; - -import java.io.StringWriter; - -import javax.xml.stream.*; - -/** - * This test suite verifies that it is ok to omit writing of - * START_DOCUMENT event, to avoid getting xml declaration output - * (for example to write xml fragments). - * It was created to verify that issue - * WSTX-84 - * is not due to missing writeStartDocument() call. - */ -public class TestImplicitStartDoc - extends BaseWriterTest -{ - public void testWriteImplicitStartDoc() - throws XMLStreamException - { - XMLOutputFactory f = getOutputFactory(); - StringWriter strw = new StringWriter(); - XMLStreamWriter sw = f.createXMLStreamWriter(strw); - try { - sw.writeStartElement("root"); - } catch (Exception e) { - fail("Did not expected writeStartElement to fail, got: "+e); - } - sw.writeCharacters("x"); - sw.writeEndElement(); - - // Writing of end document should be optional, so let's check here - sw.flush(); - assertEquals("x", strw.toString()); - - sw.writeEndDocument(); - assertEquals("x", strw.toString()); - } -} diff -Nru libwoodstox-java-4.1.3/src/test/wstxtest/wstream/TestInvalidChars.java libwoodstox-java-5.1.0/src/test/wstxtest/wstream/TestInvalidChars.java --- libwoodstox-java-4.1.3/src/test/wstxtest/wstream/TestInvalidChars.java 2012-04-24 04:38:22.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/wstxtest/wstream/TestInvalidChars.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,219 +0,0 @@ -package wstxtest.wstream; - -import java.io.*; - -import javax.xml.stream.*; - -import org.codehaus.stax2.*; - -import com.ctc.wstx.api.InvalidCharHandler; -import com.ctc.wstx.api.WstxOutputProperties; - -/** - * This unit test suite verifies handling of invalid/illegal xml - * characters, with or without explicit handlers - * - * @since 4.0 - */ -public class TestInvalidChars - extends BaseWriterTest -{ - final static String INVALID_TEXT = "\u0003"; - - final static Character REPL_CHAR = Character.valueOf('*'); - - // // First let's verify that we do catch problematic chars - - public void testInvalidCatchingCharacters() throws XMLStreamException - { - doTestInvalid(CHARACTERS); - } - - public void testInvalidCatchingCData() throws XMLStreamException - { - doTestInvalid(CDATA); - } - public void testInvalidCatchingComment() throws XMLStreamException - { - doTestInvalid(COMMENT); - } - public void testInvalidCatchingPI() throws XMLStreamException - { - doTestInvalid(PROCESSING_INSTRUCTION); - } - - public void testInvalidCatchingAttribute() throws XMLStreamException - { - doTestInvalid(ATTRIBUTE); - } - - // // And then also that we can fix problems - - public void testValidReplacingCharacters() throws Exception - { - doTestValid(CHARACTERS); - } - - public void testValidReplacingCData() throws Exception - { - doTestValid(CDATA); - } - public void testValidReplacingComment() throws Exception - { - doTestValid(COMMENT); - } - public void testValidReplacingPI() throws Exception - { - doTestValid(PROCESSING_INSTRUCTION); - } - - public void testValidReplacingAttribute() throws Exception - { - doTestValid(ATTRIBUTE); - } - - /* - ////////////////////////////////////////////// - // Shared test code - ////////////////////////////////////////////// - */ - - private void doTestInvalid(int evtType) - throws XMLStreamException - { - XMLOutputFactory2 f = getFactory(null); - doTestInvalid(evtType, f.createXMLStreamWriter(new ByteArrayOutputStream(), "ISO-8859-1"), true); - doTestInvalid(evtType, f.createXMLStreamWriter(new ByteArrayOutputStream(), "US-ASCII"), true); - // [WSTX-173] affects backends that do not do their own encoding: - doTestInvalid(evtType, f.createXMLStreamWriter(new StringWriter()), false); - doTestInvalid(evtType, f.createXMLStreamWriter(new ByteArrayOutputStream(), "UTF-8"), false); - } - - /** - * @param strictChecks Due to [WSTX-173], may need to relax some checks - * to pass for now. Not needed once bug is fixed. - */ - private void doTestInvalid(int evtType, XMLStreamWriter sw1, - boolean strictChecks) - throws XMLStreamException - { - XMLStreamWriter2 sw = (XMLStreamWriter2) sw1; - sw.writeStartDocument(); - sw.writeStartElement("root"); - try { - switch (evtType) { - case ATTRIBUTE: - sw.writeAttribute("attr", INVALID_TEXT); - // always strict for attributes and characters - handleFailure(sw, "Expected an exception for ATTRIBUTE", true); - break; - case CHARACTERS: - sw.writeCharacters(INVALID_TEXT); - handleFailure(sw, "Expected an exception for CHARACTERS", true); - break; - case CDATA: - sw.writeCData(INVALID_TEXT); - handleFailure(sw, "Expected an exception for CDATA", strictChecks); - break; - case COMMENT: - sw.writeComment(INVALID_TEXT); - handleFailure(sw, "Expected an exception for COMMENT", strictChecks); - break; - case PROCESSING_INSTRUCTION: - sw.writeProcessingInstruction("pi", INVALID_TEXT); - handleFailure(sw, "Expected an exception for PROCESSING_INSTRUCTION", strictChecks); - break; - } - } catch (XMLStreamException xse) { - sw.closeCompletely(); - } - } - - private void doTestValid(int evtType) - throws IOException, XMLStreamException - { - XMLOutputFactory2 f = getFactory(REPL_CHAR); - doTestValid(f, evtType, "ISO-8859-1", true); - doTestValid(f, evtType, "US-ASCII", true); - - // [WSTX-173] affects backends that do not do their own encoding: - doTestValid(f, evtType, "UTF-8", false); - - StringWriter strw = new StringWriter(); - XMLStreamWriter sw = f.createXMLStreamWriter(strw); - buildValid(evtType, sw); - verifyValidReplacement(evtType, sw, strw.toString(), false); - } - - private void doTestValid(XMLOutputFactory2 f, int evtType, String enc, boolean strict) - throws IOException, XMLStreamException - { - ByteArrayOutputStream out = new ByteArrayOutputStream(); - XMLStreamWriter sw = f.createXMLStreamWriter(out, enc); - buildValid(evtType, sw); - verifyValidReplacement(evtType, sw, out.toString(enc), strict); - } - - private void verifyValidReplacement(int evtType, XMLStreamWriter sw, String doc, boolean strict) - { - if (doc.indexOf(REPL_CHAR.charValue()) < 0) { // no replacement... - handleFailure(sw, "Failed to replace invalid char, event "+tokenTypeDesc(evtType)+", xml = '"+doc+"'", strict); - } - } - - private void buildValid(int evtType, XMLStreamWriter sw1) - throws XMLStreamException - { - XMLStreamWriter2 sw = (XMLStreamWriter2) sw1; - sw.writeStartDocument(); - sw.writeStartElement("root"); - - switch (evtType) { - case ATTRIBUTE: - sw.writeAttribute("attr", INVALID_TEXT); - break; - case CHARACTERS: - sw.writeCharacters(INVALID_TEXT); - break; - case CDATA: - sw.writeCData(INVALID_TEXT); - break; - case COMMENT: - sw.writeComment(INVALID_TEXT); - break; - case PROCESSING_INSTRUCTION: - sw.writeProcessingInstruction("pi", INVALID_TEXT); - break; - } - sw.writeEndElement(); - sw.writeEndDocument(); - sw.closeCompletely(); - } - - private void handleFailure(XMLStreamWriter sw, String msg, boolean doFail) - { - if (doFail) { - fail(msg+" (stream writer: "+sw+")"); - } else { - warn("suppressing failure '"+msg+"' (stream writer: "+sw+")"); - } - } - - /* - ////////////////////////////////////////////// - // Helper methods, low-level - ////////////////////////////////////////////// - */ - - private XMLOutputFactory2 getFactory(Character replChar) - throws XMLStreamException - { - XMLOutputFactory2 f = getOutputFactory(); - setRepairing(f, false); - setValidateContent(f, true); - f.setProperty(WstxOutputProperties.P_OUTPUT_INVALID_CHAR_HANDLER, - (replChar == null) ? null : new InvalidCharHandler.ReplacingHandler(replChar.charValue())); - return f; - } -} - diff -Nru libwoodstox-java-4.1.3/src/test/wstxtest/wstream/TestNameValidation.java libwoodstox-java-5.1.0/src/test/wstxtest/wstream/TestNameValidation.java --- libwoodstox-java-4.1.3/src/test/wstxtest/wstream/TestNameValidation.java 2012-04-24 04:38:22.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/wstxtest/wstream/TestNameValidation.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,451 +0,0 @@ -package wstxtest.wstream; - -import java.io.*; - -import javax.xml.stream.*; - -import org.codehaus.stax2.*; - -/** - * Woodstox-specific stream writer test suite that will ensure that the - * name validation property works properly (as expected) - */ -public class TestNameValidation - extends BaseWriterTest -{ - final static String DUMMY_URL = "http://someurl"; - final static String ATTR_VALUE = "value"; - final static String PI_DATA = "just some proc.instr. content!!"; - - /* Notes about validity - * - * - Dot is valid, but not as first name char - */ - - final static String[] VALID_NS_PREFIXES = new String[] { - "a", "ab_123", "this.attr", "_uber", "pre-fix" - }; - final static String[] VALID_NS_NAMES = new String[] { - "tag", "i", "my.dotted.name", - // note: dot is valid only as non-first char... - "x.12", "a_32", "__mymy", "a-ha" - }; - final static String[] VALID_NON_NS_NAMES = new String[] { - "ns:elem", ":::a", "xyz" - }; - final static String[] VALID_NS_ROOT_NAMES = new String[] { - "ns:elem", "abc", "a1:foobar" - }; - - final static String[] INVALID_NS_PREFIXES = new String[] { - "a:1", "1abc", "xy+z", "r&b", "", "fun\tny", ".ns", "-a" - }; - final static String[] INVALID_NS_NAMES = new String[] { - ":abc", "ns:elem", ".name", "", "1", "afoo", "", "1abc", " space", ".abc", "-23" - }; - final static String[] INVALID_NS_ROOT_NAMES = new String[] { - "ns:elem:blah", "a<>2", "", ".x", "-ab", "3cpu" - }; - - /* - //////////////////////////////////////////////////// - // Main test methods - //////////////////////////////////////////////////// - */ - - public void testValidElemNames() - throws XMLStreamException - { - for (int n = 0; n < 4; ++n) { - boolean ns = ((n & 1) == 0); - boolean validate = ((n & 2) == 0); - XMLStreamWriter sw = startDoc(validate, ns); - - // Let's add a dummy root: - sw.writeStartElement("dummy"); - - if (ns) { // need to check both prefixes and names - /* Note: when not repairing, need not worry about - * namespace binding... makes life easier here - */ - for (int i = 0; i < VALID_NS_NAMES.length; ++i) { - String name = VALID_NS_NAMES[i]; - sw.writeEmptyElement(name); - sw.writeStartElement(name); - sw.writeEndElement(); - } - for (int i = 0; i < VALID_NS_PREFIXES.length; ++i) { - String prefix = VALID_NS_PREFIXES[i]; - sw.writeEmptyElement(prefix, "elem", DUMMY_URL); - sw.writeStartElement(prefix, "elem", DUMMY_URL); - sw.writeEndElement(); - } - } else { - for (int i = 0; i < VALID_NON_NS_NAMES.length; ++i) { - String name = VALID_NON_NS_NAMES[i]; - sw.writeEmptyElement(name); - sw.writeStartElement(name); - sw.writeEndElement(); - } - } - - sw.writeEndElement(); - closeDoc(sw); - } - } - - public void testInvalidElemNames() - throws XMLStreamException - { - for (int n = 0; n < 2; ++n) { - boolean ns = (n == 1); - if (ns) { // need to check both prefixes and names - for (int i = 0; i < INVALID_NS_NAMES.length; ++i) { - String name = INVALID_NS_NAMES[i]; - for (int j = 0; j < INVALID_NS_PREFIXES.length; ++j) { - String prefix = INVALID_NS_PREFIXES[j]; - doTestInvalidElemName(true, prefix, name); - doTestInvalidElemName(true, null, name); - } - } - } else { - for (int i = 0; i < INVALID_NON_NS_NAMES.length; ++i) { - String name = INVALID_NON_NS_NAMES[i]; - doTestInvalidElemName(false, null, name); - } - } - } - } - - private void doTestInvalidElemName(boolean ns, String prefix, String name) - throws XMLStreamException - { - for (int i = 0; i < 2; ++i) { // to test both empty and non-empty elems - boolean empty = (i == 1); - try { - XMLStreamWriter sw = startDoc(true, ns); - sw.writeStartElement("dummy"); - - if (prefix == null) { - if (empty) { - sw.writeEmptyElement(name); - } else { - sw.writeStartElement(name); - sw.writeEndElement(); - } - } else { - if (empty) { - sw.writeEmptyElement(prefix, name, DUMMY_URL); - } else { - sw.writeStartElement(prefix, name, DUMMY_URL); - sw.writeEndElement(); - } - } - - sw.writeEndElement(); - closeDoc(sw); - - } catch (XMLStreamException iae) { - continue; // good - } - - fail("Failed to catch an invalid element name/prefix (ns = "+ns+"); name='" - +name+"', prefix = " - +((prefix == null) ? "NULL" : ("'"+prefix+"'"))+"."); - } - } - - public void testValidAttrNames() - throws Exception - { - for (int n = 0; n < 4; ++n) { - boolean ns = ((n & 1) == 0); - boolean validate = ((n & 2) == 0); - XMLStreamWriter sw = startDoc(validate, ns); - - // Let's add a dummy root: - sw.writeStartElement("dummy"); - - if (ns) { - for (int i = 0; i < VALID_NS_NAMES.length; ++i) { - String name = VALID_NS_NAMES[i]; - sw.writeAttribute(name, ATTR_VALUE); - } - for (int i = 0; i < VALID_NS_PREFIXES.length; ++i) { - String prefix = VALID_NS_PREFIXES[i]; - sw.writeAttribute(prefix, DUMMY_URL, "attr", ATTR_VALUE); - } - } else { - for (int i = 0; i < VALID_NON_NS_NAMES.length; ++i) { - String name = VALID_NON_NS_NAMES[i]; - sw.writeAttribute(name, ATTR_VALUE); - } - } - - sw.writeEndElement(); - closeDoc(sw); - } - } - - public void testInvalidAttrNames() - throws Exception - { - for (int n = 0; n < 2; ++n) { - boolean ns = (n == 1); - if (ns) { // need to check both prefixes and names - for (int i = 0; i < INVALID_NS_NAMES.length; ++i) { - String name = INVALID_NS_NAMES[i]; - for (int j = 0; j < INVALID_NS_PREFIXES.length; ++j) { - String prefix = INVALID_NS_PREFIXES[j]; - doTestInvalidAttrName(true, prefix, name); - doTestInvalidAttrName(true, null, name); - } - } - } else { - for (int i = 0; i < INVALID_NON_NS_NAMES.length; ++i) { - String name = INVALID_NON_NS_NAMES[i]; - doTestInvalidAttrName(false, null, name); - } - } - } - } - - private void doTestInvalidAttrName(boolean ns, String prefix, String name) - throws XMLStreamException - { - XMLStreamWriter sw = startDoc(true, ns); - sw.writeStartElement("dummy"); - try { - if (prefix == null) { - sw.writeAttribute(name, ATTR_VALUE); - } else { - sw.writeAttribute(prefix, DUMMY_URL, name, ATTR_VALUE); - } - } catch (XMLStreamException sex) { - sw.writeEndElement(); - closeDoc(sw); - return; // good - } - - fail("Failed to catch an invalid attr name/prefix (ns = "+ns+"); name='" - +name+"', prefix = " - +((prefix == null) ? "NULL" : ("'"+prefix+"'"))+"."); - } - - /** - * According to XML Namespaces 1.1 specification, PI targets - * can not contain colons either... - */ - public void testValidPiNames() - throws Exception - { - for (int n = 0; n < 4; ++n) { - boolean ns = ((n & 1) == 0); - boolean validate = ((n & 2) == 0); - XMLStreamWriter sw = startDoc(validate, ns); - - // Let's add a dummy root: - sw.writeStartElement("dummy"); - - /* No colons allowed in namespace-aware mode - */ - String[] strs = ns ? VALID_NS_NAMES : VALID_NON_NS_NAMES; - for (int i = 0; i < strs.length; ++i) { - String name = strs[i]; - sw.writeProcessingInstruction(name); - sw.writeProcessingInstruction(name, PI_DATA); - } - - sw.writeEndElement(); - closeDoc(sw); - } - } - - public void testInvalidPiNames() - throws Exception - { - for (int n = 0; n < 4; ++n) { - boolean ns = ((n & 1) == 0); - boolean empty = ((n & 2) == 0); - String[] strs = ns ? INVALID_NS_NAMES : INVALID_NON_NS_NAMES; - - for (int i = 0; i < strs.length; ++i) { - String name = strs[i]; - XMLStreamWriter sw = startDoc(true, ns); - sw.writeStartElement("dummy"); - - - try { - if (empty) { - sw.writeProcessingInstruction(name); - } else { - sw.writeProcessingInstruction(name, PI_DATA); - } - } catch (XMLStreamException sex) { - sw.writeEndElement(); - closeDoc(sw); - continue; // good - } - - fail("Failed to catch an invalid proc.instr. name (ns = "+ns+") '" - +name+"'."); - } - } - } - - /** - * Since the root element name is NOT really properly split (ie. it's - * never dealt with as a scoped name), we can only check if that it has - * zero or one colons (in NS-awre) mode, but nothing further - */ - public void testValidRootNames() - throws Exception - { - for (int n = 0; n < 4; ++n) { - boolean ns = ((n & 1) == 0); - boolean validate = ((n & 2) == 0); - - String[] strs = ns ? VALID_NS_ROOT_NAMES : VALID_NON_NS_NAMES; - for (int i = 0; i < strs.length; ++i) { - XMLStreamWriter2 sw = (XMLStreamWriter2)startDoc(validate, ns); - String rootName = strs[i]; - // only root name is mandatory, others are optional - sw.writeDTD(rootName, null, null, null); - // need a matching root, then: - if (ns) { // may need to split - int ix = rootName.indexOf(':'); - if (ix > 0) { - sw.writeEmptyElement(rootName.substring(0, ix), - rootName.substring(ix+1), - DUMMY_URL); - } else { - sw.writeEmptyElement(rootName); - } - } else { - sw.writeEmptyElement(rootName); - } - closeDoc(sw); - } - } - } - - public void testInvalidRootNames() - throws Exception - { - for (int n = 0; n < 2; ++n) { - boolean ns = ((n & 1) == 0); - String[] strs = ns ? INVALID_NS_ROOT_NAMES : INVALID_NON_NS_NAMES; - - for (int i = 0; i < strs.length; ++i) { - String rootName = strs[i]; - XMLStreamWriter2 sw = (XMLStreamWriter2)startDoc(true, ns); - try { - // only root name is mandatory, others are optional - sw.writeDTD(rootName, null, null, null); - sw.writeEmptyElement(rootName); // need a root...and should match too - } catch (XMLStreamException sex) { - continue; // good - } - - fail("Failed to catch an invalid DTD root name (ns = "+ns+") '" - +rootName+"'."); - } - } - } - - /** - * According to XML Namespaces 1.1 specification, entity names (ids) - * can not contain colons either... - *

- * Note: Here we count on the fact that the current stream writer - * does not (and actually, can not!) verify whether the entity - * has been properly declared. - */ - public void testValidEntityNames() - throws Exception - { - for (int n = 0; n < 4; ++n) { - boolean ns = ((n & 1) == 0); - boolean validate = ((n & 2) == 0); - XMLStreamWriter sw = startDoc(validate, ns); - - // Let's add a dummy root: - sw.writeStartElement("dummy"); - - /* No colons allowed in namespace-aware mode - */ - String[] strs = ns ? VALID_NS_NAMES : VALID_NON_NS_NAMES; - for (int i = 0; i < strs.length; ++i) { - String name = strs[i]; - sw.writeEntityRef(name); - } - - sw.writeEndElement(); - closeDoc(sw); - } - } - - public void testInvalidEntityNames() - throws XMLStreamException - { - for (int n = 0; n < 2; ++n) { - boolean ns = ((n & 1) == 0); - String[] strs = ns ? INVALID_NS_ROOT_NAMES : INVALID_NON_NS_NAMES; - - for (int i = 0; i < strs.length; ++i) { - String name = strs[i]; - XMLStreamWriter2 sw = (XMLStreamWriter2)startDoc(true, ns); - sw.writeStartElement("dummy"); - try { - // only root name is mandatory, others are optional - sw.writeEntityRef(name); - } catch (XMLStreamException sex) { - sw.writeEndElement(); - closeDoc(sw); - continue; // good - } - - fail("Failed to catch an invalid entity name (ns = "+ns+") '" - +name+"'."); - } - } - } - - /* - //////////////////////////////////////////////////// - // Internal methods - //////////////////////////////////////////////////// - */ - - private XMLOutputFactory getFactory(boolean validateNames, boolean ns) - throws XMLStreamException - { - XMLOutputFactory f = getOutputFactory(); - setValidateNames(f, validateNames); - setNamespaceAware(f, ns); - // Let's disable repairing - setRepairing(f, false); - return f; - } - - private XMLStreamWriter startDoc(boolean validateNames, boolean ns) - throws XMLStreamException - { - XMLOutputFactory f = getFactory(validateNames, ns); - XMLStreamWriter sw = f.createXMLStreamWriter(new StringWriter()); - sw.writeStartDocument(); - return sw; - } - - private void closeDoc(XMLStreamWriter sw) - throws XMLStreamException - { - sw.writeEndDocument(); - sw.close(); - } -} - diff -Nru libwoodstox-java-4.1.3/src/test/wstxtest/wstream/TestOptions.java libwoodstox-java-5.1.0/src/test/wstxtest/wstream/TestOptions.java --- libwoodstox-java-4.1.3/src/test/wstxtest/wstream/TestOptions.java 2012-04-24 04:38:22.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/wstxtest/wstream/TestOptions.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,69 +0,0 @@ -package wstxtest.wstream; - -import java.io.*; - -import javax.xml.stream.*; - -import com.ctc.wstx.api.WstxOutputProperties; - -/** - * This unit test suite verifies Woodstox-specific writer-side options - */ -public class TestOptions - extends BaseWriterTest -{ - public void testEmptyElemSpaces() - throws IOException, XMLStreamException - { - /* Need to test both with and without space; as well as - * using Writer and using an OutputStream (since backends - * for the two are very different). - */ - for (int i = 0; i < 6; ++i) { - boolean space = ((i & 1) == 0); - String str; - boolean writer = (i < 2); - StringWriter strw = new StringWriter(); - ByteArrayOutputStream bos = new ByteArrayOutputStream(); - XMLStreamWriter sw; - - if (writer) { - sw = getWriter(space, strw, null, null); - } else { - sw = getWriter(space, null, bos, (i < 4) ? "UTF-8" : "ISO-8859--1"); - } - sw.writeStartDocument(); - sw.writeEmptyElement("root"); - sw.writeEndDocument(); - sw.close(); - // Should have a space! - if (writer) { - str = strw.toString(); - } else { - str = new String(bos.toByteArray(), "UTF-8"); - } - - if (space) { - if (str.indexOf("") < 0) { - fail("Expected '' when space is to be added: got '"+str+"'"); - } - } else { - if (str.indexOf("") < 0) { - fail("Expected '' when space is NOT to be added: got '"+str+"'"); - } - } - } - } - - private XMLStreamWriter getWriter(boolean addSpace, Writer sw, OutputStream out, String enc) - throws IOException, XMLStreamException - { - XMLOutputFactory f = getOutputFactory(); - f.setProperty(WstxOutputProperties.P_ADD_SPACE_AFTER_EMPTY_ELEM, - Boolean.valueOf(addSpace)); - if (sw != null) { - return f.createXMLStreamWriter(sw); - } - return f.createXMLStreamWriter(out, enc); - } -} diff -Nru libwoodstox-java-4.1.3/src/test/wstxtest/wstream/TestRepairingNsOutput.java libwoodstox-java-5.1.0/src/test/wstxtest/wstream/TestRepairingNsOutput.java --- libwoodstox-java-4.1.3/src/test/wstxtest/wstream/TestRepairingNsOutput.java 2012-04-24 04:38:22.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/wstxtest/wstream/TestRepairingNsOutput.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,211 +0,0 @@ -package wstxtest.wstream; - -import java.io.*; - -import javax.xml.stream.*; - -public class TestRepairingNsOutput - extends BaseWriterTest -{ - - /* - //////////////////////////////////////////////////// - // Main test methods - //////////////////////////////////////////////////// - */ - - public void testNoDummyDefaultNs() - throws XMLStreamException - { - XMLOutputFactory f = getFactory(); - StringWriter strw = new StringWriter(); - XMLStreamWriter sw = f.createXMLStreamWriter(strw); - - sw.writeStartDocument(); - sw.writeStartElement("", "root", ""); - sw.writeAttribute("attr", "value"); - sw.writeAttribute("", "", "attr2", "value2"); - sw.writeStartElement("", "leaf", ""); - sw.writeAttribute("", "", "foop", "value2"); - sw.writeCharacters("Sub-text\n"); - sw.writeEndElement(); - sw.writeEndDocument(); - sw.close(); - - String result = strw.toString(); - - if (result.indexOf("xmlns=\"\"") > 0) { - fail("Did not expect unnecessary default NS declarations, but found some in result: ["+result+"]"); - } - } - - /** - * Starting with Woodstox 3.1, the repairing writer is to honour - * non-conflicting namespace write requests. This may be needed to - * either try to preserve ns declaration canonicality, and/or to - * minimize number of declarations (a common root can bind a namespace - * for children, even without having to use it for its own attributes - * or element name). - *

- * Since this functionality is not required (or even suggested from what - * I can tell) by Stax 1.0 specs (and Stax2 does not change definitions - * of core API), this is in woodstox-specific section of tests. - */ - public void testExplicitNsWrites() - throws XMLStreamException - { - final String URI = "http://bar"; - XMLOutputFactory f = getFactory(); - StringWriter strw = new StringWriter(); - XMLStreamWriter sw = f.createXMLStreamWriter(strw); - - sw.writeStartDocument(); - /* root in no namespace, no attributes; but want to add - * an 'early' ns declaration for ns prefix 'foo', - * with URI 'http://bar' - */ - sw.writeStartElement("", "root"); - sw.writeNamespace("foo", URI); - // leaf in that namespace, then: - sw.writeStartElement(URI, "leaf"); - sw.writeEndElement(); - sw.writeEndElement(); - sw.writeEndDocument(); - sw.close(); - - String result = strw.toString(); - - // Ok, so let's parse and verify: - XMLStreamReader sr = constructNsStreamReader(result, false); - assertTokenType(START_ELEMENT, sr.next()); - assertEquals("root", sr.getLocalName()); - assertElemNotInNamespace(sr); - - int nsCount = sr.getNamespaceCount(); - assertEquals("Expected one (and only one) namespace declaration, got "+nsCount, 1, nsCount); - assertEquals("foo", sr.getNamespacePrefix(0)); - assertEquals(URI, sr.getNamespaceURI(0)); - - // And then the branch should have no ns decls: - assertTokenType(START_ELEMENT, sr.next()); - assertEquals("leaf", sr.getLocalName()); - assertEquals(URI, sr.getNamespaceURI()); - - assertEquals(0, sr.getNamespaceCount()); - - assertTokenType(END_ELEMENT, sr.next()); - assertEquals("leaf", sr.getLocalName()); - - // fine, rest is ok - sr.close(); - } - - /** - * Similar to {@link #testExplicitNsWrites}, but tests behavior - * of calls to XMLStreamWriter.writeDefaultNamespace - */ - public void testExplicitDefaultNsWrite() - throws XMLStreamException - { - final String URI1 = "http://foo"; - final String URI2 = "http://bar"; - XMLOutputFactory f = getFactory(); - StringWriter strw = new StringWriter(); - XMLStreamWriter sw = f.createXMLStreamWriter(strw); - - sw.writeStartDocument(); - /* root in explicit namespace, but additionally want to - * reserve the default ns: - */ - sw.writeStartElement("myns", "root", URI1); - sw.writeDefaultNamespace(URI2); - // leaf in that namespace, then: - sw.writeStartElement(URI2, "leaf"); - sw.writeEndElement(); - sw.writeEndElement(); - sw.writeEndDocument(); - sw.close(); - - String result = strw.toString(); - - // Ok, so let's parse and verify: - XMLStreamReader sr = constructNsStreamReader(result, false); - assertTokenType(START_ELEMENT, sr.next()); - assertEquals("root", sr.getLocalName()); - assertEquals("myns", sr.getPrefix()); - assertEquals(URI1, sr.getNamespaceURI()); - - int nsCount = sr.getNamespaceCount(); - assertEquals("Expected two namespace declarations, got "+nsCount, 2, nsCount); - - // And then leaf should have no ns decls: - assertTokenType(START_ELEMENT, sr.next()); - assertEquals("leaf", sr.getLocalName()); - assertNoElemPrefix(sr); - assertEquals(URI2, sr.getNamespaceURI()); - assertEquals(0, sr.getNamespaceCount()); - - assertTokenType(END_ELEMENT, sr.next()); - assertEquals("leaf", sr.getLocalName()); - - // fine, rest is ok - sr.close(); - } - - /** - * This test further verifies that caller's prefix-preference - * has higher priority than that of trying to find an existing - * prefix to use. - */ - public void testExplicitDupNsWrite() - throws XMLStreamException - { - final String URI = "http://bar"; - XMLOutputFactory f = getFactory(); - StringWriter strw = new StringWriter(); - XMLStreamWriter sw = f.createXMLStreamWriter(strw); - - sw.writeStartDocument(); - sw.writeStartElement("ns", "root", URI); - sw.writeAttribute("attrns", URI, "attr", "value"); - - sw.writeEndElement(); - sw.writeEndDocument(); - sw.close(); - - String result = strw.toString(); - - // Ok, so let's parse and verify: - XMLStreamReader sr = constructNsStreamReader(result, false); - assertTokenType(START_ELEMENT, sr.next()); - assertEquals("root", sr.getLocalName()); - assertEquals(URI, sr.getNamespaceURI()); - assertEquals(1, sr.getAttributeCount()); - assertEquals("attr", sr.getAttributeLocalName(0)); - assertEquals(URI, sr.getAttributeNamespace(0)); - // so far so good: but let's verify prefix is also what caller specified - assertEquals("attrns", sr.getAttributePrefix(0)); - - assertEquals(2, sr.getNamespaceCount()); - - // fine, rest is ok - sr.close(); - } - - /* - //////////////////////////////////////////////////// - // Internal methods - //////////////////////////////////////////////////// - */ - - private XMLOutputFactory getFactory() - throws XMLStreamException - { - XMLOutputFactory f = getOutputFactory(); - setNamespaceAware(f, true); - setRepairing(f, true); - return f; - } - -} - diff -Nru libwoodstox-java-4.1.3/src/test/wstxtest/wstream/TestStructuralValidation.java libwoodstox-java-5.1.0/src/test/wstxtest/wstream/TestStructuralValidation.java --- libwoodstox-java-4.1.3/src/test/wstxtest/wstream/TestStructuralValidation.java 2012-04-24 04:38:22.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/wstxtest/wstream/TestStructuralValidation.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,177 +0,0 @@ -package wstxtest.wstream; - -import java.io.*; - -import javax.xml.stream.*; - -import org.codehaus.stax2.*; - -/** - * This unit test suite verifies that output-side content validation - * works as expected, when enabled. - */ -public class TestStructuralValidation - extends BaseWriterTest -{ - /* - //////////////////////////////////////////////////// - // Main test methods - //////////////////////////////////////////////////// - */ - - /** - * Unit test suite for testing violations of structural checks, when - * trying to output things in prolog/epilog. - */ - public void testPrologChecks() - throws Exception - { - for (int i = 0; i <= 2; ++i) { // non-ns, simple-ns, repairing-ns - for (int j = 0; j < 2; ++j) { // prolog / epilog - boolean epilog = (j > 0); - final String prologMsg = epilog ? " in epilog" : " in prolog"; - - for (int op = 0; op <= 4; ++op) { - XMLOutputFactory2 f = getFactory(i, true); - StringWriter strw = new StringWriter(); - XMLStreamWriter2 sw = (XMLStreamWriter2) f.createXMLStreamWriter(strw); - String failMsg = null; - sw.writeStartDocument(); - - if (epilog) { - sw.writeStartElement("root"); - sw.writeEndElement(); - } - - try { - switch (op) { - case 0: // No non-white space text in prolog/epilog - failMsg = "when calling writeCharacters() for non-white space text"; - sw.writeCharacters("test!"); - break; - case 1: // - "" - - failMsg = "when calling writeCharacters() for non-white space text"; - sw.writeCharacters(new char[] { 't', 'e', 's', 't' }, 0, 4); - break; - case 2: // No CDATA in prolog/epilog - failMsg = "when calling writeCData()"; - sw.writeCData("cdata"); - case 3: // - "" - - failMsg = "when calling writeCData()"; - sw.writeCData(new char[] { 't', 'e', 's', 't' }, 0, 4); - case 4: // no entity refs in prolog/epilog: - failMsg = "when calling writeEntityRef()"; - sw.writeEntityRef("entity"); - default: - throw new Error("Internal error: illegal test index "+op); - } - } catch (XMLStreamException sex) { - // good - continue; - } catch (Throwable t) { - fail("Expected an XMLStreamException for "+failMsg+prologMsg+"; got "+t); - } finally { - if (epilog) { - sw.close(); - } - } - - fail("Expected an XMLStreamException for "+failMsg+prologMsg+"; no exception thrown"); - } - } - } - } - - /** - * Unit test that verifies that root element structural problems (no root, - * that is, an empty doc; more than one root element) are caught. - */ - public void testRootElementChecks() - throws XMLStreamException - { - for (int i = 0; i <= 2; ++i) { // non-ns, simple-ns, repairing-ns - for (int op = 0; op < 2; ++op) { - XMLOutputFactory2 f = getFactory(i, true); - StringWriter strw = new StringWriter(); - XMLStreamWriter2 sw = (XMLStreamWriter2) f.createXMLStreamWriter(strw); - String failMsg = null; - sw.writeStartDocument(); - - try { - switch (op) { - case 0: // No root element? - failMsg = "missing root element"; - sw.writeEndDocument(); - break; - case 1: // Two root elements... - failMsg = "second root element"; - sw.writeStartElement("root1"); - sw.writeEndElement(); - sw.writeStartElement("root1"); - sw.writeEndElement(); - break; - default: - throw new Error("Internal error: illegal test index "+op); - } - } catch (XMLStreamException sex) { - // good - continue; - } catch (Throwable t) { - fail("Expected an XMLStreamException for "+failMsg); - } - } - } - } - - public void testWriteElementChecks() - throws XMLStreamException - { - /* - for (int i = 0; i <= 2; ++i) { - // First, checks for prolog: - - for (int op = 0; op < 2; ++op) { - XMLOutputFactory2 f = getFactory(i, true); - StringWriter strw = new StringWriter(); - XMLStreamWriter2 sw = (XMLStreamWriter2) f.createXMLStreamWriter(strw); - String failMsg = null; - - sw.writeStartDocument(); - - // No non-white space text in prolog - try { - switch (op) { - case 0: - failMsg = "when calling writeCharacters() for non-white space text in prolog"; - sw.writeCharacters("test!"); - break; - default: - } - } catch (XMLStreamException sex) { - // good - } catch (Throwable t) { - fail("Expected an XMLStreamException for illegal comment content (contains '--') in checking + non-fixing mode; got: "+t); - } - sw.close(); - } - } - */ - } - - /* - //////////////////////////////////////////////////// - // Helper methods - //////////////////////////////////////////////////// - */ - - private XMLOutputFactory2 getFactory(int type, boolean checkStruct) - throws XMLStreamException - { - XMLOutputFactory2 f = getOutputFactory(); - // type 0 -> non-ns, 1 -> ns, non-repairing, 2 -> ns, repairing - setNamespaceAware(f, type > 0); - setRepairing(f, type > 1); - setValidateStructure(f, checkStruct); - return f; - } -} diff -Nru libwoodstox-java-4.1.3/src/test/wstxtest/wstream/TestWriterProperties.java libwoodstox-java-5.1.0/src/test/wstxtest/wstream/TestWriterProperties.java --- libwoodstox-java-4.1.3/src/test/wstxtest/wstream/TestWriterProperties.java 2012-04-24 04:38:22.000000000 +0000 +++ libwoodstox-java-5.1.0/src/test/wstxtest/wstream/TestWriterProperties.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,35 +0,0 @@ -package wstxtest.wstream; - -import java.io.*; - -import javax.xml.stream.*; - -import com.ctc.wstx.api.WstxOutputProperties; - -/** - * This unit test suite checks that per-writer properties are - * accessible as expected. - */ -public class TestWriterProperties - extends BaseWriterTest -{ - public void testAccessStream() - throws XMLStreamException - { - XMLOutputFactory f = getOutputFactory(); - ByteArrayOutputStream bos = new ByteArrayOutputStream(); - XMLStreamWriter sw = f.createXMLStreamWriter(bos, "UTF-8"); - - assertSame(bos, sw.getProperty(WstxOutputProperties.P_OUTPUT_UNDERLYING_STREAM)); - } - - public void testAccessWriter() - throws XMLStreamException - { - XMLOutputFactory f = getOutputFactory(); - StringWriter strw = new StringWriter(); - XMLStreamWriter sw = f.createXMLStreamWriter(strw); - - assertSame(strw, sw.getProperty(WstxOutputProperties.P_OUTPUT_UNDERLYING_WRITER)); - } -} diff -Nru libwoodstox-java-4.1.3/.travis.yml libwoodstox-java-5.1.0/.travis.yml --- libwoodstox-java-4.1.3/.travis.yml 1970-01-01 00:00:00.000000000 +0000 +++ libwoodstox-java-5.1.0/.travis.yml 2018-03-31 01:33:28.000000000 +0000 @@ -0,0 +1,9 @@ +language: java + +jdk: + - openjdk7 + - openjdk8 + +branches: + only: + - master