1. /*
  2. * @(#)GenericPOAServerSC.java 1.80 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. package com.sun.corba.se.internal.POA;
  8. import java.util.Iterator ;
  9. import org.omg.PortableServer.*;
  10. import org.omg.PortableServer.ServantLocatorPackage.*;
  11. import org.omg.CORBA.Any;
  12. import org.omg.CORBA.CompletionStatus;
  13. import org.omg.CORBA.SystemException;
  14. import org.omg.CORBA.OBJECT_NOT_EXIST;
  15. import org.omg.CORBA.OBJ_ADAPTER;
  16. import org.omg.CORBA.INTERNAL;
  17. import org.omg.CORBA.UNKNOWN;
  18. import org.omg.CORBA.portable.*;
  19. import org.omg.PortableServer.DynamicImplementation;
  20. import com.sun.corba.se.internal.core.*;
  21. import com.sun.corba.se.internal.corba.*;
  22. import com.sun.corba.se.internal.orbutil.ORBUtility; //d11638
  23. import com.sun.corba.se.internal.orbutil.ORBConstants;
  24. import com.sun.corba.se.internal.ior.ObjectKey ;
  25. import com.sun.corba.se.internal.ior.ObjectKeyFactory ;
  26. import com.sun.corba.se.internal.ior.ObjectId ;
  27. import com.sun.corba.se.internal.ior.ObjectKeyTemplate ;
  28. import com.sun.corba.se.internal.ior.POAObjectKeyTemplate ;
  29. import com.sun.corba.se.internal.ior.IIOPProfile ;
  30. import com.sun.corba.se.internal.ior.POAId ;
  31. import com.sun.corba.se.internal.iiop.RequestCanceledException;
  32. import javax.rmi.CORBA.Tie;
  33. /** The general-purpose server-side subcontract for the POA ORB.
  34. * It handles ORB processing for transient, persistent, non-transactional
  35. * and transactional server objects.
  36. * Its main functionality is:
  37. * 1. on each incoming request, find a POA and deliver the request to it.
  38. * 2. create delegates (to be embedded in object references) for a server
  39. * object in a POA with a given quality of service. The subcontract
  40. * thus controls the layout of fields in the objectKey in the IOR.
  41. * The quality of service of the server object is known from the subcontract-id
  42. * variable ("scid").
  43. */
  44. public class GenericPOAServerSC extends ServerDelegate
  45. {
  46. public GenericPOAServerSC()
  47. {
  48. super();
  49. }
  50. public GenericPOAServerSC(POAORB o)
  51. {
  52. super(o);
  53. }
  54. public static boolean isTransient(int subcontractId)
  55. {
  56. // 2nd bit in subcontract id is 0 for transient case.
  57. return ((subcontractId & 2)==0);
  58. }
  59. /** dispatch() is the start of the upcall for remote invocations.
  60. * The IIOPInputStream cursor is at the end of the RequestHeader
  61. * and the request's arguments can be read directly. On return
  62. * the IIOPOutputStream should contain the entire reply message
  63. * (ReplyHeader + return arguments).
  64. */
  65. public ServerResponse dispatch(ServerRequest req)
  66. {
  67. if (orb.subcontractDebugFlag)
  68. dprint( "dispatch entered" ) ;
  69. POAORB poaorb = (POAORB)orb;
  70. ObjectKey okey = req.getObjectKey();
  71. ObjectKeyTemplate oktemp = okey.getTemplate() ;
  72. int sId = oktemp.getServerId() ;
  73. if (orb.subcontractDebugFlag)
  74. dprint( "dispatch: sId = " + sId ) ;
  75. // to set the codebase information, if any transmitted; and also
  76. // appropriate ORB Version.
  77. consumeServiceContexts(req);
  78. // Now that we have the service contexts processed and the
  79. // correct ORBVersion set, we must finish initializing the
  80. // stream.
  81. req.performORBVersionSpecificInit();
  82. // If this is a transient SC, then check if the serverid matches
  83. // this server's transientServerId. Else check if the serverid
  84. // matches this server's persistentServerId.
  85. if ( (isTransient(scid) && sId == poaorb.getTransientServerId())
  86. || (!isTransient(scid) && poaorb.persistentServerIdInitialized
  87. && sId == poaorb.getPersistentServerId()) ) {
  88. return internalDispatch(req, okey);
  89. } else if ( poaorb.getBadServerIdHandler() != null ) { // e.g. in ORBD
  90. try {
  91. if (orb.subcontractDebugFlag)
  92. dprint( "dispatch: handling Bad server id (may be ORBD)" ) ;
  93. // will throw an exception: ForwardException
  94. poaorb.getBadServerIdHandler().handle(okey);
  95. } catch ( ForwardException fex ) {
  96. IOR ior = fex.getIOR();
  97. return req.createLocationForward(ior, null);
  98. }
  99. } else {
  100. throw new OBJECT_NOT_EXIST(
  101. com.sun.corba.se.internal.orbutil.MinorCodes.BAD_SERVER_ID,
  102. CompletionStatus.COMPLETED_NO);
  103. }
  104. return null; // to keep javac happy
  105. }
  106. private ServerResponse internalDispatch(ServerRequest req, ObjectKey okey )
  107. {
  108. if (orb.subcontractDebugFlag)
  109. dprint( "internalDispatch entered" ) ;
  110. byte[] objectId = okey.getId().getId() ;
  111. ObjectKeyTemplate oktemp = okey.getTemplate() ;
  112. POAId poaid = null ;
  113. if (oktemp instanceof POAObjectKeyTemplate) {
  114. POAObjectKeyTemplate poktemp = (POAObjectKeyTemplate)oktemp ;
  115. poaid = poktemp.getPOAId() ;
  116. }
  117. int targetScid = oktemp.getSubcontractId() ;
  118. if (orb.subcontractDebugFlag)
  119. dprint( "internalDispatch: targetScid = " + targetScid ) ;
  120. String operation = req.getOperationName();
  121. CookieHolder cookieHolder = new CookieHolder();
  122. POAImpl poaimpl=null;
  123. Servant servant=null;
  124. //The following is and INTERNAL minor code.
  125. //Use it only with INTERNAL exceptions.
  126. int mc = MinorCodes.SERVANT_LOOKUP ;
  127. ServerResponse resp = null ;
  128. try {
  129. poaimpl = (POAImpl)getPOA(poaid);
  130. // Prepare Portable Interceptors for a new server request
  131. // and invoke receive_request_service_contexts. The starting
  132. // point may throw a SystemException or ForwardRequest.
  133. byte[] adapterId = oktemp.getAdapterId( orb );
  134. ((POAORB)orb).initializeServerPIInfo( req, poaimpl,
  135. objectId, adapterId );
  136. ((POAORB)orb).invokeServerPIStartingPoint();
  137. servant =
  138. poaimpl.getServant(objectId, cookieHolder, operation, req);
  139. if (servant == null) {
  140. boolean raiseObjectAdapterException = true;
  141. if (SpecialMethod.isSpecialMethod(operation)) {
  142. SpecialMethod specialMethod =
  143. SpecialMethod.getSpecialMethod(operation);
  144. if (specialMethod instanceof NonExistent ||
  145. specialMethod instanceof NotExistent)
  146. {
  147. raiseObjectAdapterException = false;
  148. }
  149. }
  150. if (raiseObjectAdapterException) {
  151. throw new OBJ_ADAPTER(MinorCodes.NULL_SERVANT,
  152. CompletionStatus.COMPLETED_NO);
  153. }
  154. }
  155. // Store server request interceptor information and invoke
  156. // receive_request if this is not DSI.
  157. // Note: we do not know the MDI on a null servant.
  158. // We only end up in that situation if _non_existent called.
  159. ((POAORB)orb).setServerPIInfo( servant,
  160. (servant == null ?
  161. "unknown" :
  162. servant._all_interfaces( poaimpl, objectId )[0]) );
  163. if( ((servant != null) &&
  164. !(servant instanceof DynamicImplementation) ) ||
  165. SpecialMethod.isSpecialMethod( operation ) )
  166. {
  167. ((POAORB)orb).invokeServerPIIntermediatePoint();
  168. }
  169. mc = MinorCodes.SERVANT_DISPATCH ;
  170. resp = dispatchToServant(servant, req, objectId,
  171. poaimpl, targetScid);
  172. } catch ( POADestroyed ex ) {
  173. if (orb.subcontractDebugFlag)
  174. dprint( "internalDispatch: POADestroyed exception caught" ) ;
  175. // REVISIT: does this need to be called explicitly?
  176. if (poaimpl != null) {
  177. poaimpl.returnServantAndRemoveThreadInfo();
  178. }
  179. // Destroyed POAs can be recreated by normal adapter activation.
  180. // So just restart the dispatch.
  181. return internalDispatch(req, okey);
  182. } catch ( ForwardRequest ex ) {
  183. if (orb.subcontractDebugFlag)
  184. dprint( "internalDispatch: ForwardRequest exception caught" ) ;
  185. return handleInternalDispatchForwardRequest(
  186. (ObjectImpl)ex.forward_reference, req );
  187. } catch ( InternalRuntimeForwardRequest ex ) {
  188. if (orb.subcontractDebugFlag)
  189. dprint( "internalDispatch: InternalRuntimeForwardRequest caught" ) ;
  190. // Thrown by Portable Interceptors from InterceptorInvoker,
  191. // through iiop.ServerResponseImpl constructor.
  192. return handleInternalDispatchForwardRequest(
  193. (ObjectImpl)ex.forward, req );
  194. } catch (RequestCanceledException ex) {
  195. if (orb.subcontractDebugFlag) {
  196. dprint("internalDispatch: RequestCanceledException caught");
  197. }
  198. // No need to do anything specific. This is handled
  199. // out in RequestProcessor.
  200. throw ex;
  201. } catch ( Throwable t ) {
  202. if (orb.subcontractDebugFlag) {
  203. dprint( "internalDispatch: Throwable caught: " + t ) ;
  204. t.printStackTrace( System.out) ;
  205. }
  206. resp = orb.handleThrowableDuringServerDispatch(
  207. req,
  208. t,
  209. CompletionStatus.COMPLETED_MAYBE);
  210. }
  211. return resp ;
  212. }
  213. // Internal utility method to handle a ForwardRequest from within
  214. // internalDispatch.
  215. private ServerResponse handleInternalDispatchForwardRequest(
  216. ObjectImpl foi, com.sun.corba.se.internal.core.ServerRequest req)
  217. {
  218. // Get the IOR from the ForwardRequest and send it back.
  219. ClientSubcontract delegate = (ClientSubcontract)foi._get_delegate();
  220. IOR ior = delegate.marshal();
  221. ServerResponse resp = req.createLocationForward(ior, null);
  222. return resp;
  223. }
  224. // Allow access from ServantCachePOAClientSC
  225. POA getPOA(POAId poaid)
  226. {
  227. if (poaid == null)
  228. throw new INTERNAL() ;
  229. POAORB poaorb = (POAORB)orb;
  230. POA poa=null;
  231. try {
  232. Iterator iter = poaid.iterator() ;
  233. poa = poaorb.getRootPOA();
  234. while (iter.hasNext()) {
  235. String name = (String)(iter.next()) ;
  236. poa = poa.find_POA( name, true ) ;
  237. }
  238. } catch ( org.omg.PortableServer.POAPackage.AdapterNonExistent ex ){
  239. throw new OBJ_ADAPTER(MinorCodes.POA_NOT_FOUND,
  240. CompletionStatus.COMPLETED_NO);
  241. } catch ( OBJECT_NOT_EXIST ex ) {
  242. throw ex;
  243. } catch ( Exception ex ) {
  244. throw new OBJ_ADAPTER(MinorCodes.POA_LOOKUP_ERROR,
  245. CompletionStatus.COMPLETED_NO);
  246. }
  247. if ( poa == null )
  248. throw new OBJ_ADAPTER(MinorCodes.POA_LOOKUP_ERROR,
  249. CompletionStatus.COMPLETED_NO);
  250. return poa;
  251. }
  252. // This is used by the Util.isLocal case in rmi-iiop stubs.
  253. // Called from local stub thru GenericPOAClientSC.
  254. public ServantObject preinvoke(IOR targetIor, String method,
  255. Class expectedType)
  256. {
  257. byte[] objectId = targetIor.getObjectId() ;
  258. POAId poaid = targetIor.getPOAId() ;
  259. // Get servant
  260. CookieHolder cookieHolder = new CookieHolder();
  261. POAImpl poaimpl=null;
  262. Servant servant=null;
  263. try {
  264. poaimpl = (POAImpl)getPOA(poaid);
  265. servant = poaimpl.getServant(objectId, cookieHolder, method, null);
  266. } catch ( POADestroyed ex ) {
  267. if (poaimpl != null) {
  268. poaimpl.returnServantAndRemoveThreadInfo();
  269. }
  270. // Destroyed POAs can be recreated by normal adapter activation.
  271. // So just reinvoke this method.
  272. return preinvoke(targetIor, method, expectedType);
  273. } catch ( ForwardRequest ex ) {
  274. if (poaimpl != null) {
  275. poaimpl.returnServantAndRemoveThreadInfo();
  276. }
  277. // REVISIT: java2idl rtf:
  278. // The isLocal branch does not have a remarshal loop to
  279. // handle ForwardRequest. Therefore, just return null.
  280. return null;
  281. } catch ( ThreadDeath ex ) {
  282. // Balancing happenings in ORB.process.
  283. throw ex;
  284. } catch ( Throwable t ) {
  285. if (poaimpl != null) {
  286. poaimpl.returnServantAndRemoveThreadInfo();
  287. }
  288. SystemException ex;
  289. if ( t instanceof SystemException )
  290. ex = (SystemException)t;
  291. else
  292. ex = new OBJ_ADAPTER(MinorCodes.LOCAL_SERVANT_LOOKUP,
  293. CompletionStatus.COMPLETED_NO);
  294. throw ex;
  295. }
  296. // No exceptions. So handle servant.
  297. if ( servant == null ||
  298. ( ! (servant instanceof Tie)
  299. && !expectedType.isInstance(servant) ) ) {
  300. if (poaimpl != null) {
  301. poaimpl.returnServantAndRemoveThreadInfo();
  302. }
  303. return null;
  304. }
  305. boolean alternateServant = false;
  306. if (servant != null && servant instanceof Tie ) {
  307. if(!expectedType.isInstance(((Tie)servant).getTarget())){
  308. if (poaimpl != null) {
  309. poaimpl.returnServantAndRemoveThreadInfo();
  310. }
  311. return null;
  312. }
  313. else alternateServant = true;
  314. }
  315. ServantObject servantObject = new ServantObject();
  316. if (alternateServant) {
  317. //servant is Tie if alternate servant is set
  318. servantObject.servant = ((Tie)servant).getTarget();
  319. } else {
  320. servantObject.servant = servant;
  321. }
  322. return servantObject;
  323. }
  324. // This is used by the Util.isLocal case in rmi-iiop stubs.
  325. // Called from local stub thru GenericPOAClientSC.
  326. // This will always be called if preinvoke returned a non-null value.
  327. public void postinvoke(IOR targetIor, ServantObject servantobj)
  328. {
  329. POAImpl poaimpl = ((POAORB)orb).getCurrent().getPOA();
  330. // This must be called explicitly since no reply streams are
  331. // created in this case.
  332. poaimpl.returnServantAndRemoveThreadInfo();
  333. }
  334. //dispatching to servant
  335. private ServerResponse dispatchToServant( Servant servant,
  336. com.sun.corba.se.internal.core.ServerRequest req,
  337. byte[] oid, POAImpl poa, int targetScid )
  338. {
  339. if (orb.subcontractDebugFlag)
  340. dprint( "dispatchToServant entered" ) ;
  341. POAORB myorb = (POAORB)orb;
  342. ServerRequestImpl sreq = new ServerRequestImpl(req, orb);
  343. String operation = req.getOperationName();
  344. if (SpecialMethod.isSpecialMethod(operation)) {
  345. if (orb.subcontractDebugFlag)
  346. dprint( "dispatchToServant: handling special method" ) ;
  347. SpecialMethod method = SpecialMethod.getSpecialMethod(operation);
  348. ServerResponse resp = method.invoke(servant, req);
  349. return resp;
  350. }
  351. // COMMENT(Ram J) Null servant checks should happen within the POA contract.
  352. // Look at the POAImpl.internalGetServant(). This method should either
  353. // return a valid servant or raise an appropriate exception.
  354. /*
  355. // According to CORBA V2.3, section 11.2.6, for null servant
  356. // OBJ_ADAPTER Exception should be thrown
  357. if (servant == null)
  358. throw new OBJ_ADAPTER(MinorCodes.NULL_SERVANT,
  359. CompletionStatus.COMPLETED_NO);
  360. */
  361. // POA supports two kinds of servants: those that are instances
  362. // of DynamicImplementation (the IDL/DSI case), and those that are
  363. // instances of InvokeHandler (the IDL/Streams and RMI cases).
  364. boolean isDynamicImplementation =
  365. servant instanceof DynamicImplementation ;
  366. DynamicImplementation dynimpl = null ;
  367. InvokeHandler invhandle = null ;
  368. if (isDynamicImplementation)
  369. dynimpl = (DynamicImplementation)servant;
  370. else
  371. invhandle = (InvokeHandler)servant ;
  372. // Invoke the transaction hooks only if this is not a
  373. // dispatch for a special method.
  374. // Check if the target objref has non-transactional SCID even
  375. // though servant is transactional. If so, get new IOR.
  376. IOR ior = ((POAORB)orb).checkTransactional( servant, oid, poa,
  377. targetScid ) ;
  378. if ( ior != null ) {
  379. if (orb.subcontractDebugFlag) {
  380. dprint( "dispatchToServant: forwarding to new transactional IOR" ) ;
  381. ior.dump() ;
  382. }
  383. return req.createLocationForward(ior, null);
  384. }
  385. // Extract transaction context and deliver it to JTS
  386. receivedRequest(req, operation);
  387. // Makes a down call ORB to set the application specific
  388. // service context fields.
  389. myorb.receivedRequestServiceContexts(req.getServiceContexts());
  390. // Invoke on the servant using the portable DSI skeleton
  391. if (isDynamicImplementation) {
  392. try {
  393. if (orb.subcontractDebugFlag)
  394. dprint( "dispatchToServant: starting dynamic invocation" ) ;
  395. // Note: When/if dynimpl.invoke calls arguments() or
  396. // set_exception() then intermediate points are run.
  397. dynimpl.invoke(sreq);
  398. // Check if ServerRequestImpl.result() has been called
  399. Any excany = sreq.checkResultCalled();
  400. // Create and marshal the ReplyMessage header.
  401. // Get the reply transaction context from JTS if necessary
  402. // and marshal it too.
  403. ServerResponse resp = sendingReply(req, operation, null,
  404. excany);
  405. if ( excany == null ) { // normal return
  406. OutputStream os = (OutputStream)resp;
  407. // Marshal out/inout/return parameters into the ReplyMessage
  408. sreq.marshalReplyParams(os);
  409. }
  410. return resp ;
  411. } catch (SystemException ex) {
  412. return sendingReply(req, operation, ex, null);
  413. } catch( InternalRuntimeForwardRequest ex ) {
  414. // If PI throws a ForwardRequest, it is rethrown as a
  415. // InternalRuntimeForwardRequest. We catch this here so
  416. // we can pass it back to internalDispatch who knows how
  417. // to handle it appropriately.
  418. throw ex;
  419. } catch (RequestCanceledException ex) {
  420. throw ex;
  421. } catch (Throwable ex) {
  422. SystemException ex2 =
  423. orb.convertThrowableToSystemException(
  424. ex,
  425. CompletionStatus.COMPLETED_MAYBE);
  426. return sendingReply(req, operation, ex2, null);
  427. }
  428. } else {
  429. try {
  430. if (orb.subcontractDebugFlag)
  431. dprint( "dispatchToServant: starting invhandler invocation" ) ;
  432. ServerResponse resp =
  433. (ServerResponse)invhandle._invoke(
  434. operation,
  435. (org.omg.CORBA.portable.InputStream)req,
  436. new SubcontractResponseHandler(req,orb) ) ;
  437. return resp;
  438. } catch (UnknownException ex) {
  439. // RMIC generated tie skeletons convert all Throwable exception
  440. // types (including RequestCanceledException, ThreadDeath)
  441. // thrown during reading fragments into UnknownException.
  442. // If RequestCanceledException was indeed raised,
  443. // then rethrow it, which will eventually cause the worker
  444. // thread to unstack the dispatch and wait for other requests.
  445. if (ex.originalEx instanceof RequestCanceledException) {
  446. throw (RequestCanceledException) ex.originalEx;
  447. }
  448. SystemException sys = new UNKNOWN(0,
  449. CompletionStatus.COMPLETED_MAYBE);
  450. ServiceContexts contexts = makeServiceContexts( req ) ;
  451. try {
  452. UEInfoServiceContext uesc = new UEInfoServiceContext(
  453. ex.originalEx ) ;
  454. try {
  455. contexts.put( uesc ) ;
  456. } catch (DuplicateServiceContext dsc) {
  457. // can't happen: contexts only contains a transaction sc, if any
  458. }
  459. } catch (ThreadDeath d) {
  460. throw d;
  461. } catch (Throwable t) {
  462. }
  463. return req.createSystemExceptionResponse(sys,contexts);
  464. } catch (RequestCanceledException ex) {
  465. // IDLJ generated non-tie based skeletons do not catch the
  466. // RequestCanceledException. Rethrow the exception, which will
  467. // cause the worker thread to unwind the dispatch and wait for
  468. // other requests.
  469. throw ex;
  470. } catch (Throwable ex) {
  471. SystemException sex =
  472. orb.convertThrowableToSystemException(
  473. ex,
  474. CompletionStatus.COMPLETED_MAYBE);
  475. return sendingReply(req, operation, sex, null);
  476. }
  477. }
  478. }
  479. protected ClientSubcontract createClientSubcontract(int scid)
  480. {
  481. ClientSubcontract clientRep = new GenericPOAClientSC();
  482. return clientRep;
  483. }
  484. /** Create an objref given an IOR. This may be called while an
  485. * objref is being unmarshalled. Note: the IOR may have been created by
  486. * a foreign ORB.
  487. */
  488. public java.lang.Object createObjref(IOR ior)
  489. {
  490. ObjectKeyTemplate oktemp = ior.getProfile().getTemplate().getObjectKeyTemplate() ;
  491. int scid = oktemp.getSubcontractId() ;
  492. if (scid < ORBConstants.FIRST_POA_SCID)
  493. return super.createObjref(ior) ;
  494. SubcontractRegistry scRegistry = orb.getSubcontractRegistry();
  495. ObjectImpl objref = new CORBAObjectImpl() ;
  496. ClientSubcontract rep ;
  497. // Create a subcontract and stick it in the stub
  498. // XXX Set a transactional subcontract for the foreign objref
  499. // if objref.is_a("TransactionalObject") returns true.
  500. if (ior.isLocal())
  501. rep = createClientSubcontract( scid ) ;
  502. else
  503. rep = scRegistry.getClientSubcontract(oktemp) ;
  504. rep.unmarshal( ior ) ;
  505. rep.setOrb( orb ) ;
  506. objref._set_delegate( (org.omg.CORBA.portable.Delegate)rep ) ;
  507. return objref ;
  508. }
  509. private void throw_object_not_exist()
  510. {
  511. throw new OBJECT_NOT_EXIST(
  512. com.sun.corba.se.internal.orbutil.MinorCodes.BAD_SERVER_ID,
  513. CompletionStatus.COMPLETED_NO);
  514. }
  515. /** Called from ORB.locate when a LocateRequest arrives.
  516. * Need to signal one of OBJECT_HERE, OBJECT_FORWARD, OBJECT_NOT_EXIST.
  517. */
  518. public IOR locate(ObjectKey okey)
  519. {
  520. ObjectKeyTemplate oktemp = okey.getTemplate() ;
  521. int sid = oktemp.getServerId() ;
  522. int scid = oktemp.getSubcontractId() ;
  523. POAORB poaorb = (POAORB)orb;
  524. // XXX Check only serverid. For now, POA checking will be done as
  525. // part of the normal invocation. (i.e. OBJECT_NOT_EXIST may be
  526. // thrown on the normal invocation even though the locate request
  527. // is successful).
  528. if (isTransient( scid ))
  529. if (sid == poaorb.getTransientServerId())
  530. return null ;
  531. else
  532. throw_object_not_exist() ;
  533. // At this point, have a persistent subcontact
  534. if (poaorb.isLocalServerId( scid, sid ))
  535. return null ;
  536. // At this point, either the persistent server ID is not initialized,
  537. // or else the server id of the object key does not match that of the orb.
  538. if ( poaorb.getBadServerIdHandler() != null ) { // e.g. in ORBD
  539. try {
  540. // will always throw an exception: ForwardException
  541. poaorb.getBadServerIdHandler().handle(okey);
  542. return null;
  543. } catch ( ForwardException fex ) {
  544. return fex.getIOR();
  545. }
  546. } else {
  547. throw_object_not_exist() ;
  548. }
  549. // can't get here, but the compiler can't figure that out!
  550. return null ;
  551. }
  552. public Class getClientSubcontractClass()
  553. {
  554. return com.sun.corba.se.internal.POA.GenericPOAClientSC.class;
  555. }
  556. // servant is not supported in this, therefore return false
  557. public boolean isServantSupported()
  558. {
  559. return false;
  560. }
  561. // These methods from ClientSubcontract should not be used for POA objects
  562. public java.lang.Object getServant(byte[] objKey)
  563. {
  564. throw new INTERNAL(MinorCodes.WRONG_CLIENTSC, CompletionStatus.COMPLETED_MAYBE);
  565. }
  566. public void destroyObjref(java.lang.Object objref)
  567. {
  568. // This method should not be invoked on POA objects, but
  569. // just ignore it, since it's harmless and it causes problems
  570. // for EJB currently.
  571. // throw new INTERNAL(MinorCodes.WRONG_CLIENTSC, CompletionStatus.COMPLETED_MAYBE);
  572. }
  573. public java.lang.Object createObjref(byte[] userKey,
  574. java.lang.Object servant)
  575. {
  576. throw new INTERNAL(MinorCodes.WRONG_CLIENTSC, CompletionStatus.COMPLETED_MAYBE);
  577. }
  578. // hooks that can be overridden by subclasses to do subcontract specific
  579. // work; This done as part of POA Transactions split. The JTS or J2EE
  580. // could override these hooks to do their specific stuff
  581. // These methods are overridden in com.sun.corba.se.internal.TransactionalPOA.TransactionalServerSC
  582. public void receivedRequest(com.sun.corba.se.internal.core.ServerRequest req,
  583. String method)
  584. {
  585. }
  586. public ServiceContexts makeServiceContexts(com.sun.corba.se.internal.core.ServerRequest req)
  587. {
  588. POAORB myorb = (POAORB)orb;
  589. ObjectKey okey = req.getObjectKey();
  590. int tscid = okey.getTemplate().getSubcontractId() ;
  591. ServiceContexts scs = new ServiceContexts( orb ) ;
  592. // call any hooks if defined
  593. try {
  594. myorb.sendingReplyServiceContexts(scs);
  595. } catch (Throwable ex) {
  596. ; //Do not let hook errors escape.
  597. }
  598. return scs ;
  599. }
  600. /** Must always be called, just after the servant's method returns.
  601. * Creates the ReplyMessage header and puts in the transaction context
  602. * if necessary.
  603. */
  604. public ServerResponse sendingReply(com.sun.corba.se.internal.core.ServerRequest req,
  605. String method,
  606. SystemException exc,
  607. Any excany)
  608. {
  609. ServiceContexts scs = makeServiceContexts( req ) ;
  610. // Create reply msg
  611. if ( exc == null && excany == null ) { // normal return
  612. return req.createResponse(scs);
  613. } else if ( excany != null ) {
  614. // Check if the servant set a SystemException or
  615. // UserException
  616. ServerResponse resp;
  617. String repId=null;
  618. try {
  619. repId = excany.type().id();
  620. } catch ( org.omg.CORBA.TypeCodePackage.BadKind e ) {}
  621. if ( ORBUtility.isSystemException(repId) ) {
  622. // Get the exception object from the Any
  623. InputStream in = excany.create_input_stream();
  624. SystemException ex = ORBUtility.readSystemException(in);
  625. // Marshal the exception back
  626. resp = req.createSystemExceptionResponse(ex, scs);
  627. } else {
  628. resp = req.createUserExceptionResponse(scs);
  629. OutputStream os = (OutputStream)resp;
  630. excany.write_value(os);
  631. }
  632. return resp;
  633. } else { // SystemException was thrown
  634. return req.createSystemExceptionResponse(exc, scs);
  635. }
  636. }
  637. }