RepositoryId.java revision 608:7e06bf1dcb09
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
32package com.sun.corba.se.impl.util;
33
34import java.util.StringTokenizer;
35import java.util.Hashtable;
36import java.io.IOException;
37import java.lang.reflect.Method;
38
39// Imports for using codebase URL to load class
40import java.net.MalformedURLException;
41import org.omg.CORBA.portable.ValueBase;
42import 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;
47import com.sun.corba.se.impl.io.ObjectStreamClass;
48
49import javax.rmi.CORBA.Util;
50
51public 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}
994