[izpack-devel] Adding XInclude support

Matthew Fudge matfud at yahoo.com
Thu Dec 13 17:03:33 CET 2007


Index: src/tests/net/n3/nanoxml/xinclude/XIncludeXMLBuilderTestCase.java
===================================================================
--- src/tests/net/n3/nanoxml/xinclude/XIncludeXMLBuilderTestCase.java    (revision 0)
+++ src/tests/net/n3/nanoxml/xinclude/XIncludeXMLBuilderTestCase.java    (revision 0)
@@ -0,0 +1,217 @@
+/*
+ * Copyright 2007 Volantis Systems Ltd., All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package net.n3.nanoxml.xinclude;
+
+import junit.framework.TestCase;
+import net.n3.nanoxml.IXMLReader;
+import net.n3.nanoxml.NonValidator;
+import net.n3.nanoxml.StdXMLParser;
+import net.n3.nanoxml.StdXMLReader;
+import net.n3.nanoxml.XMLBuilderFactory;
+import net.n3.nanoxml.XMLElement;
+
+import java.util.Enumeration;
+
+/**
+ * Test the XInclude style functionality added to the XMLBuilder
+ */
+public class XIncludeXMLBuilderTestCase extends TestCase {
+
+
+    /**
+     * This method takes the fileBase name and attempts to find two files
+     * called <fileBase>-input.xml and <fileBase>-expected.xml
+     *
+     * @param fileBase the base of the test file names
+     * @throws Exception
+     */
+    public void doTest(String fileBase) throws Exception {
+
+        String baseURL = getClass().getResource(fileBase + "-input.xml").toExternalForm();
+        // set up a new parser to parse the input xml (with includes)
+        StdXMLParser inputParser = new StdXMLParser();
+        inputParser.setBuilder(XMLBuilderFactory.createXMLBuilder());
+        IXMLReader inputReader = new StdXMLReader(
+            getClass().getResourceAsStream(fileBase + "-input.xml"));
+        inputReader.setSystemID(baseURL);
+        inputParser.setReader(inputReader);
+        inputParser.setValidator(new NonValidator());
+
+        // set up a new parser to parse the expected xml (without includes)
+        StdXMLParser expectedParser = new StdXMLParser();
+        expectedParser.setBuilder(XMLBuilderFactory.createXMLBuilder());
+        IXMLReader expectedReader = new StdXMLReader(
+            getClass().getResourceAsStream(fileBase + "-expect.xml"));
+        expectedReader.setSystemID(baseURL);
+        expectedParser.setReader(expectedReader);
+        expectedParser.setValidator(new NonValidator());
+
+        XMLElement inputElement = (XMLElement) inputParser.parse();
+        XMLElement expectedElement = (XMLElement) expectedParser.parse();
+
+        deepEqual(expectedElement, inputElement);
+        
+    }
+
+    /**
+     * This method is used to ensure that the contents of the specified file
+     * (when having "-input.xml" appended) cause the parser to fail
+     *
+     * @param fileBase the base name of the input file.
+     * @throws Exception
+     */
+    public void ensureFailure(String fileBase) throws Exception {
+        try {
+            String baseURL = getClass().getResource(fileBase + "-input.xml").toExternalForm();
+            // set up a new parser to parse the input xml (with includes)
+            StdXMLParser inputParser = new StdXMLParser();
+            inputParser.setBuilder(XMLBuilderFactory.createXMLBuilder());
+            IXMLReader inputReader = new StdXMLReader(
+                getClass().getResourceAsStream(fileBase + "-input.xml"));
+            inputReader.setSystemID(baseURL);
+            inputParser.setReader(inputReader);
+            inputParser.setValidator(new NonValidator());
+
+            inputParser.parse();
+            fail("an exception should have been thrown");
+        } catch (Throwable t) {
+            // success
+        }
+    }
+
+    /**
+     * Perform a deep equality check on the two nodes.
+     *
+     */
+    public void deepEqual(XMLElement a, XMLElement b) {
+
+        assertEquals("element names", a.getName(), b.getName());
+        assertEquals("element attributes for "+ a.getName(),
+            a.getAttributes(), b.getAttributes());
+        assertEquals("content for " + a.getName(),
+            a.getContent(), b.getContent());
+        assertEquals("equal number of children" + a.getName(),
+            a.getChildrenCount(), b.getChildrenCount());
+
+        Enumeration aChildren = a.enumerateChildren();
+        Enumeration bChildren = b.enumerateChildren();
+        while (aChildren.hasMoreElements()) {
+            XMLElement aChild = (XMLElement) aChildren.nextElement();
+            XMLElement bChild = (XMLElement) bChildren.nextElement();
+            deepEqual(aChild,  bChild);
+        }
+    }
+
+    /**
+     * Test Empty document with include
+     * @throws Exception
+     */
+    public void testIncludeOnly() throws Exception {
+       doTest("include-only");
+    }
+
+    /**
+     * Test that a fragment included as the root node does not have the
+     * "fragment" element removed
+     * @throws Exception
+     */
+    public void testIncludeFragmentOnly() throws Exception {
+        doTest("include-fragment-only");
+    }
+
+    /**
+     * Test to ensure that content is correctly included when the include
+     * element is not the root element
+     * @throws Exception
+     */
+    public void testIncludeInElement() throws Exception {
+        doTest("include-in-element");
+    }
+
+    /**
+     * Test to ensure that content is correctly included when the include
+     * element is not the root element
+     * @throws Exception
+     */
+    public void testIncludeFragmentInElement() throws Exception {
+        doTest("include-fragment-in-element");
+    }
+
+    /**
+     * Test text inclusion
+     * @throws Exception
+     */
+    public void testIncludeTextInElement() throws Exception {
+        doTest("include-fragment-in-element");
+    }
+
+    /**
+     * Ensure that the parse attribute accepts "text" and treats it like text
+     * @throws Exception
+     */
+    public void testParseAttributeText() throws Exception {
+       doTest("include-xml-as-text");
+    }
+
+    /**
+     * Ensure that the parse attribute accepts "xml" and treats like xml
+     * (most other tests do not explicitly set the parse parameter and let it
+     * default to "xml"
+     * @throws Exception
+     */
+    public void testParseAttributeXML() throws Exception {
+       doTest("include-xml-as-xml");
+    }
+
+    /**
+     * Make sure that a failure occurs for a parse valid that is not "xml"
+     * or "text"
+     *
+     * @throws Exception
+     */
+    public void testParseInvalidAttribute() throws Exception {
+        ensureFailure("invalid-parse-attrib");
+    }
+
+    /**
+     * Ensure fallbacks work correctly
+     *
+     * @throws Exception
+     */
+    public void testFallback() throws Exception {
+        doTest("fallback");
+    }
+
+    /**
+     * Test that an empty fallback just removes the include and fallback
+     * elements
+     *
+     * @throws Exception
+     */
+    public void testEmptyFallback() throws Exception {
+        doTest("empty-fallback");
+    }
+
+    /**
+     * Ensure that two includes in the same element both get included
+     * @throws Exception
+     */
+    public void testMultipleIncludes() throws Exception {
+        doTest("multiple-include");        
+    }
+
+
+}
Index: src/tests/net/n3/nanoxml/xinclude/empty-fallback-expect.xml
===================================================================
--- src/tests/net/n3/nanoxml/xinclude/empty-fallback-expect.xml    (revision 0)
+++ src/tests/net/n3/nanoxml/xinclude/empty-fallback-expect.xml    (revision 0)
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="iso-8859-1" standalone="yes" ?>
+<aaa>
+</aaa>
\ No newline at end of file
Index: src/tests/net/n3/nanoxml/xinclude/fallback-expect.xml
===================================================================
--- src/tests/net/n3/nanoxml/xinclude/fallback-expect.xml    (revision 0)
+++ src/tests/net/n3/nanoxml/xinclude/fallback-expect.xml    (revision 0)
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="iso-8859-1" standalone="yes" ?>
+<aaa>
+    [<bbb/>
+</aaa>
\ No newline at end of file
Index: src/tests/net/n3/nanoxml/xinclude/include-only-expect.xml
===================================================================
--- src/tests/net/n3/nanoxml/xinclude/include-only-expect.xml    (revision 0)
+++ src/tests/net/n3/nanoxml/xinclude/include-only-expect.xml    (revision 0)
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="iso-8859-1" standalone="yes" ?>
+<eeee>
+    <ffff>
+        <gggg>hello</gggg>
+    </ffff>
+
+    <hhhh>
+        <iiii>there</iiii>
+    </hhhh>
+</eeee>
\ No newline at end of file
Index: src/tests/net/n3/nanoxml/xinclude/empty-fallback-input.xml
===================================================================
--- src/tests/net/n3/nanoxml/xinclude/empty-fallback-input.xml    (revision 0)
+++ src/tests/net/n3/nanoxml/xinclude/empty-fallback-input.xml    (revision 0)
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="iso-8859-1" standalone="yes" ?>
+<aaa>
+    <xinclude href="does-not-exist.xml">
+        <xfallback/>           
+    </xinclude>
+</aaa>
\ No newline at end of file
Index: src/tests/net/n3/nanoxml/xinclude/include-fragment-only-expect.xml
===================================================================
--- src/tests/net/n3/nanoxml/xinclude/include-fragment-only-expect.xml    (revision 0)
+++ src/tests/net/n3/nanoxml/xinclude/include-fragment-only-expect.xml    (revision 0)
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="iso-8859-1" standalone="yes" ?>
+<xfragment>
+    <ffff>
+        <gggg>hello</gggg>
+    </ffff>
+
+    <hhhh>
+        <iiii>there</iiii>
+    </hhhh>
+</xfragment>
\ No newline at end of file
Index: src/tests/net/n3/nanoxml/xinclude/include-xml-as-text-expect.xml
===================================================================
--- src/tests/net/n3/nanoxml/xinclude/include-xml-as-text-expect.xml    (revision 0)
+++ src/tests/net/n3/nanoxml/xinclude/include-xml-as-text-expect.xml    (revision 0)
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="iso-8859-1" standalone="yes" ?>
+<aaa>
+<![CDATA[<?xml version="1.0" encoding="iso-8859-1" standalone="yes" ?>
+<eeee>
+    <ffff>
+        <gggg>hello</gggg>
+    </ffff>
+
+    <hhhh>
+        <iiii>there</iiii>
+    </hhhh>
+</eeee>]]>
+</aaa>
\ No newline at end of file
Index: src/tests/net/n3/nanoxml/xinclude/include-text-expect.xml
===================================================================
--- src/tests/net/n3/nanoxml/xinclude/include-text-expect.xml    (revision 0)
+++ src/tests/net/n3/nanoxml/xinclude/include-text-expect.xml    (revision 0)
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="iso-8859-1" standalone="yes" ?>
+<a>
+This is some sample text that should be included
+</a>
\ No newline at end of file
Index: src/tests/net/n3/nanoxml/xinclude/fallback-input.xml
===================================================================
--- src/tests/net/n3/nanoxml/xinclude/fallback-input.xml    (revision 0)
+++ src/tests/net/n3/nanoxml/xinclude/fallback-input.xml    (revision 0)
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="iso-8859-1" standalone="yes" ?>
+<aaa>
+    <xinclude href="does-not-exist.xml">
+        <xfallback>
+            <![CDATA[<bbb/>]]>
+        </xfallback>
+    </xinclude>
+</aaa>
\ No newline at end of file
Index: src/tests/net/n3/nanoxml/xinclude/include-only-input.xml
===================================================================
--- src/tests/net/n3/nanoxml/xinclude/include-only-input.xml    (revision 0)
+++ src/tests/net/n3/nanoxml/xinclude/include-only-input.xml    (revision 0)
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="iso-8859-1" standalone="yes" ?>
+<xinclude href="content.xml"/>
\ No newline at end of file
Index: src/tests/net/n3/nanoxml/xinclude/include-fragment-only-input.xml
===================================================================
--- src/tests/net/n3/nanoxml/xinclude/include-fragment-only-input.xml    (revision 0)
+++ src/tests/net/n3/nanoxml/xinclude/include-fragment-only-input.xml    (revision 0)
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="iso-8859-1" standalone="yes" ?>
+<xinclude href="content-fragment.xml"/> 
\ No newline at end of file
Index: src/tests/net/n3/nanoxml/xinclude/include-xml-as-text-input.xml
===================================================================
--- src/tests/net/n3/nanoxml/xinclude/include-xml-as-text-input.xml    (revision 0)
+++ src/tests/net/n3/nanoxml/xinclude/include-xml-as-text-input.xml    (revision 0)
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="iso-8859-1" standalone="yes" ?>
+<aaa>
+    <xinclude href="content.xml" parse="text"/>
+</aaa>
\ No newline at end of file
Index: src/tests/net/n3/nanoxml/xinclude/include-text-input.xml
===================================================================
--- src/tests/net/n3/nanoxml/xinclude/include-text-input.xml    (revision 0)
+++ src/tests/net/n3/nanoxml/xinclude/include-text-input.xml    (revision 0)
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="iso-8859-1" standalone="yes" ?>
+<a>
+    <xinclude href="text.txt" parse="text"/>
+</a>
\ No newline at end of file
Index: src/tests/net/n3/nanoxml/xinclude/multiple-include-expect.xml
===================================================================
--- src/tests/net/n3/nanoxml/xinclude/multiple-include-expect.xml    (revision 0)
+++ src/tests/net/n3/nanoxml/xinclude/multiple-include-expect.xml    (revision 0)
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="iso-8859-1" standalone="yes" ?>
+<aaaa>
+    <ffff>
+        <gggg>hello</gggg>
+    </ffff>
+
+    <hhhh>
+        <iiii>there</iiii>
+    </hhhh>
+    <ffff>
+        <gggg>hello</gggg>
+    </ffff>
+
+    <hhhh>
+        <iiii>there</iiii>
+    </hhhh>
+</aaaa>
\ No newline at end of file
Index: src/tests/net/n3/nanoxml/xinclude/text.txt
===================================================================
--- src/tests/net/n3/nanoxml/xinclude/text.txt    (revision 0)
+++ src/tests/net/n3/nanoxml/xinclude/text.txt    (revision 0)
@@ -0,0 +1 @@
+This is some sample text that should be included
\ No newline at end of file
Index: src/tests/net/n3/nanoxml/xinclude/include-in-element-expect.xml
===================================================================
--- src/tests/net/n3/nanoxml/xinclude/include-in-element-expect.xml    (revision 0)
+++ src/tests/net/n3/nanoxml/xinclude/include-in-element-expect.xml    (revision 0)
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="iso-8859-1" standalone="yes" ?>
+<bob>
+    <eeee>
+        <ffff>
+            <gggg>hello</gggg>
+        </ffff>
+
+        <hhhh>
+            <iiii>there</iiii>
+        </hhhh>
+    </eeee>
+</bob>
\ No newline at end of file
Index: src/tests/net/n3/nanoxml/xinclude/include-fragment-in-element-expect.xml
===================================================================
--- src/tests/net/n3/nanoxml/xinclude/include-fragment-in-element-expect.xml    (revision 0)
+++ src/tests/net/n3/nanoxml/xinclude/include-fragment-in-element-expect.xml    (revision 0)
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="iso-8859-1" standalone="yes" ?>
+<bob>
+    <ffff>
+        <gggg>hello</gggg>
+    </ffff>
+
+    <hhhh>
+        <iiii>there</iiii>
+    </hhhh>
+</bob>
\ No newline at end of file
Index: src/tests/net/n3/nanoxml/xinclude/include-xml-as-xml-expect.xml
===================================================================
--- src/tests/net/n3/nanoxml/xinclude/include-xml-as-xml-expect.xml    (revision 0)
+++ src/tests/net/n3/nanoxml/xinclude/include-xml-as-xml-expect.xml    (revision 0)
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="iso-8859-1" standalone="yes" ?>
+<aaa>
+    <eeee>
+        <ffff>
+            <gggg>hello</gggg>
+        </ffff>
+
+        <hhhh>
+            <iiii>there</iiii>
+        </hhhh>
+    </eeee>
+</aaa>
\ No newline at end of file
Index: src/tests/net/n3/nanoxml/xinclude/multiple-include-input.xml
===================================================================
--- src/tests/net/n3/nanoxml/xinclude/multiple-include-input.xml    (revision 0)
+++ src/tests/net/n3/nanoxml/xinclude/multiple-include-input.xml    (revision 0)
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="iso-8859-1" standalone="yes" ?>
+<aaaa>
+    <xinclude href="content-fragment.xml"/>
+    <xinclude href="content-fragment.xml"/>
+</aaaa>
\ No newline at end of file
Index: src/tests/net/n3/nanoxml/xinclude/content.xml
===================================================================
--- src/tests/net/n3/nanoxml/xinclude/content.xml    (revision 0)
+++ src/tests/net/n3/nanoxml/xinclude/content.xml    (revision 0)
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="iso-8859-1" standalone="yes" ?>
+<eeee>
+    <ffff>
+        <gggg>hello</gggg>
+    </ffff>
+
+    <hhhh>
+        <iiii>there</iiii>
+    </hhhh>
+</eeee>
\ No newline at end of file
Index: src/tests/net/n3/nanoxml/xinclude/content-fragment.xml
===================================================================
--- src/tests/net/n3/nanoxml/xinclude/content-fragment.xml    (revision 0)
+++ src/tests/net/n3/nanoxml/xinclude/content-fragment.xml    (revision 0)
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="iso-8859-1" standalone="yes" ?>
+<xfragment>
+    <ffff>
+        <gggg>hello</gggg>
+    </ffff>
+
+    <hhhh>
+        <iiii>there</iiii>
+    </hhhh>
+</xfragment>
\ No newline at end of file
Index: src/tests/net/n3/nanoxml/xinclude/include-in-element-input.xml
===================================================================
--- src/tests/net/n3/nanoxml/xinclude/include-in-element-input.xml    (revision 0)
+++ src/tests/net/n3/nanoxml/xinclude/include-in-element-input.xml    (revision 0)
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="iso-8859-1" standalone="yes" ?>
+<bob>
+    <xinclude href="content.xml"/>
+</bob>
\ No newline at end of file
Index: src/tests/net/n3/nanoxml/xinclude/include-fragment-in-element-input.xml
===================================================================
--- src/tests/net/n3/nanoxml/xinclude/include-fragment-in-element-input.xml    (revision 0)
+++ src/tests/net/n3/nanoxml/xinclude/include-fragment-in-element-input.xml    (revision 0)
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="iso-8859-1" standalone="yes" ?>
+<bob>
+    <xinclude href="content-fragment.xml"/>
+</bob>
\ No newline at end of file
Index: src/tests/net/n3/nanoxml/xinclude/include-xml-as-xml-input.xml
===================================================================
--- src/tests/net/n3/nanoxml/xinclude/include-xml-as-xml-input.xml    (revision 0)
+++ src/tests/net/n3/nanoxml/xinclude/include-xml-as-xml-input.xml    (revision 0)
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="iso-8859-1" standalone="yes" ?>
+<aaa>
+    <xinclude href="content.xml" parse="xml"/>
+</aaa>
\ No newline at end of file
Index: src/tests/net/n3/nanoxml/xinclude/invalid-parse-attrib-input.xml
===================================================================
--- src/tests/net/n3/nanoxml/xinclude/invalid-parse-attrib-input.xml    (revision 0)
+++ src/tests/net/n3/nanoxml/xinclude/invalid-parse-attrib-input.xml    (revision 0)
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="iso-8859-1" standalone="yes" ?>
+<aaa>
+    <xinclude href="content.xml" parse="invalid"/>
+</aaa>
\ No newline at end of file
Index: src/lib/net/n3/nanoxml/XMLBuilderFactory.java
===================================================================
--- src/lib/net/n3/nanoxml/XMLBuilderFactory.java    (revision 0)
+++ src/lib/net/n3/nanoxml/XMLBuilderFactory.java    (revision 0)
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2007 Volantis Systems Ltd., All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package net.n3.nanoxml;
+
+/**
+ * Simple factory for creating builders
+ */
+public class XMLBuilderFactory {
+
+    /**
+     * Return an IXMLBuilder instance
+     *
+     * @return an IXMLBuilder instance
+     */
+    public static IXMLBuilder createXMLBuilder() {
+        return new XIncludeXMLBuilder();
+    }
+}
Index: src/lib/net/n3/nanoxml/XIncludeXMLBuilder.java
===================================================================
--- src/lib/net/n3/nanoxml/XIncludeXMLBuilder.java    (revision 0)
+++ src/lib/net/n3/nanoxml/XIncludeXMLBuilder.java    (revision 0)
@@ -0,0 +1,368 @@
+/*
+ * Copyright 2007 Volantis Systems Ltd., All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package net.n3.nanoxml;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.net.HttpURLConnection;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLConnection;
+import java.util.Iterator;
+import java.util.Stack;
+import java.util.Vector;
+
+/**
+ * Extend the XMLBuilder to add XInclude functionality
+ */
+public class XIncludeXMLBuilder extends StdXMLBuilder {
+    /**
+     * Namespace to for XInclude  (NOTE that this is not used
+     * at the moment). The specification can be found
+     * here'>http://www.w3.org/TR/xinclude/">here.
+     */
+    public static final String INCLUDE_NS = "http://www.w3.org/2001/XInclude";
+    /**
+     * The name of the include element (this should be "include" using the
+     * {@link #INCLUDE_NS} but namespaces are not supported
+     */
+    public static final String INCLUDE_ELEMENT = "xinclude";
+    /**
+     * The location of the included data
+     */
+    public static final String HREF_ATTRIB = "href";
+
+    /**
+     * The xpointer attribute. This must not be used when "parse='text'"
+     */
+    public static final String XPOINTER_ATTRIB = "xpointer";
+
+    /**
+     * The attribute to decribe the encoding of the text include (no effect when
+     * parse='xml')
+     */
+    public static final String ENCODING_ATTRIB = "encoding";
+
+    /**
+     * The attribute describing the accept header that will be used with
+     * http based includes.
+     */
+    public static final String ACCEPT_ENCODING = "accept";
+
+    /**
+     * The element for handling fallbacks. This should be called "fallback" and
+     * be in the {@link #INCLUDE_NS} but namespaces are not supported
+     */
+    public static final String FALLBACK_ELEMENT = "xfallback";
+
+    /**
+     * Parse attribute. If missing this implies "xml" its other valid value
+     * is "text"
+     */
+    public static final String PARSE_ATTRIB = "parse";
+
+    /**
+     * Namespace for the "fragment" element used to include xml documents with
+     * no explicit root node.
+     */
+    public static final String FRAGMENT_NS = "http://izpack.org/izpack/fragment";
+
+    /**
+     * The name of the fragment element is a root node element that can be
+     * used to wrap xml fragments for inclusion. It is removed during the
+     * include operation. This should be called "fragment" and be in the
+     * {@link #FRAGMENT_NS} but namespaces are not supported.
+     */
+    public static final String FRAGMENT = "xfragment";
+
+    // Javadoc inherited
+    public void endElement(String name, String nsPrefix, String nsSystemID) {
+        // get the current element before it gets popped from the stack
+        XMLElement element = getCurrentElement();
+        // let normal processing occur
+        super.endElement(name, nsPrefix, nsSystemID);
+        // now process the "include" element
+        processXInclude(element);
+    }
+
+    /**
+     * This method handles XInclude elements in the code
+     *
+     * @param element the node currently being procesed. In this case it should
+     *            be the {@link #INCLUDE_ELEMENT}
+     */
+    private void processXInclude(final XMLElement element) {
+        if (INCLUDE_ELEMENT.equals(element.getName())) {
+
+            Vector fallbackChildren = element.getChildrenNamed(FALLBACK_ELEMENT);
+            if (element.getChildrenCount() != fallbackChildren.size() ||
+                fallbackChildren.size() > 1) {
+                throw new RuntimeException(new XMLParseException(
+                    element.getSystemID(),
+                    element.getLineNr(),
+                    INCLUDE_ELEMENT + " can optionally have a single " +
+                        FRAGMENT + " as a child"));
+            }
+            boolean usingFallback = false;
+
+            String href = element.getAttribute(HREF_ATTRIB, "");
+            if (!href.equals("")) { // including an external file.
+
+                IXMLReader reader = null;
+                try {
+                    reader = getReader(element);
+                } catch (Exception e) { // yes really catch all exceptions
+                    // ok failed to read from the location for some reason.
+                    // see if we have a fallback
+                    reader = handleFallback(element);
+                    usingFallback = true;
+                }
+                String parse = element.getAttribute(PARSE_ATTRIB, "xml");
+                // process as text if we are not using our fallback and the parse
+                // type is "text"
+                if ("text".equals(parse) && !usingFallback) {
+                    includeText(element, reader);
+                } else if ("xml".equals(parse)) {
+                    includeXML(element, reader);
+                } else {
+                    throw new RuntimeException(
+                        new XMLParseException(
+                            element.getSystemID(),
+                            element.getLineNr(),
+                            PARSE_ATTRIB + " attribute of " + INCLUDE_ELEMENT +
+                                " must be \"xml\" or \"text\" but was " +
+                                parse));
+                }
+            } else { // including part of this file rather then an external one
+                if (!element.hasAttribute(XPOINTER_ATTRIB)) {
+                    throw new RuntimeException(
+                        new XMLParseException(
+                            element.getSystemID(),
+                            element.getLineNr(),
+                            XPOINTER_ATTRIB + "must be specified if href is " +
+                                "empty or missing"));
+                }
+            }
+        }
+    }
+
+    /**
+     * Handle the fallback if one exists. If one does not exist then throw
+     * a runtime exception as this is a fatal error
+     *
+     * @param include the include element
+     * @return a reader for the fallback
+     */
+    private IXMLReader handleFallback(XMLElement include) {
+        Vector fallbackChildren = include.getChildrenNamed(FALLBACK_ELEMENT);
+        if (fallbackChildren.size() == 1) {
+            // process fallback
+
+            XMLElement fallback = (XMLElement) fallbackChildren.get(0);
+            // fallback element can only contain a CDATA so it will not have
+            // its content in un-named children
+            String content = fallback.getContent();
+            if (content != null) {
+                content = content.trim();
+            }
+
+            if ("".equals(content) || content == null) {
+                // an empty fragment requires us to just remove the "include"
+                // element. A nasty hack follows:
+                // a "fragment" with no children will just be removed along with
+                // the "include" element.
+                content = "<?xml version=\"1.0\" encoding=\"iso-8859-1\" standalone=\"yes\" ?><"+ FRAGMENT + "/>";
+            } 
+            return StdXMLReader.stringReader(content);
+        } else {
+            throw new RuntimeException(new XMLParseException(
+                include.getSystemID(),
+                include.getLineNr(),
+                "could not load content"));
+        }
+    }
+
+    /**
+     * Include the xml contained in the specified reader. This content will be
+     * parsed and attached to the parent of the <param>element</param> node
+     *
+     * @param element the include element
+     * @param reader  the reader containing the xml to parse and include.
+     */
+    private void includeXML(final XMLElement element, IXMLReader reader) {
+
+        try {
+            Stack stack = getStack();
+            // set up a new parser to parse the include file.
+            StdXMLParser parser = new StdXMLParser();
+            parser.setBuilder(XMLBuilderFactory.createXMLBuilder());
+            parser.setReader(reader);
+            parser.setValidator(new NonValidator());
+
+            XMLElement childroot = (XMLElement) parser.parse();
+            // if the include element was the root element in the original
+            // document then keep the element as-is (i.e.
+            // don't remove the "fragment" element from the included content
+            if (stack.isEmpty()) {
+                setRootElement(childroot);
+            } else {
+                XMLElement parent = (XMLElement) stack.peek();
+                // remove the include element from its parent
+                parent.removeChild(element);
+
+                // if there was a "fragment" included remove the fragment
+                // element and attach its children in place of this include
+                // element.
+                if (FRAGMENT.equals(childroot.getName())) {
+                    Vector grandchildren = childroot.getChildren();
+                    Iterator it = grandchildren.iterator();
+                    while (it.hasNext()) {
+                        XMLElement grandchild = (XMLElement) it.next();
+                        parent.addChild(grandchild);
+                    }
+                } else {
+                    // if it was a complete document included then
+                    // just add it in place of the include element
+                    parent.addChild(childroot);
+                }
+            }
+        } catch (XMLException e) {
+            throw new RuntimeException(new XMLParseException(
+                element.getSystemID(), element.getLineNr(), e.getMessage()));
+        }
+    }
+
+
+    /**
+     * Include plain text. The reader contains the content in the appropriate
+     * encoding as determined by the {@link #ENCODING_ATTRIB} if one was
+     * present.
+     *
+     * @param element the include element
+     * @param reader  the reader containing the include text
+     */
+    private void includeText(XMLElement element, IXMLReader reader) {
+
+        if (element.getAttribute("xpointer") != null) {
+            throw new RuntimeException(new XMLParseException(
+                "xpointer cannot be used with parse='text'"));
+        }
+
+        Stack stack = getStack();
+        if (stack.isEmpty()) {
+            throw new RuntimeException(new XMLParseException(
+                element.getSystemID(),
+                element.getLineNr(),
+                "cannot include text as the root node"));
+        }
+
+        // remove the include element from the parent
+        XMLElement parent = (XMLElement)stack.peek();
+        parent.removeChild(element);
+        StringBuffer buffer = new StringBuffer();
+        try {
+            while (!reader.atEOF()) {
+                buffer.append(reader.read());
+            }
+        } catch (IOException e) {
+            throw new RuntimeException(new XMLParseException(
+                element.getSystemID(), element.getLineNr(), e.getMessage()));
+        }
+
+        if (parent.getChildrenCount() == 0) {
+            // no children so just set the content as there cannot have been
+            // any content there already
+            parent.setContent(buffer.toString());
+        } else {
+            // nanoxml also claims to store #PCDATA in unnamed children
+            // if there was a combination of #PCDATA and child elements.
+            // This should put it in the correct place as we haven't finihshed
+            // parsing the children of includes parent yet.
+            XMLElement content = new XMLElement();
+            content.setContent(buffer.toString());
+            parent.addChild(content);
+        }
+    }
+
+    /**
+     * Return a reader for the specified {@link #INCLUDE_ELEMENT}. The caller
+     * is responsible for closing the reader produced.
+     *
+     * @param element the include element to obtain a reader for
+     * @return a reader for the include element
+     * @throws XMLParseException if a problem occurs parsing the
+     *                           {@link #INCLUDE_ELEMENT}
+     * @throws IOException       if the href cannot be read
+     */
+    private IXMLReader getReader(XMLElement element) throws XMLParseException, IOException {
+        String href = element.getAttribute(HREF_ATTRIB);
+        // This is a bit nasty but is a simple way of handling files that are
+        // not fully qualified urls
+        URL url = null;
+        try {
+            // standard URL
+            url = new URL(href);
+        } catch (MalformedURLException e) {
+            try {
+                // absolute file without a protocol
+                if (href.charAt(0) == '/') {
+                    url = new URL("file://" + href);
+                } else {
+                    // relative file
+                    url = new URL(new URL(element.getSystemID()), href);
+                }
+            } catch (MalformedURLException e1) {
+                    new XMLParseException(element.getSystemID(),
+                    element.getLineNr(), "malformed url '" + href + "'");
+            }
+        }
+
+        URLConnection connection = url.openConnection();
+        // special handling for http and https
+        if (connection instanceof HttpURLConnection &&
+            element.hasAttribute(ENCODING_ATTRIB)) {
+            connection.setRequestProperty(
+                "accept", element.getAttribute(ENCODING_ATTRIB));
+        }
+
+        InputStream is = connection.getInputStream();
+
+        InputStreamReader reader = null;
+        // Only pay attention to the {@link #ENCODING_ATTRIB} if parse='text'  
+        if (element.getAttribute(PARSE_ATTRIB, "xml").equals("text") &&
+            element.hasAttribute(ENCODING_ATTRIB)) {
+            reader = new InputStreamReader(
+                is, element.getAttribute(ENCODING_ATTRIB, ""));
+        } else {
+            reader = new InputStreamReader(is);
+        }
+
+        IXMLReader ireader = new StdXMLReader(reader);
+        ireader.setSystemID(url.toExternalForm());
+        return ireader;
+    }
+
+    /**
+     * used to record the system id for this document.
+     *
+     * @param systemID the system id of the document being built
+     * @param lineNr the line number 
+     */
+    public void startBuilding(String systemID, int lineNr) {
+        super.startBuilding(systemID, lineNr);
+    }
+}
Index: src/lib/net/n3/nanoxml/XMLParserFactory.java
===================================================================
--- src/lib/net/n3/nanoxml/XMLParserFactory.java    (revision 1951)
+++ src/lib/net/n3/nanoxml/XMLParserFactory.java    (working copy)
@@ -65,7 +65,7 @@
     {
         String className = System.getProperty(XMLParserFactory.CLASS_KEY,
                 XMLParserFactory.DEFAULT_CLASS);
-        return XMLParserFactory.createXMLParser(className, new StdXMLBuilder());
+        return XMLParserFactory.createXMLParser(className, XMLBuilderFactory.createXMLBuilder());
     }
 
     /**
Index: src/lib/net/n3/nanoxml/StdXMLBuilder.java
===================================================================
--- src/lib/net/n3/nanoxml/StdXMLBuilder.java    (revision 1951)
+++ src/lib/net/n3/nanoxml/StdXMLBuilder.java    (working copy)
@@ -63,6 +63,36 @@
     }
 
     /**
+     * Return the element that is currently being processed
+     *
+     * @return  the element that is currently being processed
+     */
+    protected XMLElement getCurrentElement() {
+        return (XMLElement) stack.peek();
+    }
+
+    /**
+     * Return the stack used for processing the elements.
+     *
+     * @return  the stack used for processing the elements.
+     */
+    protected Stack getStack() {
+        return stack;
+    }
+
+    /**
+     * Set the root element to a new element. This causes the internal stack
+     * to be flushed and the supplied element to be pushed onto it
+     *
+     * @param element the new root element.
+     */
+    protected void setRootElement(XMLElement element) {
+        stack.clear();
+        stack.push(element);
+        this.root = element;
+    }
+
+    /**
      * Cleans up the object when it's destroyed.
      */
     protected void finalize() throws Throwable
Index: src/lib/net/n3/nanoxml/StdXMLReader.java
===================================================================
--- src/lib/net/n3/nanoxml/StdXMLReader.java    (revision 1951)
+++ src/lib/net/n3/nanoxml/StdXMLReader.java    (working copy)
@@ -138,7 +138,7 @@
         }
         catch (MalformedURLException e)
         {
-            systemID = "file:" + systemID;
+            systemID = "file://" + systemID;
 
             try
             {
Index: src/lib/com/izforge/izpack/panels/UserInputPanel.java
===================================================================
--- src/lib/com/izforge/izpack/panels/UserInputPanel.java    (revision 1951)
+++ src/lib/com/izforge/izpack/panels/UserInputPanel.java    (working copy)
@@ -54,10 +54,10 @@
 import javax.swing.text.Document;
 
 import net.n3.nanoxml.NonValidator;
-import net.n3.nanoxml.StdXMLBuilder;
 import net.n3.nanoxml.StdXMLParser;
 import net.n3.nanoxml.StdXMLReader;
 import net.n3.nanoxml.XMLElement;
+import net.n3.nanoxml.XMLBuilderFactory;
 
 import com.izforge.izpack.LocaleDatabase;
 import com.izforge.izpack.Pack;
@@ -1145,7 +1145,7 @@
 
         // initialize the parser
         StdXMLParser parser = new StdXMLParser();
-        parser.setBuilder(new StdXMLBuilder());
+        parser.setBuilder(XMLBuilderFactory.createXMLBuilder());
         parser.setValidator(new NonValidator());
         parser.setReader(new StdXMLReader(input));
 
Index: src/lib/com/izforge/izpack/panels/ShortcutPanel.java
===================================================================
--- src/lib/com/izforge/izpack/panels/ShortcutPanel.java    (revision 1951)
+++ src/lib/com/izforge/izpack/panels/ShortcutPanel.java    (working copy)
@@ -49,10 +49,10 @@
 import javax.swing.event.ListSelectionListener;
 
 import net.n3.nanoxml.NonValidator;
-import net.n3.nanoxml.StdXMLBuilder;
 import net.n3.nanoxml.StdXMLParser;
 import net.n3.nanoxml.StdXMLReader;
 import net.n3.nanoxml.XMLElement;
+import net.n3.nanoxml.XMLBuilderFactory;
 
 import com.izforge.izpack.ExecutableFile;
 import com.izforge.izpack.Pack;
@@ -830,7 +830,7 @@
          * System.out.println( "==================================================================" ); }
          */
         StdXMLParser parser = new StdXMLParser();
-        parser.setBuilder(new StdXMLBuilder());
+        parser.setBuilder(XMLBuilderFactory.createXMLBuilder());
         parser.setValidator(new NonValidator());
         parser.setReader(StdXMLReader.stringReader(substitutedSpec));
 
Index: src/lib/com/izforge/izpack/installer/AutomatedInstaller.java
===================================================================
--- src/lib/com/izforge/izpack/installer/AutomatedInstaller.java    (revision 1951)
+++ src/lib/com/izforge/izpack/installer/AutomatedInstaller.java    (working copy)
@@ -40,10 +40,10 @@
 import java.util.zip.ZipOutputStream;
 
 import net.n3.nanoxml.NonValidator;
-import net.n3.nanoxml.StdXMLBuilder;
 import net.n3.nanoxml.StdXMLParser;
 import net.n3.nanoxml.StdXMLReader;
 import net.n3.nanoxml.XMLElement;
+import net.n3.nanoxml.XMLBuilderFactory;
 
 import com.izforge.izpack.CustomData;
 import com.izforge.izpack.ExecutableFile;
@@ -454,7 +454,7 @@
 
         // Initialises the parser
         StdXMLParser parser = new StdXMLParser();
-        parser.setBuilder(new StdXMLBuilder());
+        parser.setBuilder(XMLBuilderFactory.createXMLBuilder());
         parser.setReader(new StdXMLReader(in));
         parser.setValidator(new NonValidator());
 
Index: src/lib/com/izforge/izpack/installer/InstallerFrame.java
===================================================================
--- src/lib/com/izforge/izpack/installer/InstallerFrame.java    (revision 1951)
+++ src/lib/com/izforge/izpack/installer/InstallerFrame.java    (working copy)
@@ -84,11 +84,11 @@
 import javax.swing.text.JTextComponent;
 
 import net.n3.nanoxml.NonValidator;
-import net.n3.nanoxml.StdXMLBuilder;
 import net.n3.nanoxml.StdXMLParser;
 import net.n3.nanoxml.StdXMLReader;
 import net.n3.nanoxml.XMLElement;
 import net.n3.nanoxml.XMLWriter;
+import net.n3.nanoxml.XMLBuilderFactory;
 
 import com.izforge.izpack.CustomData;
 import com.izforge.izpack.ExecutableFile;
@@ -351,7 +351,7 @@
             }
 
             StdXMLParser parser = new StdXMLParser();
