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