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