• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2006 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.internal.util;
18 
19 import android.util.Xml;
20 
21 import org.xmlpull.v1.XmlPullParser;
22 import org.xmlpull.v1.XmlPullParserException;
23 import org.xmlpull.v1.XmlSerializer;
24 
25 import java.io.IOException;
26 import java.io.InputStream;
27 import java.io.OutputStream;
28 import java.net.ProtocolException;
29 import java.util.ArrayList;
30 import java.util.HashMap;
31 import java.util.HashSet;
32 import java.util.Iterator;
33 import java.util.List;
34 import java.util.Map;
35 import java.util.Set;
36 
37 /** {@hide} */
38 public class XmlUtils {
39 
skipCurrentTag(XmlPullParser parser)40     public static void skipCurrentTag(XmlPullParser parser)
41             throws XmlPullParserException, IOException {
42         int outerDepth = parser.getDepth();
43         int type;
44         while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
45                && (type != XmlPullParser.END_TAG
46                        || parser.getDepth() > outerDepth)) {
47         }
48     }
49 
50     public static final int
convertValueToList(CharSequence value, String[] options, int defaultValue)51     convertValueToList(CharSequence value, String[] options, int defaultValue)
52     {
53         if (null != value) {
54             for (int i = 0; i < options.length; i++) {
55                 if (value.equals(options[i]))
56                     return i;
57             }
58         }
59 
60         return defaultValue;
61     }
62 
63     public static final boolean
convertValueToBoolean(CharSequence value, boolean defaultValue)64     convertValueToBoolean(CharSequence value, boolean defaultValue)
65     {
66         boolean result = false;
67 
68         if (null == value)
69             return defaultValue;
70 
71         if (value.equals("1")
72         ||  value.equals("true")
73         ||  value.equals("TRUE"))
74             result = true;
75 
76         return result;
77     }
78 
79     public static final int
convertValueToInt(CharSequence charSeq, int defaultValue)80     convertValueToInt(CharSequence charSeq, int defaultValue)
81     {
82         if (null == charSeq)
83             return defaultValue;
84 
85         String nm = charSeq.toString();
86 
87         // XXX This code is copied from Integer.decode() so we don't
88         // have to instantiate an Integer!
89 
90         int value;
91         int sign = 1;
92         int index = 0;
93         int len = nm.length();
94         int base = 10;
95 
96         if ('-' == nm.charAt(0)) {
97             sign = -1;
98             index++;
99         }
100 
101         if ('0' == nm.charAt(index)) {
102             //  Quick check for a zero by itself
103             if (index == (len - 1))
104                 return 0;
105 
106             char    c = nm.charAt(index + 1);
107 
108             if ('x' == c || 'X' == c) {
109                 index += 2;
110                 base = 16;
111             } else {
112                 index++;
113                 base = 8;
114             }
115         }
116         else if ('#' == nm.charAt(index))
117         {
118             index++;
119             base = 16;
120         }
121 
122         return Integer.parseInt(nm.substring(index), base) * sign;
123     }
124 
convertValueToUnsignedInt(String value, int defaultValue)125     public static int convertValueToUnsignedInt(String value, int defaultValue) {
126         if (null == value) {
127             return defaultValue;
128         }
129 
130         return parseUnsignedIntAttribute(value);
131     }
132 
parseUnsignedIntAttribute(CharSequence charSeq)133     public static int parseUnsignedIntAttribute(CharSequence charSeq) {
134         String  value = charSeq.toString();
135 
136         long    bits;
137         int     index = 0;
138         int     len = value.length();
139         int     base = 10;
140 
141         if ('0' == value.charAt(index)) {
142             //  Quick check for zero by itself
143             if (index == (len - 1))
144                 return 0;
145 
146             char    c = value.charAt(index + 1);
147 
148             if ('x' == c || 'X' == c) {     //  check for hex
149                 index += 2;
150                 base = 16;
151             } else {                        //  check for octal
152                 index++;
153                 base = 8;
154             }
155         } else if ('#' == value.charAt(index)) {
156             index++;
157             base = 16;
158         }
159 
160         return (int) Long.parseLong(value.substring(index), base);
161     }
162 
163     /**
164      * Flatten a Map into an output stream as XML.  The map can later be
165      * read back with readMapXml().
166      *
167      * @param val The map to be flattened.
168      * @param out Where to write the XML data.
169      *
170      * @see #writeMapXml(Map, String, XmlSerializer)
171      * @see #writeListXml
172      * @see #writeValueXml
173      * @see #readMapXml
174      */
writeMapXml(Map val, OutputStream out)175     public static final void writeMapXml(Map val, OutputStream out)
176             throws XmlPullParserException, java.io.IOException {
177         XmlSerializer serializer = new FastXmlSerializer();
178         serializer.setOutput(out, "utf-8");
179         serializer.startDocument(null, true);
180         serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
181         writeMapXml(val, null, serializer);
182         serializer.endDocument();
183     }
184 
185     /**
186      * Flatten a List into an output stream as XML.  The list can later be
187      * read back with readListXml().
188      *
189      * @param val The list to be flattened.
190      * @param out Where to write the XML data.
191      *
192      * @see #writeListXml(List, String, XmlSerializer)
193      * @see #writeMapXml
194      * @see #writeValueXml
195      * @see #readListXml
196      */
writeListXml(List val, OutputStream out)197     public static final void writeListXml(List val, OutputStream out)
198     throws XmlPullParserException, java.io.IOException
199     {
200         XmlSerializer serializer = Xml.newSerializer();
201         serializer.setOutput(out, "utf-8");
202         serializer.startDocument(null, true);
203         serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
204         writeListXml(val, null, serializer);
205         serializer.endDocument();
206     }
207 
208     /**
209      * Flatten a Map into an XmlSerializer.  The map can later be read back
210      * with readThisMapXml().
211      *
212      * @param val The map to be flattened.
213      * @param name Name attribute to include with this list's tag, or null for
214      *             none.
215      * @param out XmlSerializer to write the map into.
216      *
217      * @see #writeMapXml(Map, OutputStream)
218      * @see #writeListXml
219      * @see #writeValueXml
220      * @see #readMapXml
221      */
writeMapXml(Map val, String name, XmlSerializer out)222     public static final void writeMapXml(Map val, String name, XmlSerializer out)
223     throws XmlPullParserException, java.io.IOException
224     {
225         if (val == null) {
226             out.startTag(null, "null");
227             out.endTag(null, "null");
228             return;
229         }
230 
231         Set s = val.entrySet();
232         Iterator i = s.iterator();
233 
234         out.startTag(null, "map");
235         if (name != null) {
236             out.attribute(null, "name", name);
237         }
238 
239         while (i.hasNext()) {
240             Map.Entry e = (Map.Entry)i.next();
241             writeValueXml(e.getValue(), (String)e.getKey(), out);
242         }
243 
244         out.endTag(null, "map");
245     }
246 
247     /**
248      * Flatten a List into an XmlSerializer.  The list can later be read back
249      * with readThisListXml().
250      *
251      * @param val The list to be flattened.
252      * @param name Name attribute to include with this list's tag, or null for
253      *             none.
254      * @param out XmlSerializer to write the list into.
255      *
256      * @see #writeListXml(List, OutputStream)
257      * @see #writeMapXml
258      * @see #writeValueXml
259      * @see #readListXml
260      */
writeListXml(List val, String name, XmlSerializer out)261     public static final void writeListXml(List val, String name, XmlSerializer out)
262     throws XmlPullParserException, java.io.IOException
263     {
264         if (val == null) {
265             out.startTag(null, "null");
266             out.endTag(null, "null");
267             return;
268         }
269 
270         out.startTag(null, "list");
271         if (name != null) {
272             out.attribute(null, "name", name);
273         }
274 
275         int N = val.size();
276         int i=0;
277         while (i < N) {
278             writeValueXml(val.get(i), null, out);
279             i++;
280         }
281 
282         out.endTag(null, "list");
283     }
284 
writeSetXml(Set val, String name, XmlSerializer out)285     public static final void writeSetXml(Set val, String name, XmlSerializer out)
286             throws XmlPullParserException, java.io.IOException {
287         if (val == null) {
288             out.startTag(null, "null");
289             out.endTag(null, "null");
290             return;
291         }
292 
293         out.startTag(null, "set");
294         if (name != null) {
295             out.attribute(null, "name", name);
296         }
297 
298         for (Object v : val) {
299             writeValueXml(v, null, out);
300         }
301 
302         out.endTag(null, "set");
303     }
304 
305     /**
306      * Flatten a byte[] into an XmlSerializer.  The list can later be read back
307      * with readThisByteArrayXml().
308      *
309      * @param val The byte array to be flattened.
310      * @param name Name attribute to include with this array's tag, or null for
311      *             none.
312      * @param out XmlSerializer to write the array into.
313      *
314      * @see #writeMapXml
315      * @see #writeValueXml
316      */
writeByteArrayXml(byte[] val, String name, XmlSerializer out)317     public static final void writeByteArrayXml(byte[] val, String name,
318             XmlSerializer out)
319             throws XmlPullParserException, java.io.IOException {
320 
321         if (val == null) {
322             out.startTag(null, "null");
323             out.endTag(null, "null");
324             return;
325         }
326 
327         out.startTag(null, "byte-array");
328         if (name != null) {
329             out.attribute(null, "name", name);
330         }
331 
332         final int N = val.length;
333         out.attribute(null, "num", Integer.toString(N));
334 
335         StringBuilder sb = new StringBuilder(val.length*2);
336         for (int i=0; i<N; i++) {
337             int b = val[i];
338             int h = b>>4;
339             sb.append(h >= 10 ? ('a'+h-10) : ('0'+h));
340             h = b&0xff;
341             sb.append(h >= 10 ? ('a'+h-10) : ('0'+h));
342         }
343 
344         out.text(sb.toString());
345 
346         out.endTag(null, "byte-array");
347     }
348 
349     /**
350      * Flatten an int[] into an XmlSerializer.  The list can later be read back
351      * with readThisIntArrayXml().
352      *
353      * @param val The int array to be flattened.
354      * @param name Name attribute to include with this array's tag, or null for
355      *             none.
356      * @param out XmlSerializer to write the array into.
357      *
358      * @see #writeMapXml
359      * @see #writeValueXml
360      * @see #readThisIntArrayXml
361      */
writeIntArrayXml(int[] val, String name, XmlSerializer out)362     public static final void writeIntArrayXml(int[] val, String name,
363             XmlSerializer out)
364             throws XmlPullParserException, java.io.IOException {
365 
366         if (val == null) {
367             out.startTag(null, "null");
368             out.endTag(null, "null");
369             return;
370         }
371 
372         out.startTag(null, "int-array");
373         if (name != null) {
374             out.attribute(null, "name", name);
375         }
376 
377         final int N = val.length;
378         out.attribute(null, "num", Integer.toString(N));
379 
380         for (int i=0; i<N; i++) {
381             out.startTag(null, "item");
382             out.attribute(null, "value", Integer.toString(val[i]));
383             out.endTag(null, "item");
384         }
385 
386         out.endTag(null, "int-array");
387     }
388 
389     /**
390      * Flatten an object's value into an XmlSerializer.  The value can later
391      * be read back with readThisValueXml().
392      *
393      * Currently supported value types are: null, String, Integer, Long,
394      * Float, Double Boolean, Map, List.
395      *
396      * @param v The object to be flattened.
397      * @param name Name attribute to include with this value's tag, or null
398      *             for none.
399      * @param out XmlSerializer to write the object into.
400      *
401      * @see #writeMapXml
402      * @see #writeListXml
403      * @see #readValueXml
404      */
writeValueXml(Object v, String name, XmlSerializer out)405     public static final void writeValueXml(Object v, String name, XmlSerializer out)
406     throws XmlPullParserException, java.io.IOException
407     {
408         String typeStr;
409         if (v == null) {
410             out.startTag(null, "null");
411             if (name != null) {
412                 out.attribute(null, "name", name);
413             }
414             out.endTag(null, "null");
415             return;
416         } else if (v instanceof String) {
417             out.startTag(null, "string");
418             if (name != null) {
419                 out.attribute(null, "name", name);
420             }
421             out.text(v.toString());
422             out.endTag(null, "string");
423             return;
424         } else if (v instanceof Integer) {
425             typeStr = "int";
426         } else if (v instanceof Long) {
427             typeStr = "long";
428         } else if (v instanceof Float) {
429             typeStr = "float";
430         } else if (v instanceof Double) {
431             typeStr = "double";
432         } else if (v instanceof Boolean) {
433             typeStr = "boolean";
434         } else if (v instanceof byte[]) {
435             writeByteArrayXml((byte[])v, name, out);
436             return;
437         } else if (v instanceof int[]) {
438             writeIntArrayXml((int[])v, name, out);
439             return;
440         } else if (v instanceof Map) {
441             writeMapXml((Map)v, name, out);
442             return;
443         } else if (v instanceof List) {
444             writeListXml((List)v, name, out);
445             return;
446         } else if (v instanceof Set) {
447             writeSetXml((Set)v, name, out);
448             return;
449         } else if (v instanceof CharSequence) {
450             // XXX This is to allow us to at least write something if
451             // we encounter styled text...  but it means we will drop all
452             // of the styling information. :(
453             out.startTag(null, "string");
454             if (name != null) {
455                 out.attribute(null, "name", name);
456             }
457             out.text(v.toString());
458             out.endTag(null, "string");
459             return;
460         } else {
461             throw new RuntimeException("writeValueXml: unable to write value " + v);
462         }
463 
464         out.startTag(null, typeStr);
465         if (name != null) {
466             out.attribute(null, "name", name);
467         }
468         out.attribute(null, "value", v.toString());
469         out.endTag(null, typeStr);
470     }
471 
472     /**
473      * Read a HashMap from an InputStream containing XML.  The stream can
474      * previously have been written by writeMapXml().
475      *
476      * @param in The InputStream from which to read.
477      *
478      * @return HashMap The resulting map.
479      *
480      * @see #readListXml
481      * @see #readValueXml
482      * @see #readThisMapXml
483      * #see #writeMapXml
484      */
readMapXml(InputStream in)485     public static final HashMap readMapXml(InputStream in)
486     throws XmlPullParserException, java.io.IOException
487     {
488         XmlPullParser   parser = Xml.newPullParser();
489         parser.setInput(in, null);
490         return (HashMap)readValueXml(parser, new String[1]);
491     }
492 
493     /**
494      * Read an ArrayList from an InputStream containing XML.  The stream can
495      * previously have been written by writeListXml().
496      *
497      * @param in The InputStream from which to read.
498      *
499      * @return ArrayList The resulting list.
500      *
501      * @see #readMapXml
502      * @see #readValueXml
503      * @see #readThisListXml
504      * @see #writeListXml
505      */
readListXml(InputStream in)506     public static final ArrayList readListXml(InputStream in)
507     throws XmlPullParserException, java.io.IOException
508     {
509         XmlPullParser   parser = Xml.newPullParser();
510         parser.setInput(in, null);
511         return (ArrayList)readValueXml(parser, new String[1]);
512     }
513 
514 
515     /**
516      * Read a HashSet from an InputStream containing XML. The stream can
517      * previously have been written by writeSetXml().
518      *
519      * @param in The InputStream from which to read.
520      *
521      * @return HashSet The resulting set.
522      *
523      * @throws XmlPullParserException
524      * @throws java.io.IOException
525      *
526      * @see #readValueXml
527      * @see #readThisSetXml
528      * @see #writeSetXml
529      */
readSetXml(InputStream in)530     public static final HashSet readSetXml(InputStream in)
531             throws XmlPullParserException, java.io.IOException {
532         XmlPullParser parser = Xml.newPullParser();
533         parser.setInput(in, null);
534         return (HashSet) readValueXml(parser, new String[1]);
535     }
536 
537     /**
538      * Read a HashMap object from an XmlPullParser.  The XML data could
539      * previously have been generated by writeMapXml().  The XmlPullParser
540      * must be positioned <em>after</em> the tag that begins the map.
541      *
542      * @param parser The XmlPullParser from which to read the map data.
543      * @param endTag Name of the tag that will end the map, usually "map".
544      * @param name An array of one string, used to return the name attribute
545      *             of the map's tag.
546      *
547      * @return HashMap The newly generated map.
548      *
549      * @see #readMapXml
550      */
readThisMapXml(XmlPullParser parser, String endTag, String[] name)551     public static final HashMap readThisMapXml(XmlPullParser parser, String endTag, String[] name)
552     throws XmlPullParserException, java.io.IOException
553     {
554         HashMap map = new HashMap();
555 
556         int eventType = parser.getEventType();
557         do {
558             if (eventType == parser.START_TAG) {
559                 Object val = readThisValueXml(parser, name);
560                 if (name[0] != null) {
561                     //System.out.println("Adding to map: " + name + " -> " + val);
562                     map.put(name[0], val);
563                 } else {
564                     throw new XmlPullParserException(
565                         "Map value without name attribute: " + parser.getName());
566                 }
567             } else if (eventType == parser.END_TAG) {
568                 if (parser.getName().equals(endTag)) {
569                     return map;
570                 }
571                 throw new XmlPullParserException(
572                     "Expected " + endTag + " end tag at: " + parser.getName());
573             }
574             eventType = parser.next();
575         } while (eventType != parser.END_DOCUMENT);
576 
577         throw new XmlPullParserException(
578             "Document ended before " + endTag + " end tag");
579     }
580 
581     /**
582      * Read an ArrayList object from an XmlPullParser.  The XML data could
583      * previously have been generated by writeListXml().  The XmlPullParser
584      * must be positioned <em>after</em> the tag that begins the list.
585      *
586      * @param parser The XmlPullParser from which to read the list data.
587      * @param endTag Name of the tag that will end the list, usually "list".
588      * @param name An array of one string, used to return the name attribute
589      *             of the list's tag.
590      *
591      * @return HashMap The newly generated list.
592      *
593      * @see #readListXml
594      */
readThisListXml(XmlPullParser parser, String endTag, String[] name)595     public static final ArrayList readThisListXml(XmlPullParser parser, String endTag, String[] name)
596     throws XmlPullParserException, java.io.IOException
597     {
598         ArrayList list = new ArrayList();
599 
600         int eventType = parser.getEventType();
601         do {
602             if (eventType == parser.START_TAG) {
603                 Object val = readThisValueXml(parser, name);
604                 list.add(val);
605                 //System.out.println("Adding to list: " + val);
606             } else if (eventType == parser.END_TAG) {
607                 if (parser.getName().equals(endTag)) {
608                     return list;
609                 }
610                 throw new XmlPullParserException(
611                     "Expected " + endTag + " end tag at: " + parser.getName());
612             }
613             eventType = parser.next();
614         } while (eventType != parser.END_DOCUMENT);
615 
616         throw new XmlPullParserException(
617             "Document ended before " + endTag + " end tag");
618     }
619 
620     /**
621      * Read a HashSet object from an XmlPullParser. The XML data could previously
622      * have been generated by writeSetXml(). The XmlPullParser must be positioned
623      * <em>after</em> the tag that begins the set.
624      *
625      * @param parser The XmlPullParser from which to read the set data.
626      * @param endTag Name of the tag that will end the set, usually "set".
627      * @param name An array of one string, used to return the name attribute
628      *             of the set's tag.
629      *
630      * @return HashSet The newly generated set.
631      *
632      * @throws XmlPullParserException
633      * @throws java.io.IOException
634      *
635      * @see #readSetXml
636      */
readThisSetXml(XmlPullParser parser, String endTag, String[] name)637     public static final HashSet readThisSetXml(XmlPullParser parser, String endTag, String[] name)
638             throws XmlPullParserException, java.io.IOException {
639         HashSet set = new HashSet();
640 
641         int eventType = parser.getEventType();
642         do {
643             if (eventType == parser.START_TAG) {
644                 Object val = readThisValueXml(parser, name);
645                 set.add(val);
646                 //System.out.println("Adding to set: " + val);
647             } else if (eventType == parser.END_TAG) {
648                 if (parser.getName().equals(endTag)) {
649                     return set;
650                 }
651                 throw new XmlPullParserException(
652                         "Expected " + endTag + " end tag at: " + parser.getName());
653             }
654             eventType = parser.next();
655         } while (eventType != parser.END_DOCUMENT);
656 
657         throw new XmlPullParserException(
658                 "Document ended before " + endTag + " end tag");
659     }
660 
661     /**
662      * Read an int[] object from an XmlPullParser.  The XML data could
663      * previously have been generated by writeIntArrayXml().  The XmlPullParser
664      * must be positioned <em>after</em> the tag that begins the list.
665      *
666      * @param parser The XmlPullParser from which to read the list data.
667      * @param endTag Name of the tag that will end the list, usually "list".
668      * @param name An array of one string, used to return the name attribute
669      *             of the list's tag.
670      *
671      * @return Returns a newly generated int[].
672      *
673      * @see #readListXml
674      */
readThisIntArrayXml(XmlPullParser parser, String endTag, String[] name)675     public static final int[] readThisIntArrayXml(XmlPullParser parser,
676             String endTag, String[] name)
677             throws XmlPullParserException, java.io.IOException {
678 
679         int num;
680         try {
681             num = Integer.parseInt(parser.getAttributeValue(null, "num"));
682         } catch (NullPointerException e) {
683             throw new XmlPullParserException(
684                     "Need num attribute in byte-array");
685         } catch (NumberFormatException e) {
686             throw new XmlPullParserException(
687                     "Not a number in num attribute in byte-array");
688         }
689 
690         int[] array = new int[num];
691         int i = 0;
692 
693         int eventType = parser.getEventType();
694         do {
695             if (eventType == parser.START_TAG) {
696                 if (parser.getName().equals("item")) {
697                     try {
698                         array[i] = Integer.parseInt(
699                                 parser.getAttributeValue(null, "value"));
700                     } catch (NullPointerException e) {
701                         throw new XmlPullParserException(
702                                 "Need value attribute in item");
703                     } catch (NumberFormatException e) {
704                         throw new XmlPullParserException(
705                                 "Not a number in value attribute in item");
706                     }
707                 } else {
708                     throw new XmlPullParserException(
709                             "Expected item tag at: " + parser.getName());
710                 }
711             } else if (eventType == parser.END_TAG) {
712                 if (parser.getName().equals(endTag)) {
713                     return array;
714                 } else if (parser.getName().equals("item")) {
715                     i++;
716                 } else {
717                     throw new XmlPullParserException(
718                         "Expected " + endTag + " end tag at: "
719                         + parser.getName());
720                 }
721             }
722             eventType = parser.next();
723         } while (eventType != parser.END_DOCUMENT);
724 
725         throw new XmlPullParserException(
726             "Document ended before " + endTag + " end tag");
727     }
728 
729     /**
730      * Read a flattened object from an XmlPullParser.  The XML data could
731      * previously have been written with writeMapXml(), writeListXml(), or
732      * writeValueXml().  The XmlPullParser must be positioned <em>at</em> the
733      * tag that defines the value.
734      *
735      * @param parser The XmlPullParser from which to read the object.
736      * @param name An array of one string, used to return the name attribute
737      *             of the value's tag.
738      *
739      * @return Object The newly generated value object.
740      *
741      * @see #readMapXml
742      * @see #readListXml
743      * @see #writeValueXml
744      */
readValueXml(XmlPullParser parser, String[] name)745     public static final Object readValueXml(XmlPullParser parser, String[] name)
746     throws XmlPullParserException, java.io.IOException
747     {
748         int eventType = parser.getEventType();
749         do {
750             if (eventType == parser.START_TAG) {
751                 return readThisValueXml(parser, name);
752             } else if (eventType == parser.END_TAG) {
753                 throw new XmlPullParserException(
754                     "Unexpected end tag at: " + parser.getName());
755             } else if (eventType == parser.TEXT) {
756                 throw new XmlPullParserException(
757                     "Unexpected text: " + parser.getText());
758             }
759             eventType = parser.next();
760         } while (eventType != parser.END_DOCUMENT);
761 
762         throw new XmlPullParserException(
763             "Unexpected end of document");
764     }
765 
readThisValueXml(XmlPullParser parser, String[] name)766     private static final Object readThisValueXml(XmlPullParser parser, String[] name)
767     throws XmlPullParserException, java.io.IOException
768     {
769         final String valueName = parser.getAttributeValue(null, "name");
770         final String tagName = parser.getName();
771 
772         //System.out.println("Reading this value tag: " + tagName + ", name=" + valueName);
773 
774         Object res;
775 
776         if (tagName.equals("null")) {
777             res = null;
778         } else if (tagName.equals("string")) {
779             String value = "";
780             int eventType;
781             while ((eventType = parser.next()) != parser.END_DOCUMENT) {
782                 if (eventType == parser.END_TAG) {
783                     if (parser.getName().equals("string")) {
784                         name[0] = valueName;
785                         //System.out.println("Returning value for " + valueName + ": " + value);
786                         return value;
787                     }
788                     throw new XmlPullParserException(
789                         "Unexpected end tag in <string>: " + parser.getName());
790                 } else if (eventType == parser.TEXT) {
791                     value += parser.getText();
792                 } else if (eventType == parser.START_TAG) {
793                     throw new XmlPullParserException(
794                         "Unexpected start tag in <string>: " + parser.getName());
795                 }
796             }
797             throw new XmlPullParserException(
798                 "Unexpected end of document in <string>");
799         } else if (tagName.equals("int")) {
800             res = Integer.parseInt(parser.getAttributeValue(null, "value"));
801         } else if (tagName.equals("long")) {
802             res = Long.valueOf(parser.getAttributeValue(null, "value"));
803         } else if (tagName.equals("float")) {
804             res = new Float(parser.getAttributeValue(null, "value"));
805         } else if (tagName.equals("double")) {
806             res = new Double(parser.getAttributeValue(null, "value"));
807         } else if (tagName.equals("boolean")) {
808             res = Boolean.valueOf(parser.getAttributeValue(null, "value"));
809         } else if (tagName.equals("int-array")) {
810             parser.next();
811             res = readThisIntArrayXml(parser, "int-array", name);
812             name[0] = valueName;
813             //System.out.println("Returning value for " + valueName + ": " + res);
814             return res;
815         } else if (tagName.equals("map")) {
816             parser.next();
817             res = readThisMapXml(parser, "map", name);
818             name[0] = valueName;
819             //System.out.println("Returning value for " + valueName + ": " + res);
820             return res;
821         } else if (tagName.equals("list")) {
822             parser.next();
823             res = readThisListXml(parser, "list", name);
824             name[0] = valueName;
825             //System.out.println("Returning value for " + valueName + ": " + res);
826             return res;
827         } else if (tagName.equals("set")) {
828             parser.next();
829             res = readThisSetXml(parser, "set", name);
830             name[0] = valueName;
831             //System.out.println("Returning value for " + valueName + ": " + res);
832             return res;
833         } else {
834             throw new XmlPullParserException(
835                 "Unknown tag: " + tagName);
836         }
837 
838         // Skip through to end tag.
839         int eventType;
840         while ((eventType = parser.next()) != parser.END_DOCUMENT) {
841             if (eventType == parser.END_TAG) {
842                 if (parser.getName().equals(tagName)) {
843                     name[0] = valueName;
844                     //System.out.println("Returning value for " + valueName + ": " + res);
845                     return res;
846                 }
847                 throw new XmlPullParserException(
848                     "Unexpected end tag in <" + tagName + ">: " + parser.getName());
849             } else if (eventType == parser.TEXT) {
850                 throw new XmlPullParserException(
851                 "Unexpected text in <" + tagName + ">: " + parser.getName());
852             } else if (eventType == parser.START_TAG) {
853                 throw new XmlPullParserException(
854                     "Unexpected start tag in <" + tagName + ">: " + parser.getName());
855             }
856         }
857         throw new XmlPullParserException(
858             "Unexpected end of document in <" + tagName + ">");
859     }
860 
beginDocument(XmlPullParser parser, String firstElementName)861     public static final void beginDocument(XmlPullParser parser, String firstElementName) throws XmlPullParserException, IOException
862     {
863         int type;
864         while ((type=parser.next()) != parser.START_TAG
865                    && type != parser.END_DOCUMENT) {
866             ;
867         }
868 
869         if (type != parser.START_TAG) {
870             throw new XmlPullParserException("No start tag found");
871         }
872 
873         if (!parser.getName().equals(firstElementName)) {
874             throw new XmlPullParserException("Unexpected start tag: found " + parser.getName() +
875                     ", expected " + firstElementName);
876         }
877     }
878 
nextElement(XmlPullParser parser)879     public static final void nextElement(XmlPullParser parser) throws XmlPullParserException, IOException
880     {
881         int type;
882         while ((type=parser.next()) != parser.START_TAG
883                    && type != parser.END_DOCUMENT) {
884             ;
885         }
886     }
887 
nextElementWithin(XmlPullParser parser, int outerDepth)888     public static boolean nextElementWithin(XmlPullParser parser, int outerDepth)
889             throws IOException, XmlPullParserException {
890         for (;;) {
891             int type = parser.next();
892             if (type == XmlPullParser.END_DOCUMENT
893                     || (type == XmlPullParser.END_TAG && parser.getDepth() == outerDepth)) {
894                 return false;
895             }
896             if (type == XmlPullParser.START_TAG
897                     && parser.getDepth() == outerDepth + 1) {
898                 return true;
899             }
900         }
901     }
902 
readIntAttribute(XmlPullParser in, String name)903     public static int readIntAttribute(XmlPullParser in, String name) throws IOException {
904         final String value = in.getAttributeValue(null, name);
905         try {
906             return Integer.parseInt(value);
907         } catch (NumberFormatException e) {
908             throw new ProtocolException("problem parsing " + name + "=" + value + " as int");
909         }
910     }
911 
writeIntAttribute(XmlSerializer out, String name, int value)912     public static void writeIntAttribute(XmlSerializer out, String name, int value)
913             throws IOException {
914         out.attribute(null, name, Integer.toString(value));
915     }
916 
readLongAttribute(XmlPullParser in, String name)917     public static long readLongAttribute(XmlPullParser in, String name) throws IOException {
918         final String value = in.getAttributeValue(null, name);
919         try {
920             return Long.parseLong(value);
921         } catch (NumberFormatException e) {
922             throw new ProtocolException("problem parsing " + name + "=" + value + " as long");
923         }
924     }
925 
writeLongAttribute(XmlSerializer out, String name, long value)926     public static void writeLongAttribute(XmlSerializer out, String name, long value)
927             throws IOException {
928         out.attribute(null, name, Long.toString(value));
929     }
930 
readBooleanAttribute(XmlPullParser in, String name)931     public static boolean readBooleanAttribute(XmlPullParser in, String name) {
932         final String value = in.getAttributeValue(null, name);
933         return Boolean.parseBoolean(value);
934     }
935 
writeBooleanAttribute(XmlSerializer out, String name, boolean value)936     public static void writeBooleanAttribute(XmlSerializer out, String name, boolean value)
937             throws IOException {
938         out.attribute(null, name, Boolean.toString(value));
939     }
940 }
941