1. /*
  2. * @(#)ClientDelegate.java 1.87 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.corba;
  16. import java.util.Iterator;
  17. import org.omg.CORBA.INTERNAL;
  18. import org.omg.CORBA.ORB;
  19. import org.omg.CORBA.portable.RemarshalException;
  20. import org.omg.CORBA.SystemException;
  21. import org.omg.CORBA.CompletionStatus;
  22. import org.omg.CORBA.WrongTransaction;
  23. import org.omg.CORBA.Request;
  24. import org.omg.CORBA.NamedValue;
  25. import org.omg.CORBA.NVList;
  26. import org.omg.CORBA.Context;
  27. import org.omg.CORBA.ContextList;
  28. import org.omg.CORBA.ExceptionList;
  29. import org.omg.CORBA.TypeCode;
  30. import org.omg.CORBA.DATA_CONVERSION;
  31. import org.omg.CORBA.UNKNOWN;
  32. import org.omg.CORBA.portable.ObjectImpl;
  33. import org.omg.CORBA.portable.InputStream;
  34. import org.omg.CORBA.portable.OutputStream;
  35. import org.omg.CORBA.portable.Delegate;
  36. import org.omg.CORBA.portable.ServantObject;
  37. import org.omg.CORBA.portable.ApplicationException;
  38. import org.omg.CORBA.portable.UnknownException;
  39. import org.omg.IOP.TAG_CODE_SETS;
  40. import javax.rmi.CORBA.Util;
  41. import javax.rmi.CORBA.Tie;
  42. import java.rmi.RemoteException;
  43. import com.sun.org.omg.SendingContext.CodeBase;
  44. import com.sun.corba.se.internal.ior.IIOPProfile;
  45. import com.sun.corba.se.internal.ior.IIOPProfileTemplate;
  46. import com.sun.corba.se.internal.ior.ObjectKey;
  47. import com.sun.corba.se.internal.core.IOR;
  48. import com.sun.corba.se.internal.core.ClientGIOP;
  49. import com.sun.corba.se.internal.core.ClientSubcontract;
  50. import com.sun.corba.se.internal.core.ClientRequest;
  51. import com.sun.corba.se.internal.core.ClientResponse;
  52. import com.sun.corba.se.internal.core.ServiceContext;
  53. import com.sun.corba.se.internal.core.ServiceContexts;
  54. import com.sun.corba.se.internal.core.MarshalOutputStream;
  55. import com.sun.corba.se.internal.core.MarshalInputStream;
  56. import com.sun.corba.se.internal.core.CodeSetComponentInfo;
  57. import com.sun.corba.se.internal.core.CodeSetConversion;
  58. import com.sun.corba.se.internal.core.UEInfoServiceContext;
  59. import com.sun.corba.se.internal.core.CodeSetServiceContext;
  60. import com.sun.corba.se.internal.core.SendingContextServiceContext;
  61. import com.sun.corba.se.internal.core.ORBVersionServiceContext;
  62. import com.sun.corba.se.internal.core.NoSuchServiceContext;
  63. import com.sun.corba.se.internal.core.DuplicateServiceContext;
  64. import com.sun.corba.se.internal.core.GIOPVersion;
  65. import com.sun.corba.se.internal.core.ORBVersion;
  66. import com.sun.corba.se.internal.orbutil.MinorCodes;
  67. import com.sun.corba.se.internal.util.JDKBridge;
  68. import com.sun.corba.se.internal.orbutil.ORBUtility;
  69. import com.sun.corba.se.internal.iiop.messages.ReplyMessage;
  70. import com.sun.corba.se.internal.iiop.Connection;
  71. import com.sun.corba.se.internal.iiop.ClientRequestImpl;
  72. import com.sun.corba.se.internal.iiop.LocalClientRequestImpl;
  73. import com.sun.corba.se.internal.iiop.messages.KeyAddr;
  74. import com.sun.corba.se.internal.core.ORBVersionFactory;
  75. import com.sun.corba.se.internal.ior.CodeSetsComponent;
  76. import com.sun.corba.se.internal.ior.TaggedComponent;
  77. import com.sun.corba.se.internal.orbutil.ORBConstants;
  78. import com.sun.corba.se.internal.iiop.messages.KeyAddr;
  79. import com.sun.corba.se.internal.iiop.messages.ProfileAddr;
  80. import com.sun.corba.se.internal.iiop.messages.ReferenceAddr;
  81. /**
  82. * ClientDelegate is the RMI client-side subcontract or representation
  83. * It implements RMI delegate as well as our internal ClientSubcontract
  84. * interface.
  85. */
  86. public class ClientDelegate
  87. extends org.omg.CORBA_2_3.portable.Delegate
  88. implements ClientSubcontract
  89. {
  90. protected void dprint( String msg )
  91. {
  92. ORBUtility.dprint( this, msg ) ;
  93. }
  94. protected com.sun.corba.se.internal.corba.ORB orb;
  95. protected IOR ior;
  96. protected IOR locatedIOR;
  97. protected boolean isCachedHashValue = false;
  98. protected int cachedHashValue;
  99. protected int scid; // my subcontract id
  100. protected ServantObject servant;
  101. protected ClassLoader servantClassLoader ;
  102. protected short addressingDisposition = KeyAddr.value;
  103. protected ThreadLocal isNextIsLocalValid = new ThreadLocal( ) {
  104. protected Object initialValue( ) {
  105. return Boolean.TRUE;
  106. }
  107. };
  108. // the connection with which to store the codebase returned by the
  109. // server
  110. // orb version to be stored into thread local
  111. public ClientDelegate() {
  112. super();
  113. servant = null;
  114. }
  115. public ClientDelegate(com.sun.corba.se.internal.corba.ORB orb,
  116. IOR ior,
  117. int id)
  118. {
  119. this(orb,ior,id,null);
  120. }
  121. public ClientDelegate(com.sun.corba.se.internal.corba.ORB orb,
  122. IOR ior,
  123. int id,
  124. java.lang.Object servant)
  125. {
  126. this();
  127. setOrb(orb);
  128. this.ior = ior;
  129. this.locatedIOR = ior;
  130. this.scid = id;
  131. if (servant != null && servant instanceof Tie) {
  132. servantClassLoader = servant.getClass().getClassLoader() ;
  133. this.servant = new ServantObject();
  134. this.servant.servant = ((Tie)servant).getTarget();
  135. } else {
  136. this.servant = null;
  137. servantClassLoader = null ;
  138. }
  139. }
  140. public void unexport() {
  141. // DO NOT set the IOR to null. (Un)exporting is only concerns
  142. // the servant not the IOR. If the ior is set to null then
  143. // null pointer exceptions happen during an colocated invocation.
  144. // It is better to let the invocation proceed and get OBJECT_NOT_EXIST
  145. // from the server side.
  146. //ior = null;
  147. servant = null;
  148. }
  149. public IOR marshal() {
  150. return ior;
  151. }
  152. public IOR getIOR() {
  153. return ior;
  154. }
  155. public IOR getLocatedIOR() {
  156. return locatedIOR;
  157. }
  158. public void unmarshal(IOR ior) {
  159. this.ior = ior;
  160. this.locatedIOR = ior;
  161. }
  162. public void setAddressingDisposition(short value){
  163. this.addressingDisposition = value;
  164. }
  165. public short getAddressingDisposition() {
  166. return this.addressingDisposition;
  167. }
  168. public void setLocatedIOR( IOR locatedIOR ) {
  169. this.locatedIOR = locatedIOR;
  170. }
  171. public void setId(int id) {
  172. this.scid = id;
  173. }
  174. public int getId()
  175. {
  176. return scid ;
  177. }
  178. public void setOrb(com.sun.corba.se.internal.core.ORB orb) {
  179. this.orb = (com.sun.corba.se.internal.corba.ORB) orb;
  180. this.addressingDisposition = this.orb.getGIOPAddressDisposition();
  181. }
  182. /*
  183. * NOTE: This version of invoke should ONLY be used externally
  184. * by a DII call (it is used internally by the streams invoke).
  185. * Otherwise the PortableInterceptor internal stack will become
  186. * unbalanced.
  187. *
  188. * It is invoked from the DII implementation: RequestImpl.doInvocation().
  189. *
  190. * invoke(org.omg.CORBA.Object, OutputStream) calls this one, so
  191. * do any service context processing here.
  192. *
  193. * This is also called from GenericPOAClientSC's
  194. * invoke(org.omg.CORBA.Object, OutputStream).
  195. */
  196. public ClientResponse invoke(ClientRequest request) {
  197. if (orb.subcontractDebugFlag)
  198. dprint( "invoke(ClientRequest) called" ) ;
  199. ClientResponse resp = request.invoke();
  200. // We know for sure now that we've sent a message.
  201. // So OK to not send initial again.
  202. if (request.getConnection() != null) {
  203. request.getConnection().setPostInitialContexts();
  204. }
  205. // Notify Portable Interceptors of client response.
  206. // This must happen here so that both stream-based and DII
  207. // calls have their hands on the response.
  208. orb.setClientPIInfo( resp );
  209. if (request.isOneWay()) {
  210. return null;
  211. }
  212. consumeServiceContexts(resp);
  213. // Now that we have the service contexts processed and the
  214. // correct ORBVersion set, we must finish initializing the
  215. // stream.
  216. resp.performORBVersionSpecificInit();
  217. // FIX(Ram J) (04/28/2000) The location forwarded behaviour and the
  218. // system exception(COMM_FAILURE) behaviour (i.e retry from root ior)
  219. // is handled in this.invoke(Object, OutputStream) which called this
  220. // method. The client stubs should not directly call this method.
  221. // However, there are a few methods in the ClientDelegate : is_a(),
  222. // get_interface_def() and non_existent() which directly call
  223. // this method. Such methods should handle the location forwarded
  224. // responses by building new requests and system exception(COMM_FAILURE)
  225. // responses by retrying from root ior.
  226. return resp;
  227. }
  228. /*
  229. * This version of invoke should be used by everthing but a DII call.
  230. */
  231. public InputStream invoke(org.omg.CORBA.Object self, OutputStream out)
  232. throws ApplicationException,
  233. org.omg.CORBA.portable.RemarshalException
  234. {
  235. ClientRequest request = (ClientRequest) out;
  236. ClientResponse response = this.invoke(request);
  237. // For PI code:
  238. Exception exception = null;
  239. if (request.isOneWay()) { //oneway calls
  240. // Invoke Portable Interceptors with receive_other
  241. exception = orb.invokeClientPIEndingPoint(
  242. ReplyMessage.NO_EXCEPTION, exception );
  243. continueOrThrowSystemOrRemarshal( exception );
  244. return null;
  245. }
  246. // COMMENT(Ram J) 10/01/2000 There is no need to set the response
  247. // stream's connection to that of the request stream. The response
  248. // stream will have a connection associated if the response had been
  249. // built out of the server response; else if the response was built out
  250. // of SystemException arising out of response handling, then there
  251. // will be no connection or service context available with the response
  252. // stream. In such a case, the consumeServiceContexts has to return
  253. // gracefully.
  254. /*
  255. // consume service contexts that were returned to the client
  256. Connection c = request.getConnection();
  257. if (response != null)
  258. response.setConnection(c);
  259. */
  260. // Processing of service contexts is done in invoke(ClientRequest)
  261. if (response.isSystemException()) {
  262. SystemException se = response.getSystemException();
  263. boolean doRemarshal = false;
  264. // FIX(Ram J) (04/28/2000) added locatedIOR = ior
  265. // and throw RemarshallException to force retrying
  266. // from root ior, if system exception is COMM_FAILURE.
  267. // WARNING: There is a risk of infinite loopback if the requests on
  268. // location forwarded ior result in system exception (COMM_FAILURE)
  269. if (se instanceof org.omg.CORBA.COMM_FAILURE
  270. && se.completed == CompletionStatus.COMPLETED_NO) {
  271. if (locatedIOR != ior) {
  272. locatedIOR = ior; // retry from root ior
  273. doRemarshal = true;
  274. }
  275. }
  276. /* This used to live in a loop in IIOPOutputStream.invoke.
  277. That loop had a retry count to bound the number of tries.
  278. However that loop did not work once fragmentation was
  279. put in. So it was moved here. However, there is no
  280. place to hang the count since this throws out to the Stub.
  281. We need invocation level (i.e., thread local) date like
  282. in PI to put this count. That is scheduled for Taggart.
  283. For now, just turn this off.
  284. if (se.minor == MinorCodes.CONN_CLOSE_REBIND &&
  285. (se instanceof org.omg.CORBA.COMM_FAILURE)) {
  286. doRemarshal = true;
  287. }
  288. */
  289. if (doRemarshal) {
  290. // Invoke Portable Interceptors with receive_exception:
  291. exception = orb.invokeClientPIEndingPoint(
  292. ReplyMessage.SYSTEM_EXCEPTION, se );
  293. // If PI did not change the exception, throw a
  294. // Remarshal. Otherwise, throw the exception PI
  295. // wants thrown.
  296. if( se == exception ) {
  297. // exception = null is to maintain symmetry with
  298. // GenericPOAClientSC.
  299. //exception = null;
  300. throw new RemarshalException();
  301. }
  302. else {
  303. continueOrThrowSystemOrRemarshal( exception );
  304. throw new INTERNAL("Assertion failed. " +
  305. "exception should not be null." );
  306. }
  307. }
  308. ServiceContexts contexts = response.getServiceContexts();
  309. if (contexts != null) {
  310. try {
  311. UEInfoServiceContext usc =
  312. (UEInfoServiceContext)
  313. contexts.get(UEInfoServiceContext.SERVICE_CONTEXT_ID);
  314. Throwable unknown = usc.getUE() ;
  315. UnknownException ue = new UnknownException(unknown);
  316. // Invoke Portable Interceptors with receive_exception:
  317. exception = orb.invokeClientPIEndingPoint(
  318. ReplyMessage.SYSTEM_EXCEPTION, ue );
  319. continueOrThrowSystemOrRemarshal( exception );
  320. throw new INTERNAL(
  321. "Assertion failed. exception should not be null." );
  322. } catch (NoSuchServiceContext exc) {
  323. // NO-OP: handled by system exception below
  324. }
  325. }
  326. // Invoke Portable Interceptors with receive_exception:
  327. exception = orb.invokeClientPIEndingPoint(
  328. ReplyMessage.SYSTEM_EXCEPTION, se );
  329. continueOrThrowSystemOrRemarshal( exception );
  330. // Note: We should never need to execute this line, but
  331. // we should assert in case exception is null somehow.
  332. throw new INTERNAL(
  333. "Assertion failed: exception should not be null." );
  334. } else if (response.isUserException()) {
  335. ApplicationException appException =
  336. new ApplicationException(response.peekUserExceptionId(),
  337. (org.omg.CORBA.portable.InputStream)response);
  338. // Invoke Portable Interceptors with receive_exception
  339. // (user exception):
  340. exception = orb.invokeClientPIEndingPoint(
  341. ReplyMessage.USER_EXCEPTION, appException );
  342. if( !(exception instanceof ApplicationException) ) {
  343. continueOrThrowSystemOrRemarshal( exception );
  344. }
  345. throw (ApplicationException)exception;
  346. } else if (response.isLocationForward()) {
  347. // FIX(Ram J) (04/28/2000) added setting locatedIOR
  348. locatedIOR = response.getForwardedIOR();
  349. // Invoke Portable Interceptors with receive_other:
  350. Exception newException = orb.invokeClientPIEndingPoint(
  351. ReplyMessage.LOCATION_FORWARD, null );
  352. // For consistency with corresponding code in GenericPOAClientSC:
  353. if( !(newException instanceof RemarshalException) ) {
  354. exception = newException;
  355. }
  356. // If PI did not change exception, throw Remarshal, else
  357. // throw the exception PI wants thrown.
  358. if( exception != null ) {
  359. continueOrThrowSystemOrRemarshal( exception );
  360. }
  361. throw new org.omg.CORBA.portable.RemarshalException();
  362. } else if (response.isDifferentAddrDispositionRequested()) {
  363. // set the desired target addressing disposition.
  364. addressingDisposition = response.getAddrDisposition();
  365. // Invoke Portable Interceptors with receive_other:
  366. Exception newException = orb.invokeClientPIEndingPoint(
  367. ReplyMessage.NEEDS_ADDRESSING_MODE, null);
  368. // For consistency with corresponding code in GenericPOAClientSC:
  369. if( !(newException instanceof RemarshalException) ) {
  370. exception = newException;
  371. }
  372. // If PI did not change exception, throw Remarshal, else
  373. // throw the exception PI wants thrown.
  374. if( exception != null ) {
  375. continueOrThrowSystemOrRemarshal( exception );
  376. }
  377. throw new org.omg.CORBA.portable.RemarshalException();
  378. } else /* normal response */ {
  379. // Invoke Portable Interceptors with receive_reply:
  380. exception = orb.invokeClientPIEndingPoint(
  381. ReplyMessage.NO_EXCEPTION, null );
  382. // Remember: not thrown if exception is null.
  383. continueOrThrowSystemOrRemarshal( exception );
  384. return (InputStream) response;
  385. }
  386. }
  387. // Filters the given exception into a SystemException or a
  388. // RemarshalException and throws it. Assumes the given exception is
  389. // of one of these two types. This is a utility method for
  390. // the above invoke code which must do this numerous times.
  391. // If the exception is null, no exception is thrown.
  392. //
  393. // Note that this code is duplicated in GenericPOAClientSC.java
  394. private void continueOrThrowSystemOrRemarshal( Exception exception )
  395. throws SystemException, RemarshalException
  396. {
  397. if( exception == null ) {
  398. // do nothing.
  399. }
  400. else if( exception instanceof RemarshalException ) {
  401. throw (RemarshalException)exception;
  402. }
  403. else {
  404. throw (SystemException)exception;
  405. }
  406. }
  407. public ServiceContexts getServiceContexts( Connection c,
  408. int requestId, String opName, boolean isOneWay, GIOPVersion giopVersion )
  409. {
  410. ServiceContexts contexts = new ServiceContexts( orb ) ;
  411. addCodeSetServiceContext(c, contexts, giopVersion);
  412. // ORBVersion servicecontext needs to be sent
  413. ORBVersionServiceContext ovsc = new ORBVersionServiceContext(
  414. ORBVersionFactory.getORBVersion() ) ;
  415. try {
  416. contexts.put( ovsc ) ;
  417. } catch (DuplicateServiceContext dsc) {
  418. throw new INTERNAL() ;
  419. }
  420. // NOTE : We only want to send the runtime context the first time
  421. if ((c != null) && !c.isPostInitialContexts()) {
  422. // Do not do c.setPostInitialContexts() here.
  423. // If a client interceptor send_request does a ForwardRequest
  424. // which ends up using the same connection then the service
  425. // context would not be sent.
  426. SendingContextServiceContext scsc =
  427. new SendingContextServiceContext( orb.getServantIOR() ) ; //d11638
  428. try {
  429. contexts.put( scsc ) ;
  430. } catch (DuplicateServiceContext dsc) {
  431. throw new INTERNAL() ;
  432. }
  433. }
  434. return contexts ;
  435. }
  436. public void consumeServiceContexts(ClientResponse response)
  437. {
  438. ServiceContexts ctxts = response.getServiceContexts();
  439. ServiceContext sc ;
  440. if (ctxts == null) {
  441. return; // no service context available, return gracefully.
  442. }
  443. try {
  444. sc = ctxts.get( SendingContextServiceContext.SERVICE_CONTEXT_ID ) ;
  445. SendingContextServiceContext scsc =
  446. (SendingContextServiceContext)sc ;
  447. IOR ior = scsc.getIOR() ;
  448. try {
  449. // set the codebase returned by the server
  450. if (response.getConnection() != null) {
  451. response.getConnection().setCodeBaseIOR(ior);
  452. }
  453. } catch (ThreadDeath td) {
  454. throw td ;
  455. } catch (Throwable t) {
  456. throw new DATA_CONVERSION( MinorCodes.BAD_STRINGIFIED_IOR,
  457. CompletionStatus.COMPLETED_NO);
  458. }
  459. } catch (NoSuchServiceContext exc) {
  460. // ignore: this type not present
  461. }
  462. // see if the version subcontract is present, if yes, then set
  463. // the ORBversion
  464. try {
  465. sc = ctxts.get( ORBVersionServiceContext.SERVICE_CONTEXT_ID ) ;
  466. ORBVersionServiceContext ovsc =
  467. (ORBVersionServiceContext) sc;
  468. ORBVersion version = ovsc.getVersion();
  469. orb.setORBVersion( version ) ;
  470. } catch (NoSuchServiceContext exc) {
  471. // ignore: this type not present
  472. // If we were talking to Kestrel, we would have set the
  473. // ORB version as such at invoke time after examining
  474. // the IOR.
  475. }
  476. }
  477. /*
  478. * This is the method used by the rest of the system to
  479. * create requests. It is used both my streams-based stubs
  480. * and by DII-based calls (i.e., from RequestImpl.doInvocation()
  481. * before marshaling arguments.
  482. */
  483. public ClientRequest createRequest( String opName, boolean isOneWay )
  484. {
  485. // Create request object which is also the outputstream
  486. ClientRequest request = null;
  487. ClientGIOP giop = orb.getClientGIOP();
  488. int id = giop.allocateRequestId() ;
  489. // Initiate this request with Portable Interceptors.
  490. // This is done here so if the following COMM_FAILURE occurs we will
  491. // keep the PI ClientRequestInfo stack balanced. The COMM_FAILURE
  492. // happens before invoking starting points in getConnection so we
  493. // don't need to invoke ending points.
  494. orb.initiateClientPIRequest( false );
  495. try {
  496. request = createRequest( locatedIOR, opName, isOneWay, id );
  497. } catch (org.omg.CORBA.COMM_FAILURE ex) {
  498. if (locatedIOR == ior) {
  499. throw ex;
  500. }
  501. // The COMM_FAILURE may have happened because the server died.
  502. // Try creating the request with the original IOR.
  503. request = createRequest(ior, opName, isOneWay, id);
  504. }
  505. return request;
  506. }
  507. /*
  508. * This helper method actually creates the approprieate
  509. * request object.
  510. */
  511. protected ClientRequest createRequest(IOR iorForThisRequest, String opName,
  512. boolean isOneWay, int requestId)
  513. {
  514. IIOPProfile iop = iorForThisRequest.getProfile();
  515. ObjectKey key = iop.getObjectKey();
  516. Connection conn = null ;
  517. ServiceContexts svc = null ;
  518. GIOPVersion giopVersion =
  519. GIOPVersion.chooseRequestVersion(orb, iorForThisRequest);
  520. if (iorForThisRequest.isLocal()) {
  521. svc = getServiceContexts( conn, requestId, opName, isOneWay, giopVersion ) ;
  522. // Set the sources of info for the Portable Interceptors
  523. // ClientRequestInfo object, and invoke the client interceptor
  524. // starting points. Note these 2 lines are duplicated below.
  525. // We explicitly pass in the effective target in
  526. // case it is different than the locatedIOR field. For example,
  527. // in case of the COMM_FAILURE in the other createRequest().
  528. orb.setClientPIInfo( null, this, iorForThisRequest, iop, requestId,
  529. opName, isOneWay, svc );
  530. try {
  531. orb.invokeClientPIStartingPoint();
  532. }
  533. catch( RemarshalException e ) {
  534. // If this is a forward request, recursively call createRequest
  535. // with the located IOR.
  536. return createRequest( locatedIOR, opName, isOneWay, requestId);
  537. }
  538. return new LocalClientRequestImpl(
  539. GIOPVersion.V1_2,
  540. (com.sun.corba.se.internal.iiop.ORB)orb,
  541. iorForThisRequest, this.addressingDisposition,
  542. opName, isOneWay, svc, requestId);
  543. } else {
  544. conn = orb.getClientGIOP().getConnection(iorForThisRequest);
  545. // Code set negotiation occurs on the first request
  546. if (conn != null && conn.getCodeSetContext() == null)
  547. performCodeSetNegotiation(conn, giopVersion);
  548. svc = getServiceContexts( conn, requestId, opName, isOneWay, giopVersion ) ;
  549. // Set Portable Interceptors info. See above comment.
  550. orb.setClientPIInfo( conn, this, iorForThisRequest, iop, requestId,
  551. opName, isOneWay, svc );
  552. try {
  553. orb.invokeClientPIStartingPoint();
  554. }
  555. catch( RemarshalException e ) {
  556. // If this is a forward request, recursively call createRequest
  557. // with the located IOR.
  558. return createRequest( locatedIOR, opName, isOneWay, requestId);
  559. }
  560. return new ClientRequestImpl(giopVersion, iorForThisRequest,
  561. this.addressingDisposition,
  562. opName, isOneWay, svc,
  563. requestId, conn);
  564. }
  565. }
  566. // Invoked by DII layer (from RequestImpl.doInvocation())
  567. // after unmarshaling reply and exceptions.
  568. public void releaseReply(ClientResponse resp, String method,
  569. Exception exception)
  570. throws WrongTransaction, SystemException
  571. {
  572. }
  573. public void releaseReply(org.omg.CORBA.Object self,
  574. InputStream input)
  575. {
  576. orb.sendCancelRequestIfFinalFragmentNotSent();
  577. // Invoke Portable Interceptors cleanup. This is done to handle
  578. // exceptions during stream marshaling. More generally, exceptions
  579. // that occur in the ORB after send_request (which includes
  580. // after returning from _request) before _invoke:
  581. orb.cleanupClientPIRequest();
  582. }
  583. public boolean is_equivalent(org.omg.CORBA.Object obj,
  584. org.omg.CORBA.Object ref)
  585. {
  586. if ( ref == null )
  587. return false;
  588. ObjectImpl oi = (ObjectImpl)ref;
  589. ClientSubcontract del = (ClientSubcontract)oi._get_delegate();
  590. if (del == this)
  591. return true;
  592. if (!(del instanceof ClientDelegate))
  593. return false;
  594. return ior.isEquivalent(del.marshal());
  595. }
  596. public int hash(org.omg.CORBA.Object obj, int maximum)
  597. {
  598. int h = this.hashCode();
  599. if ( h > maximum )
  600. return 0;
  601. return h;
  602. }
  603. public int hashCode()
  604. {
  605. // This is not synchronized since the returned value is constant
  606. // so the overhead of synchronization is unnecessary.
  607. if (! isCachedHashValue) {
  608. cachedHashValue = ior.stringify().hashCode();
  609. isCachedHashValue = true;
  610. }
  611. return cachedHashValue;
  612. }
  613. public org.omg.CORBA.Object duplicate(org.omg.CORBA.Object orig) {
  614. return orig;
  615. }
  616. public void release(org.omg.CORBA.Object obj) {
  617. // DONT clear out internal variables to release memory !!
  618. // This delegate may be pointed-to by other objrefs !
  619. }
  620. public org.omg.CORBA.Request create_request(org.omg.CORBA.Object obj,
  621. org.omg.CORBA.Context ctx,
  622. String operation,
  623. org.omg.CORBA.NVList arg_list,
  624. org.omg.CORBA.NamedValue result)
  625. {
  626. return new RequestImpl(orb, obj, ctx, operation, arg_list,
  627. result, null, null);
  628. }
  629. public org.omg.CORBA.Request request(org.omg.CORBA.Object obj,
  630. String operation)
  631. {
  632. return new RequestImpl(orb, obj, null, operation, null, null, null,
  633. null);
  634. }
  635. public org.omg.CORBA.ORB orb(org.omg.CORBA.Object self)
  636. {
  637. return this.orb;
  638. }
  639. public org.omg.CORBA.Request create_request(org.omg.CORBA.Object obj,
  640. org.omg.CORBA.Context ctx,
  641. String operation,
  642. org.omg.CORBA.NVList arg_list,
  643. org.omg.CORBA.NamedValue result,
  644. org.omg.CORBA.ExceptionList exclist,
  645. org.omg.CORBA.ContextList ctxlist)
  646. {
  647. return new RequestImpl(orb, obj, ctx, operation, arg_list, result,
  648. exclist, ctxlist);
  649. }
  650. private static String AppExcInSpecialMethod =
  651. "ApplicationException in SpecialMethod - should not happen";
  652. public org.omg.CORBA.Object get_interface_def(org.omg.CORBA.Object obj)
  653. {
  654. InputStream is = null;
  655. try {
  656. ClientRequest os = createRequest("_interface", false);
  657. is = (InputStream) invoke((org.omg.CORBA.Object)null,
  658. (OutputStream)os);
  659. ObjectImpl objimpl = (ObjectImpl) is.read_Object();
  660. // check if returned object is of correct type
  661. if ( !objimpl._is_a("IDL:omg.org/CORBA/InterfaceDef:1.0") )
  662. throw new org.omg.CORBA.UNKNOWN(
  663. "InterfaceDef object of wrong type returned by server", 0,
  664. CompletionStatus.COMPLETED_MAYBE);
  665. // instantiate the stub
  666. ObjectImpl stub;
  667. try {
  668. stub = (ObjectImpl)
  669. JDKBridge.loadClass("org.omg.CORBA._InterfaceDefStub").
  670. newInstance();
  671. } catch (Exception ex) {
  672. throw new org.omg.CORBA.UNKNOWN(
  673. "org.omg.CORBA._InterfaceDefStub class not available", 0,
  674. CompletionStatus.COMPLETED_NO);
  675. }
  676. org.omg.CORBA.portable.Delegate del = objimpl._get_delegate();
  677. stub._set_delegate(del);
  678. return stub;
  679. } catch (ApplicationException e) {
  680. // This cannot happen.
  681. throw new INTERNAL(AppExcInSpecialMethod);
  682. } catch (RemarshalException e) {
  683. return get_interface_def(obj);
  684. } finally {
  685. releaseReply((org.omg.CORBA.Object)null, (InputStream)is);
  686. }
  687. }
  688. public boolean is_a(org.omg.CORBA.Object obj, String dest)
  689. {
  690. // dest is the typeId of the interface to compare against.
  691. // repositoryIds is the list of typeIds that the stub knows about.
  692. // First we look for an answer using local information.
  693. String [] repositoryIds = ((ObjectImpl)obj)._ids();
  694. String myid = ior.getTypeId();
  695. if ( dest.equals(myid) ) {
  696. return true;
  697. }
  698. for ( int i=0; i<repositoryIds.length; i++ ) {
  699. if ( dest.equals(repositoryIds[i]) ) {
  700. return true;
  701. }
  702. }
  703. // But repositoryIds may not be complete, so it may be necessary to
  704. // go to server.
  705. InputStream is = null;
  706. try {
  707. ClientRequest os = createRequest("_is_a", false);
  708. os.write_string(dest);
  709. is = (InputStream) invoke((org.omg.CORBA.Object) null,
  710. (OutputStream)os);
  711. return is.read_boolean();
  712. } catch (ApplicationException e) {
  713. // This cannot happen.
  714. throw new INTERNAL(AppExcInSpecialMethod);
  715. } catch (RemarshalException e) {
  716. return is_a(obj, dest);
  717. } finally {
  718. releaseReply((org.omg.CORBA.Object)null, (InputStream)is);
  719. }
  720. }
  721. public boolean non_existent(org.omg.CORBA.Object obj)
  722. {
  723. InputStream is = null;
  724. try {
  725. ClientRequest os = createRequest("_non_existent", false);
  726. is = (InputStream) invoke((org.omg.CORBA.Object)null,
  727. (OutputStream)os);
  728. return is.read_boolean();
  729. } catch (ApplicationException e) {
  730. // This cannot happen.
  731. throw new INTERNAL(AppExcInSpecialMethod);
  732. } catch (RemarshalException e) {
  733. return non_existent(obj);
  734. } finally {
  735. releaseReply((org.omg.CORBA.Object)null, (InputStream)is);
  736. }
  737. }
  738. public OutputStream request(org.omg.CORBA.Object self,
  739. String operation,
  740. boolean responseExpected) {
  741. return (OutputStream) createRequest(operation, !responseExpected);
  742. }
  743. /**
  744. * Returns true if this object is implemented by a local servant.
  745. * We maintain a ThreadLocal to keep track of isLocal() calls to make
  746. * sure that we do not loop more than 2 times. In the first call we
  747. * set the isNextIsLocalValid to false so that the next call on the same
  748. * thread would force to return false in case servant_preinvoke() returns
  749. * null.
  750. *
  751. * @param self The object reference which delegated to this delegate.
  752. * @return true only if the servant incarnating this object is located in
  753. * this Java VM. Return false if the servant is not local or the ORB
  754. * does not support local stubs for this particular servant. The default
  755. * behavior of is_local() is to return false.
  756. */
  757. public boolean is_local(org.omg.CORBA.Object self) {
  758. if ( ((Boolean) isNextIsLocalValid.get()).booleanValue( ) == true ) {
  759. return ior.isLocal();
  760. }
  761. isNextIsLocalValid.set( Boolean.TRUE );
  762. return false;
  763. }
  764. public boolean useLocalInvocation( org.omg.CORBA.Object self )
  765. {
  766. return false ;
  767. }
  768. /**
  769. * Returns a Java reference to the servant which should be used for this
  770. * request. servant_preinvoke() is invoked by a local stub.
  771. * If a ServantObject object is returned, then its servant field
  772. * has been set to an object of the expected type (Note: the object may
  773. * or may not be the actual servant instance). The local stub may cast
  774. * the servant field to the expected type, and then invoke the operation
  775. * directly. The ServantRequest object is valid for only one invocation,
  776. * and cannot be used for more than one invocation.
  777. *
  778. * @param self The object reference which delegated to this delegate.
  779. *
  780. * @param operation a string containing the operation name.
  781. * The operation name corresponds to the operation name as it would be
  782. * encoded in a GIOP request.
  783. *
  784. * @param a Class object representing the expected type of the servant.
  785. * The expected type is the Class object associated with the operations
  786. * class of the stub's interface (e.g. A stub for an interface Foo,
  787. * would pass the Class object for the FooOperations interface).
  788. *
  789. * @return a ServantObject object.
  790. * The method may return a null value if it does not wish to support
  791. * this optimization (e.g. due to security, transactions, etc).
  792. * The method must return null if the servant is not of the expected type.
  793. */
  794. public ServantObject servant_preinvoke(org.omg.CORBA.Object self,
  795. String operation,
  796. Class expectedType) {
  797. if (servant != null &&
  798. expectedType.isAssignableFrom(servant.servant.getClass())) {
  799. // _REVISIT_ Security check? If we put a security check
  800. // on the client side of a connection (IIOPConnection.send()?)
  801. // to ensure that the client has permission, do so here as
  802. // well. Since a permission check is done when the socket
  803. // is initially opened, but not on each use, we probably
  804. // need to do the check ourselves since the call stack can
  805. // be completely different each time, and a new caller may
  806. // not have permission.
  807. return servant;
  808. }
  809. // Set it to false to disallow isLocal to be called again and again
  810. // in case of servant being null in _servant_preinvoke() call
  811. isNextIsLocalValid.set( Boolean.FALSE );
  812. return null;
  813. }
  814. /* Returns the codebase for object reference provided.
  815. * @param self the object reference whose codebase needs to be returned.
  816. * @return the codebase as a space delimited list of url strings or
  817. * null if none.
  818. */
  819. public String get_codebase(org.omg.CORBA.Object self) {
  820. if (ior != null) {
  821. return ior.getCodebase();
  822. }
  823. return null;
  824. }
  825. public String toString() {
  826. return ior.stringify();
  827. }
  828. /**
  829. * This method overrides the org.omg.CORBA.portable.Delegate.equals method,
  830. * and does the equality check based on IOR equality.
  831. */
  832. public boolean equals(org.omg.CORBA.Object self, java.lang.Object other) {
  833. if (!(other instanceof ObjectImpl)) {
  834. return false;
  835. }
  836. ObjectImpl otherObj = (ObjectImpl) other;
  837. if (otherObj._get_delegate() instanceof ClientDelegate) {
  838. ClientDelegate otherDel = (ClientDelegate) otherObj._get_delegate();
  839. IOR otherIor = otherDel.getIOR();
  840. return this.ior.equals(otherIor);
  841. } else if (otherObj._get_delegate() instanceof Delegate) {
  842. return super.equals(self, other);
  843. }
  844. return false;
  845. }
  846. private void performCodeSetNegotiation(Connection conn,
  847. GIOPVersion giopVersion) {
  848. // conn.getCodeSetContext() is null when no other requests have
  849. // been made on this connection to trigger code set negotation.
  850. if (conn != null &&
  851. conn.getCodeSetContext() == null &&
  852. !giopVersion.equals(GIOPVersion.V1_0)) {
  853. synchronized(conn) {
  854. // Double checking. Don't let any other
  855. // threads use this connection until the
  856. // code sets are straight.
  857. if (conn.getCodeSetContext() != null)
  858. return;
  859. // This only looks at the first code set component. If
  860. // there can be multiple locations with multiple code sets,
  861. // this requires more work.
  862. IIOPProfileTemplate temp = getLocatedIOR().getProfile().getTemplate();
  863. Iterator iter = temp.iteratorById(TAG_CODE_SETS.value);
  864. if (!iter.hasNext()) {
  865. // Didn't have a code set component. The default will
  866. // be to use ISO8859-1 for char data and throw an
  867. // exception if wchar data is used.
  868. return;
  869. }
  870. // Get the native and conversion code sets the
  871. // server specified in its IOR
  872. CodeSetComponentInfo serverCodeSets
  873. = ((CodeSetsComponent)iter.next()).getCodeSetComponentInfo();
  874. // Perform the negotiation between this ORB's code sets and
  875. // the ones from the IOR
  876. CodeSetComponentInfo.CodeSetContext result
  877. = CodeSetConversion.impl().negotiate(conn.getORB().getCodeSetComponentInfo(),
  878. serverCodeSets);
  879. conn.setCodeSetContext(result);
  880. }
  881. }
  882. }
  883. private void addCodeSetServiceContext(Connection conn,
  884. ServiceContexts ctxs,
  885. GIOPVersion giopVersion) {
  886. // REVISIT. OMG issue 3318 concerning sending the code set
  887. // service context more than once was deemed too much for the
  888. // RTF. Here's our strategy for the moment:
  889. //
  890. // Send it on every request (necessary in cases of fragmentation
  891. // with multithreaded clients or when the first thing on a
  892. // connection is a LocateRequest). Provide an ORB property
  893. // to disable multiple sends.
  894. //
  895. // Note that the connection is null in the local case and no
  896. // service context is included. We use the ORB provided
  897. // encapsulation streams.
  898. //
  899. // Also, there will be no negotiation or service context
  900. // in GIOP 1.0. ISO8859-1 is used for char/string, and
  901. // wchar/wstring are illegal.
  902. //
  903. if (giopVersion.equals(GIOPVersion.V1_0) || conn == null)
  904. return;
  905. CodeSetComponentInfo.CodeSetContext codeSetCtx = null;
  906. if (conn.getORB().alwaysSendCodeSetServiceContext() ||
  907. !conn.isPostInitialContexts()) {
  908. // Get the negotiated code sets (if any) out of the connection
  909. codeSetCtx = conn.getCodeSetContext();
  910. }
  911. // Either we shouldn't send the code set service context, or
  912. // for some reason, the connection doesn't have its code sets.
  913. // Perhaps the server didn't include them in the IOR. Uses
  914. // ISO8859-1 for char and makes wchar/wstring illegal.
  915. if (codeSetCtx == null)
  916. return;
  917. CodeSetServiceContext cssc = new CodeSetServiceContext(codeSetCtx);
  918. try {
  919. ctxs.put(cssc);
  920. } catch (DuplicateServiceContext dsc) {
  921. // Ignore
  922. }
  923. }
  924. }