-            parser.setBuilder(new StdXMLBuilder());
+            parser.setBuilder(XMLBuilderFactory.createXMLBuilder());
             parser.setValidator(new NonValidator());
             parser.setReader(new StdXMLReader(input));
 
@@ -443,7 +443,7 @@
 
         // Initialises the parser
         StdXMLParser parser = new StdXMLParser();
-        parser.setBuilder(new StdXMLBuilder());
+        parser.setBuilder(XMLBuilderFactory.createXMLBuilder());
         parser.setReader(new StdXMLReader(inXML));
         parser.setValidator(new NonValidator());
 
@@ -495,7 +495,7 @@
 
       // Initialises the parser
       StdXMLParser parser = new StdXMLParser();
-      parser.setBuilder(new StdXMLBuilder());
+      parser.setBuilder(XMLBuilderFactory.createXMLBuilder());
       parser.setReader(new StdXMLReader(inXML));
       parser.setValidator(new NonValidator());
 
Index: src/lib/com/izforge/izpack/installer/CompileWorker.java
===================================================================
--- src/lib/com/izforge/izpack/installer/CompileWorker.java    (revision 1951)
+++ src/lib/com/izforge/izpack/installer/CompileWorker.java    (working copy)
@@ -40,10 +40,10 @@
 import java.util.Vector;
 
 import net.n3.nanoxml.NonValidator;
