|
1 /* |
|
2 * Copyright 1998-2004 Sun Microsystems, Inc. All Rights Reserved. |
|
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
|
4 * |
|
5 * This code is free software; you can redistribute it and/or modify it |
|
6 * under the terms of the GNU General Public License version 2 only, as |
|
7 * published by the Free Software Foundation. Sun designates this |
|
8 * particular file as subject to the "Classpath" exception as provided |
|
9 * by Sun in the LICENSE file that accompanied this code. |
|
10 * |
|
11 * This code is distributed in the hope that it will be useful, but WITHOUT |
|
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
|
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
|
14 * version 2 for more details (a copy is included in the LICENSE file that |
|
15 * accompanied this code). |
|
16 * |
|
17 * You should have received a copy of the GNU General Public License version |
|
18 * 2 along with this work; if not, write to the Free Software Foundation, |
|
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
|
20 * |
|
21 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, |
|
22 * CA 95054 USA or visit www.sun.com if you need additional information or |
|
23 * have any questions. |
|
24 */ |
|
25 /* |
|
26 * Licensed Materials - Property of IBM |
|
27 * RMI-IIOP v1.0 |
|
28 * Copyright IBM Corp. 1998 1999 All Rights Reserved |
|
29 * |
|
30 */ |
|
31 |
|
32 package com.sun.corba.se.impl.io; |
|
33 |
|
34 import java.io.InputStream; |
|
35 import java.io.IOException; |
|
36 import java.io.StreamCorruptedException; |
|
37 import java.io.ObjectInputValidation; |
|
38 import java.io.NotActiveException; |
|
39 import java.io.InvalidObjectException; |
|
40 import java.io.InvalidClassException; |
|
41 import java.io.DataInputStream; |
|
42 import java.io.OptionalDataException; |
|
43 import java.io.WriteAbortedException; |
|
44 import java.io.Externalizable; |
|
45 import java.io.EOFException; |
|
46 import java.lang.reflect.*; |
|
47 import java.util.Vector; |
|
48 import java.util.Stack; |
|
49 import java.util.Hashtable; |
|
50 import java.util.Enumeration; |
|
51 |
|
52 import sun.corba.Bridge ; |
|
53 |
|
54 import java.security.AccessController ; |
|
55 import java.security.PrivilegedAction ; |
|
56 |
|
57 import com.sun.corba.se.impl.io.ObjectStreamClass; |
|
58 import com.sun.corba.se.impl.util.Utility; |
|
59 |
|
60 import org.omg.CORBA.portable.ValueInputStream; |
|
61 |
|
62 import org.omg.CORBA.ValueMember; |
|
63 import org.omg.CORBA.SystemException; |
|
64 import org.omg.CORBA.TCKind; |
|
65 import org.omg.CORBA.ORB; |
|
66 import org.omg.CORBA.CompletionStatus; |
|
67 import org.omg.CORBA.portable.IndirectionException; |
|
68 import org.omg.CORBA.MARSHAL; |
|
69 import org.omg.CORBA.TypeCode; |
|
70 |
|
71 import com.sun.org.omg.CORBA.ValueDefPackage.FullValueDescription; |
|
72 import com.sun.org.omg.SendingContext.CodeBase; |
|
73 |
|
74 import javax.rmi.PortableRemoteObject; |
|
75 import javax.rmi.CORBA.Util; |
|
76 import javax.rmi.CORBA.ValueHandler; |
|
77 |
|
78 import java.security.*; |
|
79 import java.util.*; |
|
80 |
|
81 import com.sun.corba.se.impl.orbutil.ObjectUtility ; |
|
82 import com.sun.corba.se.impl.logging.OMGSystemException ; |
|
83 import com.sun.corba.se.impl.logging.UtilSystemException ; |
|
84 |
|
85 import com.sun.corba.se.spi.logging.CORBALogDomains ; |
|
86 |
|
87 /** |
|
88 * IIOPInputStream is used by the ValueHandlerImpl to handle Java serialization |
|
89 * input semantics. |
|
90 * |
|
91 * @author Stephen Lewallen |
|
92 * @since JDK1.1.6 |
|
93 */ |
|
94 |
|
95 public class IIOPInputStream |
|
96 extends com.sun.corba.se.impl.io.InputStreamHook |
|
97 { |
|
98 private static Bridge bridge = |
|
99 (Bridge)AccessController.doPrivileged( |
|
100 new PrivilegedAction() { |
|
101 public Object run() { |
|
102 return Bridge.get() ; |
|
103 } |
|
104 } |
|
105 ) ; |
|
106 |
|
107 private static OMGSystemException omgWrapper = OMGSystemException.get( |
|
108 CORBALogDomains.RPC_ENCODING ) ; |
|
109 private static UtilSystemException utilWrapper = UtilSystemException.get( |
|
110 CORBALogDomains.RPC_ENCODING ) ; |
|
111 |
|
112 // Necessary to pass the appropriate fields into the |
|
113 // defaultReadObjectDelegate method (which takes no |
|
114 // parameters since it's called from |
|
115 // java.io.ObjectInpuStream defaultReadObject() |
|
116 // which we can't change). |
|
117 // |
|
118 // This is only used in the case where the fields had |
|
119 // to be obtained remotely because of a serializable |
|
120 // version difference. Set in inputObjectUsingFVD. |
|
121 // Part of serialization evolution fixes for Ladybird, |
|
122 // bug 4365188. |
|
123 private ValueMember defaultReadObjectFVDMembers[] = null; |
|
124 |
|
125 private org.omg.CORBA_2_3.portable.InputStream orbStream; |
|
126 |
|
127 private CodeBase cbSender; |
|
128 |
|
129 private ValueHandlerImpl vhandler; //d4365188 |
|
130 |
|
131 private Object currentObject = null; |
|
132 |
|
133 private ObjectStreamClass currentClassDesc = null; |
|
134 |
|
135 private Class currentClass = null; |
|
136 |
|
137 private int recursionDepth = 0; |
|
138 |
|
139 private int simpleReadDepth = 0; |
|
140 |
|
141 // The ActiveRecursionManager replaces the old RecursionManager which |
|
142 // used to record how many recursions were made, and resolve them after |
|
143 // an object was completely deserialized. |
|
144 // |
|
145 // That created problems (as in bug 4414154) because when custom |
|
146 // unmarshaling in readObject, there can be recursive references |
|
147 // to one of the objects currently being unmarshaled, and the |
|
148 // passive recursion system failed. |
|
149 ActiveRecursionManager activeRecursionMgr = new ActiveRecursionManager(); |
|
150 |
|
151 private IOException abortIOException = null; |
|
152 |
|
153 /* Remember the first exception that stopped this stream. */ |
|
154 private ClassNotFoundException abortClassNotFoundException = null; |
|
155 |
|
156 /* Vector of validation callback objects |
|
157 * The vector is created as needed. The vector is maintained in |
|
158 * order of highest (first) priority to lowest |
|
159 */ |
|
160 private Vector callbacks; |
|
161 |
|
162 // Serialization machinery fields |
|
163 /* Arrays used to keep track of classes and ObjectStreamClasses |
|
164 * as they are being merged; used in inputObject. |
|
165 * spClass is the stack pointer for both. */ |
|
166 ObjectStreamClass[] classdesc; |
|
167 Class[] classes; |
|
168 int spClass; |
|
169 |
|
170 private static final String kEmptyStr = ""; |
|
171 |
|
172 // TCKind TypeCodes used in FVD inputClassFields |
|
173 //public static final TypeCode kRemoteTypeCode = new TypeCodeImpl(TCKind._tk_objref); |
|
174 //public static final TypeCode kValueTypeCode = new TypeCodeImpl(TCKind._tk_value); |
|
175 // removed TypeCodeImpl dependency |
|
176 public static final TypeCode kRemoteTypeCode = ORB.init().get_primitive_tc(TCKind.tk_objref); |
|
177 public static final TypeCode kValueTypeCode = ORB.init().get_primitive_tc(TCKind.tk_value); |
|
178 |
|
179 // TESTING CODE - useFVDOnly should be made final before FCS in order to |
|
180 // optimize out the check. |
|
181 private static final boolean useFVDOnly = false; |
|
182 |
|
183 private byte streamFormatVersion; |
|
184 |
|
185 // Since java.io.OptionalDataException's constructors are |
|
186 // package private, but we need to throw it in some special |
|
187 // cases, we try to do it by reflection. |
|
188 private static final Constructor OPT_DATA_EXCEPTION_CTOR; |
|
189 |
|
190 private Object[] readObjectArgList = { this } ; |
|
191 |
|
192 static { |
|
193 OPT_DATA_EXCEPTION_CTOR = getOptDataExceptionCtor(); |
|
194 } |
|
195 |
|
196 // Grab the OptionalDataException boolean ctor and make |
|
197 // it accessible. Note that any exceptions |
|
198 // will be wrapped in ExceptionInInitializerErrors. |
|
199 private static Constructor getOptDataExceptionCtor() { |
|
200 |
|
201 try { |
|
202 |
|
203 Constructor result = |
|
204 |
|
205 (Constructor) AccessController.doPrivileged( |
|
206 new PrivilegedExceptionAction() { |
|
207 public java.lang.Object run() |
|
208 throws NoSuchMethodException, |
|
209 SecurityException { |
|
210 |
|
211 Constructor boolCtor |
|
212 = OptionalDataException.class.getDeclaredConstructor( |
|
213 new Class[] { |
|
214 Boolean.TYPE }); |
|
215 |
|
216 boolCtor.setAccessible(true); |
|
217 |
|
218 return boolCtor; |
|
219 }}); |
|
220 |
|
221 if (result == null) |
|
222 // XXX I18N, logging needed. |
|
223 throw new Error("Unable to find OptionalDataException constructor"); |
|
224 |
|
225 return result; |
|
226 |
|
227 } catch (Exception ex) { |
|
228 // XXX I18N, logging needed. |
|
229 throw new ExceptionInInitializerError(ex); |
|
230 } |
|
231 } |
|
232 |
|
233 // Create a new OptionalDataException with the EOF marker |
|
234 // set to true. See handleOptionalDataMarshalException. |
|
235 private OptionalDataException createOptionalDataException() { |
|
236 try { |
|
237 OptionalDataException result |
|
238 = (OptionalDataException) |
|
239 OPT_DATA_EXCEPTION_CTOR.newInstance(new Object[] { |
|
240 Boolean.TRUE }); |
|
241 |
|
242 if (result == null) |
|
243 // XXX I18N, logging needed. |
|
244 throw new Error("Created null OptionalDataException"); |
|
245 |
|
246 return result; |
|
247 |
|
248 } catch (Exception ex) { |
|
249 // XXX I18N, logging needed. |
|
250 throw new Error("Couldn't create OptionalDataException", ex); |
|
251 } |
|
252 } |
|
253 |
|
254 // Return the stream format version currently being used |
|
255 // to deserialize an object |
|
256 protected byte getStreamFormatVersion() { |
|
257 return streamFormatVersion; |
|
258 } |
|
259 |
|
260 // At the beginning of data sent by a writeObject or |
|
261 // writeExternal method there is a byte telling the |
|
262 // reader the stream format version. |
|
263 private void readFormatVersion() throws IOException { |
|
264 |
|
265 streamFormatVersion = orbStream.read_octet(); |
|
266 |
|
267 if (streamFormatVersion < 1 || |
|
268 streamFormatVersion > vhandler.getMaximumStreamFormatVersion()) { |
|
269 SystemException sysex = omgWrapper.unsupportedFormatVersion( |
|
270 CompletionStatus.COMPLETED_MAYBE); |
|
271 // XXX I18N? Logging for IOException? |
|
272 IOException result = new IOException("Unsupported format version: " |
|
273 + streamFormatVersion); |
|
274 result.initCause( sysex ) ; |
|
275 throw result ; |
|
276 } |
|
277 |
|
278 if (streamFormatVersion == 2) { |
|
279 if (!(orbStream instanceof ValueInputStream)) { |
|
280 SystemException sysex = omgWrapper.notAValueinputstream( |
|
281 CompletionStatus.COMPLETED_MAYBE); |
|
282 // XXX I18N? Logging for IOException? |
|
283 IOException result = new IOException("Not a ValueInputStream"); |
|
284 result.initCause( sysex ) ; |
|
285 throw result; |
|
286 } |
|
287 } |
|
288 } |
|
289 |
|
290 public static void setTestFVDFlag(boolean val){ |
|
291 // useFVDOnly = val; |
|
292 } |
|
293 |
|
294 /** |
|
295 * Dummy constructor; passes upper stream a dummy stream; |
|
296 **/ |
|
297 public IIOPInputStream() |
|
298 throws java.io.IOException { |
|
299 super(); |
|
300 resetStream(); |
|
301 } |
|
302 |
|
303 public final void setOrbStream(org.omg.CORBA_2_3.portable.InputStream os) { |
|
304 orbStream = os; |
|
305 } |
|
306 |
|
307 public final org.omg.CORBA_2_3.portable.InputStream getOrbStream() { |
|
308 return orbStream; |
|
309 } |
|
310 |
|
311 //added setSender and getSender |
|
312 public final void setSender(CodeBase cb) { |
|
313 cbSender = cb; |
|
314 } |
|
315 |
|
316 public final CodeBase getSender() { |
|
317 return cbSender; |
|
318 } |
|
319 |
|
320 // 4365188 this is added to enable backward compatability w/ wrong |
|
321 // rep-ids |
|
322 public final void setValueHandler(ValueHandler vh) { |
|
323 vhandler = (com.sun.corba.se.impl.io.ValueHandlerImpl) vh; |
|
324 } |
|
325 |
|
326 public final ValueHandler getValueHandler() { |
|
327 return (javax.rmi.CORBA.ValueHandler) vhandler; |
|
328 } |
|
329 |
|
330 public final void increaseRecursionDepth(){ |
|
331 recursionDepth++; |
|
332 } |
|
333 |
|
334 public final int decreaseRecursionDepth(){ |
|
335 return --recursionDepth; |
|
336 } |
|
337 |
|
338 /** |
|
339 * Override the actions of the final method "readObject()" |
|
340 * in ObjectInputStream. |
|
341 * @since JDK1.1.6 |
|
342 * |
|
343 * Read an object from the ObjectInputStream. |
|
344 * The class of the object, the signature of the class, and the values |
|
345 * of the non-transient and non-static fields of the class and all |
|
346 * of its supertypes are read. Default deserializing for a class can be |
|
347 * overriden using the writeObject and readObject methods. |
|
348 * Objects referenced by this object are read transitively so |
|
349 * that a complete equivalent graph of objects is reconstructed by readObject. <p> |
|
350 * |
|
351 * The root object is completly restored when all of its fields |
|
352 * and the objects it references are completely restored. At this |
|
353 * point the object validation callbacks are executed in order |
|
354 * based on their registered priorities. The callbacks are |
|
355 * registered by objects (in the readObject special methods) |
|
356 * as they are individually restored. |
|
357 * |
|
358 * Exceptions are thrown for problems with the InputStream and for classes |
|
359 * that should not be deserialized. All exceptions are fatal to the |
|
360 * InputStream and leave it in an indeterminate state; it is up to the caller |
|
361 * to ignore or recover the stream state. |
|
362 * @exception java.lang.ClassNotFoundException Class of a serialized object |
|
363 * cannot be found. |
|
364 * @exception InvalidClassException Something is wrong with a class used by |
|
365 * serialization. |
|
366 * @exception StreamCorruptedException Control information in the |
|
367 * stream is inconsistent. |
|
368 * @exception OptionalDataException Primitive data was found in the |
|
369 * stream instead of objects. |
|
370 * @exception IOException Any of the usual Input/Output related exceptions. |
|
371 * @since JDK1.1 |
|
372 */ |
|
373 public final Object readObjectDelegate() throws IOException |
|
374 { |
|
375 try { |
|
376 |
|
377 readObjectState.readData(this); |
|
378 |
|
379 return orbStream.read_abstract_interface(); |
|
380 } catch (MARSHAL marshalException) { |
|
381 handleOptionalDataMarshalException(marshalException, true); |
|
382 throw marshalException; |
|
383 } catch(IndirectionException cdrie) |
|
384 { |
|
385 // The CDR stream had never seen the given offset before, |
|
386 // so check the recursion manager (it will throw an |
|
387 // IOException if it doesn't have a reference, either). |
|
388 return activeRecursionMgr.getObject(cdrie.offset); |
|
389 } |
|
390 } |
|
391 |
|
392 final Object simpleReadObject(Class clz, |
|
393 String repositoryID, |
|
394 com.sun.org.omg.SendingContext.CodeBase sender, |
|
395 int offset) |
|
396 /* throws OptionalDataException, ClassNotFoundException, IOException */ |
|
397 { |
|
398 |
|
399 /* Save the current state and get ready to read an object. */ |
|
400 Object prevObject = currentObject; |
|
401 ObjectStreamClass prevClassDesc = currentClassDesc; |
|
402 Class prevClass = currentClass; |
|
403 byte oldStreamFormatVersion = streamFormatVersion; |
|
404 |
|
405 simpleReadDepth++; // Entering |
|
406 Object obj = null; |
|
407 |
|
408 /* |
|
409 * Check for reset, handle it before reading an object. |
|
410 */ |
|
411 try { |
|
412 // d4365188: backward compatability |
|
413 if (vhandler.useFullValueDescription(clz, repositoryID)) { |
|
414 obj = inputObjectUsingFVD(clz, repositoryID, sender, offset); |
|
415 } else { |
|
416 obj = inputObject(clz, repositoryID, sender, offset); |
|
417 } |
|
418 |
|
419 obj = currentClassDesc.readResolve(obj); |
|
420 } |
|
421 catch(ClassNotFoundException cnfe) |
|
422 { |
|
423 bridge.throwException( cnfe ) ; |
|
424 return null; |
|
425 } |
|
426 catch(IOException ioe) |
|
427 { |
|
428 // System.out.println("CLZ = " + clz + "; " + ioe.toString()); |
|
429 bridge.throwException(ioe) ; |
|
430 return null; |
|
431 } |
|
432 finally { |
|
433 simpleReadDepth --; |
|
434 currentObject = prevObject; |
|
435 currentClassDesc = prevClassDesc; |
|
436 currentClass = prevClass; |
|
437 streamFormatVersion = oldStreamFormatVersion; |
|
438 } |
|
439 |
|
440 |
|
441 /* Check for thrown exceptions and re-throw them, clearing them if |
|
442 * this is the last recursive call . |
|
443 */ |
|
444 IOException exIOE = abortIOException; |
|
445 if (simpleReadDepth == 0) |
|
446 abortIOException = null; |
|
447 if (exIOE != null){ |
|
448 bridge.throwException( exIOE ) ; |
|
449 return null; |
|
450 } |
|
451 |
|
452 |
|
453 ClassNotFoundException exCNF = abortClassNotFoundException; |
|
454 if (simpleReadDepth == 0) |
|
455 abortClassNotFoundException = null; |
|
456 if (exCNF != null) { |
|
457 bridge.throwException( exCNF ) ; |
|
458 return null; |
|
459 } |
|
460 |
|
461 return obj; |
|
462 } |
|
463 |
|
464 public final void simpleSkipObject(String repositoryID, |
|
465 com.sun.org.omg.SendingContext.CodeBase sender) |
|
466 /* throws OptionalDataException, ClassNotFoundException, IOException */ |
|
467 { |
|
468 |
|
469 /* Save the current state and get ready to read an object. */ |
|
470 Object prevObject = currentObject; |
|
471 ObjectStreamClass prevClassDesc = currentClassDesc; |
|
472 Class prevClass = currentClass; |
|
473 byte oldStreamFormatVersion = streamFormatVersion; |
|
474 |
|
475 simpleReadDepth++; // Entering |
|
476 Object obj = null; |
|
477 |
|
478 /* |
|
479 * Check for reset, handle it before reading an object. |
|
480 */ |
|
481 try { |
|
482 skipObjectUsingFVD(repositoryID, sender); |
|
483 } |
|
484 catch(ClassNotFoundException cnfe) |
|
485 { |
|
486 bridge.throwException( cnfe ) ; |
|
487 return; |
|
488 } |
|
489 catch(IOException ioe) |
|
490 { |
|
491 bridge.throwException( ioe ) ; |
|
492 return; |
|
493 } |
|
494 finally { |
|
495 simpleReadDepth --; |
|
496 streamFormatVersion = oldStreamFormatVersion; |
|
497 currentObject = prevObject; |
|
498 currentClassDesc = prevClassDesc; |
|
499 currentClass = prevClass; |
|
500 } |
|
501 |
|
502 |
|
503 /* Check for thrown exceptions and re-throw them, clearing them if |
|
504 * this is the last recursive call . |
|
505 */ |
|
506 IOException exIOE = abortIOException; |
|
507 if (simpleReadDepth == 0) |
|
508 abortIOException = null; |
|
509 if (exIOE != null){ |
|
510 bridge.throwException( exIOE ) ; |
|
511 return; |
|
512 } |
|
513 |
|
514 |
|
515 ClassNotFoundException exCNF = abortClassNotFoundException; |
|
516 if (simpleReadDepth == 0) |
|
517 abortClassNotFoundException = null; |
|
518 if (exCNF != null) { |
|
519 bridge.throwException( exCNF ) ; |
|
520 return; |
|
521 } |
|
522 |
|
523 return; |
|
524 } |
|
525 ///////////////// |
|
526 |
|
527 /** |
|
528 * This method is called by trusted subclasses of ObjectOutputStream |
|
529 * that constructed ObjectOutputStream using the |
|
530 * protected no-arg constructor. The subclass is expected to provide |
|
531 * an override method with the modifier "final". |
|
532 * |
|
533 * @return the Object read from the stream. |
|
534 * |
|
535 * @see #ObjectInputStream() |
|
536 * @see #readObject |
|
537 * @since JDK 1.2 |
|
538 */ |
|
539 protected final Object readObjectOverride() |
|
540 throws OptionalDataException, ClassNotFoundException, IOException |
|
541 { |
|
542 return readObjectDelegate(); |
|
543 } |
|
544 |
|
545 /** |
|
546 * Override the actions of the final method "defaultReadObject()" |
|
547 * in ObjectInputStream. |
|
548 * @since JDK1.1.6 |
|
549 * |
|
550 * Read the non-static and non-transient fields of the current class |
|
551 * from this stream. This may only be called from the readObject method |
|
552 * of the class being deserialized. It will throw the NotActiveException |
|
553 * if it is called otherwise. |
|
554 * |
|
555 * @exception java.lang.ClassNotFoundException if the class of a serialized |
|
556 * object could not be found. |
|
557 * @exception IOException if an I/O error occurs. |
|
558 * @exception NotActiveException if the stream is not currently reading |
|
559 * objects. |
|
560 * @since JDK1.1 |
|
561 */ |
|
562 public final void defaultReadObjectDelegate() |
|
563 /* throws IOException, ClassNotFoundException, NotActiveException */ |
|
564 { |
|
565 try { |
|
566 if (currentObject == null || currentClassDesc == null) |
|
567 // XXX I18N, logging needed. |
|
568 throw new NotActiveException("defaultReadObjectDelegate"); |
|
569 |
|
570 // The array will be null unless fields were retrieved |
|
571 // remotely because of a serializable version difference. |
|
572 // Bug fix for 4365188. See the definition of |
|
573 // defaultReadObjectFVDMembers for more information. |
|
574 if (defaultReadObjectFVDMembers != null && |
|
575 defaultReadObjectFVDMembers.length > 0) { |
|
576 |
|
577 // WARNING: Be very careful! What if some of |
|
578 // these fields actually have to do this, too? |
|
579 // This works because the defaultReadObjectFVDMembers |
|
580 // reference is passed to inputClassFields, but |
|
581 // there is no guarantee that |
|
582 // defaultReadObjectFVDMembers will point to the |
|
583 // same array after calling inputClassFields. |
|
584 |
|
585 // Use the remote fields to unmarshal. |
|
586 inputClassFields(currentObject, |
|
587 currentClass, |
|
588 currentClassDesc, |
|
589 defaultReadObjectFVDMembers, |
|
590 cbSender); |
|
591 |
|
592 } else { |
|
593 |
|
594 // Use the local fields to unmarshal. |
|
595 ObjectStreamField[] fields = |
|
596 currentClassDesc.getFieldsNoCopy(); |
|
597 if (fields.length > 0) { |
|
598 inputClassFields(currentObject, currentClass, fields, cbSender); |
|
599 } |
|
600 } |
|
601 } |
|
602 catch(NotActiveException nae) |
|
603 { |
|
604 bridge.throwException( nae ) ; |
|
605 } |
|
606 catch(IOException ioe) |
|
607 { |
|
608 bridge.throwException( ioe ) ; |
|
609 } |
|
610 catch(ClassNotFoundException cnfe) |
|
611 { |
|
612 bridge.throwException( cnfe ) ; |
|
613 } |
|
614 |
|
615 } |
|
616 |
|
617 /** |
|
618 * Override the actions of the final method "enableResolveObject()" |
|
619 * in ObjectInputStream. |
|
620 * @since JDK1.1.6 |
|
621 * |
|
622 * Enable the stream to allow objects read from the stream to be replaced. |
|
623 * If the stream is a trusted class it is allowed to enable replacment. |
|
624 * Trusted classes are those classes with a classLoader equals null. <p> |
|
625 * |
|
626 * When enabled the resolveObject method is called for every object |
|
627 * being deserialized. |
|
628 * |
|
629 * @exception SecurityException The classloader of this stream object is non-null. |
|
630 * @since JDK1.1 |
|
631 */ |
|
632 public final boolean enableResolveObjectDelegate(boolean enable) |
|
633 /* throws SecurityException */ |
|
634 { |
|
635 return false; |
|
636 } |
|
637 |
|
638 // The following three methods allow the implementing orbStream |
|
639 // to provide mark/reset behavior as defined in java.io.InputStream. |
|
640 |
|
641 public final void mark(int readAheadLimit) { |
|
642 orbStream.mark(readAheadLimit); |
|
643 } |
|
644 |
|
645 public final boolean markSupported() { |
|
646 return orbStream.markSupported(); |
|
647 } |
|
648 |
|
649 public final void reset() throws IOException { |
|
650 try { |
|
651 orbStream.reset(); |
|
652 } catch (Error e) { |
|
653 IOException err = new IOException(e.getMessage()); |
|
654 err.initCause(e) ; |
|
655 throw err ; |
|
656 } |
|
657 } |
|
658 |
|
659 public final int available() throws IOException{ |
|
660 return 0; // unreliable |
|
661 } |
|
662 |
|
663 public final void close() throws IOException{ |
|
664 // no op |
|
665 } |
|
666 |
|
667 public final int read() throws IOException{ |
|
668 try{ |
|
669 readObjectState.readData(this); |
|
670 |
|
671 return (orbStream.read_octet() << 0) & 0x000000FF; |
|
672 } catch (MARSHAL marshalException) { |
|
673 if (marshalException.minor |
|
674 == OMGSystemException.RMIIIOP_OPTIONAL_DATA_INCOMPATIBLE1) { |
|
675 setState(IN_READ_OBJECT_NO_MORE_OPT_DATA); |
|
676 return -1; |
|
677 } |
|
678 |
|
679 throw marshalException; |
|
680 } catch(Error e) { |
|
681 IOException exc = new IOException(e.getMessage()); |
|
682 exc.initCause(e) ; |
|
683 throw exc ; |
|
684 } |
|
685 } |
|
686 |
|
687 public final int read(byte data[], int offset, int length) throws IOException{ |
|
688 try{ |
|
689 readObjectState.readData(this); |
|
690 |
|
691 orbStream.read_octet_array(data, offset, length); |
|
692 return length; |
|
693 } catch (MARSHAL marshalException) { |
|
694 if (marshalException.minor |
|
695 == OMGSystemException.RMIIIOP_OPTIONAL_DATA_INCOMPATIBLE1) { |
|
696 setState(IN_READ_OBJECT_NO_MORE_OPT_DATA); |
|
697 return -1; |
|
698 } |
|
699 |
|
700 throw marshalException; |
|
701 } catch(Error e) { |
|
702 IOException exc = new IOException(e.getMessage()); |
|
703 exc.initCause(e) ; |
|
704 throw exc ; |
|
705 } |
|
706 |
|
707 } |
|
708 |
|
709 public final boolean readBoolean() throws IOException{ |
|
710 try{ |
|
711 readObjectState.readData(this); |
|
712 |
|
713 return orbStream.read_boolean(); |
|
714 } catch (MARSHAL marshalException) { |
|
715 handleOptionalDataMarshalException(marshalException, false); |
|
716 throw marshalException; |
|
717 |
|
718 } catch(Error e) { |
|
719 IOException exc = new IOException(e.getMessage()); |
|
720 exc.initCause(e); |
|
721 throw exc ; |
|
722 } |
|
723 } |
|
724 |
|
725 public final byte readByte() throws IOException{ |
|
726 try{ |
|
727 readObjectState.readData(this); |
|
728 |
|
729 return orbStream.read_octet(); |
|
730 } catch (MARSHAL marshalException) { |
|
731 handleOptionalDataMarshalException(marshalException, false); |
|
732 throw marshalException; |
|
733 |
|
734 } catch(Error e) { |
|
735 IOException exc = new IOException(e.getMessage()); |
|
736 exc.initCause(e); |
|
737 throw exc ; |
|
738 } |
|
739 } |
|
740 |
|
741 public final char readChar() throws IOException{ |
|
742 try{ |
|
743 readObjectState.readData(this); |
|
744 |
|
745 return orbStream.read_wchar(); |
|
746 } catch (MARSHAL marshalException) { |
|
747 handleOptionalDataMarshalException(marshalException, false); |
|
748 throw marshalException; |
|
749 |
|
750 } catch(Error e) { |
|
751 IOException exc = new IOException(e.getMessage()); |
|
752 exc.initCause(e); |
|
753 throw exc ; |
|
754 } |
|
755 } |
|
756 |
|
757 public final double readDouble() throws IOException{ |
|
758 try{ |
|
759 readObjectState.readData(this); |
|
760 |
|
761 return orbStream.read_double(); |
|
762 } catch (MARSHAL marshalException) { |
|
763 handleOptionalDataMarshalException(marshalException, false); |
|
764 throw marshalException; |
|
765 } catch(Error e) { |
|
766 IOException exc = new IOException(e.getMessage()); |
|
767 exc.initCause(e); |
|
768 throw exc ; |
|
769 } |
|
770 } |
|
771 |
|
772 public final float readFloat() throws IOException{ |
|
773 try{ |
|
774 readObjectState.readData(this); |
|
775 |
|
776 return orbStream.read_float(); |
|
777 } catch (MARSHAL marshalException) { |
|
778 handleOptionalDataMarshalException(marshalException, false); |
|
779 throw marshalException; |
|
780 } catch(Error e) { |
|
781 IOException exc = new IOException(e.getMessage()); |
|
782 exc.initCause(e); |
|
783 throw exc ; |
|
784 } |
|
785 } |
|
786 |
|
787 public final void readFully(byte data[]) throws IOException{ |
|
788 // d11623 : implement readFully, required for serializing some core classes |
|
789 |
|
790 readFully(data, 0, data.length); |
|
791 } |
|
792 |
|
793 public final void readFully(byte data[], int offset, int size) throws IOException{ |
|
794 // d11623 : implement readFully, required for serializing some core classes |
|
795 try{ |
|
796 readObjectState.readData(this); |
|
797 |
|
798 orbStream.read_octet_array(data, offset, size); |
|
799 } catch (MARSHAL marshalException) { |
|
800 handleOptionalDataMarshalException(marshalException, false); |
|
801 |
|
802 throw marshalException; |
|
803 } catch(Error e) { |
|
804 IOException exc = new IOException(e.getMessage()); |
|
805 exc.initCause(e); |
|
806 throw exc ; |
|
807 } |
|
808 } |
|
809 |
|
810 public final int readInt() throws IOException{ |
|
811 try{ |
|
812 readObjectState.readData(this); |
|
813 |
|
814 return orbStream.read_long(); |
|
815 } catch (MARSHAL marshalException) { |
|
816 handleOptionalDataMarshalException(marshalException, false); |
|
817 throw marshalException; |
|
818 } catch(Error e) { |
|
819 IOException exc = new IOException(e.getMessage()); |
|
820 exc.initCause(e); |
|
821 throw exc ; |
|
822 } |
|
823 } |
|
824 |
|
825 public final String readLine() throws IOException{ |
|
826 // XXX I18N, logging needed. |
|
827 throw new IOException("Method readLine not supported"); |
|
828 } |
|
829 |
|
830 public final long readLong() throws IOException{ |
|
831 try{ |
|
832 readObjectState.readData(this); |
|
833 |
|
834 return orbStream.read_longlong(); |
|
835 } catch (MARSHAL marshalException) { |
|
836 handleOptionalDataMarshalException(marshalException, false); |
|
837 throw marshalException; |
|
838 } catch(Error e) { |
|
839 IOException exc = new IOException(e.getMessage()); |
|
840 exc.initCause(e); |
|
841 throw exc ; |
|
842 } |
|
843 } |
|
844 |
|
845 public final short readShort() throws IOException{ |
|
846 try{ |
|
847 readObjectState.readData(this); |
|
848 |
|
849 return orbStream.read_short(); |
|
850 } catch (MARSHAL marshalException) { |
|
851 handleOptionalDataMarshalException(marshalException, false); |
|
852 throw marshalException; |
|
853 } catch(Error e) { |
|
854 IOException exc = new IOException(e.getMessage()); |
|
855 exc.initCause(e); |
|
856 throw exc ; |
|
857 } |
|
858 } |
|
859 |
|
860 protected final void readStreamHeader() throws IOException, StreamCorruptedException{ |
|
861 // no op |
|
862 } |
|
863 |
|
864 public final int readUnsignedByte() throws IOException{ |
|
865 try{ |
|
866 readObjectState.readData(this); |
|
867 |
|
868 return (orbStream.read_octet() << 0) & 0x000000FF; |
|
869 } catch (MARSHAL marshalException) { |
|
870 handleOptionalDataMarshalException(marshalException, false); |
|
871 throw marshalException; |
|
872 } catch(Error e) { |
|
873 IOException exc = new IOException(e.getMessage()); |
|
874 exc.initCause(e); |
|
875 throw exc ; |
|
876 } |
|
877 } |
|
878 |
|
879 public final int readUnsignedShort() throws IOException{ |
|
880 try{ |
|
881 readObjectState.readData(this); |
|
882 |
|
883 return (orbStream.read_ushort() << 0) & 0x0000FFFF; |
|
884 } catch (MARSHAL marshalException) { |
|
885 handleOptionalDataMarshalException(marshalException, false); |
|
886 throw marshalException; |
|
887 } catch(Error e) { |
|
888 IOException exc = new IOException(e.getMessage()); |
|
889 exc.initCause(e); |
|
890 throw exc ; |
|
891 } |
|
892 } |
|
893 |
|
894 /** |
|
895 * Helper method for correcting the Kestrel bug 4367783 (dealing |
|
896 * with larger than 8-bit chars). The old behavior is preserved |
|
897 * in orbutil.IIOPInputStream_1_3 in order to interoperate with |
|
898 * our legacy ORBs. |
|
899 */ |
|
900 protected String internalReadUTF(org.omg.CORBA.portable.InputStream stream) |
|
901 { |
|
902 return stream.read_wstring(); |
|
903 } |
|
904 |
|
905 public final String readUTF() throws IOException{ |
|
906 try{ |
|
907 readObjectState.readData(this); |
|
908 |
|
909 return internalReadUTF(orbStream); |
|
910 } catch (MARSHAL marshalException) { |
|
911 handleOptionalDataMarshalException(marshalException, false); |
|
912 throw marshalException; |
|
913 } catch(Error e) { |
|
914 IOException exc = new IOException(e.getMessage()); |
|
915 exc.initCause(e); |
|
916 throw exc ; |
|
917 } |
|
918 } |
|
919 |
|
920 // If the ORB stream detects an incompatibility between what's |
|
921 // on the wire and what our Serializable's readObject wants, |
|
922 // it throws a MARSHAL exception with a specific minor code. |
|
923 // This is rethrown to the readObject as an OptionalDataException. |
|
924 // So far in RMI-IIOP, this process isn't specific enough to |
|
925 // tell the readObject how much data is available, so we always |
|
926 // set the OptionalDataException's EOF marker to true. |
|
927 private void handleOptionalDataMarshalException(MARSHAL marshalException, |
|
928 boolean objectRead) |
|
929 throws IOException { |
|
930 |
|
931 // Java Object Serialization spec 3.4: "If the readObject method |
|
932 // of the class attempts to read more data than is present in the |
|
933 // optional part of the stream for this class, the stream will |
|
934 // return -1 for bytewise reads, throw an EOFException for |
|
935 // primitive data reads, or throw an OptionalDataException |
|
936 // with the eof field set to true for object reads." |
|
937 if (marshalException.minor |
|
938 == OMGSystemException.RMIIIOP_OPTIONAL_DATA_INCOMPATIBLE1) { |
|
939 |
|
940 IOException result; |
|
941 |
|
942 if (!objectRead) |
|
943 result = new EOFException("No more optional data"); |
|
944 else |
|
945 result = createOptionalDataException(); |
|
946 |
|
947 result.initCause(marshalException); |
|
948 |
|
949 setState(IN_READ_OBJECT_NO_MORE_OPT_DATA); |
|
950 |
|
951 throw result; |
|
952 } |
|
953 } |
|
954 |
|
955 public final synchronized void registerValidation(ObjectInputValidation obj, |
|
956 int prio) |
|
957 throws NotActiveException, InvalidObjectException{ |
|
958 // XXX I18N, logging needed. |
|
959 throw new Error("Method registerValidation not supported"); |
|
960 } |
|
961 |
|
962 protected final Class resolveClass(ObjectStreamClass v) |
|
963 throws IOException, ClassNotFoundException{ |
|
964 // XXX I18N, logging needed. |
|
965 throw new IOException("Method resolveClass not supported"); |
|
966 } |
|
967 |
|
968 protected final Object resolveObject(Object obj) throws IOException{ |
|
969 // XXX I18N, logging needed. |
|
970 throw new IOException("Method resolveObject not supported"); |
|
971 } |
|
972 |
|
973 public final int skipBytes(int len) throws IOException{ |
|
974 try{ |
|
975 readObjectState.readData(this); |
|
976 |
|
977 byte buf[] = new byte[len]; |
|
978 orbStream.read_octet_array(buf, 0, len); |
|
979 return len; |
|
980 } catch (MARSHAL marshalException) { |
|
981 handleOptionalDataMarshalException(marshalException, false); |
|
982 |
|
983 throw marshalException; |
|
984 } catch(Error e) { |
|
985 IOException exc = new IOException(e.getMessage()); |
|
986 exc.initCause(e) ; |
|
987 throw exc ; |
|
988 } |
|
989 } |
|
990 |
|
991 private Object inputObject(Class clz, |
|
992 String repositoryID, |
|
993 com.sun.org.omg.SendingContext.CodeBase sender, |
|
994 int offset) |
|
995 throws IOException, ClassNotFoundException |
|
996 { |
|
997 |
|
998 /* |
|
999 * Get the descriptor and then class of the incoming object. |
|
1000 */ |
|
1001 |
|
1002 currentClassDesc = ObjectStreamClass.lookup(clz); |
|
1003 currentClass = currentClassDesc.forClass(); |
|
1004 //currentClassDesc.setClass(currentClass); |
|
1005 if (currentClass == null) |
|
1006 // XXX I18N, logging needed. |
|
1007 throw new ClassNotFoundException(currentClassDesc.getName()); |
|
1008 |
|
1009 try { |
|
1010 /* If Externalizable, |
|
1011 * Create an instance and tell it to read its data. |
|
1012 * else, |
|
1013 * Handle it as a serializable class. |
|
1014 */ |
|
1015 if (currentClassDesc.isExternalizable()) { |
|
1016 try { |
|
1017 currentObject = (currentClass == null) ? |
|
1018 null : currentClassDesc.newInstance(); |
|
1019 if (currentObject != null) { |
|
1020 |
|
1021 // Store this object and its beginning position |
|
1022 // since there might be indirections to it while |
|
1023 // it's been unmarshalled. |
|
1024 activeRecursionMgr.addObject(offset, currentObject); |
|
1025 |
|
1026 // Read format version |
|
1027 readFormatVersion(); |
|
1028 |
|
1029 Externalizable ext = (Externalizable)currentObject; |
|
1030 ext.readExternal(this); |
|
1031 } |
|
1032 } catch (InvocationTargetException e) { |
|
1033 InvalidClassException exc = new InvalidClassException( |
|
1034 currentClass.getName(), |
|
1035 "InvocationTargetException accessing no-arg constructor"); |
|
1036 exc.initCause( e ) ; |
|
1037 throw exc ; |
|
1038 } catch (UnsupportedOperationException e) { |
|
1039 InvalidClassException exc = new InvalidClassException( |
|
1040 currentClass.getName(), |
|
1041 "UnsupportedOperationException accessing no-arg constructor"); |
|
1042 exc.initCause( e ) ; |
|
1043 throw exc ; |
|
1044 } catch (InstantiationException e) { |
|
1045 InvalidClassException exc = new InvalidClassException( |
|
1046 currentClass.getName(), |
|
1047 "InstantiationException accessing no-arg constructor"); |
|
1048 exc.initCause( e ) ; |
|
1049 throw exc ; |
|
1050 } |
|
1051 } // end : if (currentClassDesc.isExternalizable()) |
|
1052 else { |
|
1053 /* Count number of classes and descriptors we might have |
|
1054 * to work on. |
|
1055 */ |
|
1056 |
|
1057 ObjectStreamClass currdesc = currentClassDesc; |
|
1058 Class currclass = currentClass; |
|
1059 |
|
1060 int spBase = spClass; // current top of stack |
|
1061 |
|
1062 /* The object's classes should be processed from supertype to subtype |
|
1063 * Push all the clases of the current object onto a stack. |
|
1064 * Note that only the serializable classes are represented |
|
1065 * in the descriptor list. |
|
1066 * |
|
1067 * Handle versioning where one or more supertypes of |
|
1068 * have been inserted or removed. The stack will |
|
1069 * contain pairs of descriptors and the corresponding |
|
1070 * class. If the object has a class that did not occur in |
|
1071 * the original the descriptor will be null. If the |
|
1072 * original object had a descriptor for a class not |
|
1073 * present in the local hierarchy of the object the class will be |
|
1074 * null. |
|
1075 * |
|
1076 */ |
|
1077 |
|
1078 /* |
|
1079 * This is your basic diff pattern, made simpler |
|
1080 * because reordering is not allowed. |
|
1081 */ |
|
1082 // sun.4296963 ibm.11861 |
|
1083 // d11861 we should stop when we find the highest serializable class |
|
1084 // We need this so that when we allocate the new object below, we |
|
1085 // can call the constructor of the non-serializable superclass. |
|
1086 // Note that in the JRMP variant of this code the |
|
1087 // ObjectStreamClass.lookup() method handles this, but we've put |
|
1088 // this fix here rather than change lookup because the new behaviour |
|
1089 // is needed in other cases. |
|
1090 |
|
1091 for (currdesc = currentClassDesc, currclass = currentClass; |
|
1092 currdesc != null && currdesc.isSerializable(); /*sun.4296963 ibm.11861*/ |
|
1093 currdesc = currdesc.getSuperclass()) { |
|
1094 |
|
1095 /* |
|
1096 * Search the classes to see if the class of this |
|
1097 * descriptor appears further up the hierarchy. Until |
|
1098 * it's found assume its an inserted class. If it's |
|
1099 * not found, its the descriptor's class that has been |
|
1100 * removed. |
|
1101 */ |
|
1102 Class cc = currdesc.forClass(); |
|
1103 Class cl; |
|
1104 for (cl = currclass; cl != null; cl = cl.getSuperclass()) { |
|
1105 if (cc == cl) { |
|
1106 // found a superclass that matches this descriptor |
|
1107 break; |
|
1108 } else { |
|
1109 /* Ignore a class that doesn't match. No |
|
1110 * action is needed since it is already |
|
1111 * initialized. |
|
1112 */ |
|
1113 } |
|
1114 } // end : for (cl = currclass; cl != null; cl = cl.getSuperclass()) |
|
1115 /* Test if there is room for this new entry. |
|
1116 * If not, double the size of the arrays and copy the contents. |
|
1117 */ |
|
1118 spClass++; |
|
1119 if (spClass >= classes.length) { |
|
1120 int newlen = classes.length * 2; |
|
1121 Class[] newclasses = new Class[newlen]; |
|
1122 ObjectStreamClass[] newclassdesc = new ObjectStreamClass[newlen]; |
|
1123 |
|
1124 System.arraycopy(classes, 0, |
|
1125 newclasses, 0, |
|
1126 classes.length); |
|
1127 System.arraycopy(classdesc, 0, |
|
1128 newclassdesc, 0, |
|
1129 classes.length); |
|
1130 |
|
1131 classes = newclasses; |
|
1132 classdesc = newclassdesc; |
|
1133 } |
|
1134 |
|
1135 if (cl == null) { |
|
1136 /* Class not found corresponding to this descriptor. |
|
1137 * Pop off all the extra classes pushed. |
|
1138 * Push the descriptor and a null class. |
|
1139 */ |
|
1140 classdesc[spClass] = currdesc; |
|
1141 classes[spClass] = null; |
|
1142 } else { |
|
1143 /* Current class descriptor matches current class. |
|
1144 * Some classes may have been inserted. |
|
1145 * Record the match and advance the class, continue |
|
1146 * with the next descriptor. |
|
1147 */ |
|
1148 classdesc[spClass] = currdesc; |
|
1149 classes[spClass] = cl; |
|
1150 currclass = cl.getSuperclass(); |
|
1151 } |
|
1152 } // end : for (currdesc = currentClassDesc, currclass = currentClass; |
|
1153 |
|
1154 /* Allocate a new object. The object is only constructed |
|
1155 * above the highest serializable class and is set to |
|
1156 * default values for all more specialized classes. |
|
1157 */ |
|
1158 try { |
|
1159 currentObject = (currentClass == null) ? |
|
1160 null : currentClassDesc.newInstance() ; |
|
1161 |
|
1162 // Store this object and its beginning position |
|
1163 // since there might be indirections to it while |
|
1164 // it's been unmarshalled. |
|
1165 activeRecursionMgr.addObject(offset, currentObject); |
|
1166 } catch (InvocationTargetException e) { |
|
1167 InvalidClassException exc = new InvalidClassException( |
|
1168 currentClass.getName(), |
|
1169 "InvocationTargetException accessing no-arg constructor"); |
|
1170 exc.initCause( e ) ; |
|
1171 throw exc ; |
|
1172 } catch (UnsupportedOperationException e) { |
|
1173 InvalidClassException exc = new InvalidClassException( |
|
1174 currentClass.getName(), |
|
1175 "UnsupportedOperationException accessing no-arg constructor"); |
|
1176 exc.initCause( e ) ; |
|
1177 throw exc ; |
|
1178 } catch (InstantiationException e) { |
|
1179 InvalidClassException exc = new InvalidClassException( |
|
1180 currentClass.getName(), |
|
1181 "InstantiationException accessing no-arg constructor"); |
|
1182 exc.initCause( e ) ; |
|
1183 throw exc ; |
|
1184 } |
|
1185 |
|
1186 /* |
|
1187 * For all the pushed descriptors and classes. |
|
1188 * if the class has its own writeObject and readObject methods |
|
1189 * call the readObject method |
|
1190 * else |
|
1191 * invoke the defaultReadObject method |
|
1192 */ |
|
1193 try { |
|
1194 for (spClass = spClass; spClass > spBase; spClass--) { |
|
1195 /* |
|
1196 * Set current descriptor and corresponding class |
|
1197 */ |
|
1198 currentClassDesc = classdesc[spClass]; |
|
1199 currentClass = classes[spClass]; |
|
1200 if (classes[spClass] != null) { |
|
1201 /* Read the data from the stream described by the |
|
1202 * descriptor and store into the matching class. |
|
1203 */ |
|
1204 |
|
1205 ReadObjectState oldState = readObjectState; |
|
1206 setState(DEFAULT_STATE); |
|
1207 |
|
1208 try { |
|
1209 |
|
1210 // Changed since invokeObjectReader no longer does this. |
|
1211 if (currentClassDesc.hasWriteObject()) { |
|
1212 |
|
1213 // Read format version |
|
1214 readFormatVersion(); |
|
1215 |
|
1216 // Read defaultWriteObject indicator |
|
1217 boolean calledDefaultWriteObject = readBoolean(); |
|
1218 |
|
1219 readObjectState.beginUnmarshalCustomValue(this, |
|
1220 calledDefaultWriteObject, |
|
1221 (currentClassDesc.readObjectMethod |
|
1222 != null)); |
|
1223 } else { |
|
1224 if (currentClassDesc.hasReadObject()) |
|
1225 setState(IN_READ_OBJECT_REMOTE_NOT_CUSTOM_MARSHALED); |
|
1226 } |
|
1227 |
|
1228 if (!invokeObjectReader(currentClassDesc, currentObject, currentClass) || |
|
1229 readObjectState == IN_READ_OBJECT_DEFAULTS_SENT) { |
|
1230 |
|
1231 // Error case of no readObject and didn't call |
|
1232 // defaultWriteObject handled in default state |
|
1233 |
|
1234 ObjectStreamField[] fields = |
|
1235 currentClassDesc.getFieldsNoCopy(); |
|
1236 if (fields.length > 0) { |
|
1237 inputClassFields(currentObject, currentClass, fields, sender); |
|
1238 } |
|
1239 } |
|
1240 |
|
1241 if (currentClassDesc.hasWriteObject()) |
|
1242 readObjectState.endUnmarshalCustomValue(this); |
|
1243 |
|
1244 } finally { |
|
1245 setState(oldState); |
|
1246 } |
|
1247 |
|
1248 } else { |
|
1249 |
|
1250 // _REVISIT_ : Can we ever get here? |
|
1251 /* No local class for this descriptor, |
|
1252 * Skip over the data for this class. |
|
1253 * like defaultReadObject with a null currentObject. |
|
1254 * The code will read the values but discard them. |
|
1255 */ |
|
1256 ObjectStreamField[] fields = |
|
1257 currentClassDesc.getFieldsNoCopy(); |
|
1258 if (fields.length > 0) { |
|
1259 inputClassFields(null, currentClass, fields, sender); |
|
1260 } |
|
1261 |
|
1262 } |
|
1263 |
|
1264 } |
|
1265 } finally { |
|
1266 // Make sure we exit at the same stack level as when we started. |
|
1267 spClass = spBase; |
|
1268 } |
|
1269 } |
|
1270 } finally { |
|
1271 // We've completed deserializing this object. Any |
|
1272 // future indirections will be handled correctly at the |
|
1273 // CDR level. The ActiveRecursionManager only deals with |
|
1274 // objects currently being deserialized. |
|
1275 activeRecursionMgr.removeObject(offset); |
|
1276 } |
|
1277 |
|
1278 return currentObject; |
|
1279 } |
|
1280 |
|
1281 // This retrieves a vector of FVD's for the hierarchy of serializable classes stemming from |
|
1282 // repositoryID. It is assumed that the sender will not provide base_value id's for non-serializable |
|
1283 // classes! |
|
1284 private Vector getOrderedDescriptions(String repositoryID, |
|
1285 com.sun.org.omg.SendingContext.CodeBase sender) { |
|
1286 Vector descs = new Vector(); |
|
1287 |
|
1288 if (sender == null) { |
|
1289 return descs; |
|
1290 } |
|
1291 |
|
1292 FullValueDescription aFVD = sender.meta(repositoryID); |
|
1293 while (aFVD != null) { |
|
1294 descs.insertElementAt(aFVD, 0); |
|
1295 if ((aFVD.base_value != null) && !kEmptyStr.equals(aFVD.base_value)) { |
|
1296 aFVD = sender.meta(aFVD.base_value); |
|
1297 } |
|
1298 else return descs; |
|
1299 } |
|
1300 |
|
1301 return descs; |
|
1302 } |
|
1303 |
|
1304 /** |
|
1305 * This input method uses FullValueDescriptions retrieved from the sender's runtime to |
|
1306 * read in the data. This method is capable of throwing out data not applicable to client's fields. |
|
1307 * This method handles instances where the reader has a class not sent by the sender, the sender sent |
|
1308 * a class not present on the reader, and/or the reader's class does not match the sender's class. |
|
1309 * |
|
1310 * NOTE : If the local description indicates custom marshaling and the remote type's FVD also |
|
1311 * indicates custom marsahling than the local type is used to read the data off the wire. However, |
|
1312 * if either says custom while the other does not, a MARSHAL error is thrown. Externalizable is |
|
1313 * a form of custom marshaling. |
|
1314 * |
|
1315 */ |
|
1316 private Object inputObjectUsingFVD(Class clz, |
|
1317 String repositoryID, |
|
1318 com.sun.org.omg.SendingContext.CodeBase sender, |
|
1319 int offset) |
|
1320 throws IOException, ClassNotFoundException |
|
1321 { |
|
1322 int spBase = spClass; // current top of stack |
|
1323 try{ |
|
1324 |
|
1325 /* |
|
1326 * Get the descriptor and then class of the incoming object. |
|
1327 */ |
|
1328 |
|
1329 ObjectStreamClass currdesc = currentClassDesc = ObjectStreamClass.lookup(clz); |
|
1330 Class currclass = currentClass = clz; |
|
1331 |
|
1332 /* If Externalizable, |
|
1333 * Create an instance and tell it to read its data. |
|
1334 * else, |
|
1335 * Handle it as a serializable class. |
|
1336 */ |
|
1337 if (currentClassDesc.isExternalizable()) { |
|
1338 try { |
|
1339 currentObject = (currentClass == null) ? |
|
1340 null : currentClassDesc.newInstance(); |
|
1341 if (currentObject != null) { |
|
1342 // Store this object and its beginning position |
|
1343 // since there might be indirections to it while |
|
1344 // it's been unmarshalled. |
|
1345 activeRecursionMgr.addObject(offset, currentObject); |
|
1346 |
|
1347 // Read format version |
|
1348 readFormatVersion(); |
|
1349 |
|
1350 Externalizable ext = (Externalizable)currentObject; |
|
1351 ext.readExternal(this); |
|
1352 } |
|
1353 } catch (InvocationTargetException e) { |
|
1354 InvalidClassException exc = new InvalidClassException( |
|
1355 currentClass.getName(), |
|
1356 "InvocationTargetException accessing no-arg constructor"); |
|
1357 exc.initCause( e ) ; |
|
1358 throw exc ; |
|
1359 } catch (UnsupportedOperationException e) { |
|
1360 InvalidClassException exc = new InvalidClassException( |
|
1361 currentClass.getName(), |
|
1362 "UnsupportedOperationException accessing no-arg constructor"); |
|
1363 exc.initCause( e ) ; |
|
1364 throw exc ; |
|
1365 } catch (InstantiationException e) { |
|
1366 InvalidClassException exc = new InvalidClassException( |
|
1367 currentClass.getName(), |
|
1368 "InstantiationException accessing no-arg constructor"); |
|
1369 exc.initCause( e ) ; |
|
1370 throw exc ; |
|
1371 } |
|
1372 } else { |
|
1373 /* |
|
1374 * This is your basic diff pattern, made simpler |
|
1375 * because reordering is not allowed. |
|
1376 */ |
|
1377 for (currdesc = currentClassDesc, currclass = currentClass; |
|
1378 currdesc != null && currdesc.isSerializable(); /*sun.4296963 ibm.11861*/ |
|
1379 |
|
1380 currdesc = currdesc.getSuperclass()) { |
|
1381 |
|
1382 /* |
|
1383 * Search the classes to see if the class of this |
|
1384 * descriptor appears further up the hierarchy. Until |
|
1385 * it's found assume its an inserted class. If it's |
|
1386 * not found, its the descriptor's class that has been |
|
1387 * removed. |
|
1388 */ |
|
1389 Class cc = currdesc.forClass(); |
|
1390 Class cl; |
|
1391 for (cl = currclass; cl != null; cl = cl.getSuperclass()) { |
|
1392 if (cc == cl) { |
|
1393 // found a superclass that matches this descriptor |
|
1394 break; |
|
1395 } else { |
|
1396 /* Ignore a class that doesn't match. No |
|
1397 * action is needed since it is already |
|
1398 * initialized. |
|
1399 */ |
|
1400 } |
|
1401 } // end : for (cl = currclass; cl != null; cl = cl.getSuperclass()) |
|
1402 /* Test if there is room for this new entry. |
|
1403 * If not, double the size of the arrays and copy the contents. |
|
1404 */ |
|
1405 spClass++; |
|
1406 if (spClass >= classes.length) { |
|
1407 int newlen = classes.length * 2; |
|
1408 Class[] newclasses = new Class[newlen]; |
|
1409 ObjectStreamClass[] newclassdesc = new ObjectStreamClass[newlen]; |
|
1410 |
|
1411 System.arraycopy(classes, 0, |
|
1412 newclasses, 0, |
|
1413 classes.length); |
|
1414 System.arraycopy(classdesc, 0, |
|
1415 newclassdesc, 0, |
|
1416 classes.length); |
|
1417 |
|
1418 classes = newclasses; |
|
1419 classdesc = newclassdesc; |
|
1420 } |
|
1421 |
|
1422 if (cl == null) { |
|
1423 /* Class not found corresponding to this descriptor. |
|
1424 * Pop off all the extra classes pushed. |
|
1425 * Push the descriptor and a null class. |
|
1426 */ |
|
1427 classdesc[spClass] = currdesc; |
|
1428 classes[spClass] = null; |
|
1429 } else { |
|
1430 /* Current class descriptor matches current class. |
|
1431 * Some classes may have been inserted. |
|
1432 * Record the match and advance the class, continue |
|
1433 * with the next descriptor. |
|
1434 */ |
|
1435 classdesc[spClass] = currdesc; |
|
1436 classes[spClass] = cl; |
|
1437 currclass = cl.getSuperclass(); |
|
1438 } |
|
1439 } // end : for (currdesc = currentClassDesc, currclass = currentClass; |
|
1440 |
|
1441 /* Allocate a new object. |
|
1442 */ |
|
1443 try { |
|
1444 currentObject = (currentClass == null) ? |
|
1445 null : currentClassDesc.newInstance(); |
|
1446 |
|
1447 // Store this object and its beginning position |
|
1448 // since there might be indirections to it while |
|
1449 // it's been unmarshalled. |
|
1450 activeRecursionMgr.addObject(offset, currentObject); |
|
1451 } catch (InvocationTargetException e) { |
|
1452 InvalidClassException exc = new InvalidClassException( |
|
1453 currentClass.getName(), |
|
1454 "InvocationTargetException accessing no-arg constructor"); |
|
1455 exc.initCause( e ) ; |
|
1456 throw exc ; |
|
1457 } catch (UnsupportedOperationException e) { |
|
1458 InvalidClassException exc = new InvalidClassException( |
|
1459 currentClass.getName(), |
|
1460 "UnsupportedOperationException accessing no-arg constructor"); |
|
1461 exc.initCause( e ) ; |
|
1462 throw exc ; |
|
1463 } catch (InstantiationException e) { |
|
1464 InvalidClassException exc = new InvalidClassException( |
|
1465 currentClass.getName(), |
|
1466 "InstantiationException accessing no-arg constructor"); |
|
1467 exc.initCause( e ) ; |
|
1468 throw exc ; |
|
1469 } |
|
1470 |
|
1471 Enumeration fvdsList = getOrderedDescriptions(repositoryID, sender).elements(); |
|
1472 |
|
1473 while((fvdsList.hasMoreElements()) && (spClass > spBase)) { |
|
1474 FullValueDescription fvd = (FullValueDescription)fvdsList.nextElement(); |
|
1475 // d4365188: backward compatability |
|
1476 String repIDForFVD = vhandler.getClassName(fvd.id); |
|
1477 String repIDForClass = vhandler.getClassName(vhandler.getRMIRepositoryID(currentClass)); |
|
1478 |
|
1479 while ((spClass > spBase) && |
|
1480 (!repIDForFVD.equals(repIDForClass))) { |
|
1481 int pos = findNextClass(repIDForFVD, classes, spClass, spBase); |
|
1482 if (pos != -1) { |
|
1483 spClass = pos; |
|
1484 currclass = currentClass = classes[spClass]; |
|
1485 repIDForClass = vhandler.getClassName(vhandler.getRMIRepositoryID(currentClass)); |
|
1486 } |
|
1487 else { // Read and throw away one level of the fvdslist |
|
1488 |
|
1489 // This seems to mean that the sender had a superclass that |
|
1490 // we don't have |
|
1491 |
|
1492 if (fvd.is_custom) { |
|
1493 |
|
1494 readFormatVersion(); |
|
1495 boolean calledDefaultWriteObject = readBoolean(); |
|
1496 |
|
1497 if (calledDefaultWriteObject) |
|
1498 inputClassFields(null, null, null, fvd.members, sender); |
|
1499 |
|
1500 if (getStreamFormatVersion() == 2) { |
|
1501 |
|
1502 ((ValueInputStream)getOrbStream()).start_value(); |
|
1503 ((ValueInputStream)getOrbStream()).end_value(); |
|
1504 } |
|
1505 |
|
1506 // WARNING: If stream format version is 1 and there's |
|
1507 // optional data, we'll get some form of exception down |
|
1508 // the line or data corruption. |
|
1509 |
|
1510 } else { |
|
1511 |
|
1512 inputClassFields(null, currentClass, null, fvd.members, sender); |
|
1513 } |
|
1514 |
|
1515 if (fvdsList.hasMoreElements()){ |
|
1516 fvd = (FullValueDescription)fvdsList.nextElement(); |
|
1517 repIDForFVD = vhandler.getClassName(fvd.id); |
|
1518 } |
|
1519 else return currentObject; |
|
1520 } |
|
1521 } |
|
1522 |
|
1523 currdesc = currentClassDesc = ObjectStreamClass.lookup(currentClass); |
|
1524 |
|
1525 if (!repIDForClass.equals("java.lang.Object")) { |
|
1526 |
|
1527 // If the sender used custom marshaling, then it should have put |
|
1528 // the two bytes on the wire indicating stream format version |
|
1529 // and whether or not the writeObject method called |
|
1530 // defaultWriteObject/writeFields. |
|
1531 |
|
1532 ReadObjectState oldState = readObjectState; |
|
1533 setState(DEFAULT_STATE); |
|
1534 |
|
1535 try { |
|
1536 |
|
1537 if (fvd.is_custom) { |
|
1538 |
|
1539 // Read format version |
|
1540 readFormatVersion(); |
|
1541 |
|
1542 // Read defaultWriteObject indicator |
|
1543 boolean calledDefaultWriteObject = readBoolean(); |
|
1544 |
|
1545 readObjectState.beginUnmarshalCustomValue(this, |
|
1546 calledDefaultWriteObject, |
|
1547 (currentClassDesc.readObjectMethod |
|
1548 != null)); |
|
1549 } |
|
1550 |
|
1551 boolean usedReadObject = false; |
|
1552 |
|
1553 // Always use readObject if it exists, and fall back to default |
|
1554 // unmarshaling if it doesn't. |
|
1555 try { |
|
1556 |
|
1557 if (!fvd.is_custom && currentClassDesc.hasReadObject()) |
|
1558 setState(IN_READ_OBJECT_REMOTE_NOT_CUSTOM_MARSHALED); |
|
1559 |
|
1560 // See the definition of defaultReadObjectFVDMembers |
|
1561 // for more information. This concerns making sure |
|
1562 // we use the remote FVD's members in defaultReadObject. |
|
1563 defaultReadObjectFVDMembers = fvd.members; |
|
1564 usedReadObject = invokeObjectReader(currentClassDesc, |
|
1565 currentObject, |
|
1566 currentClass); |
|
1567 |
|
1568 } finally { |
|
1569 defaultReadObjectFVDMembers = null; |
|
1570 } |
|
1571 |
|
1572 // Note that the !usedReadObject !calledDefaultWriteObject |
|
1573 // case is handled by the beginUnmarshalCustomValue method |
|
1574 // of the default state |
|
1575 if (!usedReadObject || readObjectState == IN_READ_OBJECT_DEFAULTS_SENT) |
|
1576 inputClassFields(currentObject, currentClass, currdesc, fvd.members, sender); |
|
1577 |
|
1578 if (fvd.is_custom) |
|
1579 readObjectState.endUnmarshalCustomValue(this); |
|
1580 |
|
1581 } finally { |
|
1582 setState(oldState); |
|
1583 } |
|
1584 |
|
1585 currclass = currentClass = classes[--spClass]; |
|
1586 |
|
1587 } else { |
|
1588 |
|
1589 // The remaining hierarchy of the local class does not match the sender's FVD. |
|
1590 // So, use remaining FVDs to read data off wire. If any remaining FVDs indicate |
|
1591 // custom marshaling, throw MARSHAL error. |
|
1592 inputClassFields(null, currentClass, null, fvd.members, sender); |
|
1593 |
|
1594 while (fvdsList.hasMoreElements()){ |
|
1595 fvd = (FullValueDescription)fvdsList.nextElement(); |
|
1596 |
|
1597 if (fvd.is_custom) |
|
1598 skipCustomUsingFVD(fvd.members, sender); |
|
1599 else |
|
1600 inputClassFields(null, currentClass, null, fvd.members, sender); |
|
1601 } |
|
1602 |
|
1603 } |
|
1604 |
|
1605 } // end : while(fvdsList.hasMoreElements()) |
|
1606 while (fvdsList.hasMoreElements()){ |
|
1607 |
|
1608 FullValueDescription fvd = (FullValueDescription)fvdsList.nextElement(); |
|
1609 if (fvd.is_custom) |
|
1610 skipCustomUsingFVD(fvd.members, sender); |
|
1611 else |
|
1612 throwAwayData(fvd.members, sender); |
|
1613 } |
|
1614 } |
|
1615 |
|
1616 return currentObject; |
|
1617 } |
|
1618 finally { |
|
1619 // Make sure we exit at the same stack level as when we started. |
|
1620 spClass = spBase; |
|
1621 |
|
1622 // We've completed deserializing this object. Any |
|
1623 // future indirections will be handled correctly at the |
|
1624 // CDR level. The ActiveRecursionManager only deals with |
|
1625 // objects currently being deserialized. |
|
1626 activeRecursionMgr.removeObject(offset); |
|
1627 } |
|
1628 |
|
1629 } |
|
1630 |
|
1631 /** |
|
1632 * This input method uses FullValueDescriptions retrieved from the sender's runtime to |
|
1633 * read in the data. This method is capable of throwing out data not applicable to client's fields. |
|
1634 * |
|
1635 * NOTE : If the local description indicates custom marshaling and the remote type's FVD also |
|
1636 * indicates custom marsahling than the local type is used to read the data off the wire. However, |
|
1637 * if either says custom while the other does not, a MARSHAL error is thrown. Externalizable is |
|
1638 * a form of custom marshaling. |
|
1639 * |
|
1640 */ |
|
1641 private Object skipObjectUsingFVD(String repositoryID, |
|
1642 com.sun.org.omg.SendingContext.CodeBase sender) |
|
1643 throws IOException, ClassNotFoundException |
|
1644 { |
|
1645 |
|
1646 Enumeration fvdsList = getOrderedDescriptions(repositoryID, sender).elements(); |
|
1647 |
|
1648 while(fvdsList.hasMoreElements()) { |
|
1649 FullValueDescription fvd = (FullValueDescription)fvdsList.nextElement(); |
|
1650 String repIDForFVD = vhandler.getClassName(fvd.id); |
|
1651 |
|
1652 if (!repIDForFVD.equals("java.lang.Object")) { |
|
1653 if (fvd.is_custom) { |
|
1654 |
|
1655 readFormatVersion(); |
|
1656 |
|
1657 boolean calledDefaultWriteObject = readBoolean(); |
|
1658 |
|
1659 if (calledDefaultWriteObject) |
|
1660 inputClassFields(null, null, null, fvd.members, sender); |
|
1661 |
|
1662 if (getStreamFormatVersion() == 2) { |
|
1663 |
|
1664 ((ValueInputStream)getOrbStream()).start_value(); |
|
1665 ((ValueInputStream)getOrbStream()).end_value(); |
|
1666 } |
|
1667 |
|
1668 // WARNING: If stream format version is 1 and there's |
|
1669 // optional data, we'll get some form of exception down |
|
1670 // the line. |
|
1671 |
|
1672 } else { |
|
1673 // Use default marshaling |
|
1674 inputClassFields(null, null, null, fvd.members, sender); |
|
1675 } |
|
1676 } |
|
1677 |
|
1678 } // end : while(fvdsList.hasMoreElements()) |
|
1679 return null; |
|
1680 |
|
1681 } |
|
1682 |
|
1683 /////////////////// |
|
1684 |
|
1685 private int findNextClass(String classname, Class classes[], int _spClass, int _spBase){ |
|
1686 |
|
1687 for (int i = _spClass; i > _spBase; i--){ |
|
1688 if (classname.equals(classes[i].getName())) { |
|
1689 return i; |
|
1690 } |
|
1691 } |
|
1692 |
|
1693 return -1; |
|
1694 } |
|
1695 |
|
1696 /* |
|
1697 * Invoke the readObject method if present. Assumes that in the case of custom |
|
1698 * marshaling, the format version and defaultWriteObject indicator were already |
|
1699 * removed. |
|
1700 */ |
|
1701 private boolean invokeObjectReader(ObjectStreamClass osc, Object obj, Class aclass) |
|
1702 throws InvalidClassException, StreamCorruptedException, |
|
1703 ClassNotFoundException, IOException |
|
1704 { |
|
1705 if (osc.readObjectMethod == null) { |
|
1706 return false; |
|
1707 } |
|
1708 |
|
1709 try { |
|
1710 osc.readObjectMethod.invoke( obj, readObjectArgList ) ; |
|
1711 return true; |
|
1712 } catch (InvocationTargetException e) { |
|
1713 Throwable t = e.getTargetException(); |
|
1714 if (t instanceof ClassNotFoundException) |
|
1715 throw (ClassNotFoundException)t; |
|
1716 else if (t instanceof IOException) |
|
1717 throw (IOException)t; |
|
1718 else if (t instanceof RuntimeException) |
|
1719 throw (RuntimeException) t; |
|
1720 else if (t instanceof Error) |
|
1721 throw (Error) t; |
|
1722 else |
|
1723 // XXX I18N, logging needed. |
|
1724 throw new Error("internal error"); |
|
1725 } catch (IllegalAccessException e) { |
|
1726 return false; |
|
1727 } |
|
1728 } |
|
1729 |
|
1730 /* |
|
1731 * Reset the stream to be just like it was after the constructor. |
|
1732 */ |
|
1733 private void resetStream() throws IOException { |
|
1734 |
|
1735 if (classes == null) |
|
1736 classes = new Class[20]; |
|
1737 else { |
|
1738 for (int i = 0; i < classes.length; i++) |
|
1739 classes[i] = null; |
|
1740 } |
|
1741 if (classdesc == null) |
|
1742 classdesc = new ObjectStreamClass[20]; |
|
1743 else { |
|
1744 for (int i = 0; i < classdesc.length; i++) |
|
1745 classdesc[i] = null; |
|
1746 } |
|
1747 spClass = 0; |
|
1748 |
|
1749 if (callbacks != null) |
|
1750 callbacks.setSize(0); // discard any pending callbacks |
|
1751 } |
|
1752 |
|
1753 /** |
|
1754 * Factored out of inputClassFields This reads a primitive value and sets it |
|
1755 * in the field of o described by the ObjectStreamField field. |
|
1756 * |
|
1757 * Note that reflection cannot be used here, because reflection cannot be used |
|
1758 * to set final fields. |
|
1759 */ |
|
1760 private void inputPrimitiveField(Object o, Class cl, ObjectStreamField field) |
|
1761 throws InvalidClassException, IOException { |
|
1762 |
|
1763 try { |
|
1764 switch (field.getTypeCode()) { |
|
1765 case 'B': |
|
1766 byte byteValue = orbStream.read_octet(); |
|
1767 bridge.putByte( o, field.getFieldID(), byteValue ) ; |
|
1768 //reflective code: field.getField().setByte( o, byteValue ) ; |
|
1769 break; |
|
1770 case 'Z': |
|
1771 boolean booleanValue = orbStream.read_boolean(); |
|
1772 bridge.putBoolean( o, field.getFieldID(), booleanValue ) ; |
|
1773 //reflective code: field.getField().setBoolean( o, booleanValue ) ; |
|
1774 break; |
|
1775 case 'C': |
|
1776 char charValue = orbStream.read_wchar(); |
|
1777 bridge.putChar( o, field.getFieldID(), charValue ) ; |
|
1778 //reflective code: field.getField().setChar( o, charValue ) ; |
|
1779 break; |
|
1780 case 'S': |
|
1781 short shortValue = orbStream.read_short(); |
|
1782 bridge.putShort( o, field.getFieldID(), shortValue ) ; |
|
1783 //reflective code: field.getField().setShort( o, shortValue ) ; |
|
1784 break; |
|
1785 case 'I': |
|
1786 int intValue = orbStream.read_long(); |
|
1787 bridge.putInt( o, field.getFieldID(), intValue ) ; |
|
1788 //reflective code: field.getField().setInt( o, intValue ) ; |
|
1789 break; |
|
1790 case 'J': |
|
1791 long longValue = orbStream.read_longlong(); |
|
1792 bridge.putLong( o, field.getFieldID(), longValue ) ; |
|
1793 //reflective code: field.getField().setLong( o, longValue ) ; |
|
1794 break; |
|
1795 case 'F' : |
|
1796 float floatValue = orbStream.read_float(); |
|
1797 bridge.putFloat( o, field.getFieldID(), floatValue ) ; |
|
1798 //reflective code: field.getField().setFloat( o, floatValue ) ; |
|
1799 break; |
|
1800 case 'D' : |
|
1801 double doubleValue = orbStream.read_double(); |
|
1802 bridge.putDouble( o, field.getFieldID(), doubleValue ) ; |
|
1803 //reflective code: field.getField().setDouble( o, doubleValue ) ; |
|
1804 break; |
|
1805 default: |
|
1806 // XXX I18N, logging needed. |
|
1807 throw new InvalidClassException(cl.getName()); |
|
1808 } |
|
1809 } catch (IllegalArgumentException e) { |
|
1810 /* This case should never happen. If the field types |
|
1811 are not the same, InvalidClassException is raised when |
|
1812 matching the local class to the serialized ObjectStreamClass. */ |
|
1813 ClassCastException cce = new ClassCastException("Assigning instance of class " + |
|
1814 field.getType().getName() + |
|
1815 " to field " + |
|
1816 currentClassDesc.getName() + '#' + |
|
1817 field.getField().getName()); |
|
1818 cce.initCause( e ) ; |
|
1819 throw cce ; |
|
1820 } |
|
1821 } |
|
1822 |
|
1823 private Object inputObjectField(org.omg.CORBA.ValueMember field, |
|
1824 com.sun.org.omg.SendingContext.CodeBase sender) |
|
1825 throws IndirectionException, ClassNotFoundException, IOException, |
|
1826 StreamCorruptedException { |
|
1827 |
|
1828 Object objectValue = null; |
|
1829 Class type = null; |
|
1830 String id = field.id; |
|
1831 |
|
1832 try { |
|
1833 type = vhandler.getClassFromType(id); |
|
1834 } catch(ClassNotFoundException cnfe) { |
|
1835 // Make sure type = null |
|
1836 type = null; |
|
1837 } |
|
1838 |
|
1839 String signature = null; |
|
1840 if (type != null) |
|
1841 signature = ValueUtility.getSignature(field); |
|
1842 |
|
1843 if (signature != null && (signature.equals("Ljava/lang/Object;") || |
|
1844 signature.equals("Ljava/io/Serializable;") || |
|
1845 signature.equals("Ljava/io/Externalizable;"))) { |
|
1846 objectValue = javax.rmi.CORBA.Util.readAny(orbStream); |
|
1847 } else { |
|
1848 // Decide what method call to make based on the type. If |
|
1849 // it is a type for which we need to load a stub, convert |
|
1850 // the type to the correct stub type. |
|
1851 // |
|
1852 // NOTE : Since FullValueDescription does not allow us |
|
1853 // to ask whether something is an interface we do not |
|
1854 // have the ability to optimize this check. |
|
1855 |
|
1856 int callType = ValueHandlerImpl.kValueType; |
|
1857 |
|
1858 if (!vhandler.isSequence(id)) { |
|
1859 |
|
1860 if (field.type.kind().value() == kRemoteTypeCode.kind().value()) { |
|
1861 |
|
1862 // RMI Object reference... |
|
1863 callType = ValueHandlerImpl.kRemoteType; |
|
1864 |
|
1865 } else { |
|
1866 |
|
1867 // REVISIT. If we don't have the local class, |
|
1868 // we should probably verify that it's an RMI type, |
|
1869 // query the remote FVD, and use is_abstract. |
|
1870 // Our FVD seems to get NullPointerExceptions for any |
|
1871 // non-RMI types. |
|
1872 |
|
1873 // This uses the local class in the same way as |
|
1874 // inputObjectField(ObjectStreamField) does. REVISIT |
|
1875 // inputObjectField(ObjectStreamField)'s loadStubClass |
|
1876 // logic. Assumption is that the given type cannot |
|
1877 // evolve to become a CORBA abstract interface or |
|
1878 // a RMI abstract interface. |
|
1879 |
|
1880 if (type != null && type.isInterface() && |
|
1881 (vhandler.isAbstractBase(type) || |
|
1882 ObjectStreamClassCorbaExt.isAbstractInterface(type))) { |
|
1883 |
|
1884 callType = ValueHandlerImpl.kAbstractType; |
|
1885 } |
|
1886 } |
|
1887 } |
|
1888 |
|
1889 // Now that we have used the FVD of the field to determine the proper course |
|
1890 // of action, it is ok to use the type (Class) from this point forward since |
|
1891 // the rep. id for this read will also follow on the wire. |
|
1892 |
|
1893 switch (callType) { |
|
1894 case ValueHandlerImpl.kRemoteType: |
|
1895 if (type != null) |
|
1896 objectValue = Utility.readObjectAndNarrow(orbStream, type); |
|
1897 else |
|
1898 objectValue = orbStream.read_Object(); |
|
1899 break; |
|
1900 case ValueHandlerImpl.kAbstractType: |
|
1901 if (type != null) |
|
1902 objectValue = Utility.readAbstractAndNarrow(orbStream, type); |
|
1903 else |
|
1904 objectValue = orbStream.read_abstract_interface(); |
|
1905 break; |
|
1906 case ValueHandlerImpl.kValueType: |
|
1907 if (type != null) |
|
1908 objectValue = orbStream.read_value(type); |
|
1909 else |
|
1910 objectValue = orbStream.read_value(); |
|
1911 break; |
|
1912 default: |
|
1913 // XXX I18N, logging needed. |
|
1914 throw new StreamCorruptedException("Unknown callType: " + callType); |
|
1915 } |
|
1916 } |
|
1917 |
|
1918 return objectValue; |
|
1919 } |
|
1920 |
|
1921 /** |
|
1922 * Factored out of inputClassFields and reused in |
|
1923 * inputCurrentClassFieldsForReadFields. |
|
1924 * |
|
1925 * Reads the field (which of an Object type as opposed to a primitive) |
|
1926 * described by ObjectStreamField field and returns it. |
|
1927 */ |
|
1928 private Object inputObjectField(ObjectStreamField field) |
|
1929 throws InvalidClassException, StreamCorruptedException, |
|
1930 ClassNotFoundException, IndirectionException, IOException { |
|
1931 |
|
1932 if (ObjectStreamClassCorbaExt.isAny(field.getTypeString())) { |
|
1933 return javax.rmi.CORBA.Util.readAny(orbStream); |
|
1934 } |
|
1935 |
|
1936 Object objectValue = null; |
|
1937 |
|
1938 // fields have an API to provide the actual class |
|
1939 // corresponding to the data type |
|
1940 // Class type = osc.forClass(); |
|
1941 Class fieldType = field.getType(); |
|
1942 Class actualType = fieldType; // This may change if stub loaded. |
|
1943 |
|
1944 // Decide what method call to make based on the fieldType. If |
|
1945 // it is a type for which we need to load a stub, convert |
|
1946 // the type to the correct stub type. |
|
1947 |
|
1948 int callType = ValueHandlerImpl.kValueType; |
|
1949 boolean narrow = false; |
|
1950 |
|
1951 if (fieldType.isInterface()) { |
|
1952 boolean loadStubClass = false; |
|
1953 |
|
1954 if (java.rmi.Remote.class.isAssignableFrom(fieldType)) { |
|
1955 |
|
1956 // RMI Object reference... |
|
1957 callType = ValueHandlerImpl.kRemoteType; |
|
1958 |
|
1959 } else if (org.omg.CORBA.Object.class.isAssignableFrom(fieldType)){ |
|
1960 |
|
1961 // IDL Object reference... |
|
1962 callType = ValueHandlerImpl.kRemoteType; |
|
1963 loadStubClass = true; |
|
1964 |
|
1965 } else if (vhandler.isAbstractBase(fieldType)) { |
|
1966 // IDL Abstract Object reference... |
|
1967 |
|
1968 callType = ValueHandlerImpl.kAbstractType; |
|
1969 loadStubClass = true; |
|
1970 } else if (ObjectStreamClassCorbaExt.isAbstractInterface(fieldType)) { |
|
1971 // RMI Abstract Object reference... |
|
1972 |
|
1973 callType = ValueHandlerImpl.kAbstractType; |
|
1974 } |
|
1975 |
|
1976 if (loadStubClass) { |
|
1977 try { |
|
1978 String codebase = Util.getCodebase(fieldType); |
|
1979 String repID = vhandler.createForAnyType(fieldType); |
|
1980 Class stubType = |
|
1981 Utility.loadStubClass(repID, codebase, fieldType); |
|
1982 actualType = stubType; |
|
1983 } catch (ClassNotFoundException e) { |
|
1984 narrow = true; |
|
1985 } |
|
1986 } else { |
|
1987 narrow = true; |
|
1988 } |
|
1989 } |
|
1990 |
|
1991 switch (callType) { |
|
1992 case ValueHandlerImpl.kRemoteType: |
|
1993 if (!narrow) |
|
1994 objectValue = (Object)orbStream.read_Object(actualType); |
|
1995 else |
|
1996 objectValue = Utility.readObjectAndNarrow(orbStream, actualType); |
|
1997 break; |
|
1998 case ValueHandlerImpl.kAbstractType: |
|
1999 if (!narrow) |
|
2000 objectValue = (Object)orbStream.read_abstract_interface(actualType); |
|
2001 else |
|
2002 objectValue = Utility.readAbstractAndNarrow(orbStream, actualType); |
|
2003 break; |
|
2004 case ValueHandlerImpl.kValueType: |
|
2005 objectValue = (Object)orbStream.read_value(actualType); |
|
2006 break; |
|
2007 default: |
|
2008 // XXX I18N, logging needed. |
|
2009 throw new StreamCorruptedException("Unknown callType: " + callType); |
|
2010 } |
|
2011 |
|
2012 return objectValue; |
|
2013 } |
|
2014 |
|
2015 private final boolean mustUseRemoteValueMembers() { |
|
2016 return defaultReadObjectFVDMembers != null; |
|
2017 } |
|
2018 |
|
2019 void readFields(java.util.Map fieldToValueMap) |
|
2020 throws InvalidClassException, StreamCorruptedException, |
|
2021 ClassNotFoundException, IOException { |
|
2022 |
|
2023 if (mustUseRemoteValueMembers()) { |
|
2024 inputRemoteMembersForReadFields(fieldToValueMap); |
|
2025 } else |
|
2026 inputCurrentClassFieldsForReadFields(fieldToValueMap); |
|
2027 } |
|
2028 |
|
2029 private final void inputRemoteMembersForReadFields(java.util.Map fieldToValueMap) |
|
2030 throws InvalidClassException, StreamCorruptedException, |
|
2031 ClassNotFoundException, IOException { |
|
2032 |
|
2033 // Must have this local variable since defaultReadObjectFVDMembers |
|
2034 // may get mangled by recursion. |
|
2035 ValueMember fields[] = defaultReadObjectFVDMembers; |
|
2036 |
|
2037 try { |
|
2038 |
|
2039 for (int i = 0; i < fields.length; i++) { |
|
2040 |
|
2041 switch (fields[i].type.kind().value()) { |
|
2042 |
|
2043 case TCKind._tk_octet: |
|
2044 byte byteValue = orbStream.read_octet(); |
|
2045 fieldToValueMap.put(fields[i].name, new Byte(byteValue)); |
|
2046 break; |
|
2047 case TCKind._tk_boolean: |
|
2048 boolean booleanValue = orbStream.read_boolean(); |
|
2049 fieldToValueMap.put(fields[i].name, new Boolean(booleanValue)); |
|
2050 break; |
|
2051 case TCKind._tk_char: |
|
2052 // Backwards compatibility. Older Sun ORBs sent |
|
2053 // _tk_char even though they read and wrote wchars |
|
2054 // correctly. |
|
2055 // |
|
2056 // Fall through to the _tk_wchar case. |
|
2057 case TCKind._tk_wchar: |
|
2058 char charValue = orbStream.read_wchar(); |
|
2059 fieldToValueMap.put(fields[i].name, new Character(charValue)); |
|
2060 break; |
|
2061 case TCKind._tk_short: |
|
2062 short shortValue = orbStream.read_short(); |
|
2063 fieldToValueMap.put(fields[i].name, new Short(shortValue)); |
|
2064 break; |
|
2065 case TCKind._tk_long: |
|
2066 int intValue = orbStream.read_long(); |
|
2067 fieldToValueMap.put(fields[i].name, new Integer(intValue)); |
|
2068 break; |
|
2069 case TCKind._tk_longlong: |
|
2070 long longValue = orbStream.read_longlong(); |
|
2071 fieldToValueMap.put(fields[i].name, new Long(longValue)); |
|
2072 break; |
|
2073 case TCKind._tk_float: |
|
2074 float floatValue = orbStream.read_float(); |
|
2075 fieldToValueMap.put(fields[i].name, new Float(floatValue)); |
|
2076 break; |
|
2077 case TCKind._tk_double: |
|
2078 double doubleValue = orbStream.read_double(); |
|
2079 fieldToValueMap.put(fields[i].name, new Double(doubleValue)); |
|
2080 break; |
|
2081 case TCKind._tk_value: |
|
2082 case TCKind._tk_objref: |
|
2083 case TCKind._tk_value_box: |
|
2084 Object objectValue = null; |
|
2085 try { |
|
2086 objectValue = inputObjectField(fields[i], |
|
2087 cbSender); |
|
2088 |
|
2089 } catch (IndirectionException cdrie) { |
|
2090 // The CDR stream had never seen the given offset before, |
|
2091 // so check the recursion manager (it will throw an |
|
2092 // IOException if it doesn't have a reference, either). |
|
2093 objectValue = activeRecursionMgr.getObject(cdrie.offset); |
|
2094 } |
|
2095 |
|
2096 fieldToValueMap.put(fields[i].name, objectValue); |
|
2097 break; |
|
2098 default: |
|
2099 // XXX I18N, logging needed. |
|
2100 throw new StreamCorruptedException("Unknown kind: " |
|
2101 + fields[i].type.kind().value()); |
|
2102 } |
|
2103 } |
|
2104 } catch (Throwable t) { |
|
2105 StreamCorruptedException result = new StreamCorruptedException(t.getMessage()); |
|
2106 result.initCause(t); |
|
2107 throw result; |
|
2108 } |
|
2109 } |
|
2110 |
|
2111 /** |
|
2112 * Called from InputStreamHook. |
|
2113 * |
|
2114 * Reads the fields of the current class (could be the ones |
|
2115 * queried from the remote FVD) and puts them in |
|
2116 * the given Map, name to value. Wraps primitives in the |
|
2117 * corresponding java.lang Objects. |
|
2118 */ |
|
2119 private final void inputCurrentClassFieldsForReadFields(java.util.Map fieldToValueMap) |
|
2120 throws InvalidClassException, StreamCorruptedException, |
|
2121 ClassNotFoundException, IOException { |
|
2122 |
|
2123 ObjectStreamField[] fields = currentClassDesc.getFieldsNoCopy(); |
|
2124 |
|
2125 int primFields = fields.length - currentClassDesc.objFields; |
|
2126 |
|
2127 // Handle the primitives first |
|
2128 for (int i = 0; i < primFields; ++i) { |
|
2129 |
|
2130 switch (fields[i].getTypeCode()) { |
|
2131 case 'B': |
|
2132 byte byteValue = orbStream.read_octet(); |
|
2133 fieldToValueMap.put(fields[i].getName(), |
|
2134 new Byte(byteValue)); |
|
2135 break; |
|
2136 case 'Z': |
|
2137 boolean booleanValue = orbStream.read_boolean(); |
|
2138 fieldToValueMap.put(fields[i].getName(), |
|
2139 new Boolean(booleanValue)); |
|
2140 break; |
|
2141 case 'C': |
|
2142 char charValue = orbStream.read_wchar(); |
|
2143 fieldToValueMap.put(fields[i].getName(), |
|
2144 new Character(charValue)); |
|
2145 break; |
|
2146 case 'S': |
|
2147 short shortValue = orbStream.read_short(); |
|
2148 fieldToValueMap.put(fields[i].getName(), |
|
2149 new Short(shortValue)); |
|
2150 break; |
|
2151 case 'I': |
|
2152 int intValue = orbStream.read_long(); |
|
2153 fieldToValueMap.put(fields[i].getName(), |
|
2154 new Integer(intValue)); |
|
2155 break; |
|
2156 case 'J': |
|
2157 long longValue = orbStream.read_longlong(); |
|
2158 fieldToValueMap.put(fields[i].getName(), |
|
2159 new Long(longValue)); |
|
2160 break; |
|
2161 case 'F' : |
|
2162 float floatValue = orbStream.read_float(); |
|
2163 fieldToValueMap.put(fields[i].getName(), |
|
2164 new Float(floatValue)); |
|
2165 break; |
|
2166 case 'D' : |
|
2167 double doubleValue = orbStream.read_double(); |
|
2168 fieldToValueMap.put(fields[i].getName(), |
|
2169 new Double(doubleValue)); |
|
2170 break; |
|
2171 default: |
|
2172 // XXX I18N, logging needed. |
|
2173 throw new InvalidClassException(currentClassDesc.getName()); |
|
2174 } |
|
2175 } |
|
2176 |
|
2177 /* Read and set object fields from the input stream. */ |
|
2178 if (currentClassDesc.objFields > 0) { |
|
2179 for (int i = primFields; i < fields.length; i++) { |
|
2180 Object objectValue = null; |
|
2181 try { |
|
2182 objectValue = inputObjectField(fields[i]); |
|
2183 } catch(IndirectionException cdrie) { |
|
2184 // The CDR stream had never seen the given offset before, |
|
2185 // so check the recursion manager (it will throw an |
|
2186 // IOException if it doesn't have a reference, either). |
|
2187 objectValue = activeRecursionMgr.getObject(cdrie.offset); |
|
2188 } |
|
2189 |
|
2190 fieldToValueMap.put(fields[i].getName(), objectValue); |
|
2191 } |
|
2192 } |
|
2193 } |
|
2194 |
|
2195 /* |
|
2196 * Read the fields of the specified class from the input stream and set |
|
2197 * the values of the fields in the specified object. If the specified |
|
2198 * object is null, just consume the fields without setting any values. If |
|
2199 * any ObjectStreamField does not have a reflected Field, don't try to set |
|
2200 * that field in the object. |
|
2201 * |
|
2202 * REVISIT -- This code doesn't do what the comment says to when |
|
2203 * getField() is null! |
|
2204 */ |
|
2205 private void inputClassFields(Object o, Class cl, |
|
2206 ObjectStreamField[] fields, |
|
2207 com.sun.org.omg.SendingContext.CodeBase sender) |
|
2208 throws InvalidClassException, StreamCorruptedException, |
|
2209 ClassNotFoundException, IOException |
|
2210 { |
|
2211 |
|
2212 int primFields = fields.length - currentClassDesc.objFields; |
|
2213 |
|
2214 if (o != null) { |
|
2215 for (int i = 0; i < primFields; ++i) { |
|
2216 if (fields[i].getField() == null) |
|
2217 continue; |
|
2218 |
|
2219 inputPrimitiveField(o, cl, fields[i]); |
|
2220 } |
|
2221 } |
|
2222 |
|
2223 /* Read and set object fields from the input stream. */ |
|
2224 if (currentClassDesc.objFields > 0) { |
|
2225 for (int i = primFields; i < fields.length; i++) { |
|
2226 Object objectValue = null; |
|
2227 |
|
2228 try { |
|
2229 objectValue = inputObjectField(fields[i]); |
|
2230 } catch(IndirectionException cdrie) { |
|
2231 // The CDR stream had never seen the given offset before, |
|
2232 // so check the recursion manager (it will throw an |
|
2233 // IOException if it doesn't have a reference, either). |
|
2234 objectValue = activeRecursionMgr.getObject(cdrie.offset); |
|
2235 } |
|
2236 |
|
2237 if ((o == null) || (fields[i].getField() == null)) { |
|
2238 continue; |
|
2239 } |
|
2240 |
|
2241 try { |
|
2242 bridge.putObject( o, fields[i].getFieldID(), objectValue ) ; |
|
2243 // reflective code: fields[i].getField().set( o, objectValue ) ; |
|
2244 } catch (IllegalArgumentException e) { |
|
2245 ClassCastException exc = new ClassCastException("Assigning instance of class " + |
|
2246 objectValue.getClass().getName() + |
|
2247 " to field " + |
|
2248 currentClassDesc.getName() + |
|
2249 '#' + |
|
2250 fields[i].getField().getName()); |
|
2251 exc.initCause( e ) ; |
|
2252 throw exc ; |
|
2253 } |
|
2254 } // end : for loop |
|
2255 } |
|
2256 } |
|
2257 |
|
2258 /* |
|
2259 * Read the fields of the specified class from the input stream and set |
|
2260 * the values of the fields in the specified object. If the specified |
|
2261 * object is null, just consume the fields without setting any values. If |
|
2262 * any ObjectStreamField does not have a reflected Field, don't try to set |
|
2263 * that field in the object. |
|
2264 */ |
|
2265 private void inputClassFields(Object o, Class cl, |
|
2266 ObjectStreamClass osc, |
|
2267 ValueMember[] fields, |
|
2268 com.sun.org.omg.SendingContext.CodeBase sender) |
|
2269 throws InvalidClassException, StreamCorruptedException, |
|
2270 ClassNotFoundException, IOException |
|
2271 { |
|
2272 try{ |
|
2273 for (int i = 0; i < fields.length; ++i) { |
|
2274 try { |
|
2275 switch (fields[i].type.kind().value()) { |
|
2276 case TCKind._tk_octet: |
|
2277 byte byteValue = orbStream.read_octet(); |
|
2278 if ((o != null) && osc.hasField(fields[i])) |
|
2279 setByteField(o, cl, fields[i].name, byteValue); |
|
2280 break; |
|
2281 case TCKind._tk_boolean: |
|
2282 boolean booleanValue = orbStream.read_boolean(); |
|
2283 if ((o != null) && osc.hasField(fields[i])) |
|
2284 setBooleanField(o, cl, fields[i].name, booleanValue); |
|
2285 break; |
|
2286 case TCKind._tk_char: |
|
2287 // Backwards compatibility. Older Sun ORBs sent |
|
2288 // _tk_char even though they read and wrote wchars |
|
2289 // correctly. |
|
2290 // |
|
2291 // Fall through to the _tk_wchar case. |
|
2292 case TCKind._tk_wchar: |
|
2293 char charValue = orbStream.read_wchar(); |
|
2294 if ((o != null) && osc.hasField(fields[i])) |
|
2295 setCharField(o, cl, fields[i].name, charValue); |
|
2296 break; |
|
2297 case TCKind._tk_short: |
|
2298 short shortValue = orbStream.read_short(); |
|
2299 if ((o != null) && osc.hasField(fields[i])) |
|
2300 setShortField(o, cl, fields[i].name, shortValue); |
|
2301 break; |
|
2302 case TCKind._tk_long: |
|
2303 int intValue = orbStream.read_long(); |
|
2304 if ((o != null) && osc.hasField(fields[i])) |
|
2305 setIntField(o, cl, fields[i].name, intValue); |
|
2306 break; |
|
2307 case TCKind._tk_longlong: |
|
2308 long longValue = orbStream.read_longlong(); |
|
2309 if ((o != null) && osc.hasField(fields[i])) |
|
2310 setLongField(o, cl, fields[i].name, longValue); |
|
2311 break; |
|
2312 case TCKind._tk_float: |
|
2313 float floatValue = orbStream.read_float(); |
|
2314 if ((o != null) && osc.hasField(fields[i])) |
|
2315 setFloatField(o, cl, fields[i].name, floatValue); |
|
2316 break; |
|
2317 case TCKind._tk_double: |
|
2318 double doubleValue = orbStream.read_double(); |
|
2319 if ((o != null) && osc.hasField(fields[i])) |
|
2320 setDoubleField(o, cl, fields[i].name, doubleValue); |
|
2321 break; |
|
2322 case TCKind._tk_value: |
|
2323 case TCKind._tk_objref: |
|
2324 case TCKind._tk_value_box: |
|
2325 Object objectValue = null; |
|
2326 try { |
|
2327 objectValue = inputObjectField(fields[i], sender); |
|
2328 } catch (IndirectionException cdrie) { |
|
2329 // The CDR stream had never seen the given offset before, |
|
2330 // so check the recursion manager (it will throw an |
|
2331 // IOException if it doesn't have a reference, either). |
|
2332 objectValue = activeRecursionMgr.getObject(cdrie.offset); |
|
2333 } |
|
2334 |
|
2335 if (o == null) |
|
2336 continue; |
|
2337 try { |
|
2338 if (osc.hasField(fields[i])){ |
|
2339 setObjectField(o, |
|
2340 cl, |
|
2341 fields[i].name, |
|
2342 objectValue); |
|
2343 } else { |
|
2344 // REVISIT. Convert to a log message. |
|
2345 // This is a normal case when fields have |
|
2346 // been added as part of evolution, but |
|
2347 // silently skipping can make it hard to |
|
2348 // debug if there's an error |
|
2349 // System.out.println("**** warning, not setting field: " |
|
2350 // + fields[i].name |
|
2351 // + " since not on class " |
|
2352 // + osc.getName()); |
|
2353 |
|
2354 } |
|
2355 } catch (IllegalArgumentException e) { |
|
2356 // XXX I18N, logging needed. |
|
2357 ClassCastException cce = new ClassCastException("Assigning instance of class " + |
|
2358 objectValue.getClass().getName() + " to field " + fields[i].name); |
|
2359 cce.initCause(e) ; |
|
2360 throw cce ; |
|
2361 } |
|
2362 break; |
|
2363 default: |
|
2364 // XXX I18N, logging needed. |
|
2365 throw new StreamCorruptedException("Unknown kind: " |
|
2366 + fields[i].type.kind().value()); |
|
2367 } |
|
2368 } catch (IllegalArgumentException e) { |
|
2369 /* This case should never happen. If the field types |
|
2370 are not the same, InvalidClassException is raised when |
|
2371 matching the local class to the serialized ObjectStreamClass. */ |
|
2372 // XXX I18N, logging needed. |
|
2373 ClassCastException cce = new ClassCastException("Assigning instance of class " + fields[i].id + |
|
2374 " to field " + currentClassDesc.getName() + '#' + fields[i].name); |
|
2375 cce.initCause( e ) ; |
|
2376 throw cce ; |
|
2377 } |
|
2378 } |
|
2379 } catch(Throwable t){ |
|
2380 // XXX I18N, logging needed. |
|
2381 StreamCorruptedException sce = new StreamCorruptedException(t.getMessage()); |
|
2382 sce.initCause(t) ; |
|
2383 throw sce ; |
|
2384 } |
|
2385 } |
|
2386 |
|
2387 private void skipCustomUsingFVD(ValueMember[] fields, |
|
2388 com.sun.org.omg.SendingContext.CodeBase sender) |
|
2389 throws InvalidClassException, StreamCorruptedException, |
|
2390 ClassNotFoundException, IOException |
|
2391 { |
|
2392 readFormatVersion(); |
|
2393 boolean calledDefaultWriteObject = readBoolean(); |
|
2394 |
|
2395 if (calledDefaultWriteObject) |
|
2396 throwAwayData(fields, sender); |
|
2397 |
|
2398 if (getStreamFormatVersion() == 2) { |
|
2399 |
|
2400 ((ValueInputStream)getOrbStream()).start_value(); |
|
2401 ((ValueInputStream)getOrbStream()).end_value(); |
|
2402 } |
|
2403 } |
|
2404 |
|
2405 /* |
|
2406 * Read the fields of the specified class from the input stream throw data away. |
|
2407 * This must handle same switch logic as above. |
|
2408 */ |
|
2409 private void throwAwayData(ValueMember[] fields, |
|
2410 com.sun.org.omg.SendingContext.CodeBase sender) |
|
2411 throws InvalidClassException, StreamCorruptedException, |
|
2412 ClassNotFoundException, IOException |
|
2413 { |
|
2414 for (int i = 0; i < fields.length; ++i) { |
|
2415 |
|
2416 try { |
|
2417 |
|
2418 switch (fields[i].type.kind().value()) { |
|
2419 case TCKind._tk_octet: |
|
2420 orbStream.read_octet(); |
|
2421 break; |
|
2422 case TCKind._tk_boolean: |
|
2423 orbStream.read_boolean(); |
|
2424 break; |
|
2425 case TCKind._tk_char: |
|
2426 // Backwards compatibility. Older Sun ORBs sent |
|
2427 // _tk_char even though they read and wrote wchars |
|
2428 // correctly. |
|
2429 // |
|
2430 // Fall through to the _tk_wchar case. |
|
2431 case TCKind._tk_wchar: |
|
2432 orbStream.read_wchar(); |
|
2433 break; |
|
2434 case TCKind._tk_short: |
|
2435 orbStream.read_short(); |
|
2436 break; |
|
2437 case TCKind._tk_long: |
|
2438 orbStream.read_long(); |
|
2439 break; |
|
2440 case TCKind._tk_longlong: |
|
2441 orbStream.read_longlong(); |
|
2442 break; |
|
2443 case TCKind._tk_float: |
|
2444 orbStream.read_float(); |
|
2445 break; |
|
2446 case TCKind._tk_double: |
|
2447 orbStream.read_double(); |
|
2448 break; |
|
2449 case TCKind._tk_value: |
|
2450 case TCKind._tk_objref: |
|
2451 case TCKind._tk_value_box: |
|
2452 Class type = null; |
|
2453 String id = fields[i].id; |
|
2454 |
|
2455 try { |
|
2456 type = vhandler.getClassFromType(id); |
|
2457 } |
|
2458 catch(ClassNotFoundException cnfe){ |
|
2459 // Make sure type = null |
|
2460 type = null; |
|
2461 } |
|
2462 String signature = null; |
|
2463 if (type != null) |
|
2464 signature = ValueUtility.getSignature(fields[i]); |
|
2465 |
|
2466 // Read value |
|
2467 try { |
|
2468 if ((signature != null) && ( signature.equals("Ljava/lang/Object;") || |
|
2469 signature.equals("Ljava/io/Serializable;") || |
|
2470 signature.equals("Ljava/io/Externalizable;")) ) { |
|
2471 javax.rmi.CORBA.Util.readAny(orbStream); |
|
2472 } |
|
2473 else { |
|
2474 // Decide what method call to make based on the type. |
|
2475 // |
|
2476 // NOTE : Since FullValueDescription does not allow us |
|
2477 // to ask whether something is an interface we do not |
|
2478 // have the ability to optimize this check. |
|
2479 |
|
2480 int callType = ValueHandlerImpl.kValueType; |
|
2481 |
|
2482 if (!vhandler.isSequence(id)) { |
|
2483 FullValueDescription fieldFVD = sender.meta(fields[i].id); |
|
2484 if (kRemoteTypeCode == fields[i].type) { |
|
2485 |
|
2486 // RMI Object reference... |
|
2487 callType = ValueHandlerImpl.kRemoteType; |
|
2488 } else if (fieldFVD.is_abstract) { |
|
2489 // RMI Abstract Object reference... |
|
2490 |
|
2491 callType = ValueHandlerImpl.kAbstractType; |
|
2492 } |
|
2493 } |
|
2494 |
|
2495 // Now that we have used the FVD of the field to determine the proper course |
|
2496 // of action, it is ok to use the type (Class) from this point forward since |
|
2497 // the rep. id for this read will also follow on the wire. |
|
2498 |
|
2499 switch (callType) { |
|
2500 case ValueHandlerImpl.kRemoteType: |
|
2501 orbStream.read_Object(); |
|
2502 break; |
|
2503 case ValueHandlerImpl.kAbstractType: |
|
2504 orbStream.read_abstract_interface(); |
|
2505 break; |
|
2506 case ValueHandlerImpl.kValueType: |
|
2507 if (type != null) { |
|
2508 orbStream.read_value(type); |
|
2509 } else { |
|
2510 orbStream.read_value(); |
|
2511 } |
|
2512 break; |
|
2513 default: |
|
2514 // XXX I18N, logging needed. |
|
2515 throw new StreamCorruptedException("Unknown callType: " |
|
2516 + callType); |
|
2517 } |
|
2518 } |
|
2519 |
|
2520 } |
|
2521 catch(IndirectionException cdrie) { |
|
2522 // Since we are throwing this away, don't bother handling recursion. |
|
2523 continue; |
|
2524 } |
|
2525 |
|
2526 break; |
|
2527 default: |
|
2528 // XXX I18N, logging needed. |
|
2529 throw new StreamCorruptedException("Unknown kind: " |
|
2530 + fields[i].type.kind().value()); |
|
2531 |
|
2532 } |
|
2533 } catch (IllegalArgumentException e) { |
|
2534 /* This case should never happen. If the field types |
|
2535 are not the same, InvalidClassException is raised when |
|
2536 matching the local class to the serialized ObjectStreamClass. */ |
|
2537 // XXX I18N, logging needed. |
|
2538 ClassCastException cce = new ClassCastException("Assigning instance of class " + |
|
2539 fields[i].id + " to field " + currentClassDesc.getName() + |
|
2540 '#' + fields[i].name); |
|
2541 cce.initCause(e) ; |
|
2542 throw cce ; |
|
2543 } |
|
2544 } |
|
2545 |
|
2546 } |
|
2547 |
|
2548 private static void setObjectField(Object o, Class c, String fieldName, Object v) |
|
2549 { |
|
2550 try { |
|
2551 Field fld = c.getDeclaredField( fieldName ) ; |
|
2552 long key = bridge.objectFieldOffset( fld ) ; |
|
2553 bridge.putObject( o, key, v ) ; |
|
2554 } catch (Exception e) { |
|
2555 throw utilWrapper.errorSetObjectField( e, fieldName, |
|
2556 ObjectUtility.compactObjectToString( o ), |
|
2557 ObjectUtility.compactObjectToString( v )) ; |
|
2558 } |
|
2559 } |
|
2560 |
|
2561 private static void setBooleanField(Object o, Class c, String fieldName, boolean v) |
|
2562 { |
|
2563 try { |
|
2564 Field fld = c.getDeclaredField( fieldName ) ; |
|
2565 long key = bridge.objectFieldOffset( fld ) ; |
|
2566 bridge.putBoolean( o, key, v ) ; |
|
2567 } catch (Exception e) { |
|
2568 throw utilWrapper.errorSetBooleanField( e, fieldName, |
|
2569 ObjectUtility.compactObjectToString( o ), |
|
2570 new Boolean(v) ) ; |
|
2571 } |
|
2572 } |
|
2573 |
|
2574 private static void setByteField(Object o, Class c, String fieldName, byte v) |
|
2575 { |
|
2576 try { |
|
2577 Field fld = c.getDeclaredField( fieldName ) ; |
|
2578 long key = bridge.objectFieldOffset( fld ) ; |
|
2579 bridge.putByte( o, key, v ) ; |
|
2580 } catch (Exception e) { |
|
2581 throw utilWrapper.errorSetByteField( e, fieldName, |
|
2582 ObjectUtility.compactObjectToString( o ), |
|
2583 new Byte(v) ) ; |
|
2584 } |
|
2585 } |
|
2586 |
|
2587 private static void setCharField(Object o, Class c, String fieldName, char v) |
|
2588 { |
|
2589 try { |
|
2590 Field fld = c.getDeclaredField( fieldName ) ; |
|
2591 long key = bridge.objectFieldOffset( fld ) ; |
|
2592 bridge.putChar( o, key, v ) ; |
|
2593 } catch (Exception e) { |
|
2594 throw utilWrapper.errorSetCharField( e, fieldName, |
|
2595 ObjectUtility.compactObjectToString( o ), |
|
2596 new Character(v) ) ; |
|
2597 } |
|
2598 } |
|
2599 |
|
2600 private static void setShortField(Object o, Class c, String fieldName, short v) |
|
2601 { |
|
2602 try { |
|
2603 Field fld = c.getDeclaredField( fieldName ) ; |
|
2604 long key = bridge.objectFieldOffset( fld ) ; |
|
2605 bridge.putShort( o, key, v ) ; |
|
2606 } catch (Exception e) { |
|
2607 throw utilWrapper.errorSetShortField( e, fieldName, |
|
2608 ObjectUtility.compactObjectToString( o ), |
|
2609 new Short(v) ) ; |
|
2610 } |
|
2611 } |
|
2612 |
|
2613 private static void setIntField(Object o, Class c, String fieldName, int v) |
|
2614 { |
|
2615 try { |
|
2616 Field fld = c.getDeclaredField( fieldName ) ; |
|
2617 long key = bridge.objectFieldOffset( fld ) ; |
|
2618 bridge.putInt( o, key, v ) ; |
|
2619 } catch (Exception e) { |
|
2620 throw utilWrapper.errorSetIntField( e, fieldName, |
|
2621 ObjectUtility.compactObjectToString( o ), |
|
2622 new Integer(v) ) ; |
|
2623 } |
|
2624 } |
|
2625 |
|
2626 private static void setLongField(Object o, Class c, String fieldName, long v) |
|
2627 { |
|
2628 try { |
|
2629 Field fld = c.getDeclaredField( fieldName ) ; |
|
2630 long key = bridge.objectFieldOffset( fld ) ; |
|
2631 bridge.putLong( o, key, v ) ; |
|
2632 } catch (Exception e) { |
|
2633 throw utilWrapper.errorSetLongField( e, fieldName, |
|
2634 ObjectUtility.compactObjectToString( o ), |
|
2635 new Long(v) ) ; |
|
2636 } |
|
2637 } |
|
2638 |
|
2639 private static void setFloatField(Object o, Class c, String fieldName, float v) |
|
2640 { |
|
2641 try { |
|
2642 Field fld = c.getDeclaredField( fieldName ) ; |
|
2643 long key = bridge.objectFieldOffset( fld ) ; |
|
2644 bridge.putFloat( o, key, v ) ; |
|
2645 } catch (Exception e) { |
|
2646 throw utilWrapper.errorSetFloatField( e, fieldName, |
|
2647 ObjectUtility.compactObjectToString( o ), |
|
2648 new Float(v) ) ; |
|
2649 } |
|
2650 } |
|
2651 |
|
2652 private static void setDoubleField(Object o, Class c, String fieldName, double v) |
|
2653 { |
|
2654 try { |
|
2655 Field fld = c.getDeclaredField( fieldName ) ; |
|
2656 long key = bridge.objectFieldOffset( fld ) ; |
|
2657 bridge.putDouble( o, key, v ) ; |
|
2658 } catch (Exception e) { |
|
2659 throw utilWrapper.errorSetDoubleField( e, fieldName, |
|
2660 ObjectUtility.compactObjectToString( o ), |
|
2661 new Double(v) ) ; |
|
2662 } |
|
2663 } |
|
2664 |
|
2665 /** |
|
2666 * This class maintains a map of stream position to |
|
2667 * an Object currently being deserialized. It is used |
|
2668 * to handle the cases where the are indirections to |
|
2669 * an object on the recursion stack. The CDR level |
|
2670 * handles indirections to objects previously seen |
|
2671 * (and completely deserialized) in the stream. |
|
2672 */ |
|
2673 static class ActiveRecursionManager |
|
2674 { |
|
2675 private Map offsetToObjectMap; |
|
2676 |
|
2677 public ActiveRecursionManager() { |
|
2678 // A hash map is unsynchronized and allows |
|
2679 // null values |
|
2680 offsetToObjectMap = new HashMap(); |
|
2681 } |
|
2682 |
|
2683 // Called right after allocating a new object. |
|
2684 // Offset is the starting position in the stream |
|
2685 // of the object. |
|
2686 public void addObject(int offset, Object value) { |
|
2687 offsetToObjectMap.put(new Integer(offset), value); |
|
2688 } |
|
2689 |
|
2690 // If the given starting position doesn't refer |
|
2691 // to the beginning of an object currently being |
|
2692 // deserialized, this throws an IOException. |
|
2693 // Otherwise, it returns a reference to the |
|
2694 // object. |
|
2695 public Object getObject(int offset) throws IOException { |
|
2696 Integer position = new Integer(offset); |
|
2697 |
|
2698 if (!offsetToObjectMap.containsKey(position)) |
|
2699 // XXX I18N, logging needed. |
|
2700 throw new IOException("Invalid indirection to offset " |
|
2701 + offset); |
|
2702 |
|
2703 return offsetToObjectMap.get(position); |
|
2704 } |
|
2705 |
|
2706 // Called when an object has been completely |
|
2707 // deserialized, so it should no longer be in |
|
2708 // this mapping. The CDR level can handle |
|
2709 // further indirections. |
|
2710 public void removeObject(int offset) { |
|
2711 offsetToObjectMap.remove(new Integer(offset)); |
|
2712 } |
|
2713 |
|
2714 // If the given offset doesn't map to an Object, |
|
2715 // then it isn't an indirection to an object |
|
2716 // currently being deserialized. |
|
2717 public boolean containsObject(int offset) { |
|
2718 return offsetToObjectMap.containsKey(new Integer(offset)); |
|
2719 } |
|
2720 } |
|
2721 } |