1. /*
  2. * @(#)Utility.java 1.35 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.util;
  16. import org.omg.CORBA.SystemException;
  17. import org.omg.CORBA.CompletionStatus;
  18. import org.omg.CORBA.UserException;
  19. import org.omg.CORBA.TCKind;
  20. import org.omg.CORBA.UNKNOWN;
  21. import org.omg.CORBA.INTERNAL;
  22. import org.omg.CORBA.Any;
  23. import org.omg.CORBA.TypeCode;
  24. import org.omg.CORBA.Principal;
  25. import org.omg.CORBA.portable.InputStream;
  26. import org.omg.CORBA.portable.OutputStream;
  27. import org.omg.CORBA.portable.BoxedValueHelper;
  28. import org.omg.CORBA.portable.ValueFactory;
  29. import org.omg.CORBA.MARSHAL;
  30. import org.omg.CORBA.portable.Streamable;
  31. import java.util.Hashtable;
  32. import java.util.NoSuchElementException;
  33. import java.rmi.Remote;
  34. import org.omg.CORBA.ORB;
  35. import org.omg.CORBA.DATA_CONVERSION;
  36. import javax.rmi.PortableRemoteObject;
  37. import javax.rmi.CORBA.Stub;
  38. import javax.rmi.CORBA.Tie;
  39. import javax.rmi.CORBA.Util;
  40. import org.omg.CORBA.BAD_OPERATION;
  41. import org.omg.CORBA.BAD_PARAM;
  42. import org.omg.CORBA.portable.Delegate;
  43. import java.rmi.server.RemoteStub;
  44. import org.omg.CORBA.portable.ObjectImpl;
  45. import java.rmi.NoSuchObjectException;
  46. import org.omg.CORBA.INV_OBJREF;
  47. import com.sun.org.omg.SendingContext.CodeBase;
  48. import java.rmi.RemoteException;
  49. import java.io.Serializable;
  50. import java.io.File;
  51. import java.io.FileInputStream;
  52. import org.omg.PortableServer.POA;
  53. // import com.sun.corba.se.internal.util.RepositoryId; // d11638
  54. /**
  55. * Handy class full of static functions.
  56. */
  57. public final class Utility {
  58. public static final String STUB_PREFIX = "_";
  59. public static final String RMI_STUB_SUFFIX = "_Stub";
  60. public static final String IDL_STUB_SUFFIX = "Stub";
  61. public static final String TIE_SUFIX = "_Tie";
  62. public static final String STUB_PACKAGE_PREFIX = "org.omg.stub.";
  63. private static IdentityHashtable tieCache = new IdentityHashtable();
  64. private static IdentityHashtable tieToStubCache = new IdentityHashtable();
  65. private static IdentityHashtable stubToTieCache = new IdentityHashtable();
  66. private static Object CACHE_MISS = new Object();
  67. /**
  68. * Ensure that stubs, ties, and implementation objects
  69. * are 'connected' to the runtime. Converts implementation
  70. * objects to a type suitable for sending on the wire.
  71. * @param obj the object to connect.
  72. * @param orb the ORB to connect to if obj is exported to IIOP.
  73. * @param convertToStub true if implementation types should be
  74. * converted to Stubs rather than just org.omg.CORBA.Object.
  75. * @return the connected object.
  76. * @exception NoSuchObjectException if obj is an implementation
  77. * which has not been exported.
  78. */
  79. public static Object autoConnect(Object obj, ORB orb, boolean convertToStub) {
  80. // Is it null?
  81. if (obj == null) {
  82. // Yes, so just return it.
  83. return obj;
  84. }
  85. // Is it an RMI Stub?
  86. if (obj instanceof Stub) {
  87. // Yes, is it connected?
  88. Stub it = (Stub)obj;
  89. try {
  90. it._get_delegate();
  91. } catch (BAD_OPERATION okay) {
  92. // No, so do it...
  93. try {
  94. it.connect(orb);
  95. } catch (RemoteException e) {
  96. // The stub could not be connected because it
  97. // has an invalid IOR...
  98. throw new INV_OBJREF(obj.getClass().getName()+
  99. " did not originate from connected object");
  100. }
  101. }
  102. // Return the connected stub...
  103. return obj;
  104. }
  105. // Is it a Remote object?
  106. if (obj instanceof Remote) {
  107. // Yes. Is this an exported IIOP implemenation
  108. // object?
  109. Remote remoteObj = (Remote)obj;
  110. Tie theTie = Util.getTie(remoteObj);
  111. if (theTie != null) {
  112. // Yes, is it connected?
  113. try {
  114. theTie.orb();
  115. } catch (BAD_OPERATION okay) {
  116. // No, so do it...
  117. theTie.orb(orb);
  118. }
  119. if (convertToStub) {
  120. // Return a stub for this object...
  121. Object result = loadStub(theTie,null,null,true); // d10926
  122. if (result != null) {
  123. return result;
  124. } else {
  125. throw new INV_OBJREF("Could not load stub for "+
  126. obj.getClass().getName());
  127. }
  128. } else {
  129. // Return the result of calling thisObject()
  130. // on the connected tie...
  131. return theTie.thisObject();
  132. }
  133. } else {
  134. // This is an implementation object which has not been
  135. // exported to IIOP OR is a JRMP stub or implementation
  136. // object which cannot be marshalled into an ORB stream...
  137. throw new INV_OBJREF(obj.getClass().getName()+
  138. " not exported or is a JRMP stub");
  139. }
  140. }
  141. // Didn't need to do anything, just return the input...
  142. return obj;
  143. }
  144. /*
  145. * Get a new instance of an RMI-IIOP Tie for the
  146. * given server object.
  147. */
  148. public static Tie loadTie(Remote obj) {
  149. Tie result = null;
  150. Class objClass = obj.getClass();
  151. // Have we tried to find this guy before?
  152. synchronized (tieCache) {
  153. Object it = tieCache.get(obj);
  154. if (it == null) {
  155. // No, so try it...
  156. try {
  157. // First try the classname...
  158. result = loadTie(objClass);
  159. // If we don't have a valid tie at this point,
  160. // walk up the parent chain until we either
  161. // load a tie or encounter PortableRemoteObject
  162. // or java.lang.Object...
  163. while (result == null &&
  164. (objClass = objClass.getSuperclass()) != null &&
  165. objClass != PortableRemoteObject.class &&
  166. objClass != Object.class) {
  167. result = loadTie(objClass);
  168. }
  169. } catch (Exception ex) {}
  170. // Did we get it?
  171. if (result == null) {
  172. // Nope, so cache that fact...
  173. tieCache.put(obj,CACHE_MISS);
  174. } else {
  175. // Yes, so cache it...
  176. tieCache.put(obj,result);
  177. }
  178. } else {
  179. // Yes, return a new instance or fail again if
  180. // it was a miss last time...
  181. if (it != CACHE_MISS) {
  182. try {
  183. result = (Tie) it.getClass().newInstance();
  184. } catch (Exception e) {
  185. }
  186. }
  187. }
  188. }
  189. return result;
  190. }
  191. /*
  192. * Load an RMI-IIOP Tie
  193. */
  194. private static Tie loadTie(Class theClass) {
  195. try {
  196. String className = tieName(theClass.getName());
  197. //_REVISIT_ The spec does not specify a loadingContext parameter for
  198. //the following call. Would it be useful to pass one?
  199. Class tieClass = loadClassForClass(className,
  200. Util.getCodebase(theClass),
  201. null, theClass, theClass.getClassLoader());
  202. return (Tie) tieClass.newInstance();
  203. } catch (Exception err) {
  204. return null;
  205. }
  206. }
  207. /*
  208. * Clear the stub/tie caches. Intended for use by
  209. * test code.
  210. */
  211. public static void clearCaches() {
  212. synchronized (tieToStubCache) {
  213. tieToStubCache.clear();
  214. }
  215. synchronized (tieCache) {
  216. tieCache.clear();
  217. }
  218. synchronized (stubToTieCache) {
  219. stubToTieCache.clear();
  220. }
  221. }
  222. /*
  223. * Load a class and check that it is assignable to a given type.
  224. * @param className the class name.
  225. * @param remoteCodebase the codebase to use. May be null.
  226. * @param loader the class loader of last resort. May be null.
  227. * @param expectedType the expected type. May be null.
  228. * @return the loaded class.
  229. */
  230. static Class loadClassOfType (String className,
  231. String remoteCodebase,
  232. ClassLoader loader,
  233. Class expectedType,
  234. ClassLoader expectedTypeClassLoader)
  235. throws ClassNotFoundException {
  236. Class loadedClass = null;
  237. try {
  238. //Sequence finding of the stubs according to spec
  239. try{
  240. //If-else is put here for speed up of J2EE.
  241. //According to the OMG spec, the if clause is not dead code.
  242. //It can occur if some compiler has allowed generation
  243. //into org.omg.stub hierarchy for non-offending
  244. //classes. This will encourage people to
  245. //produce non-offending class stubs in their own hierarchy.
  246. if(!PackagePrefixChecker
  247. .hasOffendingPrefix(PackagePrefixChecker
  248. .withoutPackagePrefix(className))){
  249. loadedClass = Util.loadClass
  250. (PackagePrefixChecker.withoutPackagePrefix(className),
  251. remoteCodebase,
  252. loader);
  253. } else {
  254. loadedClass = Util.loadClass
  255. (className,
  256. remoteCodebase,
  257. loader);
  258. }
  259. } catch (ClassNotFoundException cnfe) {
  260. loadedClass = Util.loadClass
  261. (className,
  262. remoteCodebase,
  263. loader);
  264. }
  265. if (expectedType == null)
  266. return loadedClass;
  267. } catch (ClassNotFoundException cnfe) {
  268. if (expectedType == null)
  269. throw cnfe;
  270. }
  271. // If no class was not loaded, or if the loaded class is not of the
  272. // correct type, make a further attempt to load the correct class
  273. // using the classloader of the expected type.
  274. // _REVISIT_ Is this step necessary, or should the Util,loadClass
  275. // algorithm always produce a valid class if the setup is correct?
  276. // Does the OMG standard algorithm need to be changed to include
  277. // this step?
  278. if (loadedClass == null || !expectedType.isAssignableFrom(loadedClass)){
  279. if (expectedType.getClassLoader() != expectedTypeClassLoader)
  280. throw new IllegalArgumentException(
  281. "expectedTypeClassLoader not class loader of " +
  282. "expected Type.");
  283. if (expectedTypeClassLoader != null)
  284. loadedClass = expectedTypeClassLoader.loadClass(className);
  285. else {
  286. ClassLoader cl = Thread.currentThread().getContextClassLoader();
  287. if (cl == null)
  288. cl = ClassLoader.getSystemClassLoader();
  289. loadedClass = cl.loadClass(className);
  290. }
  291. }
  292. return loadedClass;
  293. }
  294. /*
  295. * Load a class and check that it is compatible with a given type.
  296. * @param className the class name.
  297. * @param remoteCodebase the codebase to use. May be null.
  298. * @param loadingContext the loading context. May be null.
  299. * @param relatedType the related type. May be null.
  300. * @return the loaded class.
  301. */
  302. public static Class loadClassForClass (String className,
  303. String remoteCodebase,
  304. ClassLoader loader,
  305. Class relatedType,
  306. ClassLoader relatedTypeClassLoader)
  307. throws ClassNotFoundException {
  308. if (relatedType == null)
  309. return Util.loadClass(className, remoteCodebase, loader);
  310. Class loadedClass = null;
  311. try {
  312. loadedClass = Util.loadClass(className, remoteCodebase, loader);
  313. } catch (ClassNotFoundException cnfe) {
  314. if (relatedType.getClassLoader() == null)
  315. throw cnfe;
  316. }
  317. // If no class was not loaded, or if the loaded class is not of the
  318. // correct type, make a further attempt to load the correct class
  319. // using the classloader of the related type.
  320. // _REVISIT_ Is this step necessary, or should the Util,loadClass
  321. // algorithm always produce a valid class if the setup is correct?
  322. // Does the OMG standard algorithm need to be changed to include
  323. // this step?
  324. if (loadedClass == null ||
  325. (loadedClass.getClassLoader() != null &&
  326. loadedClass.getClassLoader().loadClass(relatedType.getName()) !=
  327. relatedType))
  328. {
  329. if (relatedType.getClassLoader() != relatedTypeClassLoader)
  330. throw new IllegalArgumentException(
  331. "relatedTypeClassLoader not class loader of relatedType.");
  332. if (relatedTypeClassLoader != null)
  333. loadedClass = relatedTypeClassLoader.loadClass(className);
  334. }
  335. return loadedClass;
  336. }
  337. /**
  338. * Get the helper for an IDLValue
  339. *
  340. * Throws MARSHAL exception if no helper found.
  341. */
  342. public static BoxedValueHelper getHelper(Class clazz, String codebase,
  343. String repId)
  344. {
  345. String className = null;
  346. if (clazz != null) {
  347. className = clazz.getName();
  348. if (codebase == null)
  349. codebase = Util.getCodebase(clazz);
  350. } else {
  351. if (repId != null)
  352. className = RepositoryId.cache.getId(repId).getClassName();
  353. if (className == null) // no repId or unrecognized repId
  354. throw new org.omg.CORBA.MARSHAL(
  355. MinorCodes.UNABLE_LOCATE_VALUE_HELPER,
  356. CompletionStatus.COMPLETED_MAYBE);
  357. }
  358. try {
  359. ClassLoader clazzLoader =
  360. (clazz == null ? null : clazz.getClassLoader());
  361. Class helperClass =
  362. loadClassForClass(className+"Helper", codebase, clazzLoader,
  363. clazz, clazzLoader);
  364. return (BoxedValueHelper)helperClass.newInstance();
  365. } catch (ClassNotFoundException cnfe) {
  366. throw new org.omg.CORBA.MARSHAL(cnfe.toString(),
  367. MinorCodes.UNABLE_LOCATE_VALUE_HELPER,
  368. CompletionStatus.COMPLETED_MAYBE);
  369. } catch (IllegalAccessException iae) {
  370. throw new org.omg.CORBA.MARSHAL(iae.toString(),
  371. MinorCodes.UNABLE_LOCATE_VALUE_HELPER,
  372. CompletionStatus.COMPLETED_MAYBE);
  373. } catch (InstantiationException ie) {
  374. throw new org.omg.CORBA.MARSHAL(ie.toString(),
  375. MinorCodes.UNABLE_LOCATE_VALUE_HELPER,
  376. CompletionStatus.COMPLETED_MAYBE);
  377. } catch (ClassCastException cce) {
  378. throw new org.omg.CORBA.MARSHAL(cce.toString(),
  379. MinorCodes.UNABLE_LOCATE_VALUE_HELPER,
  380. CompletionStatus.COMPLETED_MAYBE);
  381. }
  382. }
  383. /**
  384. * Get the factory for an IDLValue
  385. *
  386. * Throws MARSHAL exception if no factory found.
  387. */
  388. public static ValueFactory getFactory(Class clazz, String codebase,
  389. ORB orb, String repId)
  390. {
  391. ValueFactory factory = null;
  392. if ((orb != null) && (repId != null)) {
  393. try {
  394. factory = ((org.omg.CORBA_2_3.ORB)orb).lookup_value_factory(
  395. repId);
  396. } catch (org.omg.CORBA.BAD_PARAM ex) {
  397. // Try other way
  398. }
  399. }
  400. String className = null;
  401. if (clazz != null) {
  402. className = clazz.getName();
  403. if (codebase == null)
  404. codebase = Util.getCodebase(clazz);
  405. } else {
  406. if (repId != null)
  407. className = RepositoryId.cache.getId(repId).getClassName();
  408. if (className == null) // no repId or unrecognized repId
  409. throw new org.omg.CORBA.MARSHAL(
  410. MinorCodes.UNABLE_LOCATE_VALUE_FACTORY,
  411. CompletionStatus.COMPLETED_MAYBE);
  412. }
  413. // if earlier search found a non-default factory, or the same default
  414. // factory that loadClassForClass would return, bale out now...
  415. if (factory != null &&
  416. (!factory.getClass().getName().equals(className+"DefaultFactory") ||
  417. (clazz == null && codebase == null)))
  418. return factory;
  419. try {
  420. ClassLoader clazzLoader =
  421. (clazz == null ? null : clazz.getClassLoader());
  422. Class factoryClass =
  423. loadClassForClass(className+"DefaultFactory", codebase,
  424. clazzLoader, clazz, clazzLoader);
  425. return (ValueFactory)factoryClass.newInstance();
  426. } catch (ClassNotFoundException cnfe) {
  427. throw new org.omg.CORBA.MARSHAL(cnfe.toString(),
  428. MinorCodes.UNABLE_LOCATE_VALUE_FACTORY,
  429. CompletionStatus.COMPLETED_MAYBE);
  430. } catch (IllegalAccessException iae) {
  431. throw new org.omg.CORBA.MARSHAL(iae.toString(),
  432. MinorCodes.UNABLE_LOCATE_VALUE_FACTORY,
  433. CompletionStatus.COMPLETED_MAYBE);
  434. } catch (InstantiationException ie) {
  435. throw new org.omg.CORBA.MARSHAL(ie.toString(),
  436. MinorCodes.UNABLE_LOCATE_VALUE_FACTORY,
  437. CompletionStatus.COMPLETED_MAYBE);
  438. } catch (ClassCastException cce) {
  439. throw new org.omg.CORBA.MARSHAL(cce.toString(),
  440. MinorCodes.UNABLE_LOCATE_VALUE_FACTORY,
  441. CompletionStatus.COMPLETED_MAYBE);
  442. }
  443. }
  444. /*
  445. * Load an RMI-IIOP Stub given a Tie.
  446. * @param tie the tie.
  447. * @param stubClass the stub class. May be null.
  448. * @param remoteCodebase the codebase to use. May be null.
  449. * @param onlyMostDerived if true, will fail if cannot load a stub for the
  450. * first repID in the tie. If false, will walk all repIDs.
  451. * @return the stub or null if not found.
  452. */
  453. public static Remote loadStub (Tie tie,
  454. Class stubClass,
  455. String remoteCodebase,
  456. boolean onlyMostDerived) {
  457. StubEntry entry = null;
  458. // Do we already have it cached?
  459. synchronized (tieToStubCache) {
  460. Object cached = tieToStubCache.get(tie);
  461. if (cached == null) {
  462. // No, so go try to load it...
  463. entry = loadStubAndUpdateCache(
  464. tie,stubClass,remoteCodebase,onlyMostDerived);
  465. } else {
  466. // Yes, is it a stub? If not, it was a miss last
  467. // time, so return null again...
  468. if (cached != CACHE_MISS) {
  469. // It's a stub.
  470. entry = (StubEntry) cached;
  471. // Does the cached stub meet the requirements
  472. // of the caller? If the caller does not require
  473. // the most derived stub and does not require
  474. // a specific stub type, we don't have to check
  475. // any further because the cached type is good
  476. // enough...
  477. if (!entry.mostDerived && onlyMostDerived) {
  478. // We must reload because we do not have
  479. // the most derived cached already...
  480. entry =
  481. loadStubAndUpdateCache(tie,null,remoteCodebase,true);
  482. } else if (stubClass != null
  483. && entry.stub.getClass() != stubClass)
  484. {
  485. // We do not have exactly the right stub. First, try to
  486. // upgrade the cached stub by forcing it to the most
  487. // derived stub...
  488. entry =
  489. loadStubAndUpdateCache(tie,null,remoteCodebase,true);
  490. // If that failed, try again with the exact type
  491. // we need...
  492. if (entry == null) {
  493. entry = loadStubAndUpdateCache(tie,stubClass,
  494. remoteCodebase,onlyMostDerived);
  495. }
  496. } else {
  497. // Use the cached stub. Is the delegate set?
  498. try {
  499. Delegate stubDel =
  500. ((ObjectImpl)entry.stub)._get_delegate();
  501. } catch (Exception e2) {
  502. // No, so set it if we can...
  503. try {
  504. Delegate del =
  505. ((ObjectImpl)tie)._get_delegate();
  506. ((ObjectImpl)entry.stub)._set_delegate(del);
  507. } catch (Exception e) {}
  508. }
  509. }
  510. }
  511. }
  512. }
  513. if (entry != null) {
  514. return (Remote)entry.stub;
  515. } else {
  516. return null;
  517. }
  518. }
  519. /*
  520. * Load an RMI-IIOP Stub given a Tie, but do not look in the cache.
  521. * This method must be called with the lock held for tieToStubCache.
  522. * @param tie the tie.
  523. * @param stubClass the stub class. May be null.
  524. * @param remoteCodebase the codebase to use. May be null.
  525. * @param onlyMostDerived if true, will fail if cannot load a stub for the
  526. * first repID in the tie. If false, will walk all repIDs.
  527. * @return the StubEntry or null if not found.
  528. */
  529. private static StubEntry loadStubAndUpdateCache (Tie tie,
  530. Class stubClass,
  531. String remoteCodebase,
  532. boolean onlyMostDerived)
  533. {
  534. Stub stub = null;
  535. StubEntry entry = null;
  536. boolean isObjectImpl = (tie instanceof ObjectImpl);
  537. // Were we given a stub class?
  538. if (stubClass != null) {
  539. // Yes, so try to instantiate it...
  540. try {
  541. stub = (Stub) stubClass.newInstance();
  542. } catch (Throwable e) {
  543. if (e instanceof ThreadDeath) {
  544. throw (ThreadDeath) e;
  545. }
  546. }
  547. } else {
  548. // Nope, so we must find it. First, get the list
  549. // of ids from the tie...
  550. String[] ids = null;
  551. if( isObjectImpl ) {
  552. ids = ((ObjectImpl)tie)._ids();
  553. } else {
  554. // If Tie is extending Servant, Then the
  555. // Repository Id can be obtained from all_interfaces()
  556. // method.
  557. ids = ((org.omg.PortableServer.Servant)tie).
  558. _all_interfaces( null, null );
  559. }
  560. // If we were not given a remoteCodebase,
  561. // get one from the tie...
  562. if (remoteCodebase == null) {
  563. remoteCodebase = Util.getCodebase(tie.getClass());
  564. }
  565. // Now walk all the RepIDs till we find it or fail...
  566. for (int i = 0; i < ids.length; i++) {
  567. // Check for the java.rmi.Remote special case...
  568. if (ids[i].length() == 0) {
  569. stub = new org.omg.stub.java.rmi._Remote_Stub();
  570. break;
  571. }
  572. // Get the classname from the RepID...
  573. String className = stubNameFromRepID(ids[i]);
  574. // Now try to load it...
  575. try {
  576. // _REVISIT_ The spec does not specify a
  577. // loadingContext parameter for the following call.
  578. Class resultClass = null;
  579. try{
  580. //If-else is put here for speed up of J2EE.
  581. //According to the OMG spec, the if clause is
  582. //not dead code. It can occur if the compiler
  583. //has allowed generation into org.omg.stub
  584. //hierarchy for non-offending classes. This
  585. //will encourage people to produce non-offending
  586. //class stubs in their own hierarchy.
  587. if(!PackagePrefixChecker
  588. .hasOffendingPrefix(PackagePrefixChecker
  589. .withoutPackagePrefix(className))){
  590. resultClass = Util.loadClass
  591. (PackagePrefixChecker.withoutPackagePrefix(
  592. className),
  593. remoteCodebase,
  594. tie.getClass().getClassLoader());
  595. } else {
  596. resultClass = Util.loadClass
  597. (className,
  598. remoteCodebase,
  599. tie.getClass().getClassLoader());
  600. }
  601. } catch (ClassNotFoundException cnfe){
  602. resultClass = Util.loadClass
  603. (className,
  604. remoteCodebase,
  605. tie.getClass().getClassLoader());
  606. }
  607. stub = (Stub) resultClass.newInstance();
  608. break;
  609. } catch (Exception e){}
  610. // If we failed to load it, see if we should continue...
  611. if (onlyMostDerived) {
  612. // Stop here.
  613. break;
  614. }
  615. }
  616. }
  617. // Did we get it?
  618. if (stub != null) {
  619. // If the tie has a delegate set, grab it
  620. // and stuff it in the stub...
  621. if( isObjectImpl ) {
  622. // Tie extends ObjectImpl
  623. try {
  624. Delegate del = ((ObjectImpl)tie)._get_delegate();
  625. ((ObjectImpl)stub)._set_delegate(del);
  626. } catch( Exception e1 ) {
  627. // The tie does not have a delegate set, so stash
  628. // this tie away using the stub as a key so that
  629. // later, when the stub is connected, we can find
  630. // and connect the tie as well...
  631. synchronized (stubToTieCache) {
  632. stubToTieCache.put(stub,tie);
  633. }
  634. }
  635. } else {
  636. // Tie extends Servant
  637. try {
  638. org.omg.CORBA.Object ref =
  639. ((org.omg.PortableServer.Servant)tie).
  640. _this_object( );
  641. ((ObjectImpl)stub)._set_delegate(
  642. ((ObjectImpl)ref)._get_delegate() );
  643. } catch( org.omg.CORBA.BAD_INV_ORDER bad) {
  644. synchronized (stubToTieCache) {
  645. stubToTieCache.put(stub,tie);
  646. }
  647. } catch( Exception e ) {
  648. // Exception is caught because of any of the
  649. // following reasons
  650. // 1) POA is not associated with the TIE
  651. // 2) POA Policies for the tie-associated POA
  652. // does not support _this_object() call.
  653. throw new BAD_PARAM(MinorCodes.NO_POA,
  654. CompletionStatus.COMPLETED_NO);
  655. }
  656. }
  657. // Update the cache...
  658. entry = new StubEntry(stub,onlyMostDerived);
  659. tieToStubCache.put(tie,entry);
  660. } else {
  661. // Stub == null, so cache the miss...
  662. tieToStubCache.put(tie,CACHE_MISS);
  663. }
  664. return entry;
  665. }
  666. /*
  667. * If we loadStub(Tie,...) stashed away a tie which was
  668. * not connected, remove it from the cache and return
  669. * it.
  670. */
  671. public static Tie getAndForgetTie (Stub stub) {
  672. synchronized (stubToTieCache) {
  673. return (Tie) stubToTieCache.remove(stub);
  674. }
  675. }
  676. /*
  677. * Remove any cached Stub for the given tie.
  678. */
  679. public static void purgeStubForTie (Tie tie) {
  680. StubEntry entry;
  681. synchronized (tieToStubCache) {
  682. entry = (StubEntry)tieToStubCache.remove(tie);
  683. }
  684. if (entry != null) {
  685. synchronized (stubToTieCache) {
  686. stubToTieCache.remove(entry.stub);
  687. }
  688. }
  689. }
  690. /*
  691. * Remove cached tie/servant pair.
  692. */
  693. public static void purgeTieAndServant (Tie tie) {
  694. synchronized (tieCache) {
  695. Object target = tie.getTarget();
  696. if (target != null)
  697. tieCache.remove(target);
  698. }
  699. }
  700. /*
  701. * Convert a RepId to a stubName...
  702. */
  703. public static String stubNameFromRepID (String repID) {
  704. // Convert the typeid to a RepositoryId instance, get
  705. // the className and mangle it as needed...
  706. RepositoryId id = RepositoryId.cache.getId(repID);
  707. String className = id.getClassName();
  708. if (id.isIDLType()) {
  709. className = idlStubName(className);
  710. } else {
  711. className = stubName(className);
  712. }
  713. return className;
  714. }
  715. /*
  716. * Load an RMI-IIOP Stub.
  717. */
  718. public static Stub loadStub (ObjectImpl narrowFrom,
  719. Class narrowTo) {
  720. Stub result = null;
  721. try {
  722. // Get the codebase from the delegate to use when loading
  723. // the new stub, if possible...
  724. String codebase = null;
  725. try {
  726. // We can't assume that narrowFrom is a CORBA_2_3 ObjectImpl, yet
  727. // it may have a 2_3 Delegate that provides a codebase. Swallow
  728. // the ClassCastException otherwise.
  729. Delegate delegate = narrowFrom._get_delegate();
  730. codebase = ((org.omg.CORBA_2_3.portable.Delegate)delegate).get_codebase(narrowFrom);
  731. } catch (ClassCastException e) {
  732. }
  733. String stubName = stubName(narrowTo.getName());
  734. // _REVISIT_ Should the narrowFrom or narrowTo class be used as the
  735. // loadingContext in the following call? The spec says narrowFrom,
  736. // but this does not seem correct...
  737. Class resultClass = null;
  738. try {
  739. resultClass = loadClassOfType(stubName,
  740. codebase,
  741. narrowFrom.getClass().getClassLoader(),
  742. narrowTo,
  743. narrowTo.getClassLoader());
  744. } catch(ClassNotFoundException cnfe) {
  745. resultClass = loadClassOfType(STUB_PACKAGE_PREFIX + stubName,
  746. codebase,
  747. narrowFrom.getClass().getClassLoader(),
  748. narrowTo,
  749. narrowTo.getClassLoader());
  750. }
  751. // Create a stub instance and set the delegate...
  752. result = (Stub) resultClass.newInstance();
  753. ((ObjectImpl)result)._set_delegate(narrowFrom._get_delegate());
  754. } catch (Exception err) {
  755. }
  756. return result;
  757. }
  758. /*
  759. * Load an RMI-IIOP Stub class.
  760. */
  761. //d11638 removed unused "CodeBase sender" parameter
  762. public static Class loadStubClass(String repID,
  763. String remoteCodebase,
  764. Class expectedType)
  765. throws ClassNotFoundException {
  766. // Get the repID and check for "" special case.
  767. // We should never be called with it (See CDRInputStream
  768. // and the loadStub() method)...
  769. if (repID.length() == 0) {
  770. throw new ClassNotFoundException();
  771. }
  772. // Get the stubname from the repID and load
  773. // the class. If we have a valid 'sender', fall
  774. // back to using its codebase if we need to...
  775. String className = Utility.stubNameFromRepID(repID);
  776. ClassLoader expectedTypeClassLoader = (expectedType == null ? null : expectedType.getClassLoader());
  777. try {
  778. return loadClassOfType(className,
  779. remoteCodebase,
  780. expectedTypeClassLoader,
  781. expectedType,
  782. expectedTypeClassLoader);
  783. } catch (ClassNotFoundException e) {
  784. return loadClassOfType(STUB_PACKAGE_PREFIX + className,
  785. remoteCodebase,
  786. expectedTypeClassLoader,
  787. expectedType,
  788. expectedTypeClassLoader);
  789. }
  790. }
  791. /**
  792. * Create an RMI stub name.
  793. */
  794. public static String stubName (String className) {
  795. return
  796. PackagePrefixChecker.hasOffendingPrefix(stubNameForCompiler(className)) ?
  797. PackagePrefixChecker.packagePrefix() + stubNameForCompiler(className) :
  798. stubNameForCompiler(className);
  799. }
  800. public static String stubNameForCompiler (String className) {
  801. int index = className.indexOf('$');
  802. if (index < 0) {
  803. index = className.lastIndexOf('.');
  804. }
  805. if (index > 0) {
  806. return
  807. className.substring(0,index+1) +
  808. STUB_PREFIX +
  809. className.substring(index+1) +
  810. RMI_STUB_SUFFIX;
  811. } else {
  812. return STUB_PREFIX +
  813. className +
  814. RMI_STUB_SUFFIX;
  815. }
  816. }
  817. /**
  818. * Create an RMI tie name.
  819. */
  820. public static String tieName (String className) {
  821. return
  822. PackagePrefixChecker.hasOffendingPrefix(tieNameForCompiler(className)) ?
  823. PackagePrefixChecker.packagePrefix() + tieNameForCompiler(className) :
  824. tieNameForCompiler(className);
  825. }
  826. public static String tieNameForCompiler (String className) {
  827. int index = className.indexOf('$');
  828. if (index < 0) {
  829. index = className.lastIndexOf('.');
  830. }
  831. if (index > 0) {
  832. return className.substring(0,index+1) +
  833. STUB_PREFIX +
  834. className.substring(index+1) +
  835. TIE_SUFIX;
  836. } else {
  837. return STUB_PREFIX +
  838. className +
  839. TIE_SUFIX;
  840. }
  841. }
  842. /**
  843. * Throws the CORBA equivalent of a java.io.NotSerializableException
  844. */
  845. public static void throwNotSerializableForCorba(String className) {
  846. throw new BAD_PARAM(className,
  847. MinorCodes.NOT_SERIALIZABLE,
  848. CompletionStatus.COMPLETED_MAYBE);
  849. }
  850. /**
  851. * Create an IDL stub name.
  852. */
  853. public static String idlStubName(String className) {
  854. String result = null;
  855. int index = className.lastIndexOf('.');
  856. if (index > 0) {
  857. result = className.substring(0,index+1) +
  858. STUB_PREFIX +
  859. className.substring(index+1) +
  860. IDL_STUB_SUFFIX;
  861. } else {
  862. result = STUB_PREFIX +
  863. className +
  864. IDL_STUB_SUFFIX;
  865. }
  866. return result;
  867. }
  868. public static void printStackTrace()
  869. {
  870. Throwable thr = new Throwable( "Printing stack trace:" ) ;
  871. thr.fillInStackTrace() ;
  872. thr.printStackTrace() ;
  873. }
  874. /**
  875. * Read an object reference from the input stream and narrow
  876. * it to the desired type.
  877. * @param in the stream to read from.
  878. * @throws ClassCastException if narrowFrom cannot be cast to narrowTo.
  879. */
  880. public static Object readObjectAndNarrow(InputStream in,
  881. Class narrowTo)
  882. throws ClassCastException {
  883. Object result = in.read_Object();
  884. if (result != null)
  885. return PortableRemoteObject.narrow(result, narrowTo);
  886. else
  887. return null;
  888. }
  889. /**
  890. * Read an abstract interface type from the input stream and narrow
  891. * it to the desired type.
  892. * @param in the stream to read from.
  893. * @throws ClassCastException if narrowFrom cannot be cast to narrowTo.
  894. */
  895. public static Object readAbstractAndNarrow(org.omg.CORBA_2_3.portable.InputStream in,
  896. Class narrowTo)
  897. throws ClassCastException {
  898. Object result = in.read_abstract_interface();
  899. if (result != null)
  900. return PortableRemoteObject.narrow(result, narrowTo);
  901. else
  902. return null;
  903. }
  904. /** Converts an Ascii Character into Hexadecimal digit
  905. */
  906. static int hexOf( char x )
  907. {
  908. int val;
  909. val = x - '0';
  910. if (val >=0 && val <= 9)
  911. return val;
  912. val = (x - 'a') + 10;
  913. if (val >= 10 && val <= 15)
  914. return val;
  915. val = (x - 'A') + 10;
  916. if (val >= 10 && val <= 15)
  917. return val;
  918. throw new DATA_CONVERSION(MinorCodes.BAD_HEX_DIGIT,
  919. CompletionStatus.COMPLETED_NO);
  920. }
  921. }
  922. class StubEntry {
  923. Stub stub;
  924. boolean mostDerived;
  925. StubEntry(Stub stub, boolean mostDerived) {
  926. this.stub = stub;
  927. this.mostDerived = mostDerived;
  928. }
  929. }