1. /*
  2. * @(#)PIORB.java 1.63 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.CORBA.Any;
  9. import org.omg.CORBA.BAD_PARAM;
  10. import org.omg.CORBA.BAD_POLICY;
  11. import org.omg.CORBA.BAD_INV_ORDER;
  12. import org.omg.CORBA.COMM_FAILURE;
  13. import org.omg.CORBA.CompletionStatus;
  14. import org.omg.CORBA.INTERNAL;
  15. import org.omg.CORBA.NVList;
  16. import org.omg.CORBA.OBJECT_NOT_EXIST;
  17. import org.omg.CORBA.ORBPackage.InvalidName;
  18. import org.omg.CORBA.SystemException;
  19. import org.omg.CORBA.UserException;
  20. import org.omg.CORBA.UNKNOWN;
  21. import org.omg.CORBA.portable.ApplicationException;
  22. import org.omg.CORBA.portable.Delegate;
  23. import org.omg.CORBA.portable.ObjectImpl;
  24. import org.omg.CORBA.portable.RemarshalException;
  25. import com.sun.corba.se.internal.corba.ClientDelegate;
  26. import com.sun.corba.se.internal.corba.RequestImpl;
  27. import com.sun.corba.se.internal.core.ClientResponse;
  28. import com.sun.corba.se.internal.core.ClientRequest;
  29. import com.sun.corba.se.internal.core.ClientSubcontract;
  30. import com.sun.corba.se.internal.core.InternalRuntimeForwardRequest;
  31. import com.sun.corba.se.internal.core.IOR;
  32. import com.sun.corba.se.internal.core.ServerRequest;
  33. import com.sun.corba.se.internal.core.ServiceContexts;
  34. import com.sun.corba.se.internal.core.Constant;
  35. import com.sun.corba.se.internal.iiop.Connection;
  36. import com.sun.corba.se.internal.iiop.IIOPConnection;
  37. import com.sun.corba.se.internal.iiop.IIOPOutputStream;
  38. import com.sun.corba.se.internal.iiop.messages.ReplyMessage;
  39. import com.sun.corba.se.internal.ior.IIOPProfile;
  40. import com.sun.corba.se.internal.ior.IORTemplate;
  41. import com.sun.corba.se.internal.orbutil.ORBConstants;
  42. import com.sun.corba.se.internal.orbutil.ORBClassLoader;
  43. import com.sun.corba.se.internal.POA.POAImpl;
  44. import com.sun.corba.se.internal.POA.POAORB;
  45. import com.sun.corba.se.internal.orbutil.ORBUtility;
  46. import org.omg.IOP.CodecFactory;
  47. import org.omg.PortableInterceptor.ForwardRequest;
  48. import org.omg.PortableInterceptor.Interceptor;
  49. import org.omg.PortableInterceptor.LOCATION_FORWARD;
  50. import org.omg.PortableInterceptor.ORBInitializer;
  51. import org.omg.PortableInterceptor.ORBInitInfo;
  52. import org.omg.PortableInterceptor.ORBInitInfoPackage.DuplicateName;
  53. import org.omg.PortableInterceptor.SUCCESSFUL;
  54. import org.omg.PortableInterceptor.SYSTEM_EXCEPTION;
  55. import org.omg.PortableInterceptor.TRANSPORT_RETRY;
  56. import org.omg.PortableInterceptor.USER_EXCEPTION;
  57. import org.omg.PortableInterceptor.PolicyFactory;
  58. import java.util.*;
  59. import java.io.IOException;
  60. /**
  61. * Extends the POAORB to provide portable interceptor functionality.
  62. */
  63. public class PIORB
  64. extends POAORB
  65. {
  66. // A unique id used in ServerRequestInfo.
  67. // This does not correspond to the GIOP request id.
  68. private int serverRequestIdCounter = 0;
  69. // Stores the codec factory for producing codecs
  70. CodecFactory codecFactory = null;
  71. // The actual instances of the initializers. Some elements mat be null
  72. // if there were errors finding or instantiating intializers. These
  73. // entries should be ignored.
  74. ORBInitializer[] orbInitializers = null;
  75. // The arguments passed to the application's main method. May be null.
  76. // This is used for ORBInitializers and set from set_parameters.
  77. String[] arguments = null;
  78. // List of property name prefixes recognized by this ORB.
  79. private static final String[] PIORBPropertyNamePrefixes = {
  80. ORBConstants.PI_ORB_INITIALIZER_CLASS_PREFIX
  81. };
  82. // The list of portable interceptors, organized by type:
  83. private InterceptorList interceptorList;
  84. // Cached information for optimization - do we have any interceptors
  85. // registered of the given types? Set during ORB initialization.
  86. private boolean hasIORInterceptors;
  87. private boolean hasClientInterceptors;
  88. private boolean hasServerInterceptors;
  89. // The class responsible for invoking interceptors
  90. private InterceptorInvoker interceptorInvoker;
  91. // There will be one PICurrent instantiated for every ORB.
  92. private PICurrent current;
  93. // This table contains a list of PolicyFactories registered using
  94. // ORBInitInfo.registerPolicyFactory() method.
  95. // Key for the table is PolicyType which is an Integer
  96. // Value is PolicyFactory.
  97. private HashMap policyFactoryTable;
  98. // Table to convert from a ReplyMessage.? to a PI replyStatus short.
  99. // Note that this table relies on the order and constants of
  100. // ReplyMessage not to change.
  101. private final static short REPLY_MESSAGE_TO_PI_REPLY_STATUS[] = {
  102. SUCCESSFUL.value, // = ReplyMessage.NO_EXCEPTION
  103. USER_EXCEPTION.value, // = ReplyMessage.USER_EXCEPTION
  104. SYSTEM_EXCEPTION.value, // = ReplyMessage.SYSTEM_EXCEPTION
  105. LOCATION_FORWARD.value, // = ReplyMessage.LOCATION_FORWARD
  106. LOCATION_FORWARD.value, // = ReplyMessage.LOCATION_FORWARD_PERM
  107. TRANSPORT_RETRY.value // = ReplyMessage.NEEDS_ADDRESSING_MODE
  108. };
  109. // ThreadLocal containing a stack to store client request info objects
  110. // and a disable count.
  111. private ThreadLocal threadLocalClientRequestInfoStack =
  112. new ThreadLocal() {
  113. protected Object initialValue() {
  114. return new RequestInfoStack();
  115. }
  116. };
  117. // ThreadLocal containing the current server request info object.
  118. private ThreadLocal threadLocalServerRequestInfoStack =
  119. new ThreadLocal() {
  120. protected Object initialValue() {
  121. return new RequestInfoStack();
  122. }
  123. };
  124. // Class to contain all ThreadLocal data for ClientRequestInfo
  125. // maintenance.
  126. //
  127. // We simulate a Stack here instead of using java.util.Stack because
  128. // java.util.Stack is thread-safe, negatively impacting performance.
  129. // We use an ArrayList instead since it is not thread-safe.
  130. // RequestInfoStack is used quite frequently.
  131. private final class RequestInfoStack {
  132. // The stack for RequestInfo objects.
  133. private final ArrayList stack = new ArrayList();
  134. // Number of times a request has been made to disable interceptors.
  135. // When this reaches 0, interception hooks are disabled. Any higher
  136. // value indicates they are enabled.
  137. // NOTE: The is only currently used on the client side.
  138. public int disableCount = 0;
  139. // Tests if this stack is empty.
  140. public final boolean empty() {
  141. return stack.size() == 0;
  142. }
  143. // Looks at the object at the top of this stack without removing it
  144. // from the stack.
  145. public final Object peek() {
  146. int len = stack.size();
  147. if( len == 0 ) throw new EmptyStackException();
  148. return stack.get( len - 1 );
  149. }
  150. // Removes the object at the top of this stack and returns that
  151. // object as the value of this function.
  152. public final Object pop() {
  153. Object obj;
  154. int len = stack.size();
  155. if( len == 0 ) throw new EmptyStackException();
  156. obj = stack.get( len - 1 );
  157. stack.remove( len - 1 );
  158. return obj;
  159. }
  160. // Pushes an item onto the top of the stack
  161. public final Object push( Object item ) {
  162. stack.add( item );
  163. return item;
  164. }
  165. }
  166. /**
  167. * Default constructor.
  168. * This is the only constructor, and it must be followed by
  169. * the appropriate set_parameters() call.
  170. */
  171. public PIORB() {
  172. super();
  173. // Create codec factory:
  174. codecFactory = new CodecFactoryImpl( this );
  175. // Create new interceptor list:
  176. interceptorList = new InterceptorList();
  177. // Create a new PICurrent.
  178. current = new PICurrent( this );
  179. // Create new interceptor invoker, initially disabled:
  180. interceptorInvoker = new InterceptorInvoker( this, interceptorList,
  181. current );
  182. // Register the PI current and Codec factory objects
  183. registerInitialReference( ORBConstants.PI_CURRENT_NAME,
  184. new Constant( current ) ) ;
  185. registerInitialReference( ORBConstants.CODEC_FACTORY_NAME,
  186. new Constant( codecFactory ) ) ;
  187. }
  188. /**
  189. * Do miscellaneous initialization for subcontracts. This is called
  190. * after set_parameters() in the POAORB. It is used here to create
  191. * the CodecFactory.
  192. */
  193. protected void initPostProcessing() {
  194. // Allow POAORB to do post-processing initialization
  195. super.initPostProcessing();
  196. // If we have any orb initializers, make use of them:
  197. if( orbInitializers != null ) {
  198. // Create the ORBInitInfo object to pass to ORB intializers:
  199. ORBInitInfoImpl orbInitInfo = createORBInitInfo();
  200. // Make sure get_slot and set_slot are not called from within
  201. // ORB initializers:
  202. current.setORBInitializing( true );
  203. // Call pre_init on all ORB initializers:
  204. preInitORBInitializers( orbInitInfo );
  205. // Call post_init on all ORB initializers:
  206. postInitORBInitializers( orbInitInfo );
  207. // Proprietary: sort interceptors:
  208. interceptorList.sortInterceptors();
  209. // Re-enable get_slot and set_slot to be called from within
  210. // ORB initializers:
  211. current.setORBInitializing( false );
  212. // Ensure nobody makes any more calls on this object.
  213. orbInitInfo.setStage( ORBInitInfoImpl.STAGE_CLOSED );
  214. // Set cached flags indicating whether we have interceptors
  215. // registered of a given type.
  216. hasIORInterceptors = interceptorList.hasInterceptorsOfType(
  217. InterceptorList.INTERCEPTOR_TYPE_IOR );
  218. hasClientInterceptors = interceptorList.hasInterceptorsOfType(
  219. InterceptorList.INTERCEPTOR_TYPE_CLIENT );
  220. hasServerInterceptors = interceptorList.hasInterceptorsOfType(
  221. InterceptorList.INTERCEPTOR_TYPE_SERVER );
  222. // Enable interceptor invoker (not necessary if no interceptors
  223. // are registered). This should be the last stage of ORB
  224. // initialization.
  225. interceptorInvoker.setEnabled( true );
  226. }
  227. }
  228. /**
  229. *
  230. * ptc/00-08-06 p 205: "When an application calls ORB::destroy, the ORB
  231. * 1) waits for all requests in progress to complete
  232. * 2) calls the Interceptor::destroy operation for each interceptor
  233. * 3) completes destruction of the ORB"
  234. */
  235. public void destroy() {
  236. super.destroy();
  237. interceptorList.destroyAll();
  238. }
  239. /*
  240. **********************************************************************
  241. * The following methods deal with ORB initialization and property
  242. * parsing, etc.
  243. ************************************************************************/
  244. /**
  245. * Return a list of property names prefixes that this ORB is interested in.
  246. * This may be overridden by subclasses, but subclasses must call
  247. * super.getPropertyNamePrefixes() to get all names.
  248. * Called from super.set_parameters() for both application and applets.
  249. */
  250. protected String[] getPropertyNamePrefixes() {
  251. String[] names = super.getPropertyNamePrefixes();
  252. // Add names that we are interested in
  253. int supercount = names.length;
  254. String[] allnames = new String[supercount +
  255. PIORBPropertyNamePrefixes.length];
  256. for ( int i=0; i<supercount; i++ )
  257. allnames[i] = names[i];
  258. for ( int i=0; i<PIORBPropertyNamePrefixes.length; i++ )
  259. allnames[i+supercount] = PIORBPropertyNamePrefixes[i];
  260. if (ORBInitDebug) {
  261. dprint( "getPropertyNamePrefixes returns " +
  262. ORBUtility.objectToString( allnames ) ) ;
  263. }
  264. return allnames;
  265. }
  266. /**
  267. * Initialize any necessary ORB state; get attributes if possible.
  268. * Called from org.omg.CORBA.ORB.init(). This method is overridden
  269. * so that we may remember the commandline arguments passed to the
  270. * application instantiating this ORB. This is later available by a call
  271. * to ORBInitInfo.arguments() for ORBInitializers.
  272. *
  273. * @param params command-line arguments for the application's main method.
  274. * may be <code>null</code>.
  275. * "-param-name" and "param-value" strings.
  276. * @param props the application properties
  277. */
  278. protected void set_parameters (String[] params, Properties props) {
  279. this.arguments = params;
  280. super.set_parameters( params, props );
  281. }
  282. /**
  283. * Set ORB internal variables using the properties specified.
  284. * Called from super.set_parameters() for both applications and applets.
  285. */
  286. protected void parseProperties( Properties props ) {
  287. super.parseProperties( props );
  288. // Read in PI orb initializers and instantiate them:
  289. registerORBInitializers( props );
  290. }
  291. /**
  292. * Register and instantiate ORB initializers, as per PI spec,
  293. * ptc/00-08-06, section 21.7.3.1
  294. */
  295. private void registerORBInitializers( Properties props ) {
  296. // Find all property names that begin with the orb init prefix
  297. // and add to the orb initializers list.
  298. String orbInitPrefix = ORBConstants.PI_ORB_INITIALIZER_CLASS_PREFIX;
  299. Enumeration propertyNames = props.propertyNames();
  300. ArrayList initializerList = new ArrayList();
  301. while( propertyNames.hasMoreElements() ) {
  302. String propertyName = (String)propertyNames.nextElement();
  303. if( propertyName.startsWith( orbInitPrefix ) ) {
  304. // Extract orb initializer name from property:
  305. String initClassName = propertyName.substring(
  306. orbInitPrefix.length() );
  307. try {
  308. Class initClass = ORBClassLoader.loadClass( initClassName );
  309. // For security reasons avoid creating an instance
  310. // if this class is one that would fail the class cast
  311. // to ORBInitializer anyway.
  312. if( ORBInitializer.class.isAssignableFrom( initClass ) ) {
  313. // Now that we have a class object, instantiate one and
  314. // remember it:
  315. if( initClass != null ) {
  316. ORBInitializer initializer =
  317. (ORBInitializer)initClass.newInstance();
  318. initializerList.add( initializer );
  319. }
  320. }
  321. }
  322. catch( Exception e ) {
  323. // As per ptc/00-08-06, section 21.7.3.1., "If there
  324. // are any exceptions the ORB shall ignore them and
  325. // proceed."
  326. }
  327. } // end if this property starts with prefix
  328. } // end while there are more properties
  329. if( initializerList.size() > 0 ) {
  330. orbInitializers = (ORBInitializer[])initializerList.toArray(
  331. new ORBInitializer[0] );
  332. }
  333. else {
  334. orbInitializers = null;
  335. }
  336. }
  337. /*
  338. **************************************************************************
  339. * The following methods are the implementations for the Portable
  340. * Interceptors hooks found in POAORB and corba.ORB.
  341. *
  342. * They are made final for security purposes - someone could otherwise
  343. * derive from PIORB and get sensitive information and intercept
  344. * the interceptors themselves. This way, there is
  345. * no convenient way to get sensitive information and have PI
  346. * functionality at the same time (though they could inherit from POAORB
  347. * and get sensitive information, they would have to re-implement
  348. * Portable Interceptors to get sensitive information and still have
  349. * PI functionality).
  350. *************************************************************************/
  351. /**
  352. * Overridden from POAORB.
  353. * Called when a new POA is created.
  354. *
  355. * @param poaImpl The POAImpl associated with these IOR Interceptor.
  356. */
  357. final protected void invokeIORInterceptors( POAImpl poaImpl ) {
  358. if( !hasIORInterceptors ) return;
  359. // Forward request to interceptor invoker:
  360. interceptorInvoker.invokeIORInterceptors( poaImpl );
  361. }
  362. /*
  363. *****************
  364. * Client PI hooks
  365. *****************/
  366. /**
  367. * Overridden from corba.ORB.
  368. * Called for pseudo-ops to temporarily disable portable interceptor
  369. * hooks for calls on this thread. Keeps track of the number of
  370. * times this is called and increments the disabledCount.
  371. */
  372. final protected void disableInterceptorsThisThread() {
  373. if( !hasClientInterceptors ) return;
  374. RequestInfoStack infoStack =
  375. (RequestInfoStack)threadLocalClientRequestInfoStack.get();
  376. infoStack.disableCount++;
  377. }
  378. /**
  379. * Overridden from corba.ORB.
  380. * Called for pseudo-ops to re-enable portable interceptor
  381. * hooks for calls on this thread. Decrements the disabledCount.
  382. * If disabledCount is 0, interceptors are re-enabled.
  383. */
  384. final protected void enableInterceptorsThisThread() {
  385. if( !hasClientInterceptors ) return;
  386. RequestInfoStack infoStack =
  387. (RequestInfoStack)threadLocalClientRequestInfoStack.get();
  388. infoStack.disableCount--;
  389. }
  390. /**
  391. * Overridden from corba.ORB.
  392. * Called when the send_request or send_poll portable interception point
  393. * is to be invoked for all appropriate client-side request interceptors.
  394. * Happens on any orb-mediated call.
  395. *
  396. * @exception RemarhsalException - Thrown when this request needs to
  397. * be retried.
  398. */
  399. final protected void invokeClientPIStartingPoint()
  400. throws RemarshalException
  401. {
  402. if( !hasClientInterceptors ) return;
  403. if( !isClientPIEnabledForThisThread() ) return;
  404. // Invoke the starting interception points and record exception
  405. // and reply status info in the info object:
  406. ClientRequestInfoImpl info = peekClientRequestInfoImplStack();
  407. interceptorInvoker.invokeClientInterceptorStartingPoint( info );
  408. // Check reply status. If we will not have another chance later
  409. // to invoke the client ending points, do it now.
  410. short replyStatus = info.getReplyStatus();
  411. if( (replyStatus == SYSTEM_EXCEPTION.value) ||
  412. (replyStatus == LOCATION_FORWARD.value) )
  413. {
  414. // Note: Transport retry cannot happen here since this happens
  415. // before the request hits the wire.
  416. Exception exception = invokeClientPIEndingPoint(
  417. convertPIReplyStatusToReplyMessage( replyStatus ),
  418. info.getException() );
  419. if( exception == null ) {
  420. // Do not throw anything. Otherwise, it must be a
  421. // SystemException, UserException or RemarshalException.
  422. }
  423. if( exception instanceof SystemException ) {
  424. throw (SystemException)exception;
  425. }
  426. else if( exception instanceof RemarshalException ) {
  427. throw (RemarshalException)exception;
  428. }
  429. else if( (exception instanceof UserException) ||
  430. (exception instanceof ApplicationException) )
  431. {
  432. // It should not be possible for an interceptor to throw
  433. // a UserException. By asserting instead of throwing the
  434. // UserException, we need not declare anything but
  435. // RemarshalException in the throws clause.
  436. throw new INTERNAL(
  437. "Assertion failed: Interceptor set exception to " +
  438. "UserException or ApplicationException.",
  439. MinorCodes.EXCEPTION_INVALID,
  440. CompletionStatus.COMPLETED_NO );
  441. }
  442. }
  443. else if( replyStatus != ClientRequestInfoImpl.UNINITIALIZED ) {
  444. throw new INTERNAL(
  445. "Assertion failed: Reply status is initialized but not " +
  446. "SYSTEM_EXCEPTION, or LOCATION_FORWARD_*.",
  447. MinorCodes.REPLY_STATUS_NOTINIT,
  448. CompletionStatus.COMPLETED_NO );
  449. }
  450. }
  451. /**
  452. * Overridden from corba.ORB.
  453. * Called when the appropriate client ending interception point is
  454. * to be invoked for all apporpriate client-side request interceptors.
  455. *
  456. * @param replyStatus One of the constants in iiop.messages.ReplyMessage
  457. * indicating which reply status to set.
  458. * @param exception The exception before ending interception points have
  459. * been invoked, or null if no exception at the moment.
  460. * @return The exception to be thrown, after having gone through
  461. * all ending points, or null if there is no exception to be
  462. * thrown. Note that this exception can be either the same or
  463. * different from the exception set using setClientPIException.
  464. * There are four possible return types: null (no exception),
  465. * SystemException, UserException, or RemarshalException.
  466. */
  467. final protected Exception invokeClientPIEndingPoint(
  468. int replyStatus, Exception exception )
  469. {
  470. if( !hasClientInterceptors ) return exception;
  471. if( !isClientPIEnabledForThisThread() ) return exception;
  472. // Translate ReplyMessage.replyStatus into PI replyStatus:
  473. // Note: this is also an assertion to make sure a valid replyStatus
  474. // is passed in (IndexOutOfBoundsException will be thrown otherwise)
  475. short piReplyStatus = REPLY_MESSAGE_TO_PI_REPLY_STATUS[replyStatus];
  476. // Invoke the ending interception points and record exception
  477. // and reply status info in the info object:
  478. ClientRequestInfoImpl info = peekClientRequestInfoImplStack();
  479. info.setReplyStatus( piReplyStatus );
  480. info.setException( exception );
  481. interceptorInvoker.invokeClientInterceptorEndingPoint( info );
  482. piReplyStatus = info.getReplyStatus();
  483. // Check reply status:
  484. if( (piReplyStatus == LOCATION_FORWARD.value) ||
  485. (piReplyStatus == TRANSPORT_RETRY.value) )
  486. {
  487. // If this is a forward or a retry, reset and reuse
  488. // info object:
  489. info.reset();
  490. info.setRetryRequest( true );
  491. // ... and return a RemarshalException so the orb internals know
  492. exception = new RemarshalException();
  493. }
  494. else if( (piReplyStatus == SYSTEM_EXCEPTION.value) ||
  495. (piReplyStatus == USER_EXCEPTION.value) )
  496. {
  497. exception = info.getException();
  498. }
  499. return exception;
  500. }
  501. /**
  502. * Overridden from corba.ORB.
  503. * <p>
  504. * Invoked when a request is about to be created. Must be called before
  505. * any of the setClientPI* methods so that a new info object can be
  506. * prepared for information collection.
  507. * <p>
  508. * Happens on any orb-mediated call. Note that this method may be
  509. * called multiple times if a request is retried.
  510. * <p>
  511. * This call is essentially required so we can maintain the same info
  512. * object across invocations. This is not required by the current spec,
  513. * but we will eventually need this functionality for things like
  514. * invocation ids.
  515. * <p>
  516. * On a DII request, initiate is called twice (once in doInvocation so
  517. * we can set the RequestImpl object, and once in
  518. * ClientDelegate.createRequest. In this case, we must ignore the second
  519. * initiate call.
  520. */
  521. final protected void initiateClientPIRequest( boolean diiRequest ) {
  522. if( !hasClientInterceptors ) return;
  523. if( !isClientPIEnabledForThisThread() ) return;
  524. // Get the most recent info object from the thread local
  525. // ClientRequestInfoImpl stack:
  526. RequestInfoStack infoStack =
  527. (RequestInfoStack)threadLocalClientRequestInfoStack.get();
  528. ClientRequestInfoImpl info = null;
  529. if( !infoStack.empty() ) info =
  530. (ClientRequestInfoImpl)infoStack.peek();
  531. if( !diiRequest && (info != null) && info.isDIIInitiate() ) {
  532. // In RequestImpl.doInvocation we already called
  533. // initiateClientPIRequest( true ), so ignore this initiate.
  534. info.setDIIInitiate( false );
  535. }
  536. else {
  537. // If there is no info object or if we are not retrying a request,
  538. // push a new ClientRequestInfoImpl on the stack:
  539. if( (info == null) || !info.getRetryRequest() ) {
  540. info = new ClientRequestInfoImpl( this );
  541. infoStack.push( info );
  542. // Note: the entry count is automatically initialized to 0.
  543. }
  544. // Reset the retry request flag so that recursive calls will
  545. // push a new info object, and bump up entry count so we know
  546. // when to pop this info object:
  547. info.setRetryRequest( false );
  548. info.incrementEntryCount();
  549. // If this is a DII request, make sure we ignore the next initiate.
  550. if( diiRequest ) {
  551. info.setDIIInitiate( true );
  552. }
  553. }
  554. }
  555. /**
  556. * Overridden from corba.ORB.
  557. * Invoked when a request is about to be cleaned up. Must be called
  558. * after ending points are called so that the info object on the stack
  559. * can be deinitialized and popped from the stack at the appropriate
  560. * time.
  561. */
  562. final protected void cleanupClientPIRequest() {
  563. if( !hasClientInterceptors ) return;
  564. if( !isClientPIEnabledForThisThread() ) return;
  565. ClientRequestInfoImpl info = peekClientRequestInfoImplStack();
  566. // If the replyStatus has not yet been set, this is an indication
  567. // that the ORB threw an exception before we had a chance to
  568. // invoke the client interceptor ending points.
  569. //
  570. // _REVISIT_ We cannot handle any exceptions or ForwardRequests
  571. // flagged by the ending points here because there is no way
  572. // to gracefully handle this in any of the calling code.
  573. // This is a rare corner case, so we will ignore this for now.
  574. short replyStatus = info.getReplyStatus();
  575. if( replyStatus == info.UNINITIALIZED ) {
  576. invokeClientPIEndingPoint(
  577. ReplyMessage.SYSTEM_EXCEPTION,
  578. new UNKNOWN( "Problem between _request and _invoke.",
  579. MinorCodes.UNKNOWN_REQUEST_INVOKE,
  580. CompletionStatus.COMPLETED_MAYBE ) );
  581. }
  582. // Decrement entry count, and if it is zero, pop it from the stack.
  583. info.decrementEntryCount();
  584. if( info.getEntryCount() == 0 ) {
  585. RequestInfoStack infoStack =
  586. (RequestInfoStack)threadLocalClientRequestInfoStack.get();
  587. infoStack.pop();
  588. }
  589. }
  590. /**
  591. * Overridden from corba.ORB.
  592. * Notifies PI of the information for client-side interceptors.
  593. * PI will use this information as a source of information for the
  594. * ClientRequestInfo object.
  595. */
  596. final protected void setClientPIInfo( Connection connection,
  597. ClientDelegate delegate,
  598. IOR effectiveTarget,
  599. IIOPProfile profile,
  600. int requestId,
  601. String opName,
  602. boolean isOneWay,
  603. ServiceContexts svc )
  604. {
  605. if( !hasClientInterceptors ) return;
  606. if( !isClientPIEnabledForThisThread() ) return;
  607. peekClientRequestInfoImplStack().setInfo(
  608. connection, delegate, effectiveTarget, profile,
  609. requestId, opName, isOneWay, svc );
  610. }
  611. /**
  612. * Overridden from corba.ORB.
  613. * Notifies PI of additional information for client-side interceptors.
  614. * PI will use this information as a source of information for the
  615. * ClientRequestInfo object.
  616. */
  617. final protected void setClientPIInfo( ClientResponse response ) {
  618. if( !hasClientInterceptors ) return;
  619. if( !isClientPIEnabledForThisThread() ) return;
  620. peekClientRequestInfoImplStack().setInfo( response );
  621. }
  622. /**
  623. * Overridden from corba.ORB.
  624. * Notifies PI of additional information for client-side
  625. * interceptors. PI will use this information as a source of information
  626. * for the ClientRequestInfo object.
  627. */
  628. final protected void setClientPIInfo( RequestImpl requestImpl ) {
  629. if( !hasClientInterceptors ) return;
  630. if( !isClientPIEnabledForThisThread() ) return;
  631. peekClientRequestInfoImplStack().setDIIRequest( requestImpl );
  632. }
  633. final protected void sendCancelRequestIfFinalFragmentNotSent()
  634. {
  635. // The stack only has something in it if interceptors are registered.
  636. if( !hasClientInterceptors ) return;
  637. if( !isClientPIEnabledForThisThread() ) return;
  638. ClientRequestInfoImpl info = peekClientRequestInfoImplStack();
  639. int requestID = info.request_id();
  640. IIOPConnection connection = (IIOPConnection) info.connection();
  641. IIOPOutputStream existingOutputStream = null;
  642. if (connection != null) {
  643. // If it is a colocated request the connection will be null.
  644. // We do not (and cannot) fragment on colocated requests.
  645. existingOutputStream =
  646. connection.getIdToFragmentedOutputStreamEntry(requestID);
  647. if (existingOutputStream != null) {
  648. try {
  649. connection.sendCancelRequestWithLock(
  650. existingOutputStream.getMessage().getGIOPVersion(),
  651. requestID);
  652. } catch (IOException e) {
  653. // REVISIT: put in logging here.
  654. // REVISIT: we could attempt to send a final incomplete
  655. // fragment in this case.
  656. throw new COMM_FAILURE(
  657. e.getClass().getName(),
  658. MinorCodes.IOEXCEPTION_DURING_CANCEL_REQUEST,
  659. CompletionStatus.COMPLETED_MAYBE);
  660. } finally {
  661. connection
  662. .removeIdToFragmentedOutputStreamEntry(requestID);
  663. // Since we canceled the request we remove the out
  664. // call descriptor too, since the client thread will never
  665. // be waiting for a reply.
  666. connection.removeOutCallDescriptor(requestID);
  667. }
  668. }
  669. }
  670. }
  671. /*
  672. *****************
  673. * Server PI hooks
  674. *****************/
  675. /**
  676. * Overridden from corba.ORB.
  677. * Called when the appropriate server starting interception point is
  678. * to be invoked for all appropriate server-side request interceptors.
  679. */
  680. final protected void invokeServerPIStartingPoint()
  681. throws InternalRuntimeForwardRequest
  682. {
  683. if( !hasServerInterceptors ) return;
  684. ServerRequestInfoImpl info = peekServerRequestInfoImplStack();
  685. interceptorInvoker.invokeServerInterceptorStartingPoint( info );
  686. // Handle SystemException or ForwardRequest:
  687. serverPIHandleExceptions( info );
  688. }
  689. /**
  690. * Overridden from corba.ORB.
  691. * Called when the appropriate server intermediate interception point is
  692. * to be invoked for all appropriate server-side request interceptors.
  693. */
  694. final protected void invokeServerPIIntermediatePoint()
  695. throws InternalRuntimeForwardRequest
  696. {
  697. if( !hasServerInterceptors ) return;
  698. ServerRequestInfoImpl info = peekServerRequestInfoImplStack();
  699. interceptorInvoker.invokeServerInterceptorIntermediatePoint( info );
  700. // Clear servant from info object so that the user has control over
  701. // its lifetime:
  702. info.releaseServant();
  703. // Handle SystemException or ForwardRequest:
  704. serverPIHandleExceptions( info );
  705. }
  706. /**
  707. * Overridden from corba.ORB.
  708. * Called when the appropriate server ending interception point is
  709. * to be invoked for all appropriate server-side request interceptors.
  710. */
  711. final protected void invokeServerPIEndingPoint( ReplyMessage replyMessage )
  712. throws InternalRuntimeForwardRequest
  713. {
  714. if( !hasServerInterceptors ) return;
  715. ServerRequestInfoImpl info = peekServerRequestInfoImplStack();
  716. // REVISIT: This needs to be done "early" for the following workaround.
  717. info.setReplyMessage( replyMessage );
  718. // REVISIT: This was done inside of invokeServerInterceptorEndingPoint
  719. // but needs to be here for now. See comment in that method for why.
  720. info.setCurrentExecutionPoint( info.EXECUTION_POINT_ENDING );
  721. // It is possible we might have entered this method more than
  722. // once (e.g. if an ending point threw a SystemException, then
  723. // a new ServerResponseImpl is created).
  724. if( !info.getAlreadyExecuted() ) {
  725. int replyStatus = replyMessage.getReplyStatus();
  726. // Translate ReplyMessage.replyStatus into PI replyStatus:
  727. // Note: this is also an assertion to make sure a valid
  728. // replyStatus is passed in (IndexOutOfBoundsException will be
  729. // thrown otherwise)
  730. short piReplyStatus =
  731. REPLY_MESSAGE_TO_PI_REPLY_STATUS[replyStatus];
  732. // Make forwarded IOR available to interceptors, if applicable:
  733. if( ( piReplyStatus == LOCATION_FORWARD.value ) ||
  734. ( piReplyStatus == TRANSPORT_RETRY.value ) )
  735. {
  736. info.setForwardRequest( replyMessage.getIOR() );
  737. }
  738. // REVISIT: Do early above for now.
  739. // Make reply message available to interceptors:
  740. //info.setReplyMessage( replyMessage );
  741. // Remember exception so we can tell if an interceptor changed it.
  742. Exception prevException = info.getException();
  743. // _REVISIT_ We do not have access to the User Exception at
  744. // this point, so treat it as an UNKNOWN for now.
  745. // Note that if this is a DSI call, we do have the user exception.
  746. if( !info.isDynamic() &&
  747. (piReplyStatus == USER_EXCEPTION.value) )
  748. {
  749. info.setException(
  750. new UNKNOWN( "Cannot access user exception",
  751. MinorCodes.UNKNOWN_USER_EXCEPTION,
  752. CompletionStatus.COMPLETED_MAYBE ) );
  753. }
  754. // Invoke the ending interception points:
  755. info.setReplyStatus( piReplyStatus );
  756. interceptorInvoker.invokeServerInterceptorEndingPoint( info );
  757. short newPIReplyStatus = info.getReplyStatus();
  758. Exception newException = info.getException();
  759. // Check reply status. If an interceptor threw a SystemException
  760. // and it is different than the one that we came in with,
  761. // rethrow it so the proper response can be constructed:
  762. if( ( newPIReplyStatus == SYSTEM_EXCEPTION.value ) &&
  763. ( newException != prevException ) )
  764. {
  765. throw (SystemException)newException;
  766. }
  767. // If we are to forward the location:
  768. if( newPIReplyStatus == LOCATION_FORWARD.value ) {
  769. if( piReplyStatus != LOCATION_FORWARD.value ) {
  770. // Treat a ForwardRequest as an
  771. // InternalRuntimeForwardRequest.
  772. ForwardRequest newForwardRequest =
  773. info.getForwardRequestException();
  774. throw new InternalRuntimeForwardRequest(
  775. newForwardRequest.forward );
  776. }
  777. else if( info.isForwardRequestRaisedInEnding() ) {
  778. // Treat a ForwardRequest by changing the IOR.
  779. replyMessage.setIOR( info.getForwardRequestIOR() );
  780. }
  781. }
  782. }
  783. }
  784. /**
  785. * Overridden from corba.ORB.
  786. * Notifies PI of additional information required for ServerRequestInfo.
  787. */
  788. final protected void setServerPIInfo( Exception exception ) {
  789. if( !hasServerInterceptors ) return;
  790. ServerRequestInfoImpl info = peekServerRequestInfoImplStack();
  791. info.setException( exception );
  792. }
  793. /**
  794. * Overridden from corba.ORB.
  795. * Notifies PI of additional information required for ServerRequestInfo.
  796. */
  797. final protected void setServerPIInfo( NVList arguments )
  798. {
  799. if( !hasServerInterceptors ) return;
  800. ServerRequestInfoImpl info = peekServerRequestInfoImplStack();
  801. info.setDSIArguments( arguments );
  802. }
  803. /**
  804. * Overridden from corba.ORB.
  805. * Notifies PI of additional information required for ServerRequestInfo.
  806. */
  807. final protected void setServerPIExceptionInfo( Any exception )
  808. {
  809. if( !hasServerInterceptors ) return;
  810. ServerRequestInfoImpl info = peekServerRequestInfoImplStack();
  811. info.setDSIException( exception );
  812. }
  813. /**
  814. * Overridden from corba.ORB.
  815. * Notifies PI of additional information required for ServerRequestInfo.
  816. */
  817. final protected void setServerPIInfo( Any result )
  818. {
  819. if( !hasServerInterceptors ) return;
  820. ServerRequestInfoImpl info = peekServerRequestInfoImplStack();
  821. info.setDSIResult( result );
  822. }
  823. /**
  824. * Overridden from corba.ORB.
  825. * Notifies PI to start a new server request and set initial
  826. * information for server-side interceptors.
  827. * PI will use this information as a source of information for the
  828. * ServerRequestInfo object.
  829. */
  830. final protected void initializeServerPIInfo( ServerRequest request,
  831. java.lang.Object poaimpl, byte[] objectId, byte[] adapterId )
  832. {
  833. if( !hasServerInterceptors ) return;
  834. RequestInfoStack infoStack =
  835. (RequestInfoStack)threadLocalServerRequestInfoStack.get();
  836. ServerRequestInfoImpl info = new ServerRequestInfoImpl( this );
  837. infoStack.push( info );
  838. // Notify request object that once response is constructed, make
  839. // sure we execute ending points.
  840. request.setExecutePIInResponseConstructor( true );
  841. info.setInfo( request, (POAImpl)poaimpl, objectId, adapterId );
  842. }
  843. /**
  844. * Notifies PI of additional information reqired for ServerRequestInfo.
  845. */
  846. final protected void setServerPIInfo( java.lang.Object servant,
  847. String targetMostDerivedInterface )
  848. {
  849. if( !hasServerInterceptors ) return;
  850. ServerRequestInfoImpl info = peekServerRequestInfoImplStack();
  851. info.setInfo( servant, targetMostDerivedInterface );
  852. }
  853. /**
  854. * Overridden from corba.ORB.
  855. * See description in corba.ORB.
  856. */
  857. final protected void cleanupServerPIRequest() {
  858. if( !hasServerInterceptors ) return;
  859. RequestInfoStack infoStack =
  860. (RequestInfoStack)threadLocalServerRequestInfoStack.get();
  861. infoStack.pop();
  862. }
  863. /*
  864. **********************************************************************
  865. * The following methods are private utility methods for the PIORB's
  866. * use.
  867. ************************************************************************/
  868. /**
  869. * Handles exceptions for the starting and intermediate points for
  870. * server request interceptors. This is common code that has been
  871. * factored out into this utility method.
  872. * <p>
  873. * This method will NOT work for ending points.
  874. */
  875. private void serverPIHandleExceptions( ServerRequestInfoImpl info )
  876. throws InternalRuntimeForwardRequest
  877. {
  878. int endingPointCall = info.getEndingPointCall();
  879. if(endingPointCall == ServerRequestInfoImpl.CALL_SEND_EXCEPTION) {
  880. // If a system exception was thrown, throw it to caller:
  881. throw (SystemException)info.getException();
  882. }
  883. else if( (endingPointCall == ServerRequestInfoImpl.CALL_SEND_OTHER) &&
  884. (info.getForwardRequestException() != null) )
  885. {
  886. // If an interceptor throws a forward request, convert it
  887. // into an InternalRuntimeForwardRequest for easier handling:
  888. ForwardRequest forwardRequest = info.getForwardRequestException();
  889. throw new InternalRuntimeForwardRequest(
  890. forwardRequest.forward );
  891. }
  892. }
  893. /**
  894. * Utility method to convert a PI reply status short to a ReplyMessage
  895. * constant. This is a reverse lookup on the table defined in
  896. * REPLY_MESSAGE_TO_PI_REPLY_STATUS. The reverse lookup need not be
  897. * performed as quickly since it is only executed in exception
  898. * conditions.
  899. */
  900. private int convertPIReplyStatusToReplyMessage( short replyStatus ) {
  901. int result = 0;
  902. for( int i = 0; i < REPLY_MESSAGE_TO_PI_REPLY_STATUS.length; i++ ) {
  903. if( REPLY_MESSAGE_TO_PI_REPLY_STATUS[i] == replyStatus ) {
  904. result = i;
  905. break;
  906. }
  907. }
  908. return result;
  909. }
  910. /**
  911. * Convenience method to get the ClientRequestInfoImpl object off the
  912. * top of the ThreadLocal stack. Throws an INTERNAL exception if
  913. * the Info stack is empty.
  914. */
  915. private ClientRequestInfoImpl peekClientRequestInfoImplStack() {
  916. RequestInfoStack infoStack =
  917. (RequestInfoStack)threadLocalClientRequestInfoStack.get();
  918. ClientRequestInfoImpl info = null;
  919. if( !infoStack.empty() ) {
  920. info = (ClientRequestInfoImpl)infoStack.peek();
  921. }
  922. else {
  923. throw new INTERNAL(
  924. "Assertion failed: Client Request Info Stack is null.",
  925. MinorCodes.CLIENT_INFO_STACK_NULL,
  926. CompletionStatus.COMPLETED_NO );
  927. }
  928. return info;
  929. }
  930. /**
  931. * Convenience method to get the ServerRequestInfoImpl object off the
  932. * top of the ThreadLocal stack. Returns null if there are none.
  933. */
  934. private ServerRequestInfoImpl peekServerRequestInfoImplStack() {
  935. RequestInfoStack infoStack =
  936. (RequestInfoStack)threadLocalServerRequestInfoStack.get();
  937. ServerRequestInfoImpl info = null;
  938. if( !infoStack.empty() ) {
  939. info = (ServerRequestInfoImpl)infoStack.peek();
  940. }
  941. else {
  942. throw new INTERNAL(
  943. "Assertion failed: Server Request Info Stack is null.",
  944. MinorCodes.SERVER_INFO_STACK_NULL,
  945. CompletionStatus.COMPLETED_NO );
  946. }
  947. return info;
  948. }
  949. /**
  950. * Convenience method to determine whether Client PI is enabled
  951. * for requests on this thread.
  952. */
  953. private boolean isClientPIEnabledForThisThread() {
  954. RequestInfoStack infoStack =
  955. (RequestInfoStack)threadLocalClientRequestInfoStack.get();
  956. return (infoStack.disableCount == 0);
  957. }
  958. /**
  959. * Call pre_init on all ORB initializers
  960. */
  961. private void preInitORBInitializers( ORBInitInfoImpl info ) {
  962. // Inform ORBInitInfo we are in pre_init stage
  963. info.setStage( ORBInitInfoImpl.STAGE_PRE_INIT );
  964. // Step through each initializer instantiation and call its
  965. // pre_init. Ignore any exceptions.
  966. for( int i = 0; i < orbInitializers.length; i++ ) {
  967. ORBInitializer init = orbInitializers[i];
  968. if( init != null ) {
  969. try {
  970. init.pre_init( info );
  971. }
  972. catch( Exception e ) {
  973. // As per orbos/99-12-02, section 9.3.1.2, "If there are
  974. // any exceptions, the ORB shall ignore them and proceed."
  975. }
  976. }
  977. }
  978. }
  979. /**
  980. * Call post_init on all ORB initializers
  981. */
  982. private void postInitORBInitializers( ORBInitInfoImpl info ) {
  983. // Inform ORBInitInfo we are in post_init stage
  984. info.setStage( ORBInitInfoImpl.STAGE_POST_INIT );
  985. // Step through each initializer instantiation and call its post_init.
  986. // Ignore any exceptions.
  987. for( int i = 0; i < orbInitializers.length; i++ ) {
  988. ORBInitializer init = orbInitializers[i];
  989. if( init != null ) {
  990. try {
  991. init.post_init( info );
  992. }
  993. catch( Exception e ) {
  994. // As per orbos/99-12-02, section 9.3.1.2, "If there are
  995. // any exceptions, the ORB shall ignore them and proceed."
  996. }
  997. }
  998. }
  999. }
  1000. /**
  1001. * Creates the ORBInitInfo object to be passed to ORB intializers'
  1002. * pre_init and post_init methods
  1003. */
  1004. private ORBInitInfoImpl createORBInitInfo() {
  1005. ORBInitInfoImpl result = null;
  1006. // arguments comes from set_parameters. May be null.
  1007. // _REVISIT_ The spec does not specify which ID this is to be.
  1008. // We currently get this from the corba.ORB, which reads it from
  1009. // the ORB_ID_PROPERTY property.
  1010. String orbId = this.orbId;
  1011. // codecFactory comes from constructor of PIORB.
  1012. result = new ORBInitInfoImpl( this, arguments, orbId, codecFactory );
  1013. return result;
  1014. }
  1015. /**
  1016. * Called by ORBInitInfo when an interceptor needs to be registered.
  1017. * The type is one of:
  1018. * <ul>
  1019. * <li>INTERCEPTOR_TYPE_CLIENT - ClientRequestInterceptor
  1020. * <li>INTERCEPTOR_TYPE_SERVER - ServerRequestInterceptor
  1021. * <li>INTERCEPTOR_TYPE_IOR - IORInterceptor
  1022. * </ul>
  1023. *
  1024. * @exception DuplicateName Thrown if an interceptor of the given
  1025. * name already exists for the given type.
  1026. */
  1027. void register_interceptor( Interceptor interceptor, int type )
  1028. throws DuplicateName
  1029. {
  1030. // We will assume interceptor is not null, since it is called
  1031. // internally.
  1032. if( (type >= InterceptorList.NUM_INTERCEPTOR_TYPES) || (type < 0) ) {
  1033. throw new BAD_PARAM( "Interceptor type out of range: " + type );
  1034. }
  1035. String interceptorName = interceptor.name();
  1036. if( interceptorName == null ) {
  1037. throw new BAD_PARAM(
  1038. "Interceptor's name is null. " +
  1039. "Use empty string for anonymous interceptors." );
  1040. }
  1041. // Register with interceptor list:
  1042. interceptorList.register_interceptor( interceptor, type );
  1043. }
  1044. /**
  1045. * return the PICurrent instance created during ORB initialization.
  1046. */
  1047. PICurrent getPICurrent( ) {
  1048. return current;
  1049. }
  1050. /**
  1051. * Called when an invalid null parameter was passed. Throws a
  1052. * BAD_PARAM with a minor code of 1
  1053. */
  1054. private void nullParam()
  1055. throws BAD_PARAM
  1056. {
  1057. throw new BAD_PARAM(
  1058. com.sun.corba.se.internal.orbutil.MinorCodes.NULL_PARAM,
  1059. CompletionStatus.COMPLETED_NO );
  1060. }
  1061. /** This is the implementation of standard API defined in org.omg.CORBA.ORB
  1062. * class. This method finds the Policy Factory for the given Policy Type
  1063. * and instantiates the Policy object from the Factory. It will throw
  1064. * PolicyError exception, If the PolicyFactory for the given type is
  1065. * not registered.
  1066. * _REVISIT_, Once Policy Framework work is completed, Reorganize
  1067. * this method to com.sun.corba.se.internal.core.ORB.
  1068. */
  1069. public org.omg.CORBA.Policy create_policy(int type, org.omg.CORBA.Any val)
  1070. throws org.omg.CORBA.PolicyError
  1071. {
  1072. checkShutdownState();
  1073. if( val == null ) {
  1074. nullParam( );
  1075. }
  1076. if( policyFactoryTable == null ) {
  1077. throw new org.omg.CORBA.PolicyError(
  1078. "There is no PolicyFactory Registered for type " + type,
  1079. BAD_POLICY.value );
  1080. }
  1081. PolicyFactory factory = (PolicyFactory)policyFactoryTable.get(
  1082. new Integer(type) );
  1083. if( factory == null ) {
  1084. throw new org.omg.CORBA.PolicyError(
  1085. " Could Not Find PolicyFactory for the Type " + type,
  1086. BAD_POLICY.value);
  1087. }
  1088. org.omg.CORBA.Policy policy = factory.create_policy( type, val );
  1089. return policy;
  1090. }
  1091. /** This method registers the Policy Factory in the policyFactoryTable,
  1092. * which is a HashMap. This method is made package private, because
  1093. * it is used internally by the Interceptors.
  1094. */
  1095. void registerPolicyFactory( int type, PolicyFactory factory ) {
  1096. if( policyFactoryTable == null ) {
  1097. policyFactoryTable = new HashMap();
  1098. }
  1099. Integer key = new Integer( type );
  1100. java.lang.Object val = policyFactoryTable.get( key );
  1101. if( val == null ) {
  1102. policyFactoryTable.put( key, factory );
  1103. }
  1104. else {
  1105. throw new BAD_INV_ORDER(
  1106. "Failure in registerPolicyFactory, Trying to register a " +
  1107. "PolicyFactory with the Type " + type + " which is already " +
  1108. " registered", MinorCodes.POLICY_FACTORY_REG_FAILED,
  1109. CompletionStatus.COMPLETED_NO );
  1110. }
  1111. }
  1112. synchronized int allocateServerRequestId ()
  1113. {
  1114. return serverRequestIdCounter++;
  1115. }
  1116. }