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