1. /*
  2. * @(#)ClientRequestInfoImpl.java 1.42 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.Interceptors;
  8. import java.io.*;
  9. import java.lang.reflect.*;
  10. import org.omg.CORBA.Any;
  11. import org.omg.CORBA.BAD_INV_ORDER;
  12. import org.omg.CORBA.BAD_PARAM;
  13. import org.omg.CORBA.CompletionStatus;
  14. import org.omg.CORBA.Context;
  15. import org.omg.CORBA.ContextList;
  16. import org.omg.CORBA.CTX_RESTRICT_SCOPE;
  17. import org.omg.CORBA.ExceptionList;
  18. import org.omg.CORBA.LocalObject;
  19. import org.omg.CORBA.NamedValue;
  20. import org.omg.CORBA.NO_IMPLEMENT;
  21. import org.omg.CORBA.NO_RESOURCES;
  22. import org.omg.CORBA.NVList;
  23. import org.omg.CORBA.Object;
  24. import org.omg.CORBA.ParameterMode;
  25. import org.omg.CORBA.Policy;
  26. import org.omg.CORBA.SystemException;
  27. import org.omg.CORBA.TypeCode;
  28. import org.omg.CORBA.INTERNAL;
  29. import org.omg.CORBA.UserException;
  30. import org.omg.CORBA.portable.ApplicationException;
  31. import org.omg.CORBA.portable.InputStream;
  32. import com.sun.corba.se.internal.corba.ClientDelegate;
  33. import com.sun.corba.se.internal.core.ClientResponse;
  34. import com.sun.corba.se.internal.core.ClientRequest;
  35. import com.sun.corba.se.internal.core.DuplicateServiceContext;
  36. import com.sun.corba.se.internal.core.GIOPVersion;
  37. import com.sun.corba.se.internal.core.IOR;
  38. import com.sun.corba.se.internal.core.NoSuchServiceContext;
  39. import com.sun.corba.se.internal.core.ServiceContexts;
  40. import com.sun.corba.se.internal.core.UnknownServiceContext;
  41. import com.sun.corba.se.internal.iiop.CDROutputStream;
  42. import com.sun.corba.se.internal.iiop.Connection;
  43. import com.sun.corba.se.internal.iiop.CDRInputStream_1_0;
  44. import com.sun.corba.se.internal.ior.IIOPProfile;
  45. import com.sun.corba.se.internal.orbutil.ORBUtility;
  46. import com.sun.corba.se.internal.util.RepositoryId;
  47. import org.omg.IOP.ServiceContext;
  48. import org.omg.IOP.ServiceContextHelper;
  49. import org.omg.IOP.TaggedProfile;
  50. import org.omg.IOP.TaggedProfileHelper;
  51. import org.omg.IOP.TaggedComponent;
  52. import org.omg.IOP.TaggedComponentHelper;
  53. import org.omg.IOP.TAG_INTERNET_IOP;
  54. import org.omg.PortableInterceptor.ClientRequestInfo;
  55. import org.omg.PortableInterceptor.LOCATION_FORWARD;
  56. import org.omg.Dynamic.Parameter;
  57. import org.omg.PortableInterceptor.SUCCESSFUL;
  58. import org.omg.PortableInterceptor.SYSTEM_EXCEPTION;
  59. import org.omg.PortableInterceptor.TRANSPORT_RETRY;
  60. import org.omg.PortableInterceptor.USER_EXCEPTION;
  61. import java.util.*;
  62. /**
  63. * Implementation of the ClientRequestInfo interface as specified in
  64. * orbos/99-12-02 section 5.4.2.
  65. */
  66. public final class ClientRequestInfoImpl
  67. extends RequestInfoImpl
  68. implements ClientRequestInfo
  69. {
  70. // The available constants for startingPointCall
  71. static final int CALL_SEND_REQUEST = 0;
  72. static final int CALL_SEND_POLL = 1;
  73. // The available constants for endingPointCall
  74. static final int CALL_RECEIVE_REPLY = 0;
  75. static final int CALL_RECEIVE_EXCEPTION = 1;
  76. static final int CALL_RECEIVE_OTHER = 2;
  77. //////////////////////////////////////////////////////////////////////
  78. //
  79. // NOTE: IF AN ATTRIBUTE IS ADDED, PLEASE UPDATE RESET();
  80. //
  81. //////////////////////////////////////////////////////////////////////
  82. // The current retry request status. True if this request is being
  83. // retried and this info object is to be reused, or false otherwise.
  84. private boolean retryRequest;
  85. // The number of times this info object has been (re)used. This is
  86. // incremented every time a request is retried, and decremented every
  87. // time a request is complete. When this reaches zero, the info object
  88. // is popped from the ClientRequestInfoImpl ThreadLocal stack in PIORB.
  89. private int entryCount = 0;
  90. // The RequestImpl is set when the call is DII based.
  91. // The DII query calls like ParameterList, ExceptionList,
  92. // ContextList will be delegated to RequestImpl.
  93. private org.omg.CORBA.Request request;
  94. // Sources of client request information
  95. private IIOPProfile profile;
  96. private IOR targetIOR;
  97. private IOR effectiveTargetIOR;
  98. private int requestId;
  99. private String opName;
  100. private boolean isOneWay;
  101. private boolean diiInitiate;
  102. private ClientDelegate clientDelegate;
  103. private ClientResponse response;
  104. // Cached information:
  105. private org.omg.CORBA.Object cachedTargetObject;
  106. private org.omg.CORBA.Object cachedEffectiveTargetObject;
  107. private Parameter[] cachedArguments;
  108. private TypeCode[] cachedExceptions;
  109. private String[] cachedContexts;
  110. private String[] cachedOperationContext;
  111. private String cachedReceivedExceptionId;
  112. private Any cachedResult;
  113. private Any cachedReceivedException;
  114. private TaggedProfile cachedEffectiveProfile;
  115. // key = Integer, value = IOP.ServiceContext.
  116. private HashMap cachedRequestServiceContexts;
  117. // key = Integer, value = IOP.ServiceContext.
  118. private HashMap cachedReplyServiceContexts;
  119. // key = Integer, value = TaggedComponent
  120. private HashMap cachedEffectiveComponents;
  121. protected boolean piCurrentPushed;
  122. //////////////////////////////////////////////////////////////////////
  123. //
  124. // NOTE: IF AN ATTRIBUTE IS ADDED, PLEASE UPDATE RESET();
  125. //
  126. //////////////////////////////////////////////////////////////////////
  127. /**
  128. * Reset the info object so that it can be reused for a retry,
  129. * for example.
  130. */
  131. void reset() {
  132. super.reset();
  133. // Please keep these in the same order that they're declared above.
  134. retryRequest = false;
  135. // Do not reset entryCount because we need to know when to pop this
  136. // from the stack.
  137. request = null;
  138. profile = null;
  139. targetIOR = null;
  140. effectiveTargetIOR = null;
  141. requestId = 0;
  142. opName = null;
  143. isOneWay = false;
  144. diiInitiate = false;
  145. clientDelegate = null;
  146. response = null;
  147. // Clear cached attributes:
  148. cachedTargetObject = null;
  149. cachedEffectiveTargetObject = null;
  150. cachedArguments = null;
  151. cachedExceptions = null;
  152. cachedContexts = null;
  153. cachedOperationContext = null;
  154. cachedReceivedExceptionId = null;
  155. cachedResult = null;
  156. cachedReceivedException = null;
  157. cachedEffectiveProfile = null;
  158. cachedRequestServiceContexts = null;
  159. cachedReplyServiceContexts = null;
  160. cachedEffectiveComponents = null;
  161. piCurrentPushed = false;
  162. startingPointCall = CALL_SEND_REQUEST;
  163. endingPointCall = CALL_RECEIVE_REPLY;
  164. }
  165. /*
  166. **********************************************************************
  167. * Access protection
  168. **********************************************************************/
  169. // Method IDs for all methods in ClientRequestInfo. This allows for a
  170. // convenient O(1) lookup for checkAccess().
  171. protected static final int MID_TARGET = MID_RI_LAST + 1;
  172. protected static final int MID_EFFECTIVE_TARGET = MID_RI_LAST + 2;
  173. protected static final int MID_EFFECTIVE_PROFILE = MID_RI_LAST + 3;
  174. protected static final int MID_RECEIVED_EXCEPTION = MID_RI_LAST + 4;
  175. protected static final int MID_RECEIVED_EXCEPTION_ID = MID_RI_LAST + 5;
  176. protected static final int MID_GET_EFFECTIVE_COMPONENT = MID_RI_LAST + 6;
  177. protected static final int MID_GET_EFFECTIVE_COMPONENTS
  178. = MID_RI_LAST + 7;
  179. protected static final int MID_GET_REQUEST_POLICY = MID_RI_LAST + 8;
  180. protected static final int MID_ADD_REQUEST_SERVICE_CONTEXT
  181. = MID_RI_LAST + 9;
  182. // ClientRequestInfo validity table (see ptc/00-08-06 table 21-1).
  183. // Note: These must be in the same order as specified in contants.
  184. protected static final boolean validCall[][] = {
  185. // LEGEND:
  186. // s_req = send_request r_rep = receive_reply
  187. // s_pol = send_poll r_exc = receive_exception
  188. // r_oth = receive_other
  189. //
  190. // A true value indicates call is valid at specified point.
  191. // A false value indicates the call is invalid.
  192. //
  193. //
  194. // NOTE: If the order or number of columns change, update
  195. // checkAccess() accordingly.
  196. //
  197. // { s_req, s_pol, r_rep, r_exc, r_oth }
  198. // RequestInfo methods:
  199. /*request_id*/ { true , true , true , true , true },
  200. /*operation*/ { true , true , true , true , true },
  201. /*arguments*/ { true , false, true , false, false },
  202. /*exceptions*/ { true , false, true , true , true },
  203. /*contexts*/ { true , false, true , true , true },
  204. /*operation_context*/ { true , false, true , true , true },
  205. /*result*/ { false, false, true , false, false },
  206. /*response_expected*/ { true , true , true , true , true },
  207. /*sync_scope*/ { true , false, true , true , true },
  208. /*reply_status*/ { false, false, true , true , true },
  209. /*forward_reference*/ { false, false, false, false, true },
  210. /*get_slot*/ { true , true , true , true , true },
  211. /*get_request_service_context*/ { true , false, true , true , true },
  212. /*get_reply_service_context*/ { false, false, true , true , true },
  213. //
  214. // ClientRequestInfo methods::
  215. /*target*/ { true , true , true , true , true },
  216. /*effective_target*/ { true , true , true , true , true },
  217. /*effective_profile*/ { true , true , true , true , true },
  218. /*received_exception*/ { false, false, false, true , false },
  219. /*received_exception_id*/ { false, false, false, true , false },
  220. /*get_effective_component*/ { true , false, true , true , true },
  221. /*get_effective_components*/ { true , false, true , true , true },
  222. /*get_request_policy*/ { true , false, true , true , true },
  223. /*add_request_service_context*/ { true , false, false, false, false }
  224. };
  225. /*
  226. **********************************************************************
  227. * Public ClientRequestInfo interfaces
  228. **********************************************************************/
  229. /**
  230. * Creates a new ClientRequestInfo implementation.
  231. * The constructor is package scope since no other package need create
  232. * an instance of this class.
  233. */
  234. protected ClientRequestInfoImpl( PIORB piOrb ) {
  235. super( piOrb );
  236. startingPointCall = CALL_SEND_REQUEST;
  237. endingPointCall = CALL_RECEIVE_REPLY;
  238. }
  239. /**
  240. * The object which the client called to perform the operation.
  241. */
  242. public org.omg.CORBA.Object target (){
  243. // access is currently valid for all states:
  244. //checkAccess( MID_TARGET );
  245. if (cachedTargetObject == null) {
  246. // No synchronization since not worth it here.
  247. cachedTargetObject = iorToObject(targetIOR);
  248. }
  249. return cachedTargetObject;
  250. }
  251. /**
  252. * The actual object on which the operation will be invoked. If the
  253. * reply_status is LOCATION_FORWARD, then on subsequent requests,
  254. * effective_target will contain the forwarded IOR while target will
  255. * remain unchanged.
  256. */
  257. public org.omg.CORBA.Object effective_target() {
  258. // access is currently valid for all states:
  259. //checkAccess( MID_EFFECTIVE_TARGET );
  260. // Note: This is not necessarily the same as locatedIOR.
  261. // Reason: See the way we handle COMM_FAILURES in
  262. // ClientDelegate.createRequest, v1.32
  263. if (cachedEffectiveTargetObject == null) {
  264. // No synchronization since not worth it here.
  265. cachedEffectiveTargetObject = iorToObject(effectiveTargetIOR);
  266. }
  267. return cachedEffectiveTargetObject;
  268. }
  269. /**
  270. * The profile that will be used to send the request. If a location
  271. * forward has occurred for this operation's object and that object's
  272. * profile change accordingly, then this profile will be that located
  273. * profile.
  274. */
  275. public TaggedProfile effective_profile (){
  276. // access is currently valid for all states:
  277. //checkAccess( MID_EFFECTIVE_PROFILE );
  278. if( cachedEffectiveProfile == null ) {
  279. cachedEffectiveProfile = profile.getIOPProfile( piOrb ) ;
  280. }
  281. // Good citizen: In the interest of efficiency, we assume interceptors
  282. // will not modify the returned TaggedProfile in any way so we need
  283. // not make a deep copy of it.
  284. return cachedEffectiveProfile;
  285. }
  286. /**
  287. * Contains the exception to be returned to the client.
  288. */
  289. public Any received_exception (){
  290. checkAccess( MID_RECEIVED_EXCEPTION );
  291. if( cachedReceivedException == null ) {
  292. cachedReceivedException = exceptionToAny( exception );
  293. }
  294. // Good citizen: In the interest of efficiency, we assume interceptors
  295. // will not modify the returned Any in any way so we need
  296. // not make a deep copy of it.
  297. return cachedReceivedException;
  298. }
  299. /**
  300. * The CORBA::RepositoryId of the exception to be returned to the client.
  301. */
  302. public String received_exception_id (){
  303. checkAccess( MID_RECEIVED_EXCEPTION_ID );
  304. if( cachedReceivedExceptionId == null ) {
  305. String result = null;
  306. if( exception == null ) {
  307. // Note: exception should never be null here since we will
  308. // throw a BAD_INV_ORDER if this is not called from
  309. // receive_exception.
  310. throw new INTERNAL(
  311. "Exception was null in received_exception_id",
  312. MinorCodes.EXCEPTION_WAS_NULL,
  313. CompletionStatus.COMPLETED_NO );
  314. }
  315. else if( exception instanceof SystemException ) {
  316. String name = exception.getClass().getName();
  317. result = ORBUtility.repositoryIdOf(name);
  318. }
  319. else if( exception instanceof ApplicationException ) {
  320. result = ((ApplicationException)exception).getId();
  321. }
  322. // _REVISIT_ We need to be able to handle a UserException in the
  323. // DII case. How do we extract the ID from a UserException?
  324. cachedReceivedExceptionId = result;
  325. }
  326. return cachedReceivedExceptionId;
  327. }
  328. /**
  329. * Returns the IOP::TaggedComponent with the given ID from the profile
  330. * selected for this request. IF there is more than one component for a
  331. * given component ID, it is undefined which component this operation
  332. * returns (get_effective_component should be called instead).
  333. */
  334. public TaggedComponent get_effective_component (int id){
  335. checkAccess( MID_GET_EFFECTIVE_COMPONENT );
  336. return get_effective_components( id )[0];
  337. }
  338. /**
  339. * Returns all the tagged components with the given ID from the profile
  340. * selected for this request.
  341. */
  342. public TaggedComponent[] get_effective_components (int id){
  343. checkAccess( MID_GET_EFFECTIVE_COMPONENTS );
  344. Integer integerId = new Integer( id );
  345. TaggedComponent[] result = null;
  346. boolean justCreatedCache = false;
  347. if( cachedEffectiveComponents == null ) {
  348. cachedEffectiveComponents = new HashMap();
  349. justCreatedCache = true;
  350. }
  351. else {
  352. // Look in cache:
  353. result = (TaggedComponent[])cachedEffectiveComponents.get(
  354. integerId );
  355. }
  356. // null could mean we cached null or not in cache.
  357. if( (result == null) &&
  358. (justCreatedCache ||
  359. !cachedEffectiveComponents.containsKey( integerId ) ) )
  360. {
  361. // Not in cache. Get it from the profile:
  362. result = profile.getIOPComponents( piOrb, id ) ;
  363. cachedEffectiveComponents.put( integerId, result );
  364. }
  365. // As per ptc/00-08-06, section 21.3.13.6., If not found, raise
  366. // BAD_PARAM with minor code INVLID_COMPONENT_ID.
  367. if( (result == null) || (result.length == 0) ) {
  368. throw new BAD_PARAM( "Could not find component with provided id.",
  369. MinorCodes.INVALID_COMPONENT_ID,
  370. CompletionStatus.COMPLETED_NO );
  371. }
  372. // Good citizen: In the interest of efficiency, we will assume
  373. // interceptors will not modify the returned TaggedCompoent[], or
  374. // the TaggedComponents inside of it. Otherwise, we would need to
  375. // clone the array and make a deep copy of its contents.
  376. return result;
  377. }
  378. /**
  379. * Returns the given policy in effect for this operation.
  380. */
  381. public Policy get_request_policy (int type){
  382. checkAccess( MID_GET_REQUEST_POLICY );
  383. // _REVISIT_ Our ORB is not policy-based at this time.
  384. throw new NO_IMPLEMENT( "This ORB is not policy-based.",
  385. MinorCodes.PI_ORB_NOT_POLICY_BASED,
  386. CompletionStatus.COMPLETED_NO );
  387. }
  388. /**
  389. * Allows interceptors to add service contexts to the request.
  390. * <p>
  391. * There is no declaration of the order of the service contexts. They
  392. * may or may not appear in the order they are added.
  393. */
  394. public void add_request_service_context (ServiceContext service_context,
  395. boolean replace)
  396. {
  397. checkAccess( MID_ADD_REQUEST_SERVICE_CONTEXT );
  398. if( cachedRequestServiceContexts == null ) {
  399. cachedRequestServiceContexts = new HashMap();
  400. }
  401. addServiceContext( cachedRequestServiceContexts, serviceContexts,
  402. service_context, replace );
  403. }
  404. // NOTE: When adding a method, be sure to:
  405. // 1. Add a MID_* constant for that method
  406. // 2. Call checkAccess at the start of the method
  407. // 3. Define entries in the validCall[][] table for interception points.
  408. /*
  409. **********************************************************************
  410. * Public RequestInfo interfaces
  411. *
  412. * These are implemented here because they have differing
  413. * implementations depending on whether this is a client or a server
  414. * request info object.
  415. **********************************************************************/
  416. /**
  417. * See RequestInfoImpl for javadoc.
  418. */
  419. public int request_id (){
  420. // access is currently valid for all states:
  421. //checkAccess( MID_REQUEST_ID );
  422. /*
  423. * NOTE: The requestId in client interceptors is the same as the
  424. * GIOP request id. This works because both interceptors and
  425. * request ids are scoped by the ORB on the client side.
  426. */
  427. return requestId;
  428. }
  429. /**
  430. * See RequestInfoImpl for javadoc.
  431. */
  432. public String operation (){
  433. // access is currently valid for all states:
  434. //checkAccess( MID_OPERATION );
  435. return opName;
  436. }
  437. /**
  438. * See RequestInfoImpl for javadoc.
  439. */
  440. public Parameter[] arguments (){
  441. checkAccess( MID_ARGUMENTS );
  442. if( cachedArguments == null ) {
  443. if( request == null ) {
  444. throw new NO_RESOURCES(
  445. "The Portable Java Bindings do not support arguments()",
  446. MinorCodes.PI_OPERATION_NOT_SUPPORTED,
  447. CompletionStatus.COMPLETED_NO );
  448. }
  449. // If it is DII request then get the arguments from the DII req
  450. // and convert that into parameters.
  451. cachedArguments = nvListToParameterArray( request.arguments() );
  452. }
  453. // Good citizen: In the interest of efficiency, we assume
  454. // interceptors will be "good citizens" in that they will not
  455. // modify the contents of the Parameter[] array. We also assume
  456. // they will not change the values of the containing Anys.
  457. return cachedArguments;
  458. }
  459. /**
  460. * See RequestInfoImpl for javadoc.
  461. */
  462. public TypeCode[] exceptions (){
  463. checkAccess( MID_EXCEPTIONS );
  464. if( cachedExceptions == null ) {
  465. if( request == null ) {
  466. throw new NO_RESOURCES(
  467. "The Portable Java Bindings do not support exceptions()",
  468. MinorCodes.PI_OPERATION_NOT_SUPPORTED,
  469. CompletionStatus.COMPLETED_NO );
  470. }
  471. // Get the list of exceptions from DII request data, If there are
  472. // no exceptions raised then this method will return null.
  473. ExceptionList excList = request.exceptions( );
  474. int count = excList.count();
  475. TypeCode[] excTCList = new TypeCode[count];
  476. try {
  477. for( int i = 0; i < count; i++ ) {
  478. excTCList[i] = excList.item( i );
  479. }
  480. } catch( Exception e ) {
  481. throw new INTERNAL( "Exception in Requestnfo.exceptions()",
  482. MinorCodes.EXCEPTION_IN_EXCEPTIONS,
  483. CompletionStatus.COMPLETED_NO );
  484. }
  485. cachedExceptions = excTCList;
  486. }
  487. // Good citizen: In the interest of efficiency, we assume
  488. // interceptors will be "good citizens" in that they will not
  489. // modify the contents of the TypeCode[] array. We also assume
  490. // they will not change the values of the containing TypeCodes.
  491. return cachedExceptions;
  492. }
  493. /**
  494. * See RequestInfoImpl for javadoc.
  495. */
  496. public String[] contexts (){
  497. checkAccess( MID_CONTEXTS );
  498. if( cachedContexts == null ) {
  499. if( request == null ) {
  500. throw new NO_RESOURCES(
  501. "The Portable Java Bindings do not support contexts()",
  502. MinorCodes.PI_OPERATION_NOT_SUPPORTED,
  503. CompletionStatus.COMPLETED_NO );
  504. }
  505. // Get the list of contexts from DII request data, If there are
  506. // no contexts then this method will return null.
  507. ContextList ctxList = request.contexts( );
  508. int count = ctxList.count();
  509. String[] ctxListToReturn = new String[count];
  510. try {
  511. for( int i = 0; i < count; i++ ) {
  512. ctxListToReturn[i] = ctxList.item( i );
  513. }
  514. } catch( Exception e ) {
  515. throw new INTERNAL( "Exception in RequestInfo.contexts()",
  516. MinorCodes.EXCEPTION_IN_CONTEXTS,
  517. CompletionStatus.COMPLETED_NO );
  518. }
  519. cachedContexts = ctxListToReturn;
  520. }
  521. // Good citizen: In the interest of efficiency, we assume
  522. // interceptors will be "good citizens" in that they will not
  523. // modify the contents of the String[] array.
  524. return cachedContexts;
  525. }
  526. /**
  527. * See RequestInfoImpl for javadoc.
  528. */
  529. public String[] operation_context (){
  530. checkAccess( MID_OPERATION_CONTEXT );
  531. if( cachedOperationContext == null ) {
  532. if( request == null ) {
  533. throw new NO_RESOURCES(
  534. "The Portable Java Bindings do not support contexts()",
  535. MinorCodes.PI_OPERATION_NOT_SUPPORTED,
  536. CompletionStatus.COMPLETED_NO );
  537. }
  538. // Get the list of contexts from DII request data, If there are
  539. // no contexts then this method will return null.
  540. Context ctx = request.ctx( );
  541. // _REVISIT_ The API for get_values is not compliant with the spec,
  542. // Revisit this code once it's fixed.
  543. // _REVISIT_ Our ORB doesn't support Operation Context, This code
  544. // will not be excerscised until it's supported.
  545. // The first parameter in get_values is the start_scope which
  546. // if blank makes it as a global scope.
  547. // The second parameter is op_flags which is set to RESTRICT_SCOPE
  548. // As there is only one defined in the spec.
  549. // The Third param is the pattern which is '*' requiring it to
  550. // get all the contexts.
  551. NVList nvList = ctx.get_values( "", CTX_RESTRICT_SCOPE.value,"*" );
  552. String[] context = new String[(nvList.count() * 2) ];
  553. if( ( nvList != null ) &&( nvList.count() != 0 ) ) {
  554. // The String[] array will contain Name and Value for each
  555. // context and hence double the size in the array.
  556. int index = 0;
  557. for( int i = 0; i < nvList.count(); i++ ) {
  558. NamedValue nv;
  559. try {
  560. nv = nvList.item( i );
  561. }
  562. catch (Exception e ) {
  563. return (String[]) null;
  564. }
  565. context[index] = nv.name();
  566. index++;
  567. context[index] = nv.value().extract_string();
  568. index++;
  569. }
  570. }
  571. cachedOperationContext = context;
  572. }
  573. // Good citizen: In the interest of efficiency, we assume
  574. // interceptors will be "good citizens" in that they will not
  575. // modify the contents of the String[] array.
  576. return cachedOperationContext;
  577. }
  578. /**
  579. * See RequestInfoImpl for javadoc.
  580. */
  581. public Any result (){
  582. checkAccess( MID_RESULT );
  583. if( cachedResult == null ) {
  584. if( request == null ) {
  585. throw new NO_RESOURCES(
  586. "The Portable Java Bindings do not support result()",
  587. MinorCodes.PI_OPERATION_NOT_SUPPORTED,
  588. CompletionStatus.COMPLETED_NO );
  589. }
  590. // Get the result from the DII request data.
  591. NamedValue nvResult = request.result( );
  592. if( nvResult == null ) {
  593. throw new INTERNAL(
  594. "DII nvResult should not be null.",
  595. MinorCodes.PI_DII_RESULT_IS_NULL,
  596. CompletionStatus.COMPLETED_NO );
  597. }
  598. cachedResult = nvResult.value();
  599. }
  600. // Good citizen: In the interest of efficiency, we assume that
  601. // interceptors will not modify the contents of the result Any.
  602. // Otherwise, we would need to create a deep copy of the Any.
  603. return cachedResult;
  604. }
  605. /**
  606. * See RequestInfoImpl for javadoc.
  607. */
  608. public boolean response_expected (){
  609. // access is currently valid for all states:
  610. //checkAccess( MID_RESPONSE_EXPECTED );
  611. return !isOneWay;
  612. }
  613. /**
  614. * See RequestInfoImpl for javadoc.
  615. */
  616. public Object forward_reference (){
  617. checkAccess( MID_FORWARD_REFERENCE );
  618. // Check to make sure we are in LOCATION_FORWARD
  619. // state as per ptc/00-08-06, table 21-1
  620. // footnote 2.
  621. if( replyStatus != LOCATION_FORWARD.value ) {
  622. throw new BAD_INV_ORDER(
  623. "Invalid to query forward_reference() when reply status " +
  624. "is not LOCATION_FORWARD.",
  625. MinorCodes.INVALID_PI_CALL, CompletionStatus.COMPLETED_NO );
  626. }
  627. // Do not cache this value since if an interceptor raises
  628. // forward request then the next interceptor in the
  629. // list should see the new value.
  630. IOR ior = clientDelegate.getLocatedIOR();
  631. return iorToObject(ior);
  632. }
  633. /**
  634. * See RequestInfoImpl for javadoc.
  635. */
  636. public org.omg.IOP.ServiceContext get_request_service_context( int id ) {
  637. checkAccess( MID_GET_REQUEST_SERVICE_CONTEXT );
  638. if( cachedRequestServiceContexts == null ) {
  639. cachedRequestServiceContexts = new HashMap();
  640. }
  641. return getServiceContext( cachedRequestServiceContexts,
  642. serviceContexts, id );
  643. }
  644. /**
  645. * does not contain an etry for that ID, BAD_PARAM with a minor code of
  646. * TBD_BP is raised.
  647. */
  648. public org.omg.IOP.ServiceContext get_reply_service_context( int id ) {
  649. checkAccess( MID_GET_REPLY_SERVICE_CONTEXT );
  650. // In the event this is called from a oneway, we will have no
  651. // response object.
  652. //
  653. // In the event this is called after a IIOPConnection.purge_calls,
  654. // we will have a response object, but that object will
  655. // not contain a header (which would hold the service context
  656. // container). See bug 4624102.
  657. //
  658. // REVISIT: this is the only thing used
  659. // from response at this time. However, a more general solution
  660. // would avoid accessing other parts of response's header.
  661. //
  662. // Instead of throwing a NullPointer, we will
  663. // "gracefully" handle these with a BAD_PARAM with minor code 25.
  664. if( response == null ||
  665. response.getServiceContexts() == null )
  666. {
  667. throw new BAD_PARAM( "No such service context " +
  668. "(note: inaccessible from oneway calls)",
  669. MinorCodes.INVALID_SERVICE_CONTEXT_ID,
  670. CompletionStatus.COMPLETED_NO );
  671. }
  672. if( cachedReplyServiceContexts == null ) {
  673. cachedReplyServiceContexts = new HashMap();
  674. }
  675. return getServiceContext( cachedReplyServiceContexts,
  676. response.getServiceContexts(), id );
  677. }
  678. /*
  679. **********************************************************************
  680. * Package-scope interfaces
  681. **********************************************************************/
  682. /**
  683. * Stores the various sources of information used for this info object.
  684. */
  685. protected void setInfo( Connection connection,
  686. ClientDelegate delegate,
  687. IOR effectiveTargetIOR,
  688. IIOPProfile profile,
  689. int requestId,
  690. String opName,
  691. boolean isOneWay,
  692. ServiceContexts svc )
  693. {
  694. this.connection = connection;
  695. this.clientDelegate = delegate;
  696. this.targetIOR = delegate.getIOR();
  697. this.effectiveTargetIOR = effectiveTargetIOR;
  698. this.profile = profile;
  699. this.requestId = requestId;
  700. this.opName = opName;
  701. this.isOneWay = isOneWay;
  702. this.serviceContexts = svc;
  703. }
  704. /**
  705. * Stores the various sources of information used for this info object.
  706. */
  707. protected void setInfo( ClientResponse response ) {
  708. this.response = response;
  709. }
  710. /**
  711. * Set or reset the retry request flag.
  712. */
  713. void setRetryRequest( boolean retryRequest ) {
  714. this.retryRequest = retryRequest;
  715. }
  716. /**
  717. * Retrieve the current retry request status.
  718. */
  719. boolean getRetryRequest() {
  720. return this.retryRequest;
  721. }
  722. /**
  723. * Increases the entry count by 1.
  724. */
  725. void incrementEntryCount() {
  726. this.entryCount++;
  727. }
  728. /**
  729. * Decreases the entry count by 1.
  730. */
  731. void decrementEntryCount() {
  732. this.entryCount--;
  733. }
  734. /**
  735. * Retrieve the current entry count
  736. */
  737. int getEntryCount() {
  738. return this.entryCount;
  739. }
  740. /**
  741. * Overridden from RequestInfoImpl. Calls the super class, then
  742. * sets the ending point call depending on the reply status.
  743. */
  744. protected void setReplyStatus( short replyStatus ) {
  745. super.setReplyStatus( replyStatus );
  746. switch( replyStatus ) {
  747. case SUCCESSFUL.value:
  748. endingPointCall = CALL_RECEIVE_REPLY;
  749. break;
  750. case SYSTEM_EXCEPTION.value:
  751. case USER_EXCEPTION.value:
  752. endingPointCall = CALL_RECEIVE_EXCEPTION;
  753. break;
  754. case LOCATION_FORWARD.value:
  755. case TRANSPORT_RETRY.value:
  756. endingPointCall = CALL_RECEIVE_OTHER;
  757. break;
  758. }
  759. }
  760. /**
  761. * Sets DII request object in the RequestInfoObject.
  762. */
  763. protected void setDIIRequest(org.omg.CORBA.Request req) {
  764. request = req;
  765. }
  766. /**
  767. * Keeps track of whether initiate was called for a DII request. The ORB
  768. * needs to know this so it knows whether to ignore a second call to
  769. * initiateClientPIRequest or not.
  770. */
  771. protected void setDIIInitiate( boolean diiInitiate ) {
  772. this.diiInitiate = diiInitiate;
  773. }
  774. /**
  775. * See comment for setDIIInitiate
  776. */
  777. protected boolean isDIIInitiate() {
  778. return this.diiInitiate;
  779. }
  780. /**
  781. * The PICurrent stack should only be popped if it was pushed.
  782. * This is generally the case. But exceptions which occur
  783. * after the stub's entry to _request but before the push
  784. * end up in _releaseReply which will try to pop unless told not to.
  785. */
  786. protected void setPICurrentPushed( boolean piCurrentPushed ) {
  787. this.piCurrentPushed = piCurrentPushed;
  788. }
  789. protected boolean isPICurrentPushed() {
  790. return this.piCurrentPushed;
  791. }
  792. /**
  793. * Overridden from RequestInfoImpl.
  794. */
  795. protected void setException( Exception exception ) {
  796. super.setException( exception );
  797. // Clear cached values:
  798. cachedReceivedException = null;
  799. cachedReceivedExceptionId = null;
  800. }
  801. protected boolean getIsOneWay() {
  802. return this.isOneWay;
  803. }
  804. /**
  805. * Returns the reference to the ClientDelegate object
  806. */
  807. protected ClientDelegate getClientDelegate() {
  808. return this.clientDelegate;
  809. }
  810. /**
  811. * See description for RequestInfoImpl.checkAccess
  812. */
  813. protected void checkAccess( int methodID )
  814. throws BAD_INV_ORDER
  815. {
  816. // Make sure currentPoint matches the appropriate index in the
  817. // validCall table:
  818. int validCallIndex = 0;
  819. switch( currentExecutionPoint ) {
  820. case EXECUTION_POINT_STARTING:
  821. switch( startingPointCall ) {
  822. case CALL_SEND_REQUEST:
  823. validCallIndex = 0;
  824. break;
  825. case CALL_SEND_POLL:
  826. validCallIndex = 1;
  827. break;
  828. }
  829. break;
  830. case EXECUTION_POINT_ENDING:
  831. switch( endingPointCall ) {
  832. case CALL_RECEIVE_REPLY:
  833. validCallIndex = 2;
  834. break;
  835. case CALL_RECEIVE_EXCEPTION:
  836. validCallIndex = 3;
  837. break;
  838. case CALL_RECEIVE_OTHER:
  839. validCallIndex = 4;
  840. break;
  841. }
  842. break;
  843. }
  844. // Check the validCall table:
  845. if( !validCall[methodID][validCallIndex] ) {
  846. throw new BAD_INV_ORDER(
  847. "Cannot access this info attribute/method at this point.",
  848. MinorCodes.INVALID_PI_CALL, CompletionStatus.COMPLETED_NO );
  849. }
  850. }
  851. }