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