1 19 20 package org.netbeans.upgrade.systemoptions; 21 22 import java.io.*; 23 import java.util.*; 24 import org.openide.util.NotImplementedException; 25 26 59 60 65 public final class SerParser implements ObjectStreamConstants { 66 67 private static final boolean DEBUG = Boolean.getBoolean("org.netbeans.modules.clazz.SerParser.DEBUG"); 69 private final InputStream is; 70 private int seq = 0; 71 private final List<Object > refs = new ArrayList<Object >(100); 72 73 public SerParser(InputStream is) { 74 this.is = is; 75 } 76 77 private int makeRef(Object o) { 78 refs.add(o); 79 int i = seq; 80 seq++; 81 if (DEBUG) System.err.println("makeRef[" + i + "]=" + o); return i; 83 } 84 85 private Object getRef(int i) throws CorruptException { 86 int idx = i - baseWireHandle; 87 if (idx < 0 || idx >= seq) throw new CorruptException("Invalid reference: " + i); Object o = refs.get(idx); 89 if (o == null) throw new CorruptException("Invalid reference: " + i); return o; 91 } 92 93 public Stream parse() throws IOException, CorruptException { 94 Stream s = new Stream(); 95 s.magic = readShort(); 96 s.version = readShort(); 97 if (s.magic != STREAM_MAGIC || s.version != STREAM_VERSION) { 98 throw new CorruptException("stream version mismatch: " + hexify(s.magic) + " != " + hexify(STREAM_MAGIC) + " or " + hexify(s.version) + " != " + hexify(STREAM_VERSION)); } 100 s.contents = new ArrayList<Object >(10); 101 while (peek() != -1) { 102 s.contents.add(readContent()); 103 } 104 if (DEBUG) System.err.println("parsed: " + s); return s; 106 } 107 108 public static final class CorruptException extends IOException { 109 public CorruptException() { 110 } 111 public CorruptException(String m) { 112 super(m); 113 } 114 } 115 116 private int pushback = -1; 117 private int rb() throws IOException { 118 if (pushback != -1) { 119 int c = pushback; 120 pushback = -1; 121 return c; 122 } 123 int c = is.read(); 124 if (DEBUG) System.err.println("read: " + Integer.toHexString(c)); if (c == -1) { 126 throw new EOFException(); 127 } else { 128 return c; 129 } 130 } 131 private int peek() throws IOException { 132 if (pushback != -1) throw new IllegalStateException ("can only peek once"); pushback = is.read(); 134 if (DEBUG) System.err.println("read: " + Integer.toHexString(pushback)); return pushback; 136 } 137 138 static String hexify(byte b) { 139 int i = b; 140 if (i < 0) i += 256; 141 String s = Integer.toHexString(i).toUpperCase(Locale.US); 142 return "0x" + pad(s, 2); } 144 static String hexify(short s) { 145 int i = s; 146 if (i < 0) i += 65536; 147 String st = Integer.toHexString(i).toUpperCase(Locale.US); 148 return "0x" + pad(st, 4); } 150 static String hexify(int i) { 151 String s = Integer.toHexString(i).toUpperCase(Locale.US); 152 return "0x" + pad(s, 4); } 154 static String hexify(long l) { 155 String s1 = Integer.toHexString((int)((l & 0xFFFFFFFF00000000L) << 32)).toUpperCase(Locale.US); 156 String s2 = Integer.toHexString((int)(l & 0x00000000FFFFFFFFL)).toUpperCase(Locale.US); 157 return "0x" + pad(s1, 4) + pad(s2, 4); } 159 static String hexify(byte[] b) { 160 StringBuffer buf = new StringBuffer (2 + b.length * 2); 161 buf.append("0x"); for (int i = 0; i < b.length; i++) { 163 int x = b[i]; 164 if (x < 0) x += 256; 165 buf.append(pad(Integer.toHexString(x).toUpperCase(Locale.US), 2)); 166 } 167 return buf.toString(); 168 } 169 private static String pad(String s, int size) { 170 int i = s.length(); 171 if (i == size) { 172 return s; 173 } else { 174 StringBuffer b = new StringBuffer (size); 175 for (int k = 0; k < size - i; k++) { 176 b.append('0'); } 178 b.append(s); 179 return b.toString(); 180 } 181 } 182 183 private long readLong() throws IOException { 184 long x1 = rb(); 185 long x2 = rb(); 186 long x3 = rb(); 187 long x4 = rb(); 188 long x5 = rb(); 189 long x6 = rb(); 190 long x7 = rb(); 191 long x8 = rb(); 192 long l = (x1 << 56) + (x2 << 48) + (x3 << 40) + (x4 << 32) + (x5 << 24) + (x6 << 16) + (x7 << 8) + x8; 193 if (DEBUG) System.err.println("readLong: " + l); return l; 195 } 196 197 private int readInt() throws IOException { 198 int x1 = rb(); 199 int x2 = rb(); 200 int x3 = rb(); 201 int x4 = rb(); 202 int i = (x1 << 24) + (x2 << 16) + (x3 << 8) + x4; 203 if (DEBUG) System.err.println("readInt: " + i); return i; 205 } 206 207 private short readShort() throws IOException { 208 int x1 = rb(); 209 int x2 = rb(); 210 short s = (short)((x1 << 8) + x2); 211 if (DEBUG) System.err.println("readShort: " + s); return s; 215 } 216 217 private byte readByte() throws IOException { 218 return (byte)rb(); 219 } 220 221 private String readUTF() throws IOException { 222 short len = readShort(); 223 if (len < 0) throw new NotImplementedException(); byte[] buf = new byte[len]; 225 for (int i = 0; i < len; i++) { 226 buf[i] = readByte(); 227 } 228 String s = new String (buf, "UTF-8"); if (DEBUG) System.err.println("readUTF: " + s); return s; 231 } 232 233 248 249 252 public static final class Stream { 253 public short magic; 254 public short version; 255 public List<Object > contents; 256 public String toString() { 257 return "Stream[contents=" + contents + "]"; } 259 } 260 261 public static final Object NULL = "null"; 263 private Object readContent() throws IOException { 264 byte tc = readByte(); 265 switch (tc) { 266 case TC_OBJECT: 267 return readNewObject(); 268 case TC_CLASS: 269 return readNewClass(); 270 case TC_ARRAY: 271 return readNewArray(); 272 case TC_CLASSDESC: 273 return readNewClassDesc(); 274 case TC_PROXYCLASSDESC: 275 throw new NotImplementedException("TC_PROXYCLASSDESC"); case TC_STRING: 279 return readNewString(); 280 case TC_LONGSTRING: 281 throw new NotImplementedException("TC_LONGSTRING"); case TC_REFERENCE: 285 return readReference(); 286 case TC_NULL: 287 return NULL; 288 case TC_EXCEPTION: 289 throw new NotImplementedException("TC_EXCEPTION"); case TC_RESET: 292 throw new NotImplementedException("TC_RESET"); case TC_BLOCKDATA: 295 return readBlockData(); 296 case TC_BLOCKDATALONG: 297 return readBlockDataLong(); 298 default: 299 throw new CorruptException("Unknown typecode: " + hexify(tc)); } 301 } 302 303 public static final class ObjectWrapper { 304 public ClassDesc classdesc; 305 public List<Object > data; public String toString() { 307 return "Object[class=" + classdesc.name + ",data=<omitted>]"; } 309 } 310 311 public static final class NameValue { 312 public NameValue(FieldDesc name, Object value) { 313 this.name = name; 314 this.value = value; 315 } 316 public final FieldDesc name; 317 public final Object value; 318 public String toString() { 319 return name.toString() + "=" + value.toString(); } 321 } 322 323 public static final class ClassDesc { 324 public String name; 325 public long svuid; 326 public boolean writeMethod; 327 public boolean blockData; 328 public boolean serializable; 329 public boolean externalizable; 330 public List<FieldDesc> fields; 331 public List annotation; public ClassDesc superclass; 333 public String toString() { 334 return "Class[name=" + name + "]"; } 336 } 337 338 private ObjectWrapper readNewObject() throws IOException { 339 ObjectWrapper ow = new ObjectWrapper(); 340 ow.classdesc = readClassDesc(); 341 makeRef(ow); 342 ow.data = new ArrayList<Object > (10); 343 LinkedList<ClassDesc> hier = new LinkedList<ClassDesc>(); 344 for (ClassDesc cd = ow.classdesc; cd != null; cd = cd.superclass) { 345 hier.addFirst(cd); 346 } 347 for (ClassDesc cd: hier) { 348 if (cd.serializable) { 349 ow.data.addAll(readNoWrClass(cd)); 350 if (cd.writeMethod) { 351 ow.data.addAll(readContents()); 352 } 353 } else { 354 if (cd.blockData) { 355 ow.data.addAll(readContents()); 356 } else { 357 ow.data.add(readContent()); 360 } 361 } 362 } 363 if (DEBUG) System.err.println("readNewObject: " + ow); return ow; 365 } 366 367 private ClassDesc readClassDesc() throws IOException { 368 Object o = readContent(); 369 if (o instanceof ClassDesc) { 370 return (ClassDesc)o; 371 } else if (o == NULL) { 372 return null; 373 } else { 374 throw new CorruptException("Expected class desc, got: " + o); } 376 } 377 378 private ClassDesc readNewClass() throws IOException { 379 ClassDesc cd = readClassDesc(); 380 makeRef(cd); 381 return cd; 382 } 383 384 private ClassDesc readNewClassDesc() throws IOException { 385 ClassDesc cd = new ClassDesc(); 386 cd.name = readUTF(); 387 if (! cd.name.startsWith("[") && ! (cd.name.length() == 1 && "BSIJFDCZ".indexOf(cd.name) != -1) && ! cd.name.endsWith(";")) { cd.name = "L" + cd.name + ";"; } 394 cd.svuid = readLong(); 395 makeRef(cd); 396 byte cdf = readByte(); 397 cd.writeMethod = (cdf & SC_WRITE_METHOD) != 0; 398 cd.blockData = (cdf & SC_BLOCK_DATA) != 0; 399 cd.serializable = (cdf & SC_SERIALIZABLE) != 0; 400 cd.externalizable = (cdf & SC_EXTERNALIZABLE) != 0; 401 short count = readShort(); 402 cd.fields = new ArrayList<FieldDesc>(count); 403 for (int i = 0; i < count; i++) { 404 cd.fields.add(readFieldDesc()); 405 } 406 cd.annotation = readContents(); 407 cd.superclass = readClassDesc(); 408 if (DEBUG) System.err.println("readNewClassDesc: " + cd); return cd; 410 } 411 412 public static class FieldDesc { 413 public String name; 414 public String type; 415 public String toString() { 416 return "Field[name=" + name + ",type=" + type + "]"; } 418 } 419 public static final class ObjFieldDesc extends FieldDesc { 420 public boolean array; 421 public String toString() { 422 return "Field[name=" + name + ",type=" + type + (array ? "[]" : "") + "]"; } 424 } 425 426 private FieldDesc readFieldDesc() throws IOException { 427 char tc = (char)readByte(); 428 FieldDesc fd; 429 switch (tc) { 430 case 'B': 431 case 'C': 432 case 'D': 433 case 'F': 434 case 'I': 435 case 'J': 436 case 'S': 437 case 'Z': 438 fd = new FieldDesc(); 439 fd.type = new String (new char[] {tc}); 440 break; 441 case '[': 442 fd = new ObjFieldDesc(); 443 ((ObjFieldDesc)fd).array = true; 444 break; 445 case 'L': 446 fd = new ObjFieldDesc(); 447 ((ObjFieldDesc)fd).array = false; 448 break; 449 default: 450 throw new CorruptException("Strange field type: " + tc); } 452 fd.name = readUTF(); 453 if (fd instanceof ObjFieldDesc) { 454 String clazz = (String )readContent(); 455 463 fd.type = clazz; 464 } 465 if (DEBUG) System.err.println("readFieldDesc: " + fd); return fd; 467 } 468 469 private List<Object > readContents() throws IOException { 470 List<Object > l = new ArrayList<Object >(10); 471 while (peek() != TC_ENDBLOCKDATA) { 472 l.add(readContent()); 473 } 474 if (readByte() != TC_ENDBLOCKDATA) throw new IllegalStateException (); 475 if (DEBUG) System.err.println("readContents: " + l); return l; 477 } 478 479 public static final class ArrayWrapper { 480 public ClassDesc classdesc; 481 public List<Object > values; 482 public String toString() { 483 return classdesc.name + "{" + values + "}"; } 485 } 486 487 private ArrayWrapper readNewArray() throws IOException { 488 ArrayWrapper aw = new ArrayWrapper(); 489 aw.classdesc = readClassDesc(); 490 makeRef(aw); 491 int size = readInt(); 492 if (size < 0) throw new NotImplementedException(); 493 aw.values = new ArrayList<Object >(size); 494 for (int i = 0; i < size; i++) { 495 if (aw.classdesc.name.equals("[B")) { aw.values.add(new Byte (readByte())); 497 } else if (aw.classdesc.name.equals("[S")) { aw.values.add(new Short (readShort())); 499 } else if (aw.classdesc.name.equals("[I")) { aw.values.add(new Integer (readInt())); 501 } else if (aw.classdesc.name.equals("[J")) { aw.values.add(new Long (readLong())); 503 } else if (aw.classdesc.name.equals("[F")) { aw.values.add(new Float (Float.intBitsToFloat(readInt()))); 505 } else if (aw.classdesc.name.equals("[D")) { aw.values.add(new Double (Double.longBitsToDouble(readLong()))); 507 } else if (aw.classdesc.name.equals("[C")) { aw.values.add(new Character ((char)readShort())); 509 } else if (aw.classdesc.name.equals("[Z")) { aw.values.add(readByte() == 1 ? Boolean.TRUE : Boolean.FALSE); 511 } else { 512 aw.values.add(readContent()); 513 } 514 } 515 if (DEBUG) System.err.println("readNewArray: " + aw); return aw; 517 } 518 519 private String readNewString() throws IOException { 520 String s = readUTF(); 521 makeRef(s); 522 return s; 523 } 524 525 private Object readReference() throws IOException { 526 int i = readInt(); 527 Object r = getRef(i); 528 if (DEBUG) System.err.println("readReference: " + r); return r; 530 } 531 532 private byte[] readBlockData() throws IOException { 533 int size = readByte(); 534 if (size < 0) size += 256; 535 byte[] b = new byte[size]; 536 for (int i = 0; i < size; i++) { 537 b[i] = readByte(); 538 } 539 if (DEBUG) System.err.println("readBlockData: " + size + " bytes"); return b; 541 } 542 543 private byte[] readBlockDataLong() throws IOException { 544 int size = readInt(); 545 if (size < 0) throw new NotImplementedException(); 546 byte[] b = new byte[size]; 547 for (int i = 0; i < size; i++) { 548 b[i] = readByte(); 549 } 550 if (DEBUG) System.err.println("readBlockDataLong: " + size + " bytes"); return b; 552 } 553 554 private List<NameValue> readNoWrClass(ClassDesc cd) throws IOException { 555 List<FieldDesc> fields = cd.fields; 556 List<NameValue> values = new ArrayList<NameValue>(fields.size()); 557 for (int i = 0; i < fields.size(); i++) { 558 FieldDesc fd = (FieldDesc)fields.get(i); 559 if (fd.type.equals("B")) { values.add(new NameValue(fd, new Byte (readByte()))); 561 } else if (fd.type.equals("S")) { values.add(new NameValue(fd, new Short (readShort()))); 563 } else if (fd.type.equals("I")) { values.add(new NameValue(fd, new Integer (readInt()))); 565 } else if (fd.type.equals("J")) { values.add(new NameValue(fd, new Long (readLong()))); 567 } else if (fd.type.equals("F")) { values.add(new NameValue(fd, new Float (Float.intBitsToFloat(readInt())))); 569 } else if (fd.type.equals("D")) { values.add(new NameValue(fd, new Double (Double.longBitsToDouble(readLong())))); 571 } else if (fd.type.equals("C")) { values.add(new NameValue(fd, new Character ((char)readShort()))); 573 } else if (fd.type.equals("Z")) { values.add(new NameValue(fd, readByte() == 1 ? Boolean.TRUE : Boolean.FALSE)); 575 } else { 576 values.add(new NameValue(fd, readContent())); 577 } 578 } 579 if (DEBUG) System.err.println("readNoWrClass: " + values); return values; 581 } 582 583 } 584 | Popular Tags |