1 7 8 package java.util.prefs; 9 10 import java.util.*; 11 import java.io.*; 12 import javax.xml.parsers.*; 13 import javax.xml.transform.*; 14 import javax.xml.transform.dom.*; 15 import javax.xml.transform.stream.*; 16 import org.xml.sax.*; 17 import org.w3c.dom.*; 18 19 28 class XmlSupport { 29 private static final String PREFS_DTD_URI = 31 "http://java.sun.com/dtd/preferences.dtd"; 32 33 private static final String PREFS_DTD = 35 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" + 36 37 "<!-- DTD for preferences -->" + 38 39 "<!ELEMENT preferences (root) >" + 40 "<!ATTLIST preferences" + 41 " EXTERNAL_XML_VERSION CDATA \"0.0\" >" + 42 43 "<!ELEMENT root (map, node*) >" + 44 "<!ATTLIST root" + 45 " type (system|user) #REQUIRED >" + 46 47 "<!ELEMENT node (map, node*) >" + 48 "<!ATTLIST node" + 49 " name CDATA #REQUIRED >" + 50 51 "<!ELEMENT map (entry*) >" + 52 "<!ATTLIST map" + 53 " MAP_XML_VERSION CDATA \"0.0\" >" + 54 "<!ELEMENT entry EMPTY >" + 55 "<!ATTLIST entry" + 56 " key CDATA #REQUIRED" + 57 " value CDATA #REQUIRED >" ; 58 61 private static final String EXTERNAL_XML_VERSION = "1.0"; 62 63 66 private static final String MAP_XML_VERSION = "1.0"; 67 68 80 static void export(OutputStream os, final Preferences p, boolean subTree) 81 throws IOException, BackingStoreException { 82 if (((AbstractPreferences )p).isRemoved()) 83 throw new IllegalStateException ("Node has been removed"); 84 Document doc = createPrefsDoc("preferences"); 85 Element preferences = doc.getDocumentElement() ; 86 preferences.setAttribute("EXTERNAL_XML_VERSION", EXTERNAL_XML_VERSION); 87 Element xmlRoot = (Element) 88 preferences.appendChild(doc.createElement("root")); 89 xmlRoot.setAttribute("type", (p.isUserNode() ? "user" : "system")); 90 91 List ancestors = new ArrayList(); 93 94 for (Preferences kid = p, dad = kid.parent(); dad != null; 95 kid = dad, dad = kid.parent()) { 96 ancestors.add(kid); 97 } 98 Element e = xmlRoot; 99 for (int i=ancestors.size()-1; i >= 0; i--) { 100 e.appendChild(doc.createElement("map")); 101 e = (Element) e.appendChild(doc.createElement("node")); 102 e.setAttribute("name", ((Preferences )ancestors.get(i)).name()); 103 } 104 putPreferencesInXml(e, doc, p, subTree); 105 106 writeDoc(doc, os); 107 } 108 109 121 private static void putPreferencesInXml(Element elt, Document doc, 122 Preferences prefs, boolean subTree) throws BackingStoreException 123 { 124 Preferences [] kidsCopy = null; 125 String [] kidNames = null; 126 127 synchronized (((AbstractPreferences )prefs).lock) { 131 if (((AbstractPreferences )prefs).isRemoved()) { 134 elt.getParentNode().removeChild(elt); 135 return; 136 } 137 String [] keys = prefs.keys(); 139 Element map = (Element) elt.appendChild(doc.createElement("map")); 140 for (int i=0; i<keys.length; i++) { 141 Element entry = (Element) 142 map.appendChild(doc.createElement("entry")); 143 entry.setAttribute("key", keys[i]); 144 entry.setAttribute("value", prefs.get(keys[i], null)); 146 } 147 if (subTree) { 149 150 kidNames = prefs.childrenNames(); 151 kidsCopy = new Preferences [kidNames.length]; 152 for (int i = 0; i < kidNames.length; i++) 153 kidsCopy[i] = prefs.node(kidNames[i]); 154 } 155 } 157 158 if (subTree) { 159 for (int i=0; i < kidNames.length; i++) { 160 Element xmlKid = (Element) 161 elt.appendChild(doc.createElement("node")); 162 xmlKid.setAttribute("name", kidNames[i]); 163 putPreferencesInXml(xmlKid, doc, kidsCopy[i], subTree); 164 } 165 } 166 } 167 168 178 static void importPreferences(InputStream is) 179 throws IOException, InvalidPreferencesFormatException 180 { 181 try { 182 Document doc = loadPrefsDoc(is); 183 String xmlVersion = 184 ((Element)doc.getChildNodes().item(1)).getAttribute("EXTERNAL_XML_VERSION"); 185 if (xmlVersion.compareTo(EXTERNAL_XML_VERSION) > 0) 186 throw new InvalidPreferencesFormatException ( 187 "Exported preferences file format version " + xmlVersion + 188 " is not supported. This java installation can read" + 189 " versions " + EXTERNAL_XML_VERSION + " or older. You may need" + 190 " to install a newer version of JDK."); 191 192 Element xmlRoot = (Element) doc.getChildNodes().item(1). 193 getChildNodes().item(0); 194 Preferences prefsRoot = 195 (xmlRoot.getAttribute("type").equals("user") ? 196 Preferences.userRoot() : Preferences.systemRoot()); 197 ImportSubtree(prefsRoot, xmlRoot); 198 } catch(SAXException e) { 199 throw new InvalidPreferencesFormatException (e); 200 } 201 } 202 203 206 private static Document createPrefsDoc( String qname ) { 207 try { 208 DOMImplementation di = DocumentBuilderFactory.newInstance(). 209 newDocumentBuilder().getDOMImplementation(); 210 DocumentType dt = di.createDocumentType(qname, null, PREFS_DTD_URI); 211 return di.createDocument(null, qname, dt); 212 } catch(ParserConfigurationException e) { 213 throw new AssertionError (e); 214 } 215 } 216 217 221 private static Document loadPrefsDoc(InputStream in) 222 throws SAXException, IOException 223 { 224 Resolver r = new Resolver(); 225 DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); 226 dbf.setIgnoringElementContentWhitespace(true); 227 dbf.setValidating(true); 228 dbf.setCoalescing(true); 229 dbf.setIgnoringComments(true); 230 try { 231 DocumentBuilder db = dbf.newDocumentBuilder(); 232 db.setEntityResolver(new Resolver()); 233 db.setErrorHandler(new EH()); 234 return db.parse(new InputSource(in)); 235 } catch (ParserConfigurationException e) { 236 throw new AssertionError (e); 237 } 238 } 239 240 243 private static final void writeDoc(Document doc, OutputStream out) 244 throws IOException 245 { 246 try { 247 Transformer t = TransformerFactory.newInstance().newTransformer(); 248 t.setOutputProperty(OutputKeys.DOCTYPE_SYSTEM, doc.getDoctype().getSystemId()); 249 t.transform(new DOMSource(doc), new StreamResult(out)); 250 } catch(TransformerException e) { 251 throw new AssertionError (e); 252 } 253 } 254 255 260 private static void ImportSubtree(Preferences prefsNode, Element xmlNode) { 261 NodeList xmlKids = xmlNode.getChildNodes(); 262 int numXmlKids = xmlKids.getLength(); 263 269 Preferences [] prefsKids; 270 271 synchronized (((AbstractPreferences )prefsNode).lock) { 272 if (((AbstractPreferences )prefsNode).isRemoved()) 274 return; 275 276 Element firstXmlKid = (Element) xmlKids.item(0); 278 ImportPrefs(prefsNode, firstXmlKid); 279 prefsKids = new Preferences [numXmlKids - 1]; 280 281 for (int i=1; i < numXmlKids; i++) { 283 Element xmlKid = (Element) xmlKids.item(i); 284 prefsKids[i-1] = prefsNode.node(xmlKid.getAttribute("name")); 285 } 286 } for (int i=1; i < numXmlKids; i++) 289 ImportSubtree(prefsKids[i-1], (Element)xmlKids.item(i)); 290 } 291 292 297 private static void ImportPrefs(Preferences prefsNode, Element map) { 298 NodeList entries = map.getChildNodes(); 299 for (int i=0, numEntries = entries.getLength(); i < numEntries; i++) { 300 Element entry = (Element) entries.item(i); 301 prefsNode.put(entry.getAttribute("key"), 302 entry.getAttribute("value")); 303 } 304 } 305 306 314 static void exportMap(OutputStream os, Map map) throws IOException { 315 Document doc = createPrefsDoc("map"); 316 Element xmlMap = doc.getDocumentElement( ) ; 317 xmlMap.setAttribute("MAP_XML_VERSION", MAP_XML_VERSION); 318 319 for (Iterator i = map.entrySet().iterator(); i.hasNext(); ) { 320 Map.Entry e = (Map.Entry) i.next(); 321 Element xe = (Element) 322 xmlMap.appendChild(doc.createElement("entry")); 323 xe.setAttribute("key", (String ) e.getKey()); 324 xe.setAttribute("value", (String ) e.getValue()); 325 } 326 327 writeDoc(doc, os); 328 } 329 330 343 static void importMap(InputStream is, Map m) 344 throws IOException, InvalidPreferencesFormatException 345 { 346 try { 347 Document doc = loadPrefsDoc(is); 348 Element xmlMap = (Element) doc.getChildNodes().item(1); 349 String mapVersion = xmlMap.getAttribute("MAP_XML_VERSION"); 351 if (mapVersion.compareTo(MAP_XML_VERSION) > 0) 352 throw new InvalidPreferencesFormatException ( 353 "Preferences map file format version " + mapVersion + 354 " is not supported. This java installation can read" + 355 " versions " + MAP_XML_VERSION + " or older. You may need" + 356 " to install a newer version of JDK."); 357 358 NodeList entries = xmlMap.getChildNodes(); 359 for (int i=0, numEntries=entries.getLength(); i<numEntries; i++) { 360 Element entry = (Element) entries.item(i); 361 m.put(entry.getAttribute("key"), entry.getAttribute("value")); 362 } 363 } catch(SAXException e) { 364 throw new InvalidPreferencesFormatException (e); 365 } 366 } 367 368 private static class Resolver implements EntityResolver { 369 public InputSource resolveEntity(String pid, String sid) 370 throws SAXException 371 { 372 if (sid.equals(PREFS_DTD_URI)) { 373 InputSource is; 374 is = new InputSource(new StringReader(PREFS_DTD)); 375 is.setSystemId(PREFS_DTD_URI); 376 return is; 377 } 378 throw new SAXException("Invalid system identifier: " + sid); 379 } 380 } 381 382 private static class EH implements ErrorHandler { 383 public void error(SAXParseException x) throws SAXException { 384 throw x; 385 } 386 public void fatalError(SAXParseException x) throws SAXException { 387 throw x; 388 } 389 public void warning(SAXParseException x) throws SAXException { 390 throw x; 391 } 392 } 393 } 394 | Popular Tags |