1 /* 2 * Copyright (c) 2000, 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.orbutil; 33 34 import java.util.StringTokenizer; 35 import java.util.Hashtable; 36 import java.io.IOException; 37 import java.lang.reflect.Method; 38 39 // Imports for using codebase URL to load class 40 import java.net.MalformedURLException; 41 import org.omg.CORBA.portable.ValueBase; 42 import org.omg.CORBA.portable.IDLEntity; 43 44 import com.sun.corba.se.impl.util.JDKBridge; 45 import com.sun.corba.se.impl.util.Utility; 46 import com.sun.corba.se.impl.util.PackagePrefixChecker; 47 import com.sun.corba.se.impl.util.IdentityHashtable; 48 import com.sun.corba.se.impl.io.ObjectStreamClass; 49 50 import javax.rmi.CORBA.Util; 51 52 // keeping the original RepositoryId class that was shipped in 53 // JDK 1.3. It has interoperability bugs 54 55 public class RepositoryId_1_3 { 56 57 // Legal IDL Identifier characters (1 = legal). Note 58 // that '.' (2E) is marked as legal even though it is 59 // not legal in IDL. This allows us to treat a fully 60 // qualified Java name with '.' package separators 61 // uniformly, and is safe because that is the only 62 // legal use of '.' in a Java name. 63 64 public static final RepositoryIdCache_1_3 cache = new RepositoryIdCache_1_3(); 65 private static final byte[] IDL_IDENTIFIER_CHARS = { 66 67 // 0 1 2 3 4 5 6 7 8 9 a b c d e f 68 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, // 00-0f 69 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, // 10-1f 70 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,1,0, // 20-2f 71 1,1,1,1, 1,1,1,1, 1,1,0,0, 0,0,0,0, // 30-3f 72 0,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1, // 40-4f 73 1,1,1,1, 1,1,1,1, 1,1,1,0, 0,0,0,1, // 50-5f 74 0,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1, // 60-6f 75 1,1,1,1, 1,1,1,1, 1,1,1,0, 0,0,0,0, // 70-7f 76 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, // 80-8f 77 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, // 90-9f 78 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, // a0-af 79 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, // b0-bf 80 1,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1, // c0-cf 81 0,1,1,1, 1,1,1,0, 1,1,1,1, 1,0,0,1, // d0-df 82 1,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1, // e0-ef 83 0,1,1,1, 1,1,1,0, 1,1,1,1, 1,0,0,1, // f0-ff 84 }; 85 86 private static String defaultServerURL = null; 87 private static boolean useCodebaseOnly = false; 88 89 static { 90 if (defaultServerURL == null) 91 defaultServerURL = (String)JDKBridge.getLocalCodebase(); 92 useCodebaseOnly = JDKBridge.useCodebaseOnly(); 93 94 } 95 96 private static IdentityHashtable classToRepStr = new IdentityHashtable(); 97 private static IdentityHashtable classIDLToRepStr = new IdentityHashtable(); 98 private static IdentityHashtable classSeqToRepStr = new IdentityHashtable(); 99 100 private static IdentityHashtable repStrToByteArray = new IdentityHashtable(); 101 private static Hashtable repStrToClass = new Hashtable(); 102 103 private String repId = null; 104 private boolean isSupportedFormat = true; 105 private String typeString = null; 106 private String versionString = null; 107 private boolean isSequence = false; 108 private boolean isRMIValueType = false; 109 private boolean isIDLType = false; 110 private String completeClassName = null; 111 private String unqualifiedName = null; 112 private String definedInId = null; 113 private Class clazz = null; 114 private String suid = null, actualSuid = null; 115 private long suidLong = ObjectStreamClass.kDefaultUID, actualSuidLong = ObjectStreamClass.kDefaultUID; 116 117 // Repository ID fragments 118 private static final String kValuePrefix = "RMI:"; 119 private static final String kIDLPrefix = "IDL:"; 120 private static final String kIDLNamePrefix = "omg.org/"; 121 private static final String kIDLClassnamePrefix = "org.omg."; 122 private static final String kSequencePrefix = "["; 123 private static final String kCORBAPrefix = "CORBA/"; 124 private static final String kArrayPrefix = kValuePrefix + kSequencePrefix + kCORBAPrefix; 125 private static final int kValuePrefixLength = kValuePrefix.length(); 126 private static final int kIDLPrefixLength = kIDLPrefix.length(); 127 private static final int kSequencePrefixLength = kSequencePrefix.length(); 128 private static final String kInterfaceHashCode = ":0000000000000000"; 129 private static final String kInterfaceOnlyHashStr = "0000000000000000"; 130 private static final String kExternalizableHashStr = "0000000000000001"; 131 132 // Value tag utility methods and constants 133 public static final int kInitialValueTag= 0x7fffff00; 134 public static final int kNoTypeInfo = 0; 135 public static final int kSingleRepTypeInfo = 0x02; 136 public static final int kPartialListTypeInfo = 0x06; 137 public static final int kChunkedMask = 0x08; 138 139 // Public, well known repository IDs 140 141 // _REVISIT_ : A table structure with a good search routine for all of this 142 // would be more efficient and easier to maintain... 143 144 // String 145 public static final String kWStringValueVersion = "1.0"; 146 public static final String kWStringValueHash = ":"+kWStringValueVersion; 147 public static final String kWStringStubValue = "WStringValue"; 148 public static final String kWStringTypeStr = "omg.org/CORBA/"+kWStringStubValue; 149 public static final String kWStringValueRepID = kIDLPrefix + kWStringTypeStr + kWStringValueHash; 150 151 // Any 152 public static final String kAnyRepID = kIDLPrefix + "omg.org/CORBA/Any"; 153 154 // Class 155 public static final String kClassDescValueHash = ":" + Long.toHexString( 156 ObjectStreamClass.getSerialVersionUID(javax.rmi.CORBA.ClassDesc.class)); 157 public static final String kClassDescStubValue = "ClassDesc"; 158 public static final String kClassDescTypeStr = "javax.rmi.CORBA."+kClassDescStubValue; 159 public static final String kClassDescValueRepID = kValuePrefix + kClassDescTypeStr + kClassDescValueHash; 160 161 // Object 162 public static final String kObjectValueHash = ":1.0"; 163 public static final String kObjectStubValue = "Object"; 164 165 // Sequence 166 public static final String kSequenceValueHash = ":1.0"; 167 public static final String kPrimitiveSequenceValueHash = ":0000000000000000"; 168 169 // Serializable 170 public static final String kSerializableValueHash = ":1.0"; 171 public static final String kSerializableStubValue = "Serializable"; 172 173 // Externalizable 174 public static final String kExternalizableValueHash = ":1.0"; 175 public static final String kExternalizableStubValue = "Externalizable"; 176 177 // Remote (The empty string is used for java.rmi.Remote) 178 public static final String kRemoteValueHash = ""; 179 public static final String kRemoteStubValue = ""; 180 public static final String kRemoteTypeStr = ""; 181 public static final String kRemoteValueRepID = ""; 182 183 private static final Hashtable kSpecialArrayTypeStrings = new Hashtable(); 184 185 static { 186 kSpecialArrayTypeStrings.put("CORBA.WStringValue", new StringBuffer(java.lang.String.class.getName())); 187 kSpecialArrayTypeStrings.put("javax.rmi.CORBA.ClassDesc", new StringBuffer(java.lang.Class.class.getName())); 188 kSpecialArrayTypeStrings.put("CORBA.Object", new StringBuffer(java.rmi.Remote.class.getName())); 189 190 } 191 192 private static final Hashtable kSpecialCasesRepIDs = new Hashtable(); 193 194 static { 195 kSpecialCasesRepIDs.put(java.lang.String.class, kWStringValueRepID); 196 kSpecialCasesRepIDs.put(java.lang.Class.class, kClassDescValueRepID); 197 kSpecialCasesRepIDs.put(java.rmi.Remote.class, kRemoteValueRepID); 198 } 199 200 private static final Hashtable kSpecialCasesStubValues = new Hashtable(); 201 202 static { 203 kSpecialCasesStubValues.put(java.lang.String.class, kWStringStubValue); 204 kSpecialCasesStubValues.put(java.lang.Class.class, kClassDescStubValue); 205 kSpecialCasesStubValues.put(java.lang.Object.class, kObjectStubValue); 206 kSpecialCasesStubValues.put(java.io.Serializable.class, kSerializableStubValue); 207 kSpecialCasesStubValues.put(java.io.Externalizable.class, kExternalizableStubValue); 208 kSpecialCasesStubValues.put(java.rmi.Remote.class, kRemoteStubValue); 209 } 210 211 212 private static final Hashtable kSpecialCasesVersions = new Hashtable(); 213 214 static { 215 kSpecialCasesVersions.put(java.lang.String.class, kWStringValueHash); 216 kSpecialCasesVersions.put(java.lang.Class.class, kClassDescValueHash); 217 kSpecialCasesVersions.put(java.lang.Object.class, kObjectValueHash); 218 kSpecialCasesVersions.put(java.io.Serializable.class, kSerializableValueHash); 219 kSpecialCasesVersions.put(java.io.Externalizable.class, kExternalizableValueHash); 220 kSpecialCasesVersions.put(java.rmi.Remote.class, kRemoteValueHash); 221 } 222 223 private static final Hashtable kSpecialCasesClasses = new Hashtable(); 224 225 static { 226 kSpecialCasesClasses.put(kWStringTypeStr, java.lang.String.class); 227 kSpecialCasesClasses.put(kClassDescTypeStr, java.lang.Class.class); 228 kSpecialCasesClasses.put(kRemoteTypeStr, java.rmi.Remote.class); 229 230 kSpecialCasesClasses.put("org.omg.CORBA.WStringValue", java.lang.String.class); 231 kSpecialCasesClasses.put("javax.rmi.CORBA.ClassDesc", java.lang.Class.class); 232 //kSpecialCasesClasses.put(kRemoteTypeStr, java.rmi.Remote.class); 233 } 234 235 private static final Hashtable kSpecialCasesArrayPrefix = new Hashtable(); 236 237 static { 238 kSpecialCasesArrayPrefix.put(java.lang.String.class, kValuePrefix + kSequencePrefix + kCORBAPrefix); 239 kSpecialCasesArrayPrefix.put(java.lang.Class.class, kValuePrefix + kSequencePrefix + "javax/rmi/CORBA/"); 240 kSpecialCasesArrayPrefix.put(java.lang.Object.class, kValuePrefix + kSequencePrefix + "java/lang/"); 241 kSpecialCasesArrayPrefix.put(java.io.Serializable.class, kValuePrefix + kSequencePrefix + "java/io/"); 242 kSpecialCasesArrayPrefix.put(java.io.Externalizable.class, kValuePrefix + kSequencePrefix + "java/io/"); 243 kSpecialCasesArrayPrefix.put(java.rmi.Remote.class, kValuePrefix + kSequencePrefix + kCORBAPrefix); 244 } 245 246 private static final Hashtable kSpecialPrimitives = new Hashtable(); 247 248 static { 249 kSpecialPrimitives.put("int","long"); 250 kSpecialPrimitives.put("long","longlong"); 251 kSpecialPrimitives.put("byte","octet"); 252 } 253 254 /** 255 * Used to convert ascii to hex. 256 */ 257 private static final byte ASCII_HEX[] = { 258 (byte)'0', 259 (byte)'1', 260 (byte)'2', 261 (byte)'3', 262 (byte)'4', 263 (byte)'5', 264 (byte)'6', 265 (byte)'7', 266 (byte)'8', 267 (byte)'9', 268 (byte)'A', 269 (byte)'B', 270 (byte)'C', 271 (byte)'D', 272 (byte)'E', 273 (byte)'F', 274 }; 275 276 277 // Interface Rep ID Strings 278 public static final String kjava_rmi_Remote = createForAnyType(java.rmi.Remote.class); 279 public static final String korg_omg_CORBA_Object = createForAnyType(org.omg.CORBA.Object.class); 280 281 // Dummy arguments for getIdFromHelper method 282 public static final Class kNoParamTypes[] ={}; 283 public static final Object kNoArgs[] = {}; 284 285 286 RepositoryId_1_3(){} 287 288 RepositoryId_1_3(String aRepId){ 289 init(aRepId); 290 } 291 292 RepositoryId_1_3 init(String aRepId){ 293 294 this.repId = aRepId; 295 296 // Special case for remote 297 if (aRepId.length() == 0) { 298 clazz = java.rmi.Remote.class; 299 typeString = ""; 300 isRMIValueType = true; 301 suid = kInterfaceOnlyHashStr; 302 return this; 303 } 304 else if (aRepId.equals(kWStringValueRepID)) { 305 clazz = java.lang.String.class; 306 typeString = kWStringTypeStr; 307 isIDLType = true; 308 versionString = kWStringValueVersion; 309 return this; 310 } 311 else { 312 313 String repId = convertFromISOLatin1(aRepId); 314 315 versionString = repId.substring(repId.indexOf(':', repId.indexOf(':')+1)); 316 if (repId.startsWith(kIDLPrefix)) { 317 typeString = 318 repId.substring(kIDLPrefixLength, repId.indexOf(':', kIDLPrefixLength)); 319 isIDLType = true; 320 if (typeString.startsWith(kIDLNamePrefix)) 321 completeClassName = kIDLClassnamePrefix + 322 typeString.substring(kIDLNamePrefix.length()).replace('/','.'); 323 else completeClassName = typeString.replace('/','.'); 324 325 } 326 else if (repId.startsWith(kValuePrefix)) { 327 typeString = 328 repId.substring(kValuePrefixLength, repId.indexOf(':', kValuePrefixLength)); 329 isRMIValueType = true; 330 331 if (versionString.indexOf('.') == -1) { 332 actualSuid = versionString.substring(1); 333 suid = actualSuid; // default if not explicitly specified 334 335 if (actualSuid.indexOf(':') != -1){ 336 // we have a declared hash also 337 int pos = actualSuid.indexOf(':')+1; 338 // actualSuid = suid.substring(pos); 339 // suid = suid.substring(0, pos-1); 340 suid = actualSuid.substring(pos); 341 actualSuid = actualSuid.substring(0, pos-1); 342 } 343 344 } 345 else { 346 // _REVISIT_ : Special case version failure ? 347 } 348 } 349 else isSupportedFormat = false; 350 351 if (typeString.startsWith(kSequencePrefix)) { 352 isSequence = true; 353 } 354 355 356 return this; 357 } 358 } 359 360 public final String getUnqualifiedName() { 361 if (unqualifiedName == null){ 362 String className = getClassName(); 363 int index = (className != null) ? className.lastIndexOf('.') : -1; 364 if (index == -1){ 365 unqualifiedName = className; 366 definedInId = "IDL::1.0"; 367 } 368 else { 369 unqualifiedName = className.substring(index); 370 definedInId = "IDL:" + className.substring(0, index).replace('.','/') + ":1.0"; 371 } 372 } 373 374 return unqualifiedName; 375 } 376 377 public final String getDefinedInId() { 378 if (definedInId == null){ 379 getUnqualifiedName(); 380 } 381 382 return definedInId; 383 } 384 385 public final String getTypeString() { 386 return typeString; 387 } 388 389 public final String getVersionString() { 390 return versionString; 391 } 392 393 public final String getSerialVersionUID() { 394 return suid; 395 } 396 397 public final String getActualSerialVersionUID() { 398 return actualSuid; 399 } 400 public final long getSerialVersionUIDAsLong() { 401 return suidLong; 402 } 403 404 public final long getActualSerialVersionUIDAsLong() { 405 return actualSuidLong; 406 } 407 408 public final boolean isRMIValueType() { 409 return isRMIValueType; 410 } 411 412 public final boolean isIDLType() { 413 return isIDLType; 414 } 415 416 public final String getRepositoryId() { 417 return repId; 418 } 419 420 public static byte[] getByteArray(String repStr) { 421 synchronized (repStrToByteArray){ 422 return (byte[]) repStrToByteArray.get(repStr); 423 } 424 } 425 426 public static void setByteArray(String repStr, byte[] repStrBytes) { 427 synchronized (repStrToByteArray){ 428 repStrToByteArray.put(repStr, repStrBytes); 429 } 430 } 431 432 public final boolean isSequence() { 433 return isSequence; 434 } 435 436 public final boolean isSupportedFormat() { 437 return isSupportedFormat; 438 } 439 440 441 // This method will return the classname from the typestring OR if the classname turns out to be 442 // a special class "pseudo" name, then the matching real classname is returned. 443 public final String getClassName() { 444 445 if (isRMIValueType) 446 return typeString; 447 else if (isIDLType) 448 return completeClassName; 449 else return null; 450 451 } 452 453 // This method calls getClazzFromType() and falls back to the repStrToClass 454 // cache if no class was found. It's used where any class matching the 455 // given repid is an acceptable result. 456 public final Class getAnyClassFromType() throws ClassNotFoundException { 457 try { 458 return getClassFromType(); 459 } catch (ClassNotFoundException cnfe) { 460 Class clz = (Class)repStrToClass.get(repId); 461 if (clz != null) 462 return clz; 463 else 464 throw cnfe; 465 } 466 } 467 468 public final Class getClassFromType() 469 throws ClassNotFoundException { 470 if (clazz != null) 471 return clazz; 472 473 Class specialCase = (Class)kSpecialCasesClasses.get(getClassName()); 474 475 if (specialCase != null){ 476 clazz = specialCase; 477 return specialCase; 478 } 479 else 480 { 481 try{ 482 return Util.loadClass(getClassName(), null, null); 483 } 484 catch(ClassNotFoundException cnfe){ 485 if (defaultServerURL != null) { 486 try{ 487 return getClassFromType(defaultServerURL); 488 } 489 catch(MalformedURLException mue){ 490 throw cnfe; 491 } 492 } 493 else throw cnfe; 494 } 495 } 496 497 } 498 499 public final Class getClassFromType(Class expectedType, String codebase) 500 throws ClassNotFoundException { 501 if (clazz != null) 502 return clazz; 503 504 Class specialCase = (Class)kSpecialCasesClasses.get(getClassName()); 505 506 if (specialCase != null){ 507 clazz = specialCase; 508 return specialCase; 509 } else { 510 ClassLoader expectedTypeClassLoader = (expectedType == null ? null : expectedType.getClassLoader()); 511 return loadClassOfType(getClassName(), 512 codebase, 513 expectedTypeClassLoader, 514 expectedType, 515 expectedTypeClassLoader); 516 } 517 518 } 519 520 public final Class getClassFromType(String url) 521 throws ClassNotFoundException, MalformedURLException { 522 return Util.loadClass(getClassName(), url, null); 523 } 524 525 public final String toString() { 526 return repId; 527 } 528 529 private static String createHashString(java.io.Serializable ser) { 530 531 return createHashString(ser.getClass()); 532 } 533 534 private static String createHashString(java.lang.Class clazz) { 535 536 if (clazz.isInterface() || !java.io.Serializable.class.isAssignableFrom(clazz)) 537 return kInterfaceHashCode; 538 539 540 long actualLong = ObjectStreamClassUtil_1_3.computeStructuralUID(false, clazz); 541 String hash = null; 542 if (actualLong == 0) 543 hash = kInterfaceOnlyHashStr; 544 else if (actualLong == 1) 545 hash = kExternalizableHashStr; 546 else 547 hash = Long.toHexString(actualLong).toUpperCase(); 548 while(hash.length() < 16){ 549 hash = "0" + hash; 550 } 551 552 long declaredLong = ObjectStreamClassUtil_1_3.computeSerialVersionUID(clazz); 553 String declared = null; 554 if (declaredLong == 0) 555 declared = kInterfaceOnlyHashStr; 556 else if (declaredLong == 1) 557 declared = kExternalizableHashStr; 558 else 559 declared = Long.toHexString(declaredLong).toUpperCase(); 560 while (declared.length() < 16){ 561 declared = "0" + declared; 562 } 563 hash = hash + ":" + declared; 564 565 return ":" + hash; 566 } 567 568 /** 569 * Creates a repository ID for a sequence. This is for expert users only as 570 * this method assumes the object passed is an array. If passed an object 571 * that is not an array, it will produce a rep id for a sequence of zero 572 * length. This would be an error. 573 * @param ser The Java object to create a repository ID for 574 **/ 575 public static String createSequenceRepID(java.lang.Object ser){ 576 return createSequenceRepID(ser.getClass()); 577 } 578 579 /** 580 * Creates a repository ID for a sequence. This is for expert users only as 581 * this method assumes the object passed is an array. If passed an object 582 * that is not an array, it will produce a malformed rep id. 583 * @param clazz The Java class to create a repository ID for 584 **/ 585 public static String createSequenceRepID(java.lang.Class clazz){ 586 synchronized (classSeqToRepStr){ 587 588 String repid = (String)classSeqToRepStr.get(clazz); 589 if (repid != null) 590 return repid; 591 592 Class originalClazz = clazz; 593 594 Class type = null; 595 int numOfDims = 0; 596 597 while ((type = clazz.getComponentType()) != null) { 598 numOfDims++; 599 clazz = type; 600 } 601 602 if (clazz.isPrimitive()) 603 repid = kValuePrefix + originalClazz.getName() + kPrimitiveSequenceValueHash; 604 else { 605 StringBuffer buf = new StringBuffer(); 606 buf.append(kValuePrefix); 607 while(numOfDims-- > 0) { 608 buf.append("["); 609 } 610 buf.append("L"); 611 buf.append(convertToISOLatin1(clazz.getName())); 612 buf.append(";"); 613 buf.append(createHashString(clazz)); 614 repid = buf.toString(); 615 } 616 classSeqToRepStr.put(originalClazz,repid); 617 return repid; 618 } 619 620 } 621 622 623 public static String createForSpecialCase(java.lang.Class clazz){ 624 if (clazz.isArray()){ 625 return createSequenceRepID(clazz); 626 } 627 else { 628 return (String)kSpecialCasesRepIDs.get(clazz); 629 } 630 } 631 632 public static String createForSpecialCase(java.io.Serializable ser){ 633 Class clazz = ser.getClass(); 634 if (clazz.isArray()){ 635 return createSequenceRepID(ser); 636 } 637 else 638 return createForSpecialCase(clazz); 639 } 640 641 /** 642 * Creates a repository ID for a normal Java Type. 643 * @param ser The Java object to create a repository ID for 644 * @exception com.sun.corba.se.impl.io.TypeMismatchException if ser implements the 645 * org.omg.CORBA.portable.IDLEntity interface which indicates it is an IDL Value type. 646 **/ 647 public static String createForJavaType(java.io.Serializable ser) 648 throws com.sun.corba.se.impl.io.TypeMismatchException 649 { 650 synchronized (classToRepStr) { 651 String repid = createForSpecialCase(ser); 652 if (repid != null) 653 return repid; 654 Class clazz = ser.getClass(); 655 repid = (String)classToRepStr.get(clazz); 656 657 if (repid != null) 658 return repid; 659 660 repid = kValuePrefix + convertToISOLatin1(clazz.getName()) + 661 createHashString(clazz); 662 663 classToRepStr.put(clazz, repid); 664 repStrToClass.put(repid, clazz); 665 return repid; 666 } 667 } 668 669 /** 670 * Creates a repository ID for a normal Java Type. 671 * @param clz The Java class to create a repository ID for 672 * @exception com.sun.corba.se.impl.io.TypeMismatchException if ser implements the 673 * org.omg.CORBA.portable.IDLEntity interface which indicates it is an IDL Value type. 674 **/ 675 public static String createForJavaType(Class clz) 676 throws com.sun.corba.se.impl.io.TypeMismatchException 677 { 678 synchronized (classToRepStr){ 679 String repid = createForSpecialCase(clz); 680 if (repid != null) 681 return repid; 682 683 repid = (String)classToRepStr.get(clz); 684 if (repid != null) 685 return repid; 686 687 repid = kValuePrefix + convertToISOLatin1(clz.getName()) + 688 createHashString(clz); 689 690 classToRepStr.put(clz, repid); 691 repStrToClass.put(repid, clz); 692 return repid; 693 } 694 } 695 696 /** 697 * Creates a repository ID for an IDL Java Type. 698 * @param ser The IDL Value object to create a repository ID for 699 * @param major The major version number 700 * @param minor The minor version number 701 * @exception com.sun.corba.se.impl.io.TypeMismatchException if ser does not implement the 702 * org.omg.CORBA.portable.IDLEntity interface which indicates it is an IDL Value type. 703 **/ 704 public static String createForIDLType(Class ser, int major, int minor) 705 throws com.sun.corba.se.impl.io.TypeMismatchException 706 { 707 synchronized (classIDLToRepStr){ 708 String repid = (String)classIDLToRepStr.get(ser); 709 if (repid != null) 710 return repid; 711 712 repid = kIDLPrefix + convertToISOLatin1(ser.getName()).replace('.','/') + 713 ":" + major + "." + minor; 714 classIDLToRepStr.put(ser, repid); 715 return repid; 716 } 717 } 718 719 private static String getIdFromHelper(Class clazz){ 720 try { 721 Class helperClazz = Utility.loadClassForClass(clazz.getName()+"Helper", null, 722 clazz.getClassLoader(), clazz, clazz.getClassLoader()); 723 Method idMethod = helperClazz.getDeclaredMethod("id", kNoParamTypes); 724 return (String)idMethod.invoke(null, kNoArgs); 725 } 726 catch(java.lang.ClassNotFoundException cnfe) 727 { 728 throw new org.omg.CORBA.MARSHAL(cnfe.toString()); 729 } 730 catch(java.lang.NoSuchMethodException nsme) 731 { 732 throw new org.omg.CORBA.MARSHAL(nsme.toString()); 733 } 734 catch(java.lang.reflect.InvocationTargetException ite) 735 { 736 throw new org.omg.CORBA.MARSHAL(ite.toString()); 737 } 738 catch(java.lang.IllegalAccessException iae) 739 { 740 throw new org.omg.CORBA.MARSHAL(iae.toString()); 741 } 742 } 743 744 /** 745 * Createa a repository ID for the type if it is either a java type 746 * or an IDL type. 747 * @param type The type to create rep. id for 748 * @return The rep. id. 749 **/ 750 public static String createForAnyType(Class type) { 751 try{ 752 if (type.isArray()) 753 return createSequenceRepID(type); 754 else if (IDLEntity.class.isAssignableFrom(type)) 755 { 756 try{ 757 return getIdFromHelper(type); 758 } 759 catch(Throwable t) { 760 return createForIDLType(type, 1, 0); 761 } 762 } 763 else return createForJavaType(type); 764 } 765 catch(com.sun.corba.se.impl.io.TypeMismatchException e){ 766 return null; 767 } 768 769 } 770 771 public static boolean isAbstractBase(Class clazz) { 772 return (clazz.isInterface() && 773 IDLEntity.class.isAssignableFrom(clazz) && 774 (!ValueBase.class.isAssignableFrom(clazz)) && 775 (!org.omg.CORBA.Object.class.isAssignableFrom(clazz))); 776 777 } 778 779 /** 780 * Convert strings with illegal IDL identifier characters. 781 * <p> 782 * Section 5.5.7 of OBV spec. 783 */ 784 private static String convertToISOLatin1 (String name) { 785 786 int length = name.length(); 787 if (length == 0) { 788 return name; 789 } 790 StringBuffer buffer = null; 791 792 for (int i = 0; i < length; i++) { 793 794 char c = name.charAt(i); 795 796 if (c > 255 || IDL_IDENTIFIER_CHARS[c] == 0) { 797 798 // We gotta convert. Have we already started? 799 800 if (buffer == null) { 801 802 // No, so get set up... 803 804 buffer = new StringBuffer(name.substring(0,i)); 805 } 806 807 // Convert the character into the IDL escape syntax... 808 buffer.append( 809 "\\U" + 810 (char)ASCII_HEX[(c & 0xF000) >>> 12] + 811 (char)ASCII_HEX[(c & 0x0F00) >>> 8] + 812 (char)ASCII_HEX[(c & 0x00F0) >>> 4] + 813 (char)ASCII_HEX[(c & 0x000F)]); 814 815 } else { 816 if (buffer != null) { 817 buffer.append(c); 818 } 819 } 820 } 821 822 if (buffer != null) { 823 name = buffer.toString(); 824 } 825 826 return name; 827 } 828 829 /** 830 * Convert strings with ISO Latin 1 escape sequences back to original strings. 831 * <p> 832 * Section 5.5.7 of OBV spec. 833 */ 834 private static String convertFromISOLatin1 (String name) { 835 836 int index = -1; 837 StringBuffer buf = new StringBuffer(name); 838 839 while ((index = buf.toString().indexOf("\\U")) != -1){ 840 String str = "0000" + buf.toString().substring(index+2, index+6); 841 842 // Convert Hexadecimal 843 byte[] buffer = new byte[(str.length() - 4) / 2]; 844 for (int i=4, j=0; i < str.length(); i +=2, j++) { 845 buffer[j] = (byte)((ORBUtility.hexOf(str.charAt(i)) << 4) & 0xF0); 846 buffer[j] |= (byte)((ORBUtility.hexOf(str.charAt(i+1)) << 0) & 0x0F); 847 } 848 buf = new StringBuffer(delete(buf.toString(), index, index+6)); 849 buf.insert(index, (char)buffer[1]); 850 } 851 852 return buf.toString(); 853 854 855 } 856 857 private static String delete(String str, int from, int to) 858 { 859 return str.substring(0, from) + str.substring(to, str.length()); 860 } 861 862 private static String replace(String target, String arg, String source) 863 { 864 int i = 0; 865 i = target.indexOf(arg); 866 867 while(i != -1) 868 { 869 String left = target.substring(0, i); 870 String right = target.substring(i+arg.length()); 871 target = new String(left+source+right); 872 i = target.indexOf(arg); 873 } 874 return target; 875 } 876 877 /* 878 * Load a class and check that it is assignable to a given type. 879 * @param className the class name. 880 * @param remoteCodebase the codebase to use. May be null. 881 * @param loader the class loader of last resort. May be null. 882 * @param expectedType the expected type. May be null. 883 * @return the loaded class. 884 */ 885 private Class loadClassOfType (String className, 886 String remoteCodebase, 887 ClassLoader loader, 888 Class expectedType, 889 ClassLoader expectedTypeClassLoader) 890 throws ClassNotFoundException { 891 892 Class loadedClass = null; 893 894 try { 895 //Sequence finding of the stubs according to spec 896 try{ 897 //If-else is put here for speed up of J2EE. 898 //According to the OMG spec, the if clause is not dead code. 899 //It can occur if some compiler has allowed generation 900 //into org.omg.stub hierarchy for non-offending 901 //classes. This will encourage people to 902 //produce non-offending class stubs in their own hierarchy. 903 if(!PackagePrefixChecker 904 .hasOffendingPrefix(PackagePrefixChecker 905 .withoutPackagePrefix(className))){ 906 loadedClass = Util.loadClass 907 (PackagePrefixChecker.withoutPackagePrefix(className), 908 remoteCodebase, 909 loader); 910 } else { 911 loadedClass = Util.loadClass 912 (className, 913 remoteCodebase, 914 loader); 915 } 916 } catch (ClassNotFoundException cnfe) { 917 loadedClass = Util.loadClass 918 (className, 919 remoteCodebase, 920 loader); 921 } 922 if (expectedType == null) 923 return loadedClass; 924 } catch (ClassNotFoundException cnfe) { 925 if (expectedType == null) 926 throw cnfe; 927 } 928 929 // If no class was not loaded, or if the loaded class is not of the 930 // correct type, make a further attempt to load the correct class 931 // using the classloader of the expected type. 932 // _REVISIT_ Is this step necessary, or should the Util,loadClass 933 // algorithm always produce a valid class if the setup is correct? 934 // Does the OMG standard algorithm need to be changed to include 935 // this step? 936 if (loadedClass == null || !expectedType.isAssignableFrom(loadedClass)) { 937 if (expectedType.getClassLoader() != expectedTypeClassLoader) 938 throw new IllegalArgumentException("expectedTypeClassLoader not class loader of expectedType."); 939 940 if (expectedTypeClassLoader != null) 941 loadedClass = expectedTypeClassLoader.loadClass(className); 942 else 943 loadedClass = ORBClassLoader.loadClass(className); 944 } 945 946 return loadedClass; 947 } 948 949 /** 950 * Checks to see if the FullValueDescription should be retrieved. 951 * @exception Throws IOException if suids do not match or if the repositoryID 952 * is not an RMIValueType 953 */ 954 public static boolean useFullValueDescription(Class clazz, String repositoryID) 955 throws IOException{ 956 957 String clazzRepIDStr = createForAnyType(clazz); 958 959 if (clazzRepIDStr.equals(repositoryID)) 960 return false; 961 962 RepositoryId_1_3 targetRepid; 963 RepositoryId_1_3 clazzRepid; 964 965 synchronized(cache) { 966 // to avoid race condition where multiple threads could be 967 // accessing this method, and their access to the cache may 968 // be interleaved giving unexpected results 969 970 targetRepid = cache.getId(repositoryID); 971 clazzRepid = cache.getId(clazzRepIDStr); 972 } 973 974 if ((targetRepid.isRMIValueType()) && (clazzRepid.isRMIValueType())){ 975 if (!targetRepid.getSerialVersionUID().equals(clazzRepid.getSerialVersionUID())) { 976 977 String mssg = "Mismatched serialization UIDs : Source (Rep. ID" + 978 clazzRepid + ") = " + 979 clazzRepid.getSerialVersionUID() + " whereas Target (Rep. ID " + repositoryID + 980 ") = " + targetRepid.getSerialVersionUID(); 981 throw new IOException(mssg); 982 } else { 983 return true; 984 } 985 } else { 986 987 throw new IOException("The repository ID is not of an RMI value type (Expected ID = " + clazzRepIDStr + "; Received ID = " + repositoryID +")"); 988 } 989 } 990 }