ServerRequestInfoImpl.java revision 608:7e06bf1dcb09
1/*
2 * Copyright (c) 2000, 2012, 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 */
25package com.sun.corba.se.impl.interceptors;
26
27import org.omg.CORBA.Any;
28import org.omg.CORBA.BAD_INV_ORDER;
29import org.omg.CORBA.CompletionStatus;
30import org.omg.CORBA.INTERNAL;
31import org.omg.CORBA.LocalObject;
32import org.omg.CORBA.NO_IMPLEMENT;
33import org.omg.CORBA.NO_RESOURCES;
34import org.omg.CORBA.NVList;
35import org.omg.CORBA.Object;
36import org.omg.CORBA.Policy;
37import org.omg.CORBA.TypeCode;
38
39import org.omg.PortableServer.Servant;
40
41import org.omg.IOP.TaggedProfile;
42import org.omg.IOP.ServiceContext;
43
44import org.omg.Dynamic.Parameter;
45
46import org.omg.PortableInterceptor.InvalidSlot;
47import org.omg.PortableInterceptor.ServerRequestInfo;
48import org.omg.PortableInterceptor.LOCATION_FORWARD;
49import org.omg.PortableInterceptor.SUCCESSFUL;
50import org.omg.PortableInterceptor.SYSTEM_EXCEPTION;
51import org.omg.PortableInterceptor.TRANSPORT_RETRY;
52import org.omg.PortableInterceptor.USER_EXCEPTION;
53
54import com.sun.corba.se.spi.oa.ObjectAdapter;
55import com.sun.corba.se.spi.presentation.rmi.StubAdapter;
56
57import com.sun.corba.se.impl.protocol.giopmsgheaders.ReplyMessage;
58
59import com.sun.corba.se.spi.servicecontext.ServiceContexts;
60import com.sun.corba.se.spi.orb.ORB;
61
62import com.sun.corba.se.spi.ior.ObjectKeyTemplate;
63import com.sun.corba.se.spi.ior.ObjectAdapterId ;
64
65import com.sun.corba.se.spi.protocol.CorbaMessageMediator;
66
67import java.util.*;
68
69/**
70 * Implementation of the ServerRequestInfo interface as specified in
71 * orbos/99-12-02 section 5.4.3.
72 */
73public final class ServerRequestInfoImpl
74    extends RequestInfoImpl
75    implements ServerRequestInfo
76{
77    // The available constants for startingPointCall
78    static final int CALL_RECEIVE_REQUEST_SERVICE_CONTEXT = 0;
79
80    // The available constants for intermediatePointCall.  The default (0)
81    // is receive_request, but can be set to none on demand.
82    static final int CALL_RECEIVE_REQUEST = 0;
83    static final int CALL_INTERMEDIATE_NONE = 1;
84
85    // The available constants for endingPointCall
86    static final int CALL_SEND_REPLY = 0;
87    static final int CALL_SEND_EXCEPTION = 1;
88    static final int CALL_SEND_OTHER = 2;
89
90    //////////////////////////////////////////////////////////////////////
91    //
92    // NOTE: IF AN ATTRIBUTE IS ADDED, PLEASE UPDATE RESET();
93    //
94    //////////////////////////////////////////////////////////////////////
95
96    // Set to true if the server ending point raised ForwardRequest at some
97    // point in the ending point.
98    private boolean forwardRequestRaisedInEnding;
99
100    // Sources of server request information:
101    private CorbaMessageMediator request;
102    private java.lang.Object servant;
103    private byte[] objectId;
104    private ObjectKeyTemplate oktemp ;
105
106    // Information cached from calls to oktemp
107    private byte[] adapterId;
108    private String[] adapterName;
109
110    private ArrayList addReplyServiceContextQueue;
111    private ReplyMessage replyMessage;
112    private String targetMostDerivedInterface;
113    private NVList dsiArguments;
114    private Any dsiResult;
115    private Any dsiException;
116    private boolean isDynamic;
117    private ObjectAdapter objectAdapter;
118    private int serverRequestId;
119
120    // Cached information:
121    private Parameter[] cachedArguments;
122    private Any cachedSendingException;
123    // key = Integer, value = IOP.ServiceContext.
124    private HashMap cachedRequestServiceContexts;
125    // key = Integer, value = IOP.ServiceContext.
126    private HashMap cachedReplyServiceContexts;
127
128    //////////////////////////////////////////////////////////////////////
129    //
130    // NOTE: IF AN ATTRIBUTE IS ADDED, PLEASE UPDATE RESET();
131    //
132    //////////////////////////////////////////////////////////////////////
133
134
135    /**
136     * Reset the info object so that it can be reused for a retry,
137     * for example.
138     */
139    void reset() {
140        super.reset();
141
142        // Please keep these in the same order as declared above.
143
144        forwardRequestRaisedInEnding = false;
145
146        request = null;
147        servant = null;
148        objectId = null;
149        oktemp = null;
150
151        adapterId = null;
152        adapterName = null;
153
154        addReplyServiceContextQueue = null;
155        replyMessage = null;
156        targetMostDerivedInterface = null;
157        dsiArguments = null;
158        dsiResult = null;
159        dsiException = null;
160        isDynamic = false;
161        objectAdapter = null;
162        serverRequestId = myORB.getPIHandler().allocateServerRequestId();
163
164        // reset cached attributes:
165        cachedArguments = null;
166        cachedSendingException = null;
167        cachedRequestServiceContexts = null;
168        cachedReplyServiceContexts = null;
169
170        startingPointCall = CALL_RECEIVE_REQUEST_SERVICE_CONTEXT;
171        intermediatePointCall = CALL_RECEIVE_REQUEST;
172        endingPointCall = CALL_SEND_REPLY;
173    }
174
175    /*
176     **********************************************************************
177     * Access protection
178     **********************************************************************/
179
180    // Method IDs for all methods in ServerRequestInfo.  This allows for a
181    // convenient O(1) lookup for checkAccess().
182    protected static final int MID_SENDING_EXCEPTION       = MID_RI_LAST +  1;
183    protected static final int MID_OBJECT_ID               = MID_RI_LAST +  2;
184    protected static final int MID_ADAPTER_ID              = MID_RI_LAST +  3;
185    protected static final int MID_TARGET_MOST_DERIVED_INTERFACE
186                                                           = MID_RI_LAST +  4;
187    protected static final int MID_GET_SERVER_POLICY       = MID_RI_LAST +  5;
188    protected static final int MID_SET_SLOT                = MID_RI_LAST +  6;
189    protected static final int MID_TARGET_IS_A             = MID_RI_LAST +  7;
190    protected static final int MID_ADD_REPLY_SERVICE_CONTEXT
191                                                           = MID_RI_LAST +  8;
192    protected static final int MID_SERVER_ID               = MID_RI_LAST +  9;
193    protected static final int MID_ORB_ID                  = MID_RI_LAST +  10;
194    protected static final int MID_ADAPTER_NAME            = MID_RI_LAST +  11;
195
196    // ServerRequestInfo validity table (see ptc/00-08-06 table 21-2).
197    // Note: These must be in the same order as specified in contants.
198    private static final boolean validCall[][] = {
199        // LEGEND:
200        // r_rsc = receive_request_service_contexts
201        // r_req = receive_request
202        // s_rep = send_reply
203        // s_exc = send_exception
204        // s_oth = send_other
205        //
206        // A true value indicates call is valid at specified point.
207        // A false value indicates the call is invalid.
208        //
209        // NOTE: If the order or number of columns change, update
210        // checkAccess() accordingly.
211        //
212        //                              { r_rsc, r_req, s_rep, s_exc, s_oth }
213        // RequestInfo methods:
214        /*request_id*/                  { true , true , true , true , true  },
215        /*operation*/                   { true , true , true , true , true  },
216        /*arguments*/                   { false, true , true , false, false },
217        /*exceptions*/                  { false, true , true , true , true  },
218        /*contexts*/                    { false, true , true , true , true  },
219        /*operation_context*/           { false, true , true , false, false },
220        /*result*/                      { false, false, true , false, false },
221        /*response_expected*/           { true , true , true , true , true  },
222        /*sync_scope*/                  { true , true , true , true , true  },
223        /*reply_status*/                { false, false, true , true , true  },
224        /*forward_reference*/           { false, false, false, false, true  },
225        /*get_slot*/                    { true , true , true , true , true  },
226        /*get_request_service_context*/ { true , true , true , true , true  },
227        /*get_reply_service_context*/   { false, false, true , true , true  },
228        //
229        // ServerRequestInfo methods::
230        /*sending_exception*/           { false, false, false, true , false },
231        /*object_id*/                   { false, true , true , true , true  },
232        /*adapter_id*/                  { false, true , true , true , true  },
233        /*target_most_derived_inte...*/ { false, true , false, false, false },
234        /*get_server_policy*/           { true , true , true , true , true  },
235        /*set_slot*/                    { true , true , true , true , true  },
236        /*target_is_a*/                 { false, true , false, false, false },
237        /*add_reply_service_context*/   { true , true , true , true , true  },
238        /*orb_id*/                      { false, true , true , true , true  },
239        /*server_id*/                   { false, true , true , true , true  },
240        /*adapter_name*/                { false, true , true , true , true  }
241    };
242
243    /*
244     **********************************************************************
245     * Public interfaces
246     **********************************************************************/
247
248    /**
249     * Creates a new ServerRequestInfo implementation.
250     * The constructor is package scope since no other package need create
251     * an instance of this class.
252     */
253    ServerRequestInfoImpl( ORB myORB ) {
254        super( myORB );
255        startingPointCall = CALL_RECEIVE_REQUEST_SERVICE_CONTEXT;
256        intermediatePointCall = CALL_RECEIVE_REQUEST;
257        endingPointCall = CALL_SEND_REPLY;
258        serverRequestId = myORB.getPIHandler().allocateServerRequestId();
259    }
260
261    /**
262     * Any containing the exception to be returned to the client.
263     */
264    public Any sending_exception () {
265        checkAccess( MID_SENDING_EXCEPTION );
266
267        if( cachedSendingException == null ) {
268            Any result = null ;
269
270            if( dsiException != null ) {
271                result = dsiException;
272            } else if( exception != null ) {
273                result = exceptionToAny( exception );
274            } else {
275                // sending_exception should not be callable if both dsiException
276                // and exception are null.
277                throw wrapper.exceptionUnavailable() ;
278            }
279
280            cachedSendingException = result;
281        }
282
283        return cachedSendingException;
284    }
285
286    /**
287     * The opaque object_id describing the target of the operation invocation.
288     */
289    public byte[] object_id () {
290        checkAccess( MID_OBJECT_ID );
291
292        if( objectId == null ) {
293            // For some reason, we never set object id.  This could be
294            // because a servant locator caused a location forward or
295            // raised an exception.  As per ptc/00-08-06, section 21.3.14,
296            // we throw NO_RESOURCES
297            throw stdWrapper.piOperationNotSupported6() ;
298        }
299
300        // Good citizen: In the interest of efficiency, we will assume
301        // interceptors will not change the resulting byte[] array.
302        // Otherwise, we would need to make a clone of this array.
303
304        return objectId;
305    }
306
307    private void checkForNullTemplate()
308    {
309        if (oktemp == null) {
310            // For some reason, we never set the ObjectKeyTemplate
311            // because a servant locator caused a location forward or
312            // raised an exception.  As per ptc/00-08-06, section 21.3.14,
313            // we throw NO_RESOURCES
314            throw stdWrapper.piOperationNotSupported7() ;
315        }
316    }
317
318    public String server_id()
319    {
320        checkAccess( MID_SERVER_ID ) ;
321        checkForNullTemplate() ;
322
323        // Good citizen: In the interest of efficiency, we will assume
324        // interceptors will not change the resulting byte[] array.
325        // Otherwise, we would need to make a clone of this array.
326
327        return Integer.toString( oktemp.getServerId() ) ;
328    }
329
330    public String orb_id()
331    {
332        checkAccess( MID_ORB_ID ) ;
333
334        return myORB.getORBData().getORBId() ;
335    }
336
337    synchronized public String[] adapter_name()
338    {
339        checkAccess( MID_ADAPTER_NAME ) ;
340
341        if (adapterName == null) {
342            checkForNullTemplate() ;
343
344            ObjectAdapterId oaid = oktemp.getObjectAdapterId() ;
345            adapterName = oaid.getAdapterName() ;
346        }
347
348        return adapterName ;
349    }
350
351    /**
352     * The opaque identifier for the object adapter.
353     */
354    synchronized public byte[] adapter_id ()
355    {
356        checkAccess( MID_ADAPTER_ID );
357
358        if( adapterId == null ) {
359            checkForNullTemplate() ;
360            adapterId = oktemp.getAdapterId() ;
361        }
362
363        return adapterId;
364    }
365
366    /**
367     * The RepositoryID for the most derived interface of the servant.
368     */
369    public String target_most_derived_interface () {
370        checkAccess( MID_TARGET_MOST_DERIVED_INTERFACE );
371        return targetMostDerivedInterface;
372    }
373
374    /**
375     * Returns the policy in effect for this operation for the given policy
376     * type.
377     */
378    public Policy get_server_policy (int type) {
379        // access is currently valid for all states:
380        //checkAccess( MID_GET_SERVER_POLICY );
381
382        Policy result = null;
383
384        if( objectAdapter != null ) {
385            result = objectAdapter.getEffectivePolicy( type );
386        }
387
388        // _REVISIT_ RTF Issue: get_server_policy spec not in sync with
389        // get_effective_policy spec.
390
391        return result;
392    }
393
394    /**
395     * Allows an Interceptor to set a slot in the Current that is in the scope
396     * of the request.  If data already exists in that slot, it will be
397     * overwritten.  If the ID does not define an allocated slot, InvalidSlot
398     * is raised.
399     */
400    public void set_slot (int id, Any data) throws InvalidSlot {
401        // access is currently valid for all states:
402        //checkAccess( MID_SET_SLOT );
403
404        slotTable.set_slot( id, data );
405    }
406
407    /**
408     * Returns true if the servant is the given RepositoryId, false if it is
409     * not.
410     */
411    public boolean target_is_a (String id) {
412        checkAccess( MID_TARGET_IS_A );
413
414        boolean result = false ;
415        if( servant instanceof Servant ) {
416            result = ((Servant)servant)._is_a( id );
417        } else if (StubAdapter.isStub( servant )) {
418            result = ((org.omg.CORBA.Object)servant)._is_a( id );
419        } else {
420            throw wrapper.servantInvalid() ;
421        }
422
423        return result;
424    }
425
426    /**
427     * Allows Interceptors to add service contexts to the request.
428     */
429    public void add_reply_service_context ( ServiceContext service_context,
430                                            boolean replace )
431    {
432        // access is currently valid for all states:
433        //checkAccess( MID_ADD_REPLY_SERVICE_CONTEXT );
434
435        if( currentExecutionPoint == EXECUTION_POINT_ENDING ) {
436            ServiceContexts scs = replyMessage.getServiceContexts();
437
438            // May be null.  If this is null, create a new one in its place.
439            if( scs == null ) {
440                scs = new ServiceContexts( myORB );
441                replyMessage.setServiceContexts( scs );
442            }
443
444            if( cachedReplyServiceContexts == null ) {
445                cachedReplyServiceContexts = new HashMap();
446            }
447
448            // This is during and ending point, so we now have enough
449            // information to add the reply service context.
450            addServiceContext( cachedReplyServiceContexts, scs,
451                               service_context, replace );
452        }
453
454        // We enqueue all adds for the following reasons:
455        //
456        // If we are not in the ending point then we do not yet have a
457        // pointer to the ServiceContexts object so we cannot access the
458        // service contexts until we get to the ending point.
459        // So we enqueue this add reply service context request.
460        // It is added when we do have a handle on the service contexts object.
461        //
462        // If we are in the ending point and we just add directly to the
463        // SC container but then an interceptor raises a SystemException
464        // then that add will be lost since a new container is created
465        // for the SystemException response.
466        //
467        // Therefore we always enqueue and never dequeue (per request) so
468        // that all adds will be completed.
469
470        AddReplyServiceContextCommand addReply =
471            new AddReplyServiceContextCommand();
472        addReply.service_context = service_context;
473        addReply.replace = replace;
474
475        if( addReplyServiceContextQueue == null ) {
476            addReplyServiceContextQueue = new ArrayList();
477        }
478
479        // REVISIT: this does not add to the cache.
480        enqueue( addReply );
481    }
482
483    // NOTE: When adding a method, be sure to:
484    // 1. Add a MID_* constant for that method
485    // 2. Call checkAccess at the start of the method
486    // 3. Define entries in the validCall[][] table for interception points.
487
488    /*
489     **********************************************************************
490     * Public RequestInfo interfaces
491     *
492     * These are implemented here because they have differing
493     * implementations depending on whether this is a client or a server
494     * request info object.
495     **********************************************************************/
496
497    /**
498     * See ServerRequestInfo for javadocs.
499     */
500    public int request_id (){
501        // access is currently valid for all states:
502        //checkAccess( MID_REQUEST_ID );
503        /*
504         * NOTE: The request id in server interceptors is NOT the
505         * same as the GIOP request id.  The ORB may be servicing several
506         * connections, each with possibly overlapping sets of request ids.
507         * Therefore we create a request id specific to interceptors.
508         */
509        return serverRequestId;
510    }
511
512    /**
513     * See ServerRequestInfo for javadocs.
514     */
515    public String operation (){
516        // access is currently valid for all states:
517        //checkAccess( MID_OPERATION );
518        return request.getOperationName();
519    }
520
521    /**
522     * See ServerRequestInfo for javadocs.
523     */
524    public Parameter[] arguments (){
525        checkAccess( MID_ARGUMENTS );
526
527        if( cachedArguments == null ) {
528            if( !isDynamic ) {
529                throw stdWrapper.piOperationNotSupported1() ;
530            }
531
532            if( dsiArguments == null ) {
533                throw stdWrapper.piOperationNotSupported8() ;
534            }
535
536            // If it is a DSI request then get the arguments from the DSI req
537            // and convert that into parameters.
538            cachedArguments = nvListToParameterArray( dsiArguments );
539        }
540
541        // Good citizen: In the interest of efficiency, we assume
542        // interceptors will be "good citizens" in that they will not
543        // modify the contents of the Parameter[] array.  We also assume
544        // they will not change the values of the containing Anys.
545
546        return cachedArguments;
547    }
548
549    /**
550     * See ServerRequestInfo for javadocs.
551     */
552    public TypeCode[] exceptions (){
553        checkAccess( MID_EXCEPTIONS );
554
555        // _REVISIT_ PI RTF Issue: No exception list on server side.
556
557        throw stdWrapper.piOperationNotSupported2() ;
558    }
559
560    /**
561     * See ServerRequestInfo for javadocs.
562     */
563    public String[] contexts (){
564        checkAccess( MID_CONTEXTS );
565
566        // We do not support this because our ORB does not send contexts.
567
568        throw stdWrapper.piOperationNotSupported3() ;
569    }
570
571    /**
572     * See ServerRequestInfo for javadocs.
573     */
574    public String[] operation_context (){
575        checkAccess( MID_OPERATION_CONTEXT );
576
577        // We do not support this because our ORB does not send
578        // operation_context.
579
580        throw stdWrapper.piOperationNotSupported4() ;
581    }
582
583    /**
584     * See ServerRequestInfo for javadocs.
585     */
586    public Any result (){
587        checkAccess( MID_RESULT );
588
589        if( !isDynamic ) {
590            throw stdWrapper.piOperationNotSupported5() ;
591        }
592
593        if( dsiResult == null ) {
594            throw wrapper.piDsiResultIsNull() ;
595        }
596
597        // Good citizen: In the interest of efficiency, we assume that
598        // interceptors will not modify the contents of the result Any.
599        // Otherwise, we would need to create a deep copy of the Any.
600
601        return dsiResult;
602    }
603
604    /**
605     * See ServerRequestInfo for javadocs.
606     */
607    public boolean response_expected (){
608        // access is currently valid for all states:
609        //checkAccess( MID_RESPONSE_EXPECTED );
610        return !request.isOneWay();
611    }
612
613    /**
614     * See ServerRequestInfo for javadocs.
615     */
616    public Object forward_reference (){
617        checkAccess( MID_FORWARD_REFERENCE );
618        // Check to make sure we are in LOCATION_FORWARD
619        // state as per ptc/00-08-06, table 21-2
620        // footnote 2.
621        if( replyStatus != LOCATION_FORWARD.value ) {
622            throw stdWrapper.invalidPiCall1() ;
623        }
624
625        return getForwardRequestException().forward;
626    }
627
628    /**
629     * See ServerRequestInfo for javadocs.
630     */
631    public org.omg.IOP.ServiceContext get_request_service_context( int id ) {
632        checkAccess( MID_GET_REQUEST_SERVICE_CONTEXT );
633
634        if( cachedRequestServiceContexts == null ) {
635            cachedRequestServiceContexts = new HashMap();
636        }
637
638        return getServiceContext( cachedRequestServiceContexts,
639                                  request.getRequestServiceContexts(), id );
640    }
641
642    /**
643     * See ServerRequestInfo for javadocs.
644     */
645    public org.omg.IOP.ServiceContext get_reply_service_context( int id ) {
646        checkAccess( MID_GET_REPLY_SERVICE_CONTEXT );
647
648        if( cachedReplyServiceContexts == null ) {
649            cachedReplyServiceContexts = new HashMap();
650        }
651
652        return getServiceContext( cachedReplyServiceContexts,
653                                  replyMessage.getServiceContexts(), id );
654    }
655
656    /*
657     **********************************************************************
658     * Private-scope classes and methods
659     **********************************************************************/
660
661    // A command encapsulating a request to add a reply service context.
662    // These commands are enqueued until we have a handle on the actual
663    // reply service context, at which point they are executed.
664    private class AddReplyServiceContextCommand {
665        ServiceContext service_context;
666        boolean replace;
667    }
668
669    // Adds the given add reply service context command to the queue of
670    // such commands.  If a command is detected to have the same id as
671    // the service context in this command, and replace is false,
672    // BAD_INV_ORDER is thrown.  If replace is true, the original command
673    // in the queue is replaced by this command.
674    private void enqueue( AddReplyServiceContextCommand addReply ) {
675        int size = addReplyServiceContextQueue.size();
676        boolean found = false;
677
678        for( int i = 0; i < size; i++ ) {
679            AddReplyServiceContextCommand cmd =
680                (AddReplyServiceContextCommand)
681                addReplyServiceContextQueue.get( i );
682
683            if( cmd.service_context.context_id ==
684                addReply.service_context.context_id )
685            {
686                found = true;
687                if( addReply.replace ) {
688                    addReplyServiceContextQueue.set( i, addReply );
689                } else {
690                    throw stdWrapper.serviceContextAddFailed(
691                        new Integer( cmd.service_context.context_id ) ) ;
692                }
693                break;
694            }
695        }
696
697        if( !found ) {
698            addReplyServiceContextQueue.add( addReply );
699        }
700    }
701
702    /*
703     **********************************************************************
704     * Package and protected-scope methods
705     **********************************************************************/
706
707    /**
708     * Overridden from RequestInfoImpl.  This version calls the super
709     * and then, if we are changing to ending points, executes all
710     * enqueued AddReplyServiceContextCommands.
711     */
712    protected void setCurrentExecutionPoint( int executionPoint ) {
713        super.setCurrentExecutionPoint( executionPoint );
714
715        // If we are transitioning to ending point, we will now have a pointer
716        // to the reply service contexts, so we can execute all queued
717        // add reply service context requests.
718        if( (executionPoint == EXECUTION_POINT_ENDING) &&
719            (addReplyServiceContextQueue != null) )
720        {
721            int size = addReplyServiceContextQueue.size();
722            for( int i = 0; i < size; i++ ) {
723                AddReplyServiceContextCommand addReply =
724                    (AddReplyServiceContextCommand)
725                    addReplyServiceContextQueue.get( i );
726                try {
727                    add_reply_service_context( addReply.service_context,
728                                               addReply.replace );
729                }
730                catch( BAD_INV_ORDER e ) {
731                    // _REVISIT_  The only way this can happen is if during
732                    // rrsc or rr, the interceptor tried to add with
733                    // replace=false to a service context that is present in
734                    // the reply message.  At that time there was no way for
735                    // us to check for this, so the best we can do is ignore
736                    // the original request.
737                }
738            }
739
740            // We specifically do not empty the SC queue so that if
741            // the interceptor raises an exception the queued service contexts
742            // will be put in the exception response.
743        }
744    }
745
746    /**
747     * Stores the various sources of information used for this info object.
748     */
749    protected void setInfo( CorbaMessageMediator request, ObjectAdapter oa,
750        byte[] objectId, ObjectKeyTemplate oktemp )
751    {
752        this.request = request;
753        this.objectId = objectId;
754        this.oktemp = oktemp;
755        this.objectAdapter = oa ;
756        this.connection = (com.sun.corba.se.spi.legacy.connection.Connection)
757            request.getConnection();
758    }
759
760    /**
761     * Stores the various sources of information used for this info object.
762     */
763    protected void setDSIArguments( NVList arguments ) {
764        this.dsiArguments = arguments;
765    }
766
767    /**
768     * Stores the various sources of information used for this info object.
769     */
770    protected void setDSIException( Any exception ) {
771        this.dsiException = exception;
772
773        // Clear cached exception value:
774        cachedSendingException = null;
775    }
776
777    /**
778     * Stores the various sources of information used for this info object.
779     */
780    protected void setDSIResult( Any result ) {
781        this.dsiResult = result;
782    }
783
784    /**
785     * Sets the exception to be returned by received_exception and
786     * received_exception_id.
787     */
788    protected void setException( Exception exception ) {
789        super.setException( exception );
790
791        // Make sure DSIException is null because this is the more recent one.
792        this.dsiException = null;
793
794        // Clear cached exception value:
795        cachedSendingException = null;
796    }
797
798    /**
799     * Stores the various sources of information used for this info object.
800     */
801    protected void setInfo( java.lang.Object servant,
802                            String targetMostDerivedInterface )
803    {
804        this.servant = servant;
805        this.targetMostDerivedInterface = targetMostDerivedInterface;
806        this.isDynamic =
807            (servant instanceof
808            org.omg.PortableServer.DynamicImplementation) ||
809            (servant instanceof org.omg.CORBA.DynamicImplementation);
810    }
811
812    /**
813     * Set reply message
814     */
815    void setReplyMessage( ReplyMessage replyMessage ) {
816        this.replyMessage = replyMessage;
817    }
818
819    /**
820     * Overridden from RequestInfoImpl.  Calls the super class, then
821     * sets the ending point call depending on the reply status.
822     */
823    protected void setReplyStatus( short replyStatus ) {
824        super.setReplyStatus( replyStatus );
825        switch( replyStatus ) {
826        case SUCCESSFUL.value:
827            endingPointCall = CALL_SEND_REPLY;
828            break;
829        case SYSTEM_EXCEPTION.value:
830        case USER_EXCEPTION.value:
831            endingPointCall = CALL_SEND_EXCEPTION;
832            break;
833        case LOCATION_FORWARD.value:
834        case TRANSPORT_RETRY.value:
835            endingPointCall = CALL_SEND_OTHER;
836            break;
837        }
838    }
839
840    /**
841     * Release the servant object so the user has control over its lifetime.
842     * Called after receive_request is finished executing.
843     */
844    void releaseServant() {
845        this.servant = null;
846    }
847
848    /**
849     * Sets the forwardRequestRaisedInEnding flag to true, indicating that
850     * a server ending point has raised location forward at some point.
851     */
852    void setForwardRequestRaisedInEnding() {
853        this.forwardRequestRaisedInEnding = true;
854    }
855
856    /**
857     * Returns true if ForwardRequest was raised by a server ending point
858     * or false otherwise.
859     */
860    boolean isForwardRequestRaisedInEnding() {
861        return this.forwardRequestRaisedInEnding;
862    }
863
864    /**
865     * Returns true if this is a dynamic invocation, or false if not
866     */
867    boolean isDynamic() {
868      return this.isDynamic;
869    }
870
871    /**
872     * See description for RequestInfoImpl.checkAccess
873     */
874    protected void checkAccess( int methodID )
875    {
876        // Make sure currentPoint matches the appropriate index in the
877        // validCall table:
878        int validCallIndex = 0;
879        switch( currentExecutionPoint ) {
880        case EXECUTION_POINT_STARTING:
881            validCallIndex = 0;
882            break;
883        case EXECUTION_POINT_INTERMEDIATE:
884            validCallIndex = 1;
885            break;
886        case EXECUTION_POINT_ENDING:
887            switch( endingPointCall ) {
888            case CALL_SEND_REPLY:
889                validCallIndex = 2;
890                break;
891            case CALL_SEND_EXCEPTION:
892                validCallIndex = 3;
893                break;
894            case CALL_SEND_OTHER:
895                validCallIndex = 4;
896                break;
897            }
898            break;
899        }
900
901        // Check the validCall table:
902        if( !validCall[methodID][validCallIndex] ) {
903            throw stdWrapper.invalidPiCall2() ;
904        }
905    }
906
907}
908