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