1. /*
  2. * @(#)POAPolicyMediatorImpl_R_USM.java 1.39 04/03/01
  3. *
  4. * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
  5. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  6. */
  7. package com.sun.corba.se.impl.oa.poa ;
  8. import java.util.Set ;
  9. import org.omg.CORBA.SystemException ;
  10. import org.omg.PortableServer.ServantActivator ;
  11. import org.omg.PortableServer.Servant ;
  12. import org.omg.PortableServer.ServantManager ;
  13. import org.omg.PortableServer.ForwardRequest ;
  14. import org.omg.PortableServer.POAPackage.WrongPolicy ;
  15. import org.omg.PortableServer.POAPackage.ObjectNotActive ;
  16. import org.omg.PortableServer.POAPackage.ServantNotActive ;
  17. import org.omg.PortableServer.POAPackage.ObjectAlreadyActive ;
  18. import org.omg.PortableServer.POAPackage.ServantAlreadyActive ;
  19. import org.omg.PortableServer.POAPackage.NoServant ;
  20. import com.sun.corba.se.impl.orbutil.concurrent.SyncUtil ;
  21. import com.sun.corba.se.impl.orbutil.ORBUtility ;
  22. import com.sun.corba.se.impl.orbutil.ORBConstants ;
  23. import com.sun.corba.se.impl.oa.NullServantImpl ;
  24. import com.sun.corba.se.impl.javax.rmi.CORBA.Util ;
  25. import com.sun.corba.se.spi.oa.OAInvocationInfo ;
  26. import com.sun.corba.se.spi.oa.NullServant ;
  27. /** Implementation of POARequesHandler that provides policy specific
  28. * operations on the POA.
  29. */
  30. public class POAPolicyMediatorImpl_R_USM extends POAPolicyMediatorBase_R {
  31. protected ServantActivator activator ;
  32. POAPolicyMediatorImpl_R_USM( Policies policies, POAImpl poa )
  33. {
  34. // assert policies.retainServants()
  35. super( policies, poa ) ;
  36. activator = null ;
  37. if (!policies.useServantManager())
  38. throw poa.invocationWrapper().policyMediatorBadPolicyInFactory() ;
  39. }
  40. /* This handles a rather subtle bug (4939892). The problem is that
  41. * enter will wait on the entry if it is being etherealized. When the
  42. * deferred state transition completes, the entry is no longer in the
  43. * AOM, and so we need to get a new entry, otherwise activator.incarnate
  44. * will be called twice, once for the old entry, and again when a new
  45. * entry is created. This fix also required extending the FSM StateEngine
  46. * to allow actions to throw exceptions, and adding a new state in the
  47. * AOMEntry FSM to detect this condition.
  48. */
  49. private AOMEntry enterEntry( ActiveObjectMap.Key key )
  50. {
  51. AOMEntry result = null ;
  52. boolean failed ;
  53. do {
  54. failed = false ;
  55. result = activeObjectMap.get(key) ;
  56. try {
  57. result.enter() ;
  58. } catch (Exception exc) {
  59. failed = true ;
  60. }
  61. } while (failed) ;
  62. return result ;
  63. }
  64. protected java.lang.Object internalGetServant( byte[] id,
  65. String operation ) throws ForwardRequest
  66. {
  67. if (poa.getDebug()) {
  68. ORBUtility.dprint( this,
  69. "Calling POAPolicyMediatorImpl_R_USM.internalGetServant " +
  70. "for poa " + poa + " operation=" + operation ) ;
  71. }
  72. try {
  73. ActiveObjectMap.Key key = new ActiveObjectMap.Key( id ) ;
  74. AOMEntry entry = enterEntry(key) ;
  75. java.lang.Object servant = activeObjectMap.getServant( entry ) ;
  76. if (servant != null) {
  77. if (poa.getDebug()) {
  78. ORBUtility.dprint( this,
  79. "internalGetServant: servant already activated" ) ;
  80. }
  81. return servant ;
  82. }
  83. if (activator == null) {
  84. if (poa.getDebug()) {
  85. ORBUtility.dprint( this,
  86. "internalGetServant: no servant activator in POA" ) ;
  87. }
  88. entry.incarnateFailure() ;
  89. throw poa.invocationWrapper().poaNoServantManager() ;
  90. }
  91. // Drop the POA lock during the incarnate call and
  92. // re-acquire it afterwards. The entry state machine
  93. // prevents more than one thread from executing the
  94. // incarnate method at a time within the same POA.
  95. try {
  96. if (poa.getDebug()) {
  97. ORBUtility.dprint( this,
  98. "internalGetServant: upcall to incarnate" ) ;
  99. }
  100. poa.unlock() ;
  101. servant = activator.incarnate(id, poa);
  102. if (servant == null)
  103. servant = new NullServantImpl(
  104. poa.omgInvocationWrapper().nullServantReturned() ) ;
  105. } catch (ForwardRequest freq) {
  106. if (poa.getDebug()) {
  107. ORBUtility.dprint( this,
  108. "internalGetServant: incarnate threw ForwardRequest" ) ;
  109. }
  110. throw freq ;
  111. } catch (SystemException exc) {
  112. if (poa.getDebug()) {
  113. ORBUtility.dprint( this,
  114. "internalGetServant: incarnate threw SystemException " + exc ) ;
  115. }
  116. throw exc ;
  117. } catch (Throwable exc) {
  118. if (poa.getDebug()) {
  119. ORBUtility.dprint( this,
  120. "internalGetServant: incarnate threw Throwable " + exc ) ;
  121. }
  122. throw poa.invocationWrapper().poaServantActivatorLookupFailed(
  123. exc ) ;
  124. } finally {
  125. poa.lock() ;
  126. // servant == null means incarnate threw an exception,
  127. // while servant instanceof NullServant means incarnate returned a
  128. // null servant. Either case is an incarnate failure to the
  129. // entry state machine.
  130. if ((servant == null) || (servant instanceof NullServant)) {
  131. if (poa.getDebug()) {
  132. ORBUtility.dprint( this,
  133. "internalGetServant: incarnate failed" ) ;
  134. }
  135. // XXX Does the AOM leak in this case? Yes,
  136. // but the problem is hard to fix. There may be
  137. // a number of threads waiting for the state to change
  138. // from INCARN to something else, which is VALID or
  139. // INVALID, depending on the incarnate result.
  140. // The activeObjectMap.get() call above creates an
  141. // ActiveObjectMap.Entry if one does not already exist,
  142. // and stores it in the keyToEntry map in the AOM.
  143. entry.incarnateFailure() ;
  144. } else {
  145. // here check for unique_id policy, and if the servant
  146. // is already registered for a different ID, then throw
  147. // OBJ_ADAPTER exception, else activate it. Section 11.3.5.1
  148. // 99-10-07.pdf
  149. if (isUnique) {
  150. // check if the servant already is associated with some id
  151. if (activeObjectMap.contains((Servant)servant)) {
  152. if (poa.getDebug()) {
  153. ORBUtility.dprint( this,
  154. "internalGetServant: servant already assigned to ID" ) ;
  155. }
  156. entry.incarnateFailure() ;
  157. throw poa.invocationWrapper().poaServantNotUnique() ;
  158. }
  159. }
  160. if (poa.getDebug()) {
  161. ORBUtility.dprint( this,
  162. "internalGetServant: incarnate complete" ) ;
  163. }
  164. entry.incarnateComplete() ;
  165. activateServant(key, entry, (Servant)servant);
  166. }
  167. }
  168. return servant ;
  169. } finally {
  170. if (poa.getDebug()) {
  171. ORBUtility.dprint( this,
  172. "Exiting POAPolicyMediatorImpl_R_USM.internalGetServant " +
  173. "for poa " + poa ) ;
  174. }
  175. }
  176. }
  177. public void returnServant()
  178. {
  179. OAInvocationInfo info = orb.peekInvocationInfo();
  180. byte[] id = info.id() ;
  181. ActiveObjectMap.Key key = new ActiveObjectMap.Key( id ) ;
  182. AOMEntry entry = activeObjectMap.get( key ) ;
  183. entry.exit() ;
  184. }
  185. public void etherealizeAll()
  186. {
  187. if (activator != null) {
  188. Set keySet = activeObjectMap.keySet() ;
  189. // Copy the elements in the set to an array to avoid
  190. // changes in the set due to concurrent modification
  191. ActiveObjectMap.Key[] keys =
  192. (ActiveObjectMap.Key[])keySet.toArray(
  193. new ActiveObjectMap.Key[ keySet.size() ] ) ;
  194. for (int ctr=0; ctr<keySet.size(); ctr++) {
  195. ActiveObjectMap.Key key = keys[ctr] ;
  196. AOMEntry entry = activeObjectMap.get( key ) ;
  197. Servant servant = activeObjectMap.getServant( entry ) ;
  198. if (servant != null) {
  199. boolean remainingActivations =
  200. activeObjectMap.hasMultipleIDs(entry) ;
  201. // Here we etherealize in the thread that called this
  202. // method, rather than etherealizing in a new thread
  203. // as in the deactivate case. We still inform the
  204. // entry state machine so that only one thread at a
  205. // time can call the etherealize method.
  206. entry.startEtherealize( null ) ;
  207. try {
  208. poa.unlock() ;
  209. try {
  210. activator.etherealize(key.id, poa, servant, true,
  211. remainingActivations);
  212. } catch (Exception exc) {
  213. // ignore all exceptions
  214. }
  215. } finally {
  216. poa.lock() ;
  217. entry.etherealizeComplete() ;
  218. }
  219. }
  220. }
  221. }
  222. }
  223. public ServantManager getServantManager() throws WrongPolicy
  224. {
  225. return activator;
  226. }
  227. public void setServantManager(
  228. ServantManager servantManager ) throws WrongPolicy
  229. {
  230. if (activator != null)
  231. throw poa.invocationWrapper().servantManagerAlreadySet() ;
  232. if (servantManager instanceof ServantActivator)
  233. activator = (ServantActivator)servantManager;
  234. else
  235. throw poa.invocationWrapper().servantManagerBadType() ;
  236. }
  237. public Servant getDefaultServant() throws NoServant, WrongPolicy
  238. {
  239. throw new WrongPolicy();
  240. }
  241. public void setDefaultServant( Servant servant ) throws WrongPolicy
  242. {
  243. throw new WrongPolicy();
  244. }
  245. class Etherealizer extends Thread {
  246. private POAPolicyMediatorImpl_R_USM mediator ;
  247. private ActiveObjectMap.Key key ;
  248. private AOMEntry entry ;
  249. private Servant servant ;
  250. private boolean debug ;
  251. public Etherealizer( POAPolicyMediatorImpl_R_USM mediator,
  252. ActiveObjectMap.Key key, AOMEntry entry, Servant servant,
  253. boolean debug )
  254. {
  255. this.mediator = mediator ;
  256. this.key = key ;
  257. this.entry = entry;
  258. this.servant = servant;
  259. this.debug = debug ;
  260. }
  261. public void run() {
  262. if (debug) {
  263. ORBUtility.dprint( this, "Calling Etherealizer.run on key " +
  264. key ) ;
  265. }
  266. try {
  267. try {
  268. mediator.activator.etherealize( key.id, mediator.poa, servant,
  269. false, mediator.activeObjectMap.hasMultipleIDs( entry ) );
  270. } catch (Exception exc) {
  271. // ignore all exceptions
  272. }
  273. try {
  274. mediator.poa.lock() ;
  275. entry.etherealizeComplete() ;
  276. mediator.activeObjectMap.remove( key ) ;
  277. POAManagerImpl pm = (POAManagerImpl)mediator.poa.the_POAManager() ;
  278. POAFactory factory = pm.getFactory() ;
  279. factory.unregisterPOAForServant( mediator.poa, servant);
  280. } finally {
  281. mediator.poa.unlock() ;
  282. }
  283. } finally {
  284. if (debug) {
  285. ORBUtility.dprint( this, "Exiting Etherealizer.run" ) ;
  286. }
  287. }
  288. }
  289. }
  290. public void deactivateHelper( ActiveObjectMap.Key key, AOMEntry entry,
  291. Servant servant ) throws ObjectNotActive, WrongPolicy
  292. {
  293. if (activator == null)
  294. throw poa.invocationWrapper().poaNoServantManager() ;
  295. Etherealizer eth = new Etherealizer( this, key, entry, servant, poa.getDebug() ) ;
  296. entry.startEtherealize( eth ) ;
  297. }
  298. public Servant idToServant( byte[] id )
  299. throws WrongPolicy, ObjectNotActive
  300. {
  301. ActiveObjectMap.Key key = new ActiveObjectMap.Key( id ) ;
  302. AOMEntry entry = activeObjectMap.get(key);
  303. Servant servant = activeObjectMap.getServant( entry ) ;
  304. if (servant != null)
  305. return servant ;
  306. else
  307. throw new ObjectNotActive() ;
  308. }
  309. }