1:
38:
39:
40: package ;
41:
42: import ;
43: import ;
44: import ;
45: import ;
46:
47: import ;
48: import ;
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:
70: public class ObjectStreamClass implements Serializable
71: {
72: static final ObjectStreamField[] INVALID_FIELDS = new ObjectStreamField[0];
73:
74:
89: public static ObjectStreamClass lookup(Class<?> cl)
90: {
91: if (cl == null)
92: return null;
93: if (! (Serializable.class).isAssignableFrom(cl))
94: return null;
95:
96: return lookupForClassObject(cl);
97: }
98:
99:
104: static ObjectStreamClass lookupForClassObject(Class cl)
105: {
106: if (cl == null)
107: return null;
108:
109: ObjectStreamClass osc = (ObjectStreamClass) classLookupTable.get(cl);
110:
111: if (osc != null)
112: return osc;
113: else
114: {
115: osc = new ObjectStreamClass(cl);
116: classLookupTable.put(cl, osc);
117: return osc;
118: }
119: }
120:
121:
127: public String getName()
128: {
129: return name;
130: }
131:
132:
141: public Class<?> forClass()
142: {
143: return clazz;
144: }
145:
146:
155: public long getSerialVersionUID()
156: {
157: return uid;
158: }
159:
160:
169: public ObjectStreamField[] getFields()
170: {
171: ObjectStreamField[] copy = new ObjectStreamField[ fields.length ];
172: System.arraycopy(fields, 0, copy, 0, fields.length);
173: return copy;
174: }
175:
176:
177:
178:
179: public ObjectStreamField getField (String name)
180: {
181: for (int i = 0; i < fields.length; i++)
182: if (fields[i].getName().equals(name))
183: return fields[i];
184: return null;
185: }
186:
187:
196: public String toString()
197: {
198: return "java.io.ObjectStreamClass< " + name + ", " + uid + " >";
199: }
200:
201:
202:
203:
204:
205:
206:
207:
208: boolean hasWriteMethod()
209: {
210: return (flags & ObjectStreamConstants.SC_WRITE_METHOD) != 0;
211: }
212:
213:
214:
215: boolean isSerializable()
216: {
217: return (flags & ObjectStreamConstants.SC_SERIALIZABLE) != 0;
218: }
219:
220:
221:
222:
223: boolean isExternalizable()
224: {
225: return (flags & ObjectStreamConstants.SC_EXTERNALIZABLE) != 0;
226: }
227:
228:
229:
230: boolean isEnum()
231: {
232: return (flags & ObjectStreamConstants.SC_ENUM) != 0;
233: }
234:
235:
236:
237:
238:
239: ObjectStreamClass getSuper()
240: {
241: return superClass;
242: }
243:
244:
257: ObjectStreamClass[] hierarchy()
258: {
259: ObjectStreamClass[] result = hierarchy;
260: if (result == null)
261: {
262: int d = 0;
263:
264: for(ObjectStreamClass osc = this; osc != null; osc = osc.getSuper())
265: d++;
266:
267: result = new ObjectStreamClass[d];
268:
269: for (ObjectStreamClass osc = this; osc != null; osc = osc.getSuper())
270: {
271: result[--d] = osc;
272: }
273:
274: hierarchy = result;
275: }
276: return result;
277: }
278:
279:
282: private ObjectStreamClass[] hierarchy = null;
283:
284:
285:
286:
287:
288: int getFlags()
289: {
290: return flags;
291: }
292:
293:
294: ObjectStreamClass(String name, long uid, byte flags,
295: ObjectStreamField[] fields)
296: {
297: this.name = name;
298: this.uid = uid;
299: this.flags = flags;
300: this.fields = fields;
301: }
302:
303:
314: void setClass(Class cl, ObjectStreamClass superClass) throws InvalidClassException
315: {hierarchy = null;
316: this.clazz = cl;
317:
318: cacheMethods();
319:
320: long class_uid = getClassUID(cl);
321: if (uid == 0)
322: uid = class_uid;
323: else
324: {
325:
326:
327: if (!cl.isArray() && uid != class_uid)
328: {
329: String msg = cl +
330: ": Local class not compatible: stream serialVersionUID="
331: + uid + ", local serialVersionUID=" + class_uid;
332: throw new InvalidClassException (msg);
333: }
334: }
335:
336: isProxyClass = clazz != null && Proxy.isProxyClass(clazz);
337: this.superClass = superClass;
338: calculateOffsets();
339:
340: try
341: {
342: ObjectStreamField[] exportedFields = getSerialPersistentFields (clazz);
343:
344: if (exportedFields == null)
345: return;
346:
347: ObjectStreamField[] newFieldList = new ObjectStreamField[exportedFields.length + fields.length];
348: int i, j, k;
349:
350:
354:
355: Arrays.sort(exportedFields);
356:
357: i = 0; j = 0; k = 0;
358: while (i < fields.length && j < exportedFields.length)
359: {
360: int comp = fields[i].compareTo(exportedFields[j]);
361:
362: if (comp < 0)
363: {
364: newFieldList[k] = fields[i];
365: fields[i].setPersistent(false);
366: fields[i].setToSet(false);
367: i++;
368: }
369: else if (comp > 0)
370: {
371:
374: newFieldList[k] = exportedFields[j];
375: newFieldList[k].setPersistent(true);
376: newFieldList[k].setToSet(false);
377: try
378: {
379: newFieldList[k].lookupField(clazz);
380: newFieldList[k].checkFieldType();
381: }
382: catch (NoSuchFieldException _)
383: {
384: }
385: j++;
386: }
387: else
388: {
389: try
390: {
391: exportedFields[j].lookupField(clazz);
392: exportedFields[j].checkFieldType();
393: }
394: catch (NoSuchFieldException _)
395: {
396: }
397:
398: if (!fields[i].getType().equals(exportedFields[j].getType()))
399: throw new InvalidClassException
400: ("serialPersistentFields must be compatible with" +
401: " imported fields (about " + fields[i].getName() + ")");
402: newFieldList[k] = fields[i];
403: fields[i].setPersistent(true);
404: i++;
405: j++;
406: }
407: k++;
408: }
409:
410: if (i < fields.length)
411: for (;i<fields.length;i++,k++)
412: {
413: fields[i].setPersistent(false);
414: fields[i].setToSet(false);
415: newFieldList[k] = fields[i];
416: }
417: else
418: if (j < exportedFields.length)
419: for (;j<exportedFields.length;j++,k++)
420: {
421: exportedFields[j].setPersistent(true);
422: exportedFields[j].setToSet(false);
423: newFieldList[k] = exportedFields[j];
424: }
425:
426: fields = new ObjectStreamField[k];
427: System.arraycopy(newFieldList, 0, fields, 0, k);
428: }
429: catch (NoSuchFieldException ignore)
430: {
431: return;
432: }
433: catch (IllegalAccessException ignore)
434: {
435: return;
436: }
437: }
438:
439: void setSuperclass (ObjectStreamClass osc)
440: {
441: superClass = osc;
442: hierarchy = null;
443: }
444:
445: void calculateOffsets()
446: {
447: int i;
448: ObjectStreamField field;
449: primFieldSize = 0;
450: int fcount = fields.length;
451: for (i = 0; i < fcount; ++ i)
452: {
453: field = fields[i];
454:
455: if (! field.isPrimitive())
456: break;
457:
458: field.setOffset(primFieldSize);
459: switch (field.getTypeCode())
460: {
461: case 'B':
462: case 'Z':
463: ++ primFieldSize;
464: break;
465: case 'C':
466: case 'S':
467: primFieldSize += 2;
468: break;
469: case 'I':
470: case 'F':
471: primFieldSize += 4;
472: break;
473: case 'D':
474: case 'J':
475: primFieldSize += 8;
476: break;
477: }
478: }
479:
480: for (objectFieldCount = 0; i < fcount; ++ i)
481: fields[i].setOffset(objectFieldCount++);
482: }
483:
484: private Method findMethod(Method[] methods, String name, Class[] params,
485: Class returnType, boolean mustBePrivate)
486: {
487: outer:
488: for (int i = 0; i < methods.length; i++)
489: {
490: final Method m = methods[i];
491: int mods = m.getModifiers();
492: if (Modifier.isStatic(mods)
493: || (mustBePrivate && !Modifier.isPrivate(mods)))
494: {
495: continue;
496: }
497:
498: if (m.getName().equals(name)
499: && m.getReturnType() == returnType)
500: {
501: Class[] mp = m.getParameterTypes();
502: if (mp.length == params.length)
503: {
504: for (int j = 0; j < mp.length; j++)
505: {
506: if (mp[j] != params[j])
507: {
508: continue outer;
509: }
510: }
511: AccessController.doPrivileged(new SetAccessibleAction(m));
512: return m;
513: }
514: }
515: }
516: return null;
517: }
518:
519: private static boolean inSamePackage(Class c1, Class c2)
520: {
521: String name1 = c1.getName();
522: String name2 = c2.getName();
523:
524: int id1 = name1.lastIndexOf('.');
525: int id2 = name2.lastIndexOf('.');
526:
527:
528: if (id1 == -1 || id2 == -1)
529: return id1 == id2;
530:
531: String package1 = name1.substring(0, id1);
532: String package2 = name2.substring(0, id2);
533:
534: return package1.equals(package2);
535: }
536:
537: final static Class[] noArgs = new Class[0];
538:
539: private static Method findAccessibleMethod(String name, Class from)
540: {
541: for (Class c = from; c != null; c = c.getSuperclass())
542: {
543: try
544: {
545: Method res = c.getDeclaredMethod(name, noArgs);
546: int mods = res.getModifiers();
547:
548: if (c == from
549: || Modifier.isProtected(mods)
550: || Modifier.isPublic(mods)
551: || (! Modifier.isPrivate(mods) && inSamePackage(c, from)))
552: {
553: AccessController.doPrivileged(new SetAccessibleAction(res));
554: return res;
555: }
556: }
557: catch (NoSuchMethodException e)
558: {
559: }
560: }
561:
562: return null;
563: }
564:
565:
576: private static boolean loadedByBootOrApplicationClassLoader(Class cl)
577: {
578: ClassLoader l = cl.getClassLoader();
579: return
580: ( l == null )
581: || (l == ClassLoader.getSystemClassLoader() );
582: }
583:
584: static Hashtable methodCache = new Hashtable();
585:
586: static final Class[] readObjectSignature = { ObjectInputStream.class };
587: static final Class[] writeObjectSignature = { ObjectOutputStream.class };
588:
589: private void cacheMethods()
590: {
591: Class cl = forClass();
592: Method[] cached = (Method[]) methodCache.get(cl);
593: if (cached == null)
594: {
595: cached = new Method[4];
596: Method[] methods = cl.getDeclaredMethods();
597:
598: cached[0] = findMethod(methods, "readObject",
599: readObjectSignature,
600: Void.TYPE, true);
601: cached[1] = findMethod(methods, "writeObject",
602: writeObjectSignature,
603: Void.TYPE, true);
604:
605:
606:
607: cached[2] = findAccessibleMethod("readResolve", cl);
608: cached[3] = findAccessibleMethod("writeReplace", cl);
609:
610:
614: if (loadedByBootOrApplicationClassLoader(cl))
615: methodCache.put(cl,cached);
616: }
617: readObjectMethod = cached[0];
618: writeObjectMethod = cached[1];
619: readResolveMethod = cached[2];
620: writeReplaceMethod = cached[3];
621: }
622:
623: private ObjectStreamClass(Class cl)
624: {
625: uid = 0;
626: flags = 0;
627: isProxyClass = Proxy.isProxyClass(cl);
628:
629: clazz = cl;
630: cacheMethods();
631: name = cl.getName();
632: setFlags(cl);
633: setFields(cl);
634:
635: if ( (Serializable.class).isAssignableFrom(cl) && !isProxyClass)
636: uid = getClassUID(cl);
637: superClass = lookup(cl.getSuperclass());
638: }
639:
640:
641:
642: private void setFlags(Class cl)
643: {
644: if ((java.io.Externalizable.class).isAssignableFrom(cl))
645: flags |= ObjectStreamConstants.SC_EXTERNALIZABLE;
646: else if ((java.io.Serializable.class).isAssignableFrom(cl))
647:
648: flags |= ObjectStreamConstants.SC_SERIALIZABLE;
649:
650: if (writeObjectMethod != null)
651: flags |= ObjectStreamConstants.SC_WRITE_METHOD;
652:
653: if (cl.isEnum() || cl == Enum.class)
654: flags |= ObjectStreamConstants.SC_ENUM;
655: }
656:
657:
658:
659:
660: private void setFields(Class cl)
661: {
662: SetAccessibleAction setAccessible = new SetAccessibleAction();
663:
664: if (!isSerializable() || isExternalizable() || isEnum())
665: {
666: fields = NO_FIELDS;
667: return;
668: }
669:
670: try
671: {
672: final Field f =
673: cl.getDeclaredField("serialPersistentFields");
674: setAccessible.setMember(f);
675: AccessController.doPrivileged(setAccessible);
676: int modifiers = f.getModifiers();
677:
678: if (Modifier.isStatic(modifiers)
679: && Modifier.isFinal(modifiers)
680: && Modifier.isPrivate(modifiers))
681: {
682: fields = getSerialPersistentFields(cl);
683: if (fields != null)
684: {
685: ObjectStreamField[] fieldsName = new ObjectStreamField[fields.length];
686: System.arraycopy(fields, 0, fieldsName, 0, fields.length);
687:
688: Arrays.sort (fieldsName, new Comparator() {
689: public int compare(Object o1, Object o2)
690: {
691: ObjectStreamField f1 = (ObjectStreamField)o1;
692: ObjectStreamField f2 = (ObjectStreamField)o2;
693:
694: return f1.getName().compareTo(f2.getName());
695: }
696: });
697:
698: for (int i=1; i < fields.length; i++)
699: {
700: if (fieldsName[i-1].getName().equals(fieldsName[i].getName()))
701: {
702: fields = INVALID_FIELDS;
703: return;
704: }
705: }
706:
707: Arrays.sort (fields);
708:
709: for (int i=0; i < fields.length; i++)
710: {
711: try
712: {
713: fields[i].lookupField(cl);
714: }
715: catch (NoSuchFieldException _)
716: {
717: fields[i].setToSet(false);
718: }
719: }
720:
721: calculateOffsets();
722: return;
723: }
724: }
725: }
726: catch (NoSuchFieldException ignore)
727: {
728: }
729: catch (IllegalAccessException ignore)
730: {
731: }
732:
733: int num_good_fields = 0;
734: Field[] all_fields = cl.getDeclaredFields();
735:
736: int modifiers;
737:
738: for (int i = 0; i < all_fields.length; i++)
739: {
740: modifiers = all_fields[i].getModifiers();
741: if (Modifier.isTransient(modifiers)
742: || Modifier.isStatic(modifiers))
743: all_fields[i] = null;
744: else
745: num_good_fields++;
746: }
747:
748:
749: fields = new ObjectStreamField[ num_good_fields ];
750: for (int from = 0, to = 0; from < all_fields.length; from++)
751: if (all_fields[from] != null)
752: {
753: final Field f = all_fields[from];
754: setAccessible.setMember(f);
755: AccessController.doPrivileged(setAccessible);
756: fields[to] = new ObjectStreamField(all_fields[from]);
757: to++;
758: }
759:
760: Arrays.sort(fields);
761:
762:
763: for (int i = 1; i < fields.length; i++)
764: {
765: if(fields[i - 1].getName().equals(fields[i].getName()))
766: throw new InternalError("Duplicate field " +
767: fields[i].getName() + " in class " + cl.getName());
768: }
769: calculateOffsets();
770: }
771:
772: static Hashtable uidCache = new Hashtable();
773:
774:
775:
776: private long getClassUID(Class cl)
777: {
778: long result = 0;
779: Long cache = (Long) uidCache.get(cl);
780: if (cache != null)
781: result = cache.longValue();
782: else
783: {
784: try
785: {
786: result = getClassUIDFromField(cl);
787: }
788: catch (NoSuchFieldException ignore)
789: {
790: try
791: {
792: result = calculateClassUID(cl);
793: }
794: catch (NoSuchAlgorithmException e)
795: {
796: throw new RuntimeException
797: ("The SHA algorithm was not found to use in computing the Serial Version UID for class "
798: + cl.getName(), e);
799: }
800: catch (IOException ioe)
801: {
802: throw new RuntimeException(ioe);
803: }
804: }
805:
806: if (loadedByBootOrApplicationClassLoader(cl))
807: uidCache.put(cl,new Long(result));
808: }
809: return result;
810: }
811:
812:
821: long getClassUIDFromField(Class cl)
822: throws NoSuchFieldException
823: {
824: long result;
825:
826: try
827: {
828:
829:
830:
831: final Field suid = cl.getDeclaredField("serialVersionUID");
832: SetAccessibleAction setAccessible = new SetAccessibleAction(suid);
833: AccessController.doPrivileged(setAccessible);
834: int modifiers = suid.getModifiers();
835:
836: if (Modifier.isStatic(modifiers)
837: && Modifier.isFinal(modifiers)
838: && suid.getType() == Long.TYPE)
839: result = suid.getLong(null);
840: else
841: throw new NoSuchFieldException();
842: }
843: catch (IllegalAccessException ignore)
844: {
845: throw new NoSuchFieldException();
846: }
847:
848: return result;
849: }
850:
851:
864: long calculateClassUID(Class cl)
865: throws NoSuchAlgorithmException, IOException
866: {
867: long result;
868: MessageDigest md;
869: try
870: {
871: md = MessageDigest.getInstance("SHA");
872: }
873: catch (NoSuchAlgorithmException e)
874: {
875:
876: Gnu gnuProvider = new Gnu();
877: Security.addProvider(gnuProvider);
878: md = MessageDigest.getInstance("SHA");
879: }
880:
881: DigestOutputStream digest_out =
882: new DigestOutputStream(nullOutputStream, md);
883: DataOutputStream data_out = new DataOutputStream(digest_out);
884:
885: data_out.writeUTF(cl.getName());
886:
887: int modifiers = cl.getModifiers();
888:
889: modifiers = modifiers & (Modifier.ABSTRACT | Modifier.FINAL
890: | Modifier.INTERFACE | Modifier.PUBLIC);
891: data_out.writeInt(modifiers);
892:
893:
894:
895: if (! cl.isArray())
896: {
897: Class[] interfaces = cl.getInterfaces();
898: Arrays.sort(interfaces, interfaceComparator);
899: for (int i = 0; i < interfaces.length; i++)
900: data_out.writeUTF(interfaces[i].getName());
901: }
902:
903: Field field;
904: Field[] fields = cl.getDeclaredFields();
905: Arrays.sort(fields, memberComparator);
906: for (int i = 0; i < fields.length; i++)
907: {
908: field = fields[i];
909: modifiers = field.getModifiers();
910: if (Modifier.isPrivate(modifiers)
911: && (Modifier.isStatic(modifiers)
912: || Modifier.isTransient(modifiers)))
913: continue;
914:
915: data_out.writeUTF(field.getName());
916: data_out.writeInt(modifiers);
917: data_out.writeUTF(TypeSignature.getEncodingOfClass (field.getType()));
918: }
919:
920:
921: if (VMObjectStreamClass.hasClassInitializer(cl))
922: {
923: data_out.writeUTF("<clinit>");
924: data_out.writeInt(Modifier.STATIC);
925: data_out.writeUTF("()V");
926: }
927:
928: Constructor constructor;
929: Constructor[] constructors = cl.getDeclaredConstructors();
930: Arrays.sort (constructors, memberComparator);
931: for (int i = 0; i < constructors.length; i++)
932: {
933: constructor = constructors[i];
934: modifiers = constructor.getModifiers();
935: if (Modifier.isPrivate(modifiers))
936: continue;
937:
938: data_out.writeUTF("<init>");
939: data_out.writeInt(modifiers);
940:
941:
942:
943: data_out.writeUTF
944: (TypeSignature.getEncodingOfConstructor(constructor).replace('/','.'));
945: }
946:
947: Method method;
948: Method[] methods = cl.getDeclaredMethods();
949: Arrays.sort(methods, memberComparator);
950: for (int i = 0; i < methods.length; i++)
951: {
952: method = methods[i];
953: modifiers = method.getModifiers();
954: if (Modifier.isPrivate(modifiers))
955: continue;
956:
957: data_out.writeUTF(method.getName());
958: data_out.writeInt(modifiers);
959:
960:
961:
962: data_out.writeUTF
963: (TypeSignature.getEncodingOfMethod(method).replace('/', '.'));
964: }
965:
966: data_out.close();
967: byte[] sha = md.digest();
968: result = 0;
969: int len = sha.length < 8 ? sha.length : 8;
970: for (int i = 0; i < len; i++)
971: result += (long) (sha[i] & 0xFF) << (8 * i);
972:
973: return result;
974: }
975:
976:
985: private ObjectStreamField[] getSerialPersistentFields(Class clazz)
986: throws NoSuchFieldException, IllegalAccessException
987: {
988: ObjectStreamField[] fieldsArray = null;
989: ObjectStreamField[] o;
990:
991:
992:
993: Field f = clazz.getDeclaredField("serialPersistentFields");
994: f.setAccessible(true);
995:
996: int modifiers = f.getModifiers();
997: if (!(Modifier.isStatic(modifiers) &&
998: Modifier.isFinal(modifiers) &&
999: Modifier.isPrivate(modifiers)))
1000: return null;
1001:
1002: o = (ObjectStreamField[]) f.get(null);
1003:
1004: if (o == null)
1005: return null;
1006:
1007: fieldsArray = new ObjectStreamField[ o.length ];
1008: System.arraycopy(o, 0, fieldsArray, 0, o.length);
1009:
1010: return fieldsArray;
1011: }
1012:
1013:
1020: Externalizable newInstance() throws InvalidClassException
1021: {
1022: synchronized(this)
1023: {
1024: if (constructor == null)
1025: {
1026: try
1027: {
1028: final Constructor c = clazz.getConstructor(new Class[0]);
1029:
1030: AccessController.doPrivileged(new PrivilegedAction()
1031: {
1032: public Object run()
1033: {
1034: c.setAccessible(true);
1035: return null;
1036: }
1037: });
1038:
1039: constructor = c;
1040: }
1041: catch(NoSuchMethodException x)
1042: {
1043: throw new InvalidClassException(clazz.getName(),
1044: "No public zero-argument constructor");
1045: }
1046: }
1047: }
1048:
1049: try
1050: {
1051: return (Externalizable)constructor.newInstance(null);
1052: }
1053: catch(Exception x)
1054: {
1055: throw (InvalidClassException)
1056: new InvalidClassException(clazz.getName(),
1057: "Unable to instantiate").initCause(x);
1058: }
1059: }
1060:
1061: public static final ObjectStreamField[] NO_FIELDS = {};
1062:
1063: private static Hashtable<Class,ObjectStreamClass> classLookupTable
1064: = new Hashtable<Class,ObjectStreamClass>();
1065: private static final NullOutputStream nullOutputStream = new NullOutputStream();
1066: private static final Comparator interfaceComparator = new InterfaceComparator();
1067: private static final Comparator memberComparator = new MemberComparator();
1068: private static final
1069: Class[] writeMethodArgTypes = { java.io.ObjectOutputStream.class };
1070:
1071: private ObjectStreamClass superClass;
1072: private Class<?> clazz;
1073: private String name;
1074: private long uid;
1075: private byte flags;
1076:
1077:
1078:
1079: ObjectStreamField[] fields;
1080:
1081:
1082: int primFieldSize = -1;
1083: int objectFieldCount;
1084:
1085: Method readObjectMethod;
1086: Method readResolveMethod;
1087: Method writeReplaceMethod;
1088: Method writeObjectMethod;
1089: boolean realClassIsSerializable;
1090: boolean realClassIsExternalizable;
1091: ObjectStreamField[] fieldMapping;
1092: Constructor firstNonSerializableParentConstructor;
1093: private Constructor constructor;
1094:
1095: boolean isProxyClass = false;
1096:
1097:
1098:
1099: private static final long serialVersionUID = -6120832682080437368L;
1100:
1101:
1102:
1103: private static final class InterfaceComparator implements Comparator
1104: {
1105: public int compare(Object o1, Object o2)
1106: {
1107: return ((Class) o1).getName().compareTo(((Class) o2).getName());
1108: }
1109: }
1110:
1111:
1112:
1113:
1114: private static final class MemberComparator implements Comparator
1115: {
1116: public int compare(Object o1, Object o2)
1117: {
1118: Member m1 = (Member) o1;
1119: Member m2 = (Member) o2;
1120:
1121: int comp = m1.getName().compareTo(m2.getName());
1122:
1123: if (comp == 0)
1124: return TypeSignature.getEncodingOfMember(m1).
1125: compareTo(TypeSignature.getEncodingOfMember(m2));
1126: else
1127: return comp;
1128: }
1129: }
1130: }