• 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.graphics.Bitmap;
20 import android.graphics.BitmapFactory;
21 import android.graphics.Bitmap.CompressFormat;
22 import android.net.Uri;
23 import android.util.Base64;
24 import android.util.Xml;
25 
26 import org.xmlpull.v1.XmlPullParser;
27 import org.xmlpull.v1.XmlPullParserException;
28 import org.xmlpull.v1.XmlSerializer;
29 
30 import java.io.ByteArrayOutputStream;
31 import java.io.IOException;
32 import java.io.InputStream;
33 import java.io.OutputStream;
34 import java.net.ProtocolException;
35 import java.util.ArrayList;
36 import java.util.HashMap;
37 import java.util.HashSet;
38 import java.util.Iterator;
39 import java.util.List;
40 import java.util.Map;
41 import java.util.Set;
42 
43 /** {@hide} */
44 public class XmlUtils {
45 
skipCurrentTag(XmlPullParser parser)46     public static void skipCurrentTag(XmlPullParser parser)
47             throws XmlPullParserException, IOException {
48         int outerDepth = parser.getDepth();
49         int type;
50         while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
51                && (type != XmlPullParser.END_TAG
52                        || parser.getDepth() > outerDepth)) {
53         }
54     }
55 
56     public static final int
convertValueToList(CharSequence value, String[] options, int defaultValue)57     convertValueToList(CharSequence value, String[] options, int defaultValue)
58     {
59         if (null != value) {
60             for (int i = 0; i < options.length; i++) {
61                 if (value.equals(options[i]))
62                     return i;
63             }
64         }
65 
66         return defaultValue;
67     }
68 
69     public static final boolean
convertValueToBoolean(CharSequence value, boolean defaultValue)70     convertValueToBoolean(CharSequence value, boolean defaultValue)
71     {
72         boolean result = false;
73 
74         if (null == value)
75             return defaultValue;
76 
77         if (value.equals("1")
78         ||  value.equals("true")
79         ||  value.equals("TRUE"))
80             result = true;
81 
82         return result;
83     }
84 
85     public static final int
convertValueToInt(CharSequence charSeq, int defaultValue)86     convertValueToInt(CharSequence charSeq, int defaultValue)
87     {
88         if (null == charSeq)
89             return defaultValue;
90 
91         String nm = charSeq.toString();
92 
93         // XXX This code is copied from Integer.decode() so we don't
94         // have to instantiate an Integer!
95 
96         int value;
97         int sign = 1;
98         int index = 0;
99         int len = nm.length();
100         int base = 10;
101 
102         if ('-' == nm.charAt(0)) {
103             sign = -1;
104             index++;
105         }
106 
107         if ('0' == nm.charAt(index)) {
108             //  Quick check for a zero by itself
109             if (index == (len - 1))
110                 return 0;
111 
112             char    c = nm.charAt(index + 1);
113 
114             if ('x' == c || 'X' == c) {
115                 index += 2;
116                 base = 16;
117             } else {
118                 index++;
119                 base = 8;
120             }
121         }
122         else if ('#' == nm.charAt(index))
123         {
124             index++;
125             base = 16;
126         }
127 
128         return Integer.parseInt(nm.substring(index), base) * sign;
129     }
130 
convertValueToUnsignedInt(String value, int defaultValue)131     public static int convertValueToUnsignedInt(String value, int defaultValue) {
132         if (null == value) {
133             return defaultValue;
134         }
135 
136         return parseUnsignedIntAttribute(value);
137     }
138 
parseUnsignedIntAttribute(CharSequence charSeq)139     public static int parseUnsignedIntAttribute(CharSequence charSeq) {
140         String  value = charSeq.toString();
141 
142         long    bits;
143         int     index = 0;
144         int     len = value.length();
145         int     base = 10;
146 
147         if ('0' == value.charAt(index)) {
148             //  Quick check for zero by itself
149             if (index == (len - 1))
150                 return 0;
151 
152             char    c = value.charAt(index + 1);
153 
154             if ('x' == c || 'X' == c) {     //  check for hex
155                 index += 2;
156                 base = 16;
157             } else {                        //  check for octal
158                 index++;
159                 base = 8;
160             }
161         } else if ('#' == value.charAt(index)) {
162             index++;
163             base = 16;
164         }
165 
166         return (int) Long.parseLong(value.substring(index), base);
167     }
168 
169     /**
170      * Flatten a Map into an output stream as XML.  The map can later be
171      * read back with readMapXml().
172      *
173      * @param val The map to be flattened.
174      * @param out Where to write the XML data.
175      *
176      * @see #writeMapXml(Map, String, XmlSerializer)
177      * @see #writeListXml
178      * @see #writeValueXml
179      * @see #readMapXml
180      */
writeMapXml(Map val, OutputStream out)181     public static final void writeMapXml(Map val, OutputStream out)
182             throws XmlPullParserException, java.io.IOException {
183         XmlSerializer serializer = new FastXmlSerializer();
184         serializer.setOutput(out, "utf-8");
185         serializer.startDocument(null, true);
186         serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
187         writeMapXml(val, null, serializer);
188         serializer.endDocument();
189     }
190 
191     /**
192      * Flatten a List into an output stream as XML.  The list can later be
193      * read back with readListXml().
194      *
195      * @param val The list to be flattened.
196      * @param out Where to write the XML data.
197      *
198      * @see #writeListXml(List, String, XmlSerializer)
199      * @see #writeMapXml
200      * @see #writeValueXml
201      * @see #readListXml
202      */
writeListXml(List val, OutputStream out)203     public static final void writeListXml(List val, OutputStream out)
204     throws XmlPullParserException, java.io.IOException
205     {
206         XmlSerializer serializer = Xml.newSerializer();
207         serializer.setOutput(out, "utf-8");
208         serializer.startDocument(null, true);
209         serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
210         writeListXml(val, null, serializer);
211         serializer.endDocument();
212     }
213 
214     /**
215      * Flatten a Map into an XmlSerializer.  The map can later be read back
216      * with readThisMapXml().
217      *
218      * @param val The map to be flattened.
219      * @param name Name attribute to include with this list's tag, or null for
220      *             none.
221      * @param out XmlSerializer to write the map into.
222      *
223      * @see #writeMapXml(Map, OutputStream)
224      * @see #writeListXml
225      * @see #writeValueXml
226      * @see #readMapXml
227      */
writeMapXml(Map val, String name, XmlSerializer out)228     public static final void writeMapXml(Map val, String name, XmlSerializer out)
229             throws XmlPullParserException, java.io.IOException {
230         writeMapXml(val, name, out, null);
231     }
232 
233     /**
234      * Flatten a Map into an XmlSerializer.  The map can later be read back
235      * with readThisMapXml().
236      *
237      * @param val The map to be flattened.
238      * @param name Name attribute to include with this list's tag, or null for
239      *             none.
240      * @param out XmlSerializer to write the map into.
241      * @param callback Method to call when an Object type is not recognized.
242      *
243      * @see #writeMapXml(Map, OutputStream)
244      * @see #writeListXml
245      * @see #writeValueXml
246      * @see #readMapXml
247      *
248      * @hide
249      */
writeMapXml(Map val, String name, XmlSerializer out, WriteMapCallback callback)250     public static final void writeMapXml(Map val, String name, XmlSerializer out,
251             WriteMapCallback callback) throws XmlPullParserException, java.io.IOException {
252 
253         if (val == null) {
254             out.startTag(null, "null");
255             out.endTag(null, "null");
256             return;
257         }
258 
259         out.startTag(null, "map");
260         if (name != null) {
261             out.attribute(null, "name", name);
262         }
263 
264         writeMapXml(val, out, callback);
265 
266         out.endTag(null, "map");
267     }
268 
269     /**
270      * Flatten a Map into an XmlSerializer.  The map can later be read back
271      * with readThisMapXml(). This method presumes that the start tag and
272      * name attribute have already been written and does not write an end tag.
273      *
274      * @param val The map to be flattened.
275      * @param out XmlSerializer to write the map into.
276      *
277      * @see #writeMapXml(Map, OutputStream)
278      * @see #writeListXml
279      * @see #writeValueXml
280      * @see #readMapXml
281      *
282      * @hide
283      */
writeMapXml(Map val, XmlSerializer out, WriteMapCallback callback)284     public static final void writeMapXml(Map val, XmlSerializer out,
285             WriteMapCallback callback) throws XmlPullParserException, java.io.IOException {
286         if (val == null) {
287             return;
288         }
289 
290         Set s = val.entrySet();
291         Iterator i = s.iterator();
292 
293         while (i.hasNext()) {
294             Map.Entry e = (Map.Entry)i.next();
295             writeValueXml(e.getValue(), (String)e.getKey(), out, callback);
296         }
297     }
298 
299     /**
300      * Flatten a List into an XmlSerializer.  The list can later be read back
301      * with readThisListXml().
302      *
303      * @param val The list to be flattened.
304      * @param name Name attribute to include with this list's tag, or null for
305      *             none.
306      * @param out XmlSerializer to write the list into.
307      *
308      * @see #writeListXml(List, OutputStream)
309      * @see #writeMapXml
310      * @see #writeValueXml
311      * @see #readListXml
312      */
writeListXml(List val, String name, XmlSerializer out)313     public static final void writeListXml(List val, String name, XmlSerializer out)
314     throws XmlPullParserException, java.io.IOException
315     {
316         if (val == null) {
317             out.startTag(null, "null");
318             out.endTag(null, "null");
319             return;
320         }
321 
322         out.startTag(null, "list");
323         if (name != null) {
324             out.attribute(null, "name", name);
325         }
326 
327         int N = val.size();
328         int i=0;
329         while (i < N) {
330             writeValueXml(val.get(i), null, out);
331             i++;
332         }
333 
334         out.endTag(null, "list");
335     }
336 
writeSetXml(Set val, String name, XmlSerializer out)337     public static final void writeSetXml(Set val, String name, XmlSerializer out)
338             throws XmlPullParserException, java.io.IOException {
339         if (val == null) {
340             out.startTag(null, "null");
341             out.endTag(null, "null");
342             return;
343         }
344 
345         out.startTag(null, "set");
346         if (name != null) {
347             out.attribute(null, "name", name);
348         }
349 
350         for (Object v : val) {
351             writeValueXml(v, null, out);
352         }
353 
354         out.endTag(null, "set");
355     }
356 
357     /**
358      * Flatten a byte[] into an XmlSerializer.  The list can later be read back
359      * with readThisByteArrayXml().
360      *
361      * @param val The byte array to be flattened.
362      * @param name Name attribute to include with this array's tag, or null for
363      *             none.
364      * @param out XmlSerializer to write the array into.
365      *
366      * @see #writeMapXml
367      * @see #writeValueXml
368      */
writeByteArrayXml(byte[] val, String name, XmlSerializer out)369     public static final void writeByteArrayXml(byte[] val, String name,
370             XmlSerializer out)
371             throws XmlPullParserException, java.io.IOException {
372 
373         if (val == null) {
374             out.startTag(null, "null");
375             out.endTag(null, "null");
376             return;
377         }
378 
379         out.startTag(null, "byte-array");
380         if (name != null) {
381             out.attribute(null, "name", name);
382         }
383 
384         final int N = val.length;
385         out.attribute(null, "num", Integer.toString(N));
386 
387         StringBuilder sb = new StringBuilder(val.length*2);
388         for (int i=0; i<N; i++) {
389             int b = val[i];
390             int h = b>>4;
391             sb.append(h >= 10 ? ('a'+h-10) : ('0'+h));
392             h = b&0xff;
393             sb.append(h >= 10 ? ('a'+h-10) : ('0'+h));
394         }
395 
396         out.text(sb.toString());
397 
398         out.endTag(null, "byte-array");
399     }
400 
401     /**
402      * Flatten an int[] into an XmlSerializer.  The list can later be read back
403      * with readThisIntArrayXml().
404      *
405      * @param val The int array to be flattened.
406      * @param name Name attribute to include with this array's tag, or null for
407      *             none.
408      * @param out XmlSerializer to write the array into.
409      *
410      * @see #writeMapXml
411      * @see #writeValueXml
412      * @see #readThisIntArrayXml
413      */
writeIntArrayXml(int[] val, String name, XmlSerializer out)414     public static final void writeIntArrayXml(int[] val, String name,
415             XmlSerializer out)
416             throws XmlPullParserException, java.io.IOException {
417 
418         if (val == null) {
419             out.startTag(null, "null");
420             out.endTag(null, "null");
421             return;
422         }
423 
424         out.startTag(null, "int-array");
425         if (name != null) {
426             out.attribute(null, "name", name);
427         }
428 
429         final int N = val.length;
430         out.attribute(null, "num", Integer.toString(N));
431 
432         for (int i=0; i<N; i++) {
433             out.startTag(null, "item");
434             out.attribute(null, "value", Integer.toString(val[i]));
435             out.endTag(null, "item");
436         }
437 
438         out.endTag(null, "int-array");
439     }
440 
441     /**
442      * Flatten a long[] into an XmlSerializer.  The list can later be read back
443      * with readThisLongArrayXml().
444      *
445      * @param val The long array to be flattened.
446      * @param name Name attribute to include with this array's tag, or null for
447      *             none.
448      * @param out XmlSerializer to write the array into.
449      *
450      * @see #writeMapXml
451      * @see #writeValueXml
452      * @see #readThisIntArrayXml
453      */
writeLongArrayXml(long[] val, String name, XmlSerializer out)454     public static final void writeLongArrayXml(long[] val, String name, XmlSerializer out)
455             throws XmlPullParserException, java.io.IOException {
456 
457         if (val == null) {
458             out.startTag(null, "null");
459             out.endTag(null, "null");
460             return;
461         }
462 
463         out.startTag(null, "long-array");
464         if (name != null) {
465             out.attribute(null, "name", name);
466         }
467 
468         final int N = val.length;
469         out.attribute(null, "num", Integer.toString(N));
470 
471         for (int i=0; i<N; i++) {
472             out.startTag(null, "item");
473             out.attribute(null, "value", Long.toString(val[i]));
474             out.endTag(null, "item");
475         }
476 
477         out.endTag(null, "long-array");
478     }
479 
480     /**
481      * Flatten a double[] into an XmlSerializer.  The list can later be read back
482      * with readThisDoubleArrayXml().
483      *
484      * @param val The double array to be flattened.
485      * @param name Name attribute to include with this array's tag, or null for
486      *             none.
487      * @param out XmlSerializer to write the array into.
488      *
489      * @see #writeMapXml
490      * @see #writeValueXml
491      * @see #readThisIntArrayXml
492      */
writeDoubleArrayXml(double[] val, String name, XmlSerializer out)493     public static final void writeDoubleArrayXml(double[] val, String name, XmlSerializer out)
494             throws XmlPullParserException, java.io.IOException {
495 
496         if (val == null) {
497             out.startTag(null, "null");
498             out.endTag(null, "null");
499             return;
500         }
501 
502         out.startTag(null, "double-array");
503         if (name != null) {
504             out.attribute(null, "name", name);
505         }
506 
507         final int N = val.length;
508         out.attribute(null, "num", Integer.toString(N));
509 
510         for (int i=0; i<N; i++) {
511             out.startTag(null, "item");
512             out.attribute(null, "value", Double.toString(val[i]));
513             out.endTag(null, "item");
514         }
515 
516         out.endTag(null, "double-array");
517     }
518 
519     /**
520      * Flatten a String[] into an XmlSerializer.  The list can later be read back
521      * with readThisStringArrayXml().
522      *
523      * @param val The long array to be flattened.
524      * @param name Name attribute to include with this array's tag, or null for
525      *             none.
526      * @param out XmlSerializer to write the array into.
527      *
528      * @see #writeMapXml
529      * @see #writeValueXml
530      * @see #readThisIntArrayXml
531      */
writeStringArrayXml(String[] val, String name, XmlSerializer out)532     public static final void writeStringArrayXml(String[] val, String name, XmlSerializer out)
533             throws XmlPullParserException, java.io.IOException {
534 
535         if (val == null) {
536             out.startTag(null, "null");
537             out.endTag(null, "null");
538             return;
539         }
540 
541         out.startTag(null, "string-array");
542         if (name != null) {
543             out.attribute(null, "name", name);
544         }
545 
546         final int N = val.length;
547         out.attribute(null, "num", Integer.toString(N));
548 
549         for (int i=0; i<N; i++) {
550             out.startTag(null, "item");
551             out.attribute(null, "value", val[i]);
552             out.endTag(null, "item");
553         }
554 
555         out.endTag(null, "string-array");
556     }
557 
558     /**
559      * Flatten an object's value into an XmlSerializer.  The value can later
560      * be read back with readThisValueXml().
561      *
562      * Currently supported value types are: null, String, Integer, Long,
563      * Float, Double Boolean, Map, List.
564      *
565      * @param v The object to be flattened.
566      * @param name Name attribute to include with this value's tag, or null
567      *             for none.
568      * @param out XmlSerializer to write the object into.
569      *
570      * @see #writeMapXml
571      * @see #writeListXml
572      * @see #readValueXml
573      */
writeValueXml(Object v, String name, XmlSerializer out)574     public static final void writeValueXml(Object v, String name, XmlSerializer out)
575             throws XmlPullParserException, java.io.IOException {
576         writeValueXml(v, name, out, null);
577     }
578 
579     /**
580      * Flatten an object's value into an XmlSerializer.  The value can later
581      * be read back with readThisValueXml().
582      *
583      * Currently supported value types are: null, String, Integer, Long,
584      * Float, Double Boolean, Map, List.
585      *
586      * @param v The object to be flattened.
587      * @param name Name attribute to include with this value's tag, or null
588      *             for none.
589      * @param out XmlSerializer to write the object into.
590      * @param callback Handler for Object types not recognized.
591      *
592      * @see #writeMapXml
593      * @see #writeListXml
594      * @see #readValueXml
595      */
writeValueXml(Object v, String name, XmlSerializer out, WriteMapCallback callback)596     private static final void writeValueXml(Object v, String name, XmlSerializer out,
597             WriteMapCallback callback)  throws XmlPullParserException, java.io.IOException {
598         String typeStr;
599         if (v == null) {
600             out.startTag(null, "null");
601             if (name != null) {
602                 out.attribute(null, "name", name);
603             }
604             out.endTag(null, "null");
605             return;
606         } else if (v instanceof String) {
607             out.startTag(null, "string");
608             if (name != null) {
609                 out.attribute(null, "name", name);
610             }
611             out.text(v.toString());
612             out.endTag(null, "string");
613             return;
614         } else if (v instanceof Integer) {
615             typeStr = "int";
616         } else if (v instanceof Long) {
617             typeStr = "long";
618         } else if (v instanceof Float) {
619             typeStr = "float";
620         } else if (v instanceof Double) {
621             typeStr = "double";
622         } else if (v instanceof Boolean) {
623             typeStr = "boolean";
624         } else if (v instanceof byte[]) {
625             writeByteArrayXml((byte[])v, name, out);
626             return;
627         } else if (v instanceof int[]) {
628             writeIntArrayXml((int[])v, name, out);
629             return;
630         } else if (v instanceof long[]) {
631             writeLongArrayXml((long[])v, name, out);
632             return;
633         } else if (v instanceof double[]) {
634             writeDoubleArrayXml((double[])v, name, out);
635             return;
636         } else if (v instanceof String[]) {
637             writeStringArrayXml((String[])v, name, out);
638             return;
639         } else if (v instanceof Map) {
640             writeMapXml((Map)v, name, out);
641             return;
642         } else if (v instanceof List) {
643             writeListXml((List) v, name, out);
644             return;
645         } else if (v instanceof Set) {
646             writeSetXml((Set) v, name, out);
647             return;
648         } else if (v instanceof CharSequence) {
649             // XXX This is to allow us to at least write something if
650             // we encounter styled text...  but it means we will drop all
651             // of the styling information. :(
652             out.startTag(null, "string");
653             if (name != null) {
654                 out.attribute(null, "name", name);
655             }
656             out.text(v.toString());
657             out.endTag(null, "string");
658             return;
659         } else if (callback != null) {
660             callback.writeUnknownObject(v, name, out);
661             return;
662         } else {
663             throw new RuntimeException("writeValueXml: unable to write value " + v);
664         }
665 
666         out.startTag(null, typeStr);
667         if (name != null) {
668             out.attribute(null, "name", name);
669         }
670         out.attribute(null, "value", v.toString());
671         out.endTag(null, typeStr);
672     }
673 
674     /**
675      * Read a HashMap from an InputStream containing XML.  The stream can
676      * previously have been written by writeMapXml().
677      *
678      * @param in The InputStream from which to read.
679      *
680      * @return HashMap The resulting map.
681      *
682      * @see #readListXml
683      * @see #readValueXml
684      * @see #readThisMapXml
685      * #see #writeMapXml
686      */
687     @SuppressWarnings("unchecked")
readMapXml(InputStream in)688     public static final HashMap<String, ?> readMapXml(InputStream in)
689     throws XmlPullParserException, java.io.IOException
690     {
691         XmlPullParser   parser = Xml.newPullParser();
692         parser.setInput(in, null);
693         return (HashMap<String, ?>) readValueXml(parser, new String[1]);
694     }
695 
696     /**
697      * Read an ArrayList from an InputStream containing XML.  The stream can
698      * previously have been written by writeListXml().
699      *
700      * @param in The InputStream from which to read.
701      *
702      * @return ArrayList The resulting list.
703      *
704      * @see #readMapXml
705      * @see #readValueXml
706      * @see #readThisListXml
707      * @see #writeListXml
708      */
readListXml(InputStream in)709     public static final ArrayList readListXml(InputStream in)
710     throws XmlPullParserException, java.io.IOException
711     {
712         XmlPullParser   parser = Xml.newPullParser();
713         parser.setInput(in, null);
714         return (ArrayList)readValueXml(parser, new String[1]);
715     }
716 
717 
718     /**
719      * Read a HashSet from an InputStream containing XML. The stream can
720      * previously have been written by writeSetXml().
721      *
722      * @param in The InputStream from which to read.
723      *
724      * @return HashSet The resulting set.
725      *
726      * @throws XmlPullParserException
727      * @throws java.io.IOException
728      *
729      * @see #readValueXml
730      * @see #readThisSetXml
731      * @see #writeSetXml
732      */
readSetXml(InputStream in)733     public static final HashSet readSetXml(InputStream in)
734             throws XmlPullParserException, java.io.IOException {
735         XmlPullParser parser = Xml.newPullParser();
736         parser.setInput(in, null);
737         return (HashSet) readValueXml(parser, new String[1]);
738     }
739 
740     /**
741      * Read a HashMap object from an XmlPullParser.  The XML data could
742      * previously have been generated by writeMapXml().  The XmlPullParser
743      * must be positioned <em>after</em> the tag that begins the map.
744      *
745      * @param parser The XmlPullParser from which to read the map data.
746      * @param endTag Name of the tag that will end the map, usually "map".
747      * @param name An array of one string, used to return the name attribute
748      *             of the map's tag.
749      *
750      * @return HashMap The newly generated map.
751      *
752      * @see #readMapXml
753      */
readThisMapXml(XmlPullParser parser, String endTag, String[] name)754     public static final HashMap<String, ?> readThisMapXml(XmlPullParser parser, String endTag,
755             String[] name) throws XmlPullParserException, java.io.IOException {
756         return readThisMapXml(parser, endTag, name, null);
757     }
758 
759     /**
760      * Read a HashMap object from an XmlPullParser.  The XML data could
761      * previously have been generated by writeMapXml().  The XmlPullParser
762      * must be positioned <em>after</em> the tag that begins the map.
763      *
764      * @param parser The XmlPullParser from which to read the map data.
765      * @param endTag Name of the tag that will end the map, usually "map".
766      * @param name An array of one string, used to return the name attribute
767      *             of the map's tag.
768      *
769      * @return HashMap The newly generated map.
770      *
771      * @see #readMapXml
772      * @hide
773      */
readThisMapXml(XmlPullParser parser, String endTag, String[] name, ReadMapCallback callback)774     public static final HashMap<String, ?> readThisMapXml(XmlPullParser parser, String endTag,
775             String[] name, ReadMapCallback callback)
776             throws XmlPullParserException, java.io.IOException
777     {
778         HashMap<String, Object> map = new HashMap<String, Object>();
779 
780         int eventType = parser.getEventType();
781         do {
782             if (eventType == parser.START_TAG) {
783                 Object val = readThisValueXml(parser, name, callback);
784                 map.put(name[0], val);
785             } else if (eventType == parser.END_TAG) {
786                 if (parser.getName().equals(endTag)) {
787                     return map;
788                 }
789                 throw new XmlPullParserException(
790                     "Expected " + endTag + " end tag at: " + parser.getName());
791             }
792             eventType = parser.next();
793         } while (eventType != parser.END_DOCUMENT);
794 
795         throw new XmlPullParserException(
796             "Document ended before " + endTag + " end tag");
797     }
798 
799     /**
800      * Read an ArrayList object from an XmlPullParser.  The XML data could
801      * previously have been generated by writeListXml().  The XmlPullParser
802      * must be positioned <em>after</em> the tag that begins the list.
803      *
804      * @param parser The XmlPullParser from which to read the list data.
805      * @param endTag Name of the tag that will end the list, usually "list".
806      * @param name An array of one string, used to return the name attribute
807      *             of the list's tag.
808      *
809      * @return HashMap The newly generated list.
810      *
811      * @see #readListXml
812      */
readThisListXml(XmlPullParser parser, String endTag, String[] name)813     public static final ArrayList readThisListXml(XmlPullParser parser, String endTag,
814             String[] name) throws XmlPullParserException, java.io.IOException {
815         return readThisListXml(parser, endTag, name, null);
816     }
817 
818     /**
819      * Read an ArrayList object from an XmlPullParser.  The XML data could
820      * previously have been generated by writeListXml().  The XmlPullParser
821      * must be positioned <em>after</em> the tag that begins the list.
822      *
823      * @param parser The XmlPullParser from which to read the list data.
824      * @param endTag Name of the tag that will end the list, usually "list".
825      * @param name An array of one string, used to return the name attribute
826      *             of the list's tag.
827      *
828      * @return HashMap The newly generated list.
829      *
830      * @see #readListXml
831      */
readThisListXml(XmlPullParser parser, String endTag, String[] name, ReadMapCallback callback)832     private static final ArrayList readThisListXml(XmlPullParser parser, String endTag,
833             String[] name, ReadMapCallback callback)
834             throws XmlPullParserException, java.io.IOException {
835         ArrayList list = new ArrayList();
836 
837         int eventType = parser.getEventType();
838         do {
839             if (eventType == parser.START_TAG) {
840                 Object val = readThisValueXml(parser, name, callback);
841                 list.add(val);
842                 //System.out.println("Adding to list: " + val);
843             } else if (eventType == parser.END_TAG) {
844                 if (parser.getName().equals(endTag)) {
845                     return list;
846                 }
847                 throw new XmlPullParserException(
848                     "Expected " + endTag + " end tag at: " + parser.getName());
849             }
850             eventType = parser.next();
851         } while (eventType != parser.END_DOCUMENT);
852 
853         throw new XmlPullParserException(
854             "Document ended before " + endTag + " end tag");
855     }
856 
857     /**
858      * Read a HashSet object from an XmlPullParser. The XML data could previously
859      * have been generated by writeSetXml(). The XmlPullParser must be positioned
860      * <em>after</em> the tag that begins the set.
861      *
862      * @param parser The XmlPullParser from which to read the set data.
863      * @param endTag Name of the tag that will end the set, usually "set".
864      * @param name An array of one string, used to return the name attribute
865      *             of the set's tag.
866      *
867      * @return HashSet The newly generated set.
868      *
869      * @throws XmlPullParserException
870      * @throws java.io.IOException
871      *
872      * @see #readSetXml
873      */
readThisSetXml(XmlPullParser parser, String endTag, String[] name)874     public static final HashSet readThisSetXml(XmlPullParser parser, String endTag, String[] name)
875             throws XmlPullParserException, java.io.IOException {
876         return readThisSetXml(parser, endTag, name, null);
877     }
878 
879     /**
880      * Read a HashSet object from an XmlPullParser. The XML data could previously
881      * have been generated by writeSetXml(). The XmlPullParser must be positioned
882      * <em>after</em> the tag that begins the set.
883      *
884      * @param parser The XmlPullParser from which to read the set data.
885      * @param endTag Name of the tag that will end the set, usually "set".
886      * @param name An array of one string, used to return the name attribute
887      *             of the set's tag.
888      *
889      * @return HashSet The newly generated set.
890      *
891      * @throws XmlPullParserException
892      * @throws java.io.IOException
893      *
894      * @see #readSetXml
895      * @hide
896      */
readThisSetXml(XmlPullParser parser, String endTag, String[] name, ReadMapCallback callback)897     private static final HashSet readThisSetXml(XmlPullParser parser, String endTag, String[] name,
898             ReadMapCallback callback) throws XmlPullParserException, java.io.IOException {
899         HashSet set = new HashSet();
900 
901         int eventType = parser.getEventType();
902         do {
903             if (eventType == parser.START_TAG) {
904                 Object val = readThisValueXml(parser, name, callback);
905                 set.add(val);
906                 //System.out.println("Adding to set: " + val);
907             } else if (eventType == parser.END_TAG) {
908                 if (parser.getName().equals(endTag)) {
909                     return set;
910                 }
911                 throw new XmlPullParserException(
912                         "Expected " + endTag + " end tag at: " + parser.getName());
913             }
914             eventType = parser.next();
915         } while (eventType != parser.END_DOCUMENT);
916 
917         throw new XmlPullParserException(
918                 "Document ended before " + endTag + " end tag");
919     }
920 
921     /**
922      * Read an int[] object from an XmlPullParser.  The XML data could
923      * previously have been generated by writeIntArrayXml().  The XmlPullParser
924      * must be positioned <em>after</em> the tag that begins the list.
925      *
926      * @param parser The XmlPullParser from which to read the list data.
927      * @param endTag Name of the tag that will end the list, usually "list".
928      * @param name An array of one string, used to return the name attribute
929      *             of the list's tag.
930      *
931      * @return Returns a newly generated int[].
932      *
933      * @see #readListXml
934      */
readThisIntArrayXml(XmlPullParser parser, String endTag, String[] name)935     public static final int[] readThisIntArrayXml(XmlPullParser parser,
936             String endTag, String[] name)
937             throws XmlPullParserException, java.io.IOException {
938 
939         int num;
940         try {
941             num = Integer.parseInt(parser.getAttributeValue(null, "num"));
942         } catch (NullPointerException e) {
943             throw new XmlPullParserException(
944                     "Need num attribute in byte-array");
945         } catch (NumberFormatException e) {
946             throw new XmlPullParserException(
947                     "Not a number in num attribute in byte-array");
948         }
949         parser.next();
950 
951         int[] array = new int[num];
952         int i = 0;
953 
954         int eventType = parser.getEventType();
955         do {
956             if (eventType == parser.START_TAG) {
957                 if (parser.getName().equals("item")) {
958                     try {
959                         array[i] = Integer.parseInt(
960                                 parser.getAttributeValue(null, "value"));
961                     } catch (NullPointerException e) {
962                         throw new XmlPullParserException(
963                                 "Need value attribute in item");
964                     } catch (NumberFormatException e) {
965                         throw new XmlPullParserException(
966                                 "Not a number in value attribute in item");
967                     }
968                 } else {
969                     throw new XmlPullParserException(
970                             "Expected item tag at: " + parser.getName());
971                 }
972             } else if (eventType == parser.END_TAG) {
973                 if (parser.getName().equals(endTag)) {
974                     return array;
975                 } else if (parser.getName().equals("item")) {
976                     i++;
977                 } else {
978                     throw new XmlPullParserException(
979                         "Expected " + endTag + " end tag at: "
980                         + parser.getName());
981                 }
982             }
983             eventType = parser.next();
984         } while (eventType != parser.END_DOCUMENT);
985 
986         throw new XmlPullParserException(
987             "Document ended before " + endTag + " end tag");
988     }
989 
990     /**
991      * Read a long[] object from an XmlPullParser.  The XML data could
992      * previously have been generated by writeLongArrayXml().  The XmlPullParser
993      * must be positioned <em>after</em> the tag that begins the list.
994      *
995      * @param parser The XmlPullParser from which to read the list data.
996      * @param endTag Name of the tag that will end the list, usually "list".
997      * @param name An array of one string, used to return the name attribute
998      *             of the list's tag.
999      *
1000      * @return Returns a newly generated long[].
1001      *
1002      * @see #readListXml
1003      */
readThisLongArrayXml(XmlPullParser parser, String endTag, String[] name)1004     public static final long[] readThisLongArrayXml(XmlPullParser parser,
1005             String endTag, String[] name)
1006             throws XmlPullParserException, java.io.IOException {
1007 
1008         int num;
1009         try {
1010             num = Integer.parseInt(parser.getAttributeValue(null, "num"));
1011         } catch (NullPointerException e) {
1012             throw new XmlPullParserException("Need num attribute in long-array");
1013         } catch (NumberFormatException e) {
1014             throw new XmlPullParserException("Not a number in num attribute in long-array");
1015         }
1016         parser.next();
1017 
1018         long[] array = new long[num];
1019         int i = 0;
1020 
1021         int eventType = parser.getEventType();
1022         do {
1023             if (eventType == parser.START_TAG) {
1024                 if (parser.getName().equals("item")) {
1025                     try {
1026                         array[i] = Long.parseLong(parser.getAttributeValue(null, "value"));
1027                     } catch (NullPointerException e) {
1028                         throw new XmlPullParserException("Need value attribute in item");
1029                     } catch (NumberFormatException e) {
1030                         throw new XmlPullParserException("Not a number in value attribute in item");
1031                     }
1032                 } else {
1033                     throw new XmlPullParserException("Expected item tag at: " + parser.getName());
1034                 }
1035             } else if (eventType == parser.END_TAG) {
1036                 if (parser.getName().equals(endTag)) {
1037                     return array;
1038                 } else if (parser.getName().equals("item")) {
1039                     i++;
1040                 } else {
1041                     throw new XmlPullParserException("Expected " + endTag + " end tag at: " +
1042                             parser.getName());
1043                 }
1044             }
1045             eventType = parser.next();
1046         } while (eventType != parser.END_DOCUMENT);
1047 
1048         throw new XmlPullParserException("Document ended before " + endTag + " end tag");
1049     }
1050 
1051     /**
1052      * Read a double[] object from an XmlPullParser.  The XML data could
1053      * previously have been generated by writeDoubleArrayXml().  The XmlPullParser
1054      * must be positioned <em>after</em> the tag that begins the list.
1055      *
1056      * @param parser The XmlPullParser from which to read the list data.
1057      * @param endTag Name of the tag that will end the list, usually "double-array".
1058      * @param name An array of one string, used to return the name attribute
1059      *             of the list's tag.
1060      *
1061      * @return Returns a newly generated double[].
1062      *
1063      * @see #readListXml
1064      */
readThisDoubleArrayXml(XmlPullParser parser, String endTag, String[] name)1065     public static final double[] readThisDoubleArrayXml(XmlPullParser parser, String endTag,
1066             String[] name) throws XmlPullParserException, java.io.IOException {
1067 
1068         int num;
1069         try {
1070             num = Integer.parseInt(parser.getAttributeValue(null, "num"));
1071         } catch (NullPointerException e) {
1072             throw new XmlPullParserException("Need num attribute in double-array");
1073         } catch (NumberFormatException e) {
1074             throw new XmlPullParserException("Not a number in num attribute in double-array");
1075         }
1076         parser.next();
1077 
1078         double[] array = new double[num];
1079         int i = 0;
1080 
1081         int eventType = parser.getEventType();
1082         do {
1083             if (eventType == parser.START_TAG) {
1084                 if (parser.getName().equals("item")) {
1085                     try {
1086                         array[i] = Double.parseDouble(parser.getAttributeValue(null, "value"));
1087                     } catch (NullPointerException e) {
1088                         throw new XmlPullParserException("Need value attribute in item");
1089                     } catch (NumberFormatException e) {
1090                         throw new XmlPullParserException("Not a number in value attribute in item");
1091                     }
1092                 } else {
1093                     throw new XmlPullParserException("Expected item tag at: " + parser.getName());
1094                 }
1095             } else if (eventType == parser.END_TAG) {
1096                 if (parser.getName().equals(endTag)) {
1097                     return array;
1098                 } else if (parser.getName().equals("item")) {
1099                     i++;
1100                 } else {
1101                     throw new XmlPullParserException("Expected " + endTag + " end tag at: " +
1102                             parser.getName());
1103                 }
1104             }
1105             eventType = parser.next();
1106         } while (eventType != parser.END_DOCUMENT);
1107 
1108         throw new XmlPullParserException("Document ended before " + endTag + " end tag");
1109     }
1110 
1111     /**
1112      * Read a String[] object from an XmlPullParser.  The XML data could
1113      * previously have been generated by writeStringArrayXml().  The XmlPullParser
1114      * must be positioned <em>after</em> the tag that begins the list.
1115      *
1116      * @param parser The XmlPullParser from which to read the list data.
1117      * @param endTag Name of the tag that will end the list, usually "string-array".
1118      * @param name An array of one string, used to return the name attribute
1119      *             of the list's tag.
1120      *
1121      * @return Returns a newly generated String[].
1122      *
1123      * @see #readListXml
1124      */
readThisStringArrayXml(XmlPullParser parser, String endTag, String[] name)1125     public static final String[] readThisStringArrayXml(XmlPullParser parser, String endTag,
1126             String[] name) throws XmlPullParserException, java.io.IOException {
1127 
1128         int num;
1129         try {
1130             num = Integer.parseInt(parser.getAttributeValue(null, "num"));
1131         } catch (NullPointerException e) {
1132             throw new XmlPullParserException("Need num attribute in string-array");
1133         } catch (NumberFormatException e) {
1134             throw new XmlPullParserException("Not a number in num attribute in string-array");
1135         }
1136         parser.next();
1137 
1138         String[] array = new String[num];
1139         int i = 0;
1140 
1141         int eventType = parser.getEventType();
1142         do {
1143             if (eventType == parser.START_TAG) {
1144                 if (parser.getName().equals("item")) {
1145                     try {
1146                         array[i] = parser.getAttributeValue(null, "value");
1147                     } catch (NullPointerException e) {
1148                         throw new XmlPullParserException("Need value attribute in item");
1149                     } catch (NumberFormatException e) {
1150                         throw new XmlPullParserException("Not a number in value attribute in item");
1151                     }
1152                 } else {
1153                     throw new XmlPullParserException("Expected item tag at: " + parser.getName());
1154                 }
1155             } else if (eventType == parser.END_TAG) {
1156                 if (parser.getName().equals(endTag)) {
1157                     return array;
1158                 } else if (parser.getName().equals("item")) {
1159                     i++;
1160                 } else {
1161                     throw new XmlPullParserException("Expected " + endTag + " end tag at: " +
1162                             parser.getName());
1163                 }
1164             }
1165             eventType = parser.next();
1166         } while (eventType != parser.END_DOCUMENT);
1167 
1168         throw new XmlPullParserException("Document ended before " + endTag + " end tag");
1169     }
1170 
1171     /**
1172      * Read a flattened object from an XmlPullParser.  The XML data could
1173      * previously have been written with writeMapXml(), writeListXml(), or
1174      * writeValueXml().  The XmlPullParser must be positioned <em>at</em> the
1175      * tag that defines the value.
1176      *
1177      * @param parser The XmlPullParser from which to read the object.
1178      * @param name An array of one string, used to return the name attribute
1179      *             of the value's tag.
1180      *
1181      * @return Object The newly generated value object.
1182      *
1183      * @see #readMapXml
1184      * @see #readListXml
1185      * @see #writeValueXml
1186      */
readValueXml(XmlPullParser parser, String[] name)1187     public static final Object readValueXml(XmlPullParser parser, String[] name)
1188     throws XmlPullParserException, java.io.IOException
1189     {
1190         int eventType = parser.getEventType();
1191         do {
1192             if (eventType == parser.START_TAG) {
1193                 return readThisValueXml(parser, name, null);
1194             } else if (eventType == parser.END_TAG) {
1195                 throw new XmlPullParserException(
1196                     "Unexpected end tag at: " + parser.getName());
1197             } else if (eventType == parser.TEXT) {
1198                 throw new XmlPullParserException(
1199                     "Unexpected text: " + parser.getText());
1200             }
1201             eventType = parser.next();
1202         } while (eventType != parser.END_DOCUMENT);
1203 
1204         throw new XmlPullParserException(
1205             "Unexpected end of document");
1206     }
1207 
readThisValueXml(XmlPullParser parser, String[] name, ReadMapCallback callback)1208     private static final Object readThisValueXml(XmlPullParser parser, String[] name,
1209             ReadMapCallback callback)  throws XmlPullParserException, java.io.IOException {
1210         final String valueName = parser.getAttributeValue(null, "name");
1211         final String tagName = parser.getName();
1212 
1213         //System.out.println("Reading this value tag: " + tagName + ", name=" + valueName);
1214 
1215         Object res;
1216 
1217         if (tagName.equals("null")) {
1218             res = null;
1219         } else if (tagName.equals("string")) {
1220             String value = "";
1221             int eventType;
1222             while ((eventType = parser.next()) != parser.END_DOCUMENT) {
1223                 if (eventType == parser.END_TAG) {
1224                     if (parser.getName().equals("string")) {
1225                         name[0] = valueName;
1226                         //System.out.println("Returning value for " + valueName + ": " + value);
1227                         return value;
1228                     }
1229                     throw new XmlPullParserException(
1230                         "Unexpected end tag in <string>: " + parser.getName());
1231                 } else if (eventType == parser.TEXT) {
1232                     value += parser.getText();
1233                 } else if (eventType == parser.START_TAG) {
1234                     throw new XmlPullParserException(
1235                         "Unexpected start tag in <string>: " + parser.getName());
1236                 }
1237             }
1238             throw new XmlPullParserException(
1239                 "Unexpected end of document in <string>");
1240         } else if ((res = readThisPrimitiveValueXml(parser, tagName)) != null) {
1241             // all work already done by readThisPrimitiveValueXml
1242         } else if (tagName.equals("int-array")) {
1243             res = readThisIntArrayXml(parser, "int-array", name);
1244             name[0] = valueName;
1245             //System.out.println("Returning value for " + valueName + ": " + res);
1246             return res;
1247         } else if (tagName.equals("long-array")) {
1248             res = readThisLongArrayXml(parser, "long-array", name);
1249             name[0] = valueName;
1250             //System.out.println("Returning value for " + valueName + ": " + res);
1251             return res;
1252         } else if (tagName.equals("double-array")) {
1253             res = readThisDoubleArrayXml(parser, "double-array", name);
1254             name[0] = valueName;
1255             //System.out.println("Returning value for " + valueName + ": " + res);
1256             return res;
1257         } else if (tagName.equals("string-array")) {
1258             res = readThisStringArrayXml(parser, "string-array", name);
1259             name[0] = valueName;
1260             //System.out.println("Returning value for " + valueName + ": " + res);
1261             return res;
1262         } else if (tagName.equals("map")) {
1263             parser.next();
1264             res = readThisMapXml(parser, "map", name);
1265             name[0] = valueName;
1266             //System.out.println("Returning value for " + valueName + ": " + res);
1267             return res;
1268         } else if (tagName.equals("list")) {
1269             parser.next();
1270             res = readThisListXml(parser, "list", name);
1271             name[0] = valueName;
1272             //System.out.println("Returning value for " + valueName + ": " + res);
1273             return res;
1274         } else if (tagName.equals("set")) {
1275             parser.next();
1276             res = readThisSetXml(parser, "set", name);
1277             name[0] = valueName;
1278             //System.out.println("Returning value for " + valueName + ": " + res);
1279             return res;
1280         } else if (callback != null) {
1281             res = callback.readThisUnknownObjectXml(parser, tagName);
1282             name[0] = valueName;
1283             return res;
1284         } else {
1285             throw new XmlPullParserException("Unknown tag: " + tagName);
1286         }
1287 
1288         // Skip through to end tag.
1289         int eventType;
1290         while ((eventType = parser.next()) != parser.END_DOCUMENT) {
1291             if (eventType == parser.END_TAG) {
1292                 if (parser.getName().equals(tagName)) {
1293                     name[0] = valueName;
1294                     //System.out.println("Returning value for " + valueName + ": " + res);
1295                     return res;
1296                 }
1297                 throw new XmlPullParserException(
1298                     "Unexpected end tag in <" + tagName + ">: " + parser.getName());
1299             } else if (eventType == parser.TEXT) {
1300                 throw new XmlPullParserException(
1301                 "Unexpected text in <" + tagName + ">: " + parser.getName());
1302             } else if (eventType == parser.START_TAG) {
1303                 throw new XmlPullParserException(
1304                     "Unexpected start tag in <" + tagName + ">: " + parser.getName());
1305             }
1306         }
1307         throw new XmlPullParserException(
1308             "Unexpected end of document in <" + tagName + ">");
1309     }
1310 
readThisPrimitiveValueXml(XmlPullParser parser, String tagName)1311     private static final Object readThisPrimitiveValueXml(XmlPullParser parser, String tagName)
1312     throws XmlPullParserException, java.io.IOException
1313     {
1314         try {
1315             if (tagName.equals("int")) {
1316                 return Integer.parseInt(parser.getAttributeValue(null, "value"));
1317             } else if (tagName.equals("long")) {
1318                 return Long.valueOf(parser.getAttributeValue(null, "value"));
1319             } else if (tagName.equals("float")) {
1320                 return new Float(parser.getAttributeValue(null, "value"));
1321             } else if (tagName.equals("double")) {
1322                 return new Double(parser.getAttributeValue(null, "value"));
1323             } else if (tagName.equals("boolean")) {
1324                 return Boolean.valueOf(parser.getAttributeValue(null, "value"));
1325             } else {
1326                 return null;
1327             }
1328         } catch (NullPointerException e) {
1329             throw new XmlPullParserException("Need value attribute in <" + tagName + ">");
1330         } catch (NumberFormatException e) {
1331             throw new XmlPullParserException(
1332                     "Not a number in value attribute in <" + tagName + ">");
1333         }
1334     }
1335 
beginDocument(XmlPullParser parser, String firstElementName)1336     public static final void beginDocument(XmlPullParser parser, String firstElementName) throws XmlPullParserException, IOException
1337     {
1338         int type;
1339         while ((type=parser.next()) != parser.START_TAG
1340                    && type != parser.END_DOCUMENT) {
1341             ;
1342         }
1343 
1344         if (type != parser.START_TAG) {
1345             throw new XmlPullParserException("No start tag found");
1346         }
1347 
1348         if (!parser.getName().equals(firstElementName)) {
1349             throw new XmlPullParserException("Unexpected start tag: found " + parser.getName() +
1350                     ", expected " + firstElementName);
1351         }
1352     }
1353 
nextElement(XmlPullParser parser)1354     public static final void nextElement(XmlPullParser parser) throws XmlPullParserException, IOException
1355     {
1356         int type;
1357         while ((type=parser.next()) != parser.START_TAG
1358                    && type != parser.END_DOCUMENT) {
1359             ;
1360         }
1361     }
1362 
nextElementWithin(XmlPullParser parser, int outerDepth)1363     public static boolean nextElementWithin(XmlPullParser parser, int outerDepth)
1364             throws IOException, XmlPullParserException {
1365         for (;;) {
1366             int type = parser.next();
1367             if (type == XmlPullParser.END_DOCUMENT
1368                     || (type == XmlPullParser.END_TAG && parser.getDepth() == outerDepth)) {
1369                 return false;
1370             }
1371             if (type == XmlPullParser.START_TAG
1372                     && parser.getDepth() == outerDepth + 1) {
1373                 return true;
1374             }
1375         }
1376     }
1377 
readIntAttribute(XmlPullParser in, String name, int defaultValue)1378     public static int readIntAttribute(XmlPullParser in, String name, int defaultValue) {
1379         final String value = in.getAttributeValue(null, name);
1380         try {
1381             return Integer.parseInt(value);
1382         } catch (NumberFormatException e) {
1383             return defaultValue;
1384         }
1385     }
1386 
readIntAttribute(XmlPullParser in, String name)1387     public static int readIntAttribute(XmlPullParser in, String name) throws IOException {
1388         final String value = in.getAttributeValue(null, name);
1389         try {
1390             return Integer.parseInt(value);
1391         } catch (NumberFormatException e) {
1392             throw new ProtocolException("problem parsing " + name + "=" + value + " as int");
1393         }
1394     }
1395 
writeIntAttribute(XmlSerializer out, String name, int value)1396     public static void writeIntAttribute(XmlSerializer out, String name, int value)
1397             throws IOException {
1398         out.attribute(null, name, Integer.toString(value));
1399     }
1400 
readLongAttribute(XmlPullParser in, String name, long defaultValue)1401     public static long readLongAttribute(XmlPullParser in, String name, long defaultValue) {
1402         final String value = in.getAttributeValue(null, name);
1403         try {
1404             return Long.parseLong(value);
1405         } catch (NumberFormatException e) {
1406             return defaultValue;
1407         }
1408     }
1409 
readLongAttribute(XmlPullParser in, String name)1410     public static long readLongAttribute(XmlPullParser in, String name) throws IOException {
1411         final String value = in.getAttributeValue(null, name);
1412         try {
1413             return Long.parseLong(value);
1414         } catch (NumberFormatException e) {
1415             throw new ProtocolException("problem parsing " + name + "=" + value + " as long");
1416         }
1417     }
1418 
writeLongAttribute(XmlSerializer out, String name, long value)1419     public static void writeLongAttribute(XmlSerializer out, String name, long value)
1420             throws IOException {
1421         out.attribute(null, name, Long.toString(value));
1422     }
1423 
readFloatAttribute(XmlPullParser in, String name)1424     public static float readFloatAttribute(XmlPullParser in, String name) throws IOException {
1425         final String value = in.getAttributeValue(null, name);
1426         try {
1427             return Float.parseFloat(value);
1428         } catch (NumberFormatException e) {
1429             throw new ProtocolException("problem parsing " + name + "=" + value + " as long");
1430         }
1431     }
1432 
writeFloatAttribute(XmlSerializer out, String name, float value)1433     public static void writeFloatAttribute(XmlSerializer out, String name, float value)
1434             throws IOException {
1435         out.attribute(null, name, Float.toString(value));
1436     }
1437 
readBooleanAttribute(XmlPullParser in, String name)1438     public static boolean readBooleanAttribute(XmlPullParser in, String name) {
1439         final String value = in.getAttributeValue(null, name);
1440         return Boolean.parseBoolean(value);
1441     }
1442 
readBooleanAttribute(XmlPullParser in, String name, boolean defaultValue)1443     public static boolean readBooleanAttribute(XmlPullParser in, String name,
1444             boolean defaultValue) {
1445         final String value = in.getAttributeValue(null, name);
1446         if (value == null) {
1447             return defaultValue;
1448         } else {
1449             return Boolean.parseBoolean(value);
1450         }
1451     }
1452 
writeBooleanAttribute(XmlSerializer out, String name, boolean value)1453     public static void writeBooleanAttribute(XmlSerializer out, String name, boolean value)
1454             throws IOException {
1455         out.attribute(null, name, Boolean.toString(value));
1456     }
1457 
readUriAttribute(XmlPullParser in, String name)1458     public static Uri readUriAttribute(XmlPullParser in, String name) {
1459         final String value = in.getAttributeValue(null, name);
1460         return (value != null) ? Uri.parse(value) : null;
1461     }
1462 
writeUriAttribute(XmlSerializer out, String name, Uri value)1463     public static void writeUriAttribute(XmlSerializer out, String name, Uri value)
1464             throws IOException {
1465         if (value != null) {
1466             out.attribute(null, name, value.toString());
1467         }
1468     }
1469 
readStringAttribute(XmlPullParser in, String name)1470     public static String readStringAttribute(XmlPullParser in, String name) {
1471         return in.getAttributeValue(null, name);
1472     }
1473 
writeStringAttribute(XmlSerializer out, String name, String value)1474     public static void writeStringAttribute(XmlSerializer out, String name, String value)
1475             throws IOException {
1476         if (value != null) {
1477             out.attribute(null, name, value);
1478         }
1479     }
1480 
readByteArrayAttribute(XmlPullParser in, String name)1481     public static byte[] readByteArrayAttribute(XmlPullParser in, String name) {
1482         final String value = in.getAttributeValue(null, name);
1483         if (value != null) {
1484             return Base64.decode(value, Base64.DEFAULT);
1485         } else {
1486             return null;
1487         }
1488     }
1489 
writeByteArrayAttribute(XmlSerializer out, String name, byte[] value)1490     public static void writeByteArrayAttribute(XmlSerializer out, String name, byte[] value)
1491             throws IOException {
1492         if (value != null) {
1493             out.attribute(null, name, Base64.encodeToString(value, Base64.DEFAULT));
1494         }
1495     }
1496 
readBitmapAttribute(XmlPullParser in, String name)1497     public static Bitmap readBitmapAttribute(XmlPullParser in, String name) {
1498         final byte[] value = readByteArrayAttribute(in, name);
1499         if (value != null) {
1500             return BitmapFactory.decodeByteArray(value, 0, value.length);
1501         } else {
1502             return null;
1503         }
1504     }
1505 
1506     @Deprecated
writeBitmapAttribute(XmlSerializer out, String name, Bitmap value)1507     public static void writeBitmapAttribute(XmlSerializer out, String name, Bitmap value)
1508             throws IOException {
1509         if (value != null) {
1510             final ByteArrayOutputStream os = new ByteArrayOutputStream();
1511             value.compress(CompressFormat.PNG, 90, os);
1512             writeByteArrayAttribute(out, name, os.toByteArray());
1513         }
1514     }
1515 
1516     /** @hide */
1517     public interface WriteMapCallback {
1518         /**
1519          * Called from writeMapXml when an Object type is not recognized. The implementer
1520          * must write out the entire element including start and end tags.
1521          *
1522          * @param v The object to be written out
1523          * @param name The mapping key for v. Must be written into the "name" attribute of the
1524          *             start tag.
1525          * @param out The XML output stream.
1526          * @throws XmlPullParserException on unrecognized Object type.
1527          * @throws IOException on XmlSerializer serialization errors.
1528          * @hide
1529          */
writeUnknownObject(Object v, String name, XmlSerializer out)1530          public void writeUnknownObject(Object v, String name, XmlSerializer out)
1531                  throws XmlPullParserException, IOException;
1532     }
1533 
1534     /** @hide */
1535     public interface ReadMapCallback {
1536         /**
1537          * Called from readThisMapXml when a START_TAG is not recognized. The input stream
1538          * is positioned within the start tag so that attributes can be read using in.getAttribute.
1539          *
1540          * @param in the XML input stream
1541          * @param tag the START_TAG that was not recognized.
1542          * @return the Object parsed from the stream which will be put into the map.
1543          * @throws XmlPullParserException if the START_TAG is not recognized.
1544          * @throws IOException on XmlPullParser serialization errors.
1545          * @hide
1546          */
readThisUnknownObjectXml(XmlPullParser in, String tag)1547         public Object readThisUnknownObjectXml(XmlPullParser in, String tag)
1548                 throws XmlPullParserException, IOException;
1549     }
1550 }
1551