| 285 | } |
| 286 | |
| 287 | public Object readObject() throws IOException, ClassNotFoundException { |
| 288 | int c = rawByte(); |
| 289 | if (c == TC_NULL) { |
| 290 | return null; |
| 291 | } |
| 292 | if (c == TC_STRING) { |
| 293 | int length = rawShort(); |
| 294 | byte[] bytes = new byte[length]; |
| 295 | readFully(bytes); |
| 296 | String s = new String(bytes, "UTF-8"); |
| 297 | references.add(s); |
| 298 | return s; |
| 299 | } |
| 300 | if (c == TC_REFERENCE) { |
| 301 | int handle = rawInt(); |
| 302 | return references.get(handle - HANDLE_OFFSET); |
| 303 | } |
| 304 | if (c != TC_OBJECT) { |
| 305 | throw new IOException("Unexpected token: 0x" |
| 306 | + Integer.toHexString(c)); |
| 307 | } |
| 308 | |
| 309 | // class desc |
| 310 | c = rawByte(); |
| 311 | ClassDesc classDesc; |
| 312 | if (c == TC_REFERENCE) { |
| 313 | int handle = rawInt() - HANDLE_OFFSET; |
| 314 | classDesc = (ClassDesc)references.get(handle); |
| 315 | } else if (c == TC_CLASSDESC) { |
| 316 | classDesc = classDesc(); |
| 317 | } else { |
| 318 | throw new UnsupportedOperationException("Unexpected token: 0x" |
| 319 | + Integer.toHexString(c)); |
| 320 | } |
| 321 | |
| 322 | try { |
| 323 | Object o = makeInstance(classDesc.clazz.vmClass); |
| 324 | references.add(o); |
| 325 | |
| 326 | do { |
| 327 | Object o1 = classDesc.clazz.cast(o); |
| 328 | boolean customized = (classDesc.flags & SC_WRITE_METHOD) != 0; |
| 329 | Method readMethod = customized ? |
| 330 | getReadOrWriteMethod(o, "readObject") : null; |
| 331 | if (readMethod == null) { |
| 332 | if (customized) { |
| 333 | throw new IOException("Could not find required readObject method " |
| 334 | + "in " + classDesc.clazz); |
| 335 | } |
| 336 | defaultReadObject(o, classDesc.fields); |
| 337 | } else { |
| 338 | current = o1; |
| 339 | currentFields = classDesc.fields; |
| 340 | readMethod.invoke(o, this); |
| 341 | current = null; |
| 342 | currentFields = null; |
| 343 | expectToken(TC_ENDBLOCKDATA); |
| 344 | } |