Fri, 24 Sep 2010 22:42:14 -0700
6891766: Vulnerabilities in use of reflection in CORBA
Reviewed-by: hawtin
1 /*
2 * Copyright (c) 2001, 2002, 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 */
26 /*
27 */
28 package com.sun.corba.se.impl.orbutil;
30 import java.util.StringTokenizer;
31 import java.util.Hashtable;
32 import java.io.IOException;
33 import java.lang.reflect.Method;
34 import java.net.MalformedURLException;
35 import org.omg.CORBA.portable.ValueBase;
36 import org.omg.CORBA.portable.IDLEntity;
38 //d11638 files in the same package, therefore remove their reference
39 //import com.sun.corba.se.impl.util.JDKBridge;
40 //import com.sun.corba.se.impl.util.IdentityHashtable;
41 import com.sun.corba.se.impl.util.JDKBridge;
42 import com.sun.corba.se.impl.util.Utility;
43 import com.sun.corba.se.impl.util.PackagePrefixChecker;
44 import com.sun.corba.se.impl.util.IdentityHashtable;
46 import javax.rmi.CORBA.Util;
48 /**
49 * Because all methods in RepositoryId are static, we have
50 * to duplicate all of this code, freezing it in its 1.3.1
51 * form for backwards compatibility.
52 *
53 * For security reasons, we can't expose enough of
54 * io/ObjectStreamClass, so it has to be duplicated in
55 * orbutil.
56 */
57 public class RepositoryId_1_3_1 {
59 // Legal IDL Identifier characters (1 = legal). Note
60 // that '.' (2E) is marked as legal even though it is
61 // not legal in IDL. This allows us to treat a fully
62 // qualified Java name with '.' package separators
63 // uniformly, and is safe because that is the only
64 // legal use of '.' in a Java name.
66 public static final byte[] IDL_IDENTIFIER_CHARS = {
68 // 0 1 2 3 4 5 6 7 8 9 a b c d e f
69 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, // 00-0f
70 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, // 10-1f
71 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,1,0, // 20-2f
72 1,1,1,1, 1,1,1,1, 1,1,0,0, 0,0,0,0, // 30-3f
73 0,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1, // 40-4f
74 1,1,1,1, 1,1,1,1, 1,1,1,0, 0,0,0,1, // 50-5f
75 0,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1, // 60-6f
76 1,1,1,1, 1,1,1,1, 1,1,1,0, 0,0,0,0, // 70-7f
77 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, // 80-8f
78 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, // 90-9f
79 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, // a0-af
80 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, // b0-bf
81 1,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1, // c0-cf
82 0,1,1,1, 1,1,1,0, 1,1,1,1, 1,0,0,1, // d0-df
83 1,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1, // e0-ef
84 0,1,1,1, 1,1,1,0, 1,1,1,1, 1,0,0,1, // f0-ff
85 };
88 private static final long serialVersionUID = 123456789L;
90 private static String defaultServerURL = null;
91 private static boolean useCodebaseOnly = false;
93 static {
94 if (defaultServerURL == null)
95 defaultServerURL = (String)JDKBridge.getLocalCodebase();
96 useCodebaseOnly = JDKBridge.useCodebaseOnly();
98 }
100 private static IdentityHashtable classToRepStr = new IdentityHashtable();
101 private static IdentityHashtable classIDLToRepStr = new IdentityHashtable();
102 private static IdentityHashtable classSeqToRepStr = new IdentityHashtable();
104 private static IdentityHashtable repStrToByteArray = new IdentityHashtable();
105 private static Hashtable repStrToClass = new Hashtable();
107 private String repId = null;
108 private boolean isSupportedFormat = true;
109 private String typeString = null;
110 private String versionString = null;
111 private boolean isSequence = false;
112 private boolean isRMIValueType = false;
113 private boolean isIDLType = false;
114 private String completeClassName = null;
115 private String unqualifiedName = null;
116 private String definedInId = null;
117 private Class clazz = null;
118 private String suid = null, actualSuid = null;
119 private long suidLong = ObjectStreamClass_1_3_1.kDefaultUID, actualSuidLong = ObjectStreamClass_1_3_1.kDefaultUID;
121 // Repository ID fragments
122 private static final String kSequenceKeyword = "seq";
123 private static final String kValuePrefix = "RMI:";
124 private static final String kIDLPrefix = "IDL:";
125 private static final String kIDLNamePrefix = "omg.org/";
126 private static final String kIDLClassnamePrefix = "org.omg.";
127 private static final String kSequencePrefix = "[";
128 private static final String kCORBAPrefix = "CORBA/";
129 private static final String kArrayPrefix = kValuePrefix + kSequencePrefix + kCORBAPrefix;
130 private static final int kValuePrefixLength = kValuePrefix.length();
131 private static final int kIDLPrefixLength = kIDLPrefix.length();
132 private static final int kSequencePrefixLength = kSequencePrefix.length();
133 private static final String kInterfaceHashCode = ":0000000000000000";
134 private static final String kInterfaceOnlyHashStr = "0000000000000000";
135 private static final String kExternalizableHashStr = "0000000000000001";
137 // Value tag utility methods and constants
138 public static final int kInitialValueTag= 0x7fffff00;
139 public static final int kNoTypeInfo = 0;
140 public static final int kSingleRepTypeInfo = 0x02;
141 public static final int kPartialListTypeInfo = 0x06;
142 public static final int kChunkedMask = 0x08;
143 public static final int kPreComputed_StandardRMIUnchunked = RepositoryId_1_3_1.computeValueTag(false, RepositoryId_1_3_1.kSingleRepTypeInfo, false);
144 public static final int kPreComputed_CodeBaseRMIUnchunked = RepositoryId_1_3_1.computeValueTag(true, RepositoryId_1_3_1.kSingleRepTypeInfo, false);
145 public static final int kPreComputed_StandardRMIChunked = RepositoryId_1_3_1.computeValueTag(false, RepositoryId_1_3_1.kSingleRepTypeInfo, true);
146 public static final int kPreComputed_CodeBaseRMIChunked = RepositoryId_1_3_1.computeValueTag(true, RepositoryId_1_3_1.kSingleRepTypeInfo, true);
148 public static final int kPreComputed_StandardRMIUnchunked_NoRep = RepositoryId_1_3_1.computeValueTag(false, RepositoryId_1_3_1.kNoTypeInfo, false);
149 public static final int kPreComputed_CodeBaseRMIUnchunked_NoRep = RepositoryId_1_3_1.computeValueTag(true, RepositoryId_1_3_1.kNoTypeInfo, false);
150 public static final int kPreComputed_StandardRMIChunked_NoRep = RepositoryId_1_3_1.computeValueTag(false, RepositoryId_1_3_1.kNoTypeInfo, true);
151 public static final int kPreComputed_CodeBaseRMIChunked_NoRep = RepositoryId_1_3_1.computeValueTag(true, RepositoryId_1_3_1.kNoTypeInfo, true);
153 // Public, well known repository IDs
155 // _REVISIT_ : A table structure with a good search routine for all of this
156 // would be more efficient and easier to maintain...
158 // String
159 public static final String kWStringValueVersion = "1.0";
160 public static final String kWStringValueHash = ":"+kWStringValueVersion;
161 public static final String kWStringStubValue = "WStringValue";
162 public static final String kWStringTypeStr = "omg.org/CORBA/"+kWStringStubValue;
163 public static final String kWStringValueRepID = kIDLPrefix + kWStringTypeStr + kWStringValueHash;
165 // Any
166 public static final String kAnyRepID = kIDLPrefix + "omg.org/CORBA/Any";
168 // Class
169 // Anita4: convert to uppercase
170 public static final String kClassDescValueHash = ":" +
171 Long.toHexString(
172 ObjectStreamClass_1_3_1.getActualSerialVersionUID(javax.rmi.CORBA.ClassDesc.class)).toUpperCase() + ":" +
173 Long.toHexString(
174 ObjectStreamClass_1_3_1.getSerialVersionUID(javax.rmi.CORBA.ClassDesc.class)).toUpperCase();
175 public static final String kClassDescStubValue = "ClassDesc";
176 public static final String kClassDescTypeStr = "javax.rmi.CORBA."+kClassDescStubValue;
177 public static final String kClassDescValueRepID = kValuePrefix + kClassDescTypeStr + kClassDescValueHash;
179 // Object
180 public static final String kObjectValueHash = ":1.0";
181 public static final String kObjectStubValue = "Object";
183 // Sequence
184 public static final String kSequenceValueHash = ":1.0";
185 public static final String kPrimitiveSequenceValueHash = ":0000000000000000";
187 // Serializable
188 public static final String kSerializableValueHash = ":1.0";
189 public static final String kSerializableStubValue = "Serializable";
191 // Externalizable
192 public static final String kExternalizableValueHash = ":1.0";
193 public static final String kExternalizableStubValue = "Externalizable";
195 // Remote (The empty string is used for java.rmi.Remote)
196 public static final String kRemoteValueHash = "";
197 public static final String kRemoteStubValue = "";
198 public static final String kRemoteTypeStr = "";
199 public static final String kRemoteValueRepID = "";
201 public static final Hashtable kSpecialArrayTypeStrings = new Hashtable();
203 static {
204 kSpecialArrayTypeStrings.put("CORBA.WStringValue", new StringBuffer(java.lang.String.class.getName()));
205 kSpecialArrayTypeStrings.put("javax.rmi.CORBA.ClassDesc", new StringBuffer(java.lang.Class.class.getName()));
206 kSpecialArrayTypeStrings.put("CORBA.Object", new StringBuffer(java.rmi.Remote.class.getName()));
208 }
210 public static final Hashtable kSpecialCasesRepIDs = new Hashtable();
212 static {
213 kSpecialCasesRepIDs.put(java.lang.String.class, kWStringValueRepID);
214 kSpecialCasesRepIDs.put(java.lang.Class.class, kClassDescValueRepID);
215 kSpecialCasesRepIDs.put(java.rmi.Remote.class, kRemoteValueRepID);
216 }
218 public static final Hashtable kSpecialCasesStubValues = new Hashtable();
220 static {
221 kSpecialCasesStubValues.put(java.lang.String.class, kWStringStubValue);
222 kSpecialCasesStubValues.put(java.lang.Class.class, kClassDescStubValue);
223 kSpecialCasesStubValues.put(java.lang.Object.class, kObjectStubValue);
224 kSpecialCasesStubValues.put(java.io.Serializable.class, kSerializableStubValue);
225 kSpecialCasesStubValues.put(java.io.Externalizable.class, kExternalizableStubValue);
226 kSpecialCasesStubValues.put(java.rmi.Remote.class, kRemoteStubValue);
227 }
230 public static final Hashtable kSpecialCasesVersions = new Hashtable();
232 static {
233 kSpecialCasesVersions.put(java.lang.String.class, kWStringValueHash);
234 kSpecialCasesVersions.put(java.lang.Class.class, kClassDescValueHash);
235 kSpecialCasesVersions.put(java.lang.Object.class, kObjectValueHash);
236 kSpecialCasesVersions.put(java.io.Serializable.class, kSerializableValueHash);
237 kSpecialCasesVersions.put(java.io.Externalizable.class, kExternalizableValueHash);
238 kSpecialCasesVersions.put(java.rmi.Remote.class, kRemoteValueHash);
239 }
241 public static final Hashtable kSpecialCasesClasses = new Hashtable();
243 static {
244 kSpecialCasesClasses.put(kWStringTypeStr, java.lang.String.class);
245 kSpecialCasesClasses.put(kClassDescTypeStr, java.lang.Class.class);
246 kSpecialCasesClasses.put(kRemoteTypeStr, java.rmi.Remote.class);
248 kSpecialCasesClasses.put("org.omg.CORBA.WStringValue", java.lang.String.class);
249 kSpecialCasesClasses.put("javax.rmi.CORBA.ClassDesc", java.lang.Class.class);
250 //kSpecialCasesClasses.put(kRemoteTypeStr, java.rmi.Remote.class);
251 }
253 public static final Hashtable kSpecialCasesArrayPrefix = new Hashtable();
255 static {
256 kSpecialCasesArrayPrefix.put(java.lang.String.class, kValuePrefix + kSequencePrefix + kCORBAPrefix);
257 kSpecialCasesArrayPrefix.put(java.lang.Class.class, kValuePrefix + kSequencePrefix + "javax/rmi/CORBA/");
258 kSpecialCasesArrayPrefix.put(java.lang.Object.class, kValuePrefix + kSequencePrefix + "java/lang/");
259 kSpecialCasesArrayPrefix.put(java.io.Serializable.class, kValuePrefix + kSequencePrefix + "java/io/");
260 kSpecialCasesArrayPrefix.put(java.io.Externalizable.class, kValuePrefix + kSequencePrefix + "java/io/");
261 kSpecialCasesArrayPrefix.put(java.rmi.Remote.class, kValuePrefix + kSequencePrefix + kCORBAPrefix);
262 }
264 public static final Hashtable kSpecialPrimitives = new Hashtable();
266 static {
267 kSpecialPrimitives.put("int","long");
268 kSpecialPrimitives.put("long","longlong");
269 kSpecialPrimitives.put("byte","octet");
270 }
272 /**
273 * Used to convert ascii to hex.
274 */
275 private static final byte ASCII_HEX[] = {
276 (byte)'0',
277 (byte)'1',
278 (byte)'2',
279 (byte)'3',
280 (byte)'4',
281 (byte)'5',
282 (byte)'6',
283 (byte)'7',
284 (byte)'8',
285 (byte)'9',
286 (byte)'A',
287 (byte)'B',
288 (byte)'C',
289 (byte)'D',
290 (byte)'E',
291 (byte)'F',
292 };
295 // bug fix for 4328952; to eliminate possibility of overriding this
296 // in a subclass.
297 public static final RepositoryIdCache_1_3_1 cache = new RepositoryIdCache_1_3_1();
299 // Interface Rep ID Strings
300 public static final String kjava_rmi_Remote = createForAnyType(java.rmi.Remote.class);
301 public static final String korg_omg_CORBA_Object = createForAnyType(org.omg.CORBA.Object.class);
303 // Dummy arguments for getIdFromHelper method
304 public static final Class kNoParamTypes[] ={};
305 public static final Object kNoArgs[] = {};
308 // To create a RepositoryID, use code similar to the following:
309 // RepositoryId.cache.getId( id );
311 RepositoryId_1_3_1(){}
313 RepositoryId_1_3_1(String aRepId){
314 init(aRepId);
315 }
317 RepositoryId_1_3_1 init(String aRepId){
319 this.repId = aRepId;
321 // Special case for remote
322 if (aRepId.length() == 0) {
323 clazz = java.rmi.Remote.class;
324 typeString = "";
325 isRMIValueType = true;
326 suid = kInterfaceOnlyHashStr;
327 return this;
328 }
329 else if (aRepId.equals(kWStringValueRepID)) {
330 clazz = java.lang.String.class;
331 typeString = kWStringTypeStr;
332 isIDLType = true;
333 // fix where Attempting to obtain a FullValueDescription
334 // for an RMI value type with a String field causes an exception.
335 completeClassName = "java.lang.String";
336 versionString = kWStringValueVersion;
337 return this;
338 }
339 else {
341 String repId = convertFromISOLatin1(aRepId);
343 versionString = repId.substring(repId.indexOf(':', repId.indexOf(':')+1));
344 if (repId.startsWith(kIDLPrefix)) {
345 typeString =
346 repId.substring(kIDLPrefixLength, repId.indexOf(':', kIDLPrefixLength));
347 isIDLType = true;
348 if (typeString.startsWith(kIDLNamePrefix))
349 completeClassName = kIDLClassnamePrefix +
350 typeString.substring(kIDLNamePrefix.length()).replace('/','.');
351 else completeClassName = typeString.replace('/','.');
353 }
354 else if (repId.startsWith(kValuePrefix)) {
355 typeString =
356 repId.substring(kValuePrefixLength, repId.indexOf(':', kValuePrefixLength));
357 isRMIValueType = true;
359 if (versionString.indexOf('.') == -1) {
360 actualSuid = versionString.substring(1);
361 suid = actualSuid; // default if not explicitly specified
363 if (actualSuid.indexOf(':') != -1){
364 // we have a declared hash also
365 int pos = actualSuid.indexOf(':')+1;
366 // actualSuid = suid.substring(pos);
367 // suid = suid.substring(0, pos-1);
368 suid = actualSuid.substring(pos);
369 actualSuid = actualSuid.substring(0, pos-1);
370 }
372 }
373 else {
374 // _REVISIT_ : Special case version failure ?
375 }
376 }
377 else isSupportedFormat = false;
379 if (typeString.startsWith(kSequencePrefix)) {
380 isSequence = true;
381 }
384 return this;
385 }
386 }
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 }
402 return unqualifiedName;
403 }
405 public final String getDefinedInId() {
406 if (definedInId == null){
407 getUnqualifiedName();
408 }
410 return definedInId;
411 }
413 public final String getTypeString() {
414 return typeString;
415 }
417 public final String getVersionString() {
418 return versionString;
419 }
421 public final String getSerialVersionUID() {
422 return suid;
423 }
425 public final String getActualSerialVersionUID() {
426 return actualSuid;
427 }
428 public final long getSerialVersionUIDAsLong() {
429 return suidLong;
430 }
432 public final long getActualSerialVersionUIDAsLong() {
433 return actualSuidLong;
434 }
436 public final boolean isRMIValueType() {
437 return isRMIValueType;
438 }
440 public final boolean isIDLType() {
441 return isIDLType;
442 }
444 public final String getRepositoryId() {
445 return repId;
446 }
448 public static byte[] getByteArray(String repStr) {
449 synchronized (repStrToByteArray){
450 return (byte[]) repStrToByteArray.get(repStr);
451 }
452 }
454 public static void setByteArray(String repStr, byte[] repStrBytes) {
455 synchronized (repStrToByteArray){
456 repStrToByteArray.put(repStr, repStrBytes);
457 }
458 }
460 public final boolean isSequence() {
461 return isSequence;
462 }
464 public final boolean isSupportedFormat() {
465 return isSupportedFormat;
466 }
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() {
473 if (isRMIValueType)
474 return typeString;
475 else if (isIDLType)
476 return completeClassName;
477 else return null;
479 }
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 }
496 public final Class getClassFromType()
497 throws ClassNotFoundException {
498 if (clazz != null)
499 return clazz;
501 Class specialCase = (Class)kSpecialCasesClasses.get(getClassName());
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 }
525 }
527 public final Class getClassFromType(Class expectedType, String codebase)
528 throws ClassNotFoundException {
529 if (clazz != null)
530 return clazz;
532 Class specialCase = (Class)kSpecialCasesClasses.get(getClassName());
534 if (specialCase != null){
535 clazz = specialCase;
536 return specialCase;
537 } else {
538 ClassLoader expectedTypeClassLoader = (expectedType == null ? null : expectedType.getClassLoader());
539 return loadClassOfType(getClassName(),
540 codebase,
541 expectedTypeClassLoader,
542 expectedType,
543 expectedTypeClassLoader);
544 }
546 }
548 public final Class getClassFromType(String url)
549 throws ClassNotFoundException, MalformedURLException {
550 return Util.loadClass(getClassName(), url, null);
551 }
553 public final String toString() {
554 return repId;
555 }
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{
565 String clazzRepIDStr = createForAnyType(clazz);
567 if (clazzRepIDStr.equals(repositoryID))
568 return false;
570 RepositoryId_1_3_1 targetRepid;
571 RepositoryId_1_3_1 clazzRepid;
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
578 targetRepid = cache.getId(repositoryID);
579 clazzRepid = cache.getId(clazzRepIDStr);
580 }
581 //ObjectStreamClass osc = ObjectStreamClass.lookup(clazz);
583 if ((targetRepid.isRMIValueType()) && (clazzRepid.isRMIValueType())){
584 if (!targetRepid.getSerialVersionUID().equals(clazzRepid.getSerialVersionUID())) {
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 {
599 throw new IOException("The repository ID is not of an RMI value type (Expected ID = " + clazzRepIDStr + "; Received ID = " + repositoryID +")");
600 }
601 }
603 private static String createHashString(java.io.Serializable ser) {
605 return createHashString(ser.getClass());
606 }
608 private static String createHashString(java.lang.Class clazz) {
610 if (clazz.isInterface() || !java.io.Serializable.class.isAssignableFrom(clazz))
611 return kInterfaceHashCode;
613 //ObjectStreamClass osc = ObjectStreamClass.lookup(clazz);
615 long actualLong = ObjectStreamClass_1_3_1.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 }
627 long declaredLong = ObjectStreamClass_1_3_1.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;
640 return ":" + hash;
641 }
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 }
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){
663 String repid = (String)classSeqToRepStr.get(clazz);
664 if (repid != null)
665 return repid;
667 Class originalClazz = clazz;
669 Class type = null;
670 int numOfDims = 0;
672 while ((type = clazz.getComponentType()) != null) {
673 numOfDims++;
674 clazz = type;
675 }
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 }
695 }
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 }
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 }
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);
732 if (repid != null)
733 return repid;
735 repid = kValuePrefix + convertToISOLatin1(clazz.getName()) +
736 createHashString(clazz);
738 classToRepStr.put(clazz, repid);
739 repStrToClass.put(repid, clazz);
740 return repid;
741 }
742 }
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;
758 repid = (String)classToRepStr.get(clz);
759 if (repid != null)
760 return repid;
762 repid = kValuePrefix + convertToISOLatin1(clz.getName()) +
763 createHashString(clz);
765 classToRepStr.put(clz, repid);
766 repStrToClass.put(repid, clz);
767 return repid;
768 }
769 }
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;
787 repid = kIDLPrefix + convertToISOLatin1(ser.getName()).replace('.','/') +
788 ":" + major + "." + minor;
789 classIDLToRepStr.put(ser, repid);
790 return repid;
791 }
792 }
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 }
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 }
844 }
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)));
852 }
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 }
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 }
866 /**
867 * Convert strings with illegal IDL identifier characters.
868 * <p>
869 * Section 5.5.7 of OBV spec.
870 */
871 private static String convertToISOLatin1 (String name) {
873 int length = name.length();
874 if (length == 0) {
875 return name;
876 }
877 StringBuffer buffer = null;
879 for (int i = 0; i < length; i++) {
881 char c = name.charAt(i);
883 if (c > 255 || IDL_IDENTIFIER_CHARS[c] == 0) {
885 // We gotta convert. Have we already started?
887 if (buffer == null) {
889 // No, so get set up...
891 buffer = new StringBuffer(name.substring(0,i));
892 }
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)]);
902 } else {
903 if (buffer != null) {
904 buffer.append(c);
905 }
906 }
907 }
909 if (buffer != null) {
910 name = buffer.toString();
911 }
913 return name;
914 }
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) {
923 int index = -1;
924 StringBuffer buf = new StringBuffer(name);
926 while ((index = buf.toString().indexOf("\\U")) != -1){
927 String str = "0000" + buf.toString().substring(index+2, index+6);
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)((ORBUtility.hexOf(str.charAt(i)) << 4) & 0xF0);
933 buffer[j] |= (byte)((ORBUtility.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 }
939 return buf.toString();
942 }
944 private static String delete(String str, int from, int to)
945 {
946 return str.substring(0, from) + str.substring(to, str.length());
947 }
949 private static String replace(String target, String arg, String source)
950 {
951 int i = 0;
952 i = target.indexOf(arg);
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 }
964 public static int computeValueTag(boolean codeBasePresent, int typeInfo, boolean chunkedEncoding){
965 int value_tag = kInitialValueTag;
967 if (codeBasePresent)
968 value_tag = value_tag | 0x00000001;
970 value_tag = value_tag | typeInfo;
972 if (chunkedEncoding)
973 value_tag = value_tag | kChunkedMask;
975 return value_tag;
976 }
978 public static boolean isCodeBasePresent(int value_tag){
979 return ((value_tag & 0x00000001) == 1);
980 }
982 public static int getTypeInfo(int value_tag){
983 return (value_tag & 0x00000006);
984 }
986 public static boolean isChunkedEncoding(int value_tag){
987 return ((value_tag & kChunkedMask) != 0);
988 }
990 public static String getServerURL(){
991 return defaultServerURL;
992 }
994 /*
995 * Load a class and check that it is assignable to a given type.
996 * @param className the class name.
997 * @param remoteCodebase the codebase to use. May be null.
998 * @param loader the class loader of last resort. May be null.
999 * @param expectedType the expected type. May be null.
1000 * @return the loaded class.
1001 */
1002 private Class loadClassOfType (String className,
1003 String remoteCodebase,
1004 ClassLoader loader,
1005 Class expectedType,
1006 ClassLoader expectedTypeClassLoader)
1007 throws ClassNotFoundException {
1009 Class loadedClass = null;
1011 try {
1012 //Sequence finding of the stubs according to spec
1013 try{
1014 //If-else is put here for speed up of J2EE.
1015 //According to the OMG spec, the if clause is not dead code.
1016 //It can occur if some compiler has allowed generation
1017 //into org.omg.stub hierarchy for non-offending
1018 //classes. This will encourage people to
1019 //produce non-offending class stubs in their own hierarchy.
1020 if(!PackagePrefixChecker
1021 .hasOffendingPrefix(PackagePrefixChecker
1022 .withoutPackagePrefix(className))){
1023 loadedClass = Util.loadClass
1024 (PackagePrefixChecker.withoutPackagePrefix(className),
1025 remoteCodebase,
1026 loader);
1027 } else {
1028 loadedClass = Util.loadClass
1029 (className,
1030 remoteCodebase,
1031 loader);
1032 }
1033 } catch (ClassNotFoundException cnfe) {
1034 loadedClass = Util.loadClass
1035 (className,
1036 remoteCodebase,
1037 loader);
1038 }
1039 if (expectedType == null)
1040 return loadedClass;
1041 } catch (ClassNotFoundException cnfe) {
1042 if (expectedType == null)
1043 throw cnfe;
1044 }
1046 // If no class was not loaded, or if the loaded class is not of the
1047 // correct type, make a further attempt to load the correct class
1048 // using the classloader of the expected type.
1049 // _REVISIT_ Is this step necessary, or should the Util,loadClass
1050 // algorithm always produce a valid class if the setup is correct?
1051 // Does the OMG standard algorithm need to be changed to include
1052 // this step?
1053 if (loadedClass == null || !expectedType.isAssignableFrom(loadedClass)) {
1054 if (expectedType.getClassLoader() != expectedTypeClassLoader)
1055 throw new IllegalArgumentException("expectedTypeClassLoader not class loader of expectedType.");
1057 if (expectedTypeClassLoader != null)
1058 loadedClass = expectedTypeClassLoader.loadClass(className);
1059 else
1060 loadedClass = Class.forName(className);
1061 }
1063 return loadedClass;
1064 }
1065 }