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