Eliminating need for XML SAX and DOM 2 in base Java module
authorJaroslav Tulach <jtulach@netbeans.org>
Wed, 24 Jun 2009 17:51:59 +0200
changeset 126575acc009e9d8
parent 1258 6dcea85ad8ba
parent 1264 601d21ee9aa6
child 1266 4dfe5e86d509
Eliminating need for XML SAX and DOM 2 in base Java module
src/share/classes/java/util/XMLUtils.java
src/share/classes/java/util/prefs/XmlSupport.java
     1.1 --- a/build.xml	Mon Jun 22 18:07:11 2009 +0200
     1.2 +++ b/build.xml	Wed Jun 24 17:51:59 2009 +0200
     1.3 @@ -4,15 +4,19 @@
     1.4  
     1.5      <target name="all">
     1.6          <antcall target="base"/>
     1.7 +        <antclal target="xml"/>
     1.8          <antcall target="client"/>
     1.9          <antcall target="applet"/>
    1.10          <antcall target="corba"/>
    1.11          <antcall target="tools"/>
    1.12          <antcall target="deprecated7"/>
    1.13 +
    1.14 +
    1.15 +        <antcall target="test"/>
    1.16      </target>
    1.17  
    1.18      <!-- basic parameters -->
    1.19 -    <property name="plugs" value="../../plugs"/>
    1.20 +    <property name="plugs" value="${ant.file.modularize}/../../../plugs"/>
    1.21      <fail message="You need to provide location of plugs">
    1.22          <condition><not><available file="${plugs}/jre/lib/rt-closed.jar"/></not></condition>
    1.23      </fail>
    1.24 @@ -59,7 +63,13 @@
    1.25          <pathelement location="src/solaris/classes"/>
    1.26  <!--        <pathelement location="src/windows/classes"/> -->
    1.27      </path>
    1.28 -    <property name="build.dir" location="build/modularize"/>
    1.29 +    <property name="build.dir" location="${ant.file.modularize}/../build/modularize"/>
    1.30 +    <path id="boot">
    1.31 +        <fileset dir="${build.dir}">
    1.32 +            <include name="*.jar"/>
    1.33 +        </fileset>
    1.34 +    </path>
    1.35 +    <property name="test.dir" value="${ant.file.modularize}/../build/test"/>
    1.36  
    1.37      <!-- this is the core of the separation - definition
    1.38        of what classes belong into what compilation group.
    1.39 @@ -213,6 +223,41 @@
    1.40          </and>
    1.41      </selector>
    1.42  
    1.43 +    <selector id="xml">
    1.44 +        <and>
    1.45 +            <or>
    1.46 +                <filename name="META-INF/services/sun.util.xml*"/>
    1.47 +
    1.48 +                <filename name="org/w3c/**"/>
    1.49 +                <filename name="org/sax/**"/>
    1.50 +                <filename name="com/sun/org/apache/xml/internal/**"/>
    1.51 +                <filename name="com/sun/org/apache/xpath/internal/**"/>
    1.52 +                <filename name="com/sun/org/apache/xalan/internal/**"/>
    1.53 +                <filename name="com/sun/org/apache/xerces/internal/**"/>
    1.54 +                <filename name="com/sun/xml/internal/**"/>
    1.55 +                <filename name="org/jcp/xml/dsig/internal/**"/>
    1.56 +                <filename name="javax/xml/**"/>
    1.57 +                <filename name="com/sun/servicetag/**"/>
    1.58 +                <filename name="com/sun/java/browser/**"/>
    1.59 +
    1.60 +                <!-- SQL seems to have dependency on XML,
    1.61 +                    so including it here too for now
    1.62 +                -->
    1.63 +                <filename name="com/sun/rowset/**"/>
    1.64 +                <filename name="java/sql/**"/>
    1.65 +                <filename name="javax/sql/**"/>
    1.66 +            </or>
    1.67 +            <none>
    1.68 +                <!-- remove classes from other modules -->
    1.69 +                <selector refid="applet"/>
    1.70 +                <selector refid="client"/>
    1.71 +                <selector refid="corba"/>
    1.72 +                <selector refid="tools"/>
    1.73 +                <selector refid="deprecated7"/>
    1.74 +            </none>
    1.75 +         </and>
    1.76 +    </selector>
    1.77 +
    1.78      <selector id="tools">
    1.79          <or>
    1.80              <filename name="sun/security/tools/**"/>
    1.81 @@ -243,6 +288,7 @@
    1.82              <selector refid="corba"/>
    1.83              <selector refid="applet"/>
    1.84              <selector refid="client"/>
    1.85 +            <selector refid="xml"/>
    1.86              <selector refid="tools"/>
    1.87              <selector refid="deprecated7"/>
    1.88          <!--
    1.89 @@ -306,12 +352,50 @@
    1.90              <param name="depends" value="base:client:applet:corba"/>
    1.91          </antcall>
    1.92      </target>
    1.93 +    <target name="xml">
    1.94 +        <antcall target="-compile-one-module">
    1.95 +            <param name="module" value="xml"/>
    1.96 +            <param name="depends" value="base"/>
    1.97 +        </antcall>
    1.98 +    </target>
    1.99      <target name="base">
   1.100          <antcall target="-compile-one-module">
   1.101              <param name="module" value="base"/>
   1.102          </antcall>
   1.103      </target>
   1.104  
   1.105 +    <!-- basic sanity tests -->
   1.106 +    <target name="test">
   1.107 +        <mkdir dir="${test.dir}"/>
   1.108 +        <javac srcdir="test/java/util/Properties" destdir="${test.dir}"
   1.109 +            includeantruntime="false" includejavaruntime="false"
   1.110 +            debug="true" debuglevel="lines,vars,source"
   1.111 +        >
   1.112 +            <bootclasspath refid="boot"/>
   1.113 +        </javac>
   1.114 +        <javac srcdir="test/java/util/prefs/Preferences" destdir="${test.dir}"
   1.115 +            includeantruntime="false" includejavaruntime="false"
   1.116 +            debug="true" debuglevel="lines,vars,source"
   1.117 +        >
   1.118 +            <bootclasspath refid="boot"/>
   1.119 +        </javac>
   1.120 +
   1.121 +        <java classname="XMLReadAndWriteTest" fork="true">
   1.122 +            <jvmarg value="-ea"/>
   1.123 +            <classpath>
   1.124 +                <path refid="boot"/>
   1.125 +                <pathelement location="${test.dir}"/>
   1.126 +            </classpath>
   1.127 +        </java>
   1.128 +        <java classname="XMLPreferencesTest" fork="true">
   1.129 +            <jvmarg value="-ea"/>
   1.130 +            <classpath>
   1.131 +                <path refid="boot"/>
   1.132 +                <pathelement location="${test.dir}"/>
   1.133 +            </classpath>
   1.134 +        </java>
   1.135 +    </target>
   1.136 +
   1.137      <!-- shared routine to compile one of the modules -->
   1.138      <target name="-compile-one-module">
   1.139          <mkdir dir="${build.dir}/classes/${module}"/>
   1.140 @@ -333,6 +417,8 @@
   1.141              includejavaruntime="false"
   1.142              includeantruntime="false"
   1.143              classpath="${module.cp}:${plugs}/jre/lib/rt-closed.jar"
   1.144 +            debug="true"
   1.145 +            debuglevel="lines,vars,source"
   1.146          >
   1.147              <src refid="src.path"/>
   1.148              <and>
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/src/share/classes/META-INF/services/sun.util.xml.PrefsXMLSupport	Wed Jun 24 17:51:59 2009 +0200
     2.3 @@ -0,0 +1,1 @@
     2.4 +com.sun.xml.internal.PrefsXmlSupportImpl
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/src/share/classes/META-INF/services/sun.util.xml.PropertiesXMLUtils	Wed Jun 24 17:51:59 2009 +0200
     3.3 @@ -0,0 +1,1 @@
     3.4 +com.sun.xml.internal.PropertiesXMLUtilsImpl
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/src/share/classes/com/sun/xml/internal/PrefsXmlSupportImpl.java	Wed Jun 24 17:51:59 2009 +0200
     4.3 @@ -0,0 +1,439 @@
     4.4 +/*
     4.5 + * Copyright 2002-2006 Sun Microsystems, Inc.  All Rights Reserved.
     4.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4.7 + *
     4.8 + * This code is free software; you can redistribute it and/or modify it
     4.9 + * under the terms of the GNU General Public License version 2 only, as
    4.10 + * published by the Free Software Foundation.  Sun designates this
    4.11 + * particular file as subject to the "Classpath" exception as provided
    4.12 + * by Sun in the LICENSE file that accompanied this code.
    4.13 + *
    4.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
    4.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    4.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    4.17 + * version 2 for more details (a copy is included in the LICENSE file that
    4.18 + * accompanied this code).
    4.19 + *
    4.20 + * You should have received a copy of the GNU General Public License version
    4.21 + * 2 along with this work; if not, write to the Free Software Foundation,
    4.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    4.23 + *
    4.24 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
    4.25 + * CA 95054 USA or visit www.sun.com if you need additional information or
    4.26 + * have any questions.
    4.27 + */
    4.28 +
    4.29 +package com.sun.xml.internal;
    4.30 +
    4.31 +import java.util.*;
    4.32 +import java.util.prefs.*;
    4.33 +import java.io.*;
    4.34 +import javax.xml.parsers.*;
    4.35 +import javax.xml.transform.*;
    4.36 +import javax.xml.transform.dom.*;
    4.37 +import javax.xml.transform.stream.*;
    4.38 +import org.xml.sax.*;
    4.39 +import org.w3c.dom.*;
    4.40 +
    4.41 +/**
    4.42 + * XML Support for java.util.prefs. Methods to import and export preference
    4.43 + * nodes and subtrees.
    4.44 + *
    4.45 + * @author  Josh Bloch and Mark Reinhold
    4.46 + * @see     Preferences
    4.47 + * @since   1.4
    4.48 + */
    4.49 +public class PrefsXmlSupportImpl extends sun.util.xml.PrefsXmlSupport {
    4.50 +    // The required DTD URI for exported preferences
    4.51 +    private static final String PREFS_DTD_URI =
    4.52 +        "http://java.sun.com/dtd/preferences.dtd";
    4.53 +
    4.54 +    // The actual DTD corresponding to the URI
    4.55 +    private static final String PREFS_DTD =
    4.56 +        "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
    4.57 +
    4.58 +        "<!-- DTD for preferences -->"               +
    4.59 +
    4.60 +        "<!ELEMENT preferences (root) >"             +
    4.61 +        "<!ATTLIST preferences"                      +
    4.62 +        " EXTERNAL_XML_VERSION CDATA \"0.0\"  >"     +
    4.63 +
    4.64 +        "<!ELEMENT root (map, node*) >"              +
    4.65 +        "<!ATTLIST root"                             +
    4.66 +        "          type (system|user) #REQUIRED >"   +
    4.67 +
    4.68 +        "<!ELEMENT node (map, node*) >"              +
    4.69 +        "<!ATTLIST node"                             +
    4.70 +        "          name CDATA #REQUIRED >"           +
    4.71 +
    4.72 +        "<!ELEMENT map (entry*) >"                   +
    4.73 +        "<!ATTLIST map"                              +
    4.74 +        "  MAP_XML_VERSION CDATA \"0.0\"  >"         +
    4.75 +        "<!ELEMENT entry EMPTY >"                    +
    4.76 +        "<!ATTLIST entry"                            +
    4.77 +        "          key CDATA #REQUIRED"              +
    4.78 +        "          value CDATA #REQUIRED >"          ;
    4.79 +    /**
    4.80 +     * Version number for the format exported preferences files.
    4.81 +     */
    4.82 +    private static final String EXTERNAL_XML_VERSION = "1.0";
    4.83 +
    4.84 +    /*
    4.85 +     * Version number for the internal map files.
    4.86 +     */
    4.87 +    private static final String MAP_XML_VERSION = "1.0";
    4.88 +
    4.89 +    /**
    4.90 +     * Export the specified preferences node and, if subTree is true, all
    4.91 +     * subnodes, to the specified output stream.  Preferences are exported as
    4.92 +     * an XML document conforming to the definition in the Preferences spec.
    4.93 +     *
    4.94 +     * @throws IOException if writing to the specified output stream
    4.95 +     *         results in an <tt>IOException</tt>.
    4.96 +     * @throws BackingStoreException if preference data cannot be read from
    4.97 +     *         backing store.
    4.98 +     * @throws IllegalStateException if this node (or an ancestor) has been
    4.99 +     *         removed with the {@link #removeNode()} method.
   4.100 +     */
   4.101 +    public void export(OutputStream os, final Preferences p, boolean subTree)
   4.102 +        throws IOException, BackingStoreException {
   4.103 +        if (isRemoved(p))
   4.104 +            throw new IllegalStateException("Node has been removed");
   4.105 +        Document doc = createPrefsDoc("preferences");
   4.106 +        Element preferences =  doc.getDocumentElement() ;
   4.107 +        preferences.setAttribute("EXTERNAL_XML_VERSION", EXTERNAL_XML_VERSION);
   4.108 +        Element xmlRoot =  (Element)
   4.109 +        preferences.appendChild(doc.createElement("root"));
   4.110 +        xmlRoot.setAttribute("type", (p.isUserNode() ? "user" : "system"));
   4.111 +
   4.112 +        // Get bottom-up list of nodes from p to root, excluding root
   4.113 +        List ancestors = new ArrayList();
   4.114 +
   4.115 +        for (Preferences kid = p, dad = kid.parent(); dad != null;
   4.116 +                                   kid = dad, dad = kid.parent()) {
   4.117 +            ancestors.add(kid);
   4.118 +        }
   4.119 +        Element e = xmlRoot;
   4.120 +        for (int i=ancestors.size()-1; i >= 0; i--) {
   4.121 +            e.appendChild(doc.createElement("map"));
   4.122 +            e = (Element) e.appendChild(doc.createElement("node"));
   4.123 +            e.setAttribute("name", ((Preferences)ancestors.get(i)).name());
   4.124 +        }
   4.125 +        putPreferencesInXml(e, doc, p, subTree);
   4.126 +
   4.127 +        writeDoc(doc, os);
   4.128 +    }
   4.129 +
   4.130 +    /**
   4.131 +     * Put the preferences in the specified Preferences node into the
   4.132 +     * specified XML element which is assumed to represent a node
   4.133 +     * in the specified XML document which is assumed to conform to
   4.134 +     * PREFS_DTD.  If subTree is true, create children of the specified
   4.135 +     * XML node conforming to all of the children of the specified
   4.136 +     * Preferences node and recurse.
   4.137 +     *
   4.138 +     * @throws BackingStoreException if it is not possible to read
   4.139 +     *         the preferences or children out of the specified
   4.140 +     *         preferences node.
   4.141 +     */
   4.142 +    private static void putPreferencesInXml(Element elt, Document doc,
   4.143 +               Preferences prefs, boolean subTree) throws BackingStoreException
   4.144 +    {
   4.145 +        Preferences[] kidsCopy = null;
   4.146 +        String[] kidNames = null;
   4.147 +
   4.148 +        // Node is locked to export its contents and get a
   4.149 +        // copy of children, then lock is released,
   4.150 +        // and, if subTree = true, recursive calls are made on children
   4.151 +        synchronized (lock(prefs)) {
   4.152 +            // Check if this node was concurrently removed. If yes
   4.153 +            // remove it from XML Document and return.
   4.154 +            if (isRemoved(prefs)) {
   4.155 +                elt.getParentNode().removeChild(elt);
   4.156 +                return;
   4.157 +            }
   4.158 +            // Put map in xml element
   4.159 +            String[] keys = prefs.keys();
   4.160 +            Element map = (Element) elt.appendChild(doc.createElement("map"));
   4.161 +            for (int i=0; i<keys.length; i++) {
   4.162 +                Element entry = (Element)
   4.163 +                    map.appendChild(doc.createElement("entry"));
   4.164 +                entry.setAttribute("key", keys[i]);
   4.165 +                // NEXT STATEMENT THROWS NULL PTR EXC INSTEAD OF ASSERT FAIL
   4.166 +                entry.setAttribute("value", prefs.get(keys[i], null));
   4.167 +            }
   4.168 +            // Recurse if appropriate
   4.169 +            if (subTree) {
   4.170 +                /* Get a copy of kids while lock is held */
   4.171 +                kidNames = prefs.childrenNames();
   4.172 +                kidsCopy = new Preferences[kidNames.length];
   4.173 +                for (int i = 0; i <  kidNames.length; i++)
   4.174 +                    kidsCopy[i] = prefs.node(kidNames[i]);
   4.175 +            }
   4.176 +            // release lock
   4.177 +        }
   4.178 +
   4.179 +        if (subTree) {
   4.180 +            for (int i=0; i < kidNames.length; i++) {
   4.181 +                Element xmlKid = (Element)
   4.182 +                    elt.appendChild(doc.createElement("node"));
   4.183 +                xmlKid.setAttribute("name", kidNames[i]);
   4.184 +                putPreferencesInXml(xmlKid, doc, kidsCopy[i], subTree);
   4.185 +            }
   4.186 +        }
   4.187 +    }
   4.188 +
   4.189 +    /**
   4.190 +     * Import preferences from the specified input stream, which is assumed
   4.191 +     * to contain an XML document in the format described in the Preferences
   4.192 +     * spec.
   4.193 +     *
   4.194 +     * @throws IOException if reading from the specified output stream
   4.195 +     *         results in an <tt>IOException</tt>.
   4.196 +     * @throws InvalidPreferencesFormatException Data on input stream does not
   4.197 +     *         constitute a valid XML document with the mandated document type.
   4.198 +     */
   4.199 +    public void importPreferences(InputStream is)
   4.200 +        throws IOException, InvalidPreferencesFormatException
   4.201 +    {
   4.202 +        try {
   4.203 +            Document doc = loadPrefsDoc(is);
   4.204 +            String xmlVersion =
   4.205 +                doc.getDocumentElement().getAttribute("EXTERNAL_XML_VERSION");
   4.206 +            if (xmlVersion.compareTo(EXTERNAL_XML_VERSION) > 0)
   4.207 +                throw new InvalidPreferencesFormatException(
   4.208 +                "Exported preferences file format version " + xmlVersion +
   4.209 +                " is not supported. This java installation can read" +
   4.210 +                " versions " + EXTERNAL_XML_VERSION + " or older. You may need" +
   4.211 +                " to install a newer version of JDK.");
   4.212 +
   4.213 +            Element xmlRoot = (Element) doc.getDocumentElement().
   4.214 +                                               getChildNodes().item(0);
   4.215 +            Preferences prefsRoot =
   4.216 +                (xmlRoot.getAttribute("type").equals("user") ?
   4.217 +                            Preferences.userRoot() : Preferences.systemRoot());
   4.218 +            ImportSubtree(prefsRoot, xmlRoot);
   4.219 +        } catch(SAXException e) {
   4.220 +            throw new InvalidPreferencesFormatException(e);
   4.221 +        }
   4.222 +    }
   4.223 +
   4.224 +    /**
   4.225 +     * Create a new prefs XML document.
   4.226 +     */
   4.227 +    private static Document createPrefsDoc( String qname ) {
   4.228 +        try {
   4.229 +            DOMImplementation di = DocumentBuilderFactory.newInstance().
   4.230 +                newDocumentBuilder().getDOMImplementation();
   4.231 +            DocumentType dt = di.createDocumentType(qname, null, PREFS_DTD_URI);
   4.232 +            return di.createDocument(null, qname, dt);
   4.233 +        } catch(ParserConfigurationException e) {
   4.234 +            throw new AssertionError(e);
   4.235 +        }
   4.236 +    }
   4.237 +
   4.238 +    /**
   4.239 +     * Load an XML document from specified input stream, which must
   4.240 +     * have the requisite DTD URI.
   4.241 +     */
   4.242 +    private static Document loadPrefsDoc(InputStream in)
   4.243 +        throws SAXException, IOException
   4.244 +    {
   4.245 +        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
   4.246 +        dbf.setIgnoringElementContentWhitespace(true);
   4.247 +        dbf.setValidating(true);
   4.248 +        dbf.setCoalescing(true);
   4.249 +        dbf.setIgnoringComments(true);
   4.250 +        try {
   4.251 +            DocumentBuilder db = dbf.newDocumentBuilder();
   4.252 +            db.setEntityResolver(new Resolver());
   4.253 +            db.setErrorHandler(new EH());
   4.254 +            return db.parse(new InputSource(in));
   4.255 +        } catch (ParserConfigurationException e) {
   4.256 +            throw new AssertionError(e);
   4.257 +        }
   4.258 +    }
   4.259 +
   4.260 +    /**
   4.261 +     * Write XML document to the specified output stream.
   4.262 +     */
   4.263 +    private static final void writeDoc(Document doc, OutputStream out)
   4.264 +        throws IOException
   4.265 +    {
   4.266 +        try {
   4.267 +            TransformerFactory tf = TransformerFactory.newInstance();
   4.268 +            try {
   4.269 +                tf.setAttribute("indent-number", new Integer(2));
   4.270 +            } catch (IllegalArgumentException iae) {
   4.271 +                //Ignore the IAE. Should not fail the writeout even the
   4.272 +                //transformer provider does not support "indent-number".
   4.273 +            }
   4.274 +            Transformer t = tf.newTransformer();
   4.275 +            t.setOutputProperty(OutputKeys.DOCTYPE_SYSTEM, doc.getDoctype().getSystemId());
   4.276 +            t.setOutputProperty(OutputKeys.INDENT, "yes");
   4.277 +            //Transformer resets the "indent" info if the "result" is a StreamResult with
   4.278 +            //an OutputStream object embedded, creating a Writer object on top of that
   4.279 +            //OutputStream object however works.
   4.280 +            t.transform(new DOMSource(doc),
   4.281 +                        new StreamResult(new BufferedWriter(new OutputStreamWriter(out, "UTF-8"))));
   4.282 +        } catch(TransformerException e) {
   4.283 +            throw new AssertionError(e);
   4.284 +        }
   4.285 +    }
   4.286 +
   4.287 +    /**
   4.288 +     * Recursively traverse the specified preferences node and store
   4.289 +     * the described preferences into the system or current user
   4.290 +     * preferences tree, as appropriate.
   4.291 +     */
   4.292 +    private static void ImportSubtree(Preferences prefsNode, Element xmlNode) {
   4.293 +        NodeList xmlKids = xmlNode.getChildNodes();
   4.294 +        int numXmlKids = xmlKids.getLength();
   4.295 +        /*
   4.296 +         * We first lock the node, import its contents and get
   4.297 +         * child nodes. Then we unlock the node and go to children
   4.298 +         * Since some of the children might have been concurrently
   4.299 +         * deleted we check for this.
   4.300 +         */
   4.301 +        Preferences[] prefsKids;
   4.302 +        /* Lock the node */
   4.303 +        synchronized (lock(prefsNode)) {
   4.304 +            //If removed, return silently
   4.305 +            if (isRemoved(prefsNode))
   4.306 +                return;
   4.307 +
   4.308 +            // Import any preferences at this node
   4.309 +            Element firstXmlKid = (Element) xmlKids.item(0);
   4.310 +            ImportPrefs(prefsNode, firstXmlKid);
   4.311 +            prefsKids = new Preferences[numXmlKids - 1];
   4.312 +
   4.313 +            // Get involved children
   4.314 +            for (int i=1; i < numXmlKids; i++) {
   4.315 +                Element xmlKid = (Element) xmlKids.item(i);
   4.316 +                prefsKids[i-1] = prefsNode.node(xmlKid.getAttribute("name"));
   4.317 +            }
   4.318 +        } // unlocked the node
   4.319 +        // import children
   4.320 +        for (int i=1; i < numXmlKids; i++)
   4.321 +            ImportSubtree(prefsKids[i-1], (Element)xmlKids.item(i));
   4.322 +    }
   4.323 +
   4.324 +    /**
   4.325 +     * Import the preferences described by the specified XML element
   4.326 +     * (a map from a preferences document) into the specified
   4.327 +     * preferences node.
   4.328 +     */
   4.329 +    private static void ImportPrefs(Preferences prefsNode, Element map) {
   4.330 +        NodeList entries = map.getChildNodes();
   4.331 +        for (int i=0, numEntries = entries.getLength(); i < numEntries; i++) {
   4.332 +            Element entry = (Element) entries.item(i);
   4.333 +            prefsNode.put(entry.getAttribute("key"),
   4.334 +                          entry.getAttribute("value"));
   4.335 +        }
   4.336 +    }
   4.337 +
   4.338 +    /**
   4.339 +     * Export the specified Map<String,String> to a map document on
   4.340 +     * the specified OutputStream as per the prefs DTD.  This is used
   4.341 +     * as the internal (undocumented) format for FileSystemPrefs.
   4.342 +     *
   4.343 +     * @throws IOException if writing to the specified output stream
   4.344 +     *         results in an <tt>IOException</tt>.
   4.345 +     */
   4.346 +    public void exportMap(OutputStream os, Map map) throws IOException {
   4.347 +        Document doc = createPrefsDoc("map");
   4.348 +        Element xmlMap = doc.getDocumentElement( ) ;
   4.349 +        xmlMap.setAttribute("MAP_XML_VERSION", MAP_XML_VERSION);
   4.350 +
   4.351 +        for (Iterator i = map.entrySet().iterator(); i.hasNext(); ) {
   4.352 +            Map.Entry e = (Map.Entry) i.next();
   4.353 +            Element xe = (Element)
   4.354 +                xmlMap.appendChild(doc.createElement("entry"));
   4.355 +            xe.setAttribute("key",   (String) e.getKey());
   4.356 +            xe.setAttribute("value", (String) e.getValue());
   4.357 +        }
   4.358 +
   4.359 +        writeDoc(doc, os);
   4.360 +    }
   4.361 +
   4.362 +    /**
   4.363 +     * Import Map from the specified input stream, which is assumed
   4.364 +     * to contain a map document as per the prefs DTD.  This is used
   4.365 +     * as the internal (undocumented) format for FileSystemPrefs.  The
   4.366 +     * key-value pairs specified in the XML document will be put into
   4.367 +     * the specified Map.  (If this Map is empty, it will contain exactly
   4.368 +     * the key-value pairs int the XML-document when this method returns.)
   4.369 +     *
   4.370 +     * @throws IOException if reading from the specified output stream
   4.371 +     *         results in an <tt>IOException</tt>.
   4.372 +     * @throws InvalidPreferencesFormatException Data on input stream does not
   4.373 +     *         constitute a valid XML document with the mandated document type.
   4.374 +     */
   4.375 +    public void importMap(InputStream is, Map m)
   4.376 +        throws IOException, InvalidPreferencesFormatException
   4.377 +    {
   4.378 +        try {
   4.379 +            Document doc = loadPrefsDoc(is);
   4.380 +            Element xmlMap = doc.getDocumentElement();
   4.381 +            // check version
   4.382 +            String mapVersion = xmlMap.getAttribute("MAP_XML_VERSION");
   4.383 +            if (mapVersion.compareTo(MAP_XML_VERSION) > 0)
   4.384 +                throw new InvalidPreferencesFormatException(
   4.385 +                "Preferences map file format version " + mapVersion +
   4.386 +                " is not supported. This java installation can read" +
   4.387 +                " versions " + MAP_XML_VERSION + " or older. You may need" +
   4.388 +                " to install a newer version of JDK.");
   4.389 +
   4.390 +            NodeList entries = xmlMap.getChildNodes();
   4.391 +            for (int i=0, numEntries=entries.getLength(); i<numEntries; i++) {
   4.392 +                Element entry = (Element) entries.item(i);
   4.393 +                m.put(entry.getAttribute("key"), entry.getAttribute("value"));
   4.394 +            }
   4.395 +        } catch(SAXException e) {
   4.396 +            throw new InvalidPreferencesFormatException(e);
   4.397 +        }
   4.398 +    }
   4.399 +
   4.400 +    private static class Resolver implements EntityResolver {
   4.401 +        public InputSource resolveEntity(String pid, String sid)
   4.402 +            throws SAXException
   4.403 +        {
   4.404 +            if (sid.equals(PREFS_DTD_URI)) {
   4.405 +                InputSource is;
   4.406 +                is = new InputSource(new StringReader(PREFS_DTD));
   4.407 +                is.setSystemId(PREFS_DTD_URI);
   4.408 +                return is;
   4.409 +            }
   4.410 +            throw new SAXException("Invalid system identifier: " + sid);
   4.411 +        }
   4.412 +    }
   4.413 +
   4.414 +    private static class EH implements ErrorHandler {
   4.415 +        public void error(SAXParseException x) throws SAXException {
   4.416 +            throw x;
   4.417 +        }
   4.418 +        public void fatalError(SAXParseException x) throws SAXException {
   4.419 +            throw x;
   4.420 +        }
   4.421 +        public void warning(SAXParseException x) throws SAXException {
   4.422 +            throw x;
   4.423 +        }
   4.424 +    }
   4.425 +
   4.426 +    private static boolean isRemoved(Preferences p) {
   4.427 +        try {
   4.428 +            p.parent(); // throws IllegalStateException if removed;
   4.429 +            return false;
   4.430 +        } catch (IllegalStateException ex) {
   4.431 +            return true;
   4.432 +        }
   4.433 +    }
   4.434 +
   4.435 +    private static Object lock(Preferences p) {
   4.436 +        /** JST-XXX: Needs reflection or accessor:
   4.437 +         * http://wiki.apidesign.org/wiki/FriendPackages
   4.438 +        return ((AbstractPreferences)prefs).lock;
   4.439 +         */
   4.440 +        return p;
   4.441 +    }
   4.442 +}
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/src/share/classes/com/sun/xml/internal/PropertiesXMLUtilsImpl.java	Wed Jun 24 17:51:59 2009 +0200
     5.3 @@ -0,0 +1,220 @@
     5.4 +/*
     5.5 + * Copyright 2003-2004 Sun Microsystems, Inc.  All Rights Reserved.
     5.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     5.7 + *
     5.8 + * This code is free software; you can redistribute it and/or modify it
     5.9 + * under the terms of the GNU General Public License version 2 only, as
    5.10 + * published by the Free Software Foundation.  Sun designates this
    5.11 + * particular file as subject to the "Classpath" exception as provided
    5.12 + * by Sun in the LICENSE file that accompanied this code.
    5.13 + *
    5.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
    5.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    5.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    5.17 + * version 2 for more details (a copy is included in the LICENSE file that
    5.18 + * accompanied this code).
    5.19 + *
    5.20 + * You should have received a copy of the GNU General Public License version
    5.21 + * 2 along with this work; if not, write to the Free Software Foundation,
    5.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    5.23 + *
    5.24 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
    5.25 + * CA 95054 USA or visit www.sun.com if you need additional information or
    5.26 + * have any questions.
    5.27 + */
    5.28 +
    5.29 +package com.sun.xml.internal;
    5.30 +
    5.31 +import java.io.*;
    5.32 +import java.util.InvalidPropertiesFormatException;
    5.33 +import java.util.Iterator;
    5.34 +import java.util.Properties;
    5.35 +import java.util.Set;
    5.36 +import org.xml.sax.*;
    5.37 +import org.w3c.dom.*;
    5.38 +import javax.xml.parsers.*;
    5.39 +import javax.xml.transform.*;
    5.40 +import javax.xml.transform.dom.*;
    5.41 +import javax.xml.transform.stream.*;
    5.42 +
    5.43 +/**
    5.44 + * A class used to aid in Properties load and save in XML. Keeping this
    5.45 + * code outside of Properties helps reduce the number of classes loaded
    5.46 + * when Properties is loaded.
    5.47 + *
    5.48 + * @author  Michael McCloskey
    5.49 + * @since   1.3
    5.50 + */
    5.51 +public class PropertiesXMLUtilsImpl extends sun.util.xml.PropertiesXMLUtils {
    5.52 +
    5.53 +    public void load(Properties props, InputStream in) throws
    5.54 +            IOException, InvalidPropertiesFormatException {
    5.55 +        doLoad(props, in);
    5.56 +    }
    5.57 +    public void save(Properties props, OutputStream out, String comment, String encoding)
    5.58 +    throws IOException {
    5.59 +        doSave(props, out, comment, encoding);
    5.60 +    }
    5.61 +
    5.62 +
    5.63 +    // XML loading and saving methods for Properties
    5.64 +
    5.65 +    // The required DTD URI for exported properties
    5.66 +    private static final String PROPS_DTD_URI =
    5.67 +    "http://java.sun.com/dtd/properties.dtd";
    5.68 +
    5.69 +    private static final String PROPS_DTD =
    5.70 +    "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
    5.71 +    "<!-- DTD for properties -->"                +
    5.72 +    "<!ELEMENT properties ( comment?, entry* ) >"+
    5.73 +    "<!ATTLIST properties"                       +
    5.74 +        " version CDATA #FIXED \"1.0\">"         +
    5.75 +    "<!ELEMENT comment (#PCDATA) >"              +
    5.76 +    "<!ELEMENT entry (#PCDATA) >"                +
    5.77 +    "<!ATTLIST entry "                           +
    5.78 +        " key CDATA #REQUIRED>";
    5.79 +
    5.80 +    /**
    5.81 +     * Version number for the format of exported properties files.
    5.82 +     */
    5.83 +    private static final String EXTERNAL_XML_VERSION = "1.0";
    5.84 +
    5.85 +    void doLoad(Properties props, InputStream in)
    5.86 +        throws IOException, InvalidPropertiesFormatException
    5.87 +    {
    5.88 +        Document doc = null;
    5.89 +        try {
    5.90 +            doc = getLoadingDoc(in);
    5.91 +        } catch (SAXException saxe) {
    5.92 +            throw new InvalidPropertiesFormatException(saxe);
    5.93 +        }
    5.94 +        Element propertiesElement = (Element)doc.getChildNodes().item(1);
    5.95 +        String xmlVersion = propertiesElement.getAttribute("version");
    5.96 +        if (xmlVersion.compareTo(EXTERNAL_XML_VERSION) > 0)
    5.97 +            throw new InvalidPropertiesFormatException(
    5.98 +                "Exported Properties file format version " + xmlVersion +
    5.99 +                " is not supported. This java installation can read" +
   5.100 +                " versions " + EXTERNAL_XML_VERSION + " or older. You" +
   5.101 +                " may need to install a newer version of JDK.");
   5.102 +        importProperties(props, propertiesElement);
   5.103 +    }
   5.104 +
   5.105 +    static Document getLoadingDoc(InputStream in)
   5.106 +        throws SAXException, IOException
   5.107 +    {
   5.108 +        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
   5.109 +        dbf.setIgnoringElementContentWhitespace(true);
   5.110 +        dbf.setValidating(true);
   5.111 +        dbf.setCoalescing(true);
   5.112 +        dbf.setIgnoringComments(true);
   5.113 +        try {
   5.114 +            DocumentBuilder db = dbf.newDocumentBuilder();
   5.115 +            db.setEntityResolver(new Resolver());
   5.116 +            db.setErrorHandler(new EH());
   5.117 +            InputSource is = new InputSource(in);
   5.118 +            return db.parse(is);
   5.119 +        } catch (ParserConfigurationException x) {
   5.120 +            throw new Error(x);
   5.121 +        }
   5.122 +    }
   5.123 +
   5.124 +    static void importProperties(Properties props, Element propertiesElement) {
   5.125 +        NodeList entries = propertiesElement.getChildNodes();
   5.126 +        int numEntries = entries.getLength();
   5.127 +        int start = numEntries > 0 &&
   5.128 +            entries.item(0).getNodeName().equals("comment") ? 1 : 0;
   5.129 +        for (int i=start; i<numEntries; i++) {
   5.130 +            Element entry = (Element)entries.item(i);
   5.131 +            if (entry.hasAttribute("key")) {
   5.132 +                Node n = entry.getFirstChild();
   5.133 +                String val = (n == null) ? "" : n.getNodeValue();
   5.134 +                props.setProperty(entry.getAttribute("key"), val);
   5.135 +            }
   5.136 +        }
   5.137 +    }
   5.138 +
   5.139 +    void doSave(Properties props, OutputStream os, String comment,
   5.140 +                     String encoding)
   5.141 +        throws IOException
   5.142 +    {
   5.143 +        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
   5.144 +        DocumentBuilder db = null;
   5.145 +        try {
   5.146 +            db = dbf.newDocumentBuilder();
   5.147 +        } catch (ParserConfigurationException pce) {
   5.148 +            assert(false);
   5.149 +        }
   5.150 +        Document doc = db.newDocument();
   5.151 +        Element properties =  (Element)
   5.152 +            doc.appendChild(doc.createElement("properties"));
   5.153 +
   5.154 +        if (comment != null) {
   5.155 +            Element comments = (Element)properties.appendChild(
   5.156 +                doc.createElement("comment"));
   5.157 +            comments.appendChild(doc.createTextNode(comment));
   5.158 +        }
   5.159 +
   5.160 +        Set keys = props.keySet();
   5.161 +        Iterator i = keys.iterator();
   5.162 +        while(i.hasNext()) {
   5.163 +            String key = (String)i.next();
   5.164 +            Element entry = (Element)properties.appendChild(
   5.165 +                doc.createElement("entry"));
   5.166 +            entry.setAttribute("key", key);
   5.167 +            entry.appendChild(doc.createTextNode(props.getProperty(key)));
   5.168 +        }
   5.169 +        emitDocument(doc, os, encoding);
   5.170 +    }
   5.171 +
   5.172 +    static void emitDocument(Document doc, OutputStream os, String encoding)
   5.173 +        throws IOException
   5.174 +    {
   5.175 +        TransformerFactory tf = TransformerFactory.newInstance();
   5.176 +        Transformer t = null;
   5.177 +        try {
   5.178 +            t = tf.newTransformer();
   5.179 +            t.setOutputProperty(OutputKeys.DOCTYPE_SYSTEM, PROPS_DTD_URI);
   5.180 +            t.setOutputProperty(OutputKeys.INDENT, "yes");
   5.181 +            t.setOutputProperty(OutputKeys.METHOD, "xml");
   5.182 +            t.setOutputProperty(OutputKeys.ENCODING, encoding);
   5.183 +        } catch (TransformerConfigurationException tce) {
   5.184 +            assert(false);
   5.185 +        }
   5.186 +        DOMSource doms = new DOMSource(doc);
   5.187 +        StreamResult sr = new StreamResult(os);
   5.188 +        try {
   5.189 +            t.transform(doms, sr);
   5.190 +        } catch (TransformerException te) {
   5.191 +            IOException ioe = new IOException();
   5.192 +            ioe.initCause(te);
   5.193 +            throw ioe;
   5.194 +        }
   5.195 +    }
   5.196 +
   5.197 +    private static class Resolver implements EntityResolver {
   5.198 +        public InputSource resolveEntity(String pid, String sid)
   5.199 +            throws SAXException
   5.200 +        {
   5.201 +            if (sid.equals(PROPS_DTD_URI)) {
   5.202 +                InputSource is;
   5.203 +                is = new InputSource(new StringReader(PROPS_DTD));
   5.204 +                is.setSystemId(PROPS_DTD_URI);
   5.205 +                return is;
   5.206 +            }
   5.207 +            throw new SAXException("Invalid system identifier: " + sid);
   5.208 +        }
   5.209 +    }
   5.210 +
   5.211 +    private static class EH implements ErrorHandler {
   5.212 +        public void error(SAXParseException x) throws SAXException {
   5.213 +            throw x;
   5.214 +        }
   5.215 +        public void fatalError(SAXParseException x) throws SAXException {
   5.216 +            throw x;
   5.217 +        }
   5.218 +        public void warning(SAXParseException x) throws SAXException {
   5.219 +            throw x;
   5.220 +        }
   5.221 +    }
   5.222 +
   5.223 +}
     6.1 --- a/src/share/classes/java/util/Properties.java	Mon Jun 22 18:07:11 2009 +0200
     6.2 +++ b/src/share/classes/java/util/Properties.java	Wed Jun 24 17:51:59 2009 +0200
     6.3 @@ -866,7 +866,7 @@
     6.4      {
     6.5          if (in == null)
     6.6              throw new NullPointerException();
     6.7 -        XMLUtils.load(this, in);
     6.8 +        sun.util.xml.PropertiesXMLUtils.getDefault().load(this, in);
     6.9          in.close();
    6.10      }
    6.11  
    6.12 @@ -931,7 +931,7 @@
    6.13      {
    6.14          if (os == null)
    6.15              throw new NullPointerException();
    6.16 -        XMLUtils.save(this, os, comment, encoding);
    6.17 +        sun.util.xml.PropertiesXMLUtils.getDefault().save(this, os, comment, encoding);
    6.18      }
    6.19  
    6.20      /**
     7.1 --- a/src/share/classes/java/util/XMLUtils.java	Mon Jun 22 18:07:11 2009 +0200
     7.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.3 @@ -1,207 +0,0 @@
     7.4 -/*
     7.5 - * Copyright 2003-2004 Sun Microsystems, Inc.  All Rights Reserved.
     7.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     7.7 - *
     7.8 - * This code is free software; you can redistribute it and/or modify it
     7.9 - * under the terms of the GNU General Public License version 2 only, as
    7.10 - * published by the Free Software Foundation.  Sun designates this
    7.11 - * particular file as subject to the "Classpath" exception as provided
    7.12 - * by Sun in the LICENSE file that accompanied this code.
    7.13 - *
    7.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
    7.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    7.16 - * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    7.17 - * version 2 for more details (a copy is included in the LICENSE file that
    7.18 - * accompanied this code).
    7.19 - *
    7.20 - * You should have received a copy of the GNU General Public License version
    7.21 - * 2 along with this work; if not, write to the Free Software Foundation,
    7.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    7.23 - *
    7.24 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
    7.25 - * CA 95054 USA or visit www.sun.com if you need additional information or
    7.26 - * have any questions.
    7.27 - */
    7.28 -
    7.29 -package java.util;
    7.30 -
    7.31 -import java.io.*;
    7.32 -import org.xml.sax.*;
    7.33 -import org.xml.sax.helpers.*;
    7.34 -import org.w3c.dom.*;
    7.35 -import javax.xml.parsers.*;
    7.36 -import javax.xml.transform.*;
    7.37 -import javax.xml.transform.dom.*;
    7.38 -import javax.xml.transform.stream.*;
    7.39 -
    7.40 -/**
    7.41 - * A class used to aid in Properties load and save in XML. Keeping this
    7.42 - * code outside of Properties helps reduce the number of classes loaded
    7.43 - * when Properties is loaded.
    7.44 - *
    7.45 - * @author  Michael McCloskey
    7.46 - * @since   1.3
    7.47 - */
    7.48 -class XMLUtils {
    7.49 -
    7.50 -    // XML loading and saving methods for Properties
    7.51 -
    7.52 -    // The required DTD URI for exported properties
    7.53 -    private static final String PROPS_DTD_URI =
    7.54 -    "http://java.sun.com/dtd/properties.dtd";
    7.55 -
    7.56 -    private static final String PROPS_DTD =
    7.57 -    "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
    7.58 -    "<!-- DTD for properties -->"                +
    7.59 -    "<!ELEMENT properties ( comment?, entry* ) >"+
    7.60 -    "<!ATTLIST properties"                       +
    7.61 -        " version CDATA #FIXED \"1.0\">"         +
    7.62 -    "<!ELEMENT comment (#PCDATA) >"              +
    7.63 -    "<!ELEMENT entry (#PCDATA) >"                +
    7.64 -    "<!ATTLIST entry "                           +
    7.65 -        " key CDATA #REQUIRED>";
    7.66 -
    7.67 -    /**
    7.68 -     * Version number for the format of exported properties files.
    7.69 -     */
    7.70 -    private static final String EXTERNAL_XML_VERSION = "1.0";
    7.71 -
    7.72 -    static void load(Properties props, InputStream in)
    7.73 -        throws IOException, InvalidPropertiesFormatException
    7.74 -    {
    7.75 -        Document doc = null;
    7.76 -        try {
    7.77 -            doc = getLoadingDoc(in);
    7.78 -        } catch (SAXException saxe) {
    7.79 -            throw new InvalidPropertiesFormatException(saxe);
    7.80 -        }
    7.81 -        Element propertiesElement = (Element)doc.getChildNodes().item(1);
    7.82 -        String xmlVersion = propertiesElement.getAttribute("version");
    7.83 -        if (xmlVersion.compareTo(EXTERNAL_XML_VERSION) > 0)
    7.84 -            throw new InvalidPropertiesFormatException(
    7.85 -                "Exported Properties file format version " + xmlVersion +
    7.86 -                " is not supported. This java installation can read" +
    7.87 -                " versions " + EXTERNAL_XML_VERSION + " or older. You" +
    7.88 -                " may need to install a newer version of JDK.");
    7.89 -        importProperties(props, propertiesElement);
    7.90 -    }
    7.91 -
    7.92 -    static Document getLoadingDoc(InputStream in)
    7.93 -        throws SAXException, IOException
    7.94 -    {
    7.95 -        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
    7.96 -        dbf.setIgnoringElementContentWhitespace(true);
    7.97 -        dbf.setValidating(true);
    7.98 -        dbf.setCoalescing(true);
    7.99 -        dbf.setIgnoringComments(true);
   7.100 -        try {
   7.101 -            DocumentBuilder db = dbf.newDocumentBuilder();
   7.102 -            db.setEntityResolver(new Resolver());
   7.103 -            db.setErrorHandler(new EH());
   7.104 -            InputSource is = new InputSource(in);
   7.105 -            return db.parse(is);
   7.106 -        } catch (ParserConfigurationException x) {
   7.107 -            throw new Error(x);
   7.108 -        }
   7.109 -    }
   7.110 -
   7.111 -    static void importProperties(Properties props, Element propertiesElement) {
   7.112 -        NodeList entries = propertiesElement.getChildNodes();
   7.113 -        int numEntries = entries.getLength();
   7.114 -        int start = numEntries > 0 &&
   7.115 -            entries.item(0).getNodeName().equals("comment") ? 1 : 0;
   7.116 -        for (int i=start; i<numEntries; i++) {
   7.117 -            Element entry = (Element)entries.item(i);
   7.118 -            if (entry.hasAttribute("key")) {
   7.119 -                Node n = entry.getFirstChild();
   7.120 -                String val = (n == null) ? "" : n.getNodeValue();
   7.121 -                props.setProperty(entry.getAttribute("key"), val);
   7.122 -            }
   7.123 -        }
   7.124 -    }
   7.125 -
   7.126 -    static void save(Properties props, OutputStream os, String comment,
   7.127 -                     String encoding)
   7.128 -        throws IOException
   7.129 -    {
   7.130 -        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
   7.131 -        DocumentBuilder db = null;
   7.132 -        try {
   7.133 -            db = dbf.newDocumentBuilder();
   7.134 -        } catch (ParserConfigurationException pce) {
   7.135 -            assert(false);
   7.136 -        }
   7.137 -        Document doc = db.newDocument();
   7.138 -        Element properties =  (Element)
   7.139 -            doc.appendChild(doc.createElement("properties"));
   7.140 -
   7.141 -        if (comment != null) {
   7.142 -            Element comments = (Element)properties.appendChild(
   7.143 -                doc.createElement("comment"));
   7.144 -            comments.appendChild(doc.createTextNode(comment));
   7.145 -        }
   7.146 -
   7.147 -        Set keys = props.keySet();
   7.148 -        Iterator i = keys.iterator();
   7.149 -        while(i.hasNext()) {
   7.150 -            String key = (String)i.next();
   7.151 -            Element entry = (Element)properties.appendChild(
   7.152 -                doc.createElement("entry"));
   7.153 -            entry.setAttribute("key", key);
   7.154 -            entry.appendChild(doc.createTextNode(props.getProperty(key)));
   7.155 -        }
   7.156 -        emitDocument(doc, os, encoding);
   7.157 -    }
   7.158 -
   7.159 -    static void emitDocument(Document doc, OutputStream os, String encoding)
   7.160 -        throws IOException
   7.161 -    {
   7.162 -        TransformerFactory tf = TransformerFactory.newInstance();
   7.163 -        Transformer t = null;
   7.164 -        try {
   7.165 -            t = tf.newTransformer();
   7.166 -            t.setOutputProperty(OutputKeys.DOCTYPE_SYSTEM, PROPS_DTD_URI);
   7.167 -            t.setOutputProperty(OutputKeys.INDENT, "yes");
   7.168 -            t.setOutputProperty(OutputKeys.METHOD, "xml");
   7.169 -            t.setOutputProperty(OutputKeys.ENCODING, encoding);
   7.170 -        } catch (TransformerConfigurationException tce) {
   7.171 -            assert(false);
   7.172 -        }
   7.173 -        DOMSource doms = new DOMSource(doc);
   7.174 -        StreamResult sr = new StreamResult(os);
   7.175 -        try {
   7.176 -            t.transform(doms, sr);
   7.177 -        } catch (TransformerException te) {
   7.178 -            IOException ioe = new IOException();
   7.179 -            ioe.initCause(te);
   7.180 -            throw ioe;
   7.181 -        }
   7.182 -    }
   7.183 -
   7.184 -    private static class Resolver implements EntityResolver {
   7.185 -        public InputSource resolveEntity(String pid, String sid)
   7.186 -            throws SAXException
   7.187 -        {
   7.188 -            if (sid.equals(PROPS_DTD_URI)) {
   7.189 -                InputSource is;
   7.190 -                is = new InputSource(new StringReader(PROPS_DTD));
   7.191 -                is.setSystemId(PROPS_DTD_URI);
   7.192 -                return is;
   7.193 -            }
   7.194 -            throw new SAXException("Invalid system identifier: " + sid);
   7.195 -        }
   7.196 -    }
   7.197 -
   7.198 -    private static class EH implements ErrorHandler {
   7.199 -        public void error(SAXParseException x) throws SAXException {
   7.200 -            throw x;
   7.201 -        }
   7.202 -        public void fatalError(SAXParseException x) throws SAXException {
   7.203 -            throw x;
   7.204 -        }
   7.205 -        public void warning(SAXParseException x) throws SAXException {
   7.206 -            throw x;
   7.207 -        }
   7.208 -    }
   7.209 -
   7.210 -}
     8.1 --- a/src/share/classes/java/util/prefs/AbstractPreferences.java	Mon Jun 22 18:07:11 2009 +0200
     8.2 +++ b/src/share/classes/java/util/prefs/AbstractPreferences.java	Wed Jun 24 17:51:59 2009 +0200
     8.3 @@ -1594,7 +1594,7 @@
     8.4      public void exportNode(OutputStream os)
     8.5          throws IOException, BackingStoreException
     8.6      {
     8.7 -        XmlSupport.export(os, this, false);
     8.8 +        sun.util.xml.PrefsXmlSupport.getDefault().export(os, this, false);
     8.9      }
    8.10  
    8.11      /**
    8.12 @@ -1610,6 +1610,6 @@
    8.13      public void exportSubtree(OutputStream os)
    8.14          throws IOException, BackingStoreException
    8.15      {
    8.16 -        XmlSupport.export(os, this, true);
    8.17 +        sun.util.xml.PrefsXmlSupport.getDefault().export(os, this, true);
    8.18      }
    8.19  }
     9.1 --- a/src/share/classes/java/util/prefs/Preferences.java	Mon Jun 22 18:07:11 2009 +0200
     9.2 +++ b/src/share/classes/java/util/prefs/Preferences.java	Wed Jun 24 17:51:59 2009 +0200
     9.3 @@ -1251,6 +1251,6 @@
     9.4      public static void importPreferences(InputStream is)
     9.5          throws IOException, InvalidPreferencesFormatException
     9.6      {
     9.7 -        XmlSupport.importPreferences(is);
     9.8 +        sun.util.xml.PrefsXmlSupport.getDefault().importPreferences(is);
     9.9      }
    9.10  }
    10.1 --- a/src/share/classes/java/util/prefs/XmlSupport.java	Mon Jun 22 18:07:11 2009 +0200
    10.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    10.3 @@ -1,421 +0,0 @@
    10.4 -/*
    10.5 - * Copyright 2002-2006 Sun Microsystems, Inc.  All Rights Reserved.
    10.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    10.7 - *
    10.8 - * This code is free software; you can redistribute it and/or modify it
    10.9 - * under the terms of the GNU General Public License version 2 only, as
   10.10 - * published by the Free Software Foundation.  Sun designates this
   10.11 - * particular file as subject to the "Classpath" exception as provided
   10.12 - * by Sun in the LICENSE file that accompanied this code.
   10.13 - *
   10.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
   10.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   10.16 - * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   10.17 - * version 2 for more details (a copy is included in the LICENSE file that
   10.18 - * accompanied this code).
   10.19 - *
   10.20 - * You should have received a copy of the GNU General Public License version
   10.21 - * 2 along with this work; if not, write to the Free Software Foundation,
   10.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   10.23 - *
   10.24 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
   10.25 - * CA 95054 USA or visit www.sun.com if you need additional information or
   10.26 - * have any questions.
   10.27 - */
   10.28 -
   10.29 -package java.util.prefs;
   10.30 -
   10.31 -import java.util.*;
   10.32 -import java.io.*;
   10.33 -import javax.xml.parsers.*;
   10.34 -import javax.xml.transform.*;
   10.35 -import javax.xml.transform.dom.*;
   10.36 -import javax.xml.transform.stream.*;
   10.37 -import org.xml.sax.*;
   10.38 -import org.w3c.dom.*;
   10.39 -
   10.40 -/**
   10.41 - * XML Support for java.util.prefs. Methods to import and export preference
   10.42 - * nodes and subtrees.
   10.43 - *
   10.44 - * @author  Josh Bloch and Mark Reinhold
   10.45 - * @see     Preferences
   10.46 - * @since   1.4
   10.47 - */
   10.48 -class XmlSupport {
   10.49 -    // The required DTD URI for exported preferences
   10.50 -    private static final String PREFS_DTD_URI =
   10.51 -        "http://java.sun.com/dtd/preferences.dtd";
   10.52 -
   10.53 -    // The actual DTD corresponding to the URI
   10.54 -    private static final String PREFS_DTD =
   10.55 -        "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
   10.56 -
   10.57 -        "<!-- DTD for preferences -->"               +
   10.58 -
   10.59 -        "<!ELEMENT preferences (root) >"             +
   10.60 -        "<!ATTLIST preferences"                      +
   10.61 -        " EXTERNAL_XML_VERSION CDATA \"0.0\"  >"     +
   10.62 -
   10.63 -        "<!ELEMENT root (map, node*) >"              +
   10.64 -        "<!ATTLIST root"                             +
   10.65 -        "          type (system|user) #REQUIRED >"   +
   10.66 -
   10.67 -        "<!ELEMENT node (map, node*) >"              +
   10.68 -        "<!ATTLIST node"                             +
   10.69 -        "          name CDATA #REQUIRED >"           +
   10.70 -
   10.71 -        "<!ELEMENT map (entry*) >"                   +
   10.72 -        "<!ATTLIST map"                              +
   10.73 -        "  MAP_XML_VERSION CDATA \"0.0\"  >"         +
   10.74 -        "<!ELEMENT entry EMPTY >"                    +
   10.75 -        "<!ATTLIST entry"                            +
   10.76 -        "          key CDATA #REQUIRED"              +
   10.77 -        "          value CDATA #REQUIRED >"          ;
   10.78 -    /**
   10.79 -     * Version number for the format exported preferences files.
   10.80 -     */
   10.81 -    private static final String EXTERNAL_XML_VERSION = "1.0";
   10.82 -
   10.83 -    /*
   10.84 -     * Version number for the internal map files.
   10.85 -     */
   10.86 -    private static final String MAP_XML_VERSION = "1.0";
   10.87 -
   10.88 -    /**
   10.89 -     * Export the specified preferences node and, if subTree is true, all
   10.90 -     * subnodes, to the specified output stream.  Preferences are exported as
   10.91 -     * an XML document conforming to the definition in the Preferences spec.
   10.92 -     *
   10.93 -     * @throws IOException if writing to the specified output stream
   10.94 -     *         results in an <tt>IOException</tt>.
   10.95 -     * @throws BackingStoreException if preference data cannot be read from
   10.96 -     *         backing store.
   10.97 -     * @throws IllegalStateException if this node (or an ancestor) has been
   10.98 -     *         removed with the {@link #removeNode()} method.
   10.99 -     */
  10.100 -    static void export(OutputStream os, final Preferences p, boolean subTree)
  10.101 -        throws IOException, BackingStoreException {
  10.102 -        if (((AbstractPreferences)p).isRemoved())
  10.103 -            throw new IllegalStateException("Node has been removed");
  10.104 -        Document doc = createPrefsDoc("preferences");
  10.105 -        Element preferences =  doc.getDocumentElement() ;
  10.106 -        preferences.setAttribute("EXTERNAL_XML_VERSION", EXTERNAL_XML_VERSION);
  10.107 -        Element xmlRoot =  (Element)
  10.108 -        preferences.appendChild(doc.createElement("root"));
  10.109 -        xmlRoot.setAttribute("type", (p.isUserNode() ? "user" : "system"));
  10.110 -
  10.111 -        // Get bottom-up list of nodes from p to root, excluding root
  10.112 -        List ancestors = new ArrayList();
  10.113 -
  10.114 -        for (Preferences kid = p, dad = kid.parent(); dad != null;
  10.115 -                                   kid = dad, dad = kid.parent()) {
  10.116 -            ancestors.add(kid);
  10.117 -        }
  10.118 -        Element e = xmlRoot;
  10.119 -        for (int i=ancestors.size()-1; i >= 0; i--) {
  10.120 -            e.appendChild(doc.createElement("map"));
  10.121 -            e = (Element) e.appendChild(doc.createElement("node"));
  10.122 -            e.setAttribute("name", ((Preferences)ancestors.get(i)).name());
  10.123 -        }
  10.124 -        putPreferencesInXml(e, doc, p, subTree);
  10.125 -
  10.126 -        writeDoc(doc, os);
  10.127 -    }
  10.128 -
  10.129 -    /**
  10.130 -     * Put the preferences in the specified Preferences node into the
  10.131 -     * specified XML element which is assumed to represent a node
  10.132 -     * in the specified XML document which is assumed to conform to
  10.133 -     * PREFS_DTD.  If subTree is true, create children of the specified
  10.134 -     * XML node conforming to all of the children of the specified
  10.135 -     * Preferences node and recurse.
  10.136 -     *
  10.137 -     * @throws BackingStoreException if it is not possible to read
  10.138 -     *         the preferences or children out of the specified
  10.139 -     *         preferences node.
  10.140 -     */
  10.141 -    private static void putPreferencesInXml(Element elt, Document doc,
  10.142 -               Preferences prefs, boolean subTree) throws BackingStoreException
  10.143 -    {
  10.144 -        Preferences[] kidsCopy = null;
  10.145 -        String[] kidNames = null;
  10.146 -
  10.147 -        // Node is locked to export its contents and get a
  10.148 -        // copy of children, then lock is released,
  10.149 -        // and, if subTree = true, recursive calls are made on children
  10.150 -        synchronized (((AbstractPreferences)prefs).lock) {
  10.151 -            // Check if this node was concurrently removed. If yes
  10.152 -            // remove it from XML Document and return.
  10.153 -            if (((AbstractPreferences)prefs).isRemoved()) {
  10.154 -                elt.getParentNode().removeChild(elt);
  10.155 -                return;
  10.156 -            }
  10.157 -            // Put map in xml element
  10.158 -            String[] keys = prefs.keys();
  10.159 -            Element map = (Element) elt.appendChild(doc.createElement("map"));
  10.160 -            for (int i=0; i<keys.length; i++) {
  10.161 -                Element entry = (Element)
  10.162 -                    map.appendChild(doc.createElement("entry"));
  10.163 -                entry.setAttribute("key", keys[i]);
  10.164 -                // NEXT STATEMENT THROWS NULL PTR EXC INSTEAD OF ASSERT FAIL
  10.165 -                entry.setAttribute("value", prefs.get(keys[i], null));
  10.166 -            }
  10.167 -            // Recurse if appropriate
  10.168 -            if (subTree) {
  10.169 -                /* Get a copy of kids while lock is held */
  10.170 -                kidNames = prefs.childrenNames();
  10.171 -                kidsCopy = new Preferences[kidNames.length];
  10.172 -                for (int i = 0; i <  kidNames.length; i++)
  10.173 -                    kidsCopy[i] = prefs.node(kidNames[i]);
  10.174 -            }
  10.175 -            // release lock
  10.176 -        }
  10.177 -
  10.178 -        if (subTree) {
  10.179 -            for (int i=0; i < kidNames.length; i++) {
  10.180 -                Element xmlKid = (Element)
  10.181 -                    elt.appendChild(doc.createElement("node"));
  10.182 -                xmlKid.setAttribute("name", kidNames[i]);
  10.183 -                putPreferencesInXml(xmlKid, doc, kidsCopy[i], subTree);
  10.184 -            }
  10.185 -        }
  10.186 -    }
  10.187 -
  10.188 -    /**
  10.189 -     * Import preferences from the specified input stream, which is assumed
  10.190 -     * to contain an XML document in the format described in the Preferences
  10.191 -     * spec.
  10.192 -     *
  10.193 -     * @throws IOException if reading from the specified output stream
  10.194 -     *         results in an <tt>IOException</tt>.
  10.195 -     * @throws InvalidPreferencesFormatException Data on input stream does not
  10.196 -     *         constitute a valid XML document with the mandated document type.
  10.197 -     */
  10.198 -    static void importPreferences(InputStream is)
  10.199 -        throws IOException, InvalidPreferencesFormatException
  10.200 -    {
  10.201 -        try {
  10.202 -            Document doc = loadPrefsDoc(is);
  10.203 -            String xmlVersion =
  10.204 -                doc.getDocumentElement().getAttribute("EXTERNAL_XML_VERSION");
  10.205 -            if (xmlVersion.compareTo(EXTERNAL_XML_VERSION) > 0)
  10.206 -                throw new InvalidPreferencesFormatException(
  10.207 -                "Exported preferences file format version " + xmlVersion +
  10.208 -                " is not supported. This java installation can read" +
  10.209 -                " versions " + EXTERNAL_XML_VERSION + " or older. You may need" +
  10.210 -                " to install a newer version of JDK.");
  10.211 -
  10.212 -            Element xmlRoot = (Element) doc.getDocumentElement().
  10.213 -                                               getChildNodes().item(0);
  10.214 -            Preferences prefsRoot =
  10.215 -                (xmlRoot.getAttribute("type").equals("user") ?
  10.216 -                            Preferences.userRoot() : Preferences.systemRoot());
  10.217 -            ImportSubtree(prefsRoot, xmlRoot);
  10.218 -        } catch(SAXException e) {
  10.219 -            throw new InvalidPreferencesFormatException(e);
  10.220 -        }
  10.221 -    }
  10.222 -
  10.223 -    /**
  10.224 -     * Create a new prefs XML document.
  10.225 -     */
  10.226 -    private static Document createPrefsDoc( String qname ) {
  10.227 -        try {
  10.228 -            DOMImplementation di = DocumentBuilderFactory.newInstance().
  10.229 -                newDocumentBuilder().getDOMImplementation();
  10.230 -            DocumentType dt = di.createDocumentType(qname, null, PREFS_DTD_URI);
  10.231 -            return di.createDocument(null, qname, dt);
  10.232 -        } catch(ParserConfigurationException e) {
  10.233 -            throw new AssertionError(e);
  10.234 -        }
  10.235 -    }
  10.236 -
  10.237 -    /**
  10.238 -     * Load an XML document from specified input stream, which must
  10.239 -     * have the requisite DTD URI.
  10.240 -     */
  10.241 -    private static Document loadPrefsDoc(InputStream in)
  10.242 -        throws SAXException, IOException
  10.243 -    {
  10.244 -        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
  10.245 -        dbf.setIgnoringElementContentWhitespace(true);
  10.246 -        dbf.setValidating(true);
  10.247 -        dbf.setCoalescing(true);
  10.248 -        dbf.setIgnoringComments(true);
  10.249 -        try {
  10.250 -            DocumentBuilder db = dbf.newDocumentBuilder();
  10.251 -            db.setEntityResolver(new Resolver());
  10.252 -            db.setErrorHandler(new EH());
  10.253 -            return db.parse(new InputSource(in));
  10.254 -        } catch (ParserConfigurationException e) {
  10.255 -            throw new AssertionError(e);
  10.256 -        }
  10.257 -    }
  10.258 -
  10.259 -    /**
  10.260 -     * Write XML document to the specified output stream.
  10.261 -     */
  10.262 -    private static final void writeDoc(Document doc, OutputStream out)
  10.263 -        throws IOException
  10.264 -    {
  10.265 -        try {
  10.266 -            TransformerFactory tf = TransformerFactory.newInstance();
  10.267 -            try {
  10.268 -                tf.setAttribute("indent-number", new Integer(2));
  10.269 -            } catch (IllegalArgumentException iae) {
  10.270 -                //Ignore the IAE. Should not fail the writeout even the
  10.271 -                //transformer provider does not support "indent-number".
  10.272 -            }
  10.273 -            Transformer t = tf.newTransformer();
  10.274 -            t.setOutputProperty(OutputKeys.DOCTYPE_SYSTEM, doc.getDoctype().getSystemId());
  10.275 -            t.setOutputProperty(OutputKeys.INDENT, "yes");
  10.276 -            //Transformer resets the "indent" info if the "result" is a StreamResult with
  10.277 -            //an OutputStream object embedded, creating a Writer object on top of that
  10.278 -            //OutputStream object however works.
  10.279 -            t.transform(new DOMSource(doc),
  10.280 -                        new StreamResult(new BufferedWriter(new OutputStreamWriter(out, "UTF-8"))));
  10.281 -        } catch(TransformerException e) {
  10.282 -            throw new AssertionError(e);
  10.283 -        }
  10.284 -    }
  10.285 -
  10.286 -    /**
  10.287 -     * Recursively traverse the specified preferences node and store
  10.288 -     * the described preferences into the system or current user
  10.289 -     * preferences tree, as appropriate.
  10.290 -     */
  10.291 -    private static void ImportSubtree(Preferences prefsNode, Element xmlNode) {
  10.292 -        NodeList xmlKids = xmlNode.getChildNodes();
  10.293 -        int numXmlKids = xmlKids.getLength();
  10.294 -        /*
  10.295 -         * We first lock the node, import its contents and get
  10.296 -         * child nodes. Then we unlock the node and go to children
  10.297 -         * Since some of the children might have been concurrently
  10.298 -         * deleted we check for this.
  10.299 -         */
  10.300 -        Preferences[] prefsKids;
  10.301 -        /* Lock the node */
  10.302 -        synchronized (((AbstractPreferences)prefsNode).lock) {
  10.303 -            //If removed, return silently
  10.304 -            if (((AbstractPreferences)prefsNode).isRemoved())
  10.305 -                return;
  10.306 -
  10.307 -            // Import any preferences at this node
  10.308 -            Element firstXmlKid = (Element) xmlKids.item(0);
  10.309 -            ImportPrefs(prefsNode, firstXmlKid);
  10.310 -            prefsKids = new Preferences[numXmlKids - 1];
  10.311 -
  10.312 -            // Get involved children
  10.313 -            for (int i=1; i < numXmlKids; i++) {
  10.314 -                Element xmlKid = (Element) xmlKids.item(i);
  10.315 -                prefsKids[i-1] = prefsNode.node(xmlKid.getAttribute("name"));
  10.316 -            }
  10.317 -        } // unlocked the node
  10.318 -        // import children
  10.319 -        for (int i=1; i < numXmlKids; i++)
  10.320 -            ImportSubtree(prefsKids[i-1], (Element)xmlKids.item(i));
  10.321 -    }
  10.322 -
  10.323 -    /**
  10.324 -     * Import the preferences described by the specified XML element
  10.325 -     * (a map from a preferences document) into the specified
  10.326 -     * preferences node.
  10.327 -     */
  10.328 -    private static void ImportPrefs(Preferences prefsNode, Element map) {
  10.329 -        NodeList entries = map.getChildNodes();
  10.330 -        for (int i=0, numEntries = entries.getLength(); i < numEntries; i++) {
  10.331 -            Element entry = (Element) entries.item(i);
  10.332 -            prefsNode.put(entry.getAttribute("key"),
  10.333 -                          entry.getAttribute("value"));
  10.334 -        }
  10.335 -    }
  10.336 -
  10.337 -    /**
  10.338 -     * Export the specified Map<String,String> to a map document on
  10.339 -     * the specified OutputStream as per the prefs DTD.  This is used
  10.340 -     * as the internal (undocumented) format for FileSystemPrefs.
  10.341 -     *
  10.342 -     * @throws IOException if writing to the specified output stream
  10.343 -     *         results in an <tt>IOException</tt>.
  10.344 -     */
  10.345 -    static void exportMap(OutputStream os, Map map) throws IOException {
  10.346 -        Document doc = createPrefsDoc("map");
  10.347 -        Element xmlMap = doc.getDocumentElement( ) ;
  10.348 -        xmlMap.setAttribute("MAP_XML_VERSION", MAP_XML_VERSION);
  10.349 -
  10.350 -        for (Iterator i = map.entrySet().iterator(); i.hasNext(); ) {
  10.351 -            Map.Entry e = (Map.Entry) i.next();
  10.352 -            Element xe = (Element)
  10.353 -                xmlMap.appendChild(doc.createElement("entry"));
  10.354 -            xe.setAttribute("key",   (String) e.getKey());
  10.355 -            xe.setAttribute("value", (String) e.getValue());
  10.356 -        }
  10.357 -
  10.358 -        writeDoc(doc, os);
  10.359 -    }
  10.360 -
  10.361 -    /**
  10.362 -     * Import Map from the specified input stream, which is assumed
  10.363 -     * to contain a map document as per the prefs DTD.  This is used
  10.364 -     * as the internal (undocumented) format for FileSystemPrefs.  The
  10.365 -     * key-value pairs specified in the XML document will be put into
  10.366 -     * the specified Map.  (If this Map is empty, it will contain exactly
  10.367 -     * the key-value pairs int the XML-document when this method returns.)
  10.368 -     *
  10.369 -     * @throws IOException if reading from the specified output stream
  10.370 -     *         results in an <tt>IOException</tt>.
  10.371 -     * @throws InvalidPreferencesFormatException Data on input stream does not
  10.372 -     *         constitute a valid XML document with the mandated document type.
  10.373 -     */
  10.374 -    static void importMap(InputStream is, Map m)
  10.375 -        throws IOException, InvalidPreferencesFormatException
  10.376 -    {
  10.377 -        try {
  10.378 -            Document doc = loadPrefsDoc(is);
  10.379 -            Element xmlMap = doc.getDocumentElement();
  10.380 -            // check version
  10.381 -            String mapVersion = xmlMap.getAttribute("MAP_XML_VERSION");
  10.382 -            if (mapVersion.compareTo(MAP_XML_VERSION) > 0)
  10.383 -                throw new InvalidPreferencesFormatException(
  10.384 -                "Preferences map file format version " + mapVersion +
  10.385 -                " is not supported. This java installation can read" +
  10.386 -                " versions " + MAP_XML_VERSION + " or older. You may need" +
  10.387 -                " to install a newer version of JDK.");
  10.388 -
  10.389 -            NodeList entries = xmlMap.getChildNodes();
  10.390 -            for (int i=0, numEntries=entries.getLength(); i<numEntries; i++) {
  10.391 -                Element entry = (Element) entries.item(i);
  10.392 -                m.put(entry.getAttribute("key"), entry.getAttribute("value"));
  10.393 -            }
  10.394 -        } catch(SAXException e) {
  10.395 -            throw new InvalidPreferencesFormatException(e);
  10.396 -        }
  10.397 -    }
  10.398 -
  10.399 -    private static class Resolver implements EntityResolver {
  10.400 -        public InputSource resolveEntity(String pid, String sid)
  10.401 -            throws SAXException
  10.402 -        {
  10.403 -            if (sid.equals(PREFS_DTD_URI)) {
  10.404 -                InputSource is;
  10.405 -                is = new InputSource(new StringReader(PREFS_DTD));
  10.406 -                is.setSystemId(PREFS_DTD_URI);
  10.407 -                return is;
  10.408 -            }
  10.409 -            throw new SAXException("Invalid system identifier: " + sid);
  10.410 -        }
  10.411 -    }
  10.412 -
  10.413 -    private static class EH implements ErrorHandler {
  10.414 -        public void error(SAXParseException x) throws SAXException {
  10.415 -            throw x;
  10.416 -        }
  10.417 -        public void fatalError(SAXParseException x) throws SAXException {
  10.418 -            throw x;
  10.419 -        }
  10.420 -        public void warning(SAXParseException x) throws SAXException {
  10.421 -            throw x;
  10.422 -        }
  10.423 -    }
  10.424 -}
    11.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    11.2 +++ b/src/share/classes/sun/util/xml/DefaultPrefsXmlSupport.java	Wed Jun 24 17:51:59 2009 +0200
    11.3 @@ -0,0 +1,361 @@
    11.4 +/*
    11.5 + * Copyright 2002-2006 Sun Microsystems, Inc.  All Rights Reserved.
    11.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    11.7 + *
    11.8 + * This code is free software; you can redistribute it and/or modify it
    11.9 + * under the terms of the GNU General Public License version 2 only, as
   11.10 + * published by the Free Software Foundation.  Sun designates this
   11.11 + * particular file as subject to the "Classpath" exception as provided
   11.12 + * by Sun in the LICENSE file that accompanied this code.
   11.13 + *
   11.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   11.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   11.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   11.17 + * version 2 for more details (a copy is included in the LICENSE file that
   11.18 + * accompanied this code).
   11.19 + *
   11.20 + * You should have received a copy of the GNU General Public License version
   11.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   11.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   11.23 + *
   11.24 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
   11.25 + * CA 95054 USA or visit www.sun.com if you need additional information or
   11.26 + * have any questions.
   11.27 + */
   11.28 +
   11.29 +package sun.util.xml;
   11.30 +
   11.31 +import java.util.*;
   11.32 +import java.util.prefs.*;
   11.33 +import java.io.*;
   11.34 +
   11.35 +/**
   11.36 + * Simplified XML Support for java.util.prefs. Methods to import and export preference
   11.37 + * nodes and subtrees.
   11.38 + *
   11.39 + * @author  Jaroslav Tulach
   11.40 + * @since   1.7
   11.41 + */
   11.42 +public class DefaultPrefsXmlSupport extends sun.util.xml.PrefsXmlSupport {
   11.43 +    public void export(OutputStream os, final Preferences p, boolean subTree)
   11.44 +        throws IOException, BackingStoreException {
   11.45 +        if (isRemoved(p))
   11.46 +            throw new IllegalStateException("Node has been removed");
   11.47 +        PrintWriter w = new PrintWriter(new OutputStreamWriter(os, "UTF-8"));
   11.48 +        w.println("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>");
   11.49 +        w.println("<!DOCTYPE preferences SYSTEM \"http://java.sun.com/dtd/preferences.dtd\">");
   11.50 +        w.println("<preferences EXTERNAL_XML_VERSION=\"1.0\">");
   11.51 +        w.print("  <root type=\"");
   11.52 +        w.print(p.isUserNode() ? "user" : "system");
   11.53 +        w.println("\">");
   11.54 +        LinkedList<Preferences> ancestors = new LinkedList<Preferences>();
   11.55 +        for (Preferences kid = p, dad = kid.parent(); dad != null;
   11.56 +                kid = dad, dad = kid.parent()) {
   11.57 +            ancestors.addFirst(kid);
   11.58 +        }
   11.59 +        String indent = "  ";
   11.60 +        for (Preferences pref : ancestors) {
   11.61 +            indent = "  " + indent;
   11.62 +            w.print(indent); w.println("<map/>");
   11.63 +            w.print(indent); w.print("<node name=\""); w.print(pref.name()); w.println("\">");
   11.64 +        }
   11.65 +
   11.66 +        putPreferencesInXml(w, indent + "  ", p, subTree);
   11.67 +        for (Preferences pref : ancestors) {
   11.68 +            w.print(indent); w.println("</node>");
   11.69 +            indent = indent.substring(2);
   11.70 +        }
   11.71 +
   11.72 +        w.println("  </root>");
   11.73 +        w.println("</preferences>");
   11.74 +        w.flush();
   11.75 +    }
   11.76 +
   11.77 +    private static void putPreferencesInXml(
   11.78 +        PrintWriter w, String indent, Preferences prefs, boolean subTree
   11.79 +    ) throws BackingStoreException {
   11.80 +        Preferences[] kidsCopy = null;
   11.81 +        String[] kidNames = null;
   11.82 +
   11.83 +        // Node is locked to export its contents and get a
   11.84 +        // copy of children, then lock is released,
   11.85 +        // and, if subTree = true, recursive calls are made on children
   11.86 +        synchronized (lock(prefs)) {
   11.87 +            // Check if this node was concurrently removed. If yes
   11.88 +            // don't print it
   11.89 +            if (isRemoved(prefs)) {
   11.90 +                return;
   11.91 +            }
   11.92 +            // Put map in xml element
   11.93 +            String[] keys = prefs.keys();
   11.94 +            if (keys.length == 0) {
   11.95 +                w.print(indent); w.println("<map/>");
   11.96 +            } else {
   11.97 +                w.print(indent); w.println("<map>");
   11.98 +                for (int i=0; i<keys.length; i++) {
   11.99 +                    w.print(indent); w.print("  <entry key=\"");
  11.100 +                    w.print(keys[i]);
  11.101 +                    w.print("\" value=\"");
  11.102 +                    w.print(prefs.get(keys[i], null));
  11.103 +                    w.println("\"/>");
  11.104 +                }
  11.105 +                w.print(indent); w.println("</map>");
  11.106 +            }
  11.107 +            // Recurse if appropriate
  11.108 +            if (subTree) {
  11.109 +                /* Get a copy of kids while lock is held */
  11.110 +                kidNames = prefs.childrenNames();
  11.111 +                kidsCopy = new Preferences[kidNames.length];
  11.112 +                for (int i = 0; i <  kidNames.length; i++)
  11.113 +                    kidsCopy[i] = prefs.node(kidNames[i]);
  11.114 +            }
  11.115 +            // release lock
  11.116 +        }
  11.117 +
  11.118 +        if (subTree) {
  11.119 +            for (int i=0; i < kidNames.length; i++) {
  11.120 +                w.print(indent); w.print("<node name=\"");
  11.121 +                w.print(kidNames[i]);
  11.122 +                w.println("\">");
  11.123 +                putPreferencesInXml(w, "  " + indent, kidsCopy[i], subTree);
  11.124 +                w.print(indent); w.println("</node>");
  11.125 +            }
  11.126 +        }
  11.127 +    }
  11.128 +
  11.129 +    /**
  11.130 +     * Import preferences from the specified input stream, which is assumed
  11.131 +     * to contain an XML document in the format described in the Preferences
  11.132 +     * spec.
  11.133 +     *
  11.134 +     * @throws IOException if reading from the specified output stream
  11.135 +     *         results in an <tt>IOException</tt>.
  11.136 +     * @throws InvalidPreferencesFormatException Data on input stream does not
  11.137 +     *         constitute a valid XML document with the mandated document type.
  11.138 +     */
  11.139 +    public void importPreferences(InputStream is)
  11.140 +        throws IOException, InvalidPreferencesFormatException
  11.141 +    {
  11.142 +        try {
  11.143 +            XMLElement doc = new XMLElement();
  11.144 +            doc.parseFromReader(new InputStreamReader(is, "UTF-8"));
  11.145 +            String xmlVersion = (String)doc.getAttribute("EXTERNAL_XML_VERSION");
  11.146 +            if (xmlVersion.compareTo("1.0") > 0)
  11.147 +                throw new InvalidPreferencesFormatException(
  11.148 +                "Exported preferences file format version " + xmlVersion +
  11.149 +                " is not supported. This java installation can read" +
  11.150 +                " versions " + "1.0" + " or older. You may need" +
  11.151 +                " to install a newer version of JDK.");
  11.152 +
  11.153 +            XMLElement xmlRoot = (XMLElement) doc.getChildren().get(0);
  11.154 +            Preferences prefsRoot =
  11.155 +                (xmlRoot.getAttribute("type").equals("user") ?
  11.156 +                            Preferences.userRoot() : Preferences.systemRoot());
  11.157 +            ImportSubtree(prefsRoot, xmlRoot);
  11.158 +        } catch(XMLParseException e) {
  11.159 +            throw new InvalidPreferencesFormatException(e);
  11.160 +        }
  11.161 +    }
  11.162 +
  11.163 +    /**
  11.164 +     * Create a new prefs XML document.
  11.165 +     *
  11.166 +    private static Document createPrefsDoc( String qname ) {
  11.167 +        try {
  11.168 +            DOMImplementation di = DocumentBuilderFactory.newInstance().
  11.169 +                newDocumentBuilder().getDOMImplementation();
  11.170 +            DocumentType dt = di.createDocumentType(qname, null, PREFS_DTD_URI);
  11.171 +            return di.createDocument(null, qname, dt);
  11.172 +        } catch(ParserConfigurationException e) {
  11.173 +            throw new AssertionError(e);
  11.174 +        }
  11.175 +    }
  11.176 +
  11.177 +
  11.178 +    /**
  11.179 +     * Write XML document to the specified output stream.
  11.180 +     *
  11.181 +    private static final void writeDoc(Document doc, OutputStream out)
  11.182 +        throws IOException
  11.183 +    {
  11.184 +        try {
  11.185 +            TransformerFactory tf = TransformerFactory.newInstance();
  11.186 +            try {
  11.187 +                tf.setAttribute("indent-number", new Integer(2));
  11.188 +            } catch (IllegalArgumentException iae) {
  11.189 +                //Ignore the IAE. Should not fail the writeout even the
  11.190 +                //transformer provider does not support "indent-number".
  11.191 +            }
  11.192 +            Transformer t = tf.newTransformer();
  11.193 +            t.setOutputProperty(OutputKeys.DOCTYPE_SYSTEM, doc.getDoctype().getSystemId());
  11.194 +            t.setOutputProperty(OutputKeys.INDENT, "yes");
  11.195 +            //Transformer resets the "indent" info if the "result" is a StreamResult with
  11.196 +            //an OutputStream object embedded, creating a Writer object on top of that
  11.197 +            //OutputStream object however works.
  11.198 +            t.transform(new DOMSource(doc),
  11.199 +                        new StreamResult(new BufferedWriter(new OutputStreamWriter(out, "UTF-8"))));
  11.200 +        } catch(TransformerException e) {
  11.201 +            throw new AssertionError(e);
  11.202 +        }
  11.203 +    }
  11.204 +
  11.205 +    /**
  11.206 +     * Recursively traverse the specified preferences node and store
  11.207 +     * the described preferences into the system or current user
  11.208 +     * preferences tree, as appropriate.
  11.209 +     */
  11.210 +    private static void ImportSubtree(Preferences prefsNode, XMLElement xmlNode) {
  11.211 +        Vector xmlKids = xmlNode.getChildren();
  11.212 +        int numXmlKids = xmlKids.size();
  11.213 +        /*
  11.214 +         * We first lock the node, import its contents and get
  11.215 +         * child nodes. Then we unlock the node and go to children
  11.216 +         * Since some of the children might have been concurrently
  11.217 +         * deleted we check for this.
  11.218 +         */
  11.219 +        Preferences[] prefsKids;
  11.220 +        /* Lock the node */
  11.221 +        synchronized (lock(prefsNode)) {
  11.222 +            //If removed, return silently
  11.223 +            if (isRemoved(prefsNode))
  11.224 +                return;
  11.225 +
  11.226 +            // Import any preferences at this node
  11.227 +            XMLElement firstXmlKid = (XMLElement) xmlKids.get(0);
  11.228 +            ImportPrefs(prefsNode, firstXmlKid);
  11.229 +            prefsKids = new Preferences[numXmlKids - 1];
  11.230 +
  11.231 +            // Get involved children
  11.232 +            for (int i=1; i < numXmlKids; i++) {
  11.233 +                XMLElement xmlKid = (XMLElement) xmlKids.get(i);
  11.234 +                prefsKids[i-1] = prefsNode.node((String)xmlKid.getAttribute("name"));
  11.235 +            }
  11.236 +        } // unlocked the node
  11.237 +        // import children
  11.238 +        for (int i=1; i < numXmlKids; i++)
  11.239 +            ImportSubtree(prefsKids[i-1], (XMLElement)xmlKids.get(i));
  11.240 +    }
  11.241 +
  11.242 +    /**
  11.243 +     * Import the preferences described by the specified XML element
  11.244 +     * (a map from a preferences document) into the specified
  11.245 +     * preferences node.
  11.246 +     */
  11.247 +    private static void ImportPrefs(Preferences prefsNode, XMLElement map) {
  11.248 +        Vector entries = map.getChildren();
  11.249 +        for (int i=0, numEntries = entries.size(); i < numEntries; i++) {
  11.250 +            XMLElement entry = (XMLElement) entries.get(i);
  11.251 +            prefsNode.put((String)entry.getAttribute("key"),
  11.252 +                          (String)entry.getAttribute("value"));
  11.253 +        }
  11.254 +    }
  11.255 +
  11.256 +    /**
  11.257 +     * Export the specified Map<String,String> to a map document on
  11.258 +     * the specified OutputStream as per the prefs DTD.  This is used
  11.259 +     * as the internal (undocumented) format for FileSystemPrefs.
  11.260 +     *
  11.261 +     * @throws IOException if writing to the specified output stream
  11.262 +     *         results in an <tt>IOException</tt>.
  11.263 +     */
  11.264 +    public void exportMap(OutputStream os, Map map) throws IOException {
  11.265 +        /*
  11.266 +        Document doc = createPrefsDoc("map");
  11.267 +        Element xmlMap = doc.getDocumentElement( ) ;
  11.268 +        xmlMap.setAttribute("MAP_XML_VERSION", MAP_XML_VERSION);
  11.269 +
  11.270 +        for (Iterator i = map.entrySet().iterator(); i.hasNext(); ) {
  11.271 +            Map.Entry e = (Map.Entry) i.next();
  11.272 +            Element xe = (Element)
  11.273 +                xmlMap.appendChild(doc.createElement("entry"));
  11.274 +            xe.setAttribute("key",   (String) e.getKey());
  11.275 +            xe.setAttribute("value", (String) e.getValue());
  11.276 +        }
  11.277 +
  11.278 +        writeDoc(doc, os);
  11.279 +         */
  11.280 +    }
  11.281 +
  11.282 +    /**
  11.283 +     * Import Map from the specified input stream, which is assumed
  11.284 +     * to contain a map document as per the prefs DTD.  This is used
  11.285 +     * as the internal (undocumented) format for FileSystemPrefs.  The
  11.286 +     * key-value pairs specified in the XML document will be put into
  11.287 +     * the specified Map.  (If this Map is empty, it will contain exactly
  11.288 +     * the key-value pairs int the XML-document when this method returns.)
  11.289 +     *
  11.290 +     * @throws IOException if reading from the specified output stream
  11.291 +     *         results in an <tt>IOException</tt>.
  11.292 +     * @throws InvalidPreferencesFormatException Data on input stream does not
  11.293 +     *         constitute a valid XML document with the mandated document type.
  11.294 +     */
  11.295 +    public void importMap(InputStream is, Map m)
  11.296 +        throws IOException, InvalidPreferencesFormatException
  11.297 +    {
  11.298 +        /*
  11.299 +        try {
  11.300 +            Document doc = loadPrefsDoc(is);
  11.301 +            Element xmlMap = doc.getDocumentElement();
  11.302 +            // check version
  11.303 +            String mapVersion = xmlMap.getAttribute("MAP_XML_VERSION");
  11.304 +            if (mapVersion.compareTo(MAP_XML_VERSION) > 0)
  11.305 +                throw new InvalidPreferencesFormatException(
  11.306 +                "Preferences map file format version " + mapVersion +
  11.307 +                " is not supported. This java installation can read" +
  11.308 +                " versions " + MAP_XML_VERSION + " or older. You may need" +
  11.309 +                " to install a newer version of JDK.");
  11.310 +
  11.311 +            NodeList entries = xmlMap.getChildNodes();
  11.312 +            for (int i=0, numEntries=entries.getLength(); i<numEntries; i++) {
  11.313 +                Element entry = (Element) entries.item(i);
  11.314 +                m.put(entry.getAttribute("key"), entry.getAttribute("value"));
  11.315 +            }
  11.316 +        } catch(SAXException e) {
  11.317 +            throw new InvalidPreferencesFormatException(e);
  11.318 +        }
  11.319 +         */
  11.320 +    }
  11.321 +/*
  11.322 +    private static class Resolver implements EntityResolver {
  11.323 +        public InputSource resolveEntity(String pid, String sid)
  11.324 +            throws SAXException
  11.325 +        {
  11.326 +            if (sid.equals(PREFS_DTD_URI)) {
  11.327 +                InputSource is;
  11.328 +                is = new InputSource(new StringReader(PREFS_DTD));
  11.329 +                is.setSystemId(PREFS_DTD_URI);
  11.330 +                return is;
  11.331 +            }
  11.332 +            throw new SAXException("Invalid system identifier: " + sid);
  11.333 +        }
  11.334 +    }
  11.335 +
  11.336 +    private static class EH implements ErrorHandler {
  11.337 +        public void error(SAXParseException x) throws SAXException {
  11.338 +            throw x;
  11.339 +        }
  11.340 +        public void fatalError(SAXParseException x) throws SAXException {
  11.341 +            throw x;
  11.342 +        }
  11.343 +        public void warning(SAXParseException x) throws SAXException {
  11.344 +            throw x;
  11.345 +        }
  11.346 +    }
  11.347 +*/
  11.348 +    private static boolean isRemoved(Preferences p) {
  11.349 +        try {
  11.350 +            p.parent(); // throws IllegalStateException if removed;
  11.351 +            return false;
  11.352 +        } catch (IllegalStateException ex) {
  11.353 +            return true;
  11.354 +        }
  11.355 +    }
  11.356 +
  11.357 +    private static Object lock(Preferences p) {
  11.358 +        /** JST-XXX: Needs reflection or accessor:
  11.359 +         * http://wiki.apidesign.org/wiki/FriendPackages
  11.360 +        return ((AbstractPreferences)prefs).lock;
  11.361 +         */
  11.362 +        return p;
  11.363 +    }
  11.364 +}
    12.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    12.2 +++ b/src/share/classes/sun/util/xml/DefaultPropertiesXMLUtils.java	Wed Jun 24 17:51:59 2009 +0200
    12.3 @@ -0,0 +1,74 @@
    12.4 +/*
    12.5 + * Copyright 2003-2004 Sun Microsystems, Inc.  All Rights Reserved.
    12.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    12.7 + *
    12.8 + * This code is free software; you can redistribute it and/or modify it
    12.9 + * under the terms of the GNU General Public License version 2 only, as
   12.10 + * published by the Free Software Foundation.  Sun designates this
   12.11 + * particular file as subject to the "Classpath" exception as provided
   12.12 + * by Sun in the LICENSE file that accompanied this code.
   12.13 + *
   12.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   12.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   12.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   12.17 + * version 2 for more details (a copy is included in the LICENSE file that
   12.18 + * accompanied this code).
   12.19 + *
   12.20 + * You should have received a copy of the GNU General Public License version
   12.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   12.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   12.23 + *
   12.24 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
   12.25 + * CA 95054 USA or visit www.sun.com if you need additional information or
   12.26 + * have any questions.
   12.27 + */
   12.28 +
   12.29 +package sun.util.xml;
   12.30 +
   12.31 +import java.io.*;
   12.32 +import java.util.Properties;
   12.33 +import java.util.InvalidPropertiesFormatException;
   12.34 +import java.util.Map.Entry;
   12.35 +
   12.36 +/**
   12.37 + * A class used to aid in Properties load and save in XML in simple way, e.g.
   12.38 + * without dependency on the big machinery of XML, SAX and DOM 2.
   12.39 + *
   12.40 + * @author  Jaroslav Tulach
   12.41 + * @since   1.7
   12.42 + */
   12.43 +public class DefaultPropertiesXMLUtils extends PropertiesXMLUtils {
   12.44 +    public void load(Properties props, InputStream in)
   12.45 +    throws IOException, InvalidPropertiesFormatException {
   12.46 +        XMLElement e = new XMLElement();
   12.47 +        e.parseFromReader(new InputStreamReader(in, "UTF-8"));
   12.48 +        for (Object o : e.getChildren()) {
   12.49 +            XMLElement ch = (XMLElement)o;
   12.50 +            if (ch.getName().equals("entry")) {
   12.51 +                props.put(ch.getAttribute("key"), ch.getContent());
   12.52 +            }
   12.53 +        }
   12.54 +    }
   12.55 +    public void save(Properties props, OutputStream out, String comment, String encoding)
   12.56 +    throws IOException {
   12.57 +        PrintWriter w = new PrintWriter(new OutputStreamWriter(out, encoding));
   12.58 +        w.println("<?xml version=\"1.0\" encoding=\"" + encoding + "\" standalone=\"no\"?>");
   12.59 +        w.println("<!DOCTYPE properties SYSTEM \"http://java.sun.com/dtd/properties.dtd\">");
   12.60 +        w.println("<properties>");
   12.61 +        if (comment != null) {
   12.62 +            w.print("<comment>");
   12.63 +            w.print(comment);
   12.64 +            w.println("</comment>");
   12.65 +        }
   12.66 +        for (Entry<Object, Object> entry : props.entrySet()) {
   12.67 +            w.print("<entry key=\"");
   12.68 +            w.print(entry.getKey());
   12.69 +            w.print("\">");
   12.70 +            w.print(entry.getValue());
   12.71 +            w.println("</entry>");
   12.72 +        }
   12.73 +        w.println("</properties>");
   12.74 +        w.flush();
   12.75 +    }
   12.76 +
   12.77 +}
    13.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    13.2 +++ b/src/share/classes/sun/util/xml/PrefsXmlSupport.java	Wed Jun 24 17:51:59 2009 +0200
    13.3 @@ -0,0 +1,69 @@
    13.4 +/*
    13.5 + * Copyright 2002-2006 Sun Microsystems, Inc.  All Rights Reserved.
    13.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    13.7 + *
    13.8 + * This code is free software; you can redistribute it and/or modify it
    13.9 + * under the terms of the GNU General Public License version 2 only, as
   13.10 + * published by the Free Software Foundation.  Sun designates this
   13.11 + * particular file as subject to the "Classpath" exception as provided
   13.12 + * by Sun in the LICENSE file that accompanied this code.
   13.13 + *
   13.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   13.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   13.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   13.17 + * version 2 for more details (a copy is included in the LICENSE file that
   13.18 + * accompanied this code).
   13.19 + *
   13.20 + * You should have received a copy of the GNU General Public License version
   13.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   13.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   13.23 + *
   13.24 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
   13.25 + * CA 95054 USA or visit www.sun.com if you need additional information or
   13.26 + * have any questions.
   13.27 + */
   13.28 +
   13.29 +package sun.util.xml;
   13.30 +
   13.31 +import java.util.*;
   13.32 +import java.util.prefs.*;
   13.33 +import java.io.*;
   13.34 +
   13.35 +/**
   13.36 + * XML Support for java.util.prefs. Methods to import and export preference
   13.37 + * nodes and subtrees.
   13.38 + *
   13.39 + * @author  Josh Bloch and Mark Reinhold
   13.40 + * @see     Preferences
   13.41 + * @since   1.4
   13.42 + */
   13.43 +public abstract class PrefsXmlSupport {
   13.44 +    public static PrefsXmlSupport getDefault() {
   13.45 +        Iterator<PrefsXmlSupport> it = ServiceLoader.load(PrefsXmlSupport.class).iterator();
   13.46 +        return it.hasNext() ? it.next() : new DefaultPrefsXmlSupport();
   13.47 +    }
   13.48 +
   13.49 +    public abstract void export(OutputStream os, final Preferences p, boolean subTree)
   13.50 +        throws IOException, BackingStoreException;
   13.51 +
   13.52 +    /**
   13.53 +     * Import preferences from the specified input stream, which is assumed
   13.54 +     * to contain an XML document in the format described in the Preferences
   13.55 +     * spec.
   13.56 +     *
   13.57 +     * @throws IOException if reading from the specified output stream
   13.58 +     *         results in an <tt>IOException</tt>.
   13.59 +     * @throws InvalidPreferencesFormatException Data on input stream does not
   13.60 +     *         constitute a valid XML document with the mandated document type.
   13.61 +     */
   13.62 +    public abstract void importPreferences(InputStream is)
   13.63 +        throws IOException, InvalidPreferencesFormatException;
   13.64 +
   13.65 +
   13.66 +    public abstract void importMap(InputStream is, Map m)
   13.67 +        throws IOException, InvalidPreferencesFormatException;
   13.68 +
   13.69 +    public abstract void exportMap(OutputStream is, Map m)
   13.70 +        throws IOException, InvalidPreferencesFormatException;
   13.71 +
   13.72 +}
    14.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    14.2 +++ b/src/share/classes/sun/util/xml/PropertiesXMLUtils.java	Wed Jun 24 17:51:59 2009 +0200
    14.3 @@ -0,0 +1,53 @@
    14.4 +/*
    14.5 + * Copyright 2003-2004 Sun Microsystems, Inc.  All Rights Reserved.
    14.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    14.7 + *
    14.8 + * This code is free software; you can redistribute it and/or modify it
    14.9 + * under the terms of the GNU General Public License version 2 only, as
   14.10 + * published by the Free Software Foundation.  Sun designates this
   14.11 + * particular file as subject to the "Classpath" exception as provided
   14.12 + * by Sun in the LICENSE file that accompanied this code.
   14.13 + *
   14.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   14.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   14.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   14.17 + * version 2 for more details (a copy is included in the LICENSE file that
   14.18 + * accompanied this code).
   14.19 + *
   14.20 + * You should have received a copy of the GNU General Public License version
   14.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   14.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   14.23 + *
   14.24 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
   14.25 + * CA 95054 USA or visit www.sun.com if you need additional information or
   14.26 + * have any questions.
   14.27 + */
   14.28 +
   14.29 +package sun.util.xml;
   14.30 +
   14.31 +import java.io.*;
   14.32 +import java.util.Properties;
   14.33 +import java.util.InvalidPropertiesFormatException;
   14.34 +import java.util.Iterator;
   14.35 +import java.util.ServiceLoader;
   14.36 +
   14.37 +/**
   14.38 + * A class used to aid in Properties load and save in XML. Keeping this
   14.39 + * code outside of Properties helps reduce the number of classes loaded
   14.40 + * when Properties is loaded.
   14.41 + *
   14.42 + * @author  Michael McCloskey
   14.43 + * @since   1.3
   14.44 + */
   14.45 +public abstract class PropertiesXMLUtils {
   14.46 +    public static PropertiesXMLUtils getDefault() {
   14.47 +        Iterator<PropertiesXMLUtils> it = ServiceLoader.load(PropertiesXMLUtils.class).iterator();
   14.48 +        return it.hasNext() ? it.next() : new DefaultPropertiesXMLUtils();
   14.49 +    }
   14.50 +
   14.51 +    public abstract void load(Properties props, InputStream in) throws
   14.52 +            IOException, InvalidPropertiesFormatException;
   14.53 +    public abstract void save(Properties props, OutputStream out, String comment, String encoding)
   14.54 +    throws IOException;
   14.55 +
   14.56 +}
    15.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    15.2 +++ b/src/share/classes/sun/util/xml/XMLElement.java	Wed Jun 24 17:51:59 2009 +0200
    15.3 @@ -0,0 +1,2874 @@
    15.4 +/* XMLElement.java
    15.5 + *
    15.6 + * $Revision: 1.4 $
    15.7 + * $Date: 2002/03/24 10:27:59 $
    15.8 + * $Name: RELEASE_2_2_1 $
    15.9 + *
   15.10 + * This file is part of NanoXML 2 Lite.
   15.11 + * Copyright (C) 2000-2002 Marc De Scheemaecker, All Rights Reserved.
   15.12 + *
   15.13 + * This software is provided 'as-is', without any express or implied warranty.
   15.14 + * In no event will the authors be held liable for any damages arising from the
   15.15 + * use of this software.
   15.16 + *
   15.17 + * Permission is granted to anyone to use this software for any purpose,
   15.18 + * including commercial applications, and to alter it and redistribute it
   15.19 + * freely, subject to the following restrictions:
   15.20 + *
   15.21 + *  1. The origin of this software must not be misrepresented; you must not
   15.22 + *     claim that you wrote the original software. If you use this software in
   15.23 + *     a product, an acknowledgment in the product documentation would be
   15.24 + *     appreciated but is not required.
   15.25 + *
   15.26 + *  2. Altered source versions must be plainly marked as such, and must not be
   15.27 + *     misrepresented as being the original software.
   15.28 + *
   15.29 + *  3. This notice may not be removed or altered from any source distribution.
   15.30 + *****************************************************************************/
   15.31 +
   15.32 +
   15.33 +package sun.util.xml;
   15.34 +
   15.35 +
   15.36 +import java.io.ByteArrayOutputStream;
   15.37 +import java.io.CharArrayReader;
   15.38 +import java.io.IOException;
   15.39 +import java.io.OutputStreamWriter;
   15.40 +import java.io.Reader;
   15.41 +import java.io.StringReader;
   15.42 +import java.io.Writer;
   15.43 +import java.util.Enumeration;
   15.44 +import java.util.Hashtable;
   15.45 +import java.util.Vector;
   15.46 +
   15.47 +
   15.48 +/**
   15.49 + * XMLElement is a representation of an XML object. The object is able to parse
   15.50 + * XML code.
   15.51 + * <P><DL>
   15.52 + * <DT><B>Parsing XML Data</B></DT>
   15.53 + * <DD>
   15.54 + * You can parse XML data using the following code:
   15.55 + * <UL><CODE>
   15.56 + * XMLElement xml = new XMLElement();<BR>
   15.57 + * FileReader reader = new FileReader("filename.xml");<BR>
   15.58 + * xml.parseFromReader(reader);
   15.59 + * </CODE></UL></DD></DL>
   15.60 + * <DL><DT><B>Retrieving Attributes</B></DT>
   15.61 + * <DD>
   15.62 + * You can enumerate the attributes of an element using the method
   15.63 + * {@link #enumerateAttributeNames() enumerateAttributeNames}.
   15.64 + * The attribute values can be retrieved using the method
   15.65 + * {@link #getStringAttribute(java.lang.String) getStringAttribute}.
   15.66 + * The following example shows how to list the attributes of an element:
   15.67 + * <UL><CODE>
   15.68 + * XMLElement element = ...;<BR>
   15.69 + * Enumeration enumV = element.getAttributeNames();<BR>
   15.70 + * while (enumV.hasMoreElements()) {<BR>
   15.71 + * &nbsp;&nbsp;&nbsp;&nbsp;String key = (String) enumV.nextElement();<BR>
   15.72 + * &nbsp;&nbsp;&nbsp;&nbsp;String value = element.getStringAttribute(key);<BR>
   15.73 + * &nbsp;&nbsp;&nbsp;&nbsp;System.out.println(key + " = " + value);<BR>
   15.74 + * }
   15.75 + * </CODE></UL></DD></DL>
   15.76 + * <DL><DT><B>Retrieving Child Elements</B></DT>
   15.77 + * <DD>
   15.78 + * You can enumerate the children of an element using
   15.79 + * {@link #enumerateChildren() enumerateChildren}.
   15.80 + * The number of child elements can be retrieved using
   15.81 + * {@link #countChildren() countChildren}.
   15.82 + * </DD></DL>
   15.83 + * <DL><DT><B>Elements Containing Character Data</B></DT>
   15.84 + * <DD>
   15.85 + * If an elements contains character data, like in the following example:
   15.86 + * <UL><CODE>
   15.87 + * &lt;title&gt;The Title&lt;/title&gt;
   15.88 + * </CODE></UL>
   15.89 + * you can retrieve that data using the method
   15.90 + * {@link #getContent() getContent}.
   15.91 + * </DD></DL>
   15.92 + * <DL><DT><B>Subclassing XMLElement</B></DT>
   15.93 + * <DD>
   15.94 + * When subclassing XMLElement, you need to override the method
   15.95 + * {@link #createAnotherElement() createAnotherElement}
   15.96 + * which has to return a new copy of the receiver.
   15.97 + * </DD></DL>
   15.98 + * <P>
   15.99 + *
  15.100 + * @see nanoxml.XMLParseException
  15.101 + *
  15.102 + * @author Marc De Scheemaecker
  15.103 + *         &lt;<A href="mailto:cyberelf@mac.com">cyberelf@mac.com</A>&gt;
  15.104 + * @version $Name: RELEASE_2_2_1 $, $Revision: 1.4 $
  15.105 + */
  15.106 +class XMLElement {
  15.107 +
  15.108 +    /**
  15.109 +     * Serialization serial version ID.
  15.110 +     */
  15.111 +    static final long serialVersionUID = 6685035139346394777L;
  15.112 +
  15.113 +
  15.114 +    /**
  15.115 +     * Major version of NanoXML. Classes with the same major and minor
  15.116 +     * version are binary compatible. Classes with the same major version
  15.117 +     * are source compatible. If the major version is different, you may
  15.118 +     * need to modify the client source code.
  15.119 +     *
  15.120 +     * @see nanoxml.XMLElement#NANOXML_MINOR_VERSION
  15.121 +     */
  15.122 +    public static final int NANOXML_MAJOR_VERSION = 2;
  15.123 +    
  15.124 +
  15.125 +    /**
  15.126 +     * Minor version of NanoXML. Classes with the same major and minor
  15.127 +     * version are binary compatible. Classes with the same major version
  15.128 +     * are source compatible. If the major version is different, you may
  15.129 +     * need to modify the client source code.
  15.130 +     *
  15.131 +     * @see nanoxml.XMLElement#NANOXML_MAJOR_VERSION
  15.132 +     */
  15.133 +    public static final int NANOXML_MINOR_VERSION = 2;
  15.134 +
  15.135 +
  15.136 +    /**
  15.137 +     * The attributes given to the element.
  15.138 +     *
  15.139 +     * <dl><dt><b>Invariants:</b></dt><dd>
  15.140 +     * <ul><li>The field can be empty.
  15.141 +     *     <li>The field is never <code>null</code>.
  15.142 +     *     <li>The keys and the values are strings.
  15.143 +     * </ul></dd></dl>
  15.144 +     */
  15.145 +    private Hashtable attributes;
  15.146 +
  15.147 +
  15.148 +    /**
  15.149 +     * Child elements of the element.
  15.150 +     *
  15.151 +     * <dl><dt><b>Invariants:</b></dt><dd>
  15.152 +     * <ul><li>The field can be empty.
  15.153 +     *     <li>The field is never <code>null</code>.
  15.154 +     *     <li>The elements are instances of <code>XMLElement</code>
  15.155 +     *         or a subclass of <code>XMLElement</code>.
  15.156 +     * </ul></dd></dl>
  15.157 +     */
  15.158 +    private Vector children;
  15.159 +
  15.160 +
  15.161 +    /**
  15.162 +     * The name of the element.
  15.163 +     *
  15.164 +     * <dl><dt><b>Invariants:</b></dt><dd>
  15.165 +     * <ul><li>The field is <code>null</code> iff the element is not
  15.166 +     *         initialized by either parse or setName.
  15.167 +     *     <li>If the field is not <code>null</code>, it's not empty.
  15.168 +     *     <li>If the field is not <code>null</code>, it contains a valid
  15.169 +     *         XML identifier.
  15.170 +     * </ul></dd></dl>
  15.171 +     */
  15.172 +    private String name;
  15.173 +
  15.174 +
  15.175 +    /**
  15.176 +     * The #PCDATA content of the object.
  15.177 +     *
  15.178 +     * <dl><dt><b>Invariants:</b></dt><dd>
  15.179 +     * <ul><li>The field is <code>null</code> iff the element is not a
  15.180 +     *         #PCDATA element.
  15.181 +     *     <li>The field can be any string, including the empty string.
  15.182 +     * </ul></dd></dl>
  15.183 +     */
  15.184 +    private String contents;
  15.185 +
  15.186 +
  15.187 +    /**
  15.188 +     * Conversion table for &amp;...; entities. The keys are the entity names
  15.189 +     * without the &amp; and ; delimiters.
  15.190 +     *
  15.191 +     * <dl><dt><b>Invariants:</b></dt><dd>
  15.192 +     * <ul><li>The field is never <code>null</code>.
  15.193 +     *     <li>The field always contains the following associations:
  15.194 +     *         "lt"&nbsp;=&gt;&nbsp;"&lt;", "gt"&nbsp;=&gt;&nbsp;"&gt;",
  15.195 +     *         "quot"&nbsp;=&gt;&nbsp;"\"", "apos"&nbsp;=&gt;&nbsp;"'",
  15.196 +     *         "amp"&nbsp;=&gt;&nbsp;"&amp;"
  15.197 +     *     <li>The keys are strings
  15.198 +     *     <li>The values are char arrays
  15.199 +     * </ul></dd></dl>
  15.200 +     */
  15.201 +    private Hashtable entities;
  15.202 +
  15.203 +
  15.204 +    /**
  15.205 +     * The line number where the element starts.
  15.206 +     *
  15.207 +     * <dl><dt><b>Invariants:</b></dt><dd>
  15.208 +     * <ul><li><code>lineNr &gt= 0</code>
  15.209 +     * </ul></dd></dl>
  15.210 +     */
  15.211 +    private int lineNr;
  15.212 +
  15.213 +
  15.214 +    /**
  15.215 +     * <code>true</code> if the case of the element and attribute names
  15.216 +     * are case insensitive.
  15.217 +     */
  15.218 +    private boolean ignoreCase;
  15.219 +
  15.220 +
  15.221 +    /**
  15.222 +     * <code>true</code> if the leading and trailing whitespace of #PCDATA
  15.223 +     * sections have to be ignored.
  15.224 +     */
  15.225 +    private boolean ignoreWhitespace;
  15.226 +
  15.227 +
  15.228 +    /**
  15.229 +     * Character read too much.
  15.230 +     * This character provides push-back functionality to the input reader
  15.231 +     * without having to use a PushbackReader.
  15.232 +     * If there is no such character, this field is '\0'.
  15.233 +     */
  15.234 +    private char charReadTooMuch;
  15.235 +
  15.236 +
  15.237 +    /**
  15.238 +     * The reader provided by the caller of the parse method.
  15.239 +     *
  15.240 +     * <dl><dt><b>Invariants:</b></dt><dd>
  15.241 +     * <ul><li>The field is not <code>null</code> while the parse method
  15.242 +     *         is running.
  15.243 +     * </ul></dd></dl>
  15.244 +     */
  15.245 +    private Reader reader;
  15.246 +
  15.247 +
  15.248 +    /**
  15.249 +     * The current line number in the source content.
  15.250 +     *
  15.251 +     * <dl><dt><b>Invariants:</b></dt><dd>
  15.252 +     * <ul><li>parserLineNr &gt; 0 while the parse method is running.
  15.253 +     * </ul></dd></dl>
  15.254 +     */
  15.255 +    private int parserLineNr;
  15.256 +
  15.257 +
  15.258 +    /**
  15.259 +     * Creates and initializes a new XML element.
  15.260 +     * Calling the construction is equivalent to:
  15.261 +     * <ul><code>new XMLElement(new Hashtable(), false, true)
  15.262 +     * </code></ul>
  15.263 +     *
  15.264 +     * <dl><dt><b>Postconditions:</b></dt><dd>
  15.265 +     * <ul><li>countChildren() => 0
  15.266 +     *     <li>enumerateChildren() => empty enumeration
  15.267 +     *     <li>enumeratePropertyNames() => empty enumeration
  15.268 +     *     <li>getChildren() => empty vector
  15.269 +     *     <li>getContent() => ""
  15.270 +     *     <li>getLineNr() => 0
  15.271 +     *     <li>getName() => null
  15.272 +     * </ul></dd></dl>
  15.273 +     *
  15.274 +     * @see nanoxml.XMLElement#XMLElement(java.util.Hashtable)
  15.275 +     *         XMLElement(Hashtable)
  15.276 +     * @see nanoxml.XMLElement#XMLElement(boolean)
  15.277 +     * @see nanoxml.XMLElement#XMLElement(java.util.Hashtable,boolean)
  15.278 +     *         XMLElement(Hashtable, boolean)
  15.279 +     */
  15.280 +    public XMLElement()
  15.281 +    {
  15.282 +        this(new Hashtable(), false, true, true);
  15.283 +    }
  15.284 +    
  15.285 +
  15.286 +    /**
  15.287 +     * Creates and initializes a new XML element.
  15.288 +     * Calling the construction is equivalent to:
  15.289 +     * <ul><code>new XMLElement(entities, false, true)
  15.290 +     * </code></ul>
  15.291 +     *
  15.292 +     * @param entities
  15.293 +     *     The entity conversion table.
  15.294 +     *
  15.295 +     * </dl><dl><dt><b>Preconditions:</b></dt><dd>
  15.296 +     * <ul><li><code>entities != null</code>
  15.297 +     * </ul></dd></dl>
  15.298 +     *
  15.299 +     * <dl><dt><b>Postconditions:</b></dt><dd>
  15.300 +     * <ul><li>countChildren() => 0
  15.301 +     *     <li>enumerateChildren() => empty enumeration
  15.302 +     *     <li>enumeratePropertyNames() => empty enumeration
  15.303 +     *     <li>getChildren() => empty vector
  15.304 +     *     <li>getContent() => ""
  15.305 +     *     <li>getLineNr() => 0
  15.306 +     *     <li>getName() => null
  15.307 +     * </ul></dd></dl><dl>
  15.308 +     *
  15.309 +     * @see nanoxml.XMLElement#XMLElement()
  15.310 +     * @see nanoxml.XMLElement#XMLElement(boolean)
  15.311 +     * @see nanoxml.XMLElement#XMLElement(java.util.Hashtable,boolean)
  15.312 +     *         XMLElement(Hashtable, boolean)
  15.313 +     */
  15.314 +    public XMLElement(Hashtable entities)
  15.315 +    {
  15.316 +        this(entities, false, true, true);
  15.317 +    }
  15.318 +
  15.319 +
  15.320 +    /**
  15.321 +     * Creates and initializes a new XML element.
  15.322 +     * Calling the construction is equivalent to:
  15.323 +     * <ul><code>new XMLElement(new Hashtable(), skipLeadingWhitespace, true)
  15.324 +     * </code></ul>
  15.325 +     *
  15.326 +     * @param skipLeadingWhitespace
  15.327 +     *     <code>true</code> if leading and trailing whitespace in PCDATA
  15.328 +     *     content has to be removed.
  15.329 +     *
  15.330 +     * </dl><dl><dt><b>Postconditions:</b></dt><dd>
  15.331 +     * <ul><li>countChildren() => 0
  15.332 +     *     <li>enumerateChildren() => empty enumeration
  15.333 +     *     <li>enumeratePropertyNames() => empty enumeration
  15.334 +     *     <li>getChildren() => empty vector
  15.335 +     *     <li>getContent() => ""
  15.336 +     *     <li>getLineNr() => 0
  15.337 +     *     <li>getName() => null
  15.338 +     * </ul></dd></dl><dl>
  15.339 +     *
  15.340 +     * @see nanoxml.XMLElement#XMLElement()
  15.341 +     * @see nanoxml.XMLElement#XMLElement(java.util.Hashtable)
  15.342 +     *         XMLElement(Hashtable)
  15.343 +     * @see nanoxml.XMLElement#XMLElement(java.util.Hashtable,boolean)
  15.344 +     *         XMLElement(Hashtable, boolean)
  15.345 +     */
  15.346 +    public XMLElement(boolean skipLeadingWhitespace)
  15.347 +    {
  15.348 +        this(new Hashtable(), skipLeadingWhitespace, true, true);
  15.349 +    }
  15.350 +
  15.351 +
  15.352 +    /**
  15.353 +     * Creates and initializes a new XML element.
  15.354 +     * Calling the construction is equivalent to:
  15.355 +     * <ul><code>new XMLElement(entities, skipLeadingWhitespace, true)
  15.356 +     * </code></ul>
  15.357 +     *
  15.358 +     * @param entities
  15.359 +     *     The entity conversion table.
  15.360 +     * @param skipLeadingWhitespace
  15.361 +     *     <code>true</code> if leading and trailing whitespace in PCDATA
  15.362 +     *     content has to be removed.
  15.363 +     *
  15.364 +     * </dl><dl><dt><b>Preconditions:</b></dt><dd>
  15.365 +     * <ul><li><code>entities != null</code>
  15.366 +     * </ul></dd></dl>
  15.367 +     *
  15.368 +     * <dl><dt><b>Postconditions:</b></dt><dd>
  15.369 +     * <ul><li>countChildren() => 0
  15.370 +     *     <li>enumerateChildren() => empty enumeration
  15.371 +     *     <li>enumeratePropertyNames() => empty enumeration
  15.372 +     *     <li>getChildren() => empty vector
  15.373 +     *     <li>getContent() => ""
  15.374 +     *     <li>getLineNr() => 0
  15.375 +     *     <li>getName() => null
  15.376 +     * </ul></dd></dl><dl>
  15.377 +     *
  15.378 +     * @see nanoxml.XMLElement#XMLElement()
  15.379 +     * @see nanoxml.XMLElement#XMLElement(boolean)
  15.380 +     * @see nanoxml.XMLElement#XMLElement(java.util.Hashtable)
  15.381 +     *         XMLElement(Hashtable)
  15.382 +     */
  15.383 +    public XMLElement(Hashtable entities,
  15.384 +                      boolean   skipLeadingWhitespace)
  15.385 +    {
  15.386 +        this(entities, skipLeadingWhitespace, true, true);
  15.387 +    }
  15.388 +
  15.389 +
  15.390 +    /**
  15.391 +     * Creates and initializes a new XML element.
  15.392 +     *
  15.393 +     * @param entities
  15.394 +     *     The entity conversion table.
  15.395 +     * @param skipLeadingWhitespace
  15.396 +     *     <code>true</code> if leading and trailing whitespace in PCDATA
  15.397 +     *     content has to be removed.
  15.398 +     * @param ignoreCase
  15.399 +     *     <code>true</code> if the case of element and attribute names have
  15.400 +     *     to be ignored.
  15.401 +     *
  15.402 +     * </dl><dl><dt><b>Preconditions:</b></dt><dd>
  15.403 +     * <ul><li><code>entities != null</code>
  15.404 +     * </ul></dd></dl>
  15.405 +     *
  15.406 +     * <dl><dt><b>Postconditions:</b></dt><dd>
  15.407 +     * <ul><li>countChildren() => 0
  15.408 +     *     <li>enumerateChildren() => empty enumeration
  15.409 +     *     <li>enumeratePropertyNames() => empty enumeration
  15.410 +     *     <li>getChildren() => empty vector
  15.411 +     *     <li>getContent() => ""
  15.412 +     *     <li>getLineNr() => 0
  15.413 +     *     <li>getName() => null
  15.414 +     * </ul></dd></dl><dl>
  15.415 +     *
  15.416 +     * @see nanoxml.XMLElement#XMLElement()
  15.417 +     * @see nanoxml.XMLElement#XMLElement(boolean)
  15.418 +     * @see nanoxml.XMLElement#XMLElement(java.util.Hashtable)
  15.419 +     *         XMLElement(Hashtable)
  15.420 +     * @see nanoxml.XMLElement#XMLElement(java.util.Hashtable,boolean)
  15.421 +     *         XMLElement(Hashtable, boolean)
  15.422 +     */
  15.423 +    public XMLElement(Hashtable entities,
  15.424 +                      boolean   skipLeadingWhitespace,
  15.425 +                      boolean   ignoreCase)
  15.426 +    {
  15.427 +        this(entities, skipLeadingWhitespace, true, ignoreCase);
  15.428 +    }
  15.429 +
  15.430 +
  15.431 +    /**
  15.432 +     * Creates and initializes a new XML element.
  15.433 +     * <P>
  15.434 +     * This constructor should <I>only</I> be called from
  15.435 +     * {@link #createAnotherElement() createAnotherElement}
  15.436 +     * to create child elements.
  15.437 +     *
  15.438 +     * @param entities
  15.439 +     *     The entity conversion table.
  15.440 +     * @param skipLeadingWhitespace
  15.441 +     *     <code>true</code> if leading and trailing whitespace in PCDATA
  15.442 +     *     content has to be removed.
  15.443 +     * @param fillBasicConversionTable
  15.444 +     *     <code>true</code> if the basic entities need to be added to
  15.445 +     *     the entity list.
  15.446 +     * @param ignoreCase
  15.447 +     *     <code>true</code> if the case of element and attribute names have
  15.448 +     *     to be ignored.
  15.449 +     *
  15.450 +     * </dl><dl><dt><b>Preconditions:</b></dt><dd>
  15.451 +     * <ul><li><code>entities != null</code>
  15.452 +     *     <li>if <code>fillBasicConversionTable == false</code>
  15.453 +     *         then <code>entities</code> contains at least the following
  15.454 +     *         entries: <code>amp</code>, <code>lt</code>, <code>gt</code>,
  15.455 +     *         <code>apos</code> and <code>quot</code>
  15.456 +     * </ul></dd></dl>
  15.457 +     *
  15.458 +     * <dl><dt><b>Postconditions:</b></dt><dd>
  15.459 +     * <ul><li>countChildren() => 0
  15.460 +     *     <li>enumerateChildren() => empty enumeration
  15.461 +     *     <li>enumeratePropertyNames() => empty enumeration
  15.462 +     *     <li>getChildren() => empty vector
  15.463 +     *     <li>getContent() => ""
  15.464 +     *     <li>getLineNr() => 0
  15.465 +     *     <li>getName() => null
  15.466 +     * </ul></dd></dl><dl>
  15.467 +     *
  15.468 +     * @see nanoxml.XMLElement#createAnotherElement()
  15.469 +     */
  15.470 +    protected XMLElement(Hashtable entities,
  15.471 +                         boolean   skipLeadingWhitespace,
  15.472 +                         boolean   fillBasicConversionTable,
  15.473 +                         boolean   ignoreCase)
  15.474 +    {
  15.475 +        this.ignoreWhitespace = skipLeadingWhitespace;
  15.476 +        this.ignoreCase = ignoreCase;
  15.477 +        this.name = null;
  15.478 +        this.contents = "";
  15.479 +        this.attributes = new Hashtable();
  15.480 +        this.children = new Vector();
  15.481 +        this.entities = entities;
  15.482 +        this.lineNr = 0;
  15.483 +        Enumeration enumV = this.entities.keys();
  15.484 +        while (enumV.hasMoreElements()) {
  15.485 +            Object key = enumV.nextElement();
  15.486 +            Object value = this.entities.get(key);
  15.487 +            if (value instanceof String) {
  15.488 +                value = ((String) value).toCharArray();
  15.489 +                this.entities.put(key, value);
  15.490 +            }
  15.491 +        }
  15.492 +        if (fillBasicConversionTable) {
  15.493 +            this.entities.put("amp", new char[] { '&' });
  15.494 +            this.entities.put("quot", new char[] { '"' });
  15.495 +            this.entities.put("apos", new char[] { '\'' });
  15.496 +            this.entities.put("lt", new char[] { '<' });
  15.497 +            this.entities.put("gt", new char[] { '>' });
  15.498 +        }
  15.499 +    }
  15.500 +
  15.501 +
  15.502 +    /**
  15.503 +     * Adds a child element.
  15.504 +     *
  15.505 +     * @param child
  15.506 +     *     The child element to add.
  15.507 +     *
  15.508 +     * </dl><dl><dt><b>Preconditions:</b></dt><dd>
  15.509 +     * <ul><li><code>child != null</code>
  15.510 +     *     <li><code>child.getName() != null</code>
  15.511 +     *     <li><code>child</code> does not have a parent element
  15.512 +     * </ul></dd></dl>
  15.513 +     *
  15.514 +     * <dl><dt><b>Postconditions:</b></dt><dd>
  15.515 +     * <ul><li>countChildren() => old.countChildren() + 1
  15.516 +     *     <li>enumerateChildren() => old.enumerateChildren() + child
  15.517 +     *     <li>getChildren() => old.enumerateChildren() + child
  15.518 +     * </ul></dd></dl><dl>
  15.519 +     *
  15.520 +     * @see nanoxml.XMLElement#countChildren()
  15.521 +     * @see nanoxml.XMLElement#enumerateChildren()
  15.522 +     * @see nanoxml.XMLElement#getChildren()
  15.523 +     * @see nanoxml.XMLElement#removeChild(nanoxml.XMLElement)
  15.524 +     *         removeChild(XMLElement)
  15.525 +     */
  15.526 +    public void addChild(XMLElement child)
  15.527 +    {
  15.528 +        this.children.addElement(child);
  15.529 +    }
  15.530 +
  15.531 +
  15.532 +    /**
  15.533 +     * Adds or modifies an attribute.
  15.534 +     *
  15.535 +     * @param name
  15.536 +     *     The name of the attribute.
  15.537 +     * @param value
  15.538 +     *     The value of the attribute.
  15.539 +     *
  15.540 +     * </dl><dl><dt><b>Preconditions:</b></dt><dd>
  15.541 +     * <ul><li><code>name != null</code>
  15.542 +     *     <li><code>name</code> is a valid XML identifier
  15.543 +     *     <li><code>value != null</code>
  15.544 +     * </ul></dd></dl>
  15.545 +     *
  15.546 +     * <dl><dt><b>Postconditions:</b></dt><dd>
  15.547 +     * <ul><li>enumerateAttributeNames()
  15.548 +     *         => old.enumerateAttributeNames() + name
  15.549 +     *     <li>getAttribute(name) => value
  15.550 +     * </ul></dd></dl><dl>
  15.551 +     *
  15.552 +     * @see nanoxml.XMLElement#setDoubleAttribute(java.lang.String, double)
  15.553 +     *         setDoubleAttribute(String, double)
  15.554 +     * @see nanoxml.XMLElement#setIntAttribute(java.lang.String, int)
  15.555 +     *         setIntAttribute(String, int)
  15.556 +     * @see nanoxml.XMLElement#enumerateAttributeNames()
  15.557 +     * @see nanoxml.XMLElement#getAttribute(java.lang.String)
  15.558 +     *         getAttribute(String)
  15.559 +     * @see nanoxml.XMLElement#getAttribute(java.lang.String, java.lang.Object)
  15.560 +     *         getAttribute(String, Object)
  15.561 +     * @see nanoxml.XMLElement#getAttribute(java.lang.String,
  15.562 +     *                                      java.util.Hashtable,
  15.563 +     *                                      java.lang.String, boolean)
  15.564 +     *         getAttribute(String, Hashtable, String, boolean)
  15.565 +     * @see nanoxml.XMLElement#getStringAttribute(java.lang.String)
  15.566 +     *         getStringAttribute(String)
  15.567 +     * @see nanoxml.XMLElement#getStringAttribute(java.lang.String,
  15.568 +     *                                            java.lang.String)
  15.569 +     *         getStringAttribute(String, String)
  15.570 +     * @see nanoxml.XMLElement#getStringAttribute(java.lang.String,
  15.571 +     *                                            java.util.Hashtable,
  15.572 +     *                                            java.lang.String, boolean)
  15.573 +     *         getStringAttribute(String, Hashtable, String, boolean)
  15.574 +     */
  15.575 +    public void setAttribute(String name,
  15.576 +                             Object value)
  15.577 +    {
  15.578 +        if (this.ignoreCase) {
  15.579 +            name = name.toUpperCase();
  15.580 +        }
  15.581 +        this.attributes.put(name, value.toString());
  15.582 +    }
  15.583 +
  15.584 +
  15.585 +    /**
  15.586 +     * Adds or modifies an attribute.
  15.587 +     *
  15.588 +     * @param name
  15.589 +     *     The name of the attribute.
  15.590 +     * @param value
  15.591 +     *     The value of the attribute.
  15.592 +     *
  15.593 +     * @deprecated Use {@link #setAttribute(java.lang.String, java.lang.Object)
  15.594 +     *             setAttribute} instead.
  15.595 +     */
  15.596 +    public void addProperty(String name,
  15.597 +                            Object value)
  15.598 +    {
  15.599 +        this.setAttribute(name, value);
  15.600 +    }
  15.601 +
  15.602 +
  15.603 +    /**
  15.604 +     * Adds or modifies an attribute.
  15.605 +     *
  15.606 +     * @param name
  15.607 +     *     The name of the attribute.
  15.608 +     * @param value
  15.609 +     *     The value of the attribute.
  15.610 +     *
  15.611 +     * </dl><dl><dt><b>Preconditions:</b></dt><dd>
  15.612 +     * <ul><li><code>name != null</code>
  15.613 +     *     <li><code>name</code> is a valid XML identifier
  15.614 +     * </ul></dd></dl>
  15.615 +     *
  15.616 +     * <dl><dt><b>Postconditions:</b></dt><dd>
  15.617 +     * <ul><li>enumerateAttributeNames()
  15.618 +     *         => old.enumerateAttributeNames() + name
  15.619 +     *     <li>getIntAttribute(name) => value
  15.620 +     * </ul></dd></dl><dl>
  15.621 +     *
  15.622 +     * @see nanoxml.XMLElement#setDoubleAttribute(java.lang.String, double)
  15.623 +     *         setDoubleAttribute(String, double)
  15.624 +     * @see nanoxml.XMLElement#setAttribute(java.lang.String, java.lang.Object)
  15.625 +     *         setAttribute(String, Object)
  15.626 +     * @see nanoxml.XMLElement#removeAttribute(java.lang.String)
  15.627 +     *         removeAttribute(String)
  15.628 +     * @see nanoxml.XMLElement#enumerateAttributeNames()
  15.629 +     * @see nanoxml.XMLElement#getIntAttribute(java.lang.String)
  15.630 +     *         getIntAttribute(String)
  15.631 +     * @see nanoxml.XMLElement#getIntAttribute(java.lang.String, int)
  15.632 +     *         getIntAttribute(String, int)
  15.633 +     * @see nanoxml.XMLElement#getIntAttribute(java.lang.String,
  15.634 +     *                                         java.util.Hashtable,
  15.635 +     *                                         java.lang.String, boolean)
  15.636 +     *         getIntAttribute(String, Hashtable, String, boolean)
  15.637 +     */
  15.638 +    public void setIntAttribute(String name,
  15.639 +                                int    value)
  15.640 +    {
  15.641 +        if (this.ignoreCase) {
  15.642 +            name = name.toUpperCase();
  15.643 +        }
  15.644 +        this.attributes.put(name, Integer.toString(value));
  15.645 +    }
  15.646 +
  15.647 +
  15.648 +    /**
  15.649 +     * Adds or modifies an attribute.
  15.650 +     *
  15.651 +     * @param name
  15.652 +     *     The name of the attribute.
  15.653 +     * @param value
  15.654 +     *     The value of the attribute.
  15.655 +     *
  15.656 +     * @deprecated Use {@link #setIntAttribute(java.lang.String, int)
  15.657 +     *             setIntAttribute} instead.
  15.658 +     */
  15.659 +    public void addProperty(String key,
  15.660 +                            int    value)
  15.661 +    {
  15.662 +        this.setIntAttribute(key, value);
  15.663 +    }
  15.664 +
  15.665 +
  15.666 +    /**
  15.667 +     * Adds or modifies an attribute.
  15.668 +     *
  15.669 +     * @param name
  15.670 +     *     The name of the attribute.
  15.671 +     * @param value
  15.672 +     *     The value of the attribute.
  15.673 +     *
  15.674 +     * </dl><dl><dt><b>Preconditions:</b></dt><dd>
  15.675 +     * <ul><li><code>name != null</code>
  15.676 +     *     <li><code>name</code> is a valid XML identifier
  15.677 +     * </ul></dd></dl>
  15.678 +     *
  15.679 +     * <dl><dt><b>Postconditions:</b></dt><dd>
  15.680 +     * <ul><li>enumerateAttributeNames()
  15.681 +     *         => old.enumerateAttributeNames() + name
  15.682 +     *     <li>getDoubleAttribute(name) => value
  15.683 +     * </ul></dd></dl><dl>
  15.684 +     *
  15.685 +     * @see nanoxml.XMLElement#setIntAttribute(java.lang.String, int)
  15.686 +     *         setIntAttribute(String, int)
  15.687 +     * @see nanoxml.XMLElement#setAttribute(java.lang.String, java.lang.Object)
  15.688 +     *         setAttribute(String, Object)
  15.689 +     * @see nanoxml.XMLElement#removeAttribute(java.lang.String)
  15.690 +     *         removeAttribute(String)
  15.691 +     * @see nanoxml.XMLElement#enumerateAttributeNames()
  15.692 +     * @see nanoxml.XMLElement#getDoubleAttribute(java.lang.String)
  15.693 +     *         getDoubleAttribute(String)
  15.694 +     * @see nanoxml.XMLElement#getDoubleAttribute(java.lang.String, double)
  15.695 +     *         getDoubleAttribute(String, double)
  15.696 +     * @see nanoxml.XMLElement#getDoubleAttribute(java.lang.String,
  15.697 +     *                                            java.util.Hashtable,
  15.698 +     *                                            java.lang.String, boolean)
  15.699 +     *         getDoubleAttribute(String, Hashtable, String, boolean)
  15.700 +     */
  15.701 +    public void setDoubleAttribute(String name,
  15.702 +                                   double value)
  15.703 +    {
  15.704 +        if (this.ignoreCase) {
  15.705 +            name = name.toUpperCase();
  15.706 +        }
  15.707 +        this.attributes.put(name, Double.toString(value));
  15.708 +    }
  15.709 +
  15.710 +
  15.711 +    /**
  15.712 +     * Adds or modifies an attribute.
  15.713 +     *
  15.714 +     * @param name
  15.715 +     *     The name of the attribute.
  15.716 +     * @param value
  15.717 +     *     The value of the attribute.
  15.718 +     *
  15.719 +     * @deprecated Use {@link #setDoubleAttribute(java.lang.String, double)
  15.720 +     *             setDoubleAttribute} instead.
  15.721 +     */
  15.722 +    public void addProperty(String name,
  15.723 +                            double value)
  15.724 +    {
  15.725 +        this.setDoubleAttribute(name, value);
  15.726 +    }
  15.727 +
  15.728 +
  15.729 +    /**
  15.730 +     * Returns the number of child elements of the element.
  15.731 +     *
  15.732 +     * <dl><dt><b>Postconditions:</b></dt><dd>
  15.733 +     * <ul><li><code>result >= 0</code>
  15.734 +     * </ul></dd></dl>
  15.735 +     *
  15.736 +     * @see nanoxml.XMLElement#addChild(nanoxml.XMLElement)
  15.737 +     *         addChild(XMLElement)
  15.738 +     * @see nanoxml.XMLElement#enumerateChildren()
  15.739 +     * @see nanoxml.XMLElement#getChildren()
  15.740 +     * @see nanoxml.XMLElement#removeChild(nanoxml.XMLElement)
  15.741 +     *         removeChild(XMLElement)
  15.742 +     */
  15.743 +    public int countChildren()
  15.744 +    {
  15.745 +        return this.children.size();
  15.746 +    }
  15.747 +
  15.748 +
  15.749 +    /**
  15.750 +     * Enumerates the attribute names.
  15.751 +     *
  15.752 +     * <dl><dt><b>Postconditions:</b></dt><dd>
  15.753 +     * <ul><li><code>result != null</code>
  15.754 +     * </ul></dd></dl>
  15.755 +     *
  15.756 +     * @see nanoxml.XMLElement#setDoubleAttribute(java.lang.String, double)
  15.757 +     *         setDoubleAttribute(String, double)
  15.758 +     * @see nanoxml.XMLElement#setIntAttribute(java.lang.String, int)
  15.759 +     *         setIntAttribute(String, int)
  15.760 +     * @see nanoxml.XMLElement#setAttribute(java.lang.String, java.lang.Object)
  15.761 +     *         setAttribute(String, Object)
  15.762 +     * @see nanoxml.XMLElement#removeAttribute(java.lang.String)
  15.763 +     *         removeAttribute(String)
  15.764 +     * @see nanoxml.XMLElement#getAttribute(java.lang.String)
  15.765 +     *         getAttribute(String)
  15.766 +     * @see nanoxml.XMLElement#getAttribute(java.lang.String, java.lang.Object)
  15.767 +     *         getAttribute(String, String)
  15.768 +     * @see nanoxml.XMLElement#getAttribute(java.lang.String,
  15.769 +     *                                      java.util.Hashtable,
  15.770 +     *                                      java.lang.String, boolean)
  15.771 +     *         getAttribute(String, Hashtable, String, boolean)
  15.772 +     * @see nanoxml.XMLElement#getStringAttribute(java.lang.String)
  15.773 +     *         getStringAttribute(String)
  15.774 +     * @see nanoxml.XMLElement#getStringAttribute(java.lang.String,
  15.775 +     *                                            java.lang.String)
  15.776 +     *         getStringAttribute(String, String)
  15.777 +     * @see nanoxml.XMLElement#getStringAttribute(java.lang.String,
  15.778 +     *                                            java.util.Hashtable,
  15.779 +     *                                            java.lang.String, boolean)
  15.780 +     *         getStringAttribute(String, Hashtable, String, boolean)
  15.781 +     * @see nanoxml.XMLElement#getIntAttribute(java.lang.String)
  15.782 +     *         getIntAttribute(String)
  15.783 +     * @see nanoxml.XMLElement#getIntAttribute(java.lang.String, int)
  15.784 +     *         getIntAttribute(String, int)
  15.785 +     * @see nanoxml.XMLElement#getIntAttribute(java.lang.String,
  15.786 +     *                                         java.util.Hashtable,
  15.787 +     *                                         java.lang.String, boolean)
  15.788 +     *         getIntAttribute(String, Hashtable, String, boolean)
  15.789 +     * @see nanoxml.XMLElement#getDoubleAttribute(java.lang.String)
  15.790 +     *         getDoubleAttribute(String)
  15.791 +     * @see nanoxml.XMLElement#getDoubleAttribute(java.lang.String, double)
  15.792 +     *         getDoubleAttribute(String, double)
  15.793 +     * @see nanoxml.XMLElement#getDoubleAttribute(java.lang.String,
  15.794 +     *                                            java.util.Hashtable,
  15.795 +     *                                            java.lang.String, boolean)
  15.796 +     *         getDoubleAttribute(String, Hashtable, String, boolean)
  15.797 +     * @see nanoxml.XMLElement#getBooleanAttribute(java.lang.String,
  15.798 +     *                                             java.lang.String,
  15.799 +     *                                             java.lang.String, boolean)
  15.800 +     *         getBooleanAttribute(String, String, String, boolean)
  15.801 +     */
  15.802 +    public Enumeration enumerateAttributeNames()
  15.803 +    {
  15.804 +        return this.attributes.keys();
  15.805 +    }
  15.806 +
  15.807 +
  15.808 +    /**
  15.809 +     * Enumerates the attribute names.
  15.810 +     *
  15.811 +     * @deprecated Use {@link #enumerateAttributeNames()
  15.812 +     *             enumerateAttributeNames} instead.
  15.813 +     */
  15.814 +    public Enumeration enumeratePropertyNames()
  15.815 +    {
  15.816 +        return this.enumerateAttributeNames();
  15.817 +    }
  15.818 +
  15.819 +
  15.820 +    /**
  15.821 +     * Enumerates the child elements.
  15.822 +     *
  15.823 +     * <dl><dt><b>Postconditions:</b></dt><dd>
  15.824 +     * <ul><li><code>result != null</code>
  15.825 +     * </ul></dd></dl>
  15.826 +     *
  15.827 +     * @see nanoxml.XMLElement#addChild(nanoxml.XMLElement)
  15.828 +     *         addChild(XMLElement)
  15.829 +     * @see nanoxml.XMLElement#countChildren()
  15.830 +     * @see nanoxml.XMLElement#getChildren()
  15.831 +     * @see nanoxml.XMLElement#removeChild(nanoxml.XMLElement)
  15.832 +     *         removeChild(XMLElement)
  15.833 +     */
  15.834 +    public Enumeration enumerateChildren()
  15.835 +    {
  15.836 +        return this.children.elements();
  15.837 +    }
  15.838 +
  15.839 +
  15.840 +    /**
  15.841 +     * Returns the child elements as a Vector. It is safe to modify this
  15.842 +     * Vector.
  15.843 +     *
  15.844 +     * <dl><dt><b>Postconditions:</b></dt><dd>
  15.845 +     * <ul><li><code>result != null</code>
  15.846 +     * </ul></dd></dl>
  15.847 +     *
  15.848 +     * @see nanoxml.XMLElement#addChild(nanoxml.XMLElement)
  15.849 +     *         addChild(XMLElement)
  15.850 +     * @see nanoxml.XMLElement#countChildren()
  15.851 +     * @see nanoxml.XMLElement#enumerateChildren()
  15.852 +     * @see nanoxml.XMLElement#removeChild(nanoxml.XMLElement)
  15.853 +     *         removeChild(XMLElement)
  15.854 +     */
  15.855 +    public Vector getChildren()
  15.856 +    {
  15.857 +        try {
  15.858 +            return (Vector) this.children.clone();
  15.859 +        } catch (Exception e) {
  15.860 +            // this never happens, however, some Java compilers are so
  15.861 +            // braindead that they require this exception clause
  15.862 +            return null;
  15.863 +        }
  15.864 +    }
  15.865 +
  15.866 +
  15.867 +    /**
  15.868 +     * Returns the PCDATA content of the object. If there is no such content,
  15.869 +     * <CODE>null</CODE> is returned.
  15.870 +     *
  15.871 +     * @deprecated Use {@link #getContent() getContent} instead.
  15.872 +     */
  15.873 +    public String getContents()
  15.874 +    {
  15.875 +        return this.getContent();
  15.876 +    }
  15.877 +
  15.878 +
  15.879 +    /**
  15.880 +     * Returns the PCDATA content of the object. If there is no such content,
  15.881 +     * <CODE>null</CODE> is returned.
  15.882 +     *
  15.883 +     * @see nanoxml.XMLElement#setContent(java.lang.String)
  15.884 +     *         setContent(String)
  15.885 +     */
  15.886 +    public String getContent()
  15.887 +    {
  15.888 +        return this.contents;
  15.889 +    }
  15.890 +
  15.891 +
  15.892 +    /**
  15.893 +     * Returns the line nr in the source data on which the element is found.
  15.894 +     * This method returns <code>0</code> there is no associated source data.
  15.895 +     *
  15.896 +     * <dl><dt><b>Postconditions:</b></dt><dd>
  15.897 +     * <ul><li><code>result >= 0</code>
  15.898 +     * </ul></dd></dl>
  15.899 +     */
  15.900 +    public int getLineNr()
  15.901 +    {
  15.902 +        return this.lineNr;
  15.903 +    }
  15.904 +
  15.905 +
  15.906 +    /**
  15.907 +     * Returns an attribute of the element.
  15.908 +     * If the attribute doesn't exist, <code>null</code> is returned.
  15.909 +     *
  15.910 +     * @param name The name of the attribute.
  15.911 +     *
  15.912 +     * </dl><dl><dt><b>Preconditions:</b></dt><dd>
  15.913 +     * <ul><li><code>name != null</code>
  15.914 +     *     <li><code>name</code> is a valid XML identifier
  15.915 +     * </ul></dd></dl><dl>
  15.916 +     *
  15.917 +     * @see nanoxml.XMLElement#setAttribute(java.lang.String, java.lang.Object)
  15.918 +     *         setAttribute(String, Object)
  15.919 +     * @see nanoxml.XMLElement#removeAttribute(java.lang.String)
  15.920 +     *         removeAttribute(String)
  15.921 +     * @see nanoxml.XMLElement#enumerateAttributeNames()
  15.922 +     * @see nanoxml.XMLElement#getAttribute(java.lang.String, java.lang.Object)
  15.923 +     *         getAttribute(String, Object)
  15.924 +     * @see nanoxml.XMLElement#getAttribute(java.lang.String,
  15.925 +     *                                      java.util.Hashtable,
  15.926 +     *                                      java.lang.String, boolean)
  15.927 +     *         getAttribute(String, Hashtable, String, boolean)
  15.928 +     */
  15.929 +    public Object getAttribute(String name)
  15.930 +    {
  15.931 +        return this.getAttribute(name, null);
  15.932 +    }
  15.933 +
  15.934 +
  15.935 +    /**
  15.936 +     * Returns an attribute of the element.
  15.937 +     * If the attribute doesn't exist, <code>defaultValue</code> is returned.
  15.938 +     *
  15.939 +     * @param name         The name of the attribute.
  15.940 +     * @param defaultValue Key to use if the attribute is missing.
  15.941 +     *
  15.942 +     * </dl><dl><dt><b>Preconditions:</b></dt><dd>
  15.943 +     * <ul><li><code>name != null</code>
  15.944 +     *     <li><code>name</code> is a valid XML identifier
  15.945 +     * </ul></dd></dl><dl>
  15.946 +     *
  15.947 +     * @see nanoxml.XMLElement#setAttribute(java.lang.String, java.lang.Object)
  15.948 +     *         setAttribute(String, Object)
  15.949 +     * @see nanoxml.XMLElement#removeAttribute(java.lang.String)
  15.950 +     *         removeAttribute(String)
  15.951 +     * @see nanoxml.XMLElement#enumerateAttributeNames()
  15.952 +     * @see nanoxml.XMLElement#getAttribute(java.lang.String)
  15.953 +     *         getAttribute(String)
  15.954 +     * @see nanoxml.XMLElement#getAttribute(java.lang.String,
  15.955 +     *                                      java.util.Hashtable,
  15.956 +     *                                      java.lang.String, boolean)
  15.957 +     *         getAttribute(String, Hashtable, String, boolean)
  15.958 +     */
  15.959 +    public Object getAttribute(String name,
  15.960 +                               Object defaultValue)
  15.961 +    {
  15.962 +        if (this.ignoreCase) {
  15.963 +            name = name.toUpperCase();
  15.964 +        }
  15.965 +        Object value = this.attributes.get(name);
  15.966 +        if (value == null) {
  15.967 +            value = defaultValue;
  15.968 +        }
  15.969 +        return value;
  15.970 +    }
  15.971 +
  15.972 +
  15.973 +    /**
  15.974 +     * Returns an attribute by looking up a key in a hashtable.
  15.975 +     * If the attribute doesn't exist, the value corresponding to defaultKey
  15.976 +     * is returned.
  15.977 +     * <P>
  15.978 +     * As an example, if valueSet contains the mapping <code>"one" =>
  15.979 +     * "1"</code>
  15.980 +     * and the element contains the attribute <code>attr="one"</code>, then
  15.981 +     * <code>getAttribute("attr", mapping, defaultKey, false)</code> returns
  15.982 +     * <code>"1"</code>.
  15.983 +     *
  15.984 +     * @param name
  15.985 +     *     The name of the attribute.
  15.986 +     * @param valueSet
  15.987 +     *     Hashtable mapping keys to values.
  15.988 +     * @param defaultKey
  15.989 +     *     Key to use if the attribute is missing.
  15.990 +     * @param allowLiterals
  15.991 +     *     <code>true</code> if literals are valid.
  15.992 +     *
  15.993 +     * </dl><dl><dt><b>Preconditions:</b></dt><dd>
  15.994 +     * <ul><li><code>name != null</code>
  15.995 +     *     <li><code>name</code> is a valid XML identifier
  15.996 +     *     <li><code>valueSet</code> != null
  15.997 +     *     <li>the keys of <code>valueSet</code> are strings
  15.998 +     * </ul></dd></dl><dl>
  15.999 +     *
 15.1000 +     * @see nanoxml.XMLElement#setAttribute(java.lang.String, java.lang.Object)
 15.1001 +     *         setAttribute(String, Object)
 15.1002 +     * @see nanoxml.XMLElement#removeAttribute(java.lang.String)
 15.1003 +     *         removeAttribute(String)
 15.1004 +     * @see nanoxml.XMLElement#enumerateAttributeNames()
 15.1005 +     * @see nanoxml.XMLElement#getAttribute(java.lang.String)
 15.1006 +     *         getAttribute(String)
 15.1007 +     * @see nanoxml.XMLElement#getAttribute(java.lang.String, java.lang.Object)
 15.1008 +     *         getAttribute(String, Object)
 15.1009 +     */
 15.1010 +    public Object getAttribute(String    name,
 15.1011 +                               Hashtable valueSet,
 15.1012 +                               String    defaultKey,
 15.1013 +                               boolean   allowLiterals)
 15.1014 +    {
 15.1015 +        if (this.ignoreCase) {
 15.1016 +            name = name.toUpperCase();
 15.1017 +        }
 15.1018 +        Object key = this.attributes.get(name);
 15.1019 +        Object result;
 15.1020 +        if (key == null) {
 15.1021 +            key = defaultKey;
 15.1022 +        }
 15.1023 +        result = valueSet.get(key);
 15.1024 +        if (result == null) {
 15.1025 +            if (allowLiterals) {
 15.1026 +                result = key;
 15.1027 +            } else {
 15.1028 +                throw this.invalidValue(name, (String) key);
 15.1029 +            }
 15.1030 +        }
 15.1031 +        return result;
 15.1032 +    }
 15.1033 +
 15.1034 +
 15.1035 +    /**
 15.1036 +     * Returns an attribute of the element.
 15.1037 +     * If the attribute doesn't exist, <code>null</code> is returned.
 15.1038 +     *
 15.1039 +     * @param name The name of the attribute.
 15.1040 +     *
 15.1041 +     * </dl><dl><dt><b>Preconditions:</b></dt><dd>
 15.1042 +     * <ul><li><code>name != null</code>
 15.1043 +     *     <li><code>name</code> is a valid XML identifier
 15.1044 +     * </ul></dd></dl><dl>
 15.1045 +     *
 15.1046 +     * @see nanoxml.XMLElement#setAttribute(java.lang.String, java.lang.Object)
 15.1047 +     *         setAttribute(String, Object)
 15.1048 +     * @see nanoxml.XMLElement#removeAttribute(java.lang.String)
 15.1049 +     *         removeAttribute(String)
 15.1050 +     * @see nanoxml.XMLElement#enumerateAttributeNames()
 15.1051 +     * @see nanoxml.XMLElement#getStringAttribute(java.lang.String,
 15.1052 +     *                                            java.lang.String)
 15.1053 +     *         getStringAttribute(String, String)
 15.1054 +     * @see nanoxml.XMLElement#getStringAttribute(java.lang.String,
 15.1055 +     *                                            java.util.Hashtable,
 15.1056 +     *                                            java.lang.String, boolean)
 15.1057 +     *         getStringAttribute(String, Hashtable, String, boolean)
 15.1058 +     */
 15.1059 +    public String getStringAttribute(String name)
 15.1060 +    {
 15.1061 +        return this.getStringAttribute(name, null);
 15.1062 +    }
 15.1063 +
 15.1064 +
 15.1065 +    /**
 15.1066 +     * Returns an attribute of the element.
 15.1067 +     * If the attribute doesn't exist, <code>defaultValue</code> is returned.
 15.1068 +     *
 15.1069 +     * @param name         The name of the attribute.
 15.1070 +     * @param defaultValue Key to use if the attribute is missing.
 15.1071 +     *
 15.1072 +     * </dl><dl><dt><b>Preconditions:</b></dt><dd>
 15.1073 +     * <ul><li><code>name != null</code>
 15.1074 +     *     <li><code>name</code> is a valid XML identifier
 15.1075 +     * </ul></dd></dl><dl>
 15.1076 +     *
 15.1077 +     * @see nanoxml.XMLElement#setAttribute(java.lang.String, java.lang.Object)
 15.1078 +     *         setAttribute(String, Object)
 15.1079 +     * @see nanoxml.XMLElement#removeAttribute(java.lang.String)
 15.1080 +     *         removeAttribute(String)
 15.1081 +     * @see nanoxml.XMLElement#enumerateAttributeNames()
 15.1082 +     * @see nanoxml.XMLElement#getStringAttribute(java.lang.String)
 15.1083 +     *         getStringAttribute(String)
 15.1084 +     * @see nanoxml.XMLElement#getStringAttribute(java.lang.String,
 15.1085 +     *                                            java.util.Hashtable,
 15.1086 +     *                                            java.lang.String, boolean)
 15.1087 +     *         getStringAttribute(String, Hashtable, String, boolean)
 15.1088 +     */
 15.1089 +    public String getStringAttribute(String name,
 15.1090 +                                     String defaultValue)
 15.1091 +    {
 15.1092 +        return (String) this.getAttribute(name, defaultValue);
 15.1093 +    }
 15.1094 +
 15.1095 +
 15.1096 +    /**
 15.1097 +     * Returns an attribute by looking up a key in a hashtable.
 15.1098 +     * If the attribute doesn't exist, the value corresponding to defaultKey
 15.1099 +     * is returned.
 15.1100 +     * <P>
 15.1101 +     * As an example, if valueSet contains the mapping <code>"one" =>
 15.1102 +     * "1"</code>
 15.1103 +     * and the element contains the attribute <code>attr="one"</code>, then
 15.1104 +     * <code>getAttribute("attr", mapping, defaultKey, false)</code> returns
 15.1105 +     * <code>"1"</code>.
 15.1106 +     *
 15.1107 +     * @param name
 15.1108 +     *     The name of the attribute.
 15.1109 +     * @param valueSet
 15.1110 +     *     Hashtable mapping keys to values.
 15.1111 +     * @param defaultKey
 15.1112 +     *     Key to use if the attribute is missing.
 15.1113 +     * @param allowLiterals
 15.1114 +     *     <code>true</code> if literals are valid.
 15.1115 +     *
 15.1116 +     * </dl><dl><dt><b>Preconditions:</b></dt><dd>
 15.1117 +     * <ul><li><code>name != null</code>
 15.1118 +     *     <li><code>name</code> is a valid XML identifier
 15.1119 +     *     <li><code>valueSet</code> != null
 15.1120 +     *     <li>the keys of <code>valueSet</code> are strings
 15.1121 +     *     <li>the values of <code>valueSet</code> are strings
 15.1122 +     * </ul></dd></dl><dl>
 15.1123 +     *
 15.1124 +     * @see nanoxml.XMLElement#setAttribute(java.lang.String, java.lang.Object)
 15.1125 +     *         setAttribute(String, Object)
 15.1126 +     * @see nanoxml.XMLElement#removeAttribute(java.lang.String)
 15.1127 +     *         removeAttribute(String)
 15.1128 +     * @see nanoxml.XMLElement#enumerateAttributeNames()
 15.1129 +     * @see nanoxml.XMLElement#getStringAttribute(java.lang.String)
 15.1130 +     *         getStringAttribute(String)
 15.1131 +     * @see nanoxml.XMLElement#getStringAttribute(java.lang.String,
 15.1132 +     *                                            java.lang.String)
 15.1133 +     *         getStringAttribute(String, String)
 15.1134 +     */
 15.1135 +    public String getStringAttribute(String    name,
 15.1136 +                                     Hashtable valueSet,
 15.1137 +                                     String    defaultKey,
 15.1138 +                                     boolean   allowLiterals)
 15.1139 +    {
 15.1140 +        return (String) this.getAttribute(name, valueSet, defaultKey,
 15.1141 +                                          allowLiterals);
 15.1142 +    }
 15.1143 +
 15.1144 +
 15.1145 +    /**
 15.1146 +     * Returns an attribute of the element.
 15.1147 +     * If the attribute doesn't exist, <code>0</code> is returned.
 15.1148 +     *
 15.1149 +     * @param name The name of the attribute.
 15.1150 +     *
 15.1151 +     * </dl><dl><dt><b>Preconditions:</b></dt><dd>
 15.1152 +     * <ul><li><code>name != null</code>
 15.1153 +     *     <li><code>name</code> is a valid XML identifier
 15.1154 +     * </ul></dd></dl><dl>
 15.1155 +     *
 15.1156 +     * @see nanoxml.XMLElement#setIntAttribute(java.lang.String, int)
 15.1157 +     *         setIntAttribute(String, int)
 15.1158 +     * @see nanoxml.XMLElement#enumerateAttributeNames()
 15.1159 +     * @see nanoxml.XMLElement#getIntAttribute(java.lang.String, int)
 15.1160 +     *         getIntAttribute(String, int)
 15.1161 +     * @see nanoxml.XMLElement#getIntAttribute(java.lang.String,
 15.1162 +     *                                         java.util.Hashtable,
 15.1163 +     *                                         java.lang.String, boolean)
 15.1164 +     *         getIntAttribute(String, Hashtable, String, boolean)
 15.1165 +     */
 15.1166 +    public int getIntAttribute(String name)
 15.1167 +    {
 15.1168 +        return this.getIntAttribute(name, 0);
 15.1169 +    }
 15.1170 +
 15.1171 +
 15.1172 +    /**
 15.1173 +     * Returns an attribute of the element.
 15.1174 +     * If the attribute doesn't exist, <code>defaultValue</code> is returned.
 15.1175 +     *
 15.1176 +     * @param name         The name of the attribute.
 15.1177 +     * @param defaultValue Key to use if the attribute is missing.
 15.1178 +     *
 15.1179 +     * </dl><dl><dt><b>Preconditions:</b></dt><dd>
 15.1180 +     * <ul><li><code>name != null</code>
 15.1181 +     *     <li><code>name</code> is a valid XML identifier
 15.1182 +     * </ul></dd></dl><dl>
 15.1183 +     *
 15.1184 +     * @see nanoxml.XMLElement#setIntAttribute(java.lang.String, int)
 15.1185 +     *         setIntAttribute(String, int)
 15.1186 +     * @see nanoxml.XMLElement#enumerateAttributeNames()
 15.1187 +     * @see nanoxml.XMLElement#getIntAttribute(java.lang.String)
 15.1188 +     *         getIntAttribute(String)
 15.1189 +     * @see nanoxml.XMLElement#getIntAttribute(java.lang.String,
 15.1190 +     *                                         java.util.Hashtable,
 15.1191 +     *                                         java.lang.String, boolean)
 15.1192 +     *         getIntAttribute(String, Hashtable, String, boolean)
 15.1193 +     */
 15.1194 +    public int getIntAttribute(String name,
 15.1195 +                               int    defaultValue)
 15.1196 +    {
 15.1197 +        if (this.ignoreCase) {
 15.1198 +            name = name.toUpperCase();
 15.1199 +        }
 15.1200 +        String value = (String) this.attributes.get(name);
 15.1201 +        if (value == null) {
 15.1202 +            return defaultValue;
 15.1203 +        } else {
 15.1204 +            try {
 15.1205 +                return Integer.parseInt(value);
 15.1206 +            } catch (NumberFormatException e) {
 15.1207 +                throw this.invalidValue(name, value);
 15.1208 +            }
 15.1209 +        }
 15.1210 +    }
 15.1211 +
 15.1212 +
 15.1213 +    /**
 15.1214 +     * Returns an attribute by looking up a key in a hashtable.
 15.1215 +     * If the attribute doesn't exist, the value corresponding to defaultKey
 15.1216 +     * is returned.
 15.1217 +     * <P>
 15.1218 +     * As an example, if valueSet contains the mapping <code>"one" => 1</code>
 15.1219 +     * and the element contains the attribute <code>attr="one"</code>, then
 15.1220 +     * <code>getIntAttribute("attr", mapping, defaultKey, false)</code> returns
 15.1221 +     * <code>1</code>.
 15.1222 +     *
 15.1223 +     * @param name
 15.1224 +     *     The name of the attribute.
 15.1225 +     * @param valueSet
 15.1226 +     *     Hashtable mapping keys to values.
 15.1227 +     * @param defaultKey
 15.1228 +     *     Key to use if the attribute is missing.
 15.1229 +     * @param allowLiteralNumbers
 15.1230 +     *     <code>true</code> if literal numbers are valid.
 15.1231 +     *
 15.1232 +     * </dl><dl><dt><b>Preconditions:</b></dt><dd>
 15.1233 +     * <ul><li><code>name != null</code>
 15.1234 +     *     <li><code>name</code> is a valid XML identifier
 15.1235 +     *     <li><code>valueSet</code> != null
 15.1236 +     *     <li>the keys of <code>valueSet</code> are strings
 15.1237 +     *     <li>the values of <code>valueSet</code> are Integer objects
 15.1238 +     *     <li><code>defaultKey</code> is either <code>null</code>, a
 15.1239 +     *         key in <code>valueSet</code> or an integer.
 15.1240 +     * </ul></dd></dl><dl>
 15.1241 +     *
 15.1242 +     * @see nanoxml.XMLElement#setIntAttribute(java.lang.String, int)
 15.1243 +     *         setIntAttribute(String, int)
 15.1244 +     * @see nanoxml.XMLElement#enumerateAttributeNames()
 15.1245 +     * @see nanoxml.XMLElement#getIntAttribute(java.lang.String)
 15.1246 +     *         getIntAttribute(String)
 15.1247 +     * @see nanoxml.XMLElement#getIntAttribute(java.lang.String, int)
 15.1248 +     *         getIntAttribute(String, int)
 15.1249 +     */
 15.1250 +    public int getIntAttribute(String    name,
 15.1251 +                               Hashtable valueSet,
 15.1252 +                               String    defaultKey,
 15.1253 +                               boolean   allowLiteralNumbers)
 15.1254 +    {
 15.1255 +        if (this.ignoreCase) {
 15.1256 +            name = name.toUpperCase();
 15.1257 +        }
 15.1258 +        Object key = this.attributes.get(name);
 15.1259 +        Integer result;
 15.1260 +        if (key == null) {
 15.1261 +            key = defaultKey;
 15.1262 +        }
 15.1263 +        try {
 15.1264 +            result = (Integer) valueSet.get(key);
 15.1265 +        } catch (ClassCastException e) {
 15.1266 +            throw this.invalidValueSet(name);
 15.1267 +        }
 15.1268 +        if (result == null) {
 15.1269 +            if (! allowLiteralNumbers) {
 15.1270 +                throw this.invalidValue(name, (String) key);
 15.1271 +            }
 15.1272 +            try {
 15.1273 +                result = Integer.valueOf((String) key);
 15.1274 +            } catch (NumberFormatException e) {
 15.1275 +                throw this.invalidValue(name, (String) key);
 15.1276 +            }
 15.1277 +        }
 15.1278 +        return result.intValue();
 15.1279 +    }
 15.1280 +
 15.1281 +
 15.1282 +    /**
 15.1283 +     * Returns an attribute of the element.
 15.1284 +     * If the attribute doesn't exist, <code>0.0</code> is returned.
 15.1285 +     *
 15.1286 +     * @param name The name of the attribute.
 15.1287 +     *
 15.1288 +     * </dl><dl><dt><b>Preconditions:</b></dt><dd>
 15.1289 +     * <ul><li><code>name != null</code>
 15.1290 +     *     <li><code>name</code> is a valid XML identifier
 15.1291 +     * </ul></dd></dl><dl>
 15.1292 +     *
 15.1293 +     * @see nanoxml.XMLElement#setDoubleAttribute(java.lang.String, double)
 15.1294 +     *         setDoubleAttribute(String, double)
 15.1295 +     * @see nanoxml.XMLElement#enumerateAttributeNames()
 15.1296 +     * @see nanoxml.XMLElement#getDoubleAttribute(java.lang.String, double)
 15.1297 +     *         getDoubleAttribute(String, double)
 15.1298 +     * @see nanoxml.XMLElement#getDoubleAttribute(java.lang.String,
 15.1299 +     *                                            java.util.Hashtable,
 15.1300 +     *                                            java.lang.String, boolean)
 15.1301 +     *         getDoubleAttribute(String, Hashtable, String, boolean)
 15.1302 +     */
 15.1303 +    public double getDoubleAttribute(String name)
 15.1304 +    {
 15.1305 +        return this.getDoubleAttribute(name, 0.);
 15.1306 +    }
 15.1307 +
 15.1308 +
 15.1309 +    /**
 15.1310 +     * Returns an attribute of the element.
 15.1311 +     * If the attribute doesn't exist, <code>defaultValue</code> is returned.
 15.1312 +     *
 15.1313 +     * @param name         The name of the attribute.
 15.1314 +     * @param defaultValue Key to use if the attribute is missing.
 15.1315 +     *
 15.1316 +     * </dl><dl><dt><b>Preconditions:</b></dt><dd>
 15.1317 +     * <ul><li><code>name != null</code>
 15.1318 +     *     <li><code>name</code> is a valid XML identifier
 15.1319 +     * </ul></dd></dl><dl>
 15.1320 +     *
 15.1321 +     * @see nanoxml.XMLElement#setDoubleAttribute(java.lang.String, double)
 15.1322 +     *         setDoubleAttribute(String, double)
 15.1323 +     * @see nanoxml.XMLElement#enumerateAttributeNames()
 15.1324 +     * @see nanoxml.XMLElement#getDoubleAttribute(java.lang.String)
 15.1325 +     *         getDoubleAttribute(String)
 15.1326 +     * @see nanoxml.XMLElement#getDoubleAttribute(java.lang.String,
 15.1327 +     *                                            java.util.Hashtable,
 15.1328 +     *                                            java.lang.String, boolean)
 15.1329 +     *         getDoubleAttribute(String, Hashtable, String, boolean)
 15.1330 +     */
 15.1331 +    public double getDoubleAttribute(String name,
 15.1332 +                                     double defaultValue)
 15.1333 +    {
 15.1334 +        if (this.ignoreCase) {
 15.1335 +            name = name.toUpperCase();
 15.1336 +        }
 15.1337 +        String value = (String) this.attributes.get(name);
 15.1338 +        if (value == null) {
 15.1339 +            return defaultValue;
 15.1340 +        } else {
 15.1341 +            try {
 15.1342 +                return Double.valueOf(value).doubleValue();
 15.1343 +            } catch (NumberFormatException e) {
 15.1344 +                throw this.invalidValue(name, value);
 15.1345 +            }
 15.1346 +        }
 15.1347 +    }
 15.1348 +
 15.1349 +
 15.1350 +    /**
 15.1351 +     * Returns an attribute by looking up a key in a hashtable.
 15.1352 +     * If the attribute doesn't exist, the value corresponding to defaultKey
 15.1353 +     * is returned.
 15.1354 +     * <P>
 15.1355 +     * As an example, if valueSet contains the mapping <code>"one" =&gt;
 15.1356 +     * 1.0</code>
 15.1357 +     * and the element contains the attribute <code>attr="one"</code>, then
 15.1358 +     * <code>getDoubleAttribute("attr", mapping, defaultKey, false)</code>
 15.1359 +     * returns <code>1.0</code>.
 15.1360 +     *
 15.1361 +     * @param name
 15.1362 +     *     The name of the attribute.
 15.1363 +     * @param valueSet
 15.1364 +     *     Hashtable mapping keys to values.
 15.1365 +     * @param defaultKey
 15.1366 +     *     Key to use if the attribute is missing.
 15.1367 +     * @param allowLiteralNumbers
 15.1368 +     *     <code>true</code> if literal numbers are valid.
 15.1369 +     *
 15.1370 +     * </dl><dl><dt><b>Preconditions:</b></dt><dd>
 15.1371 +     * <ul><li><code>name != null</code>
 15.1372 +     *     <li><code>name</code> is a valid XML identifier
 15.1373 +     *     <li><code>valueSet != null</code>
 15.1374 +     *     <li>the keys of <code>valueSet</code> are strings
 15.1375 +     *     <li>the values of <code>valueSet</code> are Double objects
 15.1376 +     *     <li><code>defaultKey</code> is either <code>null</code>, a
 15.1377 +     *         key in <code>valueSet</code> or a double.
 15.1378 +     * </ul></dd></dl><dl>
 15.1379 +     *
 15.1380 +     * @see nanoxml.XMLElement#setDoubleAttribute(java.lang.String, double)
 15.1381 +     *         setDoubleAttribute(String, double)
 15.1382 +     * @see nanoxml.XMLElement#enumerateAttributeNames()
 15.1383 +     * @see nanoxml.XMLElement#getDoubleAttribute(java.lang.String)
 15.1384 +     *         getDoubleAttribute(String)
 15.1385 +     * @see nanoxml.XMLElement#getDoubleAttribute(java.lang.String, double)
 15.1386 +     *         getDoubleAttribute(String, double)
 15.1387 +     */
 15.1388 +    public double getDoubleAttribute(String    name,
 15.1389 +                                     Hashtable valueSet,
 15.1390 +                                     String    defaultKey,
 15.1391 +                                     boolean   allowLiteralNumbers)
 15.1392 +    {
 15.1393 +        if (this.ignoreCase) {
 15.1394 +            name = name.toUpperCase();
 15.1395 +        }
 15.1396 +        Object key = this.attributes.get(name);
 15.1397 +        Double result;
 15.1398 +        if (key == null) {
 15.1399 +            key = defaultKey;
 15.1400 +        }
 15.1401 +        try {
 15.1402 +            result = (Double) valueSet.get(key);
 15.1403 +        } catch (ClassCastException e) {
 15.1404 +            throw this.invalidValueSet(name);
 15.1405 +        }
 15.1406 +        if (result == null) {
 15.1407 +            if (! allowLiteralNumbers) {
 15.1408 +                throw this.invalidValue(name, (String) key);
 15.1409 +            }
 15.1410 +            try {
 15.1411 +                result = Double.valueOf((String) key);
 15.1412 +            } catch (NumberFormatException e) {
 15.1413 +                throw this.invalidValue(name, (String) key);
 15.1414 +            }
 15.1415 +        }
 15.1416 +        return result.doubleValue();
 15.1417 +    }
 15.1418 +
 15.1419 +
 15.1420 +    /**
 15.1421 +     * Returns an attribute of the element.
 15.1422 +     * If the attribute doesn't exist, <code>defaultValue</code> is returned.
 15.1423 +     * If the value of the attribute is equal to <code>trueValue</code>,
 15.1424 +     * <code>true</code> is returned.
 15.1425 +     * If the value of the attribute is equal to <code>falseValue</code>,
 15.1426 +     * <code>false</code> is returned.
 15.1427 +     * If the value doesn't match <code>trueValue</code> or
 15.1428 +     * <code>falseValue</code>, an exception is thrown.
 15.1429 +     *
 15.1430 +     * @param name         The name of the attribute.
 15.1431 +     * @param trueValue    The value associated with <code>true</code>.
 15.1432 +     * @param falseValue   The value associated with <code>true</code>.
 15.1433 +     * @param defaultValue Value to use if the attribute is missing.
 15.1434 +     *
 15.1435 +     * </dl><dl><dt><b>Preconditions:</b></dt><dd>
 15.1436 +     * <ul><li><code>name != null</code>
 15.1437 +     *     <li><code>name</code> is a valid XML identifier
 15.1438 +     *     <li><code>trueValue</code> and <code>falseValue</code>
 15.1439 +     *         are different strings.
 15.1440 +     * </ul></dd></dl><dl>
 15.1441 +     *
 15.1442 +     * @see nanoxml.XMLElement#setAttribute(java.lang.String, java.lang.Object)
 15.1443 +     *         setAttribute(String, Object)
 15.1444 +     * @see nanoxml.XMLElement#removeAttribute(java.lang.String)
 15.1445 +     *         removeAttribute(String)
 15.1446 +     * @see nanoxml.XMLElement#enumerateAttributeNames()
 15.1447 +     */
 15.1448 +    public boolean getBooleanAttribute(String  name,
 15.1449 +                                       String  trueValue,
 15.1450 +                                       String  falseValue,
 15.1451 +                                       boolean defaultValue)
 15.1452 +    {
 15.1453 +        if (this.ignoreCase) {
 15.1454 +            name = name.toUpperCase();
 15.1455 +        }
 15.1456 +        Object value = this.attributes.get(name);
 15.1457 +        if (value == null) {
 15.1458 +            return defaultValue;
 15.1459 +        } else if (value.equals(trueValue)) {
 15.1460 +            return true;
 15.1461 +        } else if (value.equals(falseValue)) {
 15.1462 +            return false;
 15.1463 +        } else {
 15.1464 +            throw this.invalidValue(name, (String) value);
 15.1465 +        }
 15.1466 +    }
 15.1467 +
 15.1468 +
 15.1469 +    /**
 15.1470 +     * Returns an attribute by looking up a key in a hashtable.
 15.1471 +     *
 15.1472 +     * @deprecated Use {@link #getIntAttribute(java.lang.String,
 15.1473 +     *             java.util.Hashtable, java.lang.String, boolean)
 15.1474 +     *             getIntAttribute} instead.
 15.1475 +     */
 15.1476 +    public int getIntProperty(String    name,
 15.1477 +                              Hashtable valueSet,
 15.1478 +                              String    defaultKey)
 15.1479 +    {
 15.1480 +        return this.getIntAttribute(name, valueSet, defaultKey, false);
 15.1481 +    }
 15.1482 +
 15.1483 +
 15.1484 +    /**
 15.1485 +     * Returns an attribute.
 15.1486 +     *
 15.1487 +     * @deprecated Use {@link #getStringAttribute(java.lang.String)
 15.1488 +     *             getStringAttribute} instead.
 15.1489 +     */
 15.1490 +    public String getProperty(String name)
 15.1491 +    {
 15.1492 +        return this.getStringAttribute(name);
 15.1493 +    }
 15.1494 +
 15.1495 +
 15.1496 +    /**
 15.1497 +     * Returns an attribute.
 15.1498 +     *
 15.1499 +     * @deprecated Use {@link #getStringAttribute(java.lang.String,
 15.1500 +     *             java.lang.String) getStringAttribute} instead.
 15.1501 +     */
 15.1502 +    public String getProperty(String name,
 15.1503 +                              String defaultValue)
 15.1504 +    {
 15.1505 +        return this.getStringAttribute(name, defaultValue);
 15.1506 +    }
 15.1507 +
 15.1508 +
 15.1509 +    /**
 15.1510 +     * Returns an attribute.
 15.1511 +     *
 15.1512 +     * @deprecated Use {@link #getIntAttribute(java.lang.String, int)
 15.1513 +     *             getIntAttribute} instead.
 15.1514 +     */
 15.1515 +    public int getProperty(String name,
 15.1516 +                           int    defaultValue)
 15.1517 +    {
 15.1518 +        return this.getIntAttribute(name, defaultValue);
 15.1519 +    }
 15.1520 +
 15.1521 +
 15.1522 +    /**
 15.1523 +     * Returns an attribute.
 15.1524 +     *
 15.1525 +     * @deprecated Use {@link #getDoubleAttribute(java.lang.String, double)
 15.1526 +     *             getDoubleAttribute} instead.
 15.1527 +     */
 15.1528 +    public double getProperty(String name,
 15.1529 +                              double defaultValue)
 15.1530 +    {
 15.1531 +        return this.getDoubleAttribute(name, defaultValue);
 15.1532 +    }
 15.1533 +
 15.1534 +
 15.1535 +    /**
 15.1536 +     * Returns an attribute.
 15.1537 +     *
 15.1538 +     * @deprecated Use {@link #getBooleanAttribute(java.lang.String,
 15.1539 +     *             java.lang.String, java.lang.String, boolean)
 15.1540 +     *             getBooleanAttribute} instead.
 15.1541 +     */
 15.1542 +    public boolean getProperty(String  key,
 15.1543 +                               String  trueValue,
 15.1544 +                               String  falseValue,
 15.1545 +                               boolean defaultValue)
 15.1546 +    {
 15.1547 +        return this.getBooleanAttribute(key, trueValue, falseValue,
 15.1548 +                                        defaultValue);
 15.1549 +    }
 15.1550 +
 15.1551 +
 15.1552 +    /**
 15.1553 +     * Returns an attribute by looking up a key in a hashtable.
 15.1554 +     *
 15.1555 +     * @deprecated Use {@link #getAttribute(java.lang.String,
 15.1556 +     *             java.util.Hashtable, java.lang.String, boolean)
 15.1557 +     *             getAttribute} instead.
 15.1558 +     */
 15.1559 +    public Object getProperty(String    name,
 15.1560 +                              Hashtable valueSet,
 15.1561 +                              String    defaultKey)
 15.1562 +    {
 15.1563 +        return this.getAttribute(name, valueSet, defaultKey, false);
 15.1564 +    }
 15.1565 +
 15.1566 +
 15.1567 +    /**
 15.1568 +     * Returns an attribute by looking up a key in a hashtable.
 15.1569 +     *
 15.1570 +     * @deprecated Use {@link #getStringAttribute(java.lang.String,
 15.1571 +     *             java.util.Hashtable, java.lang.String, boolean)
 15.1572 +     *             getStringAttribute} instead.
 15.1573 +     */
 15.1574 +    public String getStringProperty(String    name,
 15.1575 +                                    Hashtable valueSet,
 15.1576 +                                    String    defaultKey)
 15.1577 +    {
 15.1578 +        return this.getStringAttribute(name, valueSet, defaultKey, false);
 15.1579 +    }
 15.1580 +
 15.1581 +
 15.1582 +    /**
 15.1583 +     * Returns an attribute by looking up a key in a hashtable.
 15.1584 +     *
 15.1585 +     * @deprecated Use {@link #getIntAttribute(java.lang.String,
 15.1586 +     *             java.util.Hashtable, java.lang.String, boolean)
 15.1587 +     *             getIntAttribute} instead.
 15.1588 +     */
 15.1589 +    public int getSpecialIntProperty(String    name,
 15.1590 +                                     Hashtable valueSet,
 15.1591 +                                     String    defaultKey)
 15.1592 +    {
 15.1593 +        return this.getIntAttribute(name, valueSet, defaultKey, true);
 15.1594 +    }
 15.1595 +
 15.1596 +
 15.1597 +    /**
 15.1598 +     * Returns an attribute by looking up a key in a hashtable.
 15.1599 +     *
 15.1600 +     * @deprecated Use {@link #getDoubleAttribute(java.lang.String,
 15.1601 +     *             java.util.Hashtable, java.lang.String, boolean)
 15.1602 +     *             getDoubleAttribute} instead.
 15.1603 +     */
 15.1604 +    public double getSpecialDoubleProperty(String    name,
 15.1605 +                                           Hashtable valueSet,
 15.1606 +                                           String    defaultKey)
 15.1607 +    {
 15.1608 +        return this.getDoubleAttribute(name, valueSet, defaultKey, true);
 15.1609 +    }
 15.1610 +
 15.1611 +
 15.1612 +    /**
 15.1613 +     * Returns the name of the element.
 15.1614 +     *
 15.1615 +     * @see nanoxml.XMLElement#setName(java.lang.String) setName(String)
 15.1616 +     */
 15.1617 +    public String getName()
 15.1618 +    {
 15.1619 +        return this.name;
 15.1620 +    }
 15.1621 +
 15.1622 +
 15.1623 +    /**
 15.1624 +     * Returns the name of the element.
 15.1625 +     *
 15.1626 +     * @deprecated Use {@link #getName() getName} instead.
 15.1627 +     */
 15.1628 +    public String getTagName()
 15.1629 +    {
 15.1630 +        return this.getName();
 15.1631 +    }
 15.1632 +
 15.1633 +
 15.1634 +    /**
 15.1635 +     * Reads one XML element from a java.io.Reader and parses it.
 15.1636 +     *
 15.1637 +     * @param reader
 15.1638 +     *     The reader from which to retrieve the XML data.
 15.1639 +     *
 15.1640 +     * </dl><dl><dt><b>Preconditions:</b></dt><dd>
 15.1641 +     * <ul><li><code>reader != null</code>
 15.1642 +     *     <li><code>reader</code> is not closed
 15.1643 +     * </ul></dd></dl>
 15.1644 +     *
 15.1645 +     * <dl><dt><b>Postconditions:</b></dt><dd>
 15.1646 +     * <ul><li>the state of the receiver is updated to reflect the XML element
 15.1647 +     *         parsed from the reader
 15.1648 +     *     <li>the reader points to the first character following the last
 15.1649 +     *         '&gt;' character of the XML element
 15.1650 +     * </ul></dd></dl><dl>
 15.1651 +     *
 15.1652 +     * @throws java.io.IOException
 15.1653 +     *     If an error occured while reading the input.
 15.1654 +     * @throws nanoxml.XMLParseException
 15.1655 +     *     If an error occured while parsing the read data.
 15.1656 +     */
 15.1657 +    public void parseFromReader(Reader reader)
 15.1658 +    throws IOException, XMLParseException
 15.1659 +    {
 15.1660 +        this.parseFromReader(reader, /*startingLineNr*/ 1);
 15.1661 +    }
 15.1662 +
 15.1663 +
 15.1664 +    /**
 15.1665 +     * Reads one XML element from a java.io.Reader and parses it.
 15.1666 +     *
 15.1667 +     * @param reader
 15.1668 +     *     The reader from which to retrieve the XML data.
 15.1669 +     * @param startingLineNr
 15.1670 +     *     The line number of the first line in the data.
 15.1671 +     *
 15.1672 +     * </dl><dl><dt><b>Preconditions:</b></dt><dd>
 15.1673 +     * <ul><li><code>reader != null</code>
 15.1674 +     *     <li><code>reader</code> is not closed
 15.1675 +     * </ul></dd></dl>
 15.1676 +     *
 15.1677 +     * <dl><dt><b>Postconditions:</b></dt><dd>
 15.1678 +     * <ul><li>the state of the receiver is updated to reflect the XML element
 15.1679 +     *         parsed from the reader
 15.1680 +     *     <li>the reader points to the first character following the last
 15.1681 +     *         '&gt;' character of the XML element
 15.1682 +     * </ul></dd></dl><dl>
 15.1683 +     *
 15.1684 +     * @throws java.io.IOException
 15.1685 +     *     If an error occured while reading the input.
 15.1686 +     * @throws nanoxml.XMLParseException
 15.1687 +     *     If an error occured while parsing the read data.
 15.1688 +     */
 15.1689 +    public void parseFromReader(Reader reader,
 15.1690 +                                int    startingLineNr)
 15.1691 +        throws IOException, XMLParseException
 15.1692 +    {
 15.1693 +        this.name = null;
 15.1694 +        this.contents = "";
 15.1695 +        this.attributes = new Hashtable();
 15.1696 +        this.children = new Vector();
 15.1697 +        this.charReadTooMuch = '\0';
 15.1698 +        this.reader = reader;
 15.1699 +        this.parserLineNr = startingLineNr;
 15.1700 +
 15.1701 +        for (;;) {
 15.1702 +            char ch = this.scanWhitespace();
 15.1703 +
 15.1704 +            if (ch != '<') {
 15.1705 +                throw this.expectedInput("<");
 15.1706 +            }
 15.1707 +
 15.1708 +            ch = this.readChar();
 15.1709 +
 15.1710 +            if ((ch == '!') || (ch == '?')) {
 15.1711 +                this.skipSpecialTag(0);
 15.1712 +            } else {
 15.1713 +                this.unreadChar(ch);
 15.1714 +                this.scanElement(this);
 15.1715 +                return;
 15.1716 +            }
 15.1717 +        }
 15.1718 +    }
 15.1719 +
 15.1720 +
 15.1721 +    /**
 15.1722 +     * Reads one XML element from a String and parses it.
 15.1723 +     *
 15.1724 +     * @param reader
 15.1725 +     *     The reader from which to retrieve the XML data.
 15.1726 +     *
 15.1727 +     * </dl><dl><dt><b>Preconditions:</b></dt><dd>
 15.1728 +     * <ul><li><code>string != null</code>
 15.1729 +     *     <li><code>string.length() &gt; 0</code>
 15.1730 +     * </ul></dd></dl>
 15.1731 +     *
 15.1732 +     * <dl><dt><b>Postconditions:</b></dt><dd>
 15.1733 +     * <ul><li>the state of the receiver is updated to reflect the XML element
 15.1734 +     *         parsed from the reader
 15.1735 +     * </ul></dd></dl><dl>
 15.1736 +     *
 15.1737 +     * @throws nanoxml.XMLParseException
 15.1738 +     *     If an error occured while parsing the string.
 15.1739 +     */
 15.1740 +    public void parseString(String string)
 15.1741 +        throws XMLParseException
 15.1742 +    {
 15.1743 +        try {
 15.1744 +            this.parseFromReader(new StringReader(string),
 15.1745 +                                 /*startingLineNr*/ 1);
 15.1746 +        } catch (IOException e) {
 15.1747 +            // Java exception handling suxx
 15.1748 +        }
 15.1749 +    }
 15.1750 +
 15.1751 +
 15.1752 +    /**
 15.1753 +     * Reads one XML element from a String and parses it.
 15.1754 +     *
 15.1755 +     * @param reader
 15.1756 +     *     The reader from which to retrieve the XML data.
 15.1757 +     * @param offset
 15.1758 +     *     The first character in <code>string</code> to scan.
 15.1759 +     *
 15.1760 +     * </dl><dl><dt><b>Preconditions:</b></dt><dd>
 15.1761 +     * <ul><li><code>string != null</code>
 15.1762 +     *     <li><code>offset &lt; string.length()</code>
 15.1763 +     *     <li><code>offset &gt;= 0</code>
 15.1764 +     * </ul></dd></dl>
 15.1765 +     *
 15.1766 +     * <dl><dt><b>Postconditions:</b></dt><dd>
 15.1767 +     * <ul><li>the state of the receiver is updated to reflect the XML element
 15.1768 +     *         parsed from the reader
 15.1769 +     * </ul></dd></dl><dl>
 15.1770 +     *
 15.1771 +     * @throws nanoxml.XMLParseException
 15.1772 +     *     If an error occured while parsing the string.
 15.1773 +     */
 15.1774 +    public void parseString(String string,
 15.1775 +                            int    offset)
 15.1776 +        throws XMLParseException
 15.1777 +    {
 15.1778 +        this.parseString(string.substring(offset));
 15.1779 +    }
 15.1780 +
 15.1781 +
 15.1782 +    /**
 15.1783 +     * Reads one XML element from a String and parses it.
 15.1784 +     *
 15.1785 +     * @param reader
 15.1786 +     *     The reader from which to retrieve the XML data.
 15.1787 +     * @param offset
 15.1788 +     *     The first character in <code>string</code> to scan.
 15.1789 +     * @param end
 15.1790 +     *     The character where to stop scanning.
 15.1791 +     *     This character is not scanned.
 15.1792 +     *
 15.1793 +     * </dl><dl><dt><b>Preconditions:</b></dt><dd>
 15.1794 +     * <ul><li><code>string != null</code>
 15.1795 +     *     <li><code>end &lt;= string.length()</code>
 15.1796 +     *     <li><code>offset &lt; end</code>
 15.1797 +     *     <li><code>offset &gt;= 0</code>
 15.1798 +     * </ul></dd></dl>
 15.1799 +     *
 15.1800 +     * <dl><dt><b>Postconditions:</b></dt><dd>
 15.1801 +     * <ul><li>the state of the receiver is updated to reflect the XML element
 15.1802 +     *         parsed from the reader
 15.1803 +     * </ul></dd></dl><dl>
 15.1804 +     *
 15.1805 +     * @throws nanoxml.XMLParseException
 15.1806 +     *     If an error occured while parsing the string.
 15.1807 +     */
 15.1808 +    public void parseString(String string,
 15.1809 +                            int    offset,
 15.1810 +                            int    end)
 15.1811 +        throws XMLParseException
 15.1812 +    {
 15.1813 +        this.parseString(string.substring(offset, end));
 15.1814 +    }
 15.1815 +
 15.1816 +
 15.1817 +    /**
 15.1818 +     * Reads one XML element from a String and parses it.
 15.1819 +     *
 15.1820 +     * @param reader
 15.1821 +     *     The reader from which to retrieve the XML data.
 15.1822 +     * @param offset
 15.1823 +     *     The first character in <code>string</code> to scan.
 15.1824 +     * @param end
 15.1825 +     *     The character where to stop scanning.
 15.1826 +     *     This character is not scanned.
 15.1827 +     * @param startingLineNr
 15.1828 +     *     The line number of the first line in the data.
 15.1829 +     *
 15.1830 +     * </dl><dl><dt><b>Preconditions:</b></dt><dd>
 15.1831 +     * <ul><li><code>string != null</code>
 15.1832 +     *     <li><code>end &lt;= string.length()</code>
 15.1833 +     *     <li><code>offset &lt; end</code>
 15.1834 +     *     <li><code>offset &gt;= 0</code>
 15.1835 +     * </ul></dd></dl>
 15.1836 +     *
 15.1837 +     * <dl><dt><b>Postconditions:</b></dt><dd>
 15.1838 +     * <ul><li>the state of the receiver is updated to reflect the XML element
 15.1839 +     *         parsed from the reader
 15.1840 +     * </ul></dd></dl><dl>
 15.1841 +     *
 15.1842 +     * @throws nanoxml.XMLParseException
 15.1843 +     *     If an error occured while parsing the string.
 15.1844 +     */
 15.1845 +    public void parseString(String string,
 15.1846 +                            int    offset,
 15.1847 +                            int    end,
 15.1848 +                            int    startingLineNr)
 15.1849 +        throws XMLParseException
 15.1850 +    {
 15.1851 +        string = string.substring(offset, end);
 15.1852 +        try {
 15.1853 +            this.parseFromReader(new StringReader(string), startingLineNr);
 15.1854 +        } catch (IOException e) {
 15.1855 +            // Java exception handling suxx
 15.1856 +        }
 15.1857 +    }
 15.1858 +
 15.1859 +
 15.1860 +    /**
 15.1861 +     * Reads one XML element from a char array and parses it.
 15.1862 +     *
 15.1863 +     * @param reader
 15.1864 +     *     The reader from which to retrieve the XML data.
 15.1865 +     * @param offset
 15.1866 +     *     The first character in <code>string</code> to scan.
 15.1867 +     * @param end
 15.1868 +     *     The character where to stop scanning.
 15.1869 +     *     This character is not scanned.
 15.1870 +     *
 15.1871 +     * </dl><dl><dt><b>Preconditions:</b></dt><dd>
 15.1872 +     * <ul><li><code>input != null</code>
 15.1873 +     *     <li><code>end &lt;= input.length</code>
 15.1874 +     *     <li><code>offset &lt; end</code>
 15.1875 +     *     <li><code>offset &gt;= 0</code>
 15.1876 +     * </ul></dd></dl>
 15.1877 +     *
 15.1878 +     * <dl><dt><b>Postconditions:</b></dt><dd>
 15.1879 +     * <ul><li>the state of the receiver is updated to reflect the XML element
 15.1880 +     *         parsed from the reader
 15.1881 +     * </ul></dd></dl><dl>
 15.1882 +     *
 15.1883 +     * @throws nanoxml.XMLParseException
 15.1884 +     *     If an error occured while parsing the string.
 15.1885 +     */
 15.1886 +    public void parseCharArray(char[] input,
 15.1887 +                               int    offset,
 15.1888 +                               int    end)
 15.1889 +        throws XMLParseException
 15.1890 +    {
 15.1891 +        this.parseCharArray(input, offset, end, /*startingLineNr*/ 1);
 15.1892 +    }
 15.1893 +
 15.1894 +
 15.1895 +    /**
 15.1896 +     * Reads one XML element from a char array and parses it.
 15.1897 +     *
 15.1898 +     * @param reader
 15.1899 +     *     The reader from which to retrieve the XML data.
 15.1900 +     * @param offset
 15.1901 +     *     The first character in <code>string</code> to scan.
 15.1902 +     * @param end
 15.1903 +     *     The character where to stop scanning.
 15.1904 +     *     This character is not scanned.
 15.1905 +     * @param startingLineNr
 15.1906 +     *     The line number of the first line in the data.
 15.1907 +     *
 15.1908 +     * </dl><dl><dt><b>Preconditions:</b></dt><dd>
 15.1909 +     * <ul><li><code>input != null</code>
 15.1910 +     *     <li><code>end &lt;= input.length</code>
 15.1911 +     *     <li><code>offset &lt; end</code>
 15.1912 +     *     <li><code>offset &gt;= 0</code>
 15.1913 +     * </ul></dd></dl>
 15.1914 +     *
 15.1915 +     * <dl><dt><b>Postconditions:</b></dt><dd>
 15.1916 +     * <ul><li>the state of the receiver is updated to reflect the XML element
 15.1917 +     *         parsed from the reader
 15.1918 +     * </ul></dd></dl><dl>
 15.1919 +     *
 15.1920 +     * @throws nanoxml.XMLParseException
 15.1921 +     *     If an error occured while parsing the string.
 15.1922 +     */
 15.1923 +    public void parseCharArray(char[] input,
 15.1924 +                               int    offset,
 15.1925 +                               int    end,
 15.1926 +                               int    startingLineNr)
 15.1927 +        throws XMLParseException
 15.1928 +    {
 15.1929 +        try {
 15.1930 +            Reader reader = new CharArrayReader(input, offset, end);
 15.1931 +            this.parseFromReader(reader, startingLineNr);
 15.1932 +        } catch (IOException e) {
 15.1933 +            // This exception will never happen.
 15.1934 +        }
 15.1935 +    }
 15.1936 +
 15.1937 +
 15.1938 +    /**
 15.1939 +     * Removes a child element.
 15.1940 +     *
 15.1941 +     * @param child
 15.1942 +     *     The child element to remove.
 15.1943 +     *
 15.1944 +     * </dl><dl><dt><b>Preconditions:</b></dt><dd>
 15.1945 +     * <ul><li><code>child != null</code>
 15.1946 +     *     <li><code>child</code> is a child element of the receiver
 15.1947 +     * </ul></dd></dl>
 15.1948 +     *
 15.1949 +     * <dl><dt><b>Postconditions:</b></dt><dd>
 15.1950 +     * <ul><li>countChildren() => old.countChildren() - 1
 15.1951 +     *     <li>enumerateChildren() => old.enumerateChildren() - child
 15.1952 +     *     <li>getChildren() => old.enumerateChildren() - child
 15.1953 +     * </ul></dd></dl><dl>
 15.1954 +     *
 15.1955 +     * @see nanoxml.XMLElement#addChild(nanoxml.XMLElement)
 15.1956 +     *         addChild(XMLElement)
 15.1957 +     * @see nanoxml.XMLElement#countChildren()
 15.1958 +     * @see nanoxml.XMLElement#enumerateChildren()
 15.1959 +     * @see nanoxml.XMLElement#getChildren()
 15.1960 +     */
 15.1961 +    public void removeChild(XMLElement child)
 15.1962 +    {
 15.1963 +        this.children.removeElement(child);
 15.1964 +    }
 15.1965 +
 15.1966 +
 15.1967 +    /**
 15.1968 +     * Removes an attribute.
 15.1969 +     *
 15.1970 +     * @param name
 15.1971 +     *     The name of the attribute.
 15.1972 +     *
 15.1973 +     * </dl><dl><dt><b>Preconditions:</b></dt><dd>
 15.1974 +     * <ul><li><code>name != null</code>
 15.1975 +     *     <li><code>name</code> is a valid XML identifier
 15.1976 +     * </ul></dd></dl>
 15.1977 +     *
 15.1978 +     * <dl><dt><b>Postconditions:</b></dt><dd>
 15.1979 +     * <ul><li>enumerateAttributeNames()
 15.1980 +     *         => old.enumerateAttributeNames() - name
 15.1981 +     *     <li>getAttribute(name) => <code>null</code>
 15.1982 +     * </ul></dd></dl><dl>
 15.1983 +     *
 15.1984 +     * @see nanoxml.XMLElement#enumerateAttributeNames()
 15.1985 +     * @see nanoxml.XMLElement#setDoubleAttribute(java.lang.String, double)
 15.1986 +     *         setDoubleAttribute(String, double)
 15.1987 +     * @see nanoxml.XMLElement#setIntAttribute(java.lang.String, int)
 15.1988 +     *         setIntAttribute(String, int)
 15.1989 +     * @see nanoxml.XMLElement#setAttribute(java.lang.String, java.lang.Object)
 15.1990 +     *         setAttribute(String, Object)
 15.1991 +     * @see nanoxml.XMLElement#getAttribute(java.lang.String)
 15.1992 +     *         getAttribute(String)
 15.1993 +     * @see nanoxml.XMLElement#getAttribute(java.lang.String, java.lang.Object)
 15.1994 +     *         getAttribute(String, Object)
 15.1995 +     * @see nanoxml.XMLElement#getAttribute(java.lang.String,
 15.1996 +     *                                      java.util.Hashtable,
 15.1997 +     *                                      java.lang.String, boolean)
 15.1998 +     *         getAttribute(String, Hashtable, String, boolean)
 15.1999 +     * @see nanoxml.XMLElement#getStringAttribute(java.lang.String)
 15.2000 +     *         getStringAttribute(String)
 15.2001 +     * @see nanoxml.XMLElement#getStringAttribute(java.lang.String,
 15.2002 +     *                                            java.lang.String)
 15.2003 +     *         getStringAttribute(String, String)
 15.2004 +     * @see nanoxml.XMLElement#getStringAttribute(java.lang.String,
 15.2005 +     *                                            java.util.Hashtable,
 15.2006 +     *                                            java.lang.String, boolean)
 15.2007 +     *         getStringAttribute(String, Hashtable, String, boolean)
 15.2008 +     * @see nanoxml.XMLElement#getIntAttribute(java.lang.String)
 15.2009 +     *         getIntAttribute(String)
 15.2010 +     * @see nanoxml.XMLElement#getIntAttribute(java.lang.String, int)
 15.2011 +     *         getIntAttribute(String, int)
 15.2012 +     * @see nanoxml.XMLElement#getIntAttribute(java.lang.String,
 15.2013 +     *                                         java.util.Hashtable,
 15.2014 +     *                                         java.lang.String, boolean)
 15.2015 +     *         getIntAttribute(String, Hashtable, String, boolean)
 15.2016 +     * @see nanoxml.XMLElement#getDoubleAttribute(java.lang.String)
 15.2017 +     *         getDoubleAttribute(String)
 15.2018 +     * @see nanoxml.XMLElement#getDoubleAttribute(java.lang.String, double)
 15.2019 +     *         getDoubleAttribute(String, double)
 15.2020 +     * @see nanoxml.XMLElement#getDoubleAttribute(java.lang.String,
 15.2021 +     *                                            java.util.Hashtable,
 15.2022 +     *                                            java.lang.String, boolean)
 15.2023 +     *         getDoubleAttribute(String, Hashtable, String, boolean)
 15.2024 +     * @see nanoxml.XMLElement#getBooleanAttribute(java.lang.String,
 15.2025 +     *                                             java.lang.String,
 15.2026 +     *                                             java.lang.String, boolean)
 15.2027 +     *         getBooleanAttribute(String, String, String, boolean)
 15.2028 +     */
 15.2029 +    public void removeAttribute(String name)
 15.2030 +    {
 15.2031 +        if (this.ignoreCase) {
 15.2032 +            name = name.toUpperCase();
 15.2033 +        }
 15.2034 +        this.attributes.remove(name);
 15.2035 +    }
 15.2036 +
 15.2037 +
 15.2038 +    /**
 15.2039 +     * Removes an attribute.
 15.2040 +     *
 15.2041 +     * @param name
 15.2042 +     *     The name of the attribute.
 15.2043 +     *
 15.2044 +     * @deprecated Use {@link #removeAttribute(java.lang.String)
 15.2045 +     *             removeAttribute} instead.
 15.2046 +     */
 15.2047 +    public void removeProperty(String name)
 15.2048 +    {
 15.2049 +        this.removeAttribute(name);
 15.2050 +    }
 15.2051 +
 15.2052 +
 15.2053 +    /**
 15.2054 +     * Removes an attribute.
 15.2055 +     *
 15.2056 +     * @param name
 15.2057 +     *     The name of the attribute.
 15.2058 +     *
 15.2059 +     * @deprecated Use {@link #removeAttribute(java.lang.String)
 15.2060 +     *             removeAttribute} instead.
 15.2061 +     */
 15.2062 +    public void removeChild(String name)
 15.2063 +    {
 15.2064 +        this.removeAttribute(name);
 15.2065 +    }
 15.2066 +
 15.2067 +
 15.2068 +    /**
 15.2069 +     * Creates a new similar XML element.
 15.2070 +     * <P>
 15.2071 +     * You should override this method when subclassing XMLElement.
 15.2072 +     */
 15.2073 +    protected XMLElement createAnotherElement()
 15.2074 +    {
 15.2075 +        return new XMLElement(this.entities,
 15.2076 +                              this.ignoreWhitespace,
 15.2077 +                              false,
 15.2078 +                              this.ignoreCase);
 15.2079 +    }
 15.2080 +
 15.2081 +
 15.2082 +    /**
 15.2083 +     * Changes the content string.
 15.2084 +     *
 15.2085 +     * @param content
 15.2086 +     *     The new content string.
 15.2087 +     */
 15.2088 +    public void setContent(String content)
 15.2089 +    {
 15.2090 +        this.contents = content;
 15.2091 +    }
 15.2092 +
 15.2093 +
 15.2094 +    /**
 15.2095 +     * Changes the name of the element.
 15.2096 +     *
 15.2097 +     * @param name
 15.2098 +     *     The new name.
 15.2099 +     *
 15.2100 +     * @deprecated Use {@link #setName(java.lang.String) setName} instead.
 15.2101 +     */
 15.2102 +    public void setTagName(String name)
 15.2103 +    {
 15.2104 +        this.setName(name);
 15.2105 +    }
 15.2106 +
 15.2107 +
 15.2108 +    /**
 15.2109 +     * Changes the name of the element.
 15.2110 +     *
 15.2111 +     * @param name
 15.2112 +     *     The new name.
 15.2113 +     *
 15.2114 +     * </dl><dl><dt><b>Preconditions:</b></dt><dd>
 15.2115 +     * <ul><li><code>name != null</code>
 15.2116 +     *     <li><code>name</code> is a valid XML identifier
 15.2117 +     * </ul></dd></dl>
 15.2118 +     *
 15.2119 +     * @see nanoxml.XMLElement#getName()
 15.2120 +     */
 15.2121 +    public void setName(String name)
 15.2122 +    {
 15.2123 +        this.name = name;
 15.2124 +    }
 15.2125 +
 15.2126 +
 15.2127 +    /**
 15.2128 +     * Writes the XML element to a string.
 15.2129 +     *
 15.2130 +     * @see nanoxml.XMLElement#write(java.io.Writer) write(Writer)
 15.2131 +     */
 15.2132 +    public String toString()
 15.2133 +    {
 15.2134 +        try {
 15.2135 +            ByteArrayOutputStream out = new ByteArrayOutputStream();
 15.2136 +            OutputStreamWriter writer = new OutputStreamWriter(out);
 15.2137 +            this.write(writer);
 15.2138 +            writer.flush();
 15.2139 +            return new String(out.toByteArray());
 15.2140 +        } catch (IOException e) {
 15.2141 +            // Java exception handling suxx
 15.2142 +            return super.toString();
 15.2143 +        }
 15.2144 +    }
 15.2145 +
 15.2146 +
 15.2147 +    /**
 15.2148 +     * Writes the XML element to a writer.
 15.2149 +     *
 15.2150 +     * @param writer
 15.2151 +     *     The writer to write the XML data to.
 15.2152 +     *
 15.2153 +     * </dl><dl><dt><b>Preconditions:</b></dt><dd>
 15.2154 +     * <ul><li><code>writer != null</code>
 15.2155 +     *     <li><code>writer</code> is not closed
 15.2156 +     * </ul></dd></dl>
 15.2157 +     *
 15.2158 +     * @throws java.io.IOException
 15.2159 +     *      If the data could not be written to the writer.
 15.2160 +     *
 15.2161 +     * @see nanoxml.XMLElement#toString()
 15.2162 +     */
 15.2163 +    public void write(Writer writer)
 15.2164 +        throws IOException
 15.2165 +    {
 15.2166 +        if (this.name == null) {
 15.2167 +            this.writeEncoded(writer, this.contents);
 15.2168 +            return;
 15.2169 +        }
 15.2170 +        writer.write('<');
 15.2171 +        writer.write(this.name);
 15.2172 +        if (! this.attributes.isEmpty()) {
 15.2173 +            Enumeration enumV = this.attributes.keys();
 15.2174 +            while (enumV.hasMoreElements()) {
 15.2175 +                writer.write(' ');
 15.2176 +                String key = (String) enumV.nextElement();
 15.2177 +                String value = (String) this.attributes.get(key);
 15.2178 +                writer.write(key);
 15.2179 +                writer.write('='); writer.write('"');
 15.2180 +                this.writeEncoded(writer, value);
 15.2181 +                writer.write('"');
 15.2182 +            }
 15.2183 +        }
 15.2184 +        if ((this.contents != null) && (this.contents.length() > 0)) {
 15.2185 +            writer.write('>');
 15.2186 +            this.writeEncoded(writer, this.contents);
 15.2187 +            writer.write('<'); writer.write('/');
 15.2188 +            writer.write(this.name);
 15.2189 +            writer.write('>');
 15.2190 +        } else if (this.children.isEmpty()) {
 15.2191 +            writer.write('/'); writer.write('>');
 15.2192 +        } else {
 15.2193 +            writer.write('>');
 15.2194 +            Enumeration enumV = this.enumerateChildren();
 15.2195 +            while (enumV.hasMoreElements()) {
 15.2196 +                XMLElement child = (XMLElement) enumV.nextElement();
 15.2197 +                child.write(writer);
 15.2198 +            }
 15.2199 +            writer.write('<'); writer.write('/');
 15.2200 +            writer.write(this.name);
 15.2201 +            writer.write('>');
 15.2202 +        }
 15.2203 +    }
 15.2204 +
 15.2205 +
 15.2206 +    /**
 15.2207 +     * Writes a string encoded to a writer.
 15.2208 +     *
 15.2209 +     * @param writer
 15.2210 +     *     The writer to write the XML data to.
 15.2211 +     * @param str
 15.2212 +     *     The string to write encoded.
 15.2213 +     *
 15.2214 +     * </dl><dl><dt><b>Preconditions:</b></dt><dd>
 15.2215 +     * <ul><li><code>writer != null</code>
 15.2216 +     *     <li><code>writer</code> is not closed
 15.2217 +     *     <li><code>str != null</code>
 15.2218 +     * </ul></dd></dl>
 15.2219 +     */
 15.2220 +    protected void writeEncoded(Writer writer,
 15.2221 +                                String str)
 15.2222 +        throws IOException
 15.2223 +    {
 15.2224 +        for (int i = 0; i < str.length(); i += 1) {
 15.2225 +            char ch = str.charAt(i);
 15.2226 +            switch (ch) {
 15.2227 +                case '<':
 15.2228 +                    writer.write('&'); writer.write('l'); writer.write('t');
 15.2229 +                    writer.write(';');
 15.2230 +                    break;
 15.2231 +                case '>':
 15.2232 +                    writer.write('&'); writer.write('g'); writer.write('t');
 15.2233 +                    writer.write(';');
 15.2234 +                    break;
 15.2235 +                case '&':
 15.2236 +                    writer.write('&'); writer.write('a'); writer.write('m');
 15.2237 +                    writer.write('p'); writer.write(';');
 15.2238 +                    break;
 15.2239 +                case '"':
 15.2240 +                    writer.write('&'); writer.write('q'); writer.write('u');
 15.2241 +                    writer.write('o'); writer.write('t'); writer.write(';');
 15.2242 +                    break;
 15.2243 +                case '\'':
 15.2244 +                    writer.write('&'); writer.write('a'); writer.write('p');
 15.2245 +                    writer.write('o'); writer.write('s'); writer.write(';');
 15.2246 +                    break;
 15.2247 +                default:
 15.2248 +                    int unicode = (int) ch;
 15.2249 +                    if ((unicode < 32) || (unicode > 126)) {
 15.2250 +                        writer.write('&'); writer.write('#');
 15.2251 +                        writer.write('x');
 15.2252 +                        writer.write(Integer.toString(unicode, 16));
 15.2253 +                        writer.write(';');
 15.2254 +                    } else {
 15.2255 +                        writer.write(ch);
 15.2256 +                    }
 15.2257 +            }
 15.2258 +        }
 15.2259 +    }
 15.2260 +
 15.2261 +
 15.2262 +    /**
 15.2263 +     * Scans an identifier from the current reader.
 15.2264 +     * The scanned identifier is appended to <code>result</code>.
 15.2265 +     *
 15.2266 +     * @param result
 15.2267 +     *     The buffer in which the scanned identifier will be put.
 15.2268 +     *
 15.2269 +     * </dl><dl><dt><b>Preconditions:</b></dt><dd>
 15.2270 +     * <ul><li><code>result != null</code>
 15.2271 +     *     <li>The next character read from the reader is a valid first
 15.2272 +     *         character of an XML identifier.
 15.2273 +     * </ul></dd></dl>
 15.2274 +     *
 15.2275 +     * <dl><dt><b>Postconditions:</b></dt><dd>
 15.2276 +     * <ul><li>The next character read from the reader won't be an identifier
 15.2277 +     *         character.
 15.2278 +     * </ul></dd></dl><dl>
 15.2279 +     */
 15.2280 +    protected void scanIdentifier(StringBuffer result)
 15.2281 +        throws IOException
 15.2282 +    {
 15.2283 +        for (;;) {
 15.2284 +            char ch = this.readChar();
 15.2285 +            if (((ch < 'A') || (ch > 'Z')) && ((ch < 'a') || (ch > 'z'))
 15.2286 +                && ((ch < '0') || (ch > '9')) && (ch != '_') && (ch != '.')
 15.2287 +                && (ch != ':') && (ch != '-') && (ch <= '\u007E')) {
 15.2288 +                this.unreadChar(ch);
 15.2289 +                return;
 15.2290 +            }
 15.2291 +            result.append(ch);
 15.2292 +        }
 15.2293 +    }
 15.2294 +
 15.2295 +
 15.2296 +    /**
 15.2297 +     * This method scans an identifier from the current reader.
 15.2298 +     *
 15.2299 +     * @return the next character following the whitespace.
 15.2300 +     */
 15.2301 +    protected char scanWhitespace()
 15.2302 +        throws IOException
 15.2303 +    {
 15.2304 +        for (;;) {
 15.2305 +            char ch = this.readChar();
 15.2306 +            switch (ch) {
 15.2307 +                case ' ':
 15.2308 +                case '\t':
 15.2309 +                case '\n':
 15.2310 +                case '\r':
 15.2311 +                    break;
 15.2312 +                default:
 15.2313 +                    return ch;
 15.2314 +            }
 15.2315 +        }
 15.2316 +    }
 15.2317 +
 15.2318 +
 15.2319 +    /**
 15.2320 +     * This method scans an identifier from the current reader.
 15.2321 +     * The scanned whitespace is appended to <code>result</code>.
 15.2322 +     *
 15.2323 +     * @return the next character following the whitespace.
 15.2324 +     *
 15.2325 +     * </dl><dl><dt><b>Preconditions:</b></dt><dd>
 15.2326 +     * <ul><li><code>result != null</code>
 15.2327 +     * </ul></dd></dl>
 15.2328 +     */
 15.2329 +    protected char scanWhitespace(StringBuffer result)
 15.2330 +        throws IOException
 15.2331 +    {
 15.2332 +        for (;;) {
 15.2333 +            char ch = this.readChar();
 15.2334 +            switch (ch) {
 15.2335 +                case ' ':
 15.2336 +                case '\t':
 15.2337 +                case '\n':
 15.2338 +                    result.append(ch);
 15.2339 +                case '\r':
 15.2340 +                    break;
 15.2341 +                default:
 15.2342 +                    return ch;
 15.2343 +            }
 15.2344 +        }
 15.2345 +    }
 15.2346 +
 15.2347 +
 15.2348 +    /**
 15.2349 +     * This method scans a delimited string from the current reader.
 15.2350 +     * The scanned string without delimiters is appended to
 15.2351 +     * <code>string</code>.
 15.2352 +     *
 15.2353 +     * </dl><dl><dt><b>Preconditions:</b></dt><dd>
 15.2354 +     * <ul><li><code>string != null</code>
 15.2355 +     *     <li>the next char read is the string delimiter
 15.2356 +     * </ul></dd></dl>
 15.2357 +     */
 15.2358 +    protected void scanString(StringBuffer string)
 15.2359 +        throws IOException
 15.2360 +    {
 15.2361 +        char delimiter = this.readChar();
 15.2362 +        if ((delimiter != '\'') && (delimiter != '"')) {
 15.2363 +            throw this.expectedInput("' or \"");
 15.2364 +        }
 15.2365 +        for (;;) {
 15.2366 +            char ch = this.readChar();
 15.2367 +            if (ch == delimiter) {
 15.2368 +                return;
 15.2369 +            } else if (ch == '&') {
 15.2370 +                this.resolveEntity(string);
 15.2371 +            } else {
 15.2372 +                string.append(ch);
 15.2373 +            }
 15.2374 +        }
 15.2375 +    }
 15.2376 +
 15.2377 +
 15.2378 +    /**
 15.2379 +     * Scans a #PCDATA element. CDATA sections and entities are resolved.
 15.2380 +     * The next &lt; char is skipped.
 15.2381 +     * The scanned data is appended to <code>data</code>.
 15.2382 +     *
 15.2383 +     * </dl><dl><dt><b>Preconditions:</b></dt><dd>
 15.2384 +     * <ul><li><code>data != null</code>
 15.2385 +     * </ul></dd></dl>
 15.2386 +     */
 15.2387 +    protected void scanPCData(StringBuffer data)
 15.2388 +        throws IOException
 15.2389 +    {
 15.2390 +        for (;;) {
 15.2391 +            char ch = this.readChar();
 15.2392 +            if (ch == '<') {
 15.2393 +                ch = this.readChar();
 15.2394 +                if (ch == '!') {
 15.2395 +                    this.checkCDATA(data);
 15.2396 +                } else {
 15.2397 +                    this.unreadChar(ch);
 15.2398 +                    return;
 15.2399 +                }
 15.2400 +            } else if (ch == '&') {
 15.2401 +                this.resolveEntity(data);
 15.2402 +            } else {
 15.2403 +                data.append(ch);
 15.2404 +            }
 15.2405 +        }
 15.2406 +    }
 15.2407 +
 15.2408 +
 15.2409 +    /**
 15.2410 +     * Scans a special tag and if the tag is a CDATA section, append its
 15.2411 +     * content to <code>buf</code>.
 15.2412 +     *
 15.2413 +     * </dl><dl><dt><b>Preconditions:</b></dt><dd>
 15.2414 +     * <ul><li><code>buf != null</code>
 15.2415 +     *     <li>The first &lt; has already been read.
 15.2416 +     * </ul></dd></dl>
 15.2417 +     */
 15.2418 +    protected boolean checkCDATA(StringBuffer buf)
 15.2419 +        throws IOException
 15.2420 +    {
 15.2421 +        char ch = this.readChar();
 15.2422 +        if (ch != '[') {
 15.2423 +            this.unreadChar(ch);
 15.2424 +            this.skipSpecialTag(0);
 15.2425 +            return false;
 15.2426 +        } else if (! this.checkLiteral("CDATA[")) {
 15.2427 +            this.skipSpecialTag(1); // one [ has already been read
 15.2428 +            return false;
 15.2429 +        } else {
 15.2430 +            int delimiterCharsSkipped = 0;
 15.2431 +            while (delimiterCharsSkipped < 3) {
 15.2432 +                ch = this.readChar();
 15.2433 +                switch (ch) {
 15.2434 +                    case ']':
 15.2435 +                        if (delimiterCharsSkipped < 2) {
 15.2436 +                            delimiterCharsSkipped += 1;
 15.2437 +                        } else {
 15.2438 +                            buf.append(']');
 15.2439 +                            buf.append(']');
 15.2440 +                            delimiterCharsSkipped = 0;
 15.2441 +                        }
 15.2442 +                        break;
 15.2443 +                    case '>':
 15.2444 +                        if (delimiterCharsSkipped < 2) {
 15.2445 +                            for (int i = 0; i < delimiterCharsSkipped; i++) {
 15.2446 +                                buf.append(']');
 15.2447 +                            }
 15.2448 +                            delimiterCharsSkipped = 0;
 15.2449 +                            buf.append('>');
 15.2450 +                        } else {
 15.2451 +                            delimiterCharsSkipped = 3;
 15.2452 +                        }
 15.2453 +                        break;
 15.2454 +                    default:
 15.2455 +                        for (int i = 0; i < delimiterCharsSkipped; i += 1) {
 15.2456 +                            buf.append(']');
 15.2457 +                        }
 15.2458 +                        buf.append(ch);
 15.2459 +                        delimiterCharsSkipped = 0;
 15.2460 +                }
 15.2461 +            }
 15.2462 +            return true;
 15.2463 +        }
 15.2464 +    }
 15.2465 +
 15.2466 +
 15.2467 +    /**
 15.2468 +     * Skips a comment.
 15.2469 +     *
 15.2470 +     * </dl><dl><dt><b>Preconditions:</b></dt><dd>
 15.2471 +     * <ul><li>The first &lt;!-- has already been read.
 15.2472 +     * </ul></dd></dl>
 15.2473 +     */
 15.2474 +    protected void skipComment()
 15.2475 +        throws IOException
 15.2476 +    {
 15.2477 +        int dashesToRead = 2;
 15.2478 +        while (dashesToRead > 0) {
 15.2479 +            char ch = this.readChar();
 15.2480 +            if (ch == '-') {
 15.2481 +                dashesToRead -= 1;
 15.2482 +            } else {
 15.2483 +                dashesToRead = 2;
 15.2484 +            }
 15.2485 +        }
 15.2486 +        if (this.readChar() != '>') {
 15.2487 +            throw this.expectedInput(">");
 15.2488 +        }
 15.2489 +    }
 15.2490 +
 15.2491 +
 15.2492 +    /**
 15.2493 +     * Skips a special tag or comment.
 15.2494 +     *
 15.2495 +     * @param bracketLevel The number of open square brackets ([) that have
 15.2496 +     *                     already been read.
 15.2497 +     *
 15.2498 +     * </dl><dl><dt><b>Preconditions:</b></dt><dd>
 15.2499 +     * <ul><li>The first &lt;! has already been read.
 15.2500 +     *     <li><code>bracketLevel >= 0</code>
 15.2501 +     * </ul></dd></dl>
 15.2502 +     */
 15.2503 +    protected void skipSpecialTag(int bracketLevel)
 15.2504 +        throws IOException
 15.2505 +    {
 15.2506 +        int tagLevel = 1; // <
 15.2507 +        char stringDelimiter = '\0';
 15.2508 +        if (bracketLevel == 0) {
 15.2509 +            char ch = this.readChar();
 15.2510 +            if (ch == '[') {
 15.2511 +                bracketLevel += 1;
 15.2512 +            } else if (ch == '-') {
 15.2513 +                ch = this.readChar();
 15.2514 +                if (ch == '[') {
 15.2515 +                    bracketLevel += 1;
 15.2516 +                } else if (ch == ']') {
 15.2517 +                    bracketLevel -= 1;
 15.2518 +                } else if (ch == '-') {
 15.2519 +                    this.skipComment();
 15.2520 +                    return;
 15.2521 +                }
 15.2522 +            }
 15.2523 +        }
 15.2524 +        while (tagLevel > 0) {
 15.2525 +            char ch = this.readChar();
 15.2526 +            if (stringDelimiter == '\0') {
 15.2527 +                if ((ch == '"') || (ch == '\'')) {
 15.2528 +                    stringDelimiter = ch;
 15.2529 +                } else if (bracketLevel <= 0) {
 15.2530 +                    if (ch == '<') {
 15.2531 +                        tagLevel += 1;
 15.2532 +                    } else if (ch == '>') {
 15.2533 +                        tagLevel -= 1;
 15.2534 +                    }
 15.2535 +                }
 15.2536 +                if (ch == '[') {
 15.2537 +                    bracketLevel += 1;
 15.2538 +                } else if (ch == ']') {
 15.2539 +                    bracketLevel -= 1;
 15.2540 +                }
 15.2541 +            } else {
 15.2542 +                if (ch == stringDelimiter) {
 15.2543 +                    stringDelimiter = '\0';
 15.2544 +                }
 15.2545 +            }
 15.2546 +        }
 15.2547 +    }
 15.2548 +
 15.2549 +
 15.2550 +    /**
 15.2551 +     * Scans the data for literal text.
 15.2552 +     * Scanning stops when a character does not match or after the complete
 15.2553 +     * text has been checked, whichever comes first.
 15.2554 +     *
 15.2555 +     * @param literal the literal to check.
 15.2556 +     *
 15.2557 +     * </dl><dl><dt><b>Preconditions:</b></dt><dd>
 15.2558 +     * <ul><li><code>literal != null</code>
 15.2559 +     * </ul></dd></dl>
 15.2560 +     */
 15.2561 +    protected boolean checkLiteral(String literal)
 15.2562 +        throws IOException
 15.2563 +    {
 15.2564 +        int length = literal.length();
 15.2565 +        for (int i = 0; i < length; i += 1) {
 15.2566 +            if (this.readChar() != literal.charAt(i)) {
 15.2567 +                return false;
 15.2568 +            }
 15.2569 +        }
 15.2570 +        return true;
 15.2571 +    }
 15.2572 +
 15.2573 +
 15.2574 +    /**
 15.2575 +     * Reads a character from a reader.
 15.2576 +     */
 15.2577 +    protected char readChar()
 15.2578 +        throws IOException
 15.2579 +    {
 15.2580 +        if (this.charReadTooMuch != '\0') {
 15.2581 +            char ch = this.charReadTooMuch;
 15.2582 +            this.charReadTooMuch = '\0';
 15.2583 +            return ch;
 15.2584 +        } else {
 15.2585 +            int i = this.reader.read();
 15.2586 +            if (i < 0) {
 15.2587 +                throw this.unexpectedEndOfData();
 15.2588 +            } else if (i == 10) {
 15.2589 +                this.parserLineNr += 1;
 15.2590 +                return '\n';
 15.2591 +            } else {
 15.2592 +                return (char) i;
 15.2593 +            }
 15.2594 +        }
 15.2595 +    }
 15.2596 +
 15.2597 +
 15.2598 +    /**
 15.2599 +     * Scans an XML element.
 15.2600 +     *
 15.2601 +     * @param elt The element that will contain the result.
 15.2602 +     *
 15.2603 +     * </dl><dl><dt><b>Preconditions:</b></dt><dd>
 15.2604 +     * <ul><li>The first &lt; has already been read.
 15.2605 +     *     <li><code>elt != null</code>
 15.2606 +     * </ul></dd></dl>
 15.2607 +     */
 15.2608 +    protected void scanElement(XMLElement elt)
 15.2609 +        throws IOException
 15.2610 +    {
 15.2611 +        StringBuffer buf = new StringBuffer();
 15.2612 +        this.scanIdentifier(buf);
 15.2613 +        String name = buf.toString();
 15.2614 +        elt.setName(name);
 15.2615 +        char ch = this.scanWhitespace();
 15.2616 +        while ((ch != '>') && (ch != '/')) {
 15.2617 +            buf.setLength(0);
 15.2618 +            this.unreadChar(ch);
 15.2619 +            this.scanIdentifier(buf);
 15.2620 +            String key = buf.toString();
 15.2621 +            ch = this.scanWhitespace();
 15.2622 +            if (ch != '=') {
 15.2623 +                throw this.expectedInput("=");
 15.2624 +            }
 15.2625 +            this.unreadChar(this.scanWhitespace());
 15.2626 +            buf.setLength(0);
 15.2627 +            this.scanString(buf);
 15.2628 +            elt.setAttribute(key, buf);
 15.2629 +            ch = this.scanWhitespace();
 15.2630 +        }
 15.2631 +        if (ch == '/') {
 15.2632 +            ch = this.readChar();
 15.2633 +            if (ch != '>') {
 15.2634 +                throw this.expectedInput(">");
 15.2635 +            }
 15.2636 +            return;
 15.2637 +        }
 15.2638 +        buf.setLength(0);
 15.2639 +        ch = this.scanWhitespace(buf);
 15.2640 +        if (ch != '<') {
 15.2641 +            this.unreadChar(ch);
 15.2642 +            this.scanPCData(buf);
 15.2643 +        } else {
 15.2644 +            for (;;) {
 15.2645 +                ch = this.readChar();
 15.2646 +                if (ch == '!') {
 15.2647 +                    if (this.checkCDATA(buf)) {
 15.2648 +                        this.scanPCData(buf);
 15.2649 +                        break;
 15.2650 +                    } else {
 15.2651 +                        ch = this.scanWhitespace(buf);
 15.2652 +                        if (ch != '<') {
 15.2653 +                            this.unreadChar(ch);
 15.2654 +                            this.scanPCData(buf);
 15.2655 +                            break;
 15.2656 +                        }
 15.2657 +                    }
 15.2658 +                } else {
 15.2659 +                    if ((ch != '/') || this.ignoreWhitespace) {
 15.2660 +                        buf.setLength(0);
 15.2661 +                    }
 15.2662 +                    if (ch == '/') {
 15.2663 +                        this.unreadChar(ch);
 15.2664 +                    }
 15.2665 +                    break;
 15.2666 +                }
 15.2667 +            }
 15.2668 +        }
 15.2669 +        if (buf.length() == 0) {
 15.2670 +            while (ch != '/') {
 15.2671 +                if (ch == '!') {
 15.2672 +                    ch = this.readChar();
 15.2673 +                    if (ch != '-') {
 15.2674 +                        throw this.expectedInput("Comment or Element");
 15.2675 +                    }
 15.2676 +                    ch = this.readChar();
 15.2677 +                    if (ch != '-') {
 15.2678 +                        throw this.expectedInput("Comment or Element");
 15.2679 +                    }
 15.2680 +                    this.skipComment();
 15.2681 +                } else {
 15.2682 +                    this.unreadChar(ch);
 15.2683 +                    XMLElement child = this.createAnotherElement();
 15.2684 +                    this.scanElement(child);
 15.2685 +                    elt.addChild(child);
 15.2686 +                }
 15.2687 +                ch = this.scanWhitespace();
 15.2688 +                if (ch != '<') {
 15.2689 +                    throw this.expectedInput("<");
 15.2690 +                }
 15.2691 +                ch = this.readChar();
 15.2692 +            }
 15.2693 +            this.unreadChar(ch);
 15.2694 +        } else {
 15.2695 +            if (this.ignoreWhitespace) {
 15.2696 +                elt.setContent(buf.toString().trim());
 15.2697 +            } else {
 15.2698 +                elt.setContent(buf.toString());
 15.2699 +            }
 15.2700 +        }
 15.2701 +        ch = this.readChar();
 15.2702 +        if (ch != '/') {
 15.2703 +            throw this.expectedInput("/");
 15.2704 +        }
 15.2705 +        this.unreadChar(this.scanWhitespace());
 15.2706 +        if (! this.checkLiteral(name)) {
 15.2707 +            throw this.expectedInput(name);
 15.2708 +        }
 15.2709 +        if (this.scanWhitespace() != '>') {
 15.2710 +            throw this.expectedInput(">");
 15.2711 +        }
 15.2712 +    }
 15.2713 +
 15.2714 +
 15.2715 +    /**
 15.2716 +     * Resolves an entity. The name of the entity is read from the reader.
 15.2717 +     * The value of the entity is appended to <code>buf</code>.
 15.2718 +     *
 15.2719 +     * @param buf Where to put the entity value.
 15.2720 +     *
 15.2721 +     * </dl><dl><dt><b>Preconditions:</b></dt><dd>
 15.2722 +     * <ul><li>The first &amp; has already been read.
 15.2723 +     *     <li><code>buf != null</code>
 15.2724 +     * </ul></dd></dl>
 15.2725 +     */
 15.2726 +    protected void resolveEntity(StringBuffer buf)
 15.2727 +        throws IOException
 15.2728 +    {
 15.2729 +        char ch = '\0';
 15.2730 +        StringBuffer keyBuf = new StringBuffer();
 15.2731 +        for (;;) {
 15.2732 +            ch = this.readChar();
 15.2733 +            if (ch == ';') {
 15.2734 +                break;
 15.2735 +            }
 15.2736 +            keyBuf.append(ch);
 15.2737 +        }
 15.2738 +        String key = keyBuf.toString();
 15.2739 +        if (key.charAt(0) == '#') {
 15.2740 +            try {
 15.2741 +                if (key.charAt(1) == 'x') {
 15.2742 +                    ch = (char) Integer.parseInt(key.substring(2), 16);
 15.2743 +                } else {
 15.2744 +                    ch = (char) Integer.parseInt(key.substring(1), 10);
 15.2745 +                }
 15.2746 +            } catch (NumberFormatException e) {
 15.2747 +                throw this.unknownEntity(key);
 15.2748 +            }
 15.2749 +            buf.append(ch);
 15.2750 +        } else {
 15.2751 +            char[] value = (char[]) this.entities.get(key);
 15.2752 +            if (value == null) {
 15.2753 +                throw this.unknownEntity(key);
 15.2754 +            }
 15.2755 +            buf.append(value);
 15.2756 +        }
 15.2757 +    }
 15.2758 +
 15.2759 +
 15.2760 +    /**
 15.2761 +     * Pushes a character back to the read-back buffer.
 15.2762 +     *
 15.2763 +     * @param ch The character to push back.
 15.2764 +     *
 15.2765 +     * </dl><dl><dt><b>Preconditions:</b></dt><dd>
 15.2766 +     * <ul><li>The read-back buffer is empty.
 15.2767 +     *     <li><code>ch != '\0'</code>
 15.2768 +     * </ul></dd></dl>
 15.2769 +     */
 15.2770 +    protected void unreadChar(char ch)
 15.2771 +    {
 15.2772 +        this.charReadTooMuch = ch;
 15.2773 +    }
 15.2774 +
 15.2775 +
 15.2776 +    /**
 15.2777 +     * Creates a parse exception for when an invalid valueset is given to
 15.2778 +     * a method.
 15.2779 +     *
 15.2780 +     * @param name The name of the entity.
 15.2781 +     *
 15.2782 +     * </dl><dl><dt><b>Preconditions:</b></dt><dd>
 15.2783 +     * <ul><li><code>name != null</code>
 15.2784 +     * </ul></dd></dl>
 15.2785 +     */
 15.2786 +    protected XMLParseException invalidValueSet(String name)
 15.2787 +    {
 15.2788 +        String msg = "Invalid value set (entity name = \"" + name + "\")";
 15.2789 +        return new XMLParseException(this.getName(), this.parserLineNr, msg);
 15.2790 +    }
 15.2791 +
 15.2792 +
 15.2793 +    /**
 15.2794 +     * Creates a parse exception for when an invalid value is given to a
 15.2795 +     * method.
 15.2796 +     *
 15.2797 +     * @param name  The name of the entity.
 15.2798 +     * @param value The value of the entity.
 15.2799 +     *
 15.2800 +     * </dl><dl><dt><b>Preconditions:</b></dt><dd>
 15.2801 +     * <ul><li><code>name != null</code>
 15.2802 +     *     <li><code>value != null</code>
 15.2803 +     * </ul></dd></dl>
 15.2804 +     */
 15.2805 +    protected XMLParseException invalidValue(String name,
 15.2806 +                                             String value)
 15.2807 +    {
 15.2808 +        String msg = "Attribute \"" + name + "\" does not contain a valid "
 15.2809 +                   + "value (\"" + value + "\")";
 15.2810 +        return new XMLParseException(this.getName(), this.parserLineNr, msg);
 15.2811 +    }
 15.2812 +
 15.2813 +
 15.2814 +    /**
 15.2815 +     * Creates a parse exception for when the end of the data input has been
 15.2816 +     * reached.
 15.2817 +     */
 15.2818 +    protected XMLParseException unexpectedEndOfData()
 15.2819 +    {
 15.2820 +        String msg = "Unexpected end of data reached";
 15.2821 +        return new XMLParseException(this.getName(), this.parserLineNr, msg);
 15.2822 +    }
 15.2823 +
 15.2824 +
 15.2825 +    /**
 15.2826 +     * Creates a parse exception for when a syntax error occured.
 15.2827 +     *
 15.2828 +     * @param context The context in which the error occured.
 15.2829 +     *
 15.2830 +     * </dl><dl><dt><b>Preconditions:</b></dt><dd>
 15.2831 +     * <ul><li><code>context != null</code>
 15.2832 +     *     <li><code>context.length() &gt; 0</code>
 15.2833 +     * </ul></dd></dl>
 15.2834 +     */
 15.2835 +    protected XMLParseException syntaxError(String context)
 15.2836 +    {
 15.2837 +        String msg = "Syntax error while parsing " + context;
 15.2838 +        return new XMLParseException(this.getName(), this.parserLineNr, msg);
 15.2839 +    }
 15.2840 +
 15.2841 +
 15.2842 +    /**
 15.2843 +     * Creates a parse exception for when the next character read is not
 15.2844 +     * the character that was expected.
 15.2845 +     *
 15.2846 +     * @param charSet The set of characters (in human readable form) that was
 15.2847 +     *                expected.
 15.2848 +     *
 15.2849 +     * </dl><dl><dt><b>Preconditions:</b></dt><dd>
 15.2850 +     * <ul><li><code>charSet != null</code>
 15.2851 +     *     <li><code>charSet.length() &gt; 0</code>
 15.2852 +     * </ul></dd></dl>
 15.2853 +     */
 15.2854 +    protected XMLParseException expectedInput(String charSet)
 15.2855 +    {
 15.2856 +        String msg = "Expected: " + charSet;
 15.2857 +        return new XMLParseException(this.getName(), this.parserLineNr, msg);
 15.2858 +    }
 15.2859 +
 15.2860 +
 15.2861 +    /**
 15.2862 +     * Creates a parse exception for when an entity could not be resolved.
 15.2863 +     *
 15.2864 +     * @param name The name of the entity.
 15.2865 +     *
 15.2866 +     * </dl><dl><dt><b>Preconditions:</b></dt><dd>
 15.2867 +     * <ul><li><code>name != null</code>
 15.2868 +     *     <li><code>name.length() &gt; 0</code>
 15.2869 +     * </ul></dd></dl>
 15.2870 +     */
 15.2871 +    protected XMLParseException unknownEntity(String name)
 15.2872 +    {
 15.2873 +        String msg = "Unknown or invalid entity: &" + name + ";";
 15.2874 +        return new XMLParseException(this.getName(), this.parserLineNr, msg);
 15.2875 +    }
 15.2876 +    
 15.2877 +}
    16.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    16.2 +++ b/src/share/classes/sun/util/xml/XMLParseException.java	Wed Jun 24 17:51:59 2009 +0200
    16.3 @@ -0,0 +1,129 @@
    16.4 +/* XMLParseException.java
    16.5 + *
    16.6 + * $Revision: 1.4 $
    16.7 + * $Date: 2002/03/24 10:27:59 $
    16.8 + * $Name: RELEASE_2_2_1 $
    16.9 + *
   16.10 + * This file is part of NanoXML 2 Lite.
   16.11 + * Copyright (C) 2000-2002 Marc De Scheemaecker, All Rights Reserved.
   16.12 + *
   16.13 + * This software is provided 'as-is', without any express or implied warranty.
   16.14 + * In no event will the authors be held liable for any damages arising from the
   16.15 + * use of this software.
   16.16 + *
   16.17 + * Permission is granted to anyone to use this software for any purpose,
   16.18 + * including commercial applications, and to alter it and redistribute it
   16.19 + * freely, subject to the following restrictions:
   16.20 + *
   16.21 + *  1. The origin of this software must not be misrepresented; you must not
   16.22 + *     claim that you wrote the original software. If you use this software in
   16.23 + *     a product, an acknowledgment in the product documentation would be
   16.24 + *     appreciated but is not required.
   16.25 + *
   16.26 + *  2. Altered source versions must be plainly marked as such, and must not be
   16.27 + *     misrepresented as being the original software.
   16.28 + *
   16.29 + *  3. This notice may not be removed or altered from any source distribution.
   16.30 + *****************************************************************************/
   16.31 +
   16.32 +
   16.33 + package sun.util.xml;
   16.34 +
   16.35 +
   16.36 +/**
   16.37 + * An XMLParseException is thrown when an error occures while parsing an XML
   16.38 + * string.
   16.39 + * <P>
   16.40 + * $Revision: 1.4 $<BR>
   16.41 + * $Date: 2002/03/24 10:27:59 $<P>
   16.42 + *
   16.43 + * @see nanoxml.XMLElement
   16.44 + *
   16.45 + * @author Marc De Scheemaecker
   16.46 + * @version $Name: RELEASE_2_2_1 $, $Revision: 1.4 $
   16.47 + */
   16.48 +class XMLParseException extends RuntimeException
   16.49 +{
   16.50 +
   16.51 +    /**
   16.52 +     * Indicates that no line number has been associated with this exception.
   16.53 +     */
   16.54 +    public static final int NO_LINE = -1;
   16.55 +
   16.56 +
   16.57 +    /**
   16.58 +     * The line number in the source code where the error occurred, or
   16.59 +     * <code>NO_LINE</code> if the line number is unknown.
   16.60 +     *
   16.61 +     * <dl><dt><b>Invariants:</b></dt><dd>
   16.62 +     * <ul><li><code>lineNr &gt 0 || lineNr == NO_LINE</code>
   16.63 +     * </ul></dd></dl>
   16.64 +     */
   16.65 +    private int lineNr;
   16.66 +
   16.67 +
   16.68 +    /**
   16.69 +     * Creates an exception.
   16.70 +     *
   16.71 +     * @param name    The name of the element where the error is located.
   16.72 +     * @param message A message describing what went wrong.
   16.73 +     *
   16.74 +     * </dl><dl><dt><b>Preconditions:</b></dt><dd>
   16.75 +     * <ul><li><code>message != null</code>
   16.76 +     * </ul></dd></dl>
   16.77 +     *
   16.78 +     * <dl><dt><b>Postconditions:</b></dt><dd>
   16.79 +     * <ul><li>getLineNr() => NO_LINE
   16.80 +     * </ul></dd></dl><dl>
   16.81 +     */
   16.82 +    public XMLParseException(String name,
   16.83 +                             String message)
   16.84 +    {
   16.85 +        super("XML Parse Exception during parsing of "
   16.86 +              + ((name == null) ? "the XML definition"
   16.87 +                                : ("a " + name + " element"))
   16.88 +              + ": " + message);
   16.89 +        this.lineNr = XMLParseException.NO_LINE;
   16.90 +    }
   16.91 +
   16.92 +
   16.93 +    /**
   16.94 +     * Creates an exception.
   16.95 +     *
   16.96 +     * @param name    The name of the element where the error is located.
   16.97 +     * @param lineNr  The number of the line in the input.
   16.98 +     * @param message A message describing what went wrong.
   16.99 +     *
  16.100 +     * </dl><dl><dt><b>Preconditions:</b></dt><dd>
  16.101 +     * <ul><li><code>message != null</code>
  16.102 +     *     <li><code>lineNr &gt; 0</code>
  16.103 +     * </ul></dd></dl>
  16.104 +     *
  16.105 +     * <dl><dt><b>Postconditions:</b></dt><dd>
  16.106 +     * <ul><li>getLineNr() => lineNr
  16.107 +     * </ul></dd></dl><dl>
  16.108 +     */
  16.109 +    public XMLParseException(String name,
  16.110 +                             int    lineNr,
  16.111 +                             String message)
  16.112 +    {
  16.113 +        super("XML Parse Exception during parsing of "
  16.114 +              + ((name == null) ? "the XML definition"
  16.115 +                                : ("a " + name + " element"))
  16.116 +              + " at line " + lineNr + ": " + message);
  16.117 +        this.lineNr = lineNr;
  16.118 +    }
  16.119 +
  16.120 +
  16.121 +    /**
  16.122 +     * Where the error occurred, or <code>NO_LINE</code> if the line number is
  16.123 +     * unknown.
  16.124 +     *
  16.125 +     * @see nanoxml.XMLParseException#NO_LINE
  16.126 +     */
  16.127 +    public int getLineNr()
  16.128 +    {
  16.129 +        return this.lineNr;
  16.130 +    }
  16.131 +
  16.132 +}
    17.1 --- a/src/solaris/classes/java/util/prefs/FileSystemPreferences.java	Mon Jun 22 18:07:11 2009 +0200
    17.2 +++ b/src/solaris/classes/java/util/prefs/FileSystemPreferences.java	Wed Jun 24 17:51:59 2009 +0200
    17.3 @@ -572,7 +572,7 @@
    17.4                      try {
    17.5                          newLastSyncTime = prefsFile.lastModified();
    17.6                          FileInputStream fis = new FileInputStream(prefsFile);
    17.7 -                        XmlSupport.importMap(fis, m);
    17.8 +                        sun.util.xml.PrefsXmlSupport.getDefault().importMap(fis, m);
    17.9                          fis.close();
   17.10                      } catch(Exception e) {
   17.11                          if (e instanceof InvalidPreferencesFormatException) {
   17.12 @@ -619,7 +619,7 @@
   17.13                              throw new BackingStoreException(dir +
   17.14                                                               " create failed.");
   17.15                          FileOutputStream fos = new FileOutputStream(tmpFile);
   17.16 -                        XmlSupport.exportMap(fos, prefsCache);
   17.17 +                        sun.util.xml.PrefsXmlSupport.getDefault().exportMap(fos, prefsCache);
   17.18                          fos.close();
   17.19                          if (!tmpFile.renameTo(prefsFile))
   17.20                              throw new BackingStoreException("Can't rename " +
    18.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    18.2 +++ b/test/java/util/Properties/XMLReadAndWriteTest.java	Wed Jun 24 17:51:59 2009 +0200
    18.3 @@ -0,0 +1,83 @@
    18.4 +/*
    18.5 + * To change this template, choose Tools | Templates
    18.6 + * and open the template in the editor.
    18.7 + */
    18.8 +
    18.9 +import java.io.ByteArrayInputStream;
   18.10 +import sun.util.xml.PropertiesXMLUtils;
   18.11 +
   18.12 +import java.io.ByteArrayOutputStream;
   18.13 +import java.io.IOException;
   18.14 +import java.util.Properties;
   18.15 +
   18.16 +/** Checks whether reading and writing via standard DOM and simplified API
   18.17 + * results in same results.
   18.18 + *
   18.19 + * @author Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   18.20 + */
   18.21 +public class XMLReadAndWriteTest {
   18.22 +    private static PropertiesXMLUtils FULL = new com.sun.xml.internal.PropertiesXMLUtilsImpl();
   18.23 +    private static PropertiesXMLUtils SIMPLE = new sun.util.xml.DefaultPropertiesXMLUtils();
   18.24 +
   18.25 +
   18.26 +    public static void main(String[] args) throws Exception {
   18.27 +        XMLReadAndWriteTest test = new XMLReadAndWriteTest();
   18.28 +        test.testCompareOutput();
   18.29 +        test.testCompareInput();
   18.30 +    }
   18.31 +
   18.32 +
   18.33 +    public XMLReadAndWriteTest() {
   18.34 +    }
   18.35 +
   18.36 +    public void testCompareOutput() throws IOException {
   18.37 +        Properties p = new Properties();
   18.38 +        p.setProperty("ahoj", "simple");
   18.39 +        p.setProperty("kuk", "buk");
   18.40 +        p.setProperty("multi", "one\ntwo\nthree\nfour");
   18.41 +
   18.42 +        ByteArrayOutputStream full = new ByteArrayOutputStream();
   18.43 +        FULL.save(p, full, "my commment on beginging\nand on the second line\n", "UTF-8");
   18.44 +
   18.45 +        ByteArrayOutputStream simple = new ByteArrayOutputStream();
   18.46 +        SIMPLE.save(p, simple, "my commment on beginging\nand on the second line\n", "UTF-8");
   18.47 +        if (full.toString().equals(simple.toString())) {
   18.48 +            // OK
   18.49 +            System.err.println("OK: testCompareOutput");
   18.50 +        } else {
   18.51 +            assert false :
   18.52 +                "Full version differs from simplified. Full:\n" + full + "\nSimple:\n" + simple;
   18.53 +        }
   18.54 +    }
   18.55 +
   18.56 +    public void testCompareInput() throws IOException {
   18.57 +        String text = "<?xml version='1.0' encoding='UTF-8' standalone='no'?>" +
   18.58 +            "  <!DOCTYPE properties SYSTEM 'http://java.sun.com/dtd/properties.dtd'>" +
   18.59 +            "<properties>\n" +
   18.60 +            "<comment>my commment on beginging\n" +
   18.61 +            "and on the second line" +
   18.62 +            "</comment>" +
   18.63 +            "<entry key=\"ahoj\">simple</entry>\n" +
   18.64 +            "         <entry key=\"kuk\">buk</entry>" +
   18.65 +            "   <entry key='multi'>one\n" +
   18.66 +            "two\n" +
   18.67 +            "three\n" +
   18.68 +            "four</entry>\n</properties>";
   18.69 +
   18.70 +        Properties p1 = new Properties();
   18.71 +        {
   18.72 +            ByteArrayInputStream is = new ByteArrayInputStream(text.getBytes("UTF-8"));
   18.73 +            FULL.load(p1, is);
   18.74 +        }
   18.75 +
   18.76 +        Properties p2 = new Properties();
   18.77 +        {
   18.78 +            ByteArrayInputStream is = new ByteArrayInputStream(text.getBytes("UTF-8"));
   18.79 +            SIMPLE.load(p2, is);
   18.80 +        }
   18.81 +
   18.82 +        assert p1.equals(p2) : "P1: " + p1 + "\nP2: " + p2;
   18.83 +        System.err.println("OK: testCompareInput");
   18.84 +    }
   18.85 +
   18.86 +}
   18.87 \ No newline at end of file
    19.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    19.2 +++ b/test/java/util/prefs/Preferences/XMLPreferencesTest.java	Wed Jun 24 17:51:59 2009 +0200
    19.3 @@ -0,0 +1,128 @@
    19.4 +/*
    19.5 + * Copyright 2002-2006 Sun Microsystems, Inc.  All Rights Reserved.
    19.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    19.7 + *
    19.8 + * This code is free software; you can redistribute it and/or modify it
    19.9 + * under the terms of the GNU General Public License version 2 only, as
   19.10 + * published by the Free Software Foundation.  Sun designates this
   19.11 + * particular file as subject to the "Classpath" exception as provided
   19.12 + * by Sun in the LICENSE file that accompanied this code.
   19.13 + *
   19.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   19.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   19.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   19.17 + * version 2 for more details (a copy is included in the LICENSE file that
   19.18 + * accompanied this code).
   19.19 + *
   19.20 + * You should have received a copy of the GNU General Public License version
   19.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   19.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   19.23 + *
   19.24 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
   19.25 + * CA 95054 USA or visit www.sun.com if you need additional information or
   19.26 + * have any questions.
   19.27 + */
   19.28 +
   19.29 +
   19.30 +import java.io.ByteArrayInputStream;
   19.31 +import sun.util.xml.PrefsXmlSupport;
   19.32 +
   19.33 +import java.io.ByteArrayOutputStream;
   19.34 +import java.util.Arrays;
   19.35 +import java.util.prefs.Preferences;
   19.36 +
   19.37 +/** Checks whether reading and writing via standard DOM and simplified API
   19.38 + * results in same results.
   19.39 + *
   19.40 + * @author Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   19.41 + */
   19.42 +public class XMLPreferencesTest {
   19.43 +    private static PrefsXmlSupport FULL = new com.sun.xml.internal.PrefsXmlSupportImpl();
   19.44 +    private static PrefsXmlSupport SIMPLE = new sun.util.xml.DefaultPrefsXmlSupport();
   19.45 +
   19.46 +
   19.47 +    public static void main(String[] args) throws Exception {
   19.48 +        XMLPreferencesTest test = new XMLPreferencesTest();
   19.49 +        test.testCompareOutput();
   19.50 +        test.testCompareInput();
   19.51 +    }
   19.52 +
   19.53 +
   19.54 +    public XMLPreferencesTest() {
   19.55 +    }
   19.56 +
   19.57 +    public void testCompareOutput() throws Exception {
   19.58 +        Preferences p = Preferences.userRoot().node("a/b/c");
   19.59 +        p.put("ahoj", "simple");
   19.60 +        p.putInt("kuk", 1);
   19.61 +        p.putBoolean("multi", true);
   19.62 +        p.node("child").putBoolean("data", false);
   19.63 +        p.node("empty");
   19.64 +        p.parent().putDouble("visible", 1.0);
   19.65 +
   19.66 +        ByteArrayOutputStream full = new ByteArrayOutputStream();
   19.67 +        FULL.export(full, p, true);
   19.68 +
   19.69 +        ByteArrayOutputStream simple = new ByteArrayOutputStream();
   19.70 +        SIMPLE.export(simple, p, true);
   19.71 +        if (full.toString().equals(simple.toString())) {
   19.72 +            // OK
   19.73 +            System.err.println("OK: testCompareOutput");
   19.74 +        } else {
   19.75 +            assert false :
   19.76 +                "Full version differs from simplified. Full:\n" + full + "\nSimple:\n" + simple;
   19.77 +        }
   19.78 +    }
   19.79 +
   19.80 +    public void testCompareInput() throws Exception {
   19.81 +        Preferences.userRoot().node("test1/b/c").removeNode();
   19.82 +        Preferences.userRoot().node("test2/b/c").removeNode();
   19.83 +
   19.84 +        String text = "<?xml version='1.0' encoding='UTF-8' standalone='no'?>" +
   19.85 +                "<!DOCTYPE preferences SYSTEM 'http://java.sun.com/dtd/preferences.dtd'>" +
   19.86 +                "            <preferences EXTERNAL_XML_VERSION='1.0'>" +
   19.87 +                "    <root type='user'>\n\n\n" +
   19.88 +                "<map/><node name='test1'><map/><node name='b'>" +
   19.89 +                "<map/><node name='c'><map>" +
   19.90 +                "    <entry key='ahoj' value='simple'/>" +
   19.91 +                "    <entry key='kuk' value='1'/>" +
   19.92 +                "    <entry key='multi' value='true'/>        \n" +
   19.93 +                "</map>" +
   19.94 +                "<node name='child'>" +
   19.95 +                "<map>" +
   19.96 +                "<entry key='data' value='false'/>" +
   19.97 +                "</map>" +
   19.98 +                "</node><node name='empty'><map/>" +
   19.99 +                "</node>" +
  19.100 +                "</node>" +
  19.101 +                "</node>" +
  19.102 +                "</node>" +
  19.103 +                "</root>" +
  19.104 +                "</preferences>";
  19.105 +
  19.106 +        {
  19.107 +            ByteArrayInputStream is = new ByteArrayInputStream(text.getBytes("UTF-8"));
  19.108 +            FULL.importPreferences(is);
  19.109 +        }
  19.110 +
  19.111 +        {
  19.112 +            text = text.replace("'test1'", "'test2'");
  19.113 +            ByteArrayInputStream is = new ByteArrayInputStream(text.getBytes("UTF-8"));
  19.114 +            SIMPLE.importPreferences(is);
  19.115 +        }
  19.116 +
  19.117 +        assert Preferences.userRoot().nodeExists("test1/b/c") : "Node in user imported";
  19.118 +        assert Preferences.userRoot().nodeExists("test2/b/c") : "Node in system imported";
  19.119 +
  19.120 +        Preferences u = Preferences.userRoot().node("test1/b/c");
  19.121 +        Preferences s = Preferences.userRoot().node("test2/b/c");
  19.122 +
  19.123 +        assert Arrays.equals(u.keys(), s.keys()) : "Same keys in both nodes";
  19.124 +
  19.125 +        for (String k : u.keys()) {
  19.126 +            assert u.get(k, "Neco").equals(s.get(k, "Cone")) : "Same values for " + k;
  19.127 +        }
  19.128 +        System.err.println("OK: testCompareInput");
  19.129 +    }
  19.130 +
  19.131 +}
  19.132 \ No newline at end of file