1:
37:
38:
39: package ;
40:
41: import ;
42: import ;
43: import ;
44: import ;
45: import ;
46: import ;
47: import ;
48:
49: import ;
50: import ;
51: import ;
52: import ;
53: import ;
54: import ;
55: import ;
56: import ;
57: import ;
58: import ;
59: import ;
60: import ;
61: import ;
62:
63: import ;
64: import ;
65: import ;
66: import ;
67: import ;
68: import ;
69: import ;
70: import ;
71: import ;
72: import ;
73: import ;
74: import ;
75: import ;
76: import ;
77: import ;
78: import ;
79: import ;
80:
81: import ;
82: import ;
83: import ;
84: import ;
85:
86:
91: public class RmiUtilities
92: {
93:
96: public static byte VERSION = 1;
97:
98:
101: static final int NON_WRITABLE = Modifier.STATIC | Modifier.TRANSIENT;
102:
103:
106: public static final String RMI_STRING_ID = StringValueHelper.id();
107:
108:
111: public static final String RMI_CLASS_ID = "RMI:javax.rmi.CORBA.ClassDesc:2BABDA04587ADCCC:CFBF02CF5294176B";
112:
113:
116: public static final String RMI_STRING_ARRAY_ID = "RMI:[Ljava.lang.String;:071DA8BE7F971128:A0F0A4387A3BB342";
117:
118:
121: static WStringValueHelper wStringValueHelper = new WStringValueHelper();
122:
123:
127: WeakHashMap io_format = new WeakHashMap();
128:
129:
132: static final Object STANDARD = new Object();
133:
134:
138: static final Object CUSTOM_DWO = new Object();
139:
140:
144: static final Object CUSTOM_NO_DWO = new Object();
145:
146:
149: static final Class[] READ_OBJECT_ARGS = new Class[] { ObjectInputStream.class };
150:
151:
154: static final Class[] WRITE_OBJECT_ARGS = new Class[] { ObjectOutputStream.class };
155:
156:
160: static final int S_X = 16908034;
161:
162:
165: void writeFields(OutputStream an_output, Serializable object)
166: {
167: org.omg.CORBA_2_3.portable.OutputStream output = (org.omg.CORBA_2_3.portable.OutputStream) an_output;
168: try
169: {
170: Class o_class = object.getClass();
171: Field[] fields = getWritableFields(o_class);
172: Field f;
173:
174: Class fc;
175:
176: for (int i = 0; i < fields.length; i++)
177: {
178: f = fields[i];
179: fc = f.getType();
180: Object v = f.get(object);
181:
182: if (fc == String.class)
183: {
184: output.write_value((Serializable) v, wStringValueHelper);
185: }
186: else if (fc == int.class)
187: output.write_long(((Integer) v).intValue());
188: else if (fc == long.class)
189: output.write_longlong(((Number) v).longValue());
190: else if (fc == double.class)
191: output.write_double(((Number) v).doubleValue());
192: else if (fc == float.class)
193: output.write_float(((Number) v).floatValue());
194: else if (fc == boolean.class)
195: output.write_boolean(((Boolean) v).booleanValue());
196: else if (fc == short.class)
197: output.write_short(((Number) v).shortValue());
198: else if (fc == byte.class)
199: output.write_octet(((Number) v).byteValue());
200: else if (fc == char.class)
201: output.write_wchar(((Character) v).charValue());
202: else
203: {
204: if (!fc.isInterface() && Remote.class.isAssignableFrom(fc))
205: fc = getExportedInterface(fc);
206: writeMember(output, v, fc);
207: }
208: }
209: }
210: catch (Exception ex)
211: {
212: MARSHAL m = new MARSHAL("Cannot write " + object);
213: m.minor = Minor.ValueFields;
214: m.initCause(ex);
215: throw m;
216: }
217: }
218:
219:
222: void writeMember(org.omg.CORBA_2_3.portable.OutputStream output,
223: Object object, Class xClass)
224: {
225: if (output instanceof gnuValueStream)
226: {
227: gnuRuntime g = ((gnuValueStream) output).getRunTime();
228:
229:
230: if (g != null)
231: g.target = null;
232: }
233: if (Serializable.class.isAssignableFrom(xClass)
234: || Remote.class.isAssignableFrom(xClass))
235: {
236:
237: if (org.omg.CORBA.Object.class.isAssignableFrom(xClass)
238: || Remote.class.isAssignableFrom(xClass))
239: {
240: if (object == null)
241: output.write_Object(null);
242: else if (isTieRequired(object))
243: exportTie(output, object, xClass);
244: else
245: writeValue(output, (Serializable) object);
246: }
247: else
248: output.write_value((Serializable) object, xClass);
249: }
250: else
251: {
252: MARSHAL m = new MARSHAL(xClass + " is not Serializable");
253: m.minor = Minor.NonSerializable;
254: throw m;
255: }
256: }
257:
258:
262: public boolean isTieRequired(Object object)
263: {
264: return object instanceof Remote && !(object instanceof Stub);
265: }
266:
267:
271: Class getExportedInterface(Object object)
272: throws MARSHAL
273: {
274: Class fc = null;
275: Class[] interfaces = object.getClass().getInterfaces();
276: for (int i = 0; i < interfaces.length; i++)
277: {
278: if (!Remote.class.equals(interfaces[i]))
279: if (Remote.class.isAssignableFrom(interfaces[i]))
280: {
281: if (fc == null)
282: fc = interfaces[i];
283: else
284: {
285: MARSHAL m = new MARSHAL("Both " + fc + " and " + interfaces[i]
286: + " extends Remote");
287: m.minor = Minor.TargetConversion;
288: throw m;
289: }
290: }
291: }
292: if (fc == null)
293: {
294: MARSHAL m = new MARSHAL(object.getClass()
295: + " does not implement any interface, derived from Remote");
296: m.minor = Minor.TargetConversion;
297: throw m;
298: }
299: return fc;
300: }
301:
302:
309: public static long getHashCode(Class c)
310: {
311: Class of = c.isArray() ? c.getComponentType() : null;
312: if (c.isArray()
313: && ((!Serializable.class.isAssignableFrom(of) || of.isPrimitive() || Remote.class.isAssignableFrom(of))))
314: return 0;
315: if (!Serializable.class.isAssignableFrom(c))
316: return 0;
317: try
318: {
319: ByteArrayOutputStream bout = new ByteArrayOutputStream();
320: DataOutputStream out = new DataOutputStream(bout);
321:
322: Class superClass = c.getSuperclass();
323: if (superClass != null)
324: out.writeLong(getHashCode(superClass));
325:
326: int writeObjectPresentCode;
327: try
328: {
329: c.getDeclaredMethod("writeObject",
330: new Class[] { ObjectOutputStream.class });
331: writeObjectPresentCode = 2;
332: }
333: catch (NoSuchMethodException e)
334: {
335: writeObjectPresentCode = 1;
336: }
337: out.writeInt(writeObjectPresentCode);
338:
339: Field[] fields = c.getDeclaredFields();
340:
341: Arrays.sort(fields, new Comparator()
342: {
343: public int compare(Object a, Object b)
344: {
345: Field fa = (Field) a;
346: Field fb = (Field) b;
347: return fa.getName().compareTo(fb.getName());
348: }
349: });
350:
351: Field f;
352: for (int i = 0; i < fields.length; i++)
353: {
354: f = fields[i];
355: if ((f.getModifiers() & NON_WRITABLE) == 0)
356: {
357: out.writeUTF(f.getName());
358: out.writeUTF(getDescriptor(f.getType()));
359: }
360: }
361:
362: out.flush();
363: out.close();
364: MessageDigest shaDigest;
365: try
366: {
367: shaDigest = MessageDigest.getInstance("SHA");
368: }
369: catch (Exception ex)
370: {
371: throw new InternalError("SHA digesting algorithm is not available");
372: }
373:
374:
375:
376: byte[] sha = shaDigest.digest(bout.toByteArray());
377:
378: long hash = 0;
379: for (int i = 0; i < Math.min(8, sha.length); i++)
380: {
381: hash += (long) (sha[i] & 255) << (i * 8);
382: }
383: return hash;
384: }
385: catch (IOException ioex)
386: {
387: throw new Unexpected(ioex);
388: }
389: }
390:
391:
394: public static String toHex(long l)
395: {
396: StringBuffer b = new StringBuffer();
397: b.append(Long.toHexString(l).toUpperCase());
398: while (b.length() < 16)
399: b.insert(0, '0');
400: return b.toString();
401: }
402:
403:
406: static String getDescriptor(Class type)
407: {
408: if (type.equals(boolean.class))
409: return "Z";
410: if (type.equals(byte.class))
411: return "B";
412: if (type.equals(short.class))
413: return "S";
414: if (type.equals(char.class))
415: return "C";
416: if (type.equals(int.class))
417: return "I";
418: if (type.equals(long.class))
419: return "J";
420: if (type.equals(float.class))
421: return "F";
422: if (type.equals(double.class))
423: return "D";
424: if (type.equals(void.class))
425: return "V";
426: else if (type.isArray())
427: {
428: StringBuffer l = new StringBuffer("[");
429: Class component = type.getComponentType();
430:
431: while (component.isArray())
432: {
433: l.append('[');
434: component = component.getComponentType();
435: }
436:
437: l.append('L');
438: l.append(component.getName().replace('.', '/'));
439: l.append(';');
440: return l.toString();
441: }
442: else
443: return "L" + type.getName().replace('.', '/') + ';';
444: }
445:
446: public static Field[] getWritableFields(Class c)
447: {
448: TreeSet set = new TreeSet(new Comparator()
449: {
450: public int compare(Object a, Object b)
451: {
452: return ((Field) a).getName().compareTo(((Field) b).getName());
453: }
454: });
455:
456: while (!c.equals(Object.class))
457: {
458: Field[] f = c.getDeclaredFields();
459: for (int i = 0; i < f.length; i++)
460: {
461: if ((f[i].getModifiers() & NON_WRITABLE) == 0)
462: {
463: f[i].setAccessible(true);
464: set.add(f[i]);
465: }
466: }
467: c = c.getSuperclass();
468: }
469:
470: Field[] r = new Field[set.size()];
471: int p = 0;
472: Iterator it = set.iterator();
473: while (it.hasNext())
474: {
475: r[p++] = (Field) it.next();
476: }
477: return r;
478: }
479:
480:
486: void exportTie(org.omg.CORBA_2_3.portable.OutputStream output,
487: Object implementation, Class interfaceClass)
488: {
489: try
490: {
491:
492:
493: Tie t = Util.getTie((Remote) implementation);
494: if (t instanceof Servant)
495: {
496: POA rootPoa = POAHelper.narrow(output.orb().resolve_initial_references(
497: "RootPOA"));
498: org.omg.CORBA.Object co = rootPoa.servant_to_reference((Servant) t);
499: Stub stub = (Stub) PortableRemoteObject.narrow(co, interfaceClass);
500: writeRemoteObject(output, stub);
501:
502: if (rootPoa.the_POAManager().get_state().value() == State._HOLDING)
503: rootPoa.the_POAManager().activate();
504: }
505: else if (t instanceof org.omg.CORBA.Object)
506: {
507: org.omg.CORBA.Object co = (org.omg.CORBA.Object) t;
508: output.orb().connect(co);
509:
510: Stub stub = (Stub) PortableRemoteObject.narrow(co, interfaceClass);
511: writeRemoteObject(output, stub);
512: }
513: }
514: catch (Exception ex)
515: {
516: MARSHAL m = new MARSHAL("Unable to export " + implementation);
517: m.minor = Minor.TargetConversion;
518: m.initCause(ex);
519: throw m;
520: }
521: }
522:
523:
526: void ensureOrbRunning(org.omg.CORBA_2_3.portable.OutputStream output)
527: {
528:
529: if (output.orb() instanceof OrbFunctional)
530: {
531: ((OrbFunctional) output.orb()).ensureRunning();
532: }
533: }
534:
535:
544: public void writeRemoteObject(OutputStream an_output, Object object)
545: {
546: org.omg.CORBA_2_3.portable.OutputStream output = (org.omg.CORBA_2_3.portable.OutputStream) an_output;
547:
548: if (isTieRequired(object))
549: {
550:
551:
552: Class fc = getExportedInterface(object);
553: exportTie(output, object, fc);
554: }
555: else if (object instanceof org.omg.CORBA.Object)
556: {
557: ensureOrbRunning(output);
558: an_output.write_Object((org.omg.CORBA.Object) object);
559: }
560: else if (object != null && object instanceof Serializable)
561: writeFields(an_output, (Serializable) object);
562: }
563:
564:
573: public void writeValue(OutputStream an_output, Serializable object)
574: {
575: org.omg.CORBA_2_3.portable.OutputStream output = (org.omg.CORBA_2_3.portable.OutputStream) an_output;
576:
577: if (isTieRequired(object))
578: {
579:
580:
581: Class fc = getExportedInterface(object);
582: exportTie(output, object, fc);
583: }
584: else if (object instanceof org.omg.CORBA.Object)
585: {
586: ensureOrbRunning(output);
587: an_output.write_Object((org.omg.CORBA.Object) object);
588: }
589: else if (object instanceof Externalizable)
590: {
591: try
592: {
593: ObjectOutputStream stream = new CorbaOutput(output, object,
594: this);
595: stream.write(VERSION);
596: ((Externalizable) object).writeExternal(stream);
597: }
598: catch (Exception ex)
599: {
600: MARSHAL m = new MARSHAL("writeExternal failed");
601: m.minor = Minor.Value;
602: m.initCause(ex);
603: throw m;
604: }
605: }
606: else if (object instanceof Serializable)
607: {
608: Object mode = null;
609: synchronized (io_format)
610: {
611: mode = io_format.get(object.getClass());
612: if (mode == STANDARD)
613: {
614: writeFields(an_output, (Serializable) object);
615: return;
616: }
617: }
618: try
619: {
620: Method m = object.getClass().getDeclaredMethod("writeObject",
621: WRITE_OBJECT_ARGS);
622: m.setAccessible(true);
623:
624: try
625: {
626: ObjectOutputStream stream = new CorbaOutput(output,
627: object, this);
628:
629:
630: stream.write(VERSION);
631:
632: if (mode == CUSTOM_DWO)
633:
634:
635: stream.write(1);
636: else if (mode == CUSTOM_NO_DWO)
637:
638: stream.write(0);
639: else
640: {
641:
642: DefaultWriteObjectTester tester = new DefaultWriteObjectTester(object);
643: m.invoke(object, new Object[] { tester });
644:
645: synchronized (io_format)
646: {
647: io_format.put(object.getClass(),
648: tester.dwo_called ? CUSTOM_DWO : CUSTOM_NO_DWO);
649: stream.write(tester.dwo_called ? 1 : 0);
650: }
651: }
652:
653: m.invoke(object, new Object[] { stream });
654: stream.flush();
655: }
656: catch (Exception ex)
657: {
658: MARSHAL mx = new MARSHAL(object.getClass().getName()
659: + ".writeObject failed");
660: mx.initCause(ex);
661: throw mx;
662: }
663: }
664: catch (NoSuchMethodException e)
665: {
666:
667: writeFields(an_output, (Serializable) object);
668: synchronized (io_format)
669: {
670: io_format.put(object.getClass(), STANDARD);
671: }
672: }
673: }
674: }
675:
676:
693:
697: public Serializable readValue(InputStream in, int offset, Class clz,
698: String repositoryID, RunTime sender)
699: {
700: if (in instanceof HeadlessInput)
701: ((HeadlessInput) in).subsequentCalls = true;
702:
703: gnuRuntime g;
704: Serializable object = null;
705:
706: try
707: {
708: g = (gnuRuntime) sender;
709: object = g.target;
710: }
711: catch (ClassCastException e)
712: {
713:
714: g = null;
715: }
716:
717: org.omg.CORBA_2_3.portable.InputStream input = (org.omg.CORBA_2_3.portable.InputStream) in;
718:
719: if (Remote.class.isAssignableFrom(clz)
720: || ValueBase.class.isAssignableFrom(clz))
721: {
722:
723: if (clz.isInterface())
724: try
725: {
726: clz = Util.loadClass(
727: PortableRemoteObjectDelegateImpl.getStubClassName(clz.getName()),
728: null, clz.getClassLoader());
729: }
730: catch (ClassNotFoundException e)
731: {
732: MARSHAL m = new MARSHAL("Cannot get stub from interface "
733: + clz.getClass().getName());
734: m.minor = Minor.TargetConversion;
735: m.initCause(e);
736: throw m;
737: }
738:
739:
740: if (ObjectImpl.class.isAssignableFrom(clz))
741: {
742:
743: Object ro = input.read_Object();
744:
745: ObjectImpl obj = (ObjectImpl) ro;
746: if (obj == null)
747: return null;
748:
749: Delegate delegate = obj._get_delegate();
750: object = instantiate(offset, clz, g);
751: ((ObjectImpl) object)._set_delegate(delegate);
752: }
753:
754: }
755: else if (org.omg.CORBA.Object.class.isAssignableFrom(clz))
756: object = (Serializable) input.read_Object();
757:
758: if (object == null)
759: object = instantiate(offset, clz, g);
760:
761:
762:
763:
764:
765: if (object instanceof ObjectImpl)
766: return object;
767:
768: if (object instanceof Externalizable)
769: {
770: try
771: {
772: CorbaInput stream = new CorbaInput(input, object, this,
773: offset, repositoryID, g);
774:
775: byte version = stream.readByte();
776: if (version != 1)
777: throw new MARSHAL("Unsuported RMI-IIOP version " + version);
778:
779: ((Externalizable) object).readExternal(stream);
780: }
781: catch (Exception ex)
782: {
783: MARSHAL m = new MARSHAL("readExternal failed");
784: m.initCause(ex);
785: throw m;
786: }
787: }
788: else
789: {
790: Object mode = null;
791: synchronized (io_format)
792: {
793: mode = io_format.get(object.getClass());
794: }
795:
796: if (mode == STANDARD)
797: {
798: readFields(offset, repositoryID, object, input, g);
799: }
800: else
801: {
802: try
803: {
804: Method m = object.getClass().getDeclaredMethod("readObject",
805: READ_OBJECT_ARGS);
806: try
807: {
808: m.setAccessible(true);
809:
810: CorbaInput stream = new CorbaInput(input,
811: object, this, offset, repositoryID, g);
812:
813: byte version = stream.readByte();
814: if (version != 1)
815: throw new MARSHAL("Unsuported RMI-IIOP version "
816: + version);
817:
818:
819:
820:
821: boolean dwo = stream.readByte() != 0;
822:
823: m.invoke(object, new Object[] { stream });
824: synchronized (io_format)
825: {
826: io_format.put(object.getClass(), dwo ? CUSTOM_DWO
827: : CUSTOM_NO_DWO);
828: }
829: }
830: catch (Exception ex)
831: {
832: ex.printStackTrace();
833: MARSHAL mx = new MARSHAL(object.getClass().getName()
834: + ".readObject failed");
835: mx.initCause(ex);
836: throw mx;
837: }
838: }
839: catch (NoSuchMethodException e)
840: {
841:
842: synchronized (io_format)
843: {
844: io_format.put(object.getClass(), STANDARD);
845: readFields(offset, repositoryID, object, input, g);
846: }
847: }
848: }
849: }
850: return object;
851: }
852:
853:
856: Serializable instantiate(int offset, Class clz, gnuRuntime g)
857: throws MARSHAL
858: {
859: Serializable object;
860: try
861: {
862: object = (Serializable) Vio.instantiateAnyWay(clz);
863: g.objectWritten(object, offset);
864: }
865: catch (Exception e)
866: {
867: MARSHAL m = new MARSHAL("Unable to instantiate " + clz);
868: m.minor = Minor.Instantiation;
869: m.initCause(e);
870: throw m;
871: }
872: return object;
873: }
874:
875:
878: void readFields(int offset, String repositoryID, Serializable object,
879: org.omg.CORBA_2_3.portable.InputStream input, gnuRuntime r)
880: throws MARSHAL
881: {
882: Field f = null;
883: Class o_class = object.getClass();
884:
885: try
886: {
887:
888: Field[] fields = getWritableFields(o_class);
889:
890: Class fc;
891:
892: for (int i = 0; i < fields.length; i++)
893: {
894:
895: if (input instanceof HeadlessInput)
896: ((HeadlessInput) input).subsequentCalls = true;
897:
898: f = fields[i];
899: fc = f.getType();
900:
901: Object v;
902:
903: if (fc == String.class)
904: {
905: v = input.read_value(wStringValueHelper);
906: }
907: else if (fc == int.class)
908: v = new Integer(input.read_long());
909: else if (fc == long.class)
910: v = new Long(input.read_longlong());
911: else if (fc == double.class)
912: v = new Double(input.read_double());
913: else if (fc == float.class)
914: v = new Float(input.read_float());
915: else if (fc == boolean.class)
916: v = input.read_boolean() ? Boolean.TRUE : Boolean.FALSE;
917: else if (fc == short.class)
918: v = new Short(input.read_short());
919: else if (fc == byte.class)
920: v = new Byte(input.read_octet());
921: else if (fc == char.class)
922: v = new Character(input.read_char());
923: else if (org.omg.CORBA.Object.class.isAssignableFrom(fc)
924: || Remote.class.isAssignableFrom(fc))
925: {
926: v = readValue(input, offset, fc, null, r);
927: }
928: else
929: {
930: v = Vio.read(input, fc);
931: }
932:
933: f.set(object, v);
934: }
935: }
936: catch (Exception ex)
937: {
938: MARSHAL m = new MARSHAL("Cannot read " + o_class.getName() + " field "
939: + f);
940: m.initCause(ex);
941: m.minor = Minor.ValueFields;
942: throw m;
943: }
944: }
945:
946: }