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