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