| 1 | /* ObjectInputStream.java -- Class used to read serialized objects
|
|---|
| 2 | Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
|
|---|
| 3 |
|
|---|
| 4 | This file is part of GNU Classpath.
|
|---|
| 5 |
|
|---|
| 6 | GNU Classpath is free software; you can redistribute it and/or modify
|
|---|
| 7 | it under the terms of the GNU General Public License as published by
|
|---|
| 8 | the Free Software Foundation; either version 2, or (at your option)
|
|---|
| 9 | any later version.
|
|---|
| 10 |
|
|---|
| 11 | GNU Classpath is distributed in the hope that it will be useful, but
|
|---|
| 12 | WITHOUT ANY WARRANTY; without even the implied warranty of
|
|---|
| 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|---|
| 14 | General Public License for more details.
|
|---|
| 15 |
|
|---|
| 16 | You should have received a copy of the GNU General Public License
|
|---|
| 17 | along with GNU Classpath; see the file COPYING. If not, write to the
|
|---|
| 18 | Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
|---|
| 19 | 02111-1307 USA.
|
|---|
| 20 |
|
|---|
| 21 | Linking this library statically or dynamically with other modules is
|
|---|
| 22 | making a combined work based on this library. Thus, the terms and
|
|---|
| 23 | conditions of the GNU General Public License cover the whole
|
|---|
| 24 | combination.
|
|---|
| 25 |
|
|---|
| 26 | As a special exception, the copyright holders of this library give you
|
|---|
| 27 | permission to link this library with independent modules to produce an
|
|---|
| 28 | executable, regardless of the license terms of these independent
|
|---|
| 29 | modules, and to copy and distribute the resulting executable under
|
|---|
| 30 | terms of your choice, provided that you also meet, for each linked
|
|---|
| 31 | independent module, the terms and conditions of the license of that
|
|---|
| 32 | module. An independent module is a module which is not derived from
|
|---|
| 33 | or based on this library. If you modify this library, you may extend
|
|---|
| 34 | this exception to your version of the library, but you are not
|
|---|
| 35 | obligated to do so. If you do not wish to do so, delete this
|
|---|
| 36 | exception statement from your version. */
|
|---|
| 37 |
|
|---|
| 38 |
|
|---|
| 39 | package java.io;
|
|---|
| 40 |
|
|---|
| 41 | import gnu.classpath.Configuration;
|
|---|
| 42 |
|
|---|
| 43 | import java.lang.reflect.Array;
|
|---|
| 44 | import java.lang.reflect.Modifier;
|
|---|
| 45 | import java.util.Arrays;
|
|---|
| 46 | import java.util.Hashtable;
|
|---|
| 47 | import java.util.Vector;
|
|---|
| 48 |
|
|---|
| 49 | import gnu.java.io.ObjectIdentityWrapper;
|
|---|
| 50 | import gnu.java.lang.reflect.TypeSignature;
|
|---|
| 51 | import java.lang.reflect.Field;
|
|---|
| 52 | import java.lang.reflect.Method;
|
|---|
| 53 | import java.lang.reflect.InvocationTargetException;
|
|---|
| 54 |
|
|---|
| 55 |
|
|---|
| 56 |
|
|---|
| 57 | public class ObjectInputStream extends InputStream
|
|---|
| 58 | implements ObjectInput, ObjectStreamConstants
|
|---|
| 59 | {
|
|---|
| 60 | /**
|
|---|
| 61 | Creates a new <code>ObjectInputStream</code> that will do all of
|
|---|
| 62 | its reading from <code>in</code>. This method also checks
|
|---|
| 63 | the stream by reading the header information (stream magic number
|
|---|
| 64 | and stream version).
|
|---|
| 65 |
|
|---|
| 66 | @exception IOException Reading stream header from underlying
|
|---|
| 67 | stream cannot be completed.
|
|---|
| 68 |
|
|---|
| 69 | @exception StreamCorruptedException An invalid stream magic
|
|---|
| 70 | number or stream version was read from the stream.
|
|---|
| 71 |
|
|---|
| 72 | @see readStreamHeader ()
|
|---|
| 73 | */
|
|---|
| 74 | public ObjectInputStream (InputStream in)
|
|---|
| 75 | throws IOException, StreamCorruptedException
|
|---|
| 76 | {
|
|---|
| 77 | if (Configuration.DEBUG)
|
|---|
| 78 | {
|
|---|
| 79 | String val = System.getProperty("gcj.dumpobjects");
|
|---|
| 80 | if (dump == false && val != null && !val.equals(""))
|
|---|
| 81 | {
|
|---|
| 82 | dump = true;
|
|---|
| 83 | System.out.println ("Serialization debugging enabled");
|
|---|
| 84 | }
|
|---|
| 85 | else if (dump == true && (val == null || val.equals("")))
|
|---|
| 86 | {
|
|---|
| 87 | dump = false;
|
|---|
| 88 | System.out.println ("Serialization debugging disabled");
|
|---|
| 89 | }
|
|---|
| 90 | }
|
|---|
| 91 |
|
|---|
| 92 | this.resolveEnabled = false;
|
|---|
| 93 | this.isDeserializing = false;
|
|---|
| 94 | this.blockDataPosition = 0;
|
|---|
| 95 | this.blockDataBytes = 0;
|
|---|
| 96 | this.blockData = new byte[BUFFER_SIZE];
|
|---|
| 97 | this.blockDataInput = new DataInputStream (this);
|
|---|
| 98 | this.realInputStream = new DataInputStream (in);
|
|---|
| 99 | this.nextOID = baseWireHandle;
|
|---|
| 100 | this.objectLookupTable = new Hashtable ();
|
|---|
| 101 | this.validators = new Vector ();
|
|---|
| 102 | setBlockDataMode (true);
|
|---|
| 103 | readStreamHeader ();
|
|---|
| 104 | }
|
|---|
| 105 |
|
|---|
| 106 |
|
|---|
| 107 | /**
|
|---|
| 108 | Returns the next deserialized object read from the underlying stream.
|
|---|
| 109 |
|
|---|
| 110 | This method can be overriden by a class by implementing
|
|---|
| 111 | <code>private void readObject (ObjectInputStream)</code>.
|
|---|
| 112 |
|
|---|
| 113 | If an exception is thrown from this method, the stream is left in
|
|---|
| 114 | an undefined state.
|
|---|
| 115 |
|
|---|
| 116 | @exception ClassNotFoundException The class that an object being
|
|---|
| 117 | read in belongs to cannot be found.
|
|---|
| 118 |
|
|---|
| 119 | @exception IOException Exception from underlying
|
|---|
| 120 | <code>InputStream</code>.
|
|---|
| 121 | */
|
|---|
| 122 | public final Object readObject () throws ClassNotFoundException, IOException
|
|---|
| 123 | {
|
|---|
| 124 | if (this.useSubclassMethod)
|
|---|
| 125 | return readObjectOverride ();
|
|---|
| 126 |
|
|---|
| 127 | boolean was_deserializing;
|
|---|
| 128 |
|
|---|
| 129 | Object ret_val;
|
|---|
| 130 | was_deserializing = this.isDeserializing;
|
|---|
| 131 |
|
|---|
| 132 | if (! was_deserializing)
|
|---|
| 133 | setBlockDataMode (false);
|
|---|
| 134 |
|
|---|
| 135 | this.isDeserializing = true;
|
|---|
| 136 |
|
|---|
| 137 | byte marker = this.realInputStream.readByte ();
|
|---|
| 138 | dumpElement ("MARKER: 0x" + Integer.toHexString(marker) + " ");
|
|---|
| 139 |
|
|---|
| 140 | switch (marker)
|
|---|
| 141 | {
|
|---|
| 142 | case TC_BLOCKDATA:
|
|---|
| 143 | case TC_BLOCKDATALONG:
|
|---|
| 144 | if (marker == TC_BLOCKDATALONG)
|
|---|
| 145 | dumpElementln ("BLOCKDATALONG");
|
|---|
| 146 | else
|
|---|
| 147 | dumpElementln ("BLOCKDATA");
|
|---|
| 148 | readNextBlock (marker);
|
|---|
| 149 | throw new StreamCorruptedException ("Unexpected blockData");
|
|---|
| 150 |
|
|---|
| 151 | case TC_NULL:
|
|---|
| 152 | dumpElementln ("NULL");
|
|---|
| 153 | ret_val = null;
|
|---|
| 154 | break;
|
|---|
| 155 |
|
|---|
| 156 | case TC_REFERENCE:
|
|---|
| 157 | {
|
|---|
| 158 | dumpElement ("REFERENCE ");
|
|---|
| 159 | Integer oid = new Integer (this.realInputStream.readInt ());
|
|---|
| 160 | dumpElementln (Integer.toHexString(oid.intValue()));
|
|---|
| 161 | ret_val = ((ObjectIdentityWrapper)
|
|---|
| 162 | this.objectLookupTable.get (oid)).object;
|
|---|
| 163 | break;
|
|---|
| 164 | }
|
|---|
| 165 |
|
|---|
| 166 | case TC_CLASS:
|
|---|
| 167 | {
|
|---|
| 168 | dumpElementln ("CLASS");
|
|---|
| 169 | ObjectStreamClass osc = (ObjectStreamClass)readObject ();
|
|---|
| 170 | Class clazz = osc.forClass ();
|
|---|
| 171 | assignNewHandle (clazz);
|
|---|
| 172 | ret_val = clazz;
|
|---|
| 173 | break;
|
|---|
| 174 | }
|
|---|
| 175 |
|
|---|
| 176 | case TC_CLASSDESC:
|
|---|
| 177 | {
|
|---|
| 178 | dumpElement ("CLASSDESC NAME=");
|
|---|
| 179 | String name = this.realInputStream.readUTF ();
|
|---|
| 180 | dumpElement (name + "; UID=");
|
|---|
| 181 | long uid = this.realInputStream.readLong ();
|
|---|
| 182 | dumpElement (Long.toHexString(uid) + "; FLAGS=");
|
|---|
| 183 | byte flags = this.realInputStream.readByte ();
|
|---|
| 184 | dumpElement (Integer.toHexString(flags) + "; FIELD COUNT=");
|
|---|
| 185 | short field_count = this.realInputStream.readShort ();
|
|---|
| 186 | dumpElementln (Short.toString(field_count));
|
|---|
| 187 | ObjectStreamField[] fields = new ObjectStreamField[field_count];
|
|---|
| 188 |
|
|---|
| 189 | ObjectStreamClass osc = new ObjectStreamClass (name, uid,
|
|---|
| 190 | flags, fields);
|
|---|
| 191 | assignNewHandle (osc);
|
|---|
| 192 |
|
|---|
| 193 | for (int i=0; i < field_count; i++)
|
|---|
| 194 | {
|
|---|
| 195 | dumpElement (" TYPE CODE=");
|
|---|
| 196 | char type_code = (char)this.realInputStream.readByte ();
|
|---|
| 197 | dumpElement (type_code + "; FIELD NAME=");
|
|---|
| 198 | String field_name = this.realInputStream.readUTF ();
|
|---|
| 199 | dumpElementln (field_name);
|
|---|
| 200 | String class_name;
|
|---|
| 201 |
|
|---|
| 202 | if (type_code == 'L' || type_code == '[')
|
|---|
| 203 | class_name = (String)readObject ();
|
|---|
| 204 | else
|
|---|
| 205 | class_name = String.valueOf (type_code);
|
|---|
| 206 |
|
|---|
| 207 | fields[i] =
|
|---|
| 208 | new ObjectStreamField (field_name,
|
|---|
| 209 | TypeSignature.getClassForEncoding
|
|---|
| 210 | (class_name));
|
|---|
| 211 | }
|
|---|
| 212 |
|
|---|
| 213 | Class cl = resolveClass (osc);
|
|---|
| 214 | osc.setClass (cl);
|
|---|
| 215 | setBlockDataMode (false);
|
|---|
| 216 |
|
|---|
| 217 | if (this.realInputStream.readByte () != TC_ENDBLOCKDATA)
|
|---|
| 218 | throw new IOException ("Data annotated to class was not consumed.");
|
|---|
| 219 | dumpElementln ("ENDBLOCKDATA ");
|
|---|
| 220 |
|
|---|
| 221 | osc.setSuperclass ((ObjectStreamClass)readObject ());
|
|---|
| 222 | ret_val = osc;
|
|---|
| 223 | break;
|
|---|
| 224 | }
|
|---|
| 225 |
|
|---|
| 226 | case TC_STRING:
|
|---|
| 227 | {
|
|---|
| 228 | dumpElement ("STRING=");
|
|---|
| 229 | String s = this.realInputStream.readUTF ();
|
|---|
| 230 | dumpElementln (s);
|
|---|
| 231 | ret_val = processResolution (s, assignNewHandle (s));
|
|---|
| 232 | break;
|
|---|
| 233 | }
|
|---|
| 234 |
|
|---|
| 235 | case TC_ARRAY:
|
|---|
| 236 | {
|
|---|
| 237 | dumpElementln ("ARRAY");
|
|---|
| 238 | ObjectStreamClass osc = (ObjectStreamClass)readObject ();
|
|---|
| 239 | Class componentType = osc.forClass ().getComponentType ();
|
|---|
| 240 | dumpElement ("ARRAY LENGTH=");
|
|---|
| 241 | int length = this.realInputStream.readInt ();
|
|---|
| 242 | dumpElementln (length + "; COMPONENT TYPE=" + componentType);
|
|---|
| 243 | Object array = Array.newInstance (componentType, length);
|
|---|
| 244 | int handle = assignNewHandle (array);
|
|---|
| 245 | readArrayElements (array, componentType);
|
|---|
| 246 | for (int i=0, len=Array.getLength(array); i < len; i++)
|
|---|
| 247 | dumpElementln (" ELEMENT[" + i + "]=" + Array.get(array, i).toString());
|
|---|
| 248 | ret_val = processResolution (array, handle);
|
|---|
| 249 | break;
|
|---|
| 250 | }
|
|---|
| 251 |
|
|---|
| 252 | case TC_OBJECT:
|
|---|
| 253 | {
|
|---|
| 254 | dumpElementln ("OBJECT");
|
|---|
| 255 | ObjectStreamClass osc = (ObjectStreamClass)readObject ();
|
|---|
| 256 | Class clazz = osc.forClass ();
|
|---|
| 257 |
|
|---|
| 258 | if (!Serializable.class.isAssignableFrom (clazz))
|
|---|
| 259 | throw new NotSerializableException (clazz + " is not Serializable, and thus cannot be deserialized.");
|
|---|
| 260 |
|
|---|
| 261 | if (Externalizable.class.isAssignableFrom (clazz))
|
|---|
| 262 | {
|
|---|
| 263 | Externalizable obj = null;
|
|---|
| 264 |
|
|---|
| 265 | try
|
|---|
| 266 | {
|
|---|
| 267 | obj = (Externalizable)clazz.newInstance ();
|
|---|
| 268 | }
|
|---|
| 269 | catch (InstantiationException e)
|
|---|
| 270 | {
|
|---|
| 271 | throw new ClassNotFoundException ("Instance of " + clazz
|
|---|
| 272 | + " could not be created");
|
|---|
| 273 | }
|
|---|
| 274 | catch (IllegalAccessException e)
|
|---|
| 275 | {
|
|---|
| 276 | throw new ClassNotFoundException ("Instance of " + clazz
|
|---|
| 277 | + " could not be created because class or zero-argument constructor is not accessible");
|
|---|
| 278 | }
|
|---|
| 279 | catch (NoSuchMethodError e)
|
|---|
| 280 | {
|
|---|
| 281 | throw new ClassNotFoundException ("Instance of " + clazz
|
|---|
| 282 | + " could not be created because zero-argument constructor is not defined");
|
|---|
| 283 | }
|
|---|
| 284 |
|
|---|
| 285 | int handle = assignNewHandle (obj);
|
|---|
| 286 |
|
|---|
| 287 | boolean read_from_blocks = ((osc.getFlags () & SC_BLOCK_DATA) != 0);
|
|---|
| 288 |
|
|---|
| 289 | if (read_from_blocks)
|
|---|
| 290 | setBlockDataMode (true);
|
|---|
| 291 |
|
|---|
| 292 | obj.readExternal (this);
|
|---|
| 293 |
|
|---|
| 294 | if (read_from_blocks)
|
|---|
| 295 | setBlockDataMode (false);
|
|---|
| 296 |
|
|---|
| 297 | ret_val = processResolution (obj, handle);
|
|---|
| 298 | break;
|
|---|
| 299 | } // end if (Externalizable.class.isAssignableFrom (clazz))
|
|---|
| 300 |
|
|---|
| 301 | // find the first non-serializable, non-abstract
|
|---|
| 302 | // class in clazz's inheritance hierarchy
|
|---|
| 303 | Class first_nonserial = clazz.getSuperclass ();
|
|---|
| 304 | while (Serializable.class.isAssignableFrom (first_nonserial)
|
|---|
| 305 | || Modifier.isAbstract (first_nonserial.getModifiers ()))
|
|---|
| 306 | first_nonserial = first_nonserial.getSuperclass ();
|
|---|
| 307 |
|
|---|
| 308 | // DEBUGln ("Using " + first_nonserial
|
|---|
| 309 | // + " as starting point for constructing " + clazz);
|
|---|
| 310 |
|
|---|
| 311 | Object obj = null;
|
|---|
| 312 | obj = newObject (clazz, first_nonserial);
|
|---|
| 313 |
|
|---|
| 314 | if (obj == null)
|
|---|
| 315 | throw new ClassNotFoundException ("Instance of " + clazz +
|
|---|
| 316 | " could not be created");
|
|---|
| 317 |
|
|---|
| 318 | int handle = assignNewHandle (obj);
|
|---|
| 319 | this.currentObject = obj;
|
|---|
| 320 | ObjectStreamClass[] hierarchy =
|
|---|
| 321 | ObjectStreamClass.getObjectStreamClasses (clazz);
|
|---|
| 322 |
|
|---|
| 323 | // DEBUGln ("Got class hierarchy of depth " + hierarchy.length);
|
|---|
| 324 |
|
|---|
| 325 | boolean has_read;
|
|---|
| 326 | for (int i=0; i < hierarchy.length; i++)
|
|---|
| 327 | {
|
|---|
| 328 | this.currentObjectStreamClass = hierarchy[i];
|
|---|
| 329 |
|
|---|
| 330 | dumpElementln ("Reading fields of "
|
|---|
| 331 | + this.currentObjectStreamClass.getName ());
|
|---|
| 332 |
|
|---|
| 333 | has_read = true;
|
|---|
| 334 |
|
|---|
| 335 | try
|
|---|
| 336 | {
|
|---|
| 337 | this.currentObjectStreamClass.forClass ().
|
|---|
| 338 | getDeclaredMethod ("readObject", readObjectParams);
|
|---|
| 339 | }
|
|---|
| 340 | catch (NoSuchMethodException e)
|
|---|
| 341 | {
|
|---|
| 342 | has_read = false;
|
|---|
| 343 | }
|
|---|
| 344 |
|
|---|
| 345 | // XXX: should initialize fields in classes in the hierarchy
|
|---|
| 346 | // that aren't in the stream
|
|---|
| 347 | // should skip over classes in the stream that aren't in the
|
|---|
| 348 | // real classes hierarchy
|
|---|
| 349 | readFields (obj, this.currentObjectStreamClass.fields,
|
|---|
| 350 | has_read, this.currentObjectStreamClass);
|
|---|
| 351 |
|
|---|
| 352 | if (has_read)
|
|---|
| 353 | {
|
|---|
| 354 | dumpElement ("ENDBLOCKDATA? ");
|
|---|
| 355 | try
|
|---|
| 356 | {
|
|---|
| 357 | // FIXME: XXX: This try block is to catch EOF which is
|
|---|
| 358 | // thrown for some objects. That indicates a bug in the logic.
|
|---|
| 359 | if (this.realInputStream.readByte () != TC_ENDBLOCKDATA)
|
|---|
| 360 | throw new IOException ("No end of block data seen for class with readObject (ObjectInputStream) method.");
|
|---|
| 361 | dumpElementln ("yes");
|
|---|
| 362 | }
|
|---|
| 363 | catch (EOFException e)
|
|---|
| 364 | {
|
|---|
| 365 | dumpElementln ("no, got EOFException");
|
|---|
| 366 | }
|
|---|
| 367 | catch (IOException e)
|
|---|
| 368 | {
|
|---|
| 369 | dumpElementln ("no, got IOException");
|
|---|
| 370 | }
|
|---|
| 371 | }
|
|---|
| 372 | }
|
|---|
| 373 |
|
|---|
| 374 | this.currentObject = null;
|
|---|
| 375 | this.currentObjectStreamClass = null;
|
|---|
| 376 | ret_val = processResolution (obj, handle);
|
|---|
| 377 | break;
|
|---|
| 378 | }
|
|---|
| 379 |
|
|---|
| 380 | case TC_RESET:
|
|---|
| 381 | dumpElementln ("RESET");
|
|---|
| 382 | clearHandles ();
|
|---|
| 383 | ret_val = readObject ();
|
|---|
| 384 | break;
|
|---|
| 385 |
|
|---|
| 386 | case TC_EXCEPTION:
|
|---|
| 387 | {
|
|---|
| 388 | dumpElement ("EXCEPTION=");
|
|---|
| 389 | Exception e = (Exception)readObject ();
|
|---|
| 390 | dumpElementln (e.toString());
|
|---|
| 391 | clearHandles ();
|
|---|
| 392 | throw new WriteAbortedException ("Exception thrown during writing of stream", e);
|
|---|
| 393 | }
|
|---|
| 394 |
|
|---|
| 395 | default:
|
|---|
| 396 | throw new IOException ("Unknown marker on stream");
|
|---|
| 397 | }
|
|---|
| 398 |
|
|---|
| 399 | this.isDeserializing = was_deserializing;
|
|---|
| 400 |
|
|---|
| 401 | if (! was_deserializing)
|
|---|
| 402 | {
|
|---|
| 403 | setBlockDataMode (true);
|
|---|
| 404 |
|
|---|
| 405 | if (validators.size () > 0)
|
|---|
| 406 | invokeValidators ();
|
|---|
| 407 | }
|
|---|
| 408 |
|
|---|
| 409 | return ret_val;
|
|---|
| 410 | }
|
|---|
| 411 |
|
|---|
| 412 |
|
|---|
| 413 | /**
|
|---|
| 414 | Reads the current objects non-transient, non-static fields from
|
|---|
| 415 | the current class from the underlying output stream.
|
|---|
| 416 |
|
|---|
| 417 | This method is intended to be called from within a object's
|
|---|
| 418 | <code>private void readObject (ObjectInputStream)</code>
|
|---|
| 419 | method.
|
|---|
| 420 |
|
|---|
| 421 | @exception ClassNotFoundException The class that an object being
|
|---|
| 422 | read in belongs to cannot be found.
|
|---|
| 423 |
|
|---|
| 424 | @exception NotActiveException This method was called from a
|
|---|
| 425 | context other than from the current object's and current class's
|
|---|
| 426 | <code>private void readObject (ObjectInputStream)</code>
|
|---|
| 427 | method.
|
|---|
| 428 |
|
|---|
| 429 | @exception IOException Exception from underlying
|
|---|
| 430 | <code>OutputStream</code>.
|
|---|
| 431 | */
|
|---|
| 432 | public void defaultReadObject ()
|
|---|
| 433 | throws ClassNotFoundException, IOException, NotActiveException
|
|---|
| 434 | {
|
|---|
| 435 | if (this.currentObject == null || this.currentObjectStreamClass == null)
|
|---|
| 436 | throw new NotActiveException ("defaultReadObject called by non-active class and/or object");
|
|---|
| 437 |
|
|---|
| 438 | if (fieldsAlreadyRead)
|
|---|
| 439 | throw new NotActiveException ("defaultReadObject called but fields already read from stream (by defaultReadObject or readFields)");
|
|---|
| 440 |
|
|---|
| 441 | readFields (this.currentObject,
|
|---|
| 442 | this.currentObjectStreamClass.fields,
|
|---|
| 443 | false, this.currentObjectStreamClass);
|
|---|
| 444 |
|
|---|
| 445 | fieldsAlreadyRead = true;
|
|---|
| 446 | }
|
|---|
| 447 |
|
|---|
| 448 |
|
|---|
| 449 | /**
|
|---|
| 450 | Registers a <code>ObjectInputValidation</code> to be carried out
|
|---|
| 451 | on the object graph currently being deserialized before it is
|
|---|
| 452 | returned to the original caller of <code>readObject ()</code>.
|
|---|
| 453 | The order of validation for multiple
|
|---|
| 454 | <code>ObjectInputValidation</code>s can be controled using
|
|---|
| 455 | <code>priority</code>. Validators with higher priorities are
|
|---|
| 456 | called first.
|
|---|
| 457 |
|
|---|
| 458 | @see java.io.ObjectInputValidation
|
|---|
| 459 |
|
|---|
| 460 | @exception InvalidObjectException <code>validator</code> is
|
|---|
| 461 | <code>null</code>
|
|---|
| 462 |
|
|---|
| 463 | @exception NotActiveException an attempt was made to add a
|
|---|
| 464 | validator outside of the <code>readObject</code> method of the
|
|---|
| 465 | object currently being deserialized
|
|---|
| 466 | */
|
|---|
| 467 | public void registerValidation (ObjectInputValidation validator,
|
|---|
| 468 | int priority)
|
|---|
| 469 | throws InvalidObjectException, NotActiveException
|
|---|
| 470 | {
|
|---|
| 471 | if (this.currentObject == null || this.currentObjectStreamClass == null)
|
|---|
| 472 | throw new NotActiveException ("registerValidation called by non-active class and/or object");
|
|---|
| 473 |
|
|---|
| 474 | if (validator == null)
|
|---|
| 475 | throw new InvalidObjectException ("attempt to add a null ObjectInputValidation object");
|
|---|
| 476 |
|
|---|
| 477 | this.validators.addElement (new ValidatorAndPriority (validator,
|
|---|
| 478 | priority));
|
|---|
| 479 | }
|
|---|
| 480 |
|
|---|
| 481 |
|
|---|
| 482 | /**
|
|---|
| 483 | Called when a class is being deserialized. This is a hook to
|
|---|
| 484 | allow subclasses to read in information written by the
|
|---|
| 485 | <code>annotateClass (Class)</code> method of an
|
|---|
| 486 | <code>ObjectOutputStream</code>.
|
|---|
| 487 |
|
|---|
| 488 | This implementation looks up the active call stack for a
|
|---|
| 489 | <code>ClassLoader</code>; if a <code>ClassLoader</code> is found,
|
|---|
| 490 | it is used to load the class associated with <code>osc</code>,
|
|---|
| 491 | otherwise, the default system <code>ClassLoader</code> is used.
|
|---|
| 492 |
|
|---|
| 493 | @exception IOException Exception from underlying
|
|---|
| 494 | <code>OutputStream</code>.
|
|---|
| 495 |
|
|---|
| 496 | @see java.io.ObjectOutputStream#annotateClass (java.lang.Class)
|
|---|
| 497 | */
|
|---|
| 498 | protected Class resolveClass (ObjectStreamClass osc)
|
|---|
| 499 | throws ClassNotFoundException, IOException
|
|---|
| 500 | {
|
|---|
| 501 | SecurityManager sm = System.getSecurityManager ();
|
|---|
| 502 |
|
|---|
| 503 | // FIXME: currentClassLoader doesn't yet do anything useful. We need
|
|---|
| 504 | // to call forName() with the classloader of the class which called
|
|---|
| 505 | // readObject(). See SecurityManager.getClassContext().
|
|---|
| 506 | ClassLoader cl = currentClassLoader (sm);
|
|---|
| 507 |
|
|---|
| 508 | return Class.forName (osc.getName (), true, cl);
|
|---|
| 509 | }
|
|---|
| 510 |
|
|---|
| 511 | /**
|
|---|
| 512 | Allows subclasses to resolve objects that are read from the
|
|---|
| 513 | stream with other objects to be returned in their place. This
|
|---|
| 514 | method is called the first time each object is encountered.
|
|---|
| 515 |
|
|---|
| 516 | This method must be enabled before it will be called in the
|
|---|
| 517 | serialization process.
|
|---|
| 518 |
|
|---|
| 519 | @exception IOException Exception from underlying
|
|---|
| 520 | <code>OutputStream</code>.
|
|---|
| 521 |
|
|---|
| 522 | @see enableResolveObject (boolean)
|
|---|
| 523 | */
|
|---|
| 524 | protected Object resolveObject (Object obj) throws IOException
|
|---|
| 525 | {
|
|---|
| 526 | return obj;
|
|---|
| 527 | }
|
|---|
| 528 |
|
|---|
| 529 |
|
|---|
| 530 | /**
|
|---|
| 531 | If <code>enable</code> is <code>true</code> and this object is
|
|---|
| 532 | trusted, then <code>resolveObject (Object)</code> will be called
|
|---|
| 533 | in subsequent calls to <code>readObject (Object)</code>.
|
|---|
| 534 | Otherwise, <code>resolveObject (Object)</code> will not be called.
|
|---|
| 535 |
|
|---|
| 536 | @exception SecurityException This class is not trusted.
|
|---|
| 537 | */
|
|---|
| 538 | protected boolean enableResolveObject (boolean enable)
|
|---|
| 539 | throws SecurityException
|
|---|
| 540 | {
|
|---|
| 541 | if (enable)
|
|---|
| 542 | {
|
|---|
| 543 | SecurityManager sm = System.getSecurityManager ();
|
|---|
| 544 | if (sm != null)
|
|---|
| 545 | sm.checkPermission (new SerializablePermission ("enableSubtitution"));
|
|---|
| 546 | }
|
|---|
| 547 |
|
|---|
| 548 | boolean old_val = this.resolveEnabled;
|
|---|
| 549 | this.resolveEnabled = enable;
|
|---|
| 550 | return old_val;
|
|---|
| 551 | }
|
|---|
| 552 |
|
|---|
| 553 |
|
|---|
| 554 | /**
|
|---|
| 555 | Reads stream magic and stream version information from the
|
|---|
| 556 | underlying stream.
|
|---|
| 557 |
|
|---|
| 558 | @exception IOException Exception from underlying stream.
|
|---|
| 559 |
|
|---|
| 560 | @exception StreamCorruptedException An invalid stream magic
|
|---|
| 561 | number or stream version was read from the stream.
|
|---|
| 562 | */
|
|---|
| 563 | protected void readStreamHeader ()
|
|---|
| 564 | throws IOException, StreamCorruptedException
|
|---|
| 565 | {
|
|---|
| 566 | dumpElement ("STREAM MAGIC ");
|
|---|
| 567 | if (this.realInputStream.readShort () != STREAM_MAGIC)
|
|---|
| 568 | throw new StreamCorruptedException ("Invalid stream magic number");
|
|---|
| 569 |
|
|---|
| 570 | dumpElementln ("STREAM VERSION ");
|
|---|
| 571 | if (this.realInputStream.readShort () != STREAM_VERSION)
|
|---|
| 572 | throw new StreamCorruptedException ("Invalid stream version number");
|
|---|
| 573 | }
|
|---|
| 574 |
|
|---|
| 575 |
|
|---|
| 576 | public int read () throws IOException
|
|---|
| 577 | {
|
|---|
| 578 | if (this.readDataFromBlock)
|
|---|
| 579 | {
|
|---|
| 580 | if (this.blockDataPosition >= this.blockDataBytes)
|
|---|
| 581 | readNextBlock ();
|
|---|
| 582 | return (this.blockData[this.blockDataPosition++] & 0xff);
|
|---|
| 583 | }
|
|---|
| 584 | else
|
|---|
| 585 | return this.realInputStream.read ();
|
|---|
| 586 | }
|
|---|
| 587 |
|
|---|
| 588 | public int read (byte[] data, int offset, int length) throws IOException
|
|---|
| 589 | {
|
|---|
| 590 | if (this.readDataFromBlock)
|
|---|
| 591 | {
|
|---|
| 592 | if (this.blockDataPosition + length > this.blockDataBytes)
|
|---|
| 593 | readNextBlock ();
|
|---|
| 594 |
|
|---|
| 595 | System.arraycopy (this.blockData, this.blockDataPosition,
|
|---|
| 596 | data, offset, length);
|
|---|
| 597 | blockDataPosition += length;
|
|---|
| 598 |
|
|---|
| 599 | return length;
|
|---|
| 600 | }
|
|---|
| 601 | else
|
|---|
| 602 | return this.realInputStream.read (data, offset, length);
|
|---|
| 603 | }
|
|---|
| 604 |
|
|---|
| 605 | public int available () throws IOException
|
|---|
| 606 | {
|
|---|
| 607 | if (this.readDataFromBlock)
|
|---|
| 608 | {
|
|---|
| 609 | if (this.blockDataPosition >= this.blockDataBytes)
|
|---|
| 610 | readNextBlock ();
|
|---|
| 611 |
|
|---|
| 612 | return this.blockDataBytes - this.blockDataPosition;
|
|---|
| 613 | }
|
|---|
| 614 | else
|
|---|
| 615 | return this.realInputStream.available ();
|
|---|
| 616 | }
|
|---|
| 617 |
|
|---|
| 618 | public void close () throws IOException
|
|---|
| 619 | {
|
|---|
| 620 | this.realInputStream.close ();
|
|---|
| 621 | }
|
|---|
| 622 |
|
|---|
| 623 | public boolean readBoolean () throws IOException
|
|---|
| 624 | {
|
|---|
| 625 | return this.dataInputStream.readBoolean ();
|
|---|
| 626 | }
|
|---|
| 627 |
|
|---|
| 628 | public byte readByte () throws IOException
|
|---|
| 629 | {
|
|---|
| 630 | return this.dataInputStream.readByte ();
|
|---|
| 631 | }
|
|---|
| 632 |
|
|---|
| 633 | public int readUnsignedByte () throws IOException
|
|---|
| 634 | {
|
|---|
| 635 | return this.dataInputStream.readUnsignedByte ();
|
|---|
| 636 | }
|
|---|
| 637 |
|
|---|
| 638 | public short readShort () throws IOException
|
|---|
| 639 | {
|
|---|
| 640 | return this.dataInputStream.readShort ();
|
|---|
| 641 | }
|
|---|
| 642 |
|
|---|
| 643 | public int readUnsignedShort () throws IOException
|
|---|
| 644 | {
|
|---|
| 645 | return this.dataInputStream.readUnsignedShort ();
|
|---|
| 646 | }
|
|---|
| 647 |
|
|---|
| 648 | public char readChar () throws IOException
|
|---|
| 649 | {
|
|---|
| 650 | return this.dataInputStream.readChar ();
|
|---|
| 651 | }
|
|---|
| 652 |
|
|---|
| 653 | public int readInt () throws IOException
|
|---|
| 654 | {
|
|---|
| 655 | return this.dataInputStream.readInt ();
|
|---|
| 656 | }
|
|---|
| 657 |
|
|---|
| 658 | public long readLong () throws IOException
|
|---|
| 659 | {
|
|---|
| 660 | return this.dataInputStream.readLong ();
|
|---|
| 661 | }
|
|---|
| 662 |
|
|---|
| 663 | public float readFloat () throws IOException
|
|---|
| 664 | {
|
|---|
| 665 | return this.dataInputStream.readFloat ();
|
|---|
| 666 | }
|
|---|
| 667 |
|
|---|
| 668 | public double readDouble () throws IOException
|
|---|
| 669 | {
|
|---|
| 670 | return this.dataInputStream.readDouble ();
|
|---|
| 671 | }
|
|---|
| 672 |
|
|---|
| 673 | public void readFully (byte data[]) throws IOException
|
|---|
| 674 | {
|
|---|
| 675 | this.dataInputStream.readFully (data);
|
|---|
| 676 | }
|
|---|
| 677 |
|
|---|
| 678 | public void readFully (byte data[], int offset, int size)
|
|---|
| 679 | throws IOException
|
|---|
| 680 | {
|
|---|
| 681 | this.dataInputStream.readFully (data, offset, size);
|
|---|
| 682 | }
|
|---|
| 683 |
|
|---|
| 684 | public int skipBytes (int len) throws IOException
|
|---|
| 685 | {
|
|---|
| 686 | return this.dataInputStream.skipBytes (len);
|
|---|
| 687 | }
|
|---|
| 688 |
|
|---|
| 689 | /**
|
|---|
| 690 | @deprecated
|
|---|
| 691 | @see java.io.DataInputStream#readLine ()
|
|---|
| 692 | */
|
|---|
| 693 | public String readLine () throws IOException
|
|---|
| 694 | {
|
|---|
| 695 | return this.dataInputStream.readLine ();
|
|---|
| 696 | }
|
|---|
| 697 |
|
|---|
| 698 | public String readUTF () throws IOException
|
|---|
| 699 | {
|
|---|
| 700 | return this.dataInputStream.readUTF ();
|
|---|
| 701 | }
|
|---|
| 702 |
|
|---|
| 703 |
|
|---|
| 704 | /**
|
|---|
| 705 | This class allows a class to specify exactly which fields should
|
|---|
| 706 | be read, and what values should be read for these fields.
|
|---|
| 707 |
|
|---|
| 708 | XXX: finish up comments
|
|---|
| 709 | */
|
|---|
| 710 | public static abstract class GetField
|
|---|
| 711 | {
|
|---|
| 712 | public abstract ObjectStreamClass getObjectStreamClass ();
|
|---|
| 713 |
|
|---|
| 714 | public abstract boolean defaulted (String name)
|
|---|
| 715 | throws IOException, IllegalArgumentException;
|
|---|
| 716 |
|
|---|
| 717 | public abstract boolean get (String name, boolean defvalue)
|
|---|
| 718 | throws IOException, IllegalArgumentException;
|
|---|
| 719 |
|
|---|
| 720 | public abstract char get (String name, char defvalue)
|
|---|
| 721 | throws IOException, IllegalArgumentException;
|
|---|
| 722 |
|
|---|
| 723 | public abstract byte get (String name, byte defvalue)
|
|---|
| 724 | throws IOException, IllegalArgumentException;
|
|---|
| 725 |
|
|---|
| 726 | public abstract short get (String name, short defvalue)
|
|---|
| 727 | throws IOException, IllegalArgumentException;
|
|---|
| 728 |
|
|---|
| 729 | public abstract int get (String name, int defvalue)
|
|---|
| 730 | throws IOException, IllegalArgumentException;
|
|---|
| 731 |
|
|---|
| 732 | public abstract long get (String name, long defvalue)
|
|---|
| 733 | throws IOException, IllegalArgumentException;
|
|---|
| 734 |
|
|---|
| 735 | public abstract float get (String name, float defvalue)
|
|---|
| 736 | throws IOException, IllegalArgumentException;
|
|---|
| 737 |
|
|---|
| 738 | public abstract double get (String name, double defvalue)
|
|---|
| 739 | throws IOException, IllegalArgumentException;
|
|---|
| 740 |
|
|---|
| 741 | public abstract Object get (String name, Object defvalue)
|
|---|
| 742 | throws IOException, IllegalArgumentException;
|
|---|
| 743 | }
|
|---|
| 744 |
|
|---|
| 745 | public GetField readFields ()
|
|---|
| 746 | throws IOException, ClassNotFoundException, NotActiveException
|
|---|
| 747 | {
|
|---|
| 748 | if (this.currentObject == null || this.currentObjectStreamClass == null)
|
|---|
| 749 | throw new NotActiveException ("readFields called by non-active class and/or object");
|
|---|
| 750 |
|
|---|
| 751 | if (fieldsAlreadyRead)
|
|---|
| 752 | throw new NotActiveException ("readFields called but fields already read from stream (by defaultReadObject or readFields)");
|
|---|
| 753 |
|
|---|
| 754 | final ObjectStreamClass clazz = this.currentObjectStreamClass;
|
|---|
| 755 | final byte[] prim_field_data = new byte[clazz.primFieldSize];
|
|---|
| 756 | final Object[] objs = new Object[clazz.objectFieldCount];
|
|---|
| 757 |
|
|---|
| 758 | // Apparently Block data is not used with GetField as per
|
|---|
| 759 | // empirical evidence against JDK 1.2. Also see Mauve test
|
|---|
| 760 | // java.io.ObjectInputOutput.Test.GetPutField.
|
|---|
| 761 | setBlockDataMode (false);
|
|---|
| 762 | readFully (prim_field_data);
|
|---|
| 763 | for (int i = 0; i < objs.length; ++ i)
|
|---|
| 764 | objs[i] = readObject ();
|
|---|
| 765 | setBlockDataMode (true);
|
|---|
| 766 |
|
|---|
| 767 | return new GetField ()
|
|---|
| 768 | {
|
|---|
| 769 | public ObjectStreamClass getObjectStreamClass ()
|
|---|
| 770 | {
|
|---|
| 771 | return clazz;
|
|---|
| 772 | }
|
|---|
| 773 |
|
|---|
| 774 | public boolean defaulted (String name)
|
|---|
| 775 | throws IOException, IllegalArgumentException
|
|---|
| 776 | {
|
|---|
| 777 | return clazz.getField (name) == null;
|
|---|
| 778 | }
|
|---|
| 779 |
|
|---|
| 780 | public boolean get (String name, boolean defvalue)
|
|---|
| 781 | throws IOException, IllegalArgumentException
|
|---|
| 782 | {
|
|---|
| 783 | ObjectStreamField field = getField (name, Boolean.TYPE);
|
|---|
| 784 |
|
|---|
| 785 | if (field == null)
|
|---|
| 786 | return defvalue;
|
|---|
| 787 |
|
|---|
| 788 | return prim_field_data[field.getOffset ()] == 0 ? false : true;
|
|---|
| 789 | }
|
|---|
| 790 |
|
|---|
| 791 | public char get (String name, char defvalue)
|
|---|
| 792 | throws IOException, IllegalArgumentException
|
|---|
| 793 | {
|
|---|
| 794 | ObjectStreamField field = getField (name, Character.TYPE);
|
|---|
| 795 |
|
|---|
| 796 | if (field == null)
|
|---|
| 797 | return defvalue;
|
|---|
| 798 |
|
|---|
| 799 | int off = field.getOffset ();
|
|---|
| 800 |
|
|---|
| 801 | return (char)(((prim_field_data[off++] & 0xFF) << 8)
|
|---|
| 802 | | (prim_field_data[off] & 0xFF));
|
|---|
| 803 | }
|
|---|
| 804 |
|
|---|
| 805 | public byte get (String name, byte defvalue)
|
|---|
| 806 | throws IOException, IllegalArgumentException
|
|---|
| 807 | {
|
|---|
| 808 | ObjectStreamField field = getField (name, Byte.TYPE);
|
|---|
| 809 |
|
|---|
| 810 | if (field == null)
|
|---|
| 811 | return defvalue;
|
|---|
| 812 |
|
|---|
| 813 | return prim_field_data[field.getOffset ()];
|
|---|
| 814 | }
|
|---|
| 815 |
|
|---|
| 816 | public short get (String name, short defvalue)
|
|---|
| 817 | throws IOException, IllegalArgumentException
|
|---|
| 818 | {
|
|---|
| 819 | ObjectStreamField field = getField (name, Short.TYPE);
|
|---|
| 820 |
|
|---|
| 821 | if (field == null)
|
|---|
| 822 | return defvalue;
|
|---|
| 823 |
|
|---|
| 824 | int off = field.getOffset ();
|
|---|
| 825 |
|
|---|
| 826 | return (short)(((prim_field_data[off++] & 0xFF) << 8)
|
|---|
| 827 | | (prim_field_data[off] & 0xFF));
|
|---|
| 828 | }
|
|---|
| 829 |
|
|---|
| 830 | public int get (String name, int defvalue)
|
|---|
| 831 | throws IOException, IllegalArgumentException
|
|---|
| 832 | {
|
|---|
| 833 | ObjectStreamField field = getField (name, Integer.TYPE);
|
|---|
| 834 |
|
|---|
| 835 | if (field == null)
|
|---|
| 836 | return defvalue;
|
|---|
| 837 |
|
|---|
| 838 | int off = field.getOffset ();
|
|---|
| 839 |
|
|---|
| 840 | return ((prim_field_data[off++] & 0xFF) << 24)
|
|---|
| 841 | | ((prim_field_data[off++] & 0xFF) << 16)
|
|---|
| 842 | | ((prim_field_data[off++] & 0xFF) << 8)
|
|---|
| 843 | | (prim_field_data[off] & 0xFF);
|
|---|
| 844 | }
|
|---|
| 845 |
|
|---|
| 846 | public long get (String name, long defvalue)
|
|---|
| 847 | throws IOException, IllegalArgumentException
|
|---|
| 848 | {
|
|---|
| 849 | ObjectStreamField field = getField (name, Long.TYPE);
|
|---|
| 850 |
|
|---|
| 851 | if (field == null)
|
|---|
| 852 | return defvalue;
|
|---|
| 853 |
|
|---|
| 854 | int off = field.getOffset ();
|
|---|
| 855 |
|
|---|
| 856 | return (long)(((prim_field_data[off++] & 0xFF) << 56)
|
|---|
| 857 | | ((prim_field_data[off++] & 0xFF) << 48)
|
|---|
| 858 | | ((prim_field_data[off++] & 0xFF) << 40)
|
|---|
| 859 | | ((prim_field_data[off++] & 0xFF) << 32)
|
|---|
| 860 | | ((prim_field_data[off++] & 0xFF) << 24)
|
|---|
| 861 | | ((prim_field_data[off++] & 0xFF) << 16)
|
|---|
| 862 | | ((prim_field_data[off++] & 0xFF) << 8)
|
|---|
| 863 | | (prim_field_data[off] & 0xFF));
|
|---|
| 864 | }
|
|---|
| 865 |
|
|---|
| 866 | public float get (String name, float defvalue)
|
|---|
| 867 | throws IOException, IllegalArgumentException
|
|---|
| 868 | {
|
|---|
| 869 | ObjectStreamField field = getField (name, Float.TYPE);
|
|---|
| 870 |
|
|---|
| 871 | if (field == null)
|
|---|
| 872 | return defvalue;
|
|---|
| 873 |
|
|---|
| 874 | int off = field.getOffset ();
|
|---|
| 875 |
|
|---|
| 876 | return Float.intBitsToFloat (((prim_field_data[off++] & 0xFF) << 24)
|
|---|
| 877 | | ((prim_field_data[off++] & 0xFF) << 16)
|
|---|
| 878 | | ((prim_field_data[off++] & 0xFF) << 8)
|
|---|
| 879 | | (prim_field_data[off] & 0xFF));
|
|---|
| 880 | }
|
|---|
| 881 |
|
|---|
| 882 | public double get (String name, double defvalue)
|
|---|
| 883 | throws IOException, IllegalArgumentException
|
|---|
| 884 | {
|
|---|
| 885 | ObjectStreamField field = getField (name, Double.TYPE);
|
|---|
| 886 |
|
|---|
| 887 | if (field == null)
|
|---|
| 888 | return defvalue;
|
|---|
| 889 |
|
|---|
| 890 | int off = field.getOffset ();
|
|---|
| 891 |
|
|---|
| 892 | return Double.longBitsToDouble (
|
|---|
| 893 | (long)(((prim_field_data[off++] & 0xFF) << 56)
|
|---|
| 894 | | ((prim_field_data[off++] & 0xFF) << 48)
|
|---|
| 895 | | ((prim_field_data[off++] & 0xFF) << 40)
|
|---|
| 896 | | ((prim_field_data[off++] & 0xFF) << 32)
|
|---|
| 897 | | ((prim_field_data[off++] & 0xFF) << 24)
|
|---|
| 898 | | ((prim_field_data[off++] & 0xFF) << 16)
|
|---|
| 899 | | ((prim_field_data[off++] & 0xFF) << 8)
|
|---|
| 900 | | (prim_field_data[off] & 0xFF)));
|
|---|
| 901 | }
|
|---|
| 902 |
|
|---|
| 903 | public Object get (String name, Object defvalue)
|
|---|
| 904 | throws IOException, IllegalArgumentException
|
|---|
| 905 | {
|
|---|
| 906 | ObjectStreamField field =
|
|---|
| 907 | getField (name, defvalue == null ? null : defvalue.getClass ());
|
|---|
| 908 |
|
|---|
| 909 | if (field == null)
|
|---|
| 910 | return defvalue;
|
|---|
| 911 |
|
|---|
| 912 | return objs[field.getOffset ()];
|
|---|
| 913 | }
|
|---|
| 914 |
|
|---|
| 915 | private ObjectStreamField getField (String name, Class type)
|
|---|
| 916 | throws IllegalArgumentException
|
|---|
| 917 | {
|
|---|
| 918 | ObjectStreamField field = clazz.getField (name);
|
|---|
| 919 |
|
|---|
| 920 | if (field == null)
|
|---|
| 921 | return null;
|
|---|
| 922 |
|
|---|
| 923 | Class field_type = field.getType ();
|
|---|
| 924 |
|
|---|
| 925 | if (type == field_type ||
|
|---|
| 926 | (type == null && ! field_type.isPrimitive ()))
|
|---|
| 927 | return field;
|
|---|
| 928 |
|
|---|
| 929 | throw new IllegalArgumentException ("Field requested is of type "
|
|---|
| 930 | + field_type.getName ()
|
|---|
| 931 | + ", but requested type was "
|
|---|
| 932 | + (type == null ?
|
|---|
| 933 | "Object" : type.getName ()));
|
|---|
| 934 | }
|
|---|
| 935 | };
|
|---|
| 936 |
|
|---|
| 937 | }
|
|---|
| 938 |
|
|---|
| 939 |
|
|---|
| 940 | /**
|
|---|
| 941 | Protected constructor that allows subclasses to override
|
|---|
| 942 | deserialization. This constructor should be called by subclasses
|
|---|
| 943 | that wish to override <code>readObject (Object)</code>. This
|
|---|
| 944 | method does a security check <i>NOTE: currently not
|
|---|
| 945 | implemented</i>, then sets a flag that informs
|
|---|
| 946 | <code>readObject (Object)</code> to call the subclasses
|
|---|
| 947 | <code>readObjectOverride (Object)</code> method.
|
|---|
| 948 |
|
|---|
| 949 | @see readObjectOverride (Object)
|
|---|
| 950 | */
|
|---|
| 951 | protected ObjectInputStream ()
|
|---|
| 952 | throws IOException, SecurityException
|
|---|
| 953 | {
|
|---|
| 954 | SecurityManager sec_man = System.getSecurityManager ();
|
|---|
| 955 | if (sec_man != null)
|
|---|
| 956 | sec_man.checkPermission (SUBCLASS_IMPLEMENTATION_PERMISSION);
|
|---|
| 957 | this.useSubclassMethod = true;
|
|---|
| 958 | }
|
|---|
| 959 |
|
|---|
| 960 |
|
|---|
| 961 | /**
|
|---|
| 962 | This method allows subclasses to override the default
|
|---|
| 963 | de serialization mechanism provided by
|
|---|
| 964 | <code>ObjectInputStream</code>. To make this method be used for
|
|---|
| 965 | writing objects, subclasses must invoke the 0-argument
|
|---|
| 966 | constructor on this class from there constructor.
|
|---|
| 967 |
|
|---|
| 968 | @see ObjectInputStream ()
|
|---|
| 969 | */
|
|---|
| 970 | protected Object readObjectOverride ()
|
|---|
| 971 | throws ClassNotFoundException, IOException, OptionalDataException
|
|---|
| 972 | {
|
|---|
| 973 | throw new IOException ("Subclass of ObjectInputStream must implement readObjectOverride");
|
|---|
| 974 | }
|
|---|
| 975 |
|
|---|
| 976 |
|
|---|
| 977 | // assigns the next availible handle to OBJ
|
|---|
| 978 | private int assignNewHandle (Object obj)
|
|---|
| 979 | {
|
|---|
| 980 | this.objectLookupTable.put (new Integer (this.nextOID),
|
|---|
| 981 | new ObjectIdentityWrapper (obj));
|
|---|
| 982 |
|
|---|
| 983 | // try
|
|---|
| 984 | // {
|
|---|
| 985 | // DEBUG ("Assigning handle " + this.nextOID);
|
|---|
| 986 | // DEBUGln (" to " + obj);
|
|---|
| 987 | // }
|
|---|
| 988 | // catch (Throwable t) {}
|
|---|
| 989 |
|
|---|
| 990 | return this.nextOID++;
|
|---|
| 991 | }
|
|---|
| 992 |
|
|---|
| 993 |
|
|---|
| 994 | private Object processResolution (Object obj, int handle)
|
|---|
| 995 | throws IOException
|
|---|
| 996 | {
|
|---|
| 997 | if (obj instanceof Serializable)
|
|---|
| 998 | {
|
|---|
| 999 | Method m = null;
|
|---|
| 1000 | try
|
|---|
| 1001 | {
|
|---|
| 1002 | Class classArgs[] = {};
|
|---|
| 1003 | m = obj.getClass ().getDeclaredMethod ("readResolve", classArgs);
|
|---|
| 1004 | // m can't be null by definition since an exception would
|
|---|
| 1005 | // have been thrown so a check for null is not needed.
|
|---|
| 1006 | obj = m.invoke (obj, new Object[] {});
|
|---|
| 1007 | }
|
|---|
| 1008 | catch (NoSuchMethodException ignore)
|
|---|
| 1009 | {
|
|---|
| 1010 | }
|
|---|
| 1011 | catch (IllegalAccessException ignore)
|
|---|
| 1012 | {
|
|---|
| 1013 | }
|
|---|
| 1014 | catch (InvocationTargetException ignore)
|
|---|
| 1015 | {
|
|---|
| 1016 | }
|
|---|
| 1017 | }
|
|---|
| 1018 |
|
|---|
| 1019 | if (this.resolveEnabled)
|
|---|
| 1020 | obj = resolveObject (obj);
|
|---|
| 1021 |
|
|---|
| 1022 | this.objectLookupTable.put (new Integer (handle),
|
|---|
| 1023 | new ObjectIdentityWrapper (obj));
|
|---|
| 1024 |
|
|---|
| 1025 | return obj;
|
|---|
| 1026 | }
|
|---|
| 1027 |
|
|---|
| 1028 |
|
|---|
| 1029 | private void clearHandles ()
|
|---|
| 1030 | {
|
|---|
| 1031 | this.objectLookupTable.clear ();
|
|---|
| 1032 | this.nextOID = baseWireHandle;
|
|---|
| 1033 | }
|
|---|
| 1034 |
|
|---|
| 1035 |
|
|---|
| 1036 | private void readNextBlock () throws IOException
|
|---|
| 1037 | {
|
|---|
| 1038 | // DEBUGln ("In readNextBlock ");
|
|---|
| 1039 | readNextBlock (this.realInputStream.readByte ());
|
|---|
| 1040 | }
|
|---|
| 1041 |
|
|---|
| 1042 |
|
|---|
| 1043 | private void readNextBlock (byte marker) throws IOException
|
|---|
| 1044 | {
|
|---|
| 1045 | if (marker == TC_BLOCKDATA)
|
|---|
| 1046 | {
|
|---|
| 1047 | dumpElement ("BLOCK DATA SIZE=");
|
|---|
| 1048 | this.blockDataBytes = this.realInputStream.readUnsignedByte ();
|
|---|
| 1049 | dumpElementln (Integer.toString(this.blockDataBytes));
|
|---|
| 1050 | }
|
|---|
| 1051 | else if (marker == TC_BLOCKDATALONG)
|
|---|
| 1052 | {
|
|---|
| 1053 | dumpElement ("BLOCK DATA LONG SIZE=");
|
|---|
| 1054 | this.blockDataBytes = this.realInputStream.readInt ();
|
|---|
| 1055 | dumpElementln (Integer.toString(this.blockDataBytes));
|
|---|
| 1056 | }
|
|---|
| 1057 | else
|
|---|
| 1058 | {
|
|---|
| 1059 | throw new EOFException ("Attempt to read primitive data, but no data block is active.");
|
|---|
| 1060 | }
|
|---|
| 1061 |
|
|---|
| 1062 | if (this.blockData.length < this.blockDataBytes)
|
|---|
| 1063 | this.blockData = new byte[this.blockDataBytes];
|
|---|
| 1064 |
|
|---|
| 1065 | this.realInputStream.readFully (this.blockData, 0, this.blockDataBytes);
|
|---|
| 1066 | this.blockDataPosition = 0;
|
|---|
| 1067 | }
|
|---|
| 1068 |
|
|---|
| 1069 |
|
|---|
| 1070 | private void readArrayElements (Object array, Class clazz)
|
|---|
| 1071 | throws ClassNotFoundException, IOException
|
|---|
| 1072 | {
|
|---|
| 1073 | if (clazz.isPrimitive ())
|
|---|
| 1074 | {
|
|---|
| 1075 | if (clazz == Boolean.TYPE)
|
|---|
| 1076 | {
|
|---|
| 1077 | boolean[] cast_array = (boolean[])array;
|
|---|
| 1078 | for (int i=0; i < cast_array.length; i++)
|
|---|
| 1079 | cast_array[i] = this.realInputStream.readBoolean ();
|
|---|
| 1080 | return;
|
|---|
| 1081 | }
|
|---|
| 1082 | if (clazz == Byte.TYPE)
|
|---|
| 1083 | {
|
|---|
| 1084 | byte[] cast_array = (byte[])array;
|
|---|
| 1085 | for (int i=0; i < cast_array.length; i++)
|
|---|
| 1086 | cast_array[i] = this.realInputStream.readByte ();
|
|---|
| 1087 | return;
|
|---|
| 1088 | }
|
|---|
| 1089 | if (clazz == Character.TYPE)
|
|---|
| 1090 | {
|
|---|
| 1091 | char[] cast_array = (char[])array;
|
|---|
| 1092 | for (int i=0; i < cast_array.length; i++)
|
|---|
| 1093 | cast_array[i] = this.realInputStream.readChar ();
|
|---|
| 1094 | return;
|
|---|
| 1095 | }
|
|---|
| 1096 | if (clazz == Double.TYPE)
|
|---|
| 1097 | {
|
|---|
| 1098 | double[] cast_array = (double[])array;
|
|---|
| 1099 | for (int i=0; i < cast_array.length; i++)
|
|---|
| 1100 | cast_array[i] = this.realInputStream.readDouble ();
|
|---|
| 1101 | return;
|
|---|
| 1102 | }
|
|---|
| 1103 | if (clazz == Float.TYPE)
|
|---|
| 1104 | {
|
|---|
| 1105 | float[] cast_array = (float[])array;
|
|---|
| 1106 | for (int i=0; i < cast_array.length; i++)
|
|---|
| 1107 | cast_array[i] = this.realInputStream.readFloat ();
|
|---|
| 1108 | return;
|
|---|
| 1109 | }
|
|---|
| 1110 | if (clazz == Integer.TYPE)
|
|---|
| 1111 | {
|
|---|
| 1112 | int[] cast_array = (int[])array;
|
|---|
| 1113 | for (int i=0; i < cast_array.length; i++)
|
|---|
| 1114 | cast_array[i] = this.realInputStream.readInt ();
|
|---|
| 1115 | return;
|
|---|
| 1116 | }
|
|---|
| 1117 | if (clazz == Long.TYPE)
|
|---|
| 1118 | {
|
|---|
| 1119 | long[] cast_array = (long[])array;
|
|---|
| 1120 | for (int i=0; i < cast_array.length; i++)
|
|---|
| 1121 | cast_array[i] = this.realInputStream.readLong ();
|
|---|
| 1122 | return;
|
|---|
| 1123 | }
|
|---|
| 1124 | if (clazz == Short.TYPE)
|
|---|
| 1125 | {
|
|---|
| 1126 | short[] cast_array = (short[])array;
|
|---|
| 1127 | for (int i=0; i < cast_array.length; i++)
|
|---|
| 1128 | cast_array[i] = this.realInputStream.readShort ();
|
|---|
| 1129 | return;
|
|---|
| 1130 | }
|
|---|
| 1131 | }
|
|---|
| 1132 | else
|
|---|
| 1133 | {
|
|---|
| 1134 | Object[] cast_array = (Object[])array;
|
|---|
| 1135 | for (int i=0; i < cast_array.length; i++)
|
|---|
| 1136 | cast_array[i] = readObject ();
|
|---|
| 1137 | }
|
|---|
| 1138 | }
|
|---|
| 1139 |
|
|---|
| 1140 |
|
|---|
| 1141 | private void readFields (Object obj, ObjectStreamField[] stream_fields,
|
|---|
| 1142 | boolean call_read_method,
|
|---|
| 1143 | ObjectStreamClass stream_osc)
|
|---|
| 1144 | throws ClassNotFoundException, IOException
|
|---|
| 1145 | {
|
|---|
| 1146 | // DEBUGln ("In readFields");
|
|---|
| 1147 | if (call_read_method)
|
|---|
| 1148 | {
|
|---|
| 1149 | // DEBUGln (" call_read_method is true");
|
|---|
| 1150 | fieldsAlreadyRead = false;
|
|---|
| 1151 | setBlockDataMode (true);
|
|---|
| 1152 | callReadMethod (obj, stream_osc.forClass ());
|
|---|
| 1153 | setBlockDataMode (false);
|
|---|
| 1154 | return;
|
|---|
| 1155 | }
|
|---|
| 1156 |
|
|---|
| 1157 | ObjectStreamField[] real_fields =
|
|---|
| 1158 | ObjectStreamClass.lookup (stream_osc.forClass ()).fields;
|
|---|
| 1159 |
|
|---|
| 1160 | boolean default_initialize, set_value;
|
|---|
| 1161 | String field_name = null;
|
|---|
| 1162 | Class type = null;
|
|---|
| 1163 | ObjectStreamField stream_field = null;
|
|---|
| 1164 | ObjectStreamField real_field = null;
|
|---|
| 1165 | int stream_idx = 0;
|
|---|
| 1166 | int real_idx = 0;
|
|---|
| 1167 |
|
|---|
| 1168 | while (stream_idx < stream_fields.length
|
|---|
| 1169 | && real_idx < real_fields.length)
|
|---|
| 1170 | {
|
|---|
| 1171 | default_initialize = false;
|
|---|
| 1172 | set_value = true;
|
|---|
| 1173 |
|
|---|
| 1174 | if (stream_idx == stream_fields.length)
|
|---|
| 1175 | default_initialize = true;
|
|---|
| 1176 | else
|
|---|
| 1177 | {
|
|---|
| 1178 | stream_field = stream_fields[stream_idx];
|
|---|
| 1179 | type = stream_field.getType ();
|
|---|
| 1180 | }
|
|---|
| 1181 |
|
|---|
| 1182 | if (real_idx == real_fields.length)
|
|---|
| 1183 | set_value = false;
|
|---|
| 1184 | else
|
|---|
| 1185 | {
|
|---|
| 1186 | real_field = real_fields[real_idx];
|
|---|
| 1187 | type = real_field.getType ();
|
|---|
| 1188 | field_name = real_field.getName ();
|
|---|
| 1189 | }
|
|---|
| 1190 |
|
|---|
| 1191 | if (set_value && !default_initialize)
|
|---|
| 1192 | {
|
|---|
| 1193 | int comp_val =
|
|---|
| 1194 | real_field.compareTo (stream_field);
|
|---|
| 1195 |
|
|---|
| 1196 | if (comp_val < 0)
|
|---|
| 1197 | {
|
|---|
| 1198 | default_initialize = true;
|
|---|
| 1199 | real_idx++;
|
|---|
| 1200 | }
|
|---|
| 1201 | else if (comp_val > 0)
|
|---|
| 1202 | {
|
|---|
| 1203 | set_value = false;
|
|---|
| 1204 | stream_idx++;
|
|---|
| 1205 | }
|
|---|
| 1206 | else
|
|---|
| 1207 | {
|
|---|
| 1208 | real_idx++;
|
|---|
| 1209 | stream_idx++;
|
|---|
| 1210 | }
|
|---|
| 1211 | }
|
|---|
| 1212 |
|
|---|
| 1213 | if (type == Boolean.TYPE)
|
|---|
| 1214 | {
|
|---|
| 1215 | boolean value =
|
|---|
| 1216 | default_initialize ? false : this.realInputStream.readBoolean ();
|
|---|
| 1217 | if (!default_initialize && set_value)
|
|---|
| 1218 | dumpElementln (" " + field_name + ": " + value);
|
|---|
| 1219 | if (set_value)
|
|---|
| 1220 | setBooleanField (obj, field_name, value);
|
|---|
| 1221 | }
|
|---|
| 1222 | else if (type == Byte.TYPE)
|
|---|
| 1223 | {
|
|---|
| 1224 | byte value =
|
|---|
| 1225 | default_initialize ? 0 : this.realInputStream.readByte ();
|
|---|
| 1226 | if (!default_initialize && set_value)
|
|---|
| 1227 | dumpElementln (" " + field_name + ": " + value);
|
|---|
| 1228 | if (set_value)
|
|---|
| 1229 | setByteField (obj, field_name, value);
|
|---|
| 1230 | }
|
|---|
| 1231 | else if (type == Character.TYPE)
|
|---|
| 1232 | {
|
|---|
| 1233 | char value =
|
|---|
| 1234 | default_initialize ? (char)0 : this.realInputStream.readChar ();
|
|---|
| 1235 | if (!default_initialize && set_value)
|
|---|
| 1236 | dumpElementln (" " + field_name + ": " + value);
|
|---|
| 1237 | if (set_value)
|
|---|
| 1238 | setCharField (obj, field_name, value);
|
|---|
| 1239 | }
|
|---|
| 1240 | else if (type == Double.TYPE)
|
|---|
| 1241 | {
|
|---|
| 1242 | double value =
|
|---|
| 1243 | default_initialize ? 0 : this.realInputStream.readDouble ();
|
|---|
| 1244 | if (!default_initialize && set_value)
|
|---|
| 1245 | dumpElementln (" " + field_name + ": " + value);
|
|---|
| 1246 | if (set_value)
|
|---|
| 1247 | setDoubleField (obj, field_name, value);
|
|---|
| 1248 | }
|
|---|
| 1249 | else if (type == Float.TYPE)
|
|---|
| 1250 | {
|
|---|
| 1251 | float value =
|
|---|
| 1252 | default_initialize ? 0 : this.realInputStream.readFloat ();
|
|---|
| 1253 | if (!default_initialize && set_value)
|
|---|
| 1254 | dumpElementln (" " + field_name + ": " + value);
|
|---|
| 1255 | if (set_value)
|
|---|
| 1256 | setFloatField (obj, field_name, value);
|
|---|
| 1257 | }
|
|---|
| 1258 | else if (type == Integer.TYPE)
|
|---|
| 1259 | {
|
|---|
| 1260 | int value =
|
|---|
| 1261 | default_initialize ? 0 : this.realInputStream.readInt ();
|
|---|
| 1262 | if (!default_initialize && set_value)
|
|---|
| 1263 | dumpElementln (" " + field_name + ": " + value);
|
|---|
| 1264 | if (set_value)
|
|---|
| 1265 | setIntField (obj, field_name, value);
|
|---|
| 1266 | }
|
|---|
| 1267 | else if (type == Long.TYPE)
|
|---|
| 1268 | {
|
|---|
| 1269 | long value =
|
|---|
| 1270 | default_initialize ? 0 : this.realInputStream.readLong ();
|
|---|
| 1271 | if (!default_initialize && set_value)
|
|---|
| 1272 | dumpElementln (" " + field_name + ": " + value);
|
|---|
| 1273 | if (set_value)
|
|---|
| 1274 | setLongField (obj, field_name, value);
|
|---|
| 1275 | }
|
|---|
| 1276 | else if (type == Short.TYPE)
|
|---|
| 1277 | {
|
|---|
| 1278 | short value =
|
|---|
| 1279 | default_initialize ? (short)0 : this.realInputStream.readShort ();
|
|---|
| 1280 | if (!default_initialize && set_value)
|
|---|
| 1281 | dumpElementln (" " + field_name + ": " + value);
|
|---|
| 1282 | if (set_value)
|
|---|
| 1283 | setShortField (obj, field_name, value);
|
|---|
| 1284 | }
|
|---|
| 1285 | else
|
|---|
| 1286 | {
|
|---|
| 1287 | Object value =
|
|---|
| 1288 | default_initialize ? null : readObject ();
|
|---|
| 1289 | if (set_value)
|
|---|
| 1290 | setObjectField (obj, field_name,
|
|---|
| 1291 | real_field.getTypeString (), value);
|
|---|
| 1292 | }
|
|---|
| 1293 | }
|
|---|
| 1294 | }
|
|---|
| 1295 |
|
|---|
| 1296 |
|
|---|
| 1297 | // Toggles writing primitive data to block-data buffer.
|
|---|
| 1298 | private void setBlockDataMode (boolean on)
|
|---|
| 1299 | {
|
|---|
| 1300 | // DEBUGln ("Setting block data mode to " + on);
|
|---|
| 1301 |
|
|---|
| 1302 | this.readDataFromBlock = on;
|
|---|
| 1303 |
|
|---|
| 1304 | if (on)
|
|---|
| 1305 | this.dataInputStream = this.blockDataInput;
|
|---|
| 1306 | else
|
|---|
| 1307 | this.dataInputStream = this.realInputStream;
|
|---|
| 1308 | }
|
|---|
| 1309 |
|
|---|
| 1310 |
|
|---|
| 1311 | // returns a new instance of REAL_CLASS that has been constructed
|
|---|
| 1312 | // only to the level of CONSTRUCTOR_CLASS (a super class of REAL_CLASS)
|
|---|
| 1313 | private Object newObject (Class real_class, Class constructor_class)
|
|---|
| 1314 | {
|
|---|
| 1315 | try
|
|---|
| 1316 | {
|
|---|
| 1317 | Object obj = allocateObject (real_class);
|
|---|
| 1318 | callConstructor (constructor_class, obj);
|
|---|
| 1319 | return obj;
|
|---|
| 1320 | }
|
|---|
| 1321 | catch (InstantiationException e)
|
|---|
| 1322 | {
|
|---|
| 1323 | return null;
|
|---|
| 1324 | }
|
|---|
| 1325 | }
|
|---|
| 1326 |
|
|---|
| 1327 |
|
|---|
| 1328 | // runs all registered ObjectInputValidations in prioritized order
|
|---|
| 1329 | // on OBJ
|
|---|
| 1330 | private void invokeValidators () throws InvalidObjectException
|
|---|
| 1331 | {
|
|---|
| 1332 | Object[] validators = new Object[this.validators.size ()];
|
|---|
| 1333 | this.validators.copyInto (validators);
|
|---|
| 1334 | Arrays.sort (validators);
|
|---|
| 1335 |
|
|---|
| 1336 | try
|
|---|
| 1337 | {
|
|---|
| 1338 | for (int i=0; i < validators.length; i++)
|
|---|
| 1339 | ((ObjectInputValidation)validators[i]).validateObject ();
|
|---|
| 1340 | }
|
|---|
| 1341 | finally
|
|---|
| 1342 | {
|
|---|
| 1343 | this.validators.removeAllElements ();
|
|---|
| 1344 | }
|
|---|
| 1345 | }
|
|---|
| 1346 |
|
|---|
| 1347 |
|
|---|
| 1348 | // this native method is used to get access to the protected method
|
|---|
| 1349 | // of the same name in SecurityManger
|
|---|
| 1350 | private static ClassLoader currentClassLoader (SecurityManager sm)
|
|---|
| 1351 | {
|
|---|
| 1352 | // FIXME: This is too simple.
|
|---|
| 1353 | return ClassLoader.getSystemClassLoader ();
|
|---|
| 1354 | }
|
|---|
| 1355 |
|
|---|
| 1356 | private static native Field getField (Class klass, String name)
|
|---|
| 1357 | throws java.lang.NoSuchFieldException;
|
|---|
| 1358 |
|
|---|
| 1359 | private static native Method getMethod (Class klass, String name, Class args[])
|
|---|
| 1360 | throws java.lang.NoSuchMethodException;
|
|---|
| 1361 |
|
|---|
| 1362 | private void callReadMethod (Object obj, Class klass) throws IOException
|
|---|
| 1363 | {
|
|---|
| 1364 | try
|
|---|
| 1365 | {
|
|---|
| 1366 | Class classArgs[] = {ObjectInputStream.class};
|
|---|
| 1367 | Method m = getMethod (klass, "readObject", classArgs);
|
|---|
| 1368 | if (m == null)
|
|---|
| 1369 | return;
|
|---|
| 1370 | Object args[] = {this};
|
|---|
| 1371 | m.invoke (obj, args);
|
|---|
| 1372 | }
|
|---|
| 1373 | catch (InvocationTargetException x)
|
|---|
| 1374 | {
|
|---|
| 1375 | /* Rethrow if possible. */
|
|---|
| 1376 | Throwable exception = x.getTargetException();
|
|---|
| 1377 | if (exception instanceof RuntimeException)
|
|---|
| 1378 | throw (RuntimeException) exception;
|
|---|
| 1379 | if (exception instanceof IOException)
|
|---|
| 1380 | throw (IOException) exception;
|
|---|
| 1381 |
|
|---|
| 1382 | throw new IOException ("Exception thrown from readObject() on " +
|
|---|
| 1383 | klass + ": " + exception.getClass().getName());
|
|---|
| 1384 | }
|
|---|
| 1385 | catch (Exception x)
|
|---|
| 1386 | {
|
|---|
| 1387 | throw new IOException ("Failure invoking readObject() on " +
|
|---|
| 1388 | klass + ": " + x.getClass().getName());
|
|---|
| 1389 | }
|
|---|
| 1390 | }
|
|---|
| 1391 |
|
|---|
| 1392 | private native Object allocateObject (Class clazz)
|
|---|
| 1393 | throws InstantiationException;
|
|---|
| 1394 |
|
|---|
| 1395 | private native void callConstructor (Class clazz, Object obj);
|
|---|
| 1396 |
|
|---|
| 1397 | private void setBooleanField (Object obj, String field_name,
|
|---|
| 1398 | boolean val)
|
|---|
| 1399 | {
|
|---|
| 1400 | try
|
|---|
| 1401 | {
|
|---|
| 1402 | Class klass = obj.getClass ();
|
|---|
| 1403 | Field f = getField (klass, field_name);
|
|---|
| 1404 | f.setBoolean (obj, val);
|
|---|
| 1405 | }
|
|---|
| 1406 | catch (Exception _)
|
|---|
| 1407 | {
|
|---|
| 1408 | }
|
|---|
| 1409 | }
|
|---|
| 1410 |
|
|---|
| 1411 | private void setByteField (Object obj, String field_name,
|
|---|
| 1412 | byte val)
|
|---|
| 1413 | {
|
|---|
| 1414 | try
|
|---|
| 1415 | {
|
|---|
| 1416 | Class klass = obj.getClass ();
|
|---|
| 1417 | Field f = getField (klass, field_name);
|
|---|
| 1418 | f.setByte (obj, val);
|
|---|
| 1419 | }
|
|---|
| 1420 | catch (Exception _)
|
|---|
| 1421 | {
|
|---|
| 1422 | }
|
|---|
| 1423 | }
|
|---|
| 1424 |
|
|---|
| 1425 | private void setCharField (Object obj, String field_name,
|
|---|
| 1426 | char val)
|
|---|
| 1427 | {
|
|---|
| 1428 | try
|
|---|
| 1429 | {
|
|---|
| 1430 | Class klass = obj.getClass ();
|
|---|
| 1431 | Field f = getField (klass, field_name);
|
|---|
| 1432 | f.setChar (obj, val);
|
|---|
| 1433 | }
|
|---|
| 1434 | catch (Exception _)
|
|---|
| 1435 | {
|
|---|
| 1436 | }
|
|---|
| 1437 | }
|
|---|
| 1438 |
|
|---|
| 1439 | private void setDoubleField (Object obj, String field_name,
|
|---|
| 1440 | double val)
|
|---|
| 1441 | {
|
|---|
| 1442 | try
|
|---|
| 1443 | {
|
|---|
| 1444 | Class klass = obj.getClass ();
|
|---|
| 1445 | Field f = getField (klass, field_name);
|
|---|
| 1446 | f.setDouble (obj, val);
|
|---|
| 1447 | }
|
|---|
| 1448 | catch (Exception _)
|
|---|
| 1449 | {
|
|---|
| 1450 | }
|
|---|
| 1451 | }
|
|---|
| 1452 |
|
|---|
| 1453 | private void setFloatField (Object obj, String field_name,
|
|---|
| 1454 | float val)
|
|---|
| 1455 | {
|
|---|
| 1456 | try
|
|---|
| 1457 | {
|
|---|
| 1458 | Class klass = obj.getClass ();
|
|---|
| 1459 | Field f = getField (klass, field_name);
|
|---|
| 1460 | f.setFloat (obj, val);
|
|---|
| 1461 | }
|
|---|
| 1462 | catch (Exception _)
|
|---|
| 1463 | {
|
|---|
| 1464 | }
|
|---|
| 1465 | }
|
|---|
| 1466 |
|
|---|
| 1467 | private void setIntField (Object obj, String field_name,
|
|---|
| 1468 | int val)
|
|---|
| 1469 | {
|
|---|
| 1470 | try
|
|---|
| 1471 | {
|
|---|
| 1472 | Class klass = obj.getClass ();
|
|---|
| 1473 | Field f = getField (klass, field_name);
|
|---|
| 1474 | f.setInt (obj, val);
|
|---|
| 1475 | }
|
|---|
| 1476 | catch (Exception _)
|
|---|
| 1477 | {
|
|---|
| 1478 | }
|
|---|
| 1479 | }
|
|---|
| 1480 |
|
|---|
| 1481 |
|
|---|
| 1482 | private void setLongField (Object obj, String field_name,
|
|---|
| 1483 | long val)
|
|---|
| 1484 | {
|
|---|
| 1485 | try
|
|---|
| 1486 | {
|
|---|
| 1487 | Class klass = obj.getClass ();
|
|---|
| 1488 | Field f = getField (klass, field_name);
|
|---|
| 1489 | f.setLong (obj, val);
|
|---|
| 1490 | }
|
|---|
| 1491 | catch (Exception _)
|
|---|
| 1492 | {
|
|---|
| 1493 | }
|
|---|
| 1494 | }
|
|---|
| 1495 |
|
|---|
| 1496 |
|
|---|
| 1497 | private void setShortField (Object obj, String field_name,
|
|---|
| 1498 | short val)
|
|---|
| 1499 | {
|
|---|
| 1500 | try
|
|---|
| 1501 | {
|
|---|
| 1502 | Class klass = obj.getClass ();
|
|---|
| 1503 | Field f = getField (klass, field_name);
|
|---|
| 1504 | f.setShort (obj, val);
|
|---|
| 1505 | }
|
|---|
| 1506 | catch (Exception _)
|
|---|
| 1507 | {
|
|---|
| 1508 | }
|
|---|
| 1509 | }
|
|---|
| 1510 |
|
|---|
| 1511 |
|
|---|
| 1512 | private void setObjectField (Object obj, String field_name, String type_code,
|
|---|
| 1513 | Object val)
|
|---|
| 1514 | {
|
|---|
| 1515 | try
|
|---|
| 1516 | {
|
|---|
| 1517 | Class klass = obj.getClass ();
|
|---|
| 1518 | Field f = getField (klass, field_name);
|
|---|
| 1519 | // FIXME: We should check the type_code here
|
|---|
| 1520 | f.set (obj, val);
|
|---|
| 1521 | }
|
|---|
| 1522 | catch (Exception _)
|
|---|
| 1523 | {
|
|---|
| 1524 | }
|
|---|
| 1525 | }
|
|---|
| 1526 |
|
|---|
| 1527 | private static final int BUFFER_SIZE = 1024;
|
|---|
| 1528 | private static final Class[] readObjectParams = { ObjectInputStream.class };
|
|---|
| 1529 |
|
|---|
| 1530 | private DataInputStream realInputStream;
|
|---|
| 1531 | private DataInputStream dataInputStream;
|
|---|
| 1532 | private DataInputStream blockDataInput;
|
|---|
| 1533 | private int blockDataPosition;
|
|---|
| 1534 | private int blockDataBytes;
|
|---|
| 1535 | private byte[] blockData;
|
|---|
| 1536 | private boolean useSubclassMethod;
|
|---|
| 1537 | private int nextOID;
|
|---|
| 1538 | private boolean resolveEnabled;
|
|---|
| 1539 | private Hashtable objectLookupTable;
|
|---|
| 1540 | private Object currentObject;
|
|---|
| 1541 | private ObjectStreamClass currentObjectStreamClass;
|
|---|
| 1542 | private boolean readDataFromBlock;
|
|---|
| 1543 | private boolean isDeserializing;
|
|---|
| 1544 | private boolean fieldsAlreadyRead;
|
|---|
| 1545 | private Vector validators;
|
|---|
| 1546 |
|
|---|
| 1547 | private static boolean dump;
|
|---|
| 1548 |
|
|---|
| 1549 | private void dumpElement (String msg)
|
|---|
| 1550 | {
|
|---|
| 1551 | if (Configuration.DEBUG && dump)
|
|---|
| 1552 | System.out.print(msg);
|
|---|
| 1553 | }
|
|---|
| 1554 |
|
|---|
| 1555 | private void dumpElementln (String msg)
|
|---|
| 1556 | {
|
|---|
| 1557 | if (Configuration.DEBUG && dump)
|
|---|
| 1558 | System.out.println(msg);
|
|---|
| 1559 | }
|
|---|
| 1560 | }
|
|---|
| 1561 |
|
|---|
| 1562 |
|
|---|
| 1563 | // used to keep a prioritized list of object validators
|
|---|
| 1564 | class ValidatorAndPriority implements Comparable
|
|---|
| 1565 | {
|
|---|
| 1566 | int priority;
|
|---|
| 1567 | ObjectInputValidation validator;
|
|---|
| 1568 |
|
|---|
| 1569 | ValidatorAndPriority (ObjectInputValidation validator, int priority)
|
|---|
| 1570 | {
|
|---|
| 1571 | this.priority = priority;
|
|---|
| 1572 | this.validator = validator;
|
|---|
| 1573 | }
|
|---|
| 1574 |
|
|---|
| 1575 | public int compareTo (Object o)
|
|---|
| 1576 | {
|
|---|
| 1577 | ValidatorAndPriority vap = (ValidatorAndPriority)o;
|
|---|
| 1578 | return this.priority - vap.priority;
|
|---|
| 1579 | }
|
|---|
| 1580 | }
|
|---|