1. /*
  2. * @(#)ValueUtility.java 1.29 03/12/19
  3. *
  4. * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
  5. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  6. */
  7. /*
  8. * Licensed Materials - Property of IBM
  9. * RMI-IIOP v1.0
  10. * Copyright IBM Corp. 1998 1999 All Rights Reserved
  11. *
  12. * US Government Users Restricted Rights - Use, duplication or
  13. * disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
  14. */
  15. package com.sun.corba.se.impl.io;
  16. import com.sun.org.omg.CORBA.ValueDefPackage.FullValueDescription;
  17. import com.sun.org.omg.CORBA.OperationDescription;
  18. import com.sun.org.omg.CORBA.AttributeDescription;
  19. import org.omg.CORBA.ValueMember;
  20. import com.sun.org.omg.CORBA.Initializer;
  21. import org.omg.CORBA.IDLType;
  22. import com.sun.org.omg.CORBA._IDLTypeStub;
  23. import org.omg.CORBA.ORB;
  24. import org.omg.CORBA.TypeCodePackage.*;
  25. import org.omg.CORBA.TypeCode;
  26. import org.omg.CORBA.TCKind;
  27. import java.lang.reflect.*;
  28. import com.sun.corba.se.impl.util.RepositoryId;
  29. import java.util.*;
  30. import javax.rmi.CORBA.Util;
  31. import javax.rmi.CORBA.ValueHandler;
  32. /**
  33. * Holds utility methods for converting from ObjectStreamClass to
  34. * FullValueDescription and generating typecodes from ObjectStreamClass.
  35. **/
  36. public class ValueUtility {
  37. public static final short PRIVATE_MEMBER = 0;
  38. public static final short PUBLIC_MEMBER = 1;
  39. private static final String primitiveConstants[] = {
  40. null, // tk_null 0
  41. null, // tk_void 1
  42. "S", // tk_short 2
  43. "I", // tk_long 3
  44. "S", // tk_ushort 4
  45. "I", // tk_ulong 5
  46. "F", // tk_float 6
  47. "D", // tk_double 7
  48. "Z", // tk_boolean 8
  49. "C", // tk_char 9
  50. "B", // tk_octet 10
  51. null, // tk_any 11
  52. null, // tk_typecode 12
  53. null, // tk_principal 13
  54. null, // tk_objref 14
  55. null, // tk_struct 15
  56. null, // tk_union 16
  57. null, // tk_enum 17
  58. null, // tk_string 18
  59. null, // tk_sequence 19
  60. null, // tk_array 20
  61. null, // tk_alias 21
  62. null, // tk_except 22
  63. "J", // tk_longlong 23
  64. "J", // tk_ulonglong 24
  65. "D", // tk_longdouble 25
  66. "C", // tk_wchar 26
  67. null, // tk_wstring 27
  68. null, // tk_fixed 28
  69. null, // tk_value 29
  70. null, // tk_value_box 30
  71. null, // tk_native 31
  72. null, // tk_abstract_interface 32
  73. };
  74. public static String getSignature(ValueMember member)
  75. throws ClassNotFoundException {
  76. // REVISIT. Can the type be something that is
  77. // non-primitive yet not a value_box, value, or objref?
  78. // If so, should use ObjectStreamClass or throw
  79. // exception.
  80. if (member.type.kind().value() == TCKind._tk_value_box ||
  81. member.type.kind().value() == TCKind._tk_value ||
  82. member.type.kind().value() == TCKind._tk_objref) {
  83. Class c = RepositoryId.cache.getId(member.id).getClassFromType();
  84. return ObjectStreamClass.getSignature(c);
  85. } else {
  86. return primitiveConstants[member.type.kind().value()];
  87. }
  88. }
  89. public static FullValueDescription translate(ORB orb, ObjectStreamClass osc, ValueHandler vh){
  90. // Create FullValueDescription
  91. FullValueDescription result = new FullValueDescription();
  92. Class className = osc.forClass();
  93. ValueHandlerImpl vhandler = (com.sun.corba.se.impl.io.ValueHandlerImpl) vh;
  94. String repId = vhandler.createForAnyType(className);
  95. // Set FVD name
  96. result.name = vhandler.getUnqualifiedName(repId);
  97. if (result.name == null)
  98. result.name = "";
  99. // Set FVD id _REVISIT_ : Manglings
  100. result.id = vhandler.getRMIRepositoryID(className);
  101. if (result.id == null)
  102. result.id = "";
  103. // Set FVD is_abstract
  104. result.is_abstract = ObjectStreamClassCorbaExt.isAbstractInterface(className);
  105. // Set FVD is_custom
  106. result.is_custom = osc.hasWriteObject() || osc.isExternalizable();
  107. // Set FVD defined_in _REVISIT_ : Manglings
  108. result.defined_in = vhandler.getDefinedInId(repId);
  109. if (result.defined_in == null)
  110. result.defined_in = "";
  111. // Set FVD version
  112. result.version = vhandler.getSerialVersionUID(repId);
  113. if (result.version == null)
  114. result.version = "";
  115. // Skip FVD operations - N/A
  116. result.operations = new OperationDescription[0];
  117. // Skip FVD attributed - N/A
  118. result.attributes = new AttributeDescription[0];
  119. // Set FVD members
  120. // Maps classes to repositoryIDs strings. This is used to detect recursive types.
  121. IdentityKeyValueStack createdIDs = new IdentityKeyValueStack();
  122. // Stores all types created for resolving indirect types at the end.
  123. result.members = translateMembers(orb, osc, vh, createdIDs);
  124. // Skip FVD initializers - N/A
  125. result.initializers = new Initializer[0];
  126. Class interfaces[] = osc.forClass().getInterfaces();
  127. int abstractCount = 0;
  128. // Skip FVD supported_interfaces
  129. result.supported_interfaces = new String[interfaces.length];
  130. for (int interfaceIndex = 0; interfaceIndex < interfaces.length;
  131. interfaceIndex++) {
  132. result.supported_interfaces[interfaceIndex] =
  133. vhandler.createForAnyType(interfaces[interfaceIndex]);
  134. if ((!(java.rmi.Remote.class.isAssignableFrom(interfaces[interfaceIndex]))) ||
  135. (!Modifier.isPublic(interfaces[interfaceIndex].getModifiers())))
  136. abstractCount++;
  137. }
  138. // Skip FVD abstract_base_values - N/A
  139. result.abstract_base_values = new String[abstractCount];
  140. for (int interfaceIndex = 0; interfaceIndex < interfaces.length;
  141. interfaceIndex++) {
  142. if ((!(java.rmi.Remote.class.isAssignableFrom(interfaces[interfaceIndex]))) ||
  143. (!Modifier.isPublic(interfaces[interfaceIndex].getModifiers())))
  144. result.abstract_base_values[interfaceIndex] =
  145. vhandler.createForAnyType(interfaces[interfaceIndex]);
  146. }
  147. result.is_truncatable = false;
  148. // Set FVD base_value
  149. Class superClass = osc.forClass().getSuperclass();
  150. if (java.io.Serializable.class.isAssignableFrom(superClass))
  151. result.base_value = vhandler.getRMIRepositoryID(superClass);
  152. else
  153. result.base_value = "";
  154. // Set FVD type
  155. //result.type = createTypeCodeForClass(orb, osc.forClass());
  156. result.type = orb.get_primitive_tc(TCKind.tk_value); //11638
  157. return result;
  158. }
  159. private static ValueMember[] translateMembers (ORB orb,
  160. ObjectStreamClass osc,
  161. ValueHandler vh,
  162. IdentityKeyValueStack createdIDs)
  163. {
  164. ValueHandlerImpl vhandler = (com.sun.corba.se.impl.io.ValueHandlerImpl) vh;
  165. ObjectStreamField fields[] = osc.getFields();
  166. int fieldsLength = fields.length;
  167. ValueMember[] members = new ValueMember[fieldsLength];
  168. // Note : fields come out of ObjectStreamClass in correct order for
  169. // writing. So, we will create the same order in the members array.
  170. for (int i = 0; i < fieldsLength; i++) {
  171. String valRepId = vhandler.getRMIRepositoryID(fields[i].getClazz());
  172. members[i] = new ValueMember();
  173. members[i].name = fields[i].getName();
  174. members[i].id = valRepId; // _REVISIT_ : Manglings
  175. members[i].defined_in = vhandler.getDefinedInId(valRepId);// _REVISIT_ : Manglings
  176. members[i].version = "1.0";
  177. members[i].type_def = new _IDLTypeStub(); // _REVISIT_ : IDLType implementation missing
  178. if (fields[i].getField() == null) {
  179. // When using serialPersistentFields, the class may
  180. // no longer have an actual Field that corresponds
  181. // to one of the items. The Java to IDL spec
  182. // ptc-00-01-06 1.3.5.6 says that the IDL field
  183. // should be private in this case.
  184. members[i].access = PRIVATE_MEMBER;
  185. } else {
  186. int m = fields[i].getField().getModifiers();
  187. if (Modifier.isPublic(m))
  188. members[i].access = PUBLIC_MEMBER;
  189. else
  190. members[i].access = PRIVATE_MEMBER;
  191. }
  192. switch (fields[i].getTypeCode()) {
  193. case 'B':
  194. members[i].type = orb.get_primitive_tc(TCKind.tk_octet); //11638
  195. break;
  196. case 'C':
  197. members[i].type
  198. = orb.get_primitive_tc(vhandler.getJavaCharTCKind()); // 11638
  199. break;
  200. case 'F':
  201. members[i].type = orb.get_primitive_tc(TCKind.tk_float); //11638
  202. break;
  203. case 'D' :
  204. members[i].type = orb.get_primitive_tc(TCKind.tk_double); //11638
  205. break;
  206. case 'I':
  207. members[i].type = orb.get_primitive_tc(TCKind.tk_long); //11638
  208. break;
  209. case 'J':
  210. members[i].type = orb.get_primitive_tc(TCKind.tk_longlong); //11638
  211. break;
  212. case 'S':
  213. members[i].type = orb.get_primitive_tc(TCKind.tk_short); //11638
  214. break;
  215. case 'Z':
  216. members[i].type = orb.get_primitive_tc(TCKind.tk_boolean); //11638
  217. break;
  218. // case '[':
  219. // members[i].type = orb.get_primitive_tc(TCKind.tk_value_box); //11638
  220. // members[i].id = RepositoryId.createForAnyType(fields[i].getType());
  221. // break;
  222. default:
  223. members[i].type = createTypeCodeForClassInternal(orb, fields[i].getClazz(), vhandler,
  224. createdIDs);
  225. members[i].id = vhandler.createForAnyType(fields[i].getType());
  226. break;
  227. } // end switch
  228. } // end for loop
  229. return members;
  230. }
  231. private static boolean exists(String str, String strs[]){
  232. for (int i = 0; i < strs.length; i++)
  233. if (str.equals(strs[i]))
  234. return true;
  235. return false;
  236. }
  237. public static boolean isAssignableFrom(String clzRepositoryId, FullValueDescription type,
  238. com.sun.org.omg.SendingContext.CodeBase sender){
  239. if (exists(clzRepositoryId, type.supported_interfaces))
  240. return true;
  241. if (clzRepositoryId.equals(type.id))
  242. return true;
  243. if ((type.base_value != null) &&
  244. (!type.base_value.equals(""))) {
  245. FullValueDescription parent = sender.meta(type.base_value);
  246. return isAssignableFrom(clzRepositoryId, parent, sender);
  247. }
  248. return false;
  249. }
  250. public static TypeCode createTypeCodeForClass (ORB orb, java.lang.Class c, ValueHandler vh) {
  251. // Maps classes to repositoryIDs strings. This is used to detect recursive types.
  252. IdentityKeyValueStack createdIDs = new IdentityKeyValueStack();
  253. // Stores all types created for resolving indirect types at the end.
  254. TypeCode tc = createTypeCodeForClassInternal(orb, c, vh, createdIDs);
  255. return tc;
  256. }
  257. private static TypeCode createTypeCodeForClassInternal (ORB orb,
  258. java.lang.Class c,
  259. ValueHandler vh,
  260. IdentityKeyValueStack createdIDs)
  261. {
  262. // This wrapper method is the protection against infinite recursion.
  263. TypeCode tc = null;
  264. String id = (String)createdIDs.get(c);
  265. if (id != null) {
  266. return orb.create_recursive_tc(id);
  267. } else {
  268. id = vh.getRMIRepositoryID(c);
  269. if (id == null) id = "";
  270. // cache the rep id BEFORE creating a new typecode.
  271. // so that recursive tc can look up the rep id.
  272. createdIDs.push(c, id);
  273. tc = createTypeCodeInternal(orb, c, vh, id, createdIDs);
  274. createdIDs.pop();
  275. return tc;
  276. }
  277. }
  278. // Maintains a stack of key-value pairs. Compares elements using == operator.
  279. private static class IdentityKeyValueStack {
  280. private static class KeyValuePair {
  281. Object key;
  282. Object value;
  283. KeyValuePair(Object key, Object value) {
  284. this.key = key;
  285. this.value = value;
  286. }
  287. boolean equals(KeyValuePair pair) {
  288. return pair.key == this.key;
  289. }
  290. }
  291. Stack pairs = null;
  292. Object get(Object key) {
  293. if (pairs == null) {
  294. return null;
  295. }
  296. for (Iterator i = pairs.iterator(); i.hasNext();) {
  297. KeyValuePair pair = (KeyValuePair)i.next();
  298. if (pair.key == key) {
  299. return pair.value;
  300. }
  301. }
  302. return null;
  303. }
  304. void push(Object key, Object value) {
  305. if (pairs == null) {
  306. pairs = new Stack();
  307. }
  308. pairs.push(new KeyValuePair(key, value));
  309. }
  310. void pop() {
  311. pairs.pop();
  312. }
  313. }
  314. private static TypeCode createTypeCodeInternal (ORB orb,
  315. java.lang.Class c,
  316. ValueHandler vh,
  317. String id,
  318. IdentityKeyValueStack createdIDs)
  319. {
  320. if ( c.isArray() ) {
  321. // Arrays - may recurse for multi-dimensional arrays
  322. Class componentClass = c.getComponentType();
  323. TypeCode embeddedType;
  324. if ( componentClass.isPrimitive() ){
  325. embeddedType
  326. = ValueUtility.getPrimitiveTypeCodeForClass(orb,
  327. componentClass,
  328. vh);
  329. } else {
  330. embeddedType = createTypeCodeForClassInternal(orb, componentClass, vh,
  331. createdIDs);
  332. }
  333. TypeCode t = orb.create_sequence_tc (0, embeddedType);
  334. return orb.create_value_box_tc (id, "Sequence", t);
  335. } else if ( c == java.lang.String.class ) {
  336. // Strings
  337. TypeCode t = orb.create_string_tc (0);
  338. return orb.create_value_box_tc (id, "StringValue", t);
  339. } else if (java.rmi.Remote.class.isAssignableFrom(c)) {
  340. return orb.get_primitive_tc(TCKind.tk_objref);
  341. } else if (org.omg.CORBA.Object.class.isAssignableFrom(c)) {
  342. return orb.get_primitive_tc(TCKind.tk_objref);
  343. }
  344. // Anything else
  345. ObjectStreamClass osc = ObjectStreamClass.lookup(c);
  346. if (osc == null) {
  347. return orb.create_value_box_tc (id, "Value", orb.get_primitive_tc (TCKind.tk_value));
  348. }
  349. // type modifier
  350. // REVISIT truncatable and abstract?
  351. short modifier = (osc.isCustomMarshaled() ? org.omg.CORBA.VM_CUSTOM.value : org.omg.CORBA.VM_NONE.value);
  352. // concrete base
  353. TypeCode base = null;
  354. Class superClass = c.getSuperclass();
  355. if (superClass != null && java.io.Serializable.class.isAssignableFrom(superClass)) {
  356. base = createTypeCodeForClassInternal(orb, superClass, vh, createdIDs);
  357. }
  358. // members
  359. ValueMember[] members = translateMembers (orb, osc, vh, createdIDs);
  360. return orb.create_value_tc(id, c.getName(), modifier, base, members);
  361. }
  362. public static TypeCode getPrimitiveTypeCodeForClass (ORB orb,
  363. Class c,
  364. ValueHandler vh) {
  365. if (c == Integer.TYPE) {
  366. return orb.get_primitive_tc (TCKind.tk_long);
  367. } else if (c == Byte.TYPE) {
  368. return orb.get_primitive_tc (TCKind.tk_octet);
  369. } else if (c == Long.TYPE) {
  370. return orb.get_primitive_tc (TCKind.tk_longlong);
  371. } else if (c == Float.TYPE) {
  372. return orb.get_primitive_tc (TCKind.tk_float);
  373. } else if (c == Double.TYPE) {
  374. return orb.get_primitive_tc (TCKind.tk_double);
  375. } else if (c == Short.TYPE) {
  376. return orb.get_primitive_tc (TCKind.tk_short);
  377. } else if (c == Character.TYPE) {
  378. return orb.get_primitive_tc (((ValueHandlerImpl)vh).getJavaCharTCKind());
  379. } else if (c == Boolean.TYPE) {
  380. return orb.get_primitive_tc (TCKind.tk_boolean);
  381. } else {
  382. // _REVISIT_ Not sure if this is right.
  383. return orb.get_primitive_tc (TCKind.tk_any);
  384. }
  385. }
  386. }