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