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 com.sun.star.filter.config.tools.utils;
25 
26 //_______________________________________________
27 
28 import java.lang.*;
29 import java.util.*;
30 import java.io.*;
31 
32 //_______________________________________________
33 
34 /**
35  *  It provides some constant values and some static helper routines
36  *  which are necessary to work with a xml file - especially
37  *  the filter configuration.
38  *
39  *
40  */
41 public class XMLHelper
42 {
43     //___________________________________________
44     // public const
45 
46     /** it's a possible value of the xml attribute "oor:type" and identify an integer type. */
47     public static final java.lang.String XMLTYPE_INTEGER = "xs:int";
48 
49     /** it's a possible value of the xml attribute "oor:type" and identify an boolean type. */
50     public static final java.lang.String XMLTYPE_BOOLEAN = "xs:boolean";
51 
52     /** it's a possible value of the xml attribute "oor:type" and identify an string type. */
53     public static final java.lang.String XMLTYPE_STRING = "xs:string";
54 
55     /** it's a possible value of the xml attribute "oor:type" and identify an string list type. */
56     public static final java.lang.String XMLTYPE_STRINGLIST = "oor:string-list";
57 
58     /** it's a xml attribute, which specify a property name. */
59     public static final java.lang.String XMLATTRIB_OOR_NAME = "oor:name";
60 
61     /** it's a xml attribute, which specify a property type. */
62     public static final java.lang.String XMLATTRIB_OOR_TYPE = "oor:type";
63 
64     /** it's a xml attribute, which specify a list separator. */
65     public static final java.lang.String XMLATTRIB_OOR_SEPARATOR = "oor:separator";
66 
67     /** it's a xml attribute, which specify a localized value. */
68     public static final java.lang.String XMLATTRIB_OOR_LOCALIZED = "oor:localized";
69 
70     /** it's a xml attribute, which specify a merge operation for cfg layering. */
71     public static final java.lang.String XMLATTRIB_OOR_OP = "oor:op";
72 
73     /** can be used as value for XMLATTRIB_OOR_OP. */
74     public static final java.lang.String XMLATTRIB_OP_REPLACE = "replace";
75 
76     /** it's a xml attribute, which specify a locale value. */
77     public static final java.lang.String XMLATTRIB_XML_LANG = "xml:lang";
78 
79     /** it's the tag name of a <value ...> entry. */
80     public static final java.lang.String XMLTAG_VALUE = "value";
81 
82     /** it's the tag name of a <prop ...> entry. */
83     public static final java.lang.String XMLTAG_PROP = "prop";
84 
85     /** it's the tag name of a <node ...> entry. */
86     public static final java.lang.String XMLTAG_NODE = "node";
87 
88     //___________________________________________
89     // private const
90 
91     /** a static list of all possible separators, which can be used for configuration type string-list. */
92     private static final java.lang.String[] DELIMS = {" ", ",", ";", ".", ":", "-", "_", "#", "'", "+", "*", "~", "=", "?"};
93 
94     /** index of the default separator inside list DELIMS.
95      *  It's necessary to know such default separator; because it can
96      *  be suppressed as xml attribute of the corresponding value tag. */
97     private static final int DEFAULT_SEPARATOR = 0;
98 
99     //___________________________________________
100 
101     /** analyze the structures of the given XML node and
102      *  return a property set of all found sub nodes.
103      *
104      *  Such properties are organized as [name, value] pairs.
105      *  The type of a xml node will be detected automatically.
106      *  Following types are supported:
107      *      xs:int          => java.lang.Integer
108      *      xs:bool         => java.lang.Boolean
109      *      xs:string       => java.lang.String
110      *      oor:string-list => java.util.LinkedList[java.lang.String]
111      *      oor:set         => java.util.Vector[java.lang.Object]
112      *      oor:localized   => java.util.HashMap[java.lang.Object]
113      *
114      *  @param  aNode
115      *          points directly to the xml node, where we should analyze
116      *          the children nodes.
117      *
118      *  @return [java.util.HashMap]
119      *          contains every node name as key and its string(!) as value.
120      */
convertNodeToPropSet(org.w3c.dom.Node aNode)121     public static java.util.HashMap convertNodeToPropSet(org.w3c.dom.Node aNode)
122         throws java.lang.Exception
123     {
124         java.util.HashMap aPropSet = new java.util.HashMap();
125 
126         // get all child nodes, which seems to be properties
127         java.util.Vector      lChildNodes = XMLHelper.extractChildNodesByTagName(aNode, XMLTAG_PROP);
128         java.util.Enumeration en1         = lChildNodes.elements();
129         while(en1.hasMoreElements())
130         {
131             org.w3c.dom.Node aChildNode = (org.w3c.dom.Node)en1.nextElement();
132 
133             // read its name
134             java.lang.String sChildName = XMLHelper.extractNodeAttribByName(aChildNode, XMLATTRIB_OOR_NAME);
135             if (sChildName == null)
136                 throw new java.io.IOException("unsupported format: could not extract child node name");
137 
138             // read its type info
139             java.lang.String sChildType = XMLHelper.extractNodeAttribByName(aChildNode, XMLATTRIB_OOR_TYPE);
140             if (sChildType == null)
141             {
142                 /** Special patch:
143                  *      If an xml tag has no type information set ... we can restore it
144                  *      by analyzing the already read tag name :-)
145                  *      Not very nice - but it can help to read stripped xml files too. */
146                 sChildType = XMLHelper.getTypeForTag(sChildName);
147                 if (sChildType == null)
148                     throw new java.io.IOException("unsupported format: could not extract child node type");
149             }
150 
151             // read its value(s?)
152             java.util.Vector      lChildValues = XMLHelper.extractChildNodesByTagName(aChildNode, XMLTAG_VALUE);
153             java.util.Enumeration en2          = lChildValues.elements();
154             int                   nValue       = 0;
155             java.lang.Object      aValue       = null;
156             while(en2.hasMoreElements())
157             {
158                 org.w3c.dom.Node aValueNode   = (org.w3c.dom.Node)en2.nextElement();
159                 java.lang.String sChildLocale = XMLHelper.extractNodeAttribByName(aValueNode, XMLATTRIB_XML_LANG);
160                 boolean          bLocalized   = (sChildLocale != null);
161 
162                 ++nValue;
163 
164                 if (sChildType.equals(XMLTYPE_INTEGER))
165                 {
166                     if (!bLocalized && nValue > 1)
167                         throw new java.io.IOException("unsupported format: more then one value for non localized but atomic type detected");
168                     java.lang.String sData = ((org.w3c.dom.CharacterData)aValueNode.getFirstChild()).getData();
169                     aValue = new java.lang.Integer(sData);
170                 }
171                 else
172                 if (sChildType.equals(XMLTYPE_BOOLEAN))
173                 {
174                     if (!bLocalized && nValue > 1)
175                         throw new java.io.IOException("unsupported format: more then one value for non localized but atomic type detected");
176                     java.lang.String sData = ((org.w3c.dom.CharacterData)aValueNode.getFirstChild()).getData();
177                     aValue = new java.lang.Boolean(sData);
178                 }
179                 else
180                 if (sChildType.equals(XMLTYPE_STRING))
181                 {
182                     if (!bLocalized && nValue > 1)
183                         throw new java.io.IOException("unsupported format: more then one value for non localized but atomic type detected");
184 
185                     java.lang.String sData = ((org.w3c.dom.CharacterData)aValueNode.getFirstChild()).getData();
186 
187                     java.util.HashMap lLocalized = null;
188                     if (bLocalized)
189                     {
190                         if (aValue == null)
191                             aValue = new java.util.HashMap();
192                         lLocalized = (java.util.HashMap)aValue;
193                         lLocalized.put(sChildLocale, sData);
194                     }
195                     else
196                         aValue = sData;
197                 }
198                 else
199                 if (sChildType.equals(XMLTYPE_STRINGLIST))
200                 {
201                     if (!bLocalized && nValue > 1)
202                         throw new java.io.IOException("unsupported format: more then one value for non localized but atomic type detected");
203 
204                     java.lang.String sSeparator = XMLHelper.extractNodeAttribByName(aChildNode, XMLATTRIB_OOR_SEPARATOR);
205                     if (sSeparator == null)
206                         sSeparator = " ";
207 
208                     java.lang.String          sData      = ((org.w3c.dom.CharacterData)aValueNode.getFirstChild()).getData();
209                     sData = sData.replace('\t', ' ');
210                     sData = sData.replace('\n', ' ');
211                     java.util.StringTokenizer aTokenizer = new java.util.StringTokenizer(sData, sSeparator);
212                     java.util.Vector          lList      = new java.util.Vector();
213                     while(aTokenizer.hasMoreTokens())
214                     {
215                         java.lang.String sToken = (java.lang.String)aTokenizer.nextToken();
216                         sToken.trim();
217                         if (sToken.length() < 1)
218                             continue;
219                         lList.add(sToken);
220                     }
221                     aValue = lList;
222                 }
223 
224                 aPropSet.put(sChildName, aValue);
225             }
226         }
227 
228         return aPropSet;
229     }
230 
231     //___________________________________________
232 
getTypeForTag(java.lang.String sTag)233     private static java.lang.String getTypeForTag(java.lang.String sTag)
234     {
235         java.lang.String sType = null;
236 
237         if (
238             (sTag.equals(Cache.PROPNAME_DATA            )) ||
239             (sTag.equals(Cache.PROPNAME_NAME            )) ||
240             (sTag.equals(Cache.PROPNAME_UINAME          )) ||
241             (sTag.equals(Cache.PROPNAME_MEDIATYPE       )) ||
242             (sTag.equals(Cache.PROPNAME_CLIPBOARDFORMAT )) ||
243             (sTag.equals(Cache.PROPNAME_PREFERREDFILTER )) ||
244             (sTag.equals(Cache.PROPNAME_DETECTSERVICE   )) ||
245             (sTag.equals(Cache.PROPNAME_FRAMELOADER     )) ||
246             (sTag.equals(Cache.PROPNAME_CONTENTHANDLER  )) ||
247             (sTag.equals(Cache.PROPNAME_DOCUMENTSERVICE )) ||
248             (sTag.equals(Cache.PROPNAME_FILTERSERVICE   )) ||
249             (sTag.equals(Cache.PROPNAME_TEMPLATENAME    )) ||
250             (sTag.equals(Cache.PROPNAME_TYPE            )) ||
251             (sTag.equals(Cache.PROPNAME_UICOMPONENT     ))
252            )
253             sType = XMLTYPE_STRING;
254         else
255         if (
256             (sTag.equals(Cache.PROPNAME_PREFERRED   )) ||
257             (sTag.equals("Installed"                ))
258            )
259             sType = XMLTYPE_BOOLEAN;
260         else
261         if (
262             (sTag.equals(Cache.PROPNAME_UIORDER          )) ||
263             (sTag.equals(Cache.PROPNAME_DOCUMENTICONID   )) ||
264             (sTag.equals(Cache.PROPNAME_FILEFORMATVERSION))
265            )
266             sType = XMLTYPE_INTEGER;
267         else
268         if (
269             (sTag.equals(Cache.PROPNAME_URLPATTERN  )) ||
270             (sTag.equals(Cache.PROPNAME_EXTENSIONS  )) ||
271             (sTag.equals(Cache.PROPNAME_USERDATA    )) ||
272             (sTag.equals(Cache.PROPNAME_FLAGS       )) ||
273             (sTag.equals(Cache.PROPNAME_TYPES       ))
274            )
275             sType = XMLTYPE_STRINGLIST;
276 
277         if (sType == null)
278             System.err.println("getTypeForTag("+sTag+") = "+sType);
279 
280         return sType;
281     }
282 
283     //___________________________________________
284 
285     /** return a xml representation of the given property set.
286      *
287      *  @param  aPropSet
288      *          a set of <name,value> pairs, which should be translated to xml
289      *
290      *  @return [java.lang.String]
291      *          the xml string representation.
292      *
293      *  @throws [java.lang.Exception]
294      *          if anything during conversion fill fail.
295      */
convertPropSetToXML(java.util.HashMap aPropSet , int nPrettyTabs)296     public static java.lang.String convertPropSetToXML(java.util.HashMap aPropSet   ,
297                                                        int               nPrettyTabs)
298         throws java.lang.Exception
299     {
300         java.lang.StringBuffer sXML = new java.lang.StringBuffer(256);
301 
302         java.util.Iterator it1 = aPropSet.keySet().iterator();
303         while(it1.hasNext())
304         {
305             java.lang.String sProp = (java.lang.String)it1.next();
306             java.lang.Object aVal  = aPropSet.get(sProp);
307 
308             sProp = encodeHTMLSigns(sProp);
309 
310             // is it a simple type?
311             if (
312                 (aVal instanceof java.lang.Integer) ||
313                 (aVal instanceof java.lang.Boolean) ||
314                 (aVal instanceof java.lang.String )
315                )
316             {
317                 sXML.append(XMLHelper.convertSimpleObjectToXML(sProp, aVal, nPrettyTabs));
318                 continue;
319             }
320 
321             // no!
322             // is it a list value?
323             if (aVal instanceof java.util.Vector)
324             {
325                 java.util.Vector lVal = (java.util.Vector)aVal;
326                 sXML.append(XMLHelper.convertListToXML(sProp, lVal, nPrettyTabs));
327                 continue;
328             }
329 
330             // it's a localized value?
331             if (aVal instanceof java.util.HashMap)
332             {
333                 java.util.HashMap lVal = (java.util.HashMap)aVal;
334                 sXML.append(XMLHelper.convertLocalizedValueToXML(sProp, lVal, nPrettyTabs));
335                 continue;
336             }
337 
338             // unknown type!
339             java.lang.StringBuffer sMsg = new java.lang.StringBuffer(256);
340             sMsg.append("unsupported object type detected.");
341             sMsg.append("\ttype ?  : \""+sProp+"\" = "+aVal);
342             sMsg.append("\tprop set: \""+aPropSet          );
343             throw new java.lang.Exception(sMsg.toString());
344         }
345 
346         return sXML.toString();
347     }
348 
encodeHTMLSigns(java.lang.String sValue)349     public static java.lang.String encodeHTMLSigns(java.lang.String sValue)
350     {
351         java.lang.StringBuffer sSource      = new java.lang.StringBuffer(sValue);
352         java.lang.StringBuffer sDestination = new java.lang.StringBuffer(1000  );
353 
354         for (int i=0; i<sSource.length(); ++i)
355         {
356             char c = sSource.charAt(i);
357             if (c == '&')
358                 sDestination.append("&amp;");
359             else
360                 sDestination.append(c);
361         }
362 
363         java.lang.String sReturn = sDestination.toString();
364         if (!sReturn.equals(sValue))
365             System.out.println("encode \""+sValue+"\" => \""+sReturn+"\"");
366 
367         return sReturn;
368     }
369 
370     //___________________________________________
371 
372     /** return a xml representation of an atomic property.
373      *
374      *  Atomic property types are e.g. Integer, Boolean, String.
375      *
376      *  @param  sName
377      *          the name of the property.
378 
379      *  @param  aValue
380      *          the value of the property.
381      *
382      *  @param  nPrettyTabs
383      *          count of tab signs for pretty format the xml code :-)
384      *
385      *  @return [java.lang.String]
386      *          the xml string representation.
387      *
388      *  @throws [java.lang.Exception]
389      *          if anything during conversion fill fail.
390      */
convertSimpleObjectToXML(java.lang.String sName , java.lang.Object aValue , int nPrettyTabs)391     private static java.lang.String convertSimpleObjectToXML(java.lang.String sName      ,
392                                                              java.lang.Object aValue     ,
393                                                              int              nPrettyTabs)
394         throws java.lang.Exception
395     {
396         java.lang.StringBuffer sXML = new java.lang.StringBuffer(256);
397         for (int t=0; t<nPrettyTabs; ++t)
398             sXML.append("\t");
399 
400         if (aValue instanceof java.lang.Integer)
401         {
402             sXML.append("<prop "+XMLATTRIB_OOR_NAME+"=\""+sName+"\">");
403             sXML.append("<value>"+aValue.toString()+"</value>");
404             sXML.append("</prop>\n");
405         }
406         else
407         if (aValue instanceof java.lang.Boolean)
408         {
409             sXML.append("<prop "+XMLATTRIB_OOR_NAME+"=\""+sName+"\">");
410             sXML.append("<value>"+aValue.toString()+"</value>");
411             sXML.append("</prop>\n");
412         }
413         else
414         if (aValue instanceof java.lang.String)
415         {
416             sXML.append("<prop "+XMLATTRIB_OOR_NAME+"=\""+sName+"\"");
417             java.lang.String sValue = (java.lang.String)aValue;
418 
419             sValue = encodeHTMLSigns(sValue);
420 
421             if (sValue.length() < 1)
422                 sXML.append("/>\n");
423             else
424             {
425                 sXML.append("><value>"+sValue+"</value>");
426                 sXML.append("</prop>\n");
427             }
428         }
429         else
430         {
431             System.err.println("name  = "+sName);
432             System.err.println("value = "+aValue);
433             // ! can be used outside to detect - that it was not a simple type :-)
434             throw new java.lang.Exception("not an atomic type.");
435         }
436 
437         return sXML.toString();
438     }
439 
440     //___________________________________________
441 
442     /** return a xml representation of a string-list property.
443      *
444      *  @param  sName
445      *          the name of the property.
446 
447      *  @param  aValue
448      *          the value of the property.
449      *
450      *  @param  nPrettyTabs
451      *          count of tab signs for pretty format the xml code :-)
452      *
453      *  @return [java.lang.String]
454      *          the xml string representation.
455      *
456      *  @throws [java.lang.Exception]
457      *          if anything during conversion fill fail.
458      */
convertListToXML(java.lang.String sName , java.util.Vector aValue , int nPrettyTabs)459     private static java.lang.String convertListToXML(java.lang.String sName      ,
460                                                      java.util.Vector aValue     ,
461                                                      int              nPrettyTabs)
462         throws java.lang.Exception
463     {
464         java.lang.StringBuffer sXML = new java.lang.StringBuffer(256);
465 
466         for (int t=0; t<nPrettyTabs; ++t)
467             sXML.append("\t");
468 
469         int c = aValue.size();
470         if (c < 1)
471         {
472             sXML.append("<prop "+XMLATTRIB_OOR_NAME+"=\""+sName+"\"/>\n");
473             return sXML.toString();
474         }
475 
476         // step over all list items and add it to a string buffer
477         // Every item will be separated by a default separator "\n" first.
478         // Because "\n" is not a valid separator at all and can`t occur inside
479         // our list items. During we step over all items, we check if our current separator
480         // (we use a list of possible ones!) clash with an item.
481         // If it clash - we step to the next possible separator.
482         // If our list of possible separator values runs out of range we throw
483         // an exception :-) It's better then generating of wrong values
484         // If we found a valid separator - we use it to replace our "\n" place holder
485         // at the end of the following loop ...
486 
487         int                    d        = 0;
488         java.lang.StringBuffer sValBuff = new java.lang.StringBuffer(256);
489         for (int i=0; i<c; ++i)
490         {
491             // get the next list item
492             java.lang.Object aItem = aValue.get(i);
493             if (!(aItem instanceof java.lang.String))
494                 throw new java.lang.Exception("Current implementation supports string-list only!");
495 
496             java.lang.String sValue = (java.lang.String)aItem;
497 
498             sValue = encodeHTMLSigns(sValue);
499 
500             // append item with default separator, which isn't a valid separator at all
501             // But suppress adding of the separator if last element is reached.
502             sValBuff.append(sValue);
503             if (i<(c-1))
504                 sValBuff.append("\n");
505 
506             // check for delim clash
507             // Attention: An empty (means default) element forbid using
508             // of a whitespace character as separator!
509             while(true)
510             {
511                 if (d >= DELIMS.length)
512                     throw new java.lang.Exception("No valid separator found for a string list item.");
513                 if (sValue.length() < 1 && DELIMS[d].equals(" "))
514                 {
515                     ++d;
516                     continue;
517                 }
518                 if (sValue.indexOf(DELIMS[d]) != -1)
519                 {
520                     ++d;
521                     continue;
522                 }
523                 break;
524             }
525         }
526 
527         // replace default separator with right one
528         System.out.println("TODO: must be adapted to java 1.3 :-(");
529         System.exit(-1);
530 //TODO_JAVA        java.lang.String sListVal = sValBuff.toString().replaceAll("\n", DELIMS[d]);
531         java.lang.String sListVal = null;
532 
533         sXML.append("<prop "+XMLATTRIB_OOR_NAME+"=\""+sName+"\">");
534         if (d == DEFAULT_SEPARATOR)
535             sXML.append("<value>");
536         else
537             sXML.append("<value "+XMLATTRIB_OOR_SEPARATOR+"=\""+DELIMS[d]+"\">");
538         sXML.append(sListVal);
539         sXML.append("</value>");
540         sXML.append("</prop>\n");
541 
542         return sXML.toString();
543     }
544 
545     //___________________________________________
546 
547     /** return a xml representation of a localized property.
548      *
549      *  @param  sName
550      *          the name of the property.
551 
552      *  @param  aValue
553      *          the value of the property.
554      *
555      *  @param  nPrettyTabs
556      *          count of tab signs for pretty format the xml code :-)
557      *
558      *  @return [java.lang.String]
559      *          the xml string representation.
560      *
561      *  @throws [java.lang.Exception]
562      *          if anything during conversion fill fail.
563      */
convertLocalizedValueToXML(java.lang.String sName , java.util.HashMap aValue , int nPrettyTabs)564     private static java.lang.String convertLocalizedValueToXML(java.lang.String  sName      ,
565                                                                java.util.HashMap aValue     ,
566                                                                int               nPrettyTabs)
567         throws java.lang.Exception
568     {
569         java.lang.StringBuffer sXML = new java.lang.StringBuffer(256);
570 
571         int c = aValue.size();
572         if (c < 1)
573             throw new java.lang.Exception("Can't detect type of localized values. Because the given list is empty.");
574 
575         for (int t=0; t<nPrettyTabs; ++t)
576             sXML.append("\t");
577         // !Our localized values must be formatted at a deeper column
578         // then its property name!
579         ++nPrettyTabs;
580 
581         sXML.append("<prop "+XMLATTRIB_OOR_NAME+"=\""+sName+"\">\n");
582         java.util.Iterator it = aValue.keySet().iterator();
583 //        boolean bTypeKnown = false;
584         while(it.hasNext())
585         {
586             java.lang.String sLocale = (java.lang.String)it.next();
587             java.lang.Object aLocalizedValue = aValue.get(sLocale);
588 /*
589             if (!bTypeKnown)
590             {
591                 bTypeKnown = true;
592                 if (aLocalizedValue instanceof java.lang.Integer)
593                     sXML.append(" "+XMLATTRIB_OOR_TYPE+"=\""+XMLTYPE_INTEGER+"\">\n");
594                 else
595                 if (aLocalizedValue instanceof java.lang.Boolean)
596                     sXML.append(" "+XMLATTRIB_OOR_TYPE+"=\""+XMLTYPE_BOOLEAN+"\">\n");
597                 else
598                 if (aLocalizedValue instanceof java.lang.String)
599                     sXML.append(" "+XMLATTRIB_OOR_TYPE+"=\""+XMLTYPE_STRING+"\">\n");
600                 else
601                     throw new java.lang.Exception("Unsupported type for localized value detected.");
602             }
603 */
604             java.lang.String sLocValue = aLocalizedValue.toString();
605             java.lang.String sValue    = encodeHTMLSigns(sLocValue);
606 
607             for (int t=0; t<nPrettyTabs; ++t)
608                 sXML.append("\t");
609             sXML.append("<value "+XMLATTRIB_XML_LANG+"=\""+sLocale+"\">"+sValue+"</value>\n");
610         }
611         --nPrettyTabs;
612         for (int t=0; t<nPrettyTabs; ++t)
613             sXML.append("\t");
614         sXML.append("</prop>\n");
615 
616         return sXML.toString();
617     }
618 
619     //___________________________________________
620 
621     /** returns the value of an attribute of the given node.
622      *
623      *  If the given node represent an element node, may it supports some attributes.
624      *  Then this method search for an attribute with the specified name and return its value.
625      *  If nothing could be found ... or the given node isn't a suitable node ... it returns null.
626      *
627      *  @param  aNode
628      *          the node, which should be analyzed.
629      *
630      *  @param  sAttrib
631      *          name of the attribute, which should be searched.
632      *
633      *  @return The value of the specified attribute if it could be found at the given node.
634      *          Can be null if node doesn't support attributes or the searched one does not exist there.
635      */
extractNodeAttribByName(org.w3c.dom.Node aNode , java.lang.String sAttrib)636     public static java.lang.String extractNodeAttribByName(org.w3c.dom.Node aNode  ,
637                                                            java.lang.String sAttrib)
638         throws java.lang.Exception
639     {
640         // We can get valid attributes for element nodes only!
641         if (aNode.getNodeType() != org.w3c.dom.Node.ELEMENT_NODE)
642         {
643 //            System.err.println("not an element node");
644             return null;
645         }
646 
647         // may it supports attributes in general ... but doesn't have anyone really.
648         org.w3c.dom.NamedNodeMap lAttribs = aNode.getAttributes();
649         if (lAttribs==null)
650         {
651 //            System.err.println("no attributes at all");
652             return null;
653         }
654 
655         // step over the attribute list and search for the requested one
656         for (int i=0; i<lAttribs.getLength(); ++i)
657         {
658             org.w3c.dom.Attr aAttrib = (org.w3c.dom.Attr)lAttribs.item(i);
659             if (aAttrib.getName().equals(sAttrib))
660             {
661                 java.lang.String sValue = aAttrib.getValue();
662                 return sValue;
663             }
664         }
665 
666         // the searched attribute was not found!
667 //        System.err.println("required attribute \""+sAttrib+"\" does not exist for node ["+aNode.toString()+"]");
668         return null;
669     }
670 
671     //___________________________________________
672 
673     /** returns a list of childs, which are ELEMENT_NODES and have the right tag name.
674      *
675      *  It analyze the list of all possible child nodes. Only ELEMENT_NODES are candidates.
676      *  All other ones will be ignored. Further these element nodes are compared by it's tag
677      *  names. If it match with the specified value it's added to the return list.
678      *  So the return list includes references to the DOM tree nodes only, which are child
679      *  element nodes with the right tag name.
680      *
681      *  @param  aNode
682      *          provides access to the child nodes, which should be analyzed
683      *
684      *  @param  sTag
685      *          the searched tag name.
686      *
687      * @return  A list of child nodes, which are element nodes and have the right tag name.
688      */
extractChildNodesByTagName(org.w3c.dom.Node aNode, java.lang.String sTag )689     public static java.util.Vector extractChildNodesByTagName(org.w3c.dom.Node aNode,
690                                                                java.lang.String sTag )
691     {
692         // extract first all ELEMENT_NODES of he given parent
693         // Such nodes only provide tag names.
694         java.util.Vector lChilds          = XMLHelper.extractChildNodesByType(aNode,org.w3c.dom.Node.ELEMENT_NODE);
695         java.util.Vector lExtractedChilds = new java.util.Vector(lChilds.size());
696 
697         // step over the list and search for the right tags using the specified name
698         java.util.Enumeration en = lChilds.elements();
699         while (en.hasMoreElements())
700         {
701             org.w3c.dom.Node aChild = (org.w3c.dom.Node)en.nextElement();
702             if (aChild.getNodeName().equals(sTag))
703                 lExtractedChilds.add(aChild);
704         }
705 
706         // pack(!) and return the list
707         lExtractedChilds.trimToSize();
708         return lExtractedChilds;
709     }
710 
711     //___________________________________________
712 
713     /** returns a list of childs, which supports the right node type.
714      *
715      *  It analyzes the list of all possible child nodes. If a node represents the right node type
716      *  it is added to the return list. Otherwise it will be ignored.
717      *
718      *  @param  aNode
719      *          provides access to the list of possible children nodes.
720      *
721      *  @param  nType
722      *          represent the searched node type.
723      *          Possible values are constant fields of a org.w3c.dom.Node - e.g. org.w3c.dom.Node.ELEMENT_NODE.
724      *
725      * @return A list of child nodes, which provides the right node type.
726      */
extractChildNodesByType(org.w3c.dom.Node aNode, short nType)727     public static java.util.Vector extractChildNodesByType(org.w3c.dom.Node aNode,
728                                                            short            nType)
729     {
730         // get list of all possibe childs and reserve enough space for our return list
731         // Attention: A null pointer is not allowed for return! (means lExtractedChilds)
732         org.w3c.dom.NodeList lChilds          = aNode.getChildNodes();
733         int                  c                = lChilds.getLength();
734         java.util.Vector     lExtractedChilds = new java.util.Vector(c);
735 
736         // step of these childs and select only needed ones
737         for (int i=0; i<c; ++i)
738         {
739             org.w3c.dom.Node aChild = lChilds.item(i);
740             if (aChild.getNodeType() == nType)
741                 lExtractedChilds.add(aChild);
742         }
743 
744         // pack(!) and return the list
745         lExtractedChilds.trimToSize();
746         return lExtractedChilds;
747     }
748 
749     //___________________________________________
750 
751     /** generates an xml header, using parameters.
752      *
753      *  @param  sVersion
754      *          number of the xml version.
755      *
756      *  @param  sEncoding
757      *          used file encoding.
758      *
759      *  @param  sPath
760      *          name of the configuration root.
761      *
762      *  @param  sPackage
763      *          name of the configuration package.
764      *
765      *  @param  bLanguagepack
766      *          force creation of a special header,
767      *          which is needed for language packs only.
768      *
769      *  @return [java.lang.String]
770      *          the generated xml header.
771 
772 */
generateHeader(java.lang.String sVersion , java.lang.String sEncoding , java.lang.String sPath , java.lang.String sPackage , boolean bLanguagePack)773     public static java.lang.String generateHeader(java.lang.String sVersion     ,
774                                                   java.lang.String sEncoding    ,
775                                                   java.lang.String sPath        ,
776                                                   java.lang.String sPackage     ,
777                                                   boolean          bLanguagePack)
778     {
779         java.lang.StringBuffer sHeader = new java.lang.StringBuffer(256);
780 
781         if (bLanguagePack)
782         {
783             sHeader.append("<?xml version=\"");
784             sHeader.append(sVersion);
785             sHeader.append("\" encoding=\"");
786             sHeader.append(sEncoding);
787             sHeader.append("\"?>\n");
788             sHeader.append("<oor:component-data oor:package=\"");
789             sHeader.append(sPath);
790             sHeader.append("\" oor:name=\"");
791             sHeader.append(sPackage);
792             sHeader.append("\" xmlns:install=\"http://openoffice.org/2004/installation\"");
793             sHeader.append(" xmlns:oor=\"http://openoffice.org/2001/registry\"");
794             sHeader.append(" xmlns:xs=\"http://www.w3.org/2001/XMLSchema\"");
795             sHeader.append(" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\n");
796         }
797         else
798         {
799             sHeader.append("<?xml version=\"");
800             sHeader.append(sVersion);
801             sHeader.append("\" encoding=\"");
802             sHeader.append(sEncoding);
803             sHeader.append("\"?>\n");
804             sHeader.append("<oor:component-data xmlns:oor=\"http://openoffice.org/2001/registry\" xmlns:xs=\"http://www.w3.org/2001/XMLSchema\" oor:package=\"");
805             sHeader.append(sPath);
806             sHeader.append("\" oor:name=\"");
807             sHeader.append(sPackage);
808             sHeader.append("\">\n");
809         }
810 
811         return sHeader.toString();
812     }
813 
generateFooter()814     public static java.lang.String generateFooter()
815     {
816         return "</oor:component-data>\n";
817     }
818 }
819