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