1. /*
  2. * @(#)RequestImpl.java 1.62 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 org.omg.CORBA.Any;
  17. import org.omg.CORBA.ARG_IN;
  18. import org.omg.CORBA.ARG_OUT;
  19. import org.omg.CORBA.ARG_INOUT;
  20. import org.omg.CORBA.Context;
  21. import org.omg.CORBA.ContextList;
  22. import org.omg.CORBA.Environment;
  23. import org.omg.CORBA.ExceptionList;
  24. import org.omg.CORBA.NVList;
  25. import org.omg.CORBA.NamedValue;
  26. import org.omg.CORBA.Request;
  27. import org.omg.CORBA.SystemException;
  28. import org.omg.CORBA.TCKind;
  29. import org.omg.CORBA.TypeCode;
  30. import org.omg.CORBA.TypeCodePackage.BadKind;
  31. import org.omg.CORBA.UnknownUserException;
  32. import org.omg.CORBA.Bounds;
  33. import org.omg.CORBA.UNKNOWN;
  34. import org.omg.CORBA.INTERNAL;
  35. import org.omg.CORBA.NO_IMPLEMENT;
  36. import org.omg.CORBA.CompletionStatus;
  37. import org.omg.CORBA.WrongTransaction;
  38. import org.omg.CORBA.portable.*;
  39. import com.sun.corba.se.internal.corba.ClientDelegate;
  40. import com.sun.corba.se.internal.core.*;
  41. import com.sun.corba.se.internal.iiop.messages.ReplyMessage;
  42. import com.sun.corba.se.internal.orbutil.MinorCodes;
  43. public class RequestImpl extends Request {
  44. ///////////////////////////////////////////////////////////////////////////
  45. // data members
  46. protected ObjectImpl _target = null;
  47. protected String _opName = null;
  48. protected NVList _arguments = null;
  49. protected ExceptionList _exceptions = null;
  50. private NamedValue _result = null;
  51. protected Environment _env = null;
  52. private Context _ctx = null;
  53. private ContextList _ctxList = null;
  54. protected ORB _orb = null;
  55. // invocation-specific stuff
  56. protected boolean _isOneWay = false;
  57. private int[] _paramCodes = null;
  58. private long[] _paramLongs = null;
  59. private java.lang.Object[] _paramObjects = null;
  60. // support for deferred invocations.
  61. // protected instead of private since it needs to be set by the
  62. // thread object doing the asynchronous invocation.
  63. protected boolean gotResponse = false;
  64. ///////////////////////////////////////////////////////////////////////////
  65. // constructor
  66. protected RequestImpl (ORB orb,
  67. org.omg.CORBA.Object targetObject,
  68. Context ctx,
  69. String operationName,
  70. NVList argumentList,
  71. NamedValue resultContainer,
  72. ExceptionList exceptionList,
  73. ContextList ctxList)
  74. {
  75. // initialize the orb
  76. _orb = orb;
  77. // initialize target, context and operation name
  78. _target = (ObjectImpl) targetObject;
  79. _ctx = ctx;
  80. _opName = operationName;
  81. // initialize argument list if not passed in
  82. if (argumentList == null)
  83. _arguments = new NVListImpl(_orb);
  84. else
  85. _arguments = argumentList;
  86. // set result container.
  87. _result = resultContainer;
  88. // initialize exception list if not passed in
  89. if (exceptionList == null)
  90. _exceptions = new ExceptionListImpl();
  91. else
  92. _exceptions = exceptionList;
  93. // initialize context list if not passed in
  94. if (ctxList == null)
  95. _ctxList = new ContextListImpl(_orb);
  96. else
  97. _ctxList = ctxList;
  98. // initialize environment
  99. _env = new EnvironmentImpl();
  100. }
  101. public org.omg.CORBA.Object target()
  102. {
  103. return _target;
  104. }
  105. public String operation()
  106. {
  107. return _opName;
  108. }
  109. public NVList arguments()
  110. {
  111. return _arguments;
  112. }
  113. public NamedValue result()
  114. {
  115. return _result;
  116. }
  117. public Environment env()
  118. {
  119. return _env;
  120. }
  121. public ExceptionList exceptions()
  122. {
  123. return _exceptions;
  124. }
  125. public ContextList contexts()
  126. {
  127. return _ctxList;
  128. }
  129. public synchronized Context ctx()
  130. {
  131. if (_ctx == null)
  132. _ctx = new ContextImpl(_orb);
  133. return _ctx;
  134. }
  135. public synchronized void ctx(Context newCtx)
  136. {
  137. _ctx = newCtx;
  138. }
  139. public synchronized Any add_in_arg()
  140. {
  141. return _arguments.add(org.omg.CORBA.ARG_IN.value).value();
  142. }
  143. public synchronized Any add_named_in_arg(String name)
  144. {
  145. return _arguments.add_item(name, org.omg.CORBA.ARG_IN.value).value();
  146. }
  147. public synchronized Any add_inout_arg()
  148. {
  149. return _arguments.add(org.omg.CORBA.ARG_INOUT.value).value();
  150. }
  151. public synchronized Any add_named_inout_arg(String name)
  152. {
  153. return _arguments.add_item(name, org.omg.CORBA.ARG_INOUT.value).value();
  154. }
  155. public synchronized Any add_out_arg()
  156. {
  157. return _arguments.add(org.omg.CORBA.ARG_OUT.value).value();
  158. }
  159. public synchronized Any add_named_out_arg(String name)
  160. {
  161. return _arguments.add_item(name, org.omg.CORBA.ARG_OUT.value).value();
  162. }
  163. public synchronized void set_return_type(TypeCode tc)
  164. {
  165. if (_result == null)
  166. _result = new NamedValueImpl(_orb);
  167. _result.value().type(tc);
  168. }
  169. public synchronized Any return_value()
  170. {
  171. if (_result == null)
  172. _result = new NamedValueImpl(_orb);
  173. return _result.value();
  174. }
  175. public synchronized void add_exception(TypeCode exceptionType)
  176. {
  177. _exceptions.add(exceptionType);
  178. }
  179. public synchronized void invoke()
  180. {
  181. doInvocation();
  182. }
  183. public synchronized void send_oneway()
  184. {
  185. _isOneWay = true;
  186. doInvocation();
  187. }
  188. public synchronized void send_deferred()
  189. {
  190. AsynchInvoke invokeObject = new AsynchInvoke((com.sun.corba.se.internal.corba.ORB) _orb, this, false);
  191. new Thread(invokeObject).start();
  192. }
  193. public synchronized boolean poll_response()
  194. {
  195. // this method has to be synchronized even though it seems
  196. // "readonly" since the thread object doing the asynchronous
  197. // invocation can potentially update this variable in parallel.
  198. // updates are currently simply synchronized againt the request
  199. // object.
  200. return gotResponse;
  201. }
  202. public synchronized void get_response()
  203. throws org.omg.CORBA.WrongTransaction
  204. {
  205. while (gotResponse == false) {
  206. // release the lock. wait to be notified by the thread that is
  207. // doing the asynchronous invocation.
  208. try {
  209. wait();
  210. }
  211. catch (InterruptedException e) {}
  212. }
  213. }
  214. ///////////////////////////////////////////////////////////////////////////
  215. // private helper methods
  216. /*
  217. * The doInvocation operation is where the real mechanics of
  218. * performing the request invocation is done.
  219. */
  220. protected void doInvocation() {
  221. // Get delegate
  222. // CHANGE(RAM J) (05/01/2000) changed ClientSubContract to ClientDelegate
  223. //ClientSubcontract delegate = (ClientSubcontract)_target._get_delegate();
  224. // Initiate Client Portable Interceptors. Inform the PIORB that
  225. // this is a DII request so that it knows to ignore the second
  226. // inevitable call to initiateClientPIRequest in createRequest.
  227. // Also, save the RequestImpl object for later use.
  228. _orb.initiateClientPIRequest( true );
  229. _orb.setClientPIInfo( this );
  230. ClientDelegate delegate = (ClientDelegate)_target._get_delegate();
  231. ClientRequest req;
  232. Exception exception=null;
  233. ClientResponse resp=null;
  234. // Note: This try/catch was added for PI. It is analogous to the
  235. // try / catch / finally found below for the line
  236. // "resp = delegate.invoke(req);". The finally is moved into the
  237. // catch body of SystemException since it should only be executed
  238. // if the request creation failed.
  239. try {
  240. req = delegate.createRequest(_opName, _isOneWay);
  241. }
  242. catch( SystemException ex ) {
  243. _env.exception(ex);
  244. exception = ex;
  245. // Note, this try block is copied directly from the one that
  246. // appears later in this method. Please synchronize changes.
  247. // _REVISIT_ This code needs to be reviewed by Ram.
  248. try {
  249. _orb.sendCancelRequestIfFinalFragmentNotSent();
  250. // REVISIT: Talk to sanjeevk and verify if this signature of
  251. // is releaseReply is important to DII. Can we just use one
  252. // releaseReply in ClientDelegate, instead of two?
  253. // _REVISIT_ The call to cleanupClientPIRequest should
  254. // really should go in releaseReply().
  255. // However, because GenericPOAClientSC:305 v1.54 is
  256. // explicitly calling releaseReply, this would cause
  257. // cleanup to occur twice. Ask Ram why releaseReply is
  258. // being called instead of receivedReply.
  259. // Invoke Portable Interceptors cleanup. This is done to
  260. // handle exceptions during stream marshalling.
  261. _orb.cleanupClientPIRequest();
  262. delegate.releaseReply(resp, _opName, exception);
  263. } catch ( WrongTransaction ex2 ) {
  264. // XXX return this for deferred sends
  265. throw new NO_IMPLEMENT(MinorCodes.SEND_DEFERRED_NOTIMPLEMENTED,
  266. CompletionStatus.COMPLETED_MAYBE);
  267. } catch ( SystemException ex2 ) {
  268. // substitute this exception for original exception
  269. _env.exception(ex2);
  270. throw ex2;
  271. }
  272. throw ex;
  273. }
  274. OutputStream os = (OutputStream)req;
  275. // Marshal args
  276. try {
  277. for (int i=0; i<_arguments.count() ; i++) {
  278. NamedValue nv = _arguments.item(i);
  279. switch (nv.flags()) {
  280. case ARG_IN.value:
  281. nv.value().write_value(os);
  282. break;
  283. case ARG_OUT.value:
  284. break;
  285. case ARG_INOUT.value:
  286. nv.value().write_value(os);
  287. break;
  288. }
  289. }
  290. } catch ( org.omg.CORBA.Bounds ex ) {
  291. // Cannot happen since we only iterate till _arguments.count()
  292. }
  293. try { // this outer try block ensures we do a req.completeRequest.
  294. // Invoke
  295. try {
  296. resp = delegate.invoke(req);
  297. } catch (SystemException ex) {
  298. // Pass SystemException through Portable Interceptors'
  299. // ending points, and then
  300. // set the SystemException in the env and rethrow it.
  301. exception = _orb.invokeClientPIEndingPoint(
  302. ReplyMessage.SYSTEM_EXCEPTION, ex );
  303. continueOrThrowSystemOrRemarshal( exception );
  304. // Note: We should never need to execute this line,
  305. // but we should assert in case exception was set to null
  306. // somehow.
  307. throw new INTERNAL(
  308. "Assertion failed: exception should not be null ." );
  309. }
  310. if (_isOneWay) {
  311. // Invoke Portable Interceptors with receive_other
  312. exception = _orb.invokeClientPIEndingPoint(
  313. ReplyMessage.NO_EXCEPTION, exception );
  314. continueOrThrowSystemOrRemarshal( exception );
  315. return;
  316. }
  317. // Process reply
  318. InputStream is = (InputStream) resp;
  319. if (resp.isSystemException()) {
  320. // Unmarshal the SystemException, set it in the env and throw it.
  321. SystemException se = resp.getSystemException();
  322. boolean doRemarshal = false;
  323. // FIX(Ram J) (05/01/2000) added locatedIOR = ior
  324. // and retry the request from root ior,
  325. // if system exception is COMM_FAILURE.
  326. // WARNING: There is a risk of infinite loopback
  327. // if the requests on location forwarded ior result in
  328. // system exception (COMM_FAILURE)
  329. if (se instanceof org.omg.CORBA.COMM_FAILURE
  330. && se.completed == CompletionStatus.COMPLETED_NO) {
  331. if (delegate.locatedIOR != delegate.ior) {
  332. delegate.locatedIOR = delegate.ior; // retry from root ior
  333. doRemarshal = true;
  334. }
  335. }
  336. if (se.minor == MinorCodes.CONN_CLOSE_REBIND &&
  337. (se instanceof org.omg.CORBA.COMM_FAILURE)) {
  338. doRemarshal = true;
  339. }
  340. if (doRemarshal) {
  341. // Invoke Portable Interceptors with receive_exception:
  342. exception = _orb.invokeClientPIEndingPoint(
  343. ReplyMessage.SYSTEM_EXCEPTION, se );
  344. // If PI did not change the exception, handle
  345. // COMM_FAILURE by recursively calling doInvocation.
  346. // Otherwise, throw the exception PI wants thrown.
  347. if( se == exception ) {
  348. doInvocation();
  349. }
  350. else {
  351. continueOrThrowSystemOrRemarshal( exception );
  352. throw new INTERNAL(
  353. "Assertion failed in RequestImpl. " +
  354. "exception should not be null." );
  355. }
  356. return;
  357. }
  358. // Invoke Portable Interceptors with receive_exception.
  359. exception = _orb.invokeClientPIEndingPoint(
  360. ReplyMessage.SYSTEM_EXCEPTION, se );
  361. continueOrThrowSystemOrRemarshal( exception );
  362. // Note: We should never need to execute this line, but
  363. // we should assert in case exception was set to null somehow
  364. throw new INTERNAL(
  365. "Assertion failed in RequestImpl: " +
  366. "exception should not be null." );
  367. } else if (resp.isUserException()) {
  368. // Peek exception's repository id
  369. String exid = resp.peekUserExceptionId();
  370. try {
  371. // Find the typecode for the exception
  372. for (int i=0; i<_exceptions.count() ; i++) {
  373. TypeCode tc = _exceptions.item(i);
  374. if ( tc.id().equals(exid) ) {
  375. // Since we dont have the actual user exception
  376. // class, the spec says we have to create an
  377. // UnknownUserException and put it in the
  378. // environment.
  379. Any eany = _orb.create_any();
  380. eany.read_value(is, (TypeCode)tc);
  381. exception = new UnknownUserException(eany);
  382. // _REVISIT_ Understand why this is
  383. // UnknownUserException.
  384. // Invoke Portable Interceptors with
  385. // receive_exception (user exception)
  386. Exception newException =
  387. _orb.invokeClientPIEndingPoint(
  388. ReplyMessage.USER_EXCEPTION, exception );
  389. // Note that continueOrThrowSystemOrRemarshal
  390. // will not call _env.exception in the case of
  391. // a UserException. We must do so explicitly here.
  392. _env.exception(newException);
  393. if( exception != newException ) {
  394. exception = newException;
  395. continueOrThrowSystemOrRemarshal( exception );
  396. }
  397. return;
  398. }
  399. }
  400. } catch (Exception b) {
  401. // Only exceptions to be caught are Bounds and BadKind.
  402. // Both cannot happen here.
  403. }
  404. // must be a truly unknown exception
  405. SystemException u = new UNKNOWN(MinorCodes.UNKNOWN_CORBA_EXC,
  406. CompletionStatus.COMPLETED_MAYBE);
  407. // Invoke Portable Interceptors with receive_exception:
  408. exception = _orb.invokeClientPIEndingPoint(
  409. ReplyMessage.SYSTEM_EXCEPTION, u );
  410. continueOrThrowSystemOrRemarshal( exception );
  411. // Note: We should never need to execute this line, but
  412. // we should assert in case exception was set to null somehow.
  413. throw new INTERNAL(
  414. "Assertion failed in RequestImpl : " +
  415. "exception should not be null." );
  416. } else if (resp.isLocationForward()) {
  417. // FIXED(Ram J) (05/01/2000) added setting delegate.locatedIOR
  418. // and reinvoking.
  419. delegate.locatedIOR = resp.getForwardedIOR();
  420. // Invoke Portable Interceptors with receive_other:
  421. exception = _orb.invokeClientPIEndingPoint(
  422. ReplyMessage.LOCATION_FORWARD, null );
  423. // If PI did not raise exception, invoke again. Otherwise
  424. // throw the exception PI wants thrown.
  425. if( exception == null ) {
  426. doInvocation(); // invoke again.
  427. }
  428. else {
  429. continueOrThrowSystemOrRemarshal( exception );
  430. }
  431. return;
  432. /*
  433. // Location forwards are handled internally in the subcontract.
  434. throw new INTERNAL(MinorCodes.LOCATIONFORWARD_ERROR,
  435. CompletionStatus.COMPLETED_NO);
  436. */
  437. } else if (resp.isDifferentAddrDispositionRequested()) {
  438. // set the desired target addressing disposition.
  439. delegate.addressingDisposition = resp.getAddrDisposition();
  440. // Invoke Portable Interceptors with receive_other:
  441. exception = _orb.invokeClientPIEndingPoint(
  442. ReplyMessage.NEEDS_ADDRESSING_MODE, null);
  443. // If PI did not raise exception, invoke again. Otherwise
  444. // throw the exception PI wants thrown.
  445. if( exception == null ) {
  446. doInvocation(); // invoke again.
  447. }
  448. else {
  449. continueOrThrowSystemOrRemarshal( exception );
  450. }
  451. return;
  452. } else { // normal return
  453. // Unmarshal return args
  454. unmarshalParams(is);
  455. // Invoke Portable Interceptors with receive_reply:
  456. exception = _orb.invokeClientPIEndingPoint(
  457. ReplyMessage.NO_EXCEPTION, null );
  458. // Remember: not thrown if exception is null.
  459. continueOrThrowSystemOrRemarshal( exception );
  460. }
  461. } finally {
  462. // _REVISIT_ PI Note: Any exceptions in the following try
  463. // block happen after PI endpoint has already run so they are not
  464. // reported to interceptors.
  465. // Note that changes to this try block should be synchronized with
  466. // the identical try block above.
  467. try {
  468. _orb.sendCancelRequestIfFinalFragmentNotSent();
  469. // REVISIT: Talk to sanjeevk and verify if this signature of
  470. // is releaseReply is important to DII. Can we just use one
  471. // releaseReply in ClientDelegate, instead of two?
  472. // _REVISIT_ See above revisit for same
  473. // cleanupClientPIRequest call.
  474. // Invoke Portable Interceptors cleanup. This is done to
  475. // handle exceptions during stream marshalling.
  476. _orb.cleanupClientPIRequest();
  477. delegate.releaseReply(resp, _opName, exception);
  478. } catch ( WrongTransaction ex ) {
  479. // XXX return this for deferred sends
  480. throw new NO_IMPLEMENT(MinorCodes.SEND_DEFERRED_NOTIMPLEMENTED,
  481. CompletionStatus.COMPLETED_MAYBE);
  482. } catch ( SystemException ex ) {
  483. // substitute this exception for original exception
  484. _env.exception(ex);
  485. throw ex;
  486. }
  487. }
  488. }
  489. // Filters the given exception into a SystemException and throws it.
  490. // If this is a RemarshalException, handle it by recursively calling
  491. // doInvocation(). This method assumes the given exception is a
  492. // SystemException or a RemarhsalException.
  493. //
  494. // If this is a SystemException, call _env.exception( exception ) so that
  495. // it is set in the environment.
  496. //
  497. // This is a utility method for the above doInvocation() code which must
  498. // do this numerous times. If the exception is null, no exception is
  499. // thrown.
  500. //
  501. // Note that this code is essentially the same as in ClientDelegate.java
  502. // or GenericPOAClientSC.java
  503. //
  504. private void continueOrThrowSystemOrRemarshal( Exception exception )
  505. throws SystemException
  506. {
  507. if( exception == null ) {
  508. // do nothing.
  509. }
  510. else if( exception instanceof RemarshalException ) {
  511. // invoke again:
  512. doInvocation();
  513. }
  514. else {
  515. _env.exception( exception );
  516. throw (SystemException)exception;
  517. }
  518. }
  519. protected void unmarshalParams(InputStream is)
  520. {
  521. // First unmarshal the return value if it is not void
  522. if ( _result != null ) {
  523. Any returnAny = _result.value();
  524. TypeCode returnType = returnAny.type();
  525. if ( returnType.kind().value() != TCKind._tk_void )
  526. returnAny.read_value(is, returnType);
  527. }
  528. // Now unmarshal the out/inout args
  529. try {
  530. for ( int i=0; i<_arguments.count() ; i++) {
  531. NamedValue nv = _arguments.item(i);
  532. switch( nv.flags() ) {
  533. case ARG_IN.value:
  534. break;
  535. case ARG_OUT.value:
  536. case ARG_INOUT.value:
  537. Any any = nv.value();
  538. any.read_value(is, any.type());
  539. break;
  540. }
  541. }
  542. }
  543. catch ( org.omg.CORBA.Bounds ex ) {
  544. // Cannot happen since we only iterate till _arguments.count()
  545. }
  546. }
  547. }