kevinross 2003/07/14 06:58:18
Modified: java/src/org/apache/xindice/core/filer FSFiler.java java/src/org/apache/xindice/client/xmldb/resources XMLResourceImpl.java java/src/org/apache/xindice/xml/sax SAXEventGenerator.java . build.xml .classpath java/tests/src/org/apache/xindice/integration/client/basic DocumentTest.java java/src/org/apache/xindice/tools/command StringSerializer.java Added: java/tests/src/org/apache/xindice/integration/client/basic/testdocs namespaces.xml namespace-changingprefixes.xml namespace-simpleprefixes.xml java/lib xmlunit-1.0.jar xmlunit-1.0.LICENSE Log: PR: 21535 Submitted By: Kevin O'Neill ([EMAIL PROTECTED]) Reviewed By: Kevin Ross While working my way toward integrating xindice into the BELTS runtime environment I came across this little problem. The namespace attributes were being emitted twice. Source Document <test xmlns="http://example.com/test-1"> Content emitted by getContentAsSAX <test xmlns="http://example.com/test-1" xmlns="http://example.com/test-1"> After some digging (and a few new test cases) I found that the hasSaxNamespacesPrefixes of the SAXEventGenerator and XMLResourceImpl have incorrect default values (according to http://www.saxproject.org/apidoc/org/xml/sax/package-summary.html#package_description) This patch corrects this and adds the additional test cases I used to track the problem down. It does add an addition jar dependency for the test cases though. XMLUnit. XMLUnit provides better testing of document structure than just string comparisons. Revision Changes Path 1.1 xml-xindice/java/tests/src/org/apache/xindice/integration/client/basic/testdocs/namespaces.xml Index: namespaces.xml =================================================================== <?xml version="1.0"?> <test xmlns="http://example.com/test-1"> <test xmlns="http://example.com/test-2">Some text</test> <text> Some text in another namespace with space at the start and end and a carrage return </text> </test> 1.1 xml-xindice/java/tests/src/org/apache/xindice/integration/client/basic/testdocs/namespace-changingprefixes.xml Index: namespace-changingprefixes.xml =================================================================== <?xml version="1.0"?> <test:test xmlns:test="http://example.com/test-1"> <test:test xmlns:test="http://example.com/test-2"> <test:test xmlns:test="http://example.com/test-1">confused yet?</test:test> </test:test> <test:text> Some text in another namespace with space at the start and end and a carrage return </test:text> </test:test> 1.1 xml-xindice/java/tests/src/org/apache/xindice/integration/client/basic/testdocs/namespace-simpleprefixes.xml Index: namespace-simpleprefixes.xml =================================================================== <?xml version="1.0"?> <test:test xmlns:test="http://example.com/test-1"> <test2:test xmlns:test2="http://example.com/test-2">Some text</test2:test> <test:text> Some text in another namespace with space at the start and end and a carrage return </test:text> </test:test> 1.1 xml-xindice/java/lib/xmlunit-1.0.jar <<Binary file>> 1.1 xml-xindice/java/lib/xmlunit-1.0.LICENSE Index: xmlunit-1.0.LICENSE =================================================================== /* ****************************************************************** Copyright (c) 2001, Jeff Martin, Tim Bacon All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * 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. * Neither the name of the xmlunit.sourceforge.net 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. ****************************************************************** */ 1.7 +2 -2 xml-xindice/java/src/org/apache/xindice/core/filer/FSFiler.java Index: FSFiler.java =================================================================== RCS file: /home/cvs/xml-xindice/java/src/org/apache/xindice/core/filer/FSFiler.java,v retrieving revision 1.6 retrieving revision 1.7 diff -u -r1.6 -r1.7 --- FSFiler.java 31 Oct 2002 06:59:57 -0000 1.6 +++ FSFiler.java 14 Jul 2003 13:58:17 -0000 1.7 @@ -185,7 +185,7 @@ try { locks.acquireSharedLock(file); - HashMap meta = new HashMap(1); + HashMap meta = new HashMap(2); meta.put(Record.MODIFIED, new Long(file.lastModified())); byte[] valueData = cache.getFile(file); 1.13 +16 -7 xml-xindice/java/src/org/apache/xindice/client/xmldb/resources/XMLResourceImpl.java Index: XMLResourceImpl.java =================================================================== RCS file: /home/cvs/xml-xindice/java/src/org/apache/xindice/client/xmldb/resources/XMLResourceImpl.java,v retrieving revision 1.12 retrieving revision 1.13 diff -u -r1.12 -r1.13 --- XMLResourceImpl.java 19 Nov 2002 05:36:55 -0000 1.12 +++ XMLResourceImpl.java 14 Jul 2003 13:58:17 -0000 1.13 @@ -109,18 +109,28 @@ /** * This is a SAX feature that controls how namespaces are reported in SAX. - * By default this feature is <em>on</em>. + * By default this feature is <em>off</em>. * * @see <a href="http://sax.sourceforge.net/?selected=namespaces">sax.sourceforge.net/?selected=namespaces</a> */ public static final String SAX_NAMESPACE_PREFIXES_FEATURE = SAXEventGenerator.SAX_NAMESPACE_PREFIXES_FEATURE; - /* Is the SAX namespaces feature turned on for this generator? */ + /* + * State of the SAX_NAMESPACES_FEATURE. True indicates namespace URIs and unprefixed local + * names for element and attribute names will be available. + * + * For SAX2 the default is true. + */ private boolean hasSaxNamespaces = true; - /* Is the SAX namespaces-prefixes feature turned on for this generator? */ - private boolean hasSaxNamespacesPrefixes = true; + /* + * State of the SAX_NAMESPACE_PREFIXES_FEATURE. True indicates XML 1.0 names (with prefixes) + * and attributes (including xmlns* attributes) will be available. + * + * For SAX2 the default is off. + */ + private boolean hasSaxNamespacesPrefixes = false; private SymbolTable symbols = null; private byte[] bytes = null; @@ -388,8 +398,7 @@ SAXEventGenerator events = new SAXEventGenerator(symbols, bytes); events.setFeature(SAX_NAMESPACES_FEATURE, hasSaxNamespaces); - events.setFeature(SAX_NAMESPACE_PREFIXES_FEATURE, - hasSaxNamespacesPrefixes); + events.setFeature(SAX_NAMESPACE_PREFIXES_FEATURE, hasSaxNamespacesPrefixes); events.setContentHandler(handler); if (handler instanceof ErrorHandler) { 1.19 +17 -7 xml-xindice/java/src/org/apache/xindice/xml/sax/SAXEventGenerator.java Index: SAXEventGenerator.java =================================================================== RCS file: /home/cvs/xml-xindice/java/src/org/apache/xindice/xml/sax/SAXEventGenerator.java,v retrieving revision 1.18 retrieving revision 1.19 diff -u -r1.18 -r1.19 --- SAXEventGenerator.java 25 Dec 2002 14:22:45 -0000 1.18 +++ SAXEventGenerator.java 14 Jul 2003 13:58:17 -0000 1.19 @@ -96,7 +96,7 @@ /** * This is a SAX feature that controls how namespaces are reported in SAX. - * By default this feature is <em>on</em>. + * In accordance with the SAX2 specification by default this feature is <em>on</em>. * * @see <a href="http://sax.sourceforge.net/?selected=namespaces">sax.sourceforge.net/?selected=namespaces</a> */ @@ -105,18 +105,28 @@ /** * This is a SAX feature that controls how namespaces are reported in SAX. - * By default this feature is <em>on</em>. + * In accordance with the SAX2 specification by default this feature is <em>off</em>. * * @see <a href="http://sax.sourceforge.net/?selected=namespaces">sax.sourceforge.net/?selected=namespaces</a> */ public static final String SAX_NAMESPACE_PREFIXES_FEATURE = "http://xml.org/sax/features/namespace-prefixes"; - /* Is the SAX namespaces feature turned on for this generator? */ + /* + * State of the SAX_NAMESPACES_FEATURE. True indicates namespace URIs and unprefixed local + * names for element and attribute names will be available. + * + * For SAX2 the default is true. + */ private boolean hasSaxNamespaces = true; - /* Is the SAX namespaces-prefixes feature turned on for this generator? */ - private boolean hasSaxNamespacesPrefixes = true; + /* + * State of the SAX_NAMESPACE_PREFIXES_FEATURE. True indicates XML 1.0 names (with prefixes) + * and attributes (including xmlns* attributes) will be available. + * + * For SAX2 the default is off. + */ + private boolean hasSaxNamespacesPrefixes = false; private SymbolTable symbols = null; @@ -271,7 +281,7 @@ return qname; } - private final boolean isNSAttr(String qName) { + private final boolean isNSAttr(final String qName) { return (("xmlns".equals(qName)) || qName.startsWith("xmlns:")); } 1.48 +27 -1 xml-xindice/build.xml Index: build.xml =================================================================== RCS file: /home/cvs/xml-xindice/build.xml,v retrieving revision 1.47 retrieving revision 1.48 diff -u -r1.47 -r1.48 --- build.xml 14 Jul 2003 13:40:28 -0000 1.47 +++ build.xml 14 Jul 2003 13:58:18 -0000 1.48 @@ -80,6 +80,8 @@ <include name="junit-addons-1.2.jar"/> <include name="junitperf-1.8.jar"/> <include name="servlet-2.3.jar"/> + <include name="xmlunit-1.0.jar"/> + <include name="clover-1.2.jar"/> </fileset> <!-- classpath to use within project --> <path id="project.class.path"> @@ -159,6 +161,9 @@ <path refid="project.class.path"/> </classpath> </javac> + <copy todir="${test.build.dir}"> + <fileset dir="${test.src.dir}" excludes="*.java"/> + </copy> </target> <target name="test-all" depends="test-unit, test-embed-binary, test-integration-embed, test-integration-xmlrpc, test-integration-managed"/> <target name="test-unit" depends="test-build, test-validate"> @@ -384,4 +389,25 @@ <delete dir="${api.dir}"/> </target> <target name="gump-target" depends="release"/> + + <!-- clover --> + <!-- + <taskdef resource="clovertasks"/> + + <target name="with.clover"> + <clover-setup initString="${build.dir}/coverage.db"/> + </target> + + <target name="clover.report.html" depends="with.clover"> + <clover-report> + <current outfile="clover_html"> + <format type="html"/> + </current> + </clover-report> + </target> + + <target name="clover.view" depends="with.clover"> + <clover-view/> + </target> + --> </project> 1.6 +5 -4 xml-xindice/.classpath Index: .classpath =================================================================== RCS file: /home/cvs/xml-xindice/.classpath,v retrieving revision 1.5 retrieving revision 1.6 diff -u -r1.5 -r1.6 --- .classpath 5 Jun 2003 04:01:45 -0000 1.5 +++ .classpath 14 Jul 2003 13:58:18 -0000 1.6 @@ -1,9 +1,9 @@ <?xml version="1.0" encoding="UTF-8"?> <classpath> <classpathentry kind="src" path="java/src"/> - <classpathentry kind="src" path="java/tests/src"/> - <classpathentry kind="src" path="java/examples/Addressbook/src/java"/> - <classpathentry kind="src" path="java/examples/guide/src"/> + <classpathentry kind="src" output="build/classes-tests" path="java/tests/src"/> + <classpathentry kind="src" output="build/classes-address" path="java/examples/Addressbook/src/java"/> + <classpathentry kind="src" output="build/classes-guide" path="java/examples/guide/src"/> <classpathentry exported="true" kind="var" path="JRE_LIB" sourcepath="JRE_SRC"/> <classpathentry exported="true" kind="lib" path="java/lib/ant-1.5.1.jar"/> <classpathentry exported="true" kind="lib" path="java/lib/commons-logging-1.0.1.jar"/> @@ -19,5 +19,6 @@ <classpathentry exported="true" kind="lib" path="java/lib/xml-apis-1.1.jar"/> <classpathentry exported="true" kind="lib" path="java/lib/junit-addons-1.2.jar"/> <classpathentry exported="true" kind="lib" path="java/lib/servlet-2.3.jar"/> - <classpathentry kind="output" path="classes"/> + <classpathentry kind="lib" path="java/lib/xmlunit-1.0.jar"/> + <classpathentry kind="output" path="build/classes"/> </classpath> 1.5 +183 -8 xml-xindice/java/tests/src/org/apache/xindice/integration/client/basic/DocumentTest.java Index: DocumentTest.java =================================================================== RCS file: /home/cvs/xml-xindice/java/tests/src/org/apache/xindice/integration/client/basic/DocumentTest.java,v retrieving revision 1.4 retrieving revision 1.5 diff -u -r1.4 -r1.5 --- DocumentTest.java 10 Jul 2003 14:43:51 -0000 1.4 +++ DocumentTest.java 14 Jul 2003 13:58:18 -0000 1.5 @@ -59,10 +59,22 @@ package org.apache.xindice.integration.client.basic; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; import java.io.StringWriter; +import java.io.Writer; + +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.parsers.SAXParserFactory; import org.apache.xindice.integration.client.AbstractXmlDbClientTest; -import org.apache.xml.serialize.XMLSerializer; +import org.apache.xindice.tools.command.StringSerializer; +import org.custommonkey.xmlunit.XMLAssert; +import org.xml.sax.ContentHandler; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; +import org.xml.sax.XMLReader; import org.xmldb.api.base.XMLDBException; /** @@ -118,7 +130,7 @@ String doc = this.client.getDocument(TEST_COLLECTION_PATH, "doc1"); assertNotNull(doc); - assertEquals(testDocument, doc); + assertXMLEqual(testDocument, doc); this.client.removeDocument(TEST_COLLECTION_PATH, "doc1"); } @@ -127,15 +139,14 @@ String testDocument = "<?xml version=\"1.0\"?>\n<data><test>test data</test></data>"; this.client.insertDocument(TEST_COLLECTION_PATH, "doc1", testDocument); - StringWriter out = new StringWriter(); - XMLSerializer serializer = new XMLSerializer(); - serializer.setOutputCharStream(out); + final StringWriter out = new StringWriter(); + final ContentHandler serializer = createSerializer(out); this.client.getDocumentAsSax(TEST_COLLECTION_PATH, "doc1", serializer); String doc = out.toString(); assertNotNull(doc); - assertEquals(testDocument, doc); + assertXMLEqual(testDocument, doc); this.client.removeDocument(TEST_COLLECTION_PATH, "doc1"); } @@ -200,5 +211,169 @@ this.client.removeDocument(TEST_COLLECTION_PATH, "doc2"); assertEquals(0, this.client.countDocument(TEST_COLLECTION_PATH)); } + + public void testDocumentWithNameSpaces() throws Exception + { + assertEquals(0, this.client.countDocument(TEST_COLLECTION_PATH)); + + final String testDocument = fetchTestDocument("namespaces.xml"); + this.client.insertDocument(TEST_COLLECTION_PATH, "namespaces.xml", testDocument); + + String doc = this.client.getDocument(TEST_COLLECTION_PATH, "namespaces.xml"); + assertNotNull(doc); + assertXMLEqual(testDocument, doc); + + this.client.removeDocument(TEST_COLLECTION_PATH, "namespaces.xml"); + assertEquals(0, this.client.countDocument(TEST_COLLECTION_PATH)); + } + + public void testDocumentWithNameSpacesSAX() throws Exception + { + assertEquals(0, this.client.countDocument(TEST_COLLECTION_PATH)); + + final String testDocument = fetchTestDocument("namespaces.xml"); + this.client.insertDocument(TEST_COLLECTION_PATH, "namespaces.xml", testDocument); + + final StringWriter out = new StringWriter(); + final ContentHandler serializer = createSerializer(out); + + this.client.getDocumentAsSax(TEST_COLLECTION_PATH, "namespaces.xml", serializer); + String doc = out.toString(); + + assertNotNull(doc); + assertXMLEqual(testDocument, doc); + this.client.removeDocument(TEST_COLLECTION_PATH, "namespaces.xml"); + assertEquals(0, this.client.countDocument(TEST_COLLECTION_PATH)); + } + + public void testDocumentWithSimpleNameSpacePrefixes() throws Exception + { + assertEquals(0, this.client.countDocument(TEST_COLLECTION_PATH)); + + final String testDocument = fetchTestDocument("namespace-simpleprefixes.xml"); + this.client.insertDocument(TEST_COLLECTION_PATH, "namespaces.xml", testDocument); + + String doc = this.client.getDocument(TEST_COLLECTION_PATH, "namespaces.xml"); + assertNotNull(doc); + assertXMLEqual(testDocument, doc); + + this.client.removeDocument(TEST_COLLECTION_PATH, "namespaces.xml"); + assertEquals(0, this.client.countDocument(TEST_COLLECTION_PATH)); + } + + public void testDocumentWithSimpleNameSpacePrefixesSAX() throws Exception + { + assertEquals(0, this.client.countDocument(TEST_COLLECTION_PATH)); + + final String testDocument = fetchTestDocument("namespace-simpleprefixes.xml"); + this.client.insertDocument(TEST_COLLECTION_PATH, "namespaces.xml", testDocument); + + final StringWriter out = new StringWriter(); + final ContentHandler serializer = createSerializer(out); + + this.client.getDocumentAsSax(TEST_COLLECTION_PATH, "namespaces.xml", serializer); + String doc = out.toString(); + + assertNotNull(doc); + assertXMLEqual(testDocument, doc); + + this.client.removeDocument(TEST_COLLECTION_PATH, "namespaces.xml"); + assertEquals(0, this.client.countDocument(TEST_COLLECTION_PATH)); + } + + public void testDocumentWithChangingNameSpacePrefixes() throws Exception + { + assertEquals(0, this.client.countDocument(TEST_COLLECTION_PATH)); + + final String testDocument = fetchTestDocument("namespace-changingprefixes.xml"); + this.client.insertDocument(TEST_COLLECTION_PATH, "namespaces.xml", testDocument); + + String doc = this.client.getDocument(TEST_COLLECTION_PATH, "namespaces.xml"); + assertNotNull(doc); + assertXMLEqual(testDocument, doc); + + this.client.removeDocument(TEST_COLLECTION_PATH, "namespaces.xml"); + assertEquals(0, this.client.countDocument(TEST_COLLECTION_PATH)); + } + + public void testDocumentWithChangingNameSpacePrefixesSAX() throws Exception + { + assertEquals(0, this.client.countDocument(TEST_COLLECTION_PATH)); + + final String testDocument = fetchTestDocument("namespace-changingprefixes.xml"); + this.client.insertDocument(TEST_COLLECTION_PATH, "namespaces.xml", testDocument); + + final StringWriter out = new StringWriter(); + final ContentHandler serializer = createSerializer(out); + + this.client.getDocumentAsSax(TEST_COLLECTION_PATH, "namespaces.xml", serializer); + String doc = out.toString(); + + assertNotNull(doc); + assertXMLEqual(testDocument, doc); + + this.client.removeDocument(TEST_COLLECTION_PATH, "namespaces.xml"); + assertEquals(0, this.client.countDocument(TEST_COLLECTION_PATH)); + } + + private String fetchTestDocument(String name) throws IOException, SAXException, ParserConfigurationException + { + final StringWriter out = new StringWriter(); + final ContentHandler serializer = createSerializer(out); + + parseTestDocument(name, serializer); + + return out.toString(); + } + + private void parseTestDocument(String name, ContentHandler handler) throws IOException, SAXException, ParserConfigurationException + { + InputStream in = getClass().getResourceAsStream("testdocs/" + name); + + if (null == in) + { + throw new FileNotFoundException("The resource " + name + " could not be found"); + } + + final SAXParserFactory factory = SAXParserFactory.newInstance(); + factory.setNamespaceAware(true); + + final XMLReader saxReader = factory.newSAXParser().getXMLReader(); + + saxReader.setContentHandler(handler); + saxReader.parse(new InputSource(in)); + } + + private ContentHandler createSerializer(final Writer out) + { + final ContentHandler serializer = new StringSerializer() + { + public void endDocument() throws SAXException + { + super.endDocument(); + + try + { + out.write(this.toString()); + out.flush(); + } + catch (IOException e) + { + throw new RuntimeException("Unexpected IO exception", e); + } + } + }; + + return serializer; + } + + protected void assertXMLEqual(String control, String result) throws Exception + { + try { + XMLAssert.assertXMLEqual(control, result); + } catch (SAXException e) { + fail(e.getLocalizedMessage()); + } + } } 1.6 +10 -1 xml-xindice/java/src/org/apache/xindice/tools/command/StringSerializer.java Index: StringSerializer.java =================================================================== RCS file: /home/cvs/xml-xindice/java/src/org/apache/xindice/tools/command/StringSerializer.java,v retrieving revision 1.5 retrieving revision 1.6 diff -u -r1.5 -r1.6 --- StringSerializer.java 21 Nov 2002 07:44:36 -0000 1.5 +++ StringSerializer.java 14 Jul 2003 13:58:18 -0000 1.6 @@ -93,6 +93,15 @@ /* the document so far */ private StringBuffer outputXml; + /** + * Creates new <code>StringSerializer</code>. The output encoding is not specified therefor + * will be treated as "UTF-8". + */ + public StringSerializer() + { + this(null); + } + /** * Creates new <code>StringSerializer</code>. * @@ -107,7 +116,7 @@ public StringSerializer(String outputEncoding) { this.outputEncoding = outputEncoding; - outputXml = new StringBuffer(); + outputXml = new StringBuffer(1024); // allocate a 1k block to start with namespaceMap = new HashMap(); namespaceDecls = new StringBuffer(); inCDATA = false;