1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 package org.openoffice.setup.SetupData; 29 30 import org.openoffice.setup.InstallData; 31 import org.openoffice.setup.Util.FileExtensionFilter; 32 import java.io.File; 33 import java.io.IOException; 34 import java.util.Enumeration; 35 import java.util.Hashtable; 36 import java.util.Stack; 37 import java.util.Vector; 38 import javax.xml.parsers.ParserConfigurationException; 39 import javax.xml.parsers.SAXParser; 40 import javax.xml.parsers.SAXParserFactory; 41 import org.xml.sax.Attributes; 42 import org.xml.sax.SAXException; 43 import org.xml.sax.SAXParseException; 44 import org.xml.sax.helpers.DefaultHandler; 45 public class XMLPackageDescription { 46 47 /** 48 * fill the package description tree by handling the SAXParser events 49 */ 50 private class PackageDescriptionHandler extends DefaultHandler { 51 52 private XMLPackageDescription root; 53 private Stack stack; 54 55 public PackageDescriptionHandler(XMLPackageDescription base) { 56 root = base; 57 stack = new Stack(); 58 } 59 60 private PackageDescriptionHandler() { 61 /* forbidden */ 62 } 63 64 public XMLPackageDescription getDescription() { 65 return root; 66 } 67 68 /* implement the DefaultHandler interface */ 69 70 public void characters(char[] ch, int start, int length) { 71 XMLPackageDescription entity = (XMLPackageDescription) stack.peek(); 72 entity.value = entity.value == null ? new String(ch, start, length) 73 : entity.value + new String(ch, start, length); 74 } 75 public void startDocument() { 76 stack.push(root); 77 } 78 public void endDocument() { 79 stack.pop(); 80 } 81 public void startElement(String uri, String localName, String qName, Attributes attributes) { 82 XMLPackageDescription parent = (XMLPackageDescription) stack.peek(); 83 XMLPackageDescription entity = new XMLPackageDescription(); 84 85 entity.key = qName; 86 for (int i = 0; i < attributes.getLength(); i++) { 87 entity.attributes.put(attributes.getQName(i), attributes.getValue(i)); 88 } 89 90 parent.add(entity); 91 stack.push(entity); 92 } 93 public void endElement(String uri, String localName, String qName) { 94 stack.pop(); 95 } 96 public void error(SAXParseException e) { 97 System.err.println("Parse Error:" + e); 98 } 99 public void processingInstruction(String target, String data) { 100 /* ignore */ 101 } 102 public void skippedEntity(String name) { 103 /* ignore */ 104 } 105 public void warning(SAXParseException e) { 106 System.err.println("Warning:" + e); 107 } 108 } 109 110 /** 111 * general storage for XML elements 112 */ 113 114 private String key; /* XML element name */ 115 private String value; /* XML element characters */ 116 private Hashtable attributes; /* XML element attributes */ 117 private Vector children; /* children are of type XMLPackageDescription */ 118 119 protected XMLPackageDescription() { 120 key = ""; 121 value = null; 122 attributes = new Hashtable(); 123 children = new Vector(); 124 } 125 126 private void add(XMLPackageDescription p) { 127 children.add(p); 128 } 129 130 /** 131 * helper routines to find content information 132 */ 133 protected String getKey() { 134 return key; 135 } 136 protected String getAttribute(String key) { 137 return (String) attributes.get(key); 138 } 139 protected String getValue() { 140 return value; 141 } 142 protected XMLPackageDescription getElement(String key) { 143 return getElement(key, null, null); 144 } 145 protected XMLPackageDescription getElement(String key, String attrKey, String attrValue) { 146 for (Enumeration e = children.elements(); e.hasMoreElements();) { 147 XMLPackageDescription child = (XMLPackageDescription) e.nextElement(); 148 if (child.key.equals(key)) { 149 if (attrKey == null) { 150 return child; 151 } else if (attrValue.equals(child.getAttribute(attrKey))) { 152 return child; 153 } 154 } 155 } 156 return null; 157 } 158 159 /** 160 * find a PackageDescription of type package that has the given name, 161 * recurses into the children 162 */ 163 private XMLPackageDescription findPackage(String name) { 164 String self = (String) attributes.get("name"); 165 166 if ((self != null) && self.equals(name)) 167 return this; 168 169 XMLPackageDescription found = null; 170 for (Enumeration e = children.elements(); e.hasMoreElements();) { 171 XMLPackageDescription child = (XMLPackageDescription) e.nextElement(); 172 if (child.getAttribute("parent") != null) { 173 found = child.findPackage(name); 174 if (found != null) { 175 break; 176 } 177 } 178 } 179 return found; 180 } 181 182 /** 183 * adjust the tree so that all children have a matching parent and not just 184 * the ones they got by reading files in random order 185 */ 186 private void adjust(XMLPackageDescription root) { 187 String self = (String) attributes.get("name"); 188 189 for (int i = children.size() - 1; i >= 0; --i) { 190 XMLPackageDescription child = (XMLPackageDescription) children.elementAt(i); 191 String childParentName = child.getAttribute("parent"); 192 if (childParentName != null) { 193 194 child.adjust(root); 195 196 if ((childParentName != null) && (childParentName.length() > 0) && (! childParentName.equals(self))) { 197 XMLPackageDescription newParent = root.findPackage(childParentName); 198 if (newParent != null) { 199 newParent.add(child); 200 children.remove(i); 201 } 202 } 203 } 204 } 205 } 206 207 protected void read() { 208 PackageDescriptionHandler handler = new PackageDescriptionHandler(this); 209 210 try { 211 SAXParserFactory factory = SAXParserFactory.newInstance(); 212 SAXParser parser = factory.newSAXParser(); 213 214 InstallData data = InstallData.getInstance(); 215 File xpdRoot = data.getInfoRoot("xpd"); 216 217 if ( xpdRoot != null ) { 218 File[] file = xpdRoot.listFiles(new FileExtensionFilter("xpd")); 219 220 if (file != null) { 221 for (int i = 0; i < file.length; i++) { 222 parser.parse(file[i], handler); 223 } 224 } else { 225 key = ""; 226 value = "no package file found"; 227 } 228 } 229 else { 230 System.err.println("Did not find xpd directory"); 231 } 232 } catch (ParserConfigurationException ex) { 233 ex.printStackTrace(); 234 } catch (IOException ex) { 235 ex.printStackTrace(); 236 } catch (SAXException ex) { 237 ex.printStackTrace(); 238 } 239 240 adjust(this); 241 } 242 243 /* provide an iterator through the children */ 244 protected class Elements implements Enumeration { 245 246 Enumeration e; 247 248 protected Elements() { 249 e = children.elements(); 250 } 251 public boolean hasMoreElements() { 252 return e.hasMoreElements(); 253 } 254 public Object nextElement() { 255 return e.nextElement(); 256 } 257 } 258 259 protected Enumeration elements() { 260 return new Elements(); 261 } 262 263 264 // FIXME: remove it, dump() is for testing only 265 public void dump() { 266 dump(""); 267 } 268 269 // FIXME: remove it, dump(String) is for testing only 270 public void dump(String indent) { 271 final String space = " "; 272 if (key != null) { 273 System.out.print(indent + "<" + key); 274 } 275 for (Enumeration e = attributes.keys() ; e.hasMoreElements() ;) { 276 String key = (String) e.nextElement(); 277 String value = (String) attributes.get(key); 278 System.out.print(" " + key + "=\"" + value + "\""); 279 } 280 if (key != null) { 281 System.out.print(">"); 282 } 283 284 if ((value != null) && (value.length() > 0)) { 285 String trimmedValue = value.trim(); 286 if (trimmedValue.length() > 60) { 287 trimmedValue = trimmedValue.substring(0, 57) + "..."; 288 } 289 if (trimmedValue.length() > 0) { 290 System.out.print(trimmedValue); 291 } 292 } 293 294 for (Enumeration e = children.elements() ; e.hasMoreElements() ;) { 295 XMLPackageDescription current = (XMLPackageDescription) e.nextElement(); 296 System.out.println(); 297 current.dump(indent + space); 298 } 299 if (children.size() > 0) { 300 System.out.println(); 301 System.out.print(indent); 302 } 303 if (key != null) { 304 System.out.print("</" + key + ">"); 305 } 306 } 307 } 308