1. /*
  2. * @(#)RequestInfoImpl.java 1.46 04/06/21
  3. *
  4. * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
  5. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  6. */
  7. package com.sun.corba.se.impl.interceptors;
  8. import java.io.IOException ;
  9. import java.lang.reflect.Method ;
  10. import java.lang.reflect.InvocationTargetException ;
  11. import java.util.HashMap ;
  12. import org.omg.PortableInterceptor.ForwardRequest;
  13. import org.omg.PortableInterceptor.InvalidSlot;
  14. import org.omg.PortableInterceptor.RequestInfo;
  15. import org.omg.PortableInterceptor.LOCATION_FORWARD;
  16. import org.omg.IOP.TaggedProfile;
  17. import org.omg.IOP.TaggedComponent;
  18. import org.omg.IOP.ServiceContextHelper;
  19. import org.omg.Messaging.SYNC_WITH_TRANSPORT;
  20. import org.omg.CORBA.ParameterMode;
  21. import org.omg.CORBA.Any;
  22. import org.omg.CORBA.BAD_INV_ORDER;
  23. import org.omg.CORBA.BAD_PARAM;
  24. import org.omg.CORBA.CompletionStatus;
  25. import org.omg.CORBA.Context;
  26. import org.omg.CORBA.ContextList;
  27. import org.omg.CORBA.CTX_RESTRICT_SCOPE;
  28. import org.omg.CORBA.ExceptionList;
  29. import org.omg.CORBA.INTERNAL;
  30. import org.omg.CORBA.LocalObject;
  31. import org.omg.CORBA.NamedValue;
  32. import org.omg.CORBA.NO_IMPLEMENT;
  33. import org.omg.CORBA.NO_RESOURCES;
  34. import org.omg.CORBA.NVList;
  35. import org.omg.CORBA.Object;
  36. import org.omg.CORBA.Policy;
  37. import org.omg.CORBA.SystemException;
  38. import org.omg.CORBA.TypeCode;
  39. import org.omg.CORBA.UNKNOWN;
  40. import org.omg.CORBA.UserException;
  41. import org.omg.CORBA.portable.ApplicationException;
  42. import org.omg.CORBA.portable.Delegate;
  43. import org.omg.CORBA.portable.InputStream;
  44. import org.omg.Dynamic.Parameter;
  45. import com.sun.corba.se.spi.legacy.connection.Connection;
  46. import com.sun.corba.se.spi.legacy.interceptor.RequestInfoExt;
  47. import com.sun.corba.se.spi.ior.IOR;
  48. import com.sun.corba.se.spi.ior.iiop.GIOPVersion;
  49. import com.sun.corba.se.spi.orb.ORB;
  50. import com.sun.corba.se.spi.logging.CORBALogDomains;
  51. import com.sun.corba.se.spi.servicecontext.ServiceContexts;
  52. import com.sun.corba.se.spi.servicecontext.UnknownServiceContext;
  53. import com.sun.corba.se.impl.encoding.CDRInputStream_1_0;
  54. import com.sun.corba.se.impl.encoding.EncapsOutputStream;
  55. import com.sun.corba.se.impl.orbutil.ORBUtility;
  56. import com.sun.corba.se.impl.orbutil.ORBClassLoader;
  57. import com.sun.corba.se.impl.util.RepositoryId;
  58. import com.sun.corba.se.impl.logging.InterceptorsSystemException;
  59. import com.sun.corba.se.impl.logging.OMGSystemException;
  60. /**
  61. * Implementation of the RequestInfo interface as specified in
  62. * orbos/99-12-02 section 5.4.1.
  63. */
  64. public abstract class RequestInfoImpl
  65. extends LocalObject
  66. implements RequestInfo, RequestInfoExt
  67. {
  68. //////////////////////////////////////////////////////////////////////
  69. //
  70. // NOTE: IF AN ATTRIBUTE IS ADDED, PLEASE UPDATE RESET();
  71. //
  72. //////////////////////////////////////////////////////////////////////
  73. // The ORB from which to get PICurrent and other info
  74. protected ORB myORB;
  75. protected InterceptorsSystemException wrapper ;
  76. protected OMGSystemException stdWrapper ;
  77. // The number of interceptors actually invoked for this client request.
  78. // See setFlowStackIndex for a detailed description.
  79. protected int flowStackIndex = 0;
  80. // The type of starting point call to make to the interceptors
  81. // See ClientRequestInfoImpl and ServerRequestInfoImpl for a list of
  82. // appropriate constants.
  83. protected int startingPointCall;
  84. // The type of intermediate point call to make to the interceptors
  85. // See ServerRequestInfoImpl for a list of appropriate constants.
  86. // This does not currently apply to client request interceptors but is
  87. // here in case intermediate points are introduced in the future.
  88. protected int intermediatePointCall;
  89. // The type of ending point call to make to the interceptors
  90. // See ClientRequestInfoImpl and ServerRequestInfoImpl for a list of
  91. // appropriate constants.
  92. protected int endingPointCall;
  93. // The reply status to return in reply_status. This is initialized
  94. // to UNINITIALIZED so that we can tell if this has been set or not.
  95. protected short replyStatus = UNINITIALIZED;
  96. // Constant for an uninitizlied reply status.
  97. protected static final short UNINITIALIZED = -1;
  98. // Which points we are currently executing (so we can implement the
  99. // validity table).
  100. protected int currentExecutionPoint;
  101. protected static final int EXECUTION_POINT_STARTING = 0;
  102. protected static final int EXECUTION_POINT_INTERMEDIATE = 1;
  103. protected static final int EXECUTION_POINT_ENDING = 2;
  104. // Set to true if all interceptors have had all their points
  105. // executed.
  106. protected boolean alreadyExecuted;
  107. // Sources of request information
  108. protected Connection connection;
  109. protected ServiceContexts serviceContexts;
  110. // The ForwardRequest object if this request is being forwarded.
  111. // Either the forwardRequest or the forwardRequestIOR field is set.
  112. // When set, the other field is set to null initially. If the other
  113. // field is queried, it is lazily calculated and cached. These
  114. // two attributes are always kept in sync.
  115. protected ForwardRequest forwardRequest;
  116. protected IOR forwardRequestIOR;
  117. // PICurrent's SlotTable
  118. protected SlotTable slotTable;
  119. // The exception to be returned by received_exception and
  120. // received_exception_id
  121. protected Exception exception;
  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. // Please keep these in the same order as declared above.
  133. flowStackIndex = 0;
  134. startingPointCall = 0;
  135. intermediatePointCall = 0;
  136. endingPointCall = 0;
  137. replyStatus = UNINITIALIZED;
  138. currentExecutionPoint = EXECUTION_POINT_STARTING;
  139. alreadyExecuted = false;
  140. connection = null;
  141. serviceContexts = null;
  142. forwardRequest = null;
  143. forwardRequestIOR = null;
  144. exception = null;
  145. // We don't need to reset the Slots because they are
  146. // already in the clean state after recieve_<point> interceptor
  147. // are called.
  148. }
  149. /*
  150. **********************************************************************
  151. * Access protection
  152. **********************************************************************/
  153. // Method IDs for all methods in RequestInfo. This allows for a
  154. // convenient O(1) lookup for checkAccess().
  155. protected static final int MID_REQUEST_ID = 0;
  156. protected static final int MID_OPERATION = 1;
  157. protected static final int MID_ARGUMENTS = 2;
  158. protected static final int MID_EXCEPTIONS = 3;
  159. protected static final int MID_CONTEXTS = 4;
  160. protected static final int MID_OPERATION_CONTEXT = 5;
  161. protected static final int MID_RESULT = 6;
  162. protected static final int MID_RESPONSE_EXPECTED = 7;
  163. protected static final int MID_SYNC_SCOPE = 8;
  164. protected static final int MID_REPLY_STATUS = 9;
  165. protected static final int MID_FORWARD_REFERENCE = 10;
  166. protected static final int MID_GET_SLOT = 11;
  167. protected static final int MID_GET_REQUEST_SERVICE_CONTEXT = 12;
  168. protected static final int MID_GET_REPLY_SERVICE_CONTEXT = 13;
  169. // The last value from RequestInfo (be sure to update this):
  170. protected static final int MID_RI_LAST = 13;
  171. /*
  172. **********************************************************************
  173. * Public interfaces
  174. **********************************************************************/
  175. /**
  176. * Creates a new RequestInfoImpl object.
  177. */
  178. public RequestInfoImpl( ORB myORB ) {
  179. super();
  180. this.myORB = myORB;
  181. wrapper = InterceptorsSystemException.get( myORB,
  182. CORBALogDomains.RPC_PROTOCOL ) ;
  183. stdWrapper = OMGSystemException.get( myORB,
  184. CORBALogDomains.RPC_PROTOCOL ) ;
  185. // Capture the current TSC and make it the RSC of this request.
  186. PICurrent current = (PICurrent)(myORB.getPIHandler().getPICurrent());
  187. slotTable = current.getSlotTable( );
  188. }
  189. /**
  190. * Implementation for request_id() differs for client and server
  191. * implementations.
  192. *
  193. * Uniquely identifies an active request/reply sequence. Once a
  194. * request/reply sequence is concluded this ID may be reused. (this
  195. * is NOT necessarily the same as the GIOP request_id).
  196. */
  197. abstract public int request_id ();
  198. /**
  199. * Implementation for operation() differs for client and server
  200. * implementations.
  201. *
  202. * The name of the operation being invoked.
  203. */
  204. abstract public String operation ();
  205. /**
  206. * This method returns the list of arguments for the operation that was
  207. * invoked. It raises NO_RESOURCES exception if the operation is not invoked
  208. * by using DII mechanism.
  209. */
  210. abstract public Parameter[] arguments ();
  211. /**
  212. * This method returns the list of exceptios that was raised when the
  213. * operation was invoked. It raises NO_RESOURCES exception if the operation
  214. * is not invoked by using DII mechanism.
  215. */
  216. abstract public TypeCode[] exceptions ();
  217. /**
  218. * This method returns the list of contexts for the DII operation.
  219. * It raises NO_RESOURCES exception if the operation is not invoked by
  220. * using DII mechanism.
  221. */
  222. abstract public String[] contexts ();
  223. /**
  224. * This method returns the list of operation_context for the DII operation.
  225. * It raises NO_RESOURCES exception if the operation is not invoked by
  226. * using DII mechanism.
  227. */
  228. abstract public String[] operation_context ();
  229. /**
  230. * This method returns the result from the invoked DII operation.
  231. * It raises NO_RESOURCES exception if the operation is not invoked by
  232. * using DII mechanism.
  233. */
  234. abstract public Any result ();
  235. /**
  236. * Implementation for response_expected() differs for client and server
  237. * implementations.
  238. *
  239. * Indicates whether a response is expected. On the client, a reply is
  240. * not returned when response_expected is false, so receive_reply cannot
  241. * be called. receive_other is called unless an exception occurs, in
  242. * which case receive_exception is called. On the client, within
  243. * send_poll, this attribute is true.
  244. */
  245. abstract public boolean response_expected ();
  246. /**
  247. * Defined in the Messaging specification. Pertinent only when
  248. * response_expected is false. If response_expected is true, the value
  249. * of sync_scope is undefined. It defines how far the request shall
  250. * progress before control is returned to the client. This attribute may
  251. * have one of the follwing values:
  252. * <ul>
  253. * <li>Messaging::SYNC_NONE</li>
  254. * <li>Messaging::SYNC_WITH_TRANSPORT</li>
  255. * <li>Messaging::SYNC_WITH_SERVER</li>
  256. * <li>Messaging::SYNC_WITH_TARGET</li>
  257. * </ul>
  258. */
  259. public short sync_scope (){
  260. checkAccess( MID_SYNC_SCOPE );
  261. return SYNC_WITH_TRANSPORT.value; // REVISIT - get from MessageMediator
  262. }
  263. /**
  264. * Describes the state of the result of the operation invocation. Its
  265. * value can be one of the following:
  266. * <ul>
  267. * <li>PortableInterceptor::SUCCESSFUL</li>
  268. * <li>PortableInterceptor::SYSTEM_EXCEPTION</li>
  269. * <li>PortableInterceptor::USER_EXCEPTION</li>
  270. * <li>PortableInterceptor::LOCATION_FORWARD</li>
  271. * <li>PortableInterceptor::TRANSPORT_RETRY</li>
  272. * </ul>
  273. */
  274. public short reply_status (){
  275. checkAccess( MID_REPLY_STATUS );
  276. return replyStatus;
  277. }
  278. /**
  279. * Implementation for forward_reference() differs for client and server
  280. * implementations.
  281. *
  282. * If the reply_status attribute is LOCATION_FORWARD
  283. * then this attribute will contain the object
  284. * to which the request will be forwarded. It is indeterminate whether a
  285. * forwarded request will actually occur.
  286. */
  287. abstract public Object forward_reference ();
  288. /**
  289. * Returns the data from the given slot of the PortableInterceptor::Current
  290. * that is in the scope of the request.
  291. * <p>
  292. * If the given slot has not been set, then an any containing a type code
  293. * with a TCKind value of tk_null is returned.
  294. * <p>
  295. * If the ID does not define an allocated slot, InvalidSlot is raised.
  296. */
  297. public Any get_slot (int id)
  298. throws InvalidSlot
  299. {
  300. // access is currently valid for all states:
  301. //checkAccess( MID_GET_SLOT );
  302. // Delegate the call to the slotTable which was set when RequestInfo was
  303. // created.
  304. return slotTable.get_slot( id );
  305. }
  306. /**
  307. * Implementation for get_request_service_context() differs for client
  308. * and server implementations.
  309. *
  310. * This operation returns a copy of the service context with the given ID
  311. * that is associated with the request. If the request's service context
  312. * does not contain an etry for that ID, BAD_PARAM with a minor code of
  313. * TBD_BP is raised.
  314. */
  315. abstract public org.omg.IOP.ServiceContext
  316. get_request_service_context(int id);
  317. /**
  318. * Implementation for get_reply_service_context() differs for client
  319. * and server implementations.
  320. *
  321. * This operation returns a copy of the service context with the given ID
  322. * that is associated with the reply. IF the request's service context
  323. * does not contain an entry for that ID, BAD_PARAM with a minor code of
  324. * TBD_BP is raised.
  325. */
  326. abstract public org.omg.IOP.ServiceContext
  327. get_reply_service_context (int id);
  328. // NOTE: When adding a method, be sure to:
  329. // 1. Add a MID_* constant for that method
  330. // 2. Call checkAccess at the start of the method
  331. // 3. Define entries in the validCall[][] table for interception points
  332. // in both ClientRequestInfoImpl and ServerRequestInfoImpl.
  333. /*
  334. **********************************************************************
  335. * Proprietary methods
  336. **********************************************************************/
  337. /**
  338. * @return The connection on which the request is made.
  339. *
  340. * Note: we store the connection as an internal type but
  341. * expose it here as an external type.
  342. */
  343. public com.sun.corba.se.spi.legacy.connection.Connection connection()
  344. {
  345. return connection;
  346. }
  347. /*
  348. **********************************************************************
  349. * Private utility methods
  350. **********************************************************************/
  351. /**
  352. * Inserts the UserException inside the given ApplicationException
  353. * into the given Any. Throws an UNKNOWN with minor code
  354. * OMGSYstemException.UNKNOWN_USER_EXCEPTION if the Helper class could not be
  355. * found to insert it with.
  356. */
  357. private void insertApplicationException( ApplicationException appException,
  358. Any result )
  359. throws UNKNOWN
  360. {
  361. try {
  362. // Extract the UserException from the ApplicationException.
  363. // Look up class name from repository id:
  364. RepositoryId repId = RepositoryId.cache.getId(
  365. appException.getId() );
  366. String className = repId.getClassName();
  367. // Find the read method on the helper class:
  368. String helperClassName = className + "Helper";
  369. Class helperClass = ORBClassLoader.loadClass( helperClassName );
  370. Class[] readParams = new Class[1];
  371. readParams[0] = org.omg.CORBA.portable.InputStream.class;
  372. Method readMethod = helperClass.getMethod( "read", readParams );
  373. // Invoke the read method, passing in the input stream to
  374. // retrieve the user exception. Mark and reset the stream
  375. // as to not disturb it.
  376. InputStream ueInputStream = appException.getInputStream();
  377. ueInputStream.mark( 0 );
  378. UserException userException = null;
  379. try {
  380. java.lang.Object[] readArguments = new java.lang.Object[1];
  381. readArguments[0] = ueInputStream;
  382. userException = (UserException)readMethod.invoke(
  383. null, readArguments );
  384. }
  385. finally {
  386. try {
  387. ueInputStream.reset();
  388. }
  389. catch( IOException e ) {
  390. throw wrapper.markAndResetFailed( e ) ;
  391. }
  392. }
  393. // Insert this UserException into the provided Any using the
  394. // helper class.
  395. insertUserException( userException, result );
  396. } catch( ClassNotFoundException e ) {
  397. throw stdWrapper.unknownUserException( CompletionStatus.COMPLETED_MAYBE, e ) ;
  398. } catch( NoSuchMethodException e ) {
  399. throw stdWrapper.unknownUserException( CompletionStatus.COMPLETED_MAYBE, e ) ;
  400. } catch( SecurityException e ) {
  401. throw stdWrapper.unknownUserException( CompletionStatus.COMPLETED_MAYBE, e ) ;
  402. } catch( IllegalAccessException e ) {
  403. throw stdWrapper.unknownUserException( CompletionStatus.COMPLETED_MAYBE, e ) ;
  404. } catch( IllegalArgumentException e ) {
  405. throw stdWrapper.unknownUserException( CompletionStatus.COMPLETED_MAYBE, e ) ;
  406. } catch( InvocationTargetException e ) {
  407. throw stdWrapper.unknownUserException( CompletionStatus.COMPLETED_MAYBE, e ) ;
  408. }
  409. }
  410. /**
  411. * Inserts the UserException into the given Any.
  412. * Throws an UNKNOWN with minor code
  413. * OMGSYstemException.UNKNOWN_USER_EXCEPTION if the Helper class could not be
  414. * found to insert it with.
  415. */
  416. private void insertUserException( UserException userException, Any result )
  417. throws UNKNOWN
  418. {
  419. try {
  420. // Insert this UserException into the provided Any using the
  421. // helper class.
  422. if( userException != null ) {
  423. Class exceptionClass = userException.getClass();
  424. String className = exceptionClass.getName();
  425. String helperClassName = className + "Helper";
  426. Class helperClass = ORBClassLoader.loadClass( helperClassName );
  427. // Find insert( Any, class ) method
  428. Class[] insertMethodParams = new Class[2];
  429. insertMethodParams[0] = org.omg.CORBA.Any.class;
  430. insertMethodParams[1] = exceptionClass;
  431. Method insertMethod = helperClass.getMethod(
  432. "insert", insertMethodParams );
  433. // Call helper.insert( result, userException ):
  434. java.lang.Object[] insertMethodArguments =
  435. new java.lang.Object[2];
  436. insertMethodArguments[0] = result;
  437. insertMethodArguments[1] = userException;
  438. insertMethod.invoke( null, insertMethodArguments );
  439. }
  440. } catch( ClassNotFoundException e ) {
  441. throw stdWrapper.unknownUserException( CompletionStatus.COMPLETED_MAYBE, e );
  442. } catch( NoSuchMethodException e ) {
  443. throw stdWrapper.unknownUserException( CompletionStatus.COMPLETED_MAYBE, e );
  444. } catch( SecurityException e ) {
  445. throw stdWrapper.unknownUserException( CompletionStatus.COMPLETED_MAYBE, e );
  446. } catch( IllegalAccessException e ) {
  447. throw stdWrapper.unknownUserException( CompletionStatus.COMPLETED_MAYBE, e );
  448. } catch( IllegalArgumentException e ) {
  449. throw stdWrapper.unknownUserException( CompletionStatus.COMPLETED_MAYBE, e );
  450. } catch( InvocationTargetException e ) {
  451. throw stdWrapper.unknownUserException( CompletionStatus.COMPLETED_MAYBE, e );
  452. }
  453. }
  454. /*
  455. **********************************************************************
  456. * Protected utility methods
  457. **********************************************************************/
  458. /**
  459. * Internal utility method to convert an NVList into a PI Parameter[]
  460. */
  461. protected Parameter[] nvListToParameterArray( NVList parNVList ) {
  462. // _REVISIT_ This utility method should probably be doing a deep
  463. // copy so interceptor can't accidentally change the arguments.
  464. int count = parNVList.count();
  465. Parameter[] plist = new Parameter[count];
  466. try {
  467. for( int i = 0; i < count; i++ ) {
  468. Parameter p = new Parameter();
  469. plist[i] = p;
  470. NamedValue nv = parNVList.item( i );
  471. plist[i].argument = nv.value();
  472. // ParameterMode spec can be found in 99-10-07.pdf
  473. // Section:10.5.22
  474. // nv.flags spec can be found in 99-10-07.pdf
  475. // Section 7.1.1
  476. // nv.flags has ARG_IN as 1, ARG_OUT as 2 and ARG_INOUT as 3
  477. // To convert this into enum PARAM_IN, PARAM_OUT and
  478. // PARAM_INOUT the value is subtracted by 1.
  479. plist[i].mode = ParameterMode.from_int( nv.flags() - 1 );
  480. }
  481. } catch ( Exception e ) {
  482. throw wrapper.exceptionInArguments( e ) ;
  483. }
  484. return plist;
  485. }
  486. /**
  487. * Utility to wrap the given Exception in an Any object and return it.
  488. * If the exception is a UserException which cannot be inserted into
  489. * an any, then this returns an Any containing the system exception
  490. * UNKNOWN.
  491. */
  492. protected Any exceptionToAny( Exception exception ){
  493. Any result = myORB.create_any();
  494. if( exception == null ) {
  495. // Note: exception should never be null here since we will throw
  496. // a BAD_INV_ORDER if this is not called from receive_exception.
  497. throw wrapper.exceptionWasNull2() ;
  498. } else if( exception instanceof SystemException ) {
  499. ORBUtility.insertSystemException(
  500. (SystemException)exception, result );
  501. } else if( exception instanceof ApplicationException ) {
  502. // Use the Helper class for this exception to insert it into an
  503. // Any.
  504. try {
  505. // Insert the user exception inside the application exception
  506. // into the Any result:
  507. ApplicationException appException =
  508. (ApplicationException)exception;
  509. insertApplicationException( appException, result );
  510. } catch( UNKNOWN e ) {
  511. // As per ptc/00-08-06, 21.3.13.4. if we cannot find the
  512. // appropriate class, then return an any containing UNKNOWN,
  513. // with a minor code of 1. This is conveniently the same
  514. // exception that is returned from the
  515. // insertApplicationException utility method.
  516. ORBUtility.insertSystemException( e, result );
  517. }
  518. } else if( exception instanceof UserException ) {
  519. try {
  520. UserException userException = (UserException)exception;
  521. insertUserException( userException, result );
  522. } catch( UNKNOWN e ) {
  523. ORBUtility.insertSystemException( e, result );
  524. }
  525. }
  526. return result;
  527. }
  528. /**
  529. * Utility method to look up a service context with the given id and
  530. * convert it to an IOP.ServiceContext. Uses the given HashMap as
  531. * a cache. If not found in cache, the result is inserted in the cache.
  532. */
  533. protected org.omg.IOP.ServiceContext
  534. getServiceContext ( HashMap cachedServiceContexts,
  535. ServiceContexts serviceContexts, int id )
  536. {
  537. org.omg.IOP.ServiceContext result = null;
  538. Integer integerId = new Integer( id );
  539. // Search cache first:
  540. result = (org.omg.IOP.ServiceContext)
  541. cachedServiceContexts.get( integerId );
  542. // null could normally mean that either we cached the value null
  543. // or it's not in the cache. However, there is no way for us to
  544. // cache the value null in the following code.
  545. if( result == null ) {
  546. // Not in cache. Find it and put in cache.
  547. // Get the desired "core" service context.
  548. com.sun.corba.se.spi.servicecontext.ServiceContext context =
  549. serviceContexts.get( id );
  550. if (context == null)
  551. throw stdWrapper.invalidServiceContextId() ;
  552. // Convert the "core" service context to an
  553. // "IOP" ServiceContext by writing it to a
  554. // CDROutputStream and reading it back.
  555. EncapsOutputStream out = new EncapsOutputStream(myORB);
  556. context.write( out, GIOPVersion.V1_2 );
  557. InputStream inputStream = out.create_input_stream();
  558. result = ServiceContextHelper.read( inputStream );
  559. cachedServiceContexts.put( integerId, result );
  560. }
  561. // Good citizen: For increased efficiency, we assume that interceptors
  562. // will not modify the returned ServiceContext. Otherwise, we would
  563. // have to make a deep copy.
  564. return result;
  565. }
  566. /**
  567. * Utility method to add an IOP.ServiceContext to a core.ServiceContexts
  568. * object. If replace is true, any service context with the given id
  569. * is replaced.
  570. * <p>
  571. * Raises BAD_INV_ORDER if replace is false and a service context with
  572. * the given id already exists.
  573. * <p>
  574. * Uses the given HashMap as a cache. If a service context is placed
  575. * in the container, it goes in the HashMap as well.
  576. */
  577. protected void addServiceContext(
  578. HashMap cachedServiceContexts,
  579. ServiceContexts serviceContexts,
  580. org.omg.IOP.ServiceContext service_context,
  581. boolean replace )
  582. {
  583. int id = 0 ;
  584. // Convert IOP.service_context to core.ServiceContext:
  585. EncapsOutputStream outputStream = new EncapsOutputStream(
  586. myORB );
  587. InputStream inputStream = null;
  588. UnknownServiceContext coreServiceContext = null;
  589. ServiceContextHelper.write( outputStream, service_context );
  590. inputStream = outputStream.create_input_stream();
  591. // Constructor expects id to already have been read from stream.
  592. coreServiceContext = new UnknownServiceContext(
  593. inputStream.read_long(),
  594. (org.omg.CORBA_2_3.portable.InputStream)inputStream );
  595. id = coreServiceContext.getId();
  596. if (serviceContexts.get(id) != null)
  597. if (replace)
  598. serviceContexts.delete( id );
  599. else
  600. throw stdWrapper.serviceContextAddFailed( new Integer(id) ) ;
  601. serviceContexts.put( coreServiceContext );
  602. // Place IOP.ServiceContext in cache as well:
  603. cachedServiceContexts.put( new Integer( id ), service_context );
  604. }
  605. /**
  606. * Sets the number of interceptors whose starting interception
  607. * points were successfully invoked on this client call. As specified
  608. * in orbos/99-12-02, section 5.2.1., not all interceptors will
  609. * be invoked if a ForwardRequest exception or a system exception
  610. * is raised. This keeps track of how many were successfully executed
  611. * so we know not to execute the corresponding ending interception
  612. * points for the interceptors whose starting interception points
  613. * were not completed. This simulates the "Flow Stack Visual Model"
  614. * presented in section 5.1.3.*/
  615. protected void setFlowStackIndex(int num ) {
  616. this.flowStackIndex = num;
  617. }
  618. /**
  619. * Returns the number of interceptors whose starting interception
  620. * points were actually invoked on this client request. See
  621. * setFlowStackIndex for more details.
  622. */
  623. protected int getFlowStackIndex() {
  624. return this.flowStackIndex;
  625. }
  626. /**
  627. * Sets which ending interception point should be called
  628. * for each interceptor in the virtual flow stack.
  629. */
  630. protected void setEndingPointCall( int call ) {
  631. this.endingPointCall = call;
  632. }
  633. /**
  634. * Retrieves the current ending point call type (see
  635. * setEndingPointCall for more details).
  636. */
  637. protected int getEndingPointCall() {
  638. return this.endingPointCall;
  639. }
  640. /**
  641. * Sets which intermediate interception point should be called
  642. * for each interceptor in the virtual flow stack.
  643. */
  644. protected void setIntermediatePointCall( int call ) {
  645. this.intermediatePointCall = call;
  646. }
  647. /**
  648. * Retrieves the current intermediate point call type (see
  649. * setEndingPointCall for more details).
  650. */
  651. protected int getIntermediatePointCall() {
  652. return this.intermediatePointCall;
  653. }
  654. /**
  655. * Sets which starting interception point should be called
  656. * for each interceptor in the virtual flow stack.
  657. */
  658. protected void setStartingPointCall( int call ) {
  659. this.startingPointCall = call;
  660. }
  661. /**
  662. * Retrieves the current starting point call type (see
  663. * setStartingPointCall for more details).
  664. */
  665. protected int getStartingPointCall() {
  666. return this.startingPointCall;
  667. }
  668. /**
  669. * Returns true if all interceptors' starting and ending points
  670. * have already executed to completion, or false if not yet.
  671. */
  672. protected boolean getAlreadyExecuted() {
  673. return this.alreadyExecuted;
  674. }
  675. /**
  676. * Sets whether all interceotrs' starting and ending points
  677. * have already been executed to completion.
  678. */
  679. protected void setAlreadyExecuted( boolean alreadyExecuted ) {
  680. this.alreadyExecuted = alreadyExecuted;
  681. }
  682. /**
  683. * Sets the value to be returned by reply_status
  684. */
  685. protected void setReplyStatus( short replyStatus ) {
  686. this.replyStatus = replyStatus;
  687. }
  688. /**
  689. * Gets the current reply_status without doing an access check
  690. * (available only to package and subclasses)
  691. */
  692. protected short getReplyStatus() {
  693. return this.replyStatus;
  694. }
  695. /**
  696. * Stores the given ForwardRequest object for later analysis.
  697. * This version supplements setForwardRequest( IOR );
  698. */
  699. protected void setForwardRequest( ForwardRequest forwardRequest ) {
  700. this.forwardRequest = forwardRequest;
  701. this.forwardRequestIOR = null;
  702. }
  703. /**
  704. * Stores the given IOR for later forward request analysis.
  705. * This version supplements setForwardRequest( ForwardRequest );
  706. */
  707. protected void setForwardRequest( IOR ior ) {
  708. this.forwardRequestIOR = ior;
  709. this.forwardRequest = null;
  710. }
  711. /**
  712. * Retrieves the ForwardRequest object as a ForwardRequest exception.
  713. */
  714. protected ForwardRequest getForwardRequestException() {
  715. if( this.forwardRequest == null ) {
  716. if( this.forwardRequestIOR != null ) {
  717. // Convert the internal IOR to a forward request exception
  718. // by creating an object reference.
  719. org.omg.CORBA.Object obj = iorToObject(this.forwardRequestIOR);
  720. this.forwardRequest = new ForwardRequest( obj );
  721. }
  722. }
  723. return this.forwardRequest;
  724. }
  725. /**
  726. * Retrieves the IOR of the ForwardRequest exception.
  727. */
  728. protected IOR getForwardRequestIOR() {
  729. if( this.forwardRequestIOR == null ) {
  730. if( this.forwardRequest != null ) {
  731. this.forwardRequestIOR = ORBUtility.getIOR(
  732. this.forwardRequest.forward ) ;
  733. }
  734. }
  735. return this.forwardRequestIOR;
  736. }
  737. /**
  738. * Sets the exception to be returned by received_exception and
  739. * received_exception_id.
  740. */
  741. protected void setException( Exception exception ) {
  742. this.exception = exception;
  743. }
  744. /**
  745. * Returns the exception to be returned by received_exception and
  746. * received_exception_id.
  747. */
  748. Exception getException() {
  749. return this.exception;
  750. }
  751. /**
  752. * Sets the execution point that we are currently executing
  753. * (starting points, intermediate points, or ending points).
  754. * This allows us to enforce the validity table.
  755. */
  756. protected void setCurrentExecutionPoint( int executionPoint ) {
  757. this.currentExecutionPoint = executionPoint;
  758. }
  759. /**
  760. * Check whether the caller is allowed to access this method at
  761. * this particular time. This is overridden in subclasses to implement
  762. * the validity table specified in ptc/00-04-05, table 21-1 and 21-2.
  763. * The currentExecutionPoint attribute is checked, and if access is
  764. * forbidden at this time, BAD_INV_ORDER is raised with a minor code of
  765. * TBD_BIO.
  766. *
  767. * @param methodID The ID of this method, one of the MID_* constants.
  768. * This allows us to easily look up the method access in a table.
  769. * Note that method ids may overlap between subclasses.
  770. */
  771. protected abstract void checkAccess( int methodID )
  772. throws BAD_INV_ORDER;
  773. /**
  774. * The server side does an explicit set rather than taking the
  775. * current PICurrent table as is done in the general RequestInfoImpl
  776. * constructor.
  777. */
  778. void setSlotTable(SlotTable slotTable)
  779. {
  780. this.slotTable = slotTable;
  781. }
  782. protected org.omg.CORBA.Object iorToObject( IOR ior )
  783. {
  784. return ORBUtility.makeObjectReference( ior ) ;
  785. }
  786. }