1 /*
   2  * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 package com.sun.corba.se.impl.interceptors;
  26 
  27 import java.util.*;
  28 import java.io.IOException;
  29 
  30 import org.omg.CORBA.Any;
  31 import org.omg.CORBA.BAD_PARAM;
  32 import org.omg.CORBA.BAD_POLICY;
  33 import org.omg.CORBA.BAD_INV_ORDER;
  34 import org.omg.CORBA.COMM_FAILURE;
  35 import org.omg.CORBA.CompletionStatus;
  36 import org.omg.CORBA.INTERNAL;
  37 import org.omg.CORBA.NVList;
  38 import org.omg.CORBA.OBJECT_NOT_EXIST;
  39 import org.omg.CORBA.ORBPackage.InvalidName;
  40 import org.omg.CORBA.SystemException;
  41 import org.omg.CORBA.UserException;
  42 import org.omg.CORBA.UNKNOWN;
  43 
  44 import org.omg.CORBA.portable.ApplicationException;
  45 import org.omg.CORBA.portable.RemarshalException;
  46 
  47 import org.omg.IOP.CodecFactory;
  48 
  49 import org.omg.PortableInterceptor.ForwardRequest;
  50 import org.omg.PortableInterceptor.Current;
  51 import org.omg.PortableInterceptor.Interceptor;
  52 import org.omg.PortableInterceptor.LOCATION_FORWARD;
  53 import org.omg.PortableInterceptor.ORBInitializer;
  54 import org.omg.PortableInterceptor.ORBInitInfo;
  55 import org.omg.PortableInterceptor.ORBInitInfoPackage.DuplicateName;
  56 import org.omg.PortableInterceptor.SUCCESSFUL;
  57 import org.omg.PortableInterceptor.SYSTEM_EXCEPTION;
  58 import org.omg.PortableInterceptor.TRANSPORT_RETRY;
  59 import org.omg.PortableInterceptor.USER_EXCEPTION;
  60 import org.omg.PortableInterceptor.PolicyFactory;
  61 import org.omg.PortableInterceptor.ObjectReferenceTemplate;
  62 
  63 import com.sun.corba.se.pept.encoding.OutputObject;
  64 
  65 import com.sun.corba.se.spi.ior.IOR;
  66 import com.sun.corba.se.spi.ior.ObjectKeyTemplate;
  67 import com.sun.corba.se.spi.oa.ObjectAdapter;
  68 import com.sun.corba.se.spi.orb.ORB;
  69 import com.sun.corba.se.spi.orbutil.closure.ClosureFactory;
  70 import com.sun.corba.se.spi.protocol.CorbaMessageMediator;
  71 import com.sun.corba.se.spi.protocol.ForwardException;
  72 import com.sun.corba.se.spi.protocol.PIHandler;
  73 import com.sun.corba.se.spi.protocol.RetryType;
  74 import com.sun.corba.se.spi.logging.CORBALogDomains;
  75 
  76 import com.sun.corba.se.impl.logging.InterceptorsSystemException;
  77 import com.sun.corba.se.impl.logging.ORBUtilSystemException;
  78 import com.sun.corba.se.impl.logging.OMGSystemException;
  79 import com.sun.corba.se.impl.corba.RequestImpl;
  80 import com.sun.corba.se.impl.orbutil.ORBConstants;
  81 import com.sun.corba.se.impl.orbutil.ORBUtility;
  82 import com.sun.corba.se.impl.orbutil.StackImpl;
  83 import com.sun.corba.se.impl.protocol.giopmsgheaders.ReplyMessage;
  84 
  85 /**
  86  * Provides portable interceptor functionality.
  87  */
  88 public class PIHandlerImpl implements PIHandler
  89 {
  90     // REVISIT - delete these after framework merging.
  91     boolean printPushPopEnabled = false;
  92     int pushLevel = 0;
  93     private void printPush()
  94     {
  95         if (! printPushPopEnabled) return;
  96         printSpaces(pushLevel);
  97         pushLevel++;
  98         System.out.println("PUSH");
  99     }
 100     private void printPop()
 101     {
 102         if (! printPushPopEnabled) return;
 103         pushLevel--;
 104         printSpaces(pushLevel);
 105         System.out.println("POP");
 106     }
 107     private void printSpaces(int n)
 108     {
 109         for (int i = 0; i < n; i++) {
 110             System.out.print(" ");
 111         }
 112     }
 113 
 114     private ORB orb;
 115     InterceptorsSystemException wrapper;
 116     ORBUtilSystemException orbutilWrapper;
 117     OMGSystemException omgWrapper;
 118 
 119     // A unique id used in ServerRequestInfo.
 120     // This does not correspond to the GIOP request id.
 121     private int serverRequestIdCounter = 0;
 122 
 123     // Stores the codec factory for producing codecs
 124     CodecFactory codecFactory = null;
 125 
 126     // The arguments passed to the application's main method.  May be null.
 127     // This is used for ORBInitializers and set from set_parameters.
 128     String[] arguments = null;
 129 
 130     // The list of portable interceptors, organized by type:
 131     private InterceptorList interceptorList;
 132 
 133     // Cached information for optimization - do we have any interceptors
 134     // registered of the given types?  Set during ORB initialization.
 135     private boolean hasIORInterceptors;
 136     private boolean hasClientInterceptors;  // temp always true
 137     private boolean hasServerInterceptors;
 138 
 139     // The class responsible for invoking interceptors
 140     private InterceptorInvoker interceptorInvoker;
 141 
 142     // There will be one PICurrent instantiated for every ORB.
 143     private PICurrent current;
 144 
 145     // This table contains a list of PolicyFactories registered using
 146     // ORBInitInfo.registerPolicyFactory() method.
 147     // Key for the table is PolicyType which is an Integer
 148     // Value is PolicyFactory.
 149     private HashMap policyFactoryTable;
 150 
 151     // Table to convert from a ReplyMessage.? to a PI replyStatus short.
 152     // Note that this table relies on the order and constants of
 153     // ReplyMessage not to change.
 154     private final static short REPLY_MESSAGE_TO_PI_REPLY_STATUS[] = {
 155         SUCCESSFUL.value,       // = ReplyMessage.NO_EXCEPTION
 156         USER_EXCEPTION.value,   // = ReplyMessage.USER_EXCEPTION
 157         SYSTEM_EXCEPTION.value, // = ReplyMessage.SYSTEM_EXCEPTION
 158         LOCATION_FORWARD.value, // = ReplyMessage.LOCATION_FORWARD
 159         LOCATION_FORWARD.value, // = ReplyMessage.LOCATION_FORWARD_PERM
 160         TRANSPORT_RETRY.value   // = ReplyMessage.NEEDS_ADDRESSING_MODE
 161     };
 162 
 163     // ThreadLocal containing a stack to store client request info objects
 164     // and a disable count.
 165     private ThreadLocal threadLocalClientRequestInfoStack =
 166         new ThreadLocal() {
 167             protected Object initialValue() {
 168                 return new RequestInfoStack();
 169             }
 170         };
 171 
 172     // ThreadLocal containing the current server request info object.
 173     private ThreadLocal threadLocalServerRequestInfoStack =
 174         new ThreadLocal() {
 175             protected Object initialValue() {
 176                 return new RequestInfoStack();
 177             }
 178         };
 179 
 180     public void close() {
 181         orb = null;
 182         wrapper = null;
 183         orbutilWrapper = null;
 184         omgWrapper = null;
 185         codecFactory = null;
 186         arguments = null;
 187         interceptorList = null;
 188         interceptorInvoker = null;
 189         current = null;
 190         policyFactoryTable = null;
 191         threadLocalClientRequestInfoStack = null;
 192         threadLocalServerRequestInfoStack = null;
 193     }
 194 
 195     // Class to contain all ThreadLocal data for ClientRequestInfo
 196     // maintenance.
 197     //
 198     // We use an ArrayList instead since it is not thread-safe.
 199     // RequestInfoStack is used quite frequently.
 200     private final class RequestInfoStack extends Stack {
 201         // Number of times a request has been made to disable interceptors.
 202         // When this reaches 0, interception hooks are disabled.  Any higher
 203         // value indicates they are enabled.
 204         // NOTE: The is only currently used on the client side.
 205         public int disableCount = 0;
 206     }
 207 
 208     public PIHandlerImpl( ORB orb, String[] args ) {
 209         this.orb = orb ;
 210         wrapper = InterceptorsSystemException.get( orb,
 211             CORBALogDomains.RPC_PROTOCOL ) ;
 212         orbutilWrapper = ORBUtilSystemException.get( orb,
 213             CORBALogDomains.RPC_PROTOCOL ) ;
 214         omgWrapper = OMGSystemException.get( orb,
 215             CORBALogDomains.RPC_PROTOCOL ) ;
 216         arguments = args ;
 217 
 218         // Create codec factory:
 219         codecFactory = new CodecFactoryImpl( orb );
 220 
 221         // Create new interceptor list:
 222         interceptorList = new InterceptorList( wrapper );
 223 
 224         // Create a new PICurrent.
 225         current = new PICurrent( orb );
 226 
 227         // Create new interceptor invoker, initially disabled:
 228         interceptorInvoker = new InterceptorInvoker( orb, interceptorList,
 229                                                      current );
 230 
 231         // Register the PI current and Codec factory objects
 232         orb.getLocalResolver().register( ORBConstants.PI_CURRENT_NAME,
 233             ClosureFactory.makeConstant( current ) ) ;
 234         orb.getLocalResolver().register( ORBConstants.CODEC_FACTORY_NAME,
 235             ClosureFactory.makeConstant( codecFactory ) ) ;
 236     }
 237 
 238     public void initialize() {
 239         // If we have any orb initializers, make use of them:
 240         if( orb.getORBData().getORBInitializers() != null ) {
 241             // Create the ORBInitInfo object to pass to ORB intializers:
 242             ORBInitInfoImpl orbInitInfo = createORBInitInfo();
 243 
 244             // Make sure get_slot and set_slot are not called from within
 245             // ORB initializers:
 246             current.setORBInitializing( true );
 247 
 248             // Call pre_init on all ORB initializers:
 249             preInitORBInitializers( orbInitInfo );
 250 
 251             // Call post_init on all ORB initializers:
 252             postInitORBInitializers( orbInitInfo );
 253 
 254             // Proprietary: sort interceptors:
 255             interceptorList.sortInterceptors();
 256 
 257             // Re-enable get_slot and set_slot to be called from within
 258             // ORB initializers:
 259             current.setORBInitializing( false );
 260 
 261             // Ensure nobody makes any more calls on this object.
 262             orbInitInfo.setStage( ORBInitInfoImpl.STAGE_CLOSED );
 263 
 264             // Set cached flags indicating whether we have interceptors
 265             // registered of a given type.
 266             hasIORInterceptors = interceptorList.hasInterceptorsOfType(
 267                 InterceptorList.INTERCEPTOR_TYPE_IOR );
 268             // XXX This must always be true, so that using the new generic
 269             // RPC framework can pass info between the PI stack and the
 270             // framework invocation stack.  Temporary until Harold fixes
 271             // this.  Note that this must never be true until after the
 272             // ORBInitializer instances complete executing.
 273             //hasClientInterceptors = interceptorList.hasInterceptorsOfType(
 274                 //InterceptorList.INTERCEPTOR_TYPE_CLIENT );
 275             hasClientInterceptors = true;
 276             hasServerInterceptors = interceptorList.hasInterceptorsOfType(
 277                 InterceptorList.INTERCEPTOR_TYPE_SERVER );
 278 
 279             // Enable interceptor invoker (not necessary if no interceptors
 280             // are registered).  This should be the last stage of ORB
 281             // initialization.
 282             interceptorInvoker.setEnabled( true );
 283         }
 284     }
 285 
 286     /**
 287      *  ptc/00-08-06 p 205: "When an application calls ORB::destroy, the ORB
 288      *  1) waits for all requests in progress to complete
 289      *  2) calls the Interceptor::destroy operation for each interceptor
 290      *  3) completes destruction of the ORB"
 291      *
 292      * This must be called at the end of ORB.destroy.  Note that this is not
 293      * part of the PIHandler interface, since ORBImpl implements the ORB interface.
 294      */
 295     public void destroyInterceptors() {
 296         interceptorList.destroyAll();
 297     }
 298 
 299     public void objectAdapterCreated( ObjectAdapter oa )
 300     {
 301         if (!hasIORInterceptors)
 302             return ;
 303 
 304         interceptorInvoker.objectAdapterCreated( oa ) ;
 305     }
 306 
 307     public void adapterManagerStateChanged( int managerId,
 308         short newState )
 309     {
 310         if (!hasIORInterceptors)
 311             return ;
 312 
 313         interceptorInvoker.adapterManagerStateChanged( managerId, newState ) ;
 314     }
 315 
 316     public void adapterStateChanged( ObjectReferenceTemplate[]
 317         templates, short newState )
 318     {
 319         if (!hasIORInterceptors)
 320             return ;
 321 
 322         interceptorInvoker.adapterStateChanged( templates, newState ) ;
 323     }
 324 
 325     /*
 326      *****************
 327      * Client PI hooks
 328      *****************/
 329 
 330     public void disableInterceptorsThisThread() {
 331         if( !hasClientInterceptors ) return;
 332 
 333         RequestInfoStack infoStack =
 334             (RequestInfoStack)threadLocalClientRequestInfoStack.get();
 335         infoStack.disableCount++;
 336     }
 337 
 338     public void enableInterceptorsThisThread() {
 339         if( !hasClientInterceptors ) return;
 340 
 341         RequestInfoStack infoStack =
 342             (RequestInfoStack)threadLocalClientRequestInfoStack.get();
 343         infoStack.disableCount--;
 344     }
 345 
 346     public void invokeClientPIStartingPoint()
 347         throws RemarshalException
 348     {
 349         if( !hasClientInterceptors ) return;
 350         if( !isClientPIEnabledForThisThread() ) return;
 351 
 352         // Invoke the starting interception points and record exception
 353         // and reply status info in the info object:
 354         ClientRequestInfoImpl info = peekClientRequestInfoImplStack();
 355         interceptorInvoker.invokeClientInterceptorStartingPoint( info );
 356 
 357         // Check reply status.  If we will not have another chance later
 358         // to invoke the client ending points, do it now.
 359         short replyStatus = info.getReplyStatus();
 360         if( (replyStatus == SYSTEM_EXCEPTION.value) ||
 361             (replyStatus == LOCATION_FORWARD.value) )
 362         {
 363             // Note: Transport retry cannot happen here since this happens
 364             // before the request hits the wire.
 365 
 366             Exception exception = invokeClientPIEndingPoint(
 367                 convertPIReplyStatusToReplyMessage( replyStatus ),
 368                 info.getException() );
 369             if( exception == null ) {
 370                 // Do not throw anything.  Otherwise, it must be a
 371                 // SystemException, UserException or RemarshalException.
 372             } if( exception instanceof SystemException ) {
 373                 throw (SystemException)exception;
 374             } else if( exception instanceof RemarshalException ) {
 375                 throw (RemarshalException)exception;
 376             } else if( (exception instanceof UserException) ||
 377                      (exception instanceof ApplicationException) ) {
 378                 // It should not be possible for an interceptor to throw
 379                 // a UserException.  By asserting instead of throwing the
 380                 // UserException, we need not declare anything but
 381                 // RemarshalException in the throws clause.
 382                 throw wrapper.exceptionInvalid() ;
 383             }
 384         }
 385         else if( replyStatus != ClientRequestInfoImpl.UNINITIALIZED ) {
 386             throw wrapper.replyStatusNotInit() ;
 387         }
 388     }
 389 
 390     // Needed when an error forces a retry AFTER initiateClientPIRequest
 391     // but BEFORE invokeClientPIStartingPoint.
 392     public Exception makeCompletedClientRequest( int replyStatus,
 393         Exception exception ) {
 394 
 395         // 6763340
 396         return handleClientPIEndingPoint( replyStatus, exception, false ) ;
 397     }
 398 
 399     public Exception invokeClientPIEndingPoint( int replyStatus,
 400         Exception exception ) {
 401 
 402         // 6763340
 403         return handleClientPIEndingPoint( replyStatus, exception, true ) ;
 404     }
 405 
 406     public Exception handleClientPIEndingPoint(
 407         int replyStatus, Exception exception, boolean invokeEndingPoint ) {
 408         if( !hasClientInterceptors ) return exception;
 409         if( !isClientPIEnabledForThisThread() ) return exception;
 410 
 411         // Translate ReplyMessage.replyStatus into PI replyStatus:
 412         // Note: this is also an assertion to make sure a valid replyStatus
 413         // is passed in (IndexOutOfBoundsException will be thrown otherwise)
 414         short piReplyStatus = REPLY_MESSAGE_TO_PI_REPLY_STATUS[replyStatus];
 415 
 416         // Invoke the ending interception points and record exception
 417         // and reply status info in the info object:
 418         ClientRequestInfoImpl info = peekClientRequestInfoImplStack();
 419         info.setReplyStatus( piReplyStatus );
 420         info.setException( exception );
 421 
 422         if (invokeEndingPoint) {
 423             // 6763340
 424             interceptorInvoker.invokeClientInterceptorEndingPoint( info );
 425             piReplyStatus = info.getReplyStatus();
 426         }
 427 
 428         // Check reply status:
 429         if( (piReplyStatus == LOCATION_FORWARD.value) ||
 430             (piReplyStatus == TRANSPORT_RETRY.value) ) {
 431             // If this is a forward or a retry, reset and reuse
 432             // info object:
 433             info.reset();
 434 
 435             // fix for 6763340:
 436             if (invokeEndingPoint) {
 437                 info.setRetryRequest( RetryType.AFTER_RESPONSE ) ;
 438             } else {
 439                 info.setRetryRequest( RetryType.BEFORE_RESPONSE ) ;
 440             }
 441 
 442             // ... and return a RemarshalException so the orb internals know
 443             exception = new RemarshalException();
 444         } else if( (piReplyStatus == SYSTEM_EXCEPTION.value) ||
 445                  (piReplyStatus == USER_EXCEPTION.value) ) {
 446             exception = info.getException();
 447         }
 448 
 449         return exception;
 450     }
 451 
 452     public void initiateClientPIRequest( boolean diiRequest ) {
 453         if( !hasClientInterceptors ) return;
 454         if( !isClientPIEnabledForThisThread() ) return;
 455 
 456         // Get the most recent info object from the thread local
 457         // ClientRequestInfoImpl stack:
 458         RequestInfoStack infoStack =
 459             (RequestInfoStack)threadLocalClientRequestInfoStack.get();
 460         ClientRequestInfoImpl info = null;
 461 
 462         if (!infoStack.empty() ) {
 463             info = (ClientRequestInfoImpl)infoStack.peek();
 464         }
 465 
 466         if (!diiRequest && (info != null) && info.isDIIInitiate() ) {
 467             // In RequestImpl.doInvocation we already called
 468             // initiateClientPIRequest( true ), so ignore this initiate.
 469             info.setDIIInitiate( false );
 470         } else {
 471             // If there is no info object or if we are not retrying a request,
 472             // push a new ClientRequestInfoImpl on the stack:
 473 
 474             // 6763340: don't push unless this is not a retry
 475             if( (info == null) || !info.getRetryRequest().isRetry() ) {
 476                 info = new ClientRequestInfoImpl( orb );
 477                 infoStack.push( info );
 478                 printPush();
 479                 // Note: the entry count is automatically initialized to 0.
 480             }
 481 
 482             // Reset the retry request flag so that recursive calls will
 483             // push a new info object, and bump up entry count so we know
 484             // when to pop this info object:
 485             info.setRetryRequest( RetryType.NONE );
 486             info.incrementEntryCount();
 487 
 488             // KMC 6763340: I don't know why this wasn't set earlier,
 489             // but we do not want a retry to pick up the previous
 490             // reply status, so clear it here.  Most likely a new
 491             // info was pushed before, so that this was not a problem.
 492             info.setReplyStatus( RequestInfoImpl.UNINITIALIZED ) ;
 493 
 494             // If this is a DII request, make sure we ignore the next initiate.
 495             if( diiRequest ) {
 496                 info.setDIIInitiate( true );
 497             }
 498         }
 499     }
 500 
 501     public void cleanupClientPIRequest() {
 502         if( !hasClientInterceptors ) return;
 503         if( !isClientPIEnabledForThisThread() ) return;
 504 
 505         ClientRequestInfoImpl info = peekClientRequestInfoImplStack();
 506         RetryType rt = info.getRetryRequest() ;
 507 
 508         // fix for 6763340
 509         if (!rt.equals( RetryType.BEFORE_RESPONSE )) {
 510 
 511             // If the replyStatus has not yet been set, this is an indication
 512             // that the ORB threw an exception before we had a chance to
 513             // invoke the client interceptor ending points.
 514             //
 515             // _REVISIT_ We cannot handle any exceptions or ForwardRequests
 516             // flagged by the ending points here because there is no way
 517             // to gracefully handle this in any of the calling code.
 518             // This is a rare corner case, so we will ignore this for now.
 519             short replyStatus = info.getReplyStatus();
 520             if (replyStatus == info.UNINITIALIZED ) {
 521                 invokeClientPIEndingPoint( ReplyMessage.SYSTEM_EXCEPTION,
 522                     wrapper.unknownRequestInvoke(
 523                         CompletionStatus.COMPLETED_MAYBE ) ) ;
 524             }
 525         }
 526 
 527         // Decrement entry count, and if it is zero, pop it from the stack.
 528         info.decrementEntryCount();
 529 
 530         // fix for 6763340, and probably other cases (non-recursive retry)
 531         if (info.getEntryCount() == 0 && !info.getRetryRequest().isRetry()) {
 532             // RequestInfoStack<ClientRequestInfoImpl> infoStack =
 533             //     threadLocalClientRequestInfoStack.get();
 534             RequestInfoStack infoStack =
 535                 (RequestInfoStack)threadLocalClientRequestInfoStack.get();
 536             infoStack.pop();
 537             printPop();
 538         }
 539     }
 540 
 541     public void setClientPIInfo(CorbaMessageMediator messageMediator)
 542     {
 543         if( !hasClientInterceptors ) return;
 544         if( !isClientPIEnabledForThisThread() ) return;
 545 
 546         peekClientRequestInfoImplStack().setInfo(messageMediator);
 547     }
 548 
 549     public void setClientPIInfo( RequestImpl requestImpl ) {
 550         if( !hasClientInterceptors ) return;
 551         if( !isClientPIEnabledForThisThread() ) return;
 552 
 553         peekClientRequestInfoImplStack().setDIIRequest( requestImpl );
 554     }
 555 
 556     /*
 557      *****************
 558      * Server PI hooks
 559      *****************/
 560 
 561     public void invokeServerPIStartingPoint()
 562     {
 563         if( !hasServerInterceptors ) return;
 564 
 565         ServerRequestInfoImpl info = peekServerRequestInfoImplStack();
 566         interceptorInvoker.invokeServerInterceptorStartingPoint( info );
 567 
 568         // Handle SystemException or ForwardRequest:
 569         serverPIHandleExceptions( info );
 570     }
 571 
 572     public void invokeServerPIIntermediatePoint()
 573     {
 574         if( !hasServerInterceptors ) return;
 575 
 576         ServerRequestInfoImpl info = peekServerRequestInfoImplStack();
 577         interceptorInvoker.invokeServerInterceptorIntermediatePoint( info );
 578 
 579         // Clear servant from info object so that the user has control over
 580         // its lifetime:
 581         info.releaseServant();
 582 
 583         // Handle SystemException or ForwardRequest:
 584         serverPIHandleExceptions( info );
 585     }
 586 
 587     public void invokeServerPIEndingPoint( ReplyMessage replyMessage )
 588     {
 589         if( !hasServerInterceptors ) return;
 590         ServerRequestInfoImpl info = peekServerRequestInfoImplStack();
 591 
 592         // REVISIT: This needs to be done "early" for the following workaround.
 593         info.setReplyMessage( replyMessage );
 594 
 595         // REVISIT: This was done inside of invokeServerInterceptorEndingPoint
 596         // but needs to be here for now.  See comment in that method for why.
 597         info.setCurrentExecutionPoint( info.EXECUTION_POINT_ENDING );
 598 
 599         // It is possible we might have entered this method more than
 600         // once (e.g. if an ending point threw a SystemException, then
 601         // a new ServerResponseImpl is created).
 602         if( !info.getAlreadyExecuted() ) {
 603             int replyStatus = replyMessage.getReplyStatus();
 604 
 605             // Translate ReplyMessage.replyStatus into PI replyStatus:
 606             // Note: this is also an assertion to make sure a valid
 607             // replyStatus is passed in (IndexOutOfBoundsException will be
 608             // thrown otherwise)
 609             short piReplyStatus =
 610                 REPLY_MESSAGE_TO_PI_REPLY_STATUS[replyStatus];
 611 
 612             // Make forwarded IOR available to interceptors, if applicable:
 613             if( ( piReplyStatus == LOCATION_FORWARD.value ) ||
 614                 ( piReplyStatus == TRANSPORT_RETRY.value ) )
 615             {
 616                 info.setForwardRequest( replyMessage.getIOR() );
 617             }
 618 
 619             // REVISIT: Do early above for now.
 620             // Make reply message available to interceptors:
 621             //info.setReplyMessage( replyMessage );
 622 
 623             // Remember exception so we can tell if an interceptor changed it.
 624             Exception prevException = info.getException();
 625 
 626             // _REVISIT_ We do not have access to the User Exception at
 627             // this point, so treat it as an UNKNOWN for now.
 628             // Note that if this is a DSI call, we do have the user exception.
 629             if( !info.isDynamic() &&
 630                 (piReplyStatus == USER_EXCEPTION.value) )
 631             {
 632                 info.setException( omgWrapper.unknownUserException(
 633                     CompletionStatus.COMPLETED_MAYBE ) ) ;
 634             }
 635 
 636             // Invoke the ending interception points:
 637             info.setReplyStatus( piReplyStatus );
 638             interceptorInvoker.invokeServerInterceptorEndingPoint( info );
 639             short newPIReplyStatus = info.getReplyStatus();
 640             Exception newException = info.getException();
 641 
 642             // Check reply status.  If an interceptor threw a SystemException
 643             // and it is different than the one that we came in with,
 644             // rethrow it so the proper response can be constructed:
 645             if( ( newPIReplyStatus == SYSTEM_EXCEPTION.value ) &&
 646                 ( newException != prevException ) )
 647             {
 648                 throw (SystemException)newException;
 649             }
 650 
 651             // If we are to forward the location:
 652             if( newPIReplyStatus == LOCATION_FORWARD.value ) {
 653                 if( piReplyStatus != LOCATION_FORWARD.value ) {
 654                     // Treat a ForwardRequest as a ForwardException.
 655                     IOR ior = info.getForwardRequestIOR();
 656                     throw new ForwardException( orb, ior ) ;
 657                 }
 658                 else if( info.isForwardRequestRaisedInEnding() ) {
 659                     // Treat a ForwardRequest by changing the IOR.
 660                     replyMessage.setIOR( info.getForwardRequestIOR() );
 661                 }
 662             }
 663         }
 664     }
 665 
 666     public void setServerPIInfo( Exception exception ) {
 667         if( !hasServerInterceptors ) return;
 668 
 669         ServerRequestInfoImpl info = peekServerRequestInfoImplStack();
 670         info.setException( exception );
 671     }
 672 
 673     public void setServerPIInfo( NVList arguments )
 674     {
 675         if( !hasServerInterceptors ) return;
 676 
 677         ServerRequestInfoImpl info = peekServerRequestInfoImplStack();
 678         info.setDSIArguments( arguments );
 679     }
 680 
 681     public void setServerPIExceptionInfo( Any exception )
 682     {
 683         if( !hasServerInterceptors ) return;
 684 
 685         ServerRequestInfoImpl info = peekServerRequestInfoImplStack();
 686         info.setDSIException( exception );
 687     }
 688 
 689     public void setServerPIInfo( Any result )
 690     {
 691         if( !hasServerInterceptors ) return;
 692 
 693         ServerRequestInfoImpl info = peekServerRequestInfoImplStack();
 694         info.setDSIResult( result );
 695     }
 696 
 697     public void initializeServerPIInfo( CorbaMessageMediator request,
 698         ObjectAdapter oa, byte[] objectId, ObjectKeyTemplate oktemp )
 699     {
 700         if( !hasServerInterceptors ) return;
 701 
 702         RequestInfoStack infoStack =
 703             (RequestInfoStack)threadLocalServerRequestInfoStack.get();
 704         ServerRequestInfoImpl info = new ServerRequestInfoImpl( orb );
 705         infoStack.push( info );
 706         printPush();
 707 
 708         // Notify request object that once response is constructed, make
 709         // sure we execute ending points.
 710         request.setExecutePIInResponseConstructor( true );
 711 
 712         info.setInfo( request, oa, objectId, oktemp );
 713     }
 714 
 715     public void setServerPIInfo( java.lang.Object servant,
 716                                           String targetMostDerivedInterface )
 717     {
 718         if( !hasServerInterceptors ) return;
 719 
 720         ServerRequestInfoImpl info = peekServerRequestInfoImplStack();
 721         info.setInfo( servant, targetMostDerivedInterface );
 722     }
 723 
 724     public void cleanupServerPIRequest() {
 725         if( !hasServerInterceptors ) return;
 726 
 727         RequestInfoStack infoStack =
 728             (RequestInfoStack)threadLocalServerRequestInfoStack.get();
 729         infoStack.pop();
 730         printPop();
 731     }
 732 
 733     /*
 734      **********************************************************************
 735      *  The following methods are private utility methods.
 736      ************************************************************************/
 737 
 738     /**
 739      * Handles exceptions for the starting and intermediate points for
 740      * server request interceptors.  This is common code that has been
 741      * factored out into this utility method.
 742      * <p>
 743      * This method will NOT work for ending points.
 744      */
 745     private void serverPIHandleExceptions( ServerRequestInfoImpl info )
 746     {
 747         int endingPointCall = info.getEndingPointCall();
 748         if(endingPointCall == ServerRequestInfoImpl.CALL_SEND_EXCEPTION) {
 749             // If a system exception was thrown, throw it to caller:
 750             throw (SystemException)info.getException();
 751         }
 752         else if( (endingPointCall == ServerRequestInfoImpl.CALL_SEND_OTHER) &&
 753                  (info.getForwardRequestException() != null) )
 754         {
 755             // If an interceptor throws a forward request, convert it
 756             // into a ForwardException for easier handling:
 757             IOR ior = info.getForwardRequestIOR();
 758             throw new ForwardException( orb, ior );
 759         }
 760     }
 761 
 762     /**
 763      * Utility method to convert a PI reply status short to a ReplyMessage
 764      * constant.  This is a reverse lookup on the table defined in
 765      * REPLY_MESSAGE_TO_PI_REPLY_STATUS.  The reverse lookup need not be
 766      * performed as quickly since it is only executed in exception
 767      * conditions.
 768      */
 769     private int convertPIReplyStatusToReplyMessage( short replyStatus ) {
 770         int result = 0;
 771         for( int i = 0; i < REPLY_MESSAGE_TO_PI_REPLY_STATUS.length; i++ ) {
 772             if( REPLY_MESSAGE_TO_PI_REPLY_STATUS[i] == replyStatus ) {
 773                 result = i;
 774                 break;
 775             }
 776         }
 777         return result;
 778     }
 779 
 780     /**
 781      * Convenience method to get the ClientRequestInfoImpl object off the
 782      * top of the ThreadLocal stack.  Throws an INTERNAL exception if
 783      * the Info stack is empty.
 784      */
 785     private ClientRequestInfoImpl peekClientRequestInfoImplStack() {
 786         RequestInfoStack infoStack =
 787             (RequestInfoStack)threadLocalClientRequestInfoStack.get();
 788         ClientRequestInfoImpl info = null;
 789         if( !infoStack.empty() ) {
 790             info = (ClientRequestInfoImpl)infoStack.peek();
 791         } else {
 792             throw wrapper.clientInfoStackNull() ;
 793         }
 794 
 795         return info;
 796     }
 797 
 798     /**
 799      * Convenience method to get the ServerRequestInfoImpl object off the
 800      * top of the ThreadLocal stack.  Returns null if there are none.
 801      */
 802     private ServerRequestInfoImpl peekServerRequestInfoImplStack() {
 803         RequestInfoStack infoStack =
 804             (RequestInfoStack)threadLocalServerRequestInfoStack.get();
 805         ServerRequestInfoImpl info = null;
 806 
 807         if( !infoStack.empty() ) {
 808             info = (ServerRequestInfoImpl)infoStack.peek();
 809         } else {
 810             throw wrapper.serverInfoStackNull() ;
 811         }
 812 
 813         return info;
 814     }
 815 
 816     /**
 817      * Convenience method to determine whether Client PI is enabled
 818      * for requests on this thread.
 819      */
 820     private boolean isClientPIEnabledForThisThread() {
 821         RequestInfoStack infoStack =
 822             (RequestInfoStack)threadLocalClientRequestInfoStack.get();
 823         return (infoStack.disableCount == 0);
 824     }
 825 
 826     /**
 827      * Call pre_init on all ORB initializers
 828      */
 829     private void preInitORBInitializers( ORBInitInfoImpl info ) {
 830 
 831         // Inform ORBInitInfo we are in pre_init stage
 832         info.setStage( ORBInitInfoImpl.STAGE_PRE_INIT );
 833 
 834         // Step through each initializer instantiation and call its
 835         // pre_init.  Ignore any exceptions.
 836         for( int i = 0; i < orb.getORBData().getORBInitializers().length;
 837             i++ ) {
 838             ORBInitializer init = orb.getORBData().getORBInitializers()[i];
 839             if( init != null ) {
 840                 try {
 841                     init.pre_init( info );
 842                 }
 843                 catch( Exception e ) {
 844                     // As per orbos/99-12-02, section 9.3.1.2, "If there are
 845                     // any exceptions, the ORB shall ignore them and proceed."
 846                 }
 847             }
 848         }
 849     }
 850 
 851     /**
 852      * Call post_init on all ORB initializers
 853      */
 854     private void postInitORBInitializers( ORBInitInfoImpl info ) {
 855 
 856         // Inform ORBInitInfo we are in post_init stage
 857         info.setStage( ORBInitInfoImpl.STAGE_POST_INIT );
 858 
 859         // Step through each initializer instantiation and call its post_init.
 860         // Ignore any exceptions.
 861         for( int i = 0; i < orb.getORBData().getORBInitializers().length;
 862             i++ ) {
 863             ORBInitializer init = orb.getORBData().getORBInitializers()[i];
 864             if( init != null ) {
 865                 try {
 866                     init.post_init( info );
 867                 }
 868                 catch( Exception e ) {
 869                     // As per orbos/99-12-02, section 9.3.1.2, "If there are
 870                     // any exceptions, the ORB shall ignore them and proceed."
 871                 }
 872             }
 873         }
 874     }
 875 
 876     /**
 877      * Creates the ORBInitInfo object to be passed to ORB intializers'
 878      * pre_init and post_init methods
 879      */
 880     private ORBInitInfoImpl createORBInitInfo() {
 881         ORBInitInfoImpl result = null;
 882 
 883         // arguments comes from set_parameters.  May be null.
 884 
 885         // _REVISIT_ The spec does not specify which ID this is to be.
 886         // We currently get this from the corba.ORB, which reads it from
 887         // the ORB_ID_PROPERTY property.
 888         String orbId = orb.getORBData().getORBId() ;
 889 
 890         result = new ORBInitInfoImpl( orb, arguments, orbId, codecFactory );
 891 
 892         return result;
 893     }
 894 
 895     /**
 896      * Called by ORBInitInfo when an interceptor needs to be registered.
 897      * The type is one of:
 898      * <ul>
 899      *   <li>INTERCEPTOR_TYPE_CLIENT - ClientRequestInterceptor
 900      *   <li>INTERCEPTOR_TYPE_SERVER - ServerRequestInterceptor
 901      *   <li>INTERCEPTOR_TYPE_IOR - IORInterceptor
 902      * </ul>
 903      *
 904      * @exception DuplicateName Thrown if an interceptor of the given
 905      *     name already exists for the given type.
 906      */
 907     public void register_interceptor( Interceptor interceptor, int type )
 908         throws DuplicateName
 909     {
 910         // We will assume interceptor is not null, since it is called
 911         // internally.
 912         if( (type >= InterceptorList.NUM_INTERCEPTOR_TYPES) || (type < 0) ) {
 913             throw wrapper.typeOutOfRange( new Integer( type ) ) ;
 914         }
 915 
 916         String interceptorName = interceptor.name();
 917 
 918         if( interceptorName == null ) {
 919             throw wrapper.nameNull() ;
 920         }
 921 
 922         // Register with interceptor list:
 923         interceptorList.register_interceptor( interceptor, type );
 924     }
 925 
 926     public Current getPICurrent( ) {
 927         return current;
 928     }
 929 
 930     /**
 931      * Called when an invalid null parameter was passed.  Throws a
 932      * BAD_PARAM with a minor code of 1
 933      */
 934     private void nullParam()
 935         throws BAD_PARAM
 936     {
 937         throw orbutilWrapper.nullParam() ;
 938     }
 939 
 940     /** This is the implementation of standard API defined in org.omg.CORBA.ORB
 941      *  class. This method finds the Policy Factory for the given Policy Type
 942      *  and instantiates the Policy object from the Factory. It will throw
 943      *  PolicyError exception, If the PolicyFactory for the given type is
 944      *  not registered.
 945      *  _REVISIT_, Once Policy Framework work is completed, Reorganize
 946      *  this method to com.sun.corba.se.spi.orb.ORB.
 947      */
 948     public org.omg.CORBA.Policy create_policy(int type, org.omg.CORBA.Any val)
 949         throws org.omg.CORBA.PolicyError
 950     {
 951         if( val == null ) {
 952             nullParam( );
 953         }
 954         if( policyFactoryTable == null ) {
 955             throw new org.omg.CORBA.PolicyError(
 956                 "There is no PolicyFactory Registered for type " + type,
 957                 BAD_POLICY.value );
 958         }
 959         PolicyFactory factory = (PolicyFactory)policyFactoryTable.get(
 960             new Integer(type) );
 961         if( factory == null ) {
 962             throw new org.omg.CORBA.PolicyError(
 963                 " Could Not Find PolicyFactory for the Type " + type,
 964                 BAD_POLICY.value);
 965         }
 966         org.omg.CORBA.Policy policy = factory.create_policy( type, val );
 967         return policy;
 968     }
 969 
 970     /** This method registers the Policy Factory in the policyFactoryTable,
 971      *  which is a HashMap. This method is made package private, because
 972      *  it is used internally by the  Interceptors.
 973      */
 974     public void registerPolicyFactory( int type, PolicyFactory factory ) {
 975         if( policyFactoryTable == null ) {
 976             policyFactoryTable = new HashMap();
 977         }
 978         Integer key = new Integer( type );
 979         java.lang.Object val = policyFactoryTable.get( key );
 980         if( val == null ) {
 981             policyFactoryTable.put( key, factory );
 982         }
 983         else {
 984             throw omgWrapper.policyFactoryRegFailed( new Integer( type ) ) ;
 985         }
 986     }
 987 
 988     public synchronized int allocateServerRequestId ()
 989     {
 990         return serverRequestIdCounter++;
 991     }
 992 }