-import net.n3.nanoxml.StdXMLBuilder;
 import net.n3.nanoxml.StdXMLParser;
 import net.n3.nanoxml.StdXMLReader;
 import net.n3.nanoxml.XMLElement;
+import net.n3.nanoxml.XMLBuilderFactory;
 
 import com.izforge.izpack.LocaleDatabase;
 import com.izforge.izpack.util.Debug;
@@ -240,7 +240,7 @@
         }
 
         StdXMLParser parser = new StdXMLParser();
-        parser.setBuilder(new StdXMLBuilder());
+        parser.setBuilder(XMLBuilderFactory.createXMLBuilder());
         parser.setValidator(new NonValidator());
 
         try
Index: src/lib/com/izforge/izpack/installer/ProcessPanelWorker.java
===================================================================
--- src/lib/com/izforge/izpack/installer/ProcessPanelWorker.java    (revision 1951)
+++ src/lib/com/izforge/izpack/installer/ProcessPanelWorker.java    (working copy)
@@ -38,10 +38,10 @@
 import java.util.Vector;
 
 import net.n3.nanoxml.NonValidator;
-import net.n3.nanoxml.StdXMLBuilder;
 import net.n3.nanoxml.StdXMLParser;
 import net.n3.nanoxml.StdXMLReader;
 import net.n3.nanoxml.XMLElement;
