Using code injection to separate XML related operations on Properties and Preferences outside of base module. Default implementation is still missing.
1.1 --- a/build.xml Wed Jun 24 12:33:10 2009 +0200
1.2 +++ b/build.xml Wed Jun 24 13:44:46 2009 +0200
1.3 @@ -215,24 +215,38 @@
1.4 </selector>
1.5
1.6 <selector id="xml">
1.7 - <or>
1.8 - <filename name="org/w3c/**"/>
1.9 - <filename name="org/sax/**"/>
1.10 - <filename name="com/sun/org/apache/xml/internal/**"/>
1.11 - <filename name="com/sun/org/apache/xpath/internal/**"/>
1.12 - <filename name="com/sun/org/apache/xalan/internal/**"/>
1.13 - <filename name="com/sun/org/apache/xerces/internal/**"/>
1.14 - <filename name="com/sun/xml/internal/**"/>
1.15 - <filename name="org/jcp/xml/dsig/internal/**"/>
1.16 - <filename name="javax/xml/**"/>
1.17 - <filename name="com/sun/servicetag/**"/>
1.18 - <filename name="com/sun/java/browser/**"/>
1.19 + <and>
1.20 + <or>
1.21 + <filename name="META-INF/services/sun.util.xml*"/>
1.22
1.23 - <!-- sql seems to have dependency on XML, so including here too for now -->
1.24 - <filename name="com/sun/rowset/**"/>
1.25 - <filename name="java/sql/**"/>
1.26 - <filename name="javax/sql/**"/>
1.27 - </or>
1.28 + <filename name="org/w3c/**"/>
1.29 + <filename name="org/sax/**"/>
1.30 + <filename name="com/sun/org/apache/xml/internal/**"/>
1.31 + <filename name="com/sun/org/apache/xpath/internal/**"/>
1.32 + <filename name="com/sun/org/apache/xalan/internal/**"/>
1.33 + <filename name="com/sun/org/apache/xerces/internal/**"/>
1.34 + <filename name="com/sun/xml/internal/**"/>
1.35 + <filename name="org/jcp/xml/dsig/internal/**"/>
1.36 + <filename name="javax/xml/**"/>
1.37 + <filename name="com/sun/servicetag/**"/>
1.38 + <filename name="com/sun/java/browser/**"/>
1.39 +
1.40 + <!-- SQL seems to have dependency on XML,
1.41 + so including it here too for now
1.42 + -->
1.43 + <filename name="com/sun/rowset/**"/>
1.44 + <filename name="java/sql/**"/>
1.45 + <filename name="javax/sql/**"/>
1.46 + </or>
1.47 + <none>
1.48 + <!-- remove classes from other modules -->
1.49 + <selector refid="applet"/>
1.50 + <selector refid="client"/>
1.51 + <selector refid="corba"/>
1.52 + <selector refid="tools"/>
1.53 + <selector refid="deprecated7"/>
1.54 + </none>
1.55 + </and>
1.56 </selector>
1.57
1.58 <selector id="tools">
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 13:44:46 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 13:44:46 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 13:44:46 2009 +0200
4.3 @@ -0,0 +1,422 @@
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 (((AbstractPreferences)p).isRemoved())
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 (((AbstractPreferences)prefs).lock) {
4.152 + // Check if this node was concurrently removed. If yes
4.153 + // remove it from XML Document and return.
4.154 + if (((AbstractPreferences)prefs).isRemoved()) {
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 (((AbstractPreferences)prefsNode).lock) {
4.304 + //If removed, return silently
4.305 + if (((AbstractPreferences)prefsNode).isRemoved())
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 +}
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 13:44:46 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 Wed Jun 24 12:33:10 2009 +0200
6.2 +++ b/src/share/classes/java/util/Properties.java Wed Jun 24 13:44:46 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 Wed Jun 24 12:33:10 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 Wed Jun 24 12:33:10 2009 +0200
8.2 +++ b/src/share/classes/java/util/prefs/AbstractPreferences.java Wed Jun 24 13:44:46 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 Wed Jun 24 12:33:10 2009 +0200
9.2 +++ b/src/share/classes/java/util/prefs/Preferences.java Wed Jun 24 13:44:46 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 Wed Jun 24 12:33:10 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/PrefsXmlSupport.java Wed Jun 24 13:44:46 2009 +0200
11.3 @@ -0,0 +1,69 @@
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 + * XML Support for java.util.prefs. Methods to import and export preference
11.37 + * nodes and subtrees.
11.38 + *
11.39 + * @author Josh Bloch and Mark Reinhold
11.40 + * @see Preferences
11.41 + * @since 1.4
11.42 + */
11.43 +public abstract class PrefsXmlSupport {
11.44 + public static PrefsXmlSupport getDefault() {
11.45 + Iterator<PrefsXmlSupport> it = ServiceLoader.load(PrefsXmlSupport.class).iterator();
11.46 + return it.hasNext() ? it.next() : null /* JST-XXX: some default */;
11.47 + }
11.48 +
11.49 + public abstract void export(OutputStream os, final Preferences p, boolean subTree)
11.50 + throws IOException, BackingStoreException;
11.51 +
11.52 + /**
11.53 + * Import preferences from the specified input stream, which is assumed
11.54 + * to contain an XML document in the format described in the Preferences
11.55 + * spec.
11.56 + *
11.57 + * @throws IOException if reading from the specified output stream
11.58 + * results in an <tt>IOException</tt>.
11.59 + * @throws InvalidPreferencesFormatException Data on input stream does not
11.60 + * constitute a valid XML document with the mandated document type.
11.61 + */
11.62 + public abstract void importPreferences(InputStream is)
11.63 + throws IOException, InvalidPreferencesFormatException;
11.64 +
11.65 +
11.66 + public abstract void importMap(InputStream is, Map m)
11.67 + throws IOException, InvalidPreferencesFormatException;
11.68 +
11.69 + public abstract void exportMap(OutputStream is, Map m)
11.70 + throws IOException, InvalidPreferencesFormatException;
11.71 +
11.72 +}
12.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
12.2 +++ b/src/share/classes/sun/util/xml/PropertiesXMLUtils.java Wed Jun 24 13:44:46 2009 +0200
12.3 @@ -0,0 +1,53 @@
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.Iterator;
12.35 +import java.util.ServiceLoader;
12.36 +
12.37 +/**
12.38 + * A class used to aid in Properties load and save in XML. Keeping this
12.39 + * code outside of Properties helps reduce the number of classes loaded
12.40 + * when Properties is loaded.
12.41 + *
12.42 + * @author Michael McCloskey
12.43 + * @since 1.3
12.44 + */
12.45 +public abstract class PropertiesXMLUtils {
12.46 + public static PropertiesXMLUtils getDefault() {
12.47 + Iterator<PropertiesXMLUtils> it = ServiceLoader.load(PropertiesXMLUtils.class).iterator();
12.48 + return it.hasNext() ? it.next() : null /* JST-XXX: some default */;
12.49 + }
12.50 +
12.51 + public abstract void load(Properties props, InputStream in) throws
12.52 + IOException, InvalidPropertiesFormatException;
12.53 + public abstract void save(Properties props, OutputStream out, String comment, String encoding)
12.54 + throws IOException;
12.55 +
12.56 +}
13.1 --- a/src/solaris/classes/java/util/prefs/FileSystemPreferences.java Wed Jun 24 12:33:10 2009 +0200
13.2 +++ b/src/solaris/classes/java/util/prefs/FileSystemPreferences.java Wed Jun 24 13:44:46 2009 +0200
13.3 @@ -572,7 +572,7 @@
13.4 try {
13.5 newLastSyncTime = prefsFile.lastModified();
13.6 FileInputStream fis = new FileInputStream(prefsFile);
13.7 - XmlSupport.importMap(fis, m);
13.8 + sun.util.xml.PrefsXmlSupport.getDefault().importMap(fis, m);
13.9 fis.close();
13.10 } catch(Exception e) {
13.11 if (e instanceof InvalidPreferencesFormatException) {
13.12 @@ -619,7 +619,7 @@
13.13 throw new BackingStoreException(dir +
13.14 " create failed.");
13.15 FileOutputStream fos = new FileOutputStream(tmpFile);
13.16 - XmlSupport.exportMap(fos, prefsCache);
13.17 + sun.util.xml.PrefsXmlSupport.getDefault().exportMap(fos, prefsCache);
13.18 fos.close();
13.19 if (!tmpFile.renameTo(prefsFile))
13.20 throw new BackingStoreException("Can't rename " +