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