+import net.n3.nanoxml.XMLBuilderFactory;
 
 import com.izforge.izpack.Pack;
 import com.izforge.izpack.rules.Condition;
@@ -117,7 +117,7 @@
         }
 
         StdXMLParser parser = new StdXMLParser();
-        parser.setBuilder(new StdXMLBuilder());
+        parser.setBuilder(XMLBuilderFactory.createXMLBuilder());
         parser.setValidator(new NonValidator());
 
         XMLElement spec;
Index: src/lib/com/izforge/izpack/LocaleDatabase.java
===================================================================
--- src/lib/com/izforge/izpack/LocaleDatabase.java    (revision 1951)
+++ src/lib/com/izforge/izpack/LocaleDatabase.java    (working copy)
@@ -25,10 +25,10 @@
 import java.util.Vector;
 
 import net.n3.nanoxml.NonValidator;
-import net.n3.nanoxml.StdXMLBuilder;
 import net.n3.nanoxml.StdXMLParser;
 import net.n3.nanoxml.StdXMLReader;
 import net.n3.nanoxml.XMLElement;
+import net.n3.nanoxml.XMLBuilderFactory;
 
 /**
  * Represents a database of a locale.
@@ -64,7 +64,7 @@
     {
         // Initialises the parser
         StdXMLParser parser = new StdXMLParser();
-        parser.setBuilder(new StdXMLBuilder());
+        parser.setBuilder(XMLBuilderFactory.createXMLBuilder());
         parser.setReader(new StdXMLReader(in));
         parser.setValidator(new NonValidator());
 
Index: src/lib/com/izforge/izpack/compiler/CompilerConfig.java
===================================================================
--- src/lib/com/izforge/izpack/compiler/CompilerConfig.java    (revision 1951)
+++ src/lib/com/izforge/izpack/compiler/CompilerConfig.java    (working copy)
@@ -75,11 +75,11 @@
 
 import net.n3.nanoxml.IXMLReader;
 import net.n3.nanoxml.NonValidator;
-import net.n3.nanoxml.StdXMLBuilder;
 import net.n3.nanoxml.StdXMLParser;
 import net.n3.nanoxml.StdXMLReader;
 import net.n3.nanoxml.XMLElement;
 import net.n3.nanoxml.XMLException;
+import net.n3.nanoxml.XMLBuilderFactory;
 
 /**
  * A parser for the installer xml configuration. This parses a document
@@ -1001,7 +1001,7 @@
             }
             
             StdXMLParser refXMLParser = new StdXMLParser();
-            refXMLParser.setBuilder(new StdXMLBuilder());
+            refXMLParser.setBuilder(XMLBuilderFactory.createXMLBuilder());
             refXMLParser.setReader(refXMLReader);
             refXMLParser.setValidator(new NonValidator());
 
@@ -1688,7 +1688,7 @@
         }
 
         StdXMLParser parser = new StdXMLParser();
-        parser.setBuilder(new StdXMLBuilder());
+        parser.setBuilder(XMLBuilderFactory.createXMLBuilder());
         parser.setReader(reader);
         parser.setValidator(new NonValidator());
 
Index: src/lib/com/izforge/izpack/util/SpecHelper.java
===================================================================
--- src/lib/com/izforge/izpack/util/SpecHelper.java    (revision 1951)
+++ src/lib/com/izforge/izpack/util/SpecHelper.java    (working copy)
@@ -29,10 +29,10 @@
 import java.util.Vector;
 
 import net.n3.nanoxml.NonValidator;
-import net.n3.nanoxml.StdXMLBuilder;
 import net.n3.nanoxml.StdXMLParser;
 import net.n3.nanoxml.StdXMLReader;
 import net.n3.nanoxml.XMLElement;
+import net.n3.nanoxml.XMLBuilderFactory;
 
 import com.izforge.izpack.installer.InstallerException;
 import com.izforge.izpack.installer.ResourceManager;
@@ -142,7 +142,7 @@
 
         // initialize the parser
         StdXMLParser parser = new StdXMLParser();
-        parser.setBuilder(new StdXMLBuilder());
+        parser.setBuilder(XMLBuilderFactory.createXMLBuilder());
         parser.setValidator(new NonValidator());
         parser.setReader(new StdXMLReader(input));
 











      __________________________________________________________
Sent from Yahoo! Mail - a smarter inbox http://uk.mail.yahoo.com



More information about the izpack-devel mailing list