ObjectInputStream.java 70 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144
  1. /* ObjectInputStream.java -- Class used to read serialized objects
  2. Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2005, 2006, 2008
  3. Free Software Foundation, Inc.
  4. This file is part of GNU Classpath.
  5. GNU Classpath is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2, or (at your option)
  8. any later version.
  9. GNU Classpath is distributed in the hope that it will be useful, but
  10. WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12. General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with GNU Classpath; see the file COPYING. If not, write to the
  15. Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  16. 02110-1301 USA.
  17. Linking this library statically or dynamically with other modules is
  18. making a combined work based on this library. Thus, the terms and
  19. conditions of the GNU General Public License cover the whole
  20. combination.
  21. As a special exception, the copyright holders of this library give you
  22. permission to link this library with independent modules to produce an
  23. executable, regardless of the license terms of these independent
  24. modules, and to copy and distribute the resulting executable under
  25. terms of your choice, provided that you also meet, for each linked
  26. independent module, the terms and conditions of the license of that
  27. module. An independent module is a module which is not derived from
  28. or based on this library. If you modify this library, you may extend
  29. this exception to your version of the library, but you are not
  30. obligated to do so. If you do not wish to do so, delete this
  31. exception statement from your version. */
  32. package java.io;
  33. import gnu.classpath.Pair;
  34. import gnu.classpath.VMStackWalker;
  35. import java.lang.reflect.Array;
  36. import java.lang.reflect.Constructor;
  37. import java.lang.reflect.Field;
  38. import java.lang.reflect.InvocationTargetException;
  39. import java.lang.reflect.Method;
  40. import java.lang.reflect.Modifier;
  41. import java.lang.reflect.Proxy;
  42. import java.security.AccessController;
  43. import java.security.PrivilegedAction;
  44. import java.util.HashMap;
  45. import java.util.Hashtable;
  46. import java.util.Iterator;
  47. import java.util.Map;
  48. import java.util.TreeSet;
  49. /**
  50. * @author Tom Tromey (tromey@redhat.com)
  51. * @author Jeroen Frijters (jeroen@frijters.net)
  52. * @author Guilhem Lavaux (guilhem@kaffe.org)
  53. * @author Michael Koch (konqueror@gmx.de)
  54. * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
  55. */
  56. public class ObjectInputStream extends InputStream
  57. implements ObjectInput, ObjectStreamConstants
  58. {
  59. /**
  60. * Creates a new <code>ObjectInputStream</code> that will do all of
  61. * its reading from <code>in</code>. This method also checks
  62. * the stream by reading the header information (stream magic number
  63. * and stream version).
  64. *
  65. * @exception IOException Reading stream header from underlying
  66. * stream cannot be completed.
  67. *
  68. * @exception StreamCorruptedException An invalid stream magic
  69. * number or stream version was read from the stream.
  70. *
  71. * @see #readStreamHeader()
  72. */
  73. public ObjectInputStream(InputStream in)
  74. throws IOException, StreamCorruptedException
  75. {
  76. if (DEBUG)
  77. {
  78. String val = System.getProperty("gcj.dumpobjects");
  79. if (dump == false && val != null && !val.equals(""))
  80. {
  81. dump = true;
  82. System.out.println ("Serialization debugging enabled");
  83. }
  84. else if (dump == true && (val == null || val.equals("")))
  85. {
  86. dump = false;
  87. System.out.println ("Serialization debugging disabled");
  88. }
  89. }
  90. this.resolveEnabled = false;
  91. this.blockDataPosition = 0;
  92. this.blockDataBytes = 0;
  93. this.blockData = new byte[BUFFER_SIZE];
  94. this.blockDataInput = new DataInputStream(this);
  95. this.realInputStream = new DataInputStream(in);
  96. this.nextOID = baseWireHandle;
  97. handles = new HashMap<Integer,Pair<Boolean,Object>>();
  98. this.classLookupTable = new Hashtable<Class,ObjectStreamClass>();
  99. setBlockDataMode(true);
  100. readStreamHeader();
  101. }
  102. /**
  103. * Returns the next deserialized object read from the underlying stream.
  104. *
  105. * This method can be overriden by a class by implementing
  106. * <code>private void readObject (ObjectInputStream)</code>.
  107. *
  108. * If an exception is thrown from this method, the stream is left in
  109. * an undefined state. This method can also throw Errors and
  110. * RuntimeExceptions if caused by existing readResolve() user code.
  111. *
  112. * @return The object read from the underlying stream.
  113. *
  114. * @exception ClassNotFoundException The class that an object being
  115. * read in belongs to cannot be found.
  116. *
  117. * @exception IOException Exception from underlying
  118. * <code>InputStream</code>.
  119. */
  120. public final Object readObject()
  121. throws ClassNotFoundException, IOException
  122. {
  123. return readObject(true);
  124. }
  125. /**
  126. * <p>
  127. * Returns the next deserialized object read from the
  128. * underlying stream in an unshared manner. Any object
  129. * returned by this method will not be returned by
  130. * subsequent calls to either this method or {@link #readObject()}.
  131. * </p>
  132. * <p>
  133. * This behaviour is achieved by:
  134. * </p>
  135. * <ul>
  136. * <li>Marking the handles created by successful calls to this
  137. * method, so that future calls to {@link #readObject()} or
  138. * {@link #readUnshared()} will throw an {@link ObjectStreamException}
  139. * rather than returning the same object reference.</li>
  140. * <li>Throwing an {@link ObjectStreamException} if the next
  141. * element in the stream is a reference to an earlier object.</li>
  142. * </ul>
  143. *
  144. * @return a reference to the deserialized object.
  145. * @throws ClassNotFoundException if the class of the object being
  146. * deserialized can not be found.
  147. * @throws StreamCorruptedException if information in the stream
  148. * is inconsistent.
  149. * @throws ObjectStreamException if the next object has already been
  150. * returned by an earlier call to this
  151. * method or {@link #readObject()}.
  152. * @throws OptionalDataException if primitive data occurs next in the stream.
  153. * @throws IOException if an I/O error occurs from the stream.
  154. * @since 1.4
  155. * @see #readObject()
  156. */
  157. public Object readUnshared()
  158. throws IOException, ClassNotFoundException
  159. {
  160. return readObject(false);
  161. }
  162. /**
  163. * Returns the next deserialized object read from the underlying stream.
  164. *
  165. * This method can be overriden by a class by implementing
  166. * <code>private void readObject (ObjectInputStream)</code>.
  167. *
  168. * If an exception is thrown from this method, the stream is left in
  169. * an undefined state. This method can also throw Errors and
  170. * RuntimeExceptions if caused by existing readResolve() user code.
  171. *
  172. * @param shared true if handles created by this call should be shared
  173. * with later calls.
  174. * @return The object read from the underlying stream.
  175. *
  176. * @exception ClassNotFoundException The class that an object being
  177. * read in belongs to cannot be found.
  178. *
  179. * @exception IOException Exception from underlying
  180. * <code>InputStream</code>.
  181. */
  182. private final Object readObject(boolean shared)
  183. throws ClassNotFoundException, IOException
  184. {
  185. if (this.useSubclassMethod)
  186. return readObjectOverride();
  187. Object ret_val;
  188. boolean old_mode = setBlockDataMode(false);
  189. byte marker = this.realInputStream.readByte();
  190. if (DEBUG)
  191. depth += 2;
  192. if(dump) dumpElement("MARKER: 0x" + Integer.toHexString(marker) + " ");
  193. try
  194. {
  195. ret_val = parseContent(marker, shared);
  196. }
  197. finally
  198. {
  199. setBlockDataMode(old_mode);
  200. if (DEBUG)
  201. depth -= 2;
  202. }
  203. return ret_val;
  204. }
  205. /**
  206. * Handles a content block within the stream, which begins with a marker
  207. * byte indicating its type.
  208. *
  209. * @param marker the byte marker.
  210. * @param shared true if handles created by this call should be shared
  211. * with later calls.
  212. * @return an object which represents the parsed content.
  213. * @throws ClassNotFoundException if the class of an object being
  214. * read in cannot be found.
  215. * @throws IOException if invalid data occurs or one is thrown by the
  216. * underlying <code>InputStream</code>.
  217. */
  218. private Object parseContent(byte marker, boolean shared)
  219. throws ClassNotFoundException, IOException
  220. {
  221. Object ret_val;
  222. boolean is_consumed = false;
  223. switch (marker)
  224. {
  225. case TC_ENDBLOCKDATA:
  226. {
  227. ret_val = null;
  228. is_consumed = true;
  229. break;
  230. }
  231. case TC_BLOCKDATA:
  232. case TC_BLOCKDATALONG:
  233. {
  234. if (marker == TC_BLOCKDATALONG)
  235. { if(dump) dumpElementln("BLOCKDATALONG"); }
  236. else
  237. { if(dump) dumpElementln("BLOCKDATA"); }
  238. readNextBlock(marker);
  239. }
  240. case TC_NULL:
  241. {
  242. if(dump) dumpElementln("NULL");
  243. ret_val = null;
  244. break;
  245. }
  246. case TC_REFERENCE:
  247. {
  248. if(dump) dumpElement("REFERENCE ");
  249. int oid = realInputStream.readInt();
  250. if(dump) dumpElementln(Integer.toHexString(oid));
  251. ret_val = lookupHandle(oid);
  252. if (!shared)
  253. throw new
  254. InvalidObjectException("References can not be read unshared.");
  255. break;
  256. }
  257. case TC_CLASS:
  258. {
  259. if(dump) dumpElementln("CLASS");
  260. ObjectStreamClass osc = (ObjectStreamClass)readObject();
  261. Class clazz = osc.forClass();
  262. assignNewHandle(clazz,shared);
  263. ret_val = clazz;
  264. break;
  265. }
  266. case TC_PROXYCLASSDESC:
  267. {
  268. if(dump) dumpElementln("PROXYCLASS");
  269. /* GCJ LOCAL */
  270. // The grammar at this point is
  271. // TC_PROXYCLASSDESC newHandle proxyClassDescInfo
  272. // i.e. we have to assign the handle immediately after
  273. // reading the marker.
  274. int handle = assignNewHandle("Dummy proxy",shared);
  275. /* END GCJ LOCAL */
  276. int n_intf = this.realInputStream.readInt();
  277. String[] intfs = new String[n_intf];
  278. for (int i = 0; i < n_intf; i++)
  279. {
  280. intfs[i] = this.realInputStream.readUTF();
  281. }
  282. boolean oldmode = setBlockDataMode(true);
  283. Class cl = resolveProxyClass(intfs);
  284. setBlockDataMode(oldmode);
  285. ObjectStreamClass osc = lookupClass(cl);
  286. if (osc.firstNonSerializableParentConstructor == null)
  287. {
  288. osc.realClassIsSerializable = true;
  289. osc.fields = osc.fieldMapping = new ObjectStreamField[0];
  290. try
  291. {
  292. osc.firstNonSerializableParentConstructor =
  293. Object.class.getConstructor(new Class[0]);
  294. }
  295. catch (NoSuchMethodException x)
  296. {
  297. throw (InternalError)
  298. new InternalError("Object ctor missing").initCause(x);
  299. }
  300. }
  301. /* GCJ LOCAL */
  302. rememberHandle(osc,shared,handle);
  303. /* END GCJ LOCAL */
  304. if (!is_consumed)
  305. {
  306. byte b = this.realInputStream.readByte();
  307. if (b != TC_ENDBLOCKDATA)
  308. throw new IOException("Data annotated to class was not consumed." + b);
  309. }
  310. else
  311. is_consumed = false;
  312. ObjectStreamClass superosc = (ObjectStreamClass)readObject();
  313. osc.setSuperclass(superosc);
  314. ret_val = osc;
  315. break;
  316. }
  317. case TC_CLASSDESC:
  318. {
  319. ObjectStreamClass osc = readClassDescriptor();
  320. if (!is_consumed)
  321. {
  322. byte b = this.realInputStream.readByte();
  323. if (b != TC_ENDBLOCKDATA)
  324. throw new IOException("Data annotated to class was not consumed." + b);
  325. }
  326. else
  327. is_consumed = false;
  328. osc.setSuperclass ((ObjectStreamClass)readObject());
  329. ret_val = osc;
  330. break;
  331. }
  332. case TC_STRING:
  333. {
  334. if(dump) dumpElement("STRING=");
  335. String s = this.realInputStream.readUTF();
  336. if(dump) dumpElementln(s);
  337. ret_val = processResolution(null, s, assignNewHandle(s,shared),
  338. shared);
  339. break;
  340. }
  341. case TC_LONGSTRING:
  342. {
  343. if(dump) dumpElement("STRING=");
  344. String s = this.realInputStream.readUTFLong();
  345. if(dump) dumpElementln(s);
  346. ret_val = processResolution(null, s, assignNewHandle(s,shared),
  347. shared);
  348. break;
  349. }
  350. case TC_ARRAY:
  351. {
  352. if(dump) dumpElementln("ARRAY");
  353. ObjectStreamClass osc = (ObjectStreamClass)readObject();
  354. Class componentType = osc.forClass().getComponentType();
  355. if(dump) dumpElement("ARRAY LENGTH=");
  356. int length = this.realInputStream.readInt();
  357. if(dump) dumpElementln (length + "; COMPONENT TYPE=" + componentType);
  358. Object array = Array.newInstance(componentType, length);
  359. int handle = assignNewHandle(array,shared);
  360. readArrayElements(array, componentType);
  361. if(dump)
  362. for (int i = 0, len = Array.getLength(array); i < len; i++)
  363. dumpElementln(" ELEMENT[" + i + "]=", Array.get(array, i));
  364. ret_val = processResolution(null, array, handle, shared);
  365. break;
  366. }
  367. case TC_OBJECT:
  368. {
  369. if(dump) dumpElementln("OBJECT");
  370. ObjectStreamClass osc = (ObjectStreamClass)readObject();
  371. Class clazz = osc.forClass();
  372. if (!osc.realClassIsSerializable)
  373. throw new NotSerializableException
  374. (clazz + " is not Serializable, and thus cannot be deserialized.");
  375. if (osc.realClassIsExternalizable)
  376. {
  377. Externalizable obj = osc.newInstance();
  378. int handle = assignNewHandle(obj,shared);
  379. boolean read_from_blocks = ((osc.getFlags() & SC_BLOCK_DATA) != 0);
  380. boolean oldmode = this.readDataFromBlock;
  381. if (read_from_blocks)
  382. setBlockDataMode(true);
  383. obj.readExternal(this);
  384. if (read_from_blocks)
  385. {
  386. setBlockDataMode(oldmode);
  387. if (!oldmode)
  388. if (this.realInputStream.readByte() != TC_ENDBLOCKDATA)
  389. throw new IOException("No end of block data seen for class with readExternal (ObjectInputStream) method.");
  390. }
  391. ret_val = processResolution(osc, obj, handle,shared);
  392. break;
  393. } // end if (osc.realClassIsExternalizable)
  394. Object obj = newObject(clazz, osc.firstNonSerializableParentConstructor);
  395. int handle = assignNewHandle(obj,shared);
  396. Object prevObject = this.currentObject;
  397. ObjectStreamClass prevObjectStreamClass = this.currentObjectStreamClass;
  398. TreeSet<ValidatorAndPriority> prevObjectValidators =
  399. this.currentObjectValidators;
  400. this.currentObject = obj;
  401. this.currentObjectValidators = null;
  402. ObjectStreamClass[] hierarchy = hierarchy(clazz);
  403. for (int i = 0; i < hierarchy.length; i++)
  404. {
  405. this.currentObjectStreamClass = hierarchy[i];
  406. if(dump) dumpElementln("Reading fields of " + this.currentObjectStreamClass.getName ());
  407. // XXX: should initialize fields in classes in the hierarchy
  408. // that aren't in the stream
  409. // should skip over classes in the stream that aren't in the
  410. // real classes hierarchy
  411. Method readObjectMethod = this.currentObjectStreamClass.readObjectMethod;
  412. if (readObjectMethod != null)
  413. {
  414. fieldsAlreadyRead = false;
  415. boolean oldmode = setBlockDataMode(true);
  416. callReadMethod(readObjectMethod, this.currentObjectStreamClass.forClass(), obj);
  417. setBlockDataMode(oldmode);
  418. }
  419. else
  420. {
  421. readFields(obj, currentObjectStreamClass);
  422. }
  423. if (this.currentObjectStreamClass.hasWriteMethod())
  424. {
  425. if(dump) dumpElement("ENDBLOCKDATA? ");
  426. try
  427. {
  428. /* Read blocks until an end marker */
  429. byte writeMarker = this.realInputStream.readByte();
  430. while (writeMarker != TC_ENDBLOCKDATA)
  431. {
  432. parseContent(writeMarker, shared);
  433. writeMarker = this.realInputStream.readByte();
  434. }
  435. if(dump) dumpElementln("yes");
  436. }
  437. catch (EOFException e)
  438. {
  439. throw (IOException) new IOException
  440. ("No end of block data seen for class with readObject (ObjectInputStream) method.").initCause(e);
  441. }
  442. }
  443. }
  444. this.currentObject = prevObject;
  445. this.currentObjectStreamClass = prevObjectStreamClass;
  446. ret_val = processResolution(osc, obj, handle, shared);
  447. if (currentObjectValidators != null)
  448. invokeValidators();
  449. this.currentObjectValidators = prevObjectValidators;
  450. break;
  451. }
  452. case TC_RESET:
  453. if(dump) dumpElementln("RESET");
  454. clearHandles();
  455. ret_val = readObject();
  456. break;
  457. case TC_EXCEPTION:
  458. {
  459. if(dump) dumpElement("EXCEPTION=");
  460. Exception e = (Exception)readObject();
  461. if(dump) dumpElementln(e.toString());
  462. clearHandles();
  463. throw new WriteAbortedException("Exception thrown during writing of stream", e);
  464. }
  465. case TC_ENUM:
  466. {
  467. /* TC_ENUM classDesc newHandle enumConstantName */
  468. if (dump)
  469. dumpElementln("ENUM=");
  470. ObjectStreamClass osc = (ObjectStreamClass) readObject();
  471. int enumHandle = assignNewHandle(null, shared);
  472. String constantName = (String) readObject();
  473. if (dump)
  474. dumpElementln("CONSTANT NAME = " + constantName);
  475. Class clazz = osc.forClass();
  476. Enum instance = Enum.valueOf(clazz, constantName);
  477. rememberHandle(instance, shared, enumHandle);
  478. ret_val = instance;
  479. break;
  480. }
  481. default:
  482. throw new IOException("Unknown marker on stream: " + marker);
  483. }
  484. return ret_val;
  485. }
  486. /**
  487. * This method makes a partial check of types for the fields
  488. * contained given in arguments. It checks primitive types of
  489. * fields1 against non primitive types of fields2. This method
  490. * assumes the two lists has already been sorted according to
  491. * the Java specification.
  492. *
  493. * @param name Name of the class owning the given fields.
  494. * @param fields1 First list to check.
  495. * @param fields2 Second list to check.
  496. * @throws InvalidClassException if a field in fields1, which has a primitive type, is a present
  497. * in the non primitive part in fields2.
  498. */
  499. private void checkTypeConsistency(String name, ObjectStreamField[] fields1, ObjectStreamField[] fields2)
  500. throws InvalidClassException
  501. {
  502. int nonPrimitive = 0;
  503. for (nonPrimitive = 0;
  504. nonPrimitive < fields1.length
  505. && fields1[nonPrimitive].isPrimitive(); nonPrimitive++)
  506. {
  507. }
  508. if (nonPrimitive == fields1.length)
  509. return;
  510. int i = 0;
  511. ObjectStreamField f1;
  512. ObjectStreamField f2;
  513. while (i < fields2.length
  514. && nonPrimitive < fields1.length)
  515. {
  516. f1 = fields1[nonPrimitive];
  517. f2 = fields2[i];
  518. if (!f2.isPrimitive())
  519. break;
  520. int compVal = f1.getName().compareTo (f2.getName());
  521. if (compVal < 0)
  522. {
  523. nonPrimitive++;
  524. }
  525. else if (compVal > 0)
  526. {
  527. i++;
  528. }
  529. else
  530. {
  531. throw new InvalidClassException
  532. ("invalid field type for " + f2.getName() +
  533. " in class " + name);
  534. }
  535. }
  536. }
  537. /**
  538. * This method reads a class descriptor from the real input stream
  539. * and use these data to create a new instance of ObjectStreamClass.
  540. * Fields are sorted and ordered for the real read which occurs for
  541. * each instance of the described class. Be aware that if you call that
  542. * method you must ensure that the stream is synchronized, in the other
  543. * case it may be completely desynchronized.
  544. *
  545. * @return A new instance of ObjectStreamClass containing the freshly
  546. * created descriptor.
  547. * @throws ClassNotFoundException if the required class to build the
  548. * descriptor has not been found in the system.
  549. * @throws IOException An input/output error occured.
  550. * @throws InvalidClassException If there was a compatibility problem
  551. * between the class present in the system and the serialized class.
  552. */
  553. protected ObjectStreamClass readClassDescriptor()
  554. throws ClassNotFoundException, IOException
  555. {
  556. if(dump) dumpElement("CLASSDESC NAME=");
  557. String name = this.realInputStream.readUTF();
  558. if(dump) dumpElement(name + "; UID=");
  559. long uid = this.realInputStream.readLong ();
  560. if(dump) dumpElement(Long.toHexString(uid) + "; FLAGS=");
  561. byte flags = this.realInputStream.readByte ();
  562. if(dump) dumpElement(Integer.toHexString(flags) + "; FIELD COUNT=");
  563. short field_count = this.realInputStream.readShort();
  564. if(dump) dumpElementln(Short.toString(field_count));
  565. ObjectStreamField[] fields = new ObjectStreamField[field_count];
  566. ObjectStreamClass osc = new ObjectStreamClass(name, uid,
  567. flags, fields);
  568. assignNewHandle(osc,true);
  569. for (int i = 0; i < field_count; i++)
  570. {
  571. if(dump) dumpElement(" TYPE CODE=");
  572. char type_code = (char)this.realInputStream.readByte();
  573. if(dump) dumpElement(type_code + "; FIELD NAME=");
  574. String field_name = this.realInputStream.readUTF();
  575. if(dump) dumpElementln(field_name);
  576. String class_name;
  577. // If the type code is an array or an object we must
  578. // decode a String here. In the other case we convert
  579. // the type code and pass it to ObjectStreamField.
  580. // Type codes are decoded by gnu.java.lang.reflect.TypeSignature.
  581. if (type_code == 'L' || type_code == '[')
  582. class_name = (String)readObject();
  583. else
  584. class_name = String.valueOf(type_code);
  585. fields[i] =
  586. new ObjectStreamField(field_name, class_name);
  587. }
  588. /* Now that fields have been read we may resolve the class
  589. * (and read annotation if needed). */
  590. Class clazz = resolveClass(osc);
  591. ClassLoader loader = clazz.getClassLoader();
  592. for (int i = 0; i < field_count; i++)
  593. {
  594. fields[i].resolveType(loader);
  595. }
  596. boolean oldmode = setBlockDataMode(true);
  597. osc.setClass(clazz, lookupClass(clazz.getSuperclass()));
  598. classLookupTable.put(clazz, osc);
  599. setBlockDataMode(oldmode);
  600. // find the first non-serializable class in clazz's inheritance hierarchy
  601. Class first_nonserial = clazz.getSuperclass();
  602. // Maybe it is a primitive class, those don't have a super class,
  603. // or Object itself. Otherwise we can keep getting the superclass
  604. // till we hit the Object class, or some other non-serializable class.
  605. if (first_nonserial == null)
  606. first_nonserial = clazz;
  607. else
  608. while (Serializable.class.isAssignableFrom(first_nonserial))
  609. first_nonserial = first_nonserial.getSuperclass();
  610. final Class local_constructor_class = first_nonserial;
  611. osc.firstNonSerializableParentConstructor =
  612. (Constructor)AccessController.doPrivileged(new PrivilegedAction()
  613. {
  614. public Object run()
  615. {
  616. try
  617. {
  618. Constructor c = local_constructor_class.
  619. getDeclaredConstructor(new Class[0]);
  620. if (Modifier.isPrivate(c.getModifiers()))
  621. return null;
  622. return c;
  623. }
  624. catch (NoSuchMethodException e)
  625. {
  626. // error will be reported later, in newObject()
  627. return null;
  628. }
  629. }
  630. });
  631. osc.realClassIsSerializable = Serializable.class.isAssignableFrom(clazz);
  632. osc.realClassIsExternalizable = Externalizable.class.isAssignableFrom(clazz);
  633. ObjectStreamField[] stream_fields = osc.fields;
  634. ObjectStreamField[] real_fields = ObjectStreamClass.lookupForClassObject(clazz).fields;
  635. ObjectStreamField[] fieldmapping = new ObjectStreamField[2 * Math.max(stream_fields.length, real_fields.length)];
  636. int stream_idx = 0;
  637. int real_idx = 0;
  638. int map_idx = 0;
  639. /*
  640. * Check that there is no type inconsistencies between the lists.
  641. * A special checking must be done for the two groups: primitive types and
  642. * not primitive types.
  643. */
  644. checkTypeConsistency(name, real_fields, stream_fields);
  645. checkTypeConsistency(name, stream_fields, real_fields);
  646. while (stream_idx < stream_fields.length
  647. || real_idx < real_fields.length)
  648. {
  649. ObjectStreamField stream_field = null;
  650. ObjectStreamField real_field = null;
  651. if (stream_idx == stream_fields.length)
  652. {
  653. real_field = real_fields[real_idx++];
  654. }
  655. else if (real_idx == real_fields.length)
  656. {
  657. stream_field = stream_fields[stream_idx++];
  658. }
  659. else
  660. {
  661. int comp_val =
  662. real_fields[real_idx].compareTo (stream_fields[stream_idx]);
  663. if (comp_val < 0)
  664. {
  665. real_field = real_fields[real_idx++];
  666. }
  667. else if (comp_val > 0)
  668. {
  669. stream_field = stream_fields[stream_idx++];
  670. }
  671. else
  672. {
  673. stream_field = stream_fields[stream_idx++];
  674. real_field = real_fields[real_idx++];
  675. if (stream_field.getType() != real_field.getType())
  676. throw new InvalidClassException
  677. ("invalid field type for " + real_field.getName() +
  678. " in class " + name);
  679. }
  680. }
  681. /* If some of stream_fields does not correspond to any of real_fields,
  682. * or the opposite, then fieldmapping will go short.
  683. */
  684. if (map_idx == fieldmapping.length)
  685. {
  686. ObjectStreamField[] newfieldmapping =
  687. new ObjectStreamField[fieldmapping.length + 2];
  688. System.arraycopy(fieldmapping, 0,
  689. newfieldmapping, 0, fieldmapping.length);
  690. fieldmapping = newfieldmapping;
  691. }
  692. fieldmapping[map_idx++] = stream_field;
  693. fieldmapping[map_idx++] = real_field;
  694. }
  695. osc.fieldMapping = fieldmapping;
  696. return osc;
  697. }
  698. /**
  699. * Reads the current objects non-transient, non-static fields from
  700. * the current class from the underlying output stream.
  701. *
  702. * This method is intended to be called from within a object's
  703. * <code>private void readObject (ObjectInputStream)</code>
  704. * method.
  705. *
  706. * @exception ClassNotFoundException The class that an object being
  707. * read in belongs to cannot be found.
  708. *
  709. * @exception NotActiveException This method was called from a
  710. * context other than from the current object's and current class's
  711. * <code>private void readObject (ObjectInputStream)</code>
  712. * method.
  713. *
  714. * @exception IOException Exception from underlying
  715. * <code>OutputStream</code>.
  716. */
  717. public void defaultReadObject()
  718. throws ClassNotFoundException, IOException, NotActiveException
  719. {
  720. if (this.currentObject == null || this.currentObjectStreamClass == null)
  721. throw new NotActiveException("defaultReadObject called by non-active"
  722. + " class and/or object");
  723. if (fieldsAlreadyRead)
  724. throw new NotActiveException("defaultReadObject called but fields "
  725. + "already read from stream (by "
  726. + "defaultReadObject or readFields)");
  727. boolean oldmode = setBlockDataMode(false);
  728. readFields(this.currentObject, this.currentObjectStreamClass);
  729. setBlockDataMode(oldmode);
  730. fieldsAlreadyRead = true;
  731. }
  732. /**
  733. * Registers a <code>ObjectInputValidation</code> to be carried out
  734. * on the object graph currently being deserialized before it is
  735. * returned to the original caller of <code>readObject ()</code>.
  736. * The order of validation for multiple
  737. * <code>ObjectInputValidation</code>s can be controled using
  738. * <code>priority</code>. Validators with higher priorities are
  739. * called first.
  740. *
  741. * @see java.io.ObjectInputValidation
  742. *
  743. * @exception InvalidObjectException <code>validator</code> is
  744. * <code>null</code>
  745. *
  746. * @exception NotActiveException an attempt was made to add a
  747. * validator outside of the <code>readObject</code> method of the
  748. * object currently being deserialized
  749. */
  750. public void registerValidation(ObjectInputValidation validator,
  751. int priority)
  752. throws InvalidObjectException, NotActiveException
  753. {
  754. if (this.currentObject == null || this.currentObjectStreamClass == null)
  755. throw new NotActiveException("registerValidation called by non-active "
  756. + "class and/or object");
  757. if (validator == null)
  758. throw new InvalidObjectException("attempt to add a null "
  759. + "ObjectInputValidation object");
  760. if (currentObjectValidators == null)
  761. currentObjectValidators = new TreeSet<ValidatorAndPriority>();
  762. currentObjectValidators.add(new ValidatorAndPriority(validator, priority));
  763. }
  764. /**
  765. * Called when a class is being deserialized. This is a hook to
  766. * allow subclasses to read in information written by the
  767. * <code>annotateClass (Class)</code> method of an
  768. * <code>ObjectOutputStream</code>.
  769. *
  770. * This implementation looks up the active call stack for a
  771. * <code>ClassLoader</code>; if a <code>ClassLoader</code> is found,
  772. * it is used to load the class associated with <code>osc</code>,
  773. * otherwise, the default system <code>ClassLoader</code> is used.
  774. *
  775. * @exception IOException Exception from underlying
  776. * <code>OutputStream</code>.
  777. *
  778. * @see java.io.ObjectOutputStream#annotateClass (java.lang.Class)
  779. */
  780. protected Class<?> resolveClass(ObjectStreamClass osc)
  781. throws ClassNotFoundException, IOException
  782. {
  783. String name = osc.getName();
  784. try
  785. {
  786. return Class.forName(name, true, currentLoader());
  787. }
  788. catch(ClassNotFoundException x)
  789. {
  790. if (name.equals("void"))
  791. return Void.TYPE;
  792. else if (name.equals("boolean"))
  793. return Boolean.TYPE;
  794. else if (name.equals("byte"))
  795. return Byte.TYPE;
  796. else if (name.equals("char"))
  797. return Character.TYPE;
  798. else if (name.equals("short"))
  799. return Short.TYPE;
  800. else if (name.equals("int"))
  801. return Integer.TYPE;
  802. else if (name.equals("long"))
  803. return Long.TYPE;
  804. else if (name.equals("float"))
  805. return Float.TYPE;
  806. else if (name.equals("double"))
  807. return Double.TYPE;
  808. else
  809. throw x;
  810. }
  811. }
  812. /**
  813. * Returns the most recent user defined ClassLoader on the execution stack
  814. * or null if none is found.
  815. */
  816. private ClassLoader currentLoader()
  817. {
  818. return VMStackWalker.firstNonNullClassLoader();
  819. }
  820. /**
  821. * Lookup a class stored in the local hashtable. If it is not
  822. * use the global lookup function in ObjectStreamClass to build
  823. * the ObjectStreamClass. This method is requested according to
  824. * the behaviour detected in the JDK by Kaffe's team.
  825. *
  826. * @param clazz Class to lookup in the hash table or for which
  827. * we must build a descriptor.
  828. * @return A valid instance of ObjectStreamClass corresponding
  829. * to the specified class.
  830. */
  831. private ObjectStreamClass lookupClass(Class clazz)
  832. {
  833. if (clazz == null)
  834. return null;
  835. ObjectStreamClass oclazz;
  836. oclazz = classLookupTable.get(clazz);
  837. if (oclazz == null)
  838. return ObjectStreamClass.lookup(clazz);
  839. else
  840. return oclazz;
  841. }
  842. /**
  843. * Reconstruct class hierarchy the same way {@link
  844. * java.io.ObjectStreamClass#hierarchy} does but using lookupClass
  845. * instead of ObjectStreamClass.lookup.
  846. *
  847. * @param clazz This is the class for which we want the hierarchy.
  848. *
  849. * @return An array of valid {@link java.io.ObjectStreamClass} instances which
  850. * represent the class hierarchy for clazz.
  851. */
  852. private ObjectStreamClass[] hierarchy(Class clazz)
  853. {
  854. ObjectStreamClass osc = lookupClass(clazz);
  855. return osc == null ? new ObjectStreamClass[0] : osc.hierarchy();
  856. }
  857. /**
  858. * Allows subclasses to resolve objects that are read from the
  859. * stream with other objects to be returned in their place. This
  860. * method is called the first time each object is encountered.
  861. *
  862. * This method must be enabled before it will be called in the
  863. * serialization process.
  864. *
  865. * @exception IOException Exception from underlying
  866. * <code>OutputStream</code>.
  867. *
  868. * @see #enableResolveObject(boolean)
  869. */
  870. protected Object resolveObject(Object obj) throws IOException
  871. {
  872. return obj;
  873. }
  874. protected Class<?> resolveProxyClass(String[] intfs)
  875. throws IOException, ClassNotFoundException
  876. {
  877. ClassLoader cl = currentLoader();
  878. Class<?>[] clss = new Class<?>[intfs.length];
  879. if(cl == null)
  880. {
  881. for (int i = 0; i < intfs.length; i++)
  882. clss[i] = Class.forName(intfs[i]);
  883. cl = ClassLoader.getSystemClassLoader();
  884. }
  885. else
  886. for (int i = 0; i < intfs.length; i++)
  887. clss[i] = Class.forName(intfs[i], false, cl);
  888. try
  889. {
  890. return Proxy.getProxyClass(cl, clss);
  891. }
  892. catch (IllegalArgumentException e)
  893. {
  894. throw new ClassNotFoundException(null, e);
  895. }
  896. }
  897. /**
  898. * If <code>enable</code> is <code>true</code> and this object is
  899. * trusted, then <code>resolveObject (Object)</code> will be called
  900. * in subsequent calls to <code>readObject (Object)</code>.
  901. * Otherwise, <code>resolveObject (Object)</code> will not be called.
  902. *
  903. * @exception SecurityException This class is not trusted.
  904. */
  905. protected boolean enableResolveObject (boolean enable)
  906. throws SecurityException
  907. {
  908. if (enable)
  909. {
  910. SecurityManager sm = System.getSecurityManager();
  911. if (sm != null)
  912. sm.checkPermission(new SerializablePermission("enableSubstitution"));
  913. }
  914. boolean old_val = this.resolveEnabled;
  915. this.resolveEnabled = enable;
  916. return old_val;
  917. }
  918. /**
  919. * Reads stream magic and stream version information from the
  920. * underlying stream.
  921. *
  922. * @exception IOException Exception from underlying stream.
  923. *
  924. * @exception StreamCorruptedException An invalid stream magic
  925. * number or stream version was read from the stream.
  926. */
  927. protected void readStreamHeader()
  928. throws IOException, StreamCorruptedException
  929. {
  930. if(dump) dumpElement("STREAM MAGIC ");
  931. if (this.realInputStream.readShort() != STREAM_MAGIC)
  932. throw new StreamCorruptedException("Invalid stream magic number");
  933. if(dump) dumpElementln("STREAM VERSION ");
  934. if (this.realInputStream.readShort() != STREAM_VERSION)
  935. throw new StreamCorruptedException("Invalid stream version number");
  936. }
  937. public int read() throws IOException
  938. {
  939. if (this.readDataFromBlock)
  940. {
  941. if (this.blockDataPosition >= this.blockDataBytes)
  942. readNextBlock();
  943. return (this.blockData[this.blockDataPosition++] & 0xff);
  944. }
  945. else
  946. return this.realInputStream.read();
  947. }
  948. public int read(byte[] data, int offset, int length) throws IOException
  949. {
  950. if (this.readDataFromBlock)
  951. {
  952. int remain = this.blockDataBytes - this.blockDataPosition;
  953. if (remain == 0)
  954. {
  955. readNextBlock();
  956. remain = this.blockDataBytes - this.blockDataPosition;
  957. }
  958. length = Math.min(length, remain);
  959. System.arraycopy(this.blockData, this.blockDataPosition,
  960. data, offset, length);
  961. this.blockDataPosition += length;
  962. return length;
  963. }
  964. else
  965. return this.realInputStream.read(data, offset, length);
  966. }
  967. public int available() throws IOException
  968. {
  969. if (this.readDataFromBlock)
  970. {
  971. if (this.blockDataPosition >= this.blockDataBytes)
  972. readNextBlock ();
  973. return this.blockDataBytes - this.blockDataPosition;
  974. }
  975. else
  976. return this.realInputStream.available();
  977. }
  978. public void close() throws IOException
  979. {
  980. this.realInputStream.close();
  981. }
  982. public boolean readBoolean() throws IOException
  983. {
  984. boolean switchmode = true;
  985. boolean oldmode = this.readDataFromBlock;
  986. if (!oldmode || this.blockDataBytes - this.blockDataPosition >= 1)
  987. switchmode = false;
  988. if (switchmode)
  989. oldmode = setBlockDataMode (true);
  990. boolean value = this.dataInputStream.readBoolean ();
  991. if (switchmode)
  992. setBlockDataMode (oldmode);
  993. return value;
  994. }
  995. public byte readByte() throws IOException
  996. {
  997. boolean switchmode = true;
  998. boolean oldmode = this.readDataFromBlock;
  999. if (!oldmode || this.blockDataBytes - this.blockDataPosition >= 1)
  1000. switchmode = false;
  1001. if (switchmode)
  1002. oldmode = setBlockDataMode(true);
  1003. byte value = this.dataInputStream.readByte();
  1004. if (switchmode)
  1005. setBlockDataMode(oldmode);
  1006. return value;
  1007. }
  1008. public int readUnsignedByte() throws IOException
  1009. {
  1010. boolean switchmode = true;
  1011. boolean oldmode = this.readDataFromBlock;
  1012. if (!oldmode || this.blockDataBytes - this.blockDataPosition >= 1)
  1013. switchmode = false;
  1014. if (switchmode)
  1015. oldmode = setBlockDataMode(true);
  1016. int value = this.dataInputStream.readUnsignedByte();
  1017. if (switchmode)
  1018. setBlockDataMode(oldmode);
  1019. return value;
  1020. }
  1021. public short readShort() throws IOException
  1022. {
  1023. boolean switchmode = true;
  1024. boolean oldmode = this.readDataFromBlock;
  1025. if (!oldmode || this.blockDataBytes - this.blockDataPosition >= 2)
  1026. switchmode = false;
  1027. if (switchmode)
  1028. oldmode = setBlockDataMode(true);
  1029. short value = this.dataInputStream.readShort();
  1030. if (switchmode)
  1031. setBlockDataMode(oldmode);
  1032. return value;
  1033. }
  1034. public int readUnsignedShort() throws IOException
  1035. {
  1036. boolean switchmode = true;
  1037. boolean oldmode = this.readDataFromBlock;
  1038. if (!oldmode || this.blockDataBytes - this.blockDataPosition >= 2)
  1039. switchmode = false;
  1040. if (switchmode)
  1041. oldmode = setBlockDataMode(true);
  1042. int value = this.dataInputStream.readUnsignedShort();
  1043. if (switchmode)
  1044. setBlockDataMode(oldmode);
  1045. return value;
  1046. }
  1047. public char readChar() throws IOException
  1048. {
  1049. boolean switchmode = true;
  1050. boolean oldmode = this.readDataFromBlock;
  1051. if (!oldmode || this.blockDataBytes - this.blockDataPosition >= 2)
  1052. switchmode = false;
  1053. if (switchmode)
  1054. oldmode = setBlockDataMode(true);
  1055. char value = this.dataInputStream.readChar();
  1056. if (switchmode)
  1057. setBlockDataMode(oldmode);
  1058. return value;
  1059. }
  1060. public int readInt() throws IOException
  1061. {
  1062. boolean switchmode = true;
  1063. boolean oldmode = this.readDataFromBlock;
  1064. if (!oldmode || this.blockDataBytes - this.blockDataPosition >= 4)
  1065. switchmode = false;
  1066. if (switchmode)
  1067. oldmode = setBlockDataMode(true);
  1068. int value = this.dataInputStream.readInt();
  1069. if (switchmode)
  1070. setBlockDataMode(oldmode);
  1071. return value;
  1072. }
  1073. public long readLong() throws IOException
  1074. {
  1075. boolean switchmode = true;
  1076. boolean oldmode = this.readDataFromBlock;
  1077. if (!oldmode || this.blockDataBytes - this.blockDataPosition >= 8)
  1078. switchmode = false;
  1079. if (switchmode)
  1080. oldmode = setBlockDataMode(true);
  1081. long value = this.dataInputStream.readLong();
  1082. if (switchmode)
  1083. setBlockDataMode(oldmode);
  1084. return value;
  1085. }
  1086. public float readFloat() throws IOException
  1087. {
  1088. boolean switchmode = true;
  1089. boolean oldmode = this.readDataFromBlock;
  1090. if (!oldmode || this.blockDataBytes - this.blockDataPosition >= 4)
  1091. switchmode = false;
  1092. if (switchmode)
  1093. oldmode = setBlockDataMode(true);
  1094. float value = this.dataInputStream.readFloat();
  1095. if (switchmode)
  1096. setBlockDataMode(oldmode);
  1097. return value;
  1098. }
  1099. public double readDouble() throws IOException
  1100. {
  1101. boolean switchmode = true;
  1102. boolean oldmode = this.readDataFromBlock;
  1103. if (!oldmode || this.blockDataBytes - this.blockDataPosition >= 8)
  1104. switchmode = false;
  1105. if (switchmode)
  1106. oldmode = setBlockDataMode(true);
  1107. double value = this.dataInputStream.readDouble();
  1108. if (switchmode)
  1109. setBlockDataMode(oldmode);
  1110. return value;
  1111. }
  1112. public void readFully(byte data[]) throws IOException
  1113. {
  1114. this.dataInputStream.readFully(data);
  1115. }
  1116. public void readFully(byte data[], int offset, int size)
  1117. throws IOException
  1118. {
  1119. this.dataInputStream.readFully(data, offset, size);
  1120. }
  1121. public int skipBytes(int len) throws IOException
  1122. {
  1123. return this.dataInputStream.skipBytes(len);
  1124. }
  1125. /**
  1126. * @deprecated
  1127. * @see java.io.DataInputStream#readLine ()
  1128. */
  1129. public String readLine() throws IOException
  1130. {
  1131. return this.dataInputStream.readLine();
  1132. }
  1133. public String readUTF() throws IOException
  1134. {
  1135. return this.dataInputStream.readUTF();
  1136. }
  1137. /**
  1138. * This class allows a class to specify exactly which fields should
  1139. * be read, and what values should be read for these fields.
  1140. *
  1141. * XXX: finish up comments
  1142. */
  1143. public abstract static class GetField
  1144. {
  1145. public abstract ObjectStreamClass getObjectStreamClass();
  1146. public abstract boolean defaulted(String name)
  1147. throws IOException, IllegalArgumentException;
  1148. public abstract boolean get(String name, boolean defvalue)
  1149. throws IOException, IllegalArgumentException;
  1150. public abstract char get(String name, char defvalue)
  1151. throws IOException, IllegalArgumentException;
  1152. public abstract byte get(String name, byte defvalue)
  1153. throws IOException, IllegalArgumentException;
  1154. public abstract short get(String name, short defvalue)
  1155. throws IOException, IllegalArgumentException;
  1156. public abstract int get(String name, int defvalue)
  1157. throws IOException, IllegalArgumentException;
  1158. public abstract long get(String name, long defvalue)
  1159. throws IOException, IllegalArgumentException;
  1160. public abstract float get(String name, float defvalue)
  1161. throws IOException, IllegalArgumentException;
  1162. public abstract double get(String name, double defvalue)
  1163. throws IOException, IllegalArgumentException;
  1164. public abstract Object get(String name, Object defvalue)
  1165. throws IOException, IllegalArgumentException;
  1166. }
  1167. /**
  1168. * This method should be called by a method called 'readObject' in the
  1169. * deserializing class (if present). It cannot (and should not)be called
  1170. * outside of it. Its goal is to read all fields in the real input stream
  1171. * and keep them accessible through the {@link GetField} class. Calling
  1172. * this method will not alter the deserializing object.
  1173. *
  1174. * @return A valid freshly created 'GetField' instance to get access to
  1175. * the deserialized stream.
  1176. * @throws IOException An input/output exception occured.
  1177. * @throws ClassNotFoundException
  1178. * @throws NotActiveException
  1179. */
  1180. public GetField readFields()
  1181. throws IOException, ClassNotFoundException, NotActiveException
  1182. {
  1183. if (this.currentObject == null || this.currentObjectStreamClass == null)
  1184. throw new NotActiveException("readFields called by non-active class and/or object");
  1185. if (prereadFields != null)
  1186. return prereadFields;
  1187. if (fieldsAlreadyRead)
  1188. throw new NotActiveException("readFields called but fields already read from"
  1189. + " stream (by defaultReadObject or readFields)");
  1190. final ObjectStreamClass clazz = this.currentObjectStreamClass;
  1191. final byte[] prim_field_data = new byte[clazz.primFieldSize];
  1192. final Object[] objs = new Object[clazz.objectFieldCount];
  1193. // Apparently Block data is not used with GetField as per
  1194. // empirical evidence against JDK 1.2. Also see Mauve test
  1195. // java.io.ObjectInputOutput.Test.GetPutField.
  1196. boolean oldmode = setBlockDataMode(false);
  1197. readFully(prim_field_data);
  1198. for (int i = 0; i < objs.length; ++ i)
  1199. objs[i] = readObject();
  1200. setBlockDataMode(oldmode);
  1201. prereadFields = new GetField()
  1202. {
  1203. public ObjectStreamClass getObjectStreamClass()
  1204. {
  1205. return clazz;
  1206. }
  1207. public boolean defaulted(String name)
  1208. throws IOException, IllegalArgumentException
  1209. {
  1210. ObjectStreamField f = clazz.getField(name);
  1211. /* First if we have a serialized field use the descriptor */
  1212. if (f != null)
  1213. {
  1214. /* It is in serialPersistentFields but setClass tells us
  1215. * it should not be set. This value is defaulted.
  1216. */
  1217. if (f.isPersistent() && !f.isToSet())
  1218. return true;
  1219. return false;
  1220. }
  1221. /* This is not a serialized field. There should be
  1222. * a default value only if the field really exists.
  1223. */
  1224. try
  1225. {
  1226. return (clazz.forClass().getDeclaredField (name) != null);
  1227. }
  1228. catch (NoSuchFieldException e)
  1229. {
  1230. throw new IllegalArgumentException(e);
  1231. }
  1232. }
  1233. public boolean get(String name, boolean defvalue)
  1234. throws IOException, IllegalArgumentException
  1235. {
  1236. ObjectStreamField field = getField(name, Boolean.TYPE);
  1237. if (field == null)
  1238. return defvalue;
  1239. return prim_field_data[field.getOffset()] == 0 ? false : true;
  1240. }
  1241. public char get(String name, char defvalue)
  1242. throws IOException, IllegalArgumentException
  1243. {
  1244. ObjectStreamField field = getField(name, Character.TYPE);
  1245. if (field == null)
  1246. return defvalue;
  1247. int off = field.getOffset();
  1248. return (char)(((prim_field_data[off++] & 0xFF) << 8)
  1249. | (prim_field_data[off] & 0xFF));
  1250. }
  1251. public byte get(String name, byte defvalue)
  1252. throws IOException, IllegalArgumentException
  1253. {
  1254. ObjectStreamField field = getField(name, Byte.TYPE);
  1255. if (field == null)
  1256. return defvalue;
  1257. return prim_field_data[field.getOffset()];
  1258. }
  1259. public short get(String name, short defvalue)
  1260. throws IOException, IllegalArgumentException
  1261. {
  1262. ObjectStreamField field = getField(name, Short.TYPE);
  1263. if (field == null)
  1264. return defvalue;
  1265. int off = field.getOffset();
  1266. return (short)(((prim_field_data[off++] & 0xFF) << 8)
  1267. | (prim_field_data[off] & 0xFF));
  1268. }
  1269. public int get(String name, int defvalue)
  1270. throws IOException, IllegalArgumentException
  1271. {
  1272. ObjectStreamField field = getField(name, Integer.TYPE);
  1273. if (field == null)
  1274. return defvalue;
  1275. int off = field.getOffset();
  1276. return ((prim_field_data[off++] & 0xFF) << 24)
  1277. | ((prim_field_data[off++] & 0xFF) << 16)
  1278. | ((prim_field_data[off++] & 0xFF) << 8)
  1279. | (prim_field_data[off] & 0xFF);
  1280. }
  1281. public long get(String name, long defvalue)
  1282. throws IOException, IllegalArgumentException
  1283. {
  1284. ObjectStreamField field = getField(name, Long.TYPE);
  1285. if (field == null)
  1286. return defvalue;
  1287. int off = field.getOffset();
  1288. return (long)(((prim_field_data[off++] & 0xFFL) << 56)
  1289. | ((prim_field_data[off++] & 0xFFL) << 48)
  1290. | ((prim_field_data[off++] & 0xFFL) << 40)
  1291. | ((prim_field_data[off++] & 0xFFL) << 32)
  1292. | ((prim_field_data[off++] & 0xFF) << 24)
  1293. | ((prim_field_data[off++] & 0xFF) << 16)
  1294. | ((prim_field_data[off++] & 0xFF) << 8)
  1295. | (prim_field_data[off] & 0xFF));
  1296. }
  1297. public float get(String name, float defvalue)
  1298. throws IOException, IllegalArgumentException
  1299. {
  1300. ObjectStreamField field = getField(name, Float.TYPE);
  1301. if (field == null)
  1302. return defvalue;
  1303. int off = field.getOffset();
  1304. return Float.intBitsToFloat(((prim_field_data[off++] & 0xFF) << 24)
  1305. | ((prim_field_data[off++] & 0xFF) << 16)
  1306. | ((prim_field_data[off++] & 0xFF) << 8)
  1307. | (prim_field_data[off] & 0xFF));
  1308. }
  1309. public double get(String name, double defvalue)
  1310. throws IOException, IllegalArgumentException
  1311. {
  1312. ObjectStreamField field = getField(name, Double.TYPE);
  1313. if (field == null)
  1314. return defvalue;
  1315. int off = field.getOffset();
  1316. return Double.longBitsToDouble
  1317. ( (long) (((prim_field_data[off++] & 0xFFL) << 56)
  1318. | ((prim_field_data[off++] & 0xFFL) << 48)
  1319. | ((prim_field_data[off++] & 0xFFL) << 40)
  1320. | ((prim_field_data[off++] & 0xFFL) << 32)
  1321. | ((prim_field_data[off++] & 0xFF) << 24)
  1322. | ((prim_field_data[off++] & 0xFF) << 16)
  1323. | ((prim_field_data[off++] & 0xFF) << 8)
  1324. | (prim_field_data[off] & 0xFF)));
  1325. }
  1326. public Object get(String name, Object defvalue)
  1327. throws IOException, IllegalArgumentException
  1328. {
  1329. ObjectStreamField field =
  1330. getField(name, defvalue == null ? null : defvalue.getClass ());
  1331. if (field == null)
  1332. return defvalue;
  1333. return objs[field.getOffset()];
  1334. }
  1335. private ObjectStreamField getField(String name, Class type)
  1336. throws IllegalArgumentException
  1337. {
  1338. ObjectStreamField field = clazz.getField(name);
  1339. boolean illegal = false;
  1340. // XXX This code is horrible and needs to be rewritten!
  1341. try
  1342. {
  1343. try
  1344. {
  1345. Class field_type = field.getType();
  1346. if (type == field_type ||
  1347. (type == null && !field_type.isPrimitive()))
  1348. {
  1349. /* See defaulted */
  1350. return field;
  1351. }
  1352. illegal = true;
  1353. throw new IllegalArgumentException
  1354. ("Field requested is of type "
  1355. + field_type.getName()
  1356. + ", but requested type was "
  1357. + (type == null ? "Object" : type.getName()));
  1358. }
  1359. catch (NullPointerException _)
  1360. {
  1361. /* Here we catch NullPointerException, because it may
  1362. only come from the call 'field.getType()'. If field
  1363. is null, we have to return null and classpath ethic
  1364. say we must try to avoid 'if (xxx == null)'.
  1365. */
  1366. }
  1367. catch (IllegalArgumentException e)
  1368. {
  1369. throw e;
  1370. }
  1371. return null;
  1372. }
  1373. finally
  1374. {
  1375. /* If this is an unassigned field we should return
  1376. * the default value.
  1377. */
  1378. if (!illegal && field != null && !field.isToSet() && field.isPersistent())
  1379. return null;
  1380. /* We do not want to modify transient fields. They should
  1381. * be left to 0.
  1382. */
  1383. try
  1384. {
  1385. Field f = clazz.forClass().getDeclaredField(name);
  1386. if (Modifier.isTransient(f.getModifiers()))
  1387. throw new IllegalArgumentException
  1388. ("no such field (non transient) " + name);
  1389. if (field == null && f.getType() != type)
  1390. throw new IllegalArgumentException
  1391. ("Invalid requested type for field " + name);
  1392. }
  1393. catch (NoSuchFieldException e)
  1394. {
  1395. if (field == null)
  1396. throw new IllegalArgumentException(e);
  1397. }
  1398. }
  1399. }
  1400. };
  1401. fieldsAlreadyRead = true;
  1402. return prereadFields;
  1403. }
  1404. /**
  1405. * Protected constructor that allows subclasses to override
  1406. * deserialization. This constructor should be called by subclasses
  1407. * that wish to override <code>readObject (Object)</code>. This
  1408. * method does a security check <i>NOTE: currently not
  1409. * implemented</i>, then sets a flag that informs
  1410. * <code>readObject (Object)</code> to call the subclasses
  1411. * <code>readObjectOverride (Object)</code> method.
  1412. *
  1413. * @see #readObjectOverride()
  1414. */
  1415. protected ObjectInputStream()
  1416. throws IOException, SecurityException
  1417. {
  1418. SecurityManager sec_man = System.getSecurityManager();
  1419. if (sec_man != null)
  1420. sec_man.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION);
  1421. this.useSubclassMethod = true;
  1422. }
  1423. /**
  1424. * This method allows subclasses to override the default
  1425. * de serialization mechanism provided by
  1426. * <code>ObjectInputStream</code>. To make this method be used for
  1427. * writing objects, subclasses must invoke the 0-argument
  1428. * constructor on this class from their constructor.
  1429. *
  1430. * @see #ObjectInputStream()
  1431. */
  1432. protected Object readObjectOverride()
  1433. throws ClassNotFoundException, IOException, OptionalDataException
  1434. {
  1435. throw new IOException("Subclass of ObjectInputStream must implement readObjectOverride");
  1436. }
  1437. /**
  1438. * Assigns the next available handle to <code>obj</code>.
  1439. *
  1440. * @param obj The object for which we want a new handle.
  1441. * @param shared True if the handle should be shared
  1442. * with later calls.
  1443. * @return A valid handle for the specified object.
  1444. */
  1445. private int assignNewHandle(Object obj, boolean shared)
  1446. {
  1447. int handle = this.nextOID;
  1448. this.nextOID = handle + 1;
  1449. rememberHandle(obj,shared,handle);
  1450. return handle;
  1451. }
  1452. /**
  1453. * Remember the object associated with the given handle.
  1454. *
  1455. * @param obj an object
  1456. * @param shared true if the reference should be shared
  1457. * with later calls.
  1458. * @param handle a handle, must be >= baseWireHandle
  1459. *
  1460. * @see #lookupHandle
  1461. */
  1462. private void rememberHandle(Object obj, boolean shared,
  1463. int handle)
  1464. {
  1465. handles.put(handle, new Pair<Boolean,Object>(shared, obj));
  1466. }
  1467. /**
  1468. * Look up the object associated with a given handle.
  1469. *
  1470. * @param handle a handle, must be >= baseWireHandle
  1471. * @return the object remembered for handle or null if none.
  1472. * @throws StreamCorruptedException if the handle is invalid.
  1473. * @throws InvalidObjectException if the reference is not shared.
  1474. * @see #rememberHandle
  1475. */
  1476. private Object lookupHandle(int handle)
  1477. throws ObjectStreamException
  1478. {
  1479. Pair<Boolean,Object> result = handles.get(handle);
  1480. if (result == null)
  1481. throw new StreamCorruptedException("The handle, " +
  1482. Integer.toHexString(handle) +
  1483. ", is invalid.");
  1484. if (!result.getLeft())
  1485. throw new InvalidObjectException("The handle, " +
  1486. Integer.toHexString(handle) +
  1487. ", is not shared.");
  1488. return result.getRight();
  1489. }
  1490. private Object processResolution(ObjectStreamClass osc, Object obj, int handle,
  1491. boolean shared)
  1492. throws IOException
  1493. {
  1494. if (osc != null && obj instanceof Serializable)
  1495. {
  1496. try
  1497. {
  1498. Method m = osc.readResolveMethod;
  1499. if(m != null)
  1500. {
  1501. obj = m.invoke(obj, new Object[] {});
  1502. }
  1503. }
  1504. catch (IllegalAccessException ignore)
  1505. {
  1506. }
  1507. catch (InvocationTargetException exception)
  1508. {
  1509. Throwable cause = exception.getCause();
  1510. if (cause instanceof ObjectStreamException)
  1511. throw (ObjectStreamException) cause;
  1512. else if (cause instanceof RuntimeException)
  1513. throw (RuntimeException) cause;
  1514. else if (cause instanceof Error)
  1515. throw (Error) cause;
  1516. }
  1517. }
  1518. if (this.resolveEnabled)
  1519. obj = resolveObject(obj);
  1520. rememberHandle(obj, shared, handle);
  1521. if (!shared)
  1522. {
  1523. if (obj instanceof byte[])
  1524. return ((byte[]) obj).clone();
  1525. if (obj instanceof short[])
  1526. return ((short[]) obj).clone();
  1527. if (obj instanceof int[])
  1528. return ((int[]) obj).clone();
  1529. if (obj instanceof long[])
  1530. return ((long[]) obj).clone();
  1531. if (obj instanceof char[])
  1532. return ((char[]) obj).clone();
  1533. if (obj instanceof boolean[])
  1534. return ((boolean[]) obj).clone();
  1535. if (obj instanceof float[])
  1536. return ((float[]) obj).clone();
  1537. if (obj instanceof double[])
  1538. return ((double[]) obj).clone();
  1539. if (obj instanceof Object[])
  1540. return ((Object[]) obj).clone();
  1541. }
  1542. return obj;
  1543. }
  1544. private void clearHandles()
  1545. {
  1546. handles.clear();
  1547. this.nextOID = baseWireHandle;
  1548. }
  1549. private void readNextBlock() throws IOException
  1550. {
  1551. byte marker = this.realInputStream.readByte();
  1552. while (marker == TC_RESET)
  1553. {
  1554. if(dump) dumpElementln("RESET");
  1555. clearHandles();
  1556. marker = this.realInputStream.readByte();
  1557. }
  1558. readNextBlock(marker);
  1559. }
  1560. private void readNextBlock(byte marker) throws IOException
  1561. {
  1562. if (marker == TC_BLOCKDATA)
  1563. {
  1564. if(dump) dumpElement("BLOCK DATA SIZE=");
  1565. this.blockDataBytes = this.realInputStream.readUnsignedByte();
  1566. if(dump) dumpElementln (Integer.toString(this.blockDataBytes));
  1567. }
  1568. else if (marker == TC_BLOCKDATALONG)
  1569. {
  1570. if(dump) dumpElement("BLOCK DATA LONG SIZE=");
  1571. this.blockDataBytes = this.realInputStream.readInt();
  1572. if(dump) dumpElementln (Integer.toString(this.blockDataBytes));
  1573. }
  1574. else
  1575. {
  1576. throw new EOFException("Attempt to read primitive data, but no data block is active.");
  1577. }
  1578. if (this.blockData.length < this.blockDataBytes)
  1579. this.blockData = new byte[this.blockDataBytes];
  1580. this.realInputStream.readFully (this.blockData, 0, this.blockDataBytes);
  1581. this.blockDataPosition = 0;
  1582. }
  1583. private void readArrayElements (Object array, Class clazz)
  1584. throws ClassNotFoundException, IOException
  1585. {
  1586. if (clazz.isPrimitive())
  1587. {
  1588. if (clazz == Boolean.TYPE)
  1589. {
  1590. boolean[] cast_array = (boolean[])array;
  1591. for (int i=0; i < cast_array.length; i++)
  1592. cast_array[i] = this.realInputStream.readBoolean();
  1593. return;
  1594. }
  1595. if (clazz == Byte.TYPE)
  1596. {
  1597. byte[] cast_array = (byte[])array;
  1598. for (int i=0; i < cast_array.length; i++)
  1599. cast_array[i] = this.realInputStream.readByte();
  1600. return;
  1601. }
  1602. if (clazz == Character.TYPE)
  1603. {
  1604. char[] cast_array = (char[])array;
  1605. for (int i=0; i < cast_array.length; i++)
  1606. cast_array[i] = this.realInputStream.readChar();
  1607. return;
  1608. }
  1609. if (clazz == Double.TYPE)
  1610. {
  1611. double[] cast_array = (double[])array;
  1612. for (int i=0; i < cast_array.length; i++)
  1613. cast_array[i] = this.realInputStream.readDouble();
  1614. return;
  1615. }
  1616. if (clazz == Float.TYPE)
  1617. {
  1618. float[] cast_array = (float[])array;
  1619. for (int i=0; i < cast_array.length; i++)
  1620. cast_array[i] = this.realInputStream.readFloat();
  1621. return;
  1622. }
  1623. if (clazz == Integer.TYPE)
  1624. {
  1625. int[] cast_array = (int[])array;
  1626. for (int i=0; i < cast_array.length; i++)
  1627. cast_array[i] = this.realInputStream.readInt();
  1628. return;
  1629. }
  1630. if (clazz == Long.TYPE)
  1631. {
  1632. long[] cast_array = (long[])array;
  1633. for (int i=0; i < cast_array.length; i++)
  1634. cast_array[i] = this.realInputStream.readLong();
  1635. return;
  1636. }
  1637. if (clazz == Short.TYPE)
  1638. {
  1639. short[] cast_array = (short[])array;
  1640. for (int i=0; i < cast_array.length; i++)
  1641. cast_array[i] = this.realInputStream.readShort();
  1642. return;
  1643. }
  1644. }
  1645. else
  1646. {
  1647. Object[] cast_array = (Object[])array;
  1648. for (int i=0; i < cast_array.length; i++)
  1649. cast_array[i] = readObject();
  1650. }
  1651. }
  1652. private void readFields (Object obj, ObjectStreamClass stream_osc)
  1653. throws ClassNotFoundException, IOException
  1654. {
  1655. ObjectStreamField[] fields = stream_osc.fieldMapping;
  1656. for (int i = 0; i < fields.length; i += 2)
  1657. {
  1658. ObjectStreamField stream_field = fields[i];
  1659. ObjectStreamField real_field = fields[i + 1];
  1660. boolean read_value = (stream_field != null && stream_field.getOffset() >= 0 && stream_field.isToSet());
  1661. boolean set_value = (real_field != null && real_field.isToSet());
  1662. String field_name;
  1663. char type;
  1664. if (stream_field != null)
  1665. {
  1666. field_name = stream_field.getName();
  1667. type = stream_field.getTypeCode();
  1668. }
  1669. else
  1670. {
  1671. field_name = real_field.getName();
  1672. type = real_field.getTypeCode();
  1673. }
  1674. switch(type)
  1675. {
  1676. case 'Z':
  1677. {
  1678. boolean value =
  1679. read_value ? this.realInputStream.readBoolean() : false;
  1680. if (dump && read_value && set_value)
  1681. dumpElementln(" " + field_name + ": " + value);
  1682. if (set_value)
  1683. real_field.setBooleanField(obj, value);
  1684. break;
  1685. }
  1686. case 'B':
  1687. {
  1688. byte value =
  1689. read_value ? this.realInputStream.readByte() : 0;
  1690. if (dump && read_value && set_value)
  1691. dumpElementln(" " + field_name + ": " + value);
  1692. if (set_value)
  1693. real_field.setByteField(obj, value);
  1694. break;
  1695. }
  1696. case 'C':
  1697. {
  1698. char value =
  1699. read_value ? this.realInputStream.readChar(): 0;
  1700. if (dump && read_value && set_value)
  1701. dumpElementln(" " + field_name + ": " + value);
  1702. if (set_value)
  1703. real_field.setCharField(obj, value);
  1704. break;
  1705. }
  1706. case 'D':
  1707. {
  1708. double value =
  1709. read_value ? this.realInputStream.readDouble() : 0;
  1710. if (dump && read_value && set_value)
  1711. dumpElementln(" " + field_name + ": " + value);
  1712. if (set_value)
  1713. real_field.setDoubleField(obj, value);
  1714. break;
  1715. }
  1716. case 'F':
  1717. {
  1718. float value =
  1719. read_value ? this.realInputStream.readFloat() : 0;
  1720. if (dump && read_value && set_value)
  1721. dumpElementln(" " + field_name + ": " + value);
  1722. if (set_value)
  1723. real_field.setFloatField(obj, value);
  1724. break;
  1725. }
  1726. case 'I':
  1727. {
  1728. int value =
  1729. read_value ? this.realInputStream.readInt() : 0;
  1730. if (dump && read_value && set_value)
  1731. dumpElementln(" " + field_name + ": " + value);
  1732. if (set_value)
  1733. real_field.setIntField(obj, value);
  1734. break;
  1735. }
  1736. case 'J':
  1737. {
  1738. long value =
  1739. read_value ? this.realInputStream.readLong() : 0;
  1740. if (dump && read_value && set_value)
  1741. dumpElementln(" " + field_name + ": " + value);
  1742. if (set_value)
  1743. real_field.setLongField(obj, value);
  1744. break;
  1745. }
  1746. case 'S':
  1747. {
  1748. short value =
  1749. read_value ? this.realInputStream.readShort() : 0;
  1750. if (dump && read_value && set_value)
  1751. dumpElementln(" " + field_name + ": " + value);
  1752. if (set_value)
  1753. real_field.setShortField(obj, value);
  1754. break;
  1755. }
  1756. case 'L':
  1757. case '[':
  1758. {
  1759. Object value =
  1760. read_value ? readObject() : null;
  1761. if (set_value)
  1762. real_field.setObjectField(obj, value);
  1763. break;
  1764. }
  1765. default:
  1766. throw new InternalError("Invalid type code: " + type);
  1767. }
  1768. }
  1769. }
  1770. // Toggles writing primitive data to block-data buffer.
  1771. private boolean setBlockDataMode (boolean on)
  1772. {
  1773. boolean oldmode = this.readDataFromBlock;
  1774. this.readDataFromBlock = on;
  1775. if (on)
  1776. this.dataInputStream = this.blockDataInput;
  1777. else
  1778. this.dataInputStream = this.realInputStream;
  1779. return oldmode;
  1780. }
  1781. // returns a new instance of REAL_CLASS that has been constructed
  1782. // only to the level of CONSTRUCTOR_CLASS (a super class of REAL_CLASS)
  1783. private Object newObject (Class real_class, Constructor constructor)
  1784. throws ClassNotFoundException, IOException
  1785. {
  1786. if (constructor == null)
  1787. throw new InvalidClassException("Missing accessible no-arg base class constructor for " + real_class.getName());
  1788. try
  1789. {
  1790. return VMObjectInputStream.allocateObject(real_class, constructor.getDeclaringClass(), constructor);
  1791. }
  1792. catch (InstantiationException e)
  1793. {
  1794. throw (ClassNotFoundException) new ClassNotFoundException
  1795. ("Instance of " + real_class + " could not be created").initCause(e);
  1796. }
  1797. }
  1798. // runs all registered ObjectInputValidations in prioritized order
  1799. // on OBJ
  1800. private void invokeValidators() throws InvalidObjectException
  1801. {
  1802. try
  1803. {
  1804. Iterator<ValidatorAndPriority> it = currentObjectValidators.iterator();
  1805. while(it.hasNext())
  1806. {
  1807. ValidatorAndPriority vap = it.next();
  1808. ObjectInputValidation validator = vap.validator;
  1809. validator.validateObject();
  1810. }
  1811. }
  1812. finally
  1813. {
  1814. currentObjectValidators = null;
  1815. }
  1816. }
  1817. private void callReadMethod (Method readObject, Class klass, Object obj)
  1818. throws ClassNotFoundException, IOException
  1819. {
  1820. try
  1821. {
  1822. readObject.invoke(obj, new Object[] { this });
  1823. }
  1824. catch (InvocationTargetException x)
  1825. {
  1826. /* Rethrow if possible. */
  1827. Throwable exception = x.getTargetException();
  1828. if (exception instanceof RuntimeException)
  1829. throw (RuntimeException) exception;
  1830. if (exception instanceof IOException)
  1831. throw (IOException) exception;
  1832. if (exception instanceof ClassNotFoundException)
  1833. throw (ClassNotFoundException) exception;
  1834. throw (IOException) new IOException(
  1835. "Exception thrown from readObject() on " + klass).initCause(x);
  1836. }
  1837. catch (Exception x)
  1838. {
  1839. throw (IOException) new IOException(
  1840. "Failure invoking readObject() on " + klass).initCause(x);
  1841. }
  1842. // Invalidate fields which has been read through readFields.
  1843. prereadFields = null;
  1844. }
  1845. private static final int BUFFER_SIZE = 1024;
  1846. private DataInputStream realInputStream;
  1847. private DataInputStream dataInputStream;
  1848. private DataInputStream blockDataInput;
  1849. private int blockDataPosition;
  1850. private int blockDataBytes;
  1851. private byte[] blockData;
  1852. private boolean useSubclassMethod;
  1853. private int nextOID;
  1854. private boolean resolveEnabled;
  1855. private Map<Integer,Pair<Boolean,Object>> handles;
  1856. private Object currentObject;
  1857. private ObjectStreamClass currentObjectStreamClass;
  1858. private TreeSet<ValidatorAndPriority> currentObjectValidators;
  1859. private boolean readDataFromBlock;
  1860. private boolean fieldsAlreadyRead;
  1861. private Hashtable<Class,ObjectStreamClass> classLookupTable;
  1862. private GetField prereadFields;
  1863. private static boolean dump;
  1864. // The nesting depth for debugging output
  1865. private int depth = 0;
  1866. private static final boolean DEBUG = false;
  1867. private void dumpElement (String msg)
  1868. {
  1869. System.out.print(msg);
  1870. }
  1871. private void dumpElementln (String msg)
  1872. {
  1873. System.out.println(msg);
  1874. for (int i = 0; i < depth; i++)
  1875. System.out.print (" ");
  1876. System.out.print (Thread.currentThread() + ": ");
  1877. }
  1878. private void dumpElementln (String msg, Object obj)
  1879. {
  1880. try
  1881. {
  1882. System.out.print(msg);
  1883. if (java.lang.reflect.Proxy.isProxyClass(obj.getClass()))
  1884. System.out.println(obj.getClass());
  1885. else
  1886. System.out.println(obj);
  1887. }
  1888. catch (Exception _)
  1889. {
  1890. }
  1891. for (int i = 0; i < depth; i++)
  1892. System.out.print (" ");
  1893. System.out.print (Thread.currentThread() + ": ");
  1894. }
  1895. // used to keep a prioritized list of object validators
  1896. private static final class ValidatorAndPriority implements Comparable
  1897. {
  1898. int priority;
  1899. ObjectInputValidation validator;
  1900. ValidatorAndPriority (ObjectInputValidation validator, int priority)
  1901. {
  1902. this.priority = priority;
  1903. this.validator = validator;
  1904. }
  1905. public int compareTo (Object o)
  1906. {
  1907. ValidatorAndPriority vap = (ValidatorAndPriority)o;
  1908. return this.priority - vap.priority;
  1909. }
  1910. }
  1911. }