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 + * String key = (String) enumV.nextElement();<BR>
15.72 + * String value = element.getStringAttribute(key);<BR>
15.73 + * 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 + * <title>The Title</title>
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 + * <<A href="mailto:cyberelf@mac.com">cyberelf@mac.com</A>>
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 &...; entities. The keys are the entity names
15.189 + * without the & 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" => "<", "gt" => ">",
15.195 + * "quot" => "\"", "apos" => "'",
15.196 + * "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 >= 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 > 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" =>
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 + * '>' 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 + * '>' 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() > 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 < string.length()</code>
15.1763 + * <li><code>offset >= 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 <= string.length()</code>
15.1796 + * <li><code>offset < end</code>
15.1797 + * <li><code>offset >= 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 <= string.length()</code>
15.1833 + * <li><code>offset < end</code>
15.1834 + * <li><code>offset >= 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 <= input.length</code>
15.1874 + * <li><code>offset < end</code>
15.1875 + * <li><code>offset >= 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 <= input.length</code>
15.1911 + * <li><code>offset < end</code>
15.1912 + * <li><code>offset >= 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 < 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 < 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 <!-- 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 <! 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 < 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 & 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() > 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() > 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() > 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 > 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 > 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