ClientRequestInfoImpl.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 */
25
26package com.sun.corba.se.impl.interceptors;
27
28import java.util.HashMap ;
29
30import org.omg.CORBA.Any;
31import org.omg.CORBA.BAD_INV_ORDER;
32import org.omg.CORBA.BAD_PARAM;
33import org.omg.CORBA.CompletionStatus;
34import org.omg.CORBA.Context;
35import org.omg.CORBA.ContextList;
36import org.omg.CORBA.CTX_RESTRICT_SCOPE;
37import org.omg.CORBA.ExceptionList;
38import org.omg.CORBA.LocalObject;
39import org.omg.CORBA.NamedValue;
40import org.omg.CORBA.NO_IMPLEMENT;
41import org.omg.CORBA.NO_RESOURCES;
42import org.omg.CORBA.NVList;
43import org.omg.CORBA.Object;
44import org.omg.CORBA.ParameterMode;
45import org.omg.CORBA.Policy;
46import org.omg.CORBA.SystemException;
47import org.omg.CORBA.TypeCode;
48import org.omg.CORBA.INTERNAL;
49import org.omg.CORBA.UserException;
50import org.omg.CORBA.portable.ApplicationException;
51import org.omg.CORBA.portable.InputStream;
52import com.sun.corba.se.spi.servicecontext.ServiceContexts;
53import com.sun.corba.se.spi.servicecontext.UnknownServiceContext;
54
55import org.omg.IOP.ServiceContext;
56import org.omg.IOP.ServiceContextHelper;
57import org.omg.IOP.TaggedProfile;
58import org.omg.IOP.TaggedProfileHelper;
59import org.omg.IOP.TaggedComponent;
60import org.omg.IOP.TaggedComponentHelper;
61import org.omg.IOP.TAG_INTERNET_IOP;
62import org.omg.Dynamic.Parameter;
63import org.omg.PortableInterceptor.ClientRequestInfo;
64import org.omg.PortableInterceptor.LOCATION_FORWARD;
65import org.omg.PortableInterceptor.SUCCESSFUL;
66import org.omg.PortableInterceptor.SYSTEM_EXCEPTION;
67import org.omg.PortableInterceptor.TRANSPORT_RETRY;
68import org.omg.PortableInterceptor.USER_EXCEPTION;
69
70import com.sun.corba.se.pept.protocol.MessageMediator;
71
72import com.sun.corba.se.spi.ior.IOR;
73import com.sun.corba.se.spi.ior.iiop.IIOPProfileTemplate;
74import com.sun.corba.se.spi.ior.iiop.GIOPVersion;
75import com.sun.corba.se.spi.orb.ORB;
76import com.sun.corba.se.spi.protocol.CorbaMessageMediator;
77import com.sun.corba.se.spi.protocol.RetryType;
78import com.sun.corba.se.spi.transport.CorbaContactInfo;
79import com.sun.corba.se.spi.transport.CorbaContactInfoList;
80import com.sun.corba.se.spi.transport.CorbaContactInfoListIterator;
81
82import com.sun.corba.se.impl.encoding.CDROutputStream;
83import com.sun.corba.se.impl.encoding.CDRInputStream_1_0;
84import com.sun.corba.se.impl.orbutil.ORBUtility;
85import com.sun.corba.se.impl.protocol.CorbaInvocationInfo;
86import com.sun.corba.se.impl.util.RepositoryId;
87
88/**
89 * Implementation of the ClientRequestInfo interface as specified in
90 * orbos/99-12-02 section 5.4.2.
91 */
92public final class ClientRequestInfoImpl
93    extends RequestInfoImpl
94    implements ClientRequestInfo
95{
96
97    // The available constants for startingPointCall
98    static final int CALL_SEND_REQUEST = 0;
99    static final int CALL_SEND_POLL = 1;
100
101    // The available constants for endingPointCall
102    static final int CALL_RECEIVE_REPLY = 0;
103    static final int CALL_RECEIVE_EXCEPTION = 1;
104    static final int CALL_RECEIVE_OTHER = 2;
105
106    //////////////////////////////////////////////////////////////////////
107    //
108    // NOTE: IF AN ATTRIBUTE IS ADDED, PLEASE UPDATE RESET();
109    //
110    //////////////////////////////////////////////////////////////////////
111
112    // The current retry request status.  True if this request is being
113    // retried and this info object is to be reused, or false otherwise.
114    private RetryType retryRequest;
115
116    // The number of times this info object has been (re)used.  This is
117    // incremented every time a request is retried, and decremented every
118    // time a request is complete.  When this reaches zero, the info object
119    // is popped from the ClientRequestInfoImpl ThreadLocal stack in the ORB.
120    private int entryCount = 0;
121
122    // The RequestImpl is set when the call is DII based.
123    // The DII query calls like ParameterList, ExceptionList,
124    // ContextList will be delegated to RequestImpl.
125    private org.omg.CORBA.Request request;
126
127    // Sources of client request information
128    private boolean diiInitiate;
129    private CorbaMessageMediator messageMediator;
130
131    // Cached information:
132    private org.omg.CORBA.Object cachedTargetObject;
133    private org.omg.CORBA.Object cachedEffectiveTargetObject;
134    private Parameter[] cachedArguments;
135    private TypeCode[] cachedExceptions;
136    private String[] cachedContexts;
137    private String[] cachedOperationContext;
138    private String cachedReceivedExceptionId;
139    private Any cachedResult;
140    private Any cachedReceivedException;
141    private TaggedProfile cachedEffectiveProfile;
142    // key = Integer, value = IOP.ServiceContext.
143    private HashMap cachedRequestServiceContexts;
144    // key = Integer, value = IOP.ServiceContext.
145    private HashMap cachedReplyServiceContexts;
146    // key = Integer, value = TaggedComponent
147    private HashMap cachedEffectiveComponents;
148
149
150    protected boolean piCurrentPushed;
151
152    //////////////////////////////////////////////////////////////////////
153    //
154    // NOTE: IF AN ATTRIBUTE IS ADDED, PLEASE UPDATE RESET();
155    //
156    //////////////////////////////////////////////////////////////////////
157
158    /**
159     * Reset the info object so that it can be reused for a retry,
160     * for example.
161     */
162    void reset() {
163        super.reset();
164
165        // Please keep these in the same order that they're declared above.
166
167        // 6763340
168        retryRequest = RetryType.NONE;
169
170        // Do not reset entryCount because we need to know when to pop this
171        // from the stack.
172
173        request = null;
174        diiInitiate = false;
175        messageMediator = null;
176
177        // Clear cached attributes:
178        cachedTargetObject = null;
179        cachedEffectiveTargetObject = null;
180        cachedArguments = null;
181        cachedExceptions = null;
182        cachedContexts = null;
183        cachedOperationContext = null;
184        cachedReceivedExceptionId = null;
185        cachedResult = null;
186        cachedReceivedException = null;
187        cachedEffectiveProfile = null;
188        cachedRequestServiceContexts = null;
189        cachedReplyServiceContexts = null;
190        cachedEffectiveComponents = null;
191
192        piCurrentPushed = false;
193
194        startingPointCall = CALL_SEND_REQUEST;
195        endingPointCall = CALL_RECEIVE_REPLY;
196
197    }
198
199    /*
200     **********************************************************************
201     * Access protection
202     **********************************************************************/
203
204    // Method IDs for all methods in ClientRequestInfo.  This allows for a
205    // convenient O(1) lookup for checkAccess().
206    protected static final int MID_TARGET                  = MID_RI_LAST + 1;
207    protected static final int MID_EFFECTIVE_TARGET        = MID_RI_LAST + 2;
208    protected static final int MID_EFFECTIVE_PROFILE       = MID_RI_LAST + 3;
209    protected static final int MID_RECEIVED_EXCEPTION      = MID_RI_LAST + 4;
210    protected static final int MID_RECEIVED_EXCEPTION_ID   = MID_RI_LAST + 5;
211    protected static final int MID_GET_EFFECTIVE_COMPONENT = MID_RI_LAST + 6;
212    protected static final int MID_GET_EFFECTIVE_COMPONENTS
213                                                           = MID_RI_LAST + 7;
214    protected static final int MID_GET_REQUEST_POLICY      = MID_RI_LAST + 8;
215    protected static final int MID_ADD_REQUEST_SERVICE_CONTEXT
216                                                           = MID_RI_LAST + 9;
217
218    // ClientRequestInfo validity table (see ptc/00-08-06 table 21-1).
219    // Note: These must be in the same order as specified in contants.
220    private static final boolean validCall[][] = {
221        // LEGEND:
222        // s_req = send_request     r_rep = receive_reply
223        // s_pol = send_poll        r_exc = receive_exception
224        //                          r_oth = receive_other
225        //
226        // A true value indicates call is valid at specified point.
227        // A false value indicates the call is invalid.
228        //
229        //
230        // NOTE: If the order or number of columns change, update
231        // checkAccess() accordingly.
232        //
233        //                              { s_req, s_pol, r_rep, r_exc, r_oth }
234        // RequestInfo methods:
235        /*request_id*/                  { true , true , true , true , true  },
236        /*operation*/                   { true , true , true , true , true  },
237        /*arguments*/                   { true , false, true , false, false },
238        /*exceptions*/                  { true , false, true , true , true  },
239        /*contexts*/                    { true , false, true , true , true  },
240        /*operation_context*/           { true , false, true , true , true  },
241        /*result*/                      { false, false, true , false, false },
242        /*response_expected*/           { true , true , true , true , true  },
243        /*sync_scope*/                  { true , false, true , true , true  },
244        /*reply_status*/                { false, false, true , true , true  },
245        /*forward_reference*/           { false, false, false, false, true  },
246        /*get_slot*/                    { true , true , true , true , true  },
247        /*get_request_service_context*/ { true , false, true , true , true  },
248        /*get_reply_service_context*/   { false, false, true , true , true  },
249        //
250        // ClientRequestInfo methods::
251        /*target*/                      { true , true , true , true , true  },
252        /*effective_target*/            { true , true , true , true , true  },
253        /*effective_profile*/           { true , true , true , true , true  },
254        /*received_exception*/          { false, false, false, true , false },
255        /*received_exception_id*/       { false, false, false, true , false },
256        /*get_effective_component*/     { true , false, true , true , true  },
257        /*get_effective_components*/    { true , false, true , true , true  },
258        /*get_request_policy*/          { true , false, true , true , true  },
259        /*add_request_service_context*/ { true , false, false, false, false }
260    };
261
262
263    /*
264     **********************************************************************
265     * Public ClientRequestInfo interfaces
266     **********************************************************************/
267
268    /**
269     * Creates a new ClientRequestInfo implementation.
270     * The constructor is package scope since no other package need create
271     * an instance of this class.
272     */
273    protected ClientRequestInfoImpl( ORB myORB ) {
274        super( myORB );
275        startingPointCall = CALL_SEND_REQUEST;
276        endingPointCall = CALL_RECEIVE_REPLY;
277    }
278
279    /**
280     * The object which the client called to perform the operation.
281     */
282    public org.omg.CORBA.Object target (){
283        // access is currently valid for all states:
284        //checkAccess( MID_TARGET );
285        if (cachedTargetObject == null) {
286            CorbaContactInfo corbaContactInfo = (CorbaContactInfo)
287                messageMediator.getContactInfo();
288            cachedTargetObject =
289                iorToObject(corbaContactInfo.getTargetIOR());
290        }
291        return cachedTargetObject;
292    }
293
294    /**
295     * The actual object on which the operation will be invoked.  If the
296     * reply_status is LOCATION_FORWARD, then on subsequent requests,
297     * effective_target will contain the forwarded IOR while target will
298     * remain unchanged.
299     */
300    public org.omg.CORBA.Object effective_target() {
301        // access is currently valid for all states:
302        //checkAccess( MID_EFFECTIVE_TARGET );
303
304        // Note: This is not necessarily the same as locatedIOR.
305        // Reason: See the way we handle COMM_FAILURES in
306        // ClientRequestDispatcher.createRequest, v1.32
307
308        if (cachedEffectiveTargetObject == null) {
309            CorbaContactInfo corbaContactInfo = (CorbaContactInfo)
310                messageMediator.getContactInfo();
311            // REVISIT - get through chain like getLocatedIOR helper below.
312            cachedEffectiveTargetObject =
313                iorToObject(corbaContactInfo.getEffectiveTargetIOR());
314        }
315        return cachedEffectiveTargetObject;
316    }
317
318    /**
319     * The profile that will be used to send the request.  If a location
320     * forward has occurred for this operation's object and that object's
321     * profile change accordingly, then this profile will be that located
322     * profile.
323     */
324    public TaggedProfile effective_profile (){
325        // access is currently valid for all states:
326        //checkAccess( MID_EFFECTIVE_PROFILE );
327
328        if( cachedEffectiveProfile == null ) {
329            CorbaContactInfo corbaContactInfo = (CorbaContactInfo)
330                messageMediator.getContactInfo();
331            cachedEffectiveProfile =
332                corbaContactInfo.getEffectiveProfile().getIOPProfile();
333        }
334
335        // Good citizen: In the interest of efficiency, we assume interceptors
336        // will not modify the returned TaggedProfile in any way so we need
337        // not make a deep copy of it.
338
339        return cachedEffectiveProfile;
340    }
341
342    /**
343     * Contains the exception to be returned to the client.
344     */
345    public Any received_exception (){
346        checkAccess( MID_RECEIVED_EXCEPTION );
347
348        if( cachedReceivedException == null ) {
349            cachedReceivedException = exceptionToAny( exception );
350        }
351
352        // Good citizen: In the interest of efficiency, we assume interceptors
353        // will not modify the returned Any in any way so we need
354        // not make a deep copy of it.
355
356        return cachedReceivedException;
357    }
358
359    /**
360     * The CORBA::RepositoryId of the exception to be returned to the client.
361     */
362    public String received_exception_id (){
363        checkAccess( MID_RECEIVED_EXCEPTION_ID );
364
365        if( cachedReceivedExceptionId == null ) {
366            String result = null;
367
368            if( exception == null ) {
369                // Note: exception should never be null here since we will
370                // throw a BAD_INV_ORDER if this is not called from
371                // receive_exception.
372                throw wrapper.exceptionWasNull() ;
373            } else if( exception instanceof SystemException ) {
374                String name = exception.getClass().getName();
375                result = ORBUtility.repositoryIdOf(name);
376            } else if( exception instanceof ApplicationException ) {
377                result = ((ApplicationException)exception).getId();
378            }
379
380            // _REVISIT_ We need to be able to handle a UserException in the
381            // DII case.  How do we extract the ID from a UserException?
382
383            cachedReceivedExceptionId = result;
384        }
385
386        return cachedReceivedExceptionId;
387    }
388
389    /**
390     * Returns the IOP::TaggedComponent with the given ID from the profile
391     * selected for this request.  IF there is more than one component for a
392     * given component ID, it is undefined which component this operation
393     * returns (get_effective_component should be called instead).
394     */
395    public TaggedComponent get_effective_component (int id){
396        checkAccess( MID_GET_EFFECTIVE_COMPONENT );
397
398        return get_effective_components( id )[0];
399    }
400
401    /**
402     * Returns all the tagged components with the given ID from the profile
403     * selected for this request.
404     */
405    public TaggedComponent[] get_effective_components (int id){
406        checkAccess( MID_GET_EFFECTIVE_COMPONENTS );
407        Integer integerId = new Integer( id );
408        TaggedComponent[] result = null;
409        boolean justCreatedCache = false;
410
411        if( cachedEffectiveComponents == null ) {
412            cachedEffectiveComponents = new HashMap();
413            justCreatedCache = true;
414        }
415        else {
416            // Look in cache:
417            result = (TaggedComponent[])cachedEffectiveComponents.get(
418                integerId );
419        }
420
421        // null could mean we cached null or not in cache.
422        if( (result == null) &&
423            (justCreatedCache ||
424            !cachedEffectiveComponents.containsKey( integerId ) ) )
425        {
426            // Not in cache.  Get it from the profile:
427            CorbaContactInfo corbaContactInfo = (CorbaContactInfo)
428                messageMediator.getContactInfo();
429            IIOPProfileTemplate ptemp =
430                (IIOPProfileTemplate)corbaContactInfo.getEffectiveProfile().
431                getTaggedProfileTemplate();
432            result = ptemp.getIOPComponents(myORB, id);
433            cachedEffectiveComponents.put( integerId, result );
434        }
435
436        // As per ptc/00-08-06, section 21.3.13.6., If not found, raise
437        // BAD_PARAM with minor code INVALID_COMPONENT_ID.
438        if( (result == null) || (result.length == 0) ) {
439            throw stdWrapper.invalidComponentId( integerId ) ;
440        }
441
442        // Good citizen: In the interest of efficiency, we will assume
443        // interceptors will not modify the returned TaggedCompoent[], or
444        // the TaggedComponents inside of it.  Otherwise, we would need to
445        // clone the array and make a deep copy of its contents.
446
447        return result;
448    }
449
450    /**
451     * Returns the given policy in effect for this operation.
452     */
453    public Policy get_request_policy (int type){
454        checkAccess( MID_GET_REQUEST_POLICY );
455        // _REVISIT_ Our ORB is not policy-based at this time.
456        throw wrapper.piOrbNotPolicyBased() ;
457    }
458
459    /**
460     * Allows interceptors to add service contexts to the request.
461     * <p>
462     * There is no declaration of the order of the service contexts.  They
463     * may or may not appear in the order they are added.
464     */
465    public void add_request_service_context (ServiceContext service_context,
466                                             boolean replace)
467    {
468        checkAccess( MID_ADD_REQUEST_SERVICE_CONTEXT );
469
470        if( cachedRequestServiceContexts == null ) {
471            cachedRequestServiceContexts = new HashMap();
472        }
473
474        addServiceContext( cachedRequestServiceContexts,
475                           messageMediator.getRequestServiceContexts(),
476                           service_context, replace );
477    }
478
479    // NOTE: When adding a method, be sure to:
480    // 1. Add a MID_* constant for that method
481    // 2. Call checkAccess at the start of the method
482    // 3. Define entries in the validCall[][] table for interception points.
483
484    /*
485     **********************************************************************
486     * Public RequestInfo interfaces
487     *
488     * These are implemented here because they have differing
489     * implementations depending on whether this is a client or a server
490     * request info object.
491     **********************************************************************/
492
493    /**
494     * See RequestInfoImpl for javadoc.
495     */
496    public int request_id (){
497        // access is currently valid for all states:
498        //checkAccess( MID_REQUEST_ID );
499        /*
500         * NOTE: The requestId in client interceptors is the same as the
501         * GIOP request id.  This works because both interceptors and
502         * request ids are scoped by the ORB on the client side.
503         */
504        return messageMediator.getRequestId();
505    }
506
507    /**
508     * See RequestInfoImpl for javadoc.
509     */
510    public String operation (){
511        // access is currently valid for all states:
512        //checkAccess( MID_OPERATION );
513        return messageMediator.getOperationName();
514    }
515
516    /**
517     * See RequestInfoImpl for javadoc.
518     */
519    public Parameter[] arguments (){
520        checkAccess( MID_ARGUMENTS );
521
522        if( cachedArguments == null ) {
523            if( request == null ) {
524                throw stdWrapper.piOperationNotSupported1() ;
525            }
526
527            // If it is DII request then get the arguments from the DII req
528            // and convert that into parameters.
529            cachedArguments = nvListToParameterArray( request.arguments() );
530        }
531
532        // Good citizen: In the interest of efficiency, we assume
533        // interceptors will be "good citizens" in that they will not
534        // modify the contents of the Parameter[] array.  We also assume
535        // they will not change the values of the containing Anys.
536
537        return cachedArguments;
538    }
539
540    /**
541     * See RequestInfoImpl for javadoc.
542     */
543    public TypeCode[] exceptions (){
544        checkAccess( MID_EXCEPTIONS );
545
546        if( cachedExceptions == null ) {
547            if( request == null ) {
548               throw stdWrapper.piOperationNotSupported2() ;
549            }
550
551            // Get the list of exceptions from DII request data, If there are
552            // no exceptions raised then this method will return null.
553            ExceptionList excList = request.exceptions( );
554            int count = excList.count();
555            TypeCode[] excTCList = new TypeCode[count];
556            try {
557                for( int i = 0; i < count; i++ ) {
558                    excTCList[i] = excList.item( i );
559                }
560            } catch( Exception e ) {
561                throw wrapper.exceptionInExceptions( e ) ;
562            }
563
564            cachedExceptions = excTCList;
565        }
566
567        // Good citizen: In the interest of efficiency, we assume
568        // interceptors will be "good citizens" in that they will not
569        // modify the contents of the TypeCode[] array.  We also assume
570        // they will not change the values of the containing TypeCodes.
571
572        return cachedExceptions;
573    }
574
575    /**
576     * See RequestInfoImpl for javadoc.
577     */
578    public String[] contexts (){
579        checkAccess( MID_CONTEXTS );
580
581        if( cachedContexts == null ) {
582            if( request == null ) {
583                throw stdWrapper.piOperationNotSupported3() ;
584            }
585
586            // Get the list of contexts from DII request data, If there are
587            // no contexts then this method will return null.
588            ContextList ctxList = request.contexts( );
589            int count = ctxList.count();
590            String[] ctxListToReturn = new String[count];
591            try {
592                for( int i = 0; i < count; i++ ) {
593                    ctxListToReturn[i] = ctxList.item( i );
594                }
595            } catch( Exception e ) {
596                throw wrapper.exceptionInContexts( e ) ;
597            }
598
599            cachedContexts = ctxListToReturn;
600        }
601
602        // Good citizen: In the interest of efficiency, we assume
603        // interceptors will be "good citizens" in that they will not
604        // modify the contents of the String[] array.
605
606        return cachedContexts;
607    }
608
609    /**
610     * See RequestInfoImpl for javadoc.
611     */
612    public String[] operation_context (){
613        checkAccess( MID_OPERATION_CONTEXT );
614
615        if( cachedOperationContext == null ) {
616            if( request == null ) {
617                throw stdWrapper.piOperationNotSupported4() ;
618            }
619
620            // Get the list of contexts from DII request data, If there are
621            // no contexts then this method will return null.
622            Context ctx = request.ctx( );
623            // _REVISIT_ The API for get_values is not compliant with the spec,
624            // Revisit this code once it's fixed.
625            // _REVISIT_ Our ORB doesn't support Operation Context, This code
626            // will not be excerscised until it's supported.
627            // The first parameter in get_values is the start_scope which
628            // if blank makes it as a global scope.
629            // The second parameter is op_flags which is set to RESTRICT_SCOPE
630            // As there is only one defined in the spec.
631            // The Third param is the pattern which is '*' requiring it to
632            // get all the contexts.
633            NVList nvList = ctx.get_values( "", CTX_RESTRICT_SCOPE.value,"*" );
634            String[] context = new String[(nvList.count() * 2) ];
635            if( ( nvList != null ) &&( nvList.count() != 0 ) ) {
636                // The String[] array will contain Name and Value for each
637                // context and hence double the size in the array.
638                int index = 0;
639                for( int i = 0; i < nvList.count(); i++ ) {
640                    NamedValue nv;
641                    try {
642                        nv = nvList.item( i );
643                    }
644                    catch (Exception e ) {
645                        return (String[]) null;
646                    }
647                    context[index] = nv.name();
648                    index++;
649                    context[index] = nv.value().extract_string();
650                    index++;
651                }
652            }
653
654            cachedOperationContext = context;
655        }
656
657        // Good citizen: In the interest of efficiency, we assume
658        // interceptors will be "good citizens" in that they will not
659        // modify the contents of the String[] array.
660
661        return cachedOperationContext;
662    }
663
664    /**
665     * See RequestInfoImpl for javadoc.
666     */
667    public Any result (){
668        checkAccess( MID_RESULT );
669
670        if( cachedResult == null ) {
671            if( request == null ) {
672                throw stdWrapper.piOperationNotSupported5() ;
673            }
674            // Get the result from the DII request data.
675            NamedValue nvResult = request.result( );
676
677            if( nvResult == null ) {
678                throw wrapper.piDiiResultIsNull() ;
679            }
680
681            cachedResult = nvResult.value();
682        }
683
684        // Good citizen: In the interest of efficiency, we assume that
685        // interceptors will not modify the contents of the result Any.
686        // Otherwise, we would need to create a deep copy of the Any.
687
688        return cachedResult;
689    }
690
691    /**
692     * See RequestInfoImpl for javadoc.
693     */
694    public boolean response_expected (){
695        // access is currently valid for all states:
696        //checkAccess( MID_RESPONSE_EXPECTED );
697        return ! messageMediator.isOneWay();
698    }
699
700    /**
701     * See RequestInfoImpl for javadoc.
702     */
703    public Object forward_reference (){
704        checkAccess( MID_FORWARD_REFERENCE );
705        // Check to make sure we are in LOCATION_FORWARD
706        // state as per ptc/00-08-06, table 21-1
707        // footnote 2.
708        if( replyStatus != LOCATION_FORWARD.value ) {
709            throw stdWrapper.invalidPiCall1() ;
710        }
711
712        // Do not cache this value since if an interceptor raises
713        // forward request then the next interceptor in the
714        // list should see the new value.
715        IOR ior = getLocatedIOR();
716        return iorToObject(ior);
717    }
718
719    private IOR getLocatedIOR()
720    {
721        IOR ior;
722        CorbaContactInfoList contactInfoList = (CorbaContactInfoList)
723            messageMediator.getContactInfo().getContactInfoList();
724        ior = contactInfoList.getEffectiveTargetIOR();
725        return ior;
726    }
727
728    protected void setLocatedIOR(IOR ior)
729    {
730        ORB orb = (ORB) messageMediator.getBroker();
731
732        CorbaContactInfoListIterator iterator = (CorbaContactInfoListIterator)
733            ((CorbaInvocationInfo)orb.getInvocationInfo())
734            .getContactInfoListIterator();
735
736        // REVISIT - this most likely causes reportRedirect to happen twice.
737        // Once here and once inside the request dispatcher.
738        iterator.reportRedirect(
739            (CorbaContactInfo)messageMediator.getContactInfo(),
740            ior);
741    }
742
743    /**
744     * See RequestInfoImpl for javadoc.
745     */
746    public org.omg.IOP.ServiceContext get_request_service_context( int id ) {
747        checkAccess( MID_GET_REQUEST_SERVICE_CONTEXT );
748
749        if( cachedRequestServiceContexts == null ) {
750            cachedRequestServiceContexts = new HashMap();
751        }
752
753        return  getServiceContext(cachedRequestServiceContexts,
754                                  messageMediator.getRequestServiceContexts(),
755                                  id);
756    }
757
758    /**
759     * does not contain an etry for that ID, BAD_PARAM with a minor code of
760     * TBD_BP is raised.
761     */
762    public org.omg.IOP.ServiceContext get_reply_service_context( int id ) {
763        checkAccess( MID_GET_REPLY_SERVICE_CONTEXT );
764
765        if( cachedReplyServiceContexts == null ) {
766            cachedReplyServiceContexts = new HashMap();
767        }
768
769        // In the event this is called from a oneway, we will have no
770        // response object.
771        //
772        // In the event this is called after a IIOPConnection.purgeCalls,
773        // we will have a response object, but that object will
774        // not contain a header (which would hold the service context
775        // container).  See bug 4624102.
776        //
777        // REVISIT: this is the only thing used
778        // from response at this time.  However, a more general solution
779        // would avoid accessing other parts of response's header.
780        //
781        // Instead of throwing a NullPointer, we will
782        // "gracefully" handle these with a BAD_PARAM with minor code 25.
783
784        try {
785            ServiceContexts serviceContexts =
786                messageMediator.getReplyServiceContexts();
787            if (serviceContexts == null) {
788                throw new NullPointerException();
789            }
790            return getServiceContext(cachedReplyServiceContexts,
791                                     serviceContexts, id);
792        } catch (NullPointerException e) {
793            // REVISIT how this is programmed - not what it does.
794            // See purge calls test.  The waiter is woken up by the
795            // call to purge calls - but there is no reply containing
796            // service contexts.
797            throw stdWrapper.invalidServiceContextId( e ) ;
798        }
799    }
800
801    //
802    // REVISIT
803    // Override RequestInfoImpl connection to work in framework.
804    //
805
806    public com.sun.corba.se.spi.legacy.connection.Connection connection()
807    {
808        return (com.sun.corba.se.spi.legacy.connection.Connection)
809            messageMediator.getConnection();
810    }
811
812
813
814    /*
815     **********************************************************************
816     * Package-scope interfaces
817     **********************************************************************/
818
819    protected void setInfo(MessageMediator messageMediator)
820    {
821        this.messageMediator = (CorbaMessageMediator)messageMediator;
822        // REVISIT - so mediator can handle DII in subcontract.
823        this.messageMediator.setDIIInfo(request);
824    }
825
826    /**
827     * Set or reset the retry request flag.
828     */
829    void setRetryRequest( RetryType retryRequest ) {
830        this.retryRequest = retryRequest;
831    }
832
833    /**
834     * Retrieve the current retry request status.
835     */
836    RetryType getRetryRequest() {
837        // 6763340
838        return this.retryRequest;
839    }
840
841    /**
842     * Increases the entry count by 1.
843     */
844    void incrementEntryCount() {
845        this.entryCount++;
846    }
847
848    /**
849     * Decreases the entry count by 1.
850     */
851    void decrementEntryCount() {
852        this.entryCount--;
853    }
854
855    /**
856     * Retrieve the current entry count
857     */
858    int getEntryCount() {
859        return this.entryCount;
860    }
861
862    /**
863     * Overridden from RequestInfoImpl.  Calls the super class, then
864     * sets the ending point call depending on the reply status.
865     */
866    protected void setReplyStatus( short replyStatus ) {
867        super.setReplyStatus( replyStatus );
868        switch( replyStatus ) {
869        case SUCCESSFUL.value:
870            endingPointCall = CALL_RECEIVE_REPLY;
871            break;
872        case SYSTEM_EXCEPTION.value:
873        case USER_EXCEPTION.value:
874            endingPointCall = CALL_RECEIVE_EXCEPTION;
875            break;
876        case LOCATION_FORWARD.value:
877        case TRANSPORT_RETRY.value:
878            endingPointCall = CALL_RECEIVE_OTHER;
879            break;
880        }
881    }
882
883    /**
884     * Sets DII request object in the RequestInfoObject.
885     */
886    protected void setDIIRequest(org.omg.CORBA.Request req) {
887         request = req;
888    }
889
890    /**
891     * Keeps track of whether initiate was called for a DII request.  The ORB
892     * needs to know this so it knows whether to ignore a second call to
893     * initiateClientPIRequest or not.
894     */
895    protected void setDIIInitiate( boolean diiInitiate ) {
896        this.diiInitiate = diiInitiate;
897    }
898
899    /**
900     * See comment for setDIIInitiate
901     */
902    protected boolean isDIIInitiate() {
903        return this.diiInitiate;
904    }
905
906    /**
907     * The PICurrent stack should only be popped if it was pushed.
908     * This is generally the case.  But exceptions which occur
909     * after the stub's entry to _request but before the push
910     * end up in _releaseReply which will try to pop unless told not to.
911     */
912    protected void setPICurrentPushed( boolean piCurrentPushed ) {
913        this.piCurrentPushed = piCurrentPushed;
914    }
915
916    protected boolean isPICurrentPushed() {
917        return this.piCurrentPushed;
918    }
919
920    /**
921     * Overridden from RequestInfoImpl.
922     */
923    protected void setException( Exception exception ) {
924        super.setException( exception );
925
926        // Clear cached values:
927        cachedReceivedException = null;
928        cachedReceivedExceptionId = null;
929    }
930
931    protected boolean getIsOneWay() {
932        return ! response_expected();
933    }
934
935    /**
936     * See description for RequestInfoImpl.checkAccess
937     */
938    protected void checkAccess( int methodID )
939        throws BAD_INV_ORDER
940    {
941        // Make sure currentPoint matches the appropriate index in the
942        // validCall table:
943        int validCallIndex = 0;
944        switch( currentExecutionPoint ) {
945        case EXECUTION_POINT_STARTING:
946            switch( startingPointCall ) {
947            case CALL_SEND_REQUEST:
948                validCallIndex = 0;
949                break;
950            case CALL_SEND_POLL:
951                validCallIndex = 1;
952                break;
953            }
954            break;
955        case EXECUTION_POINT_ENDING:
956            switch( endingPointCall ) {
957            case CALL_RECEIVE_REPLY:
958                validCallIndex = 2;
959                break;
960            case CALL_RECEIVE_EXCEPTION:
961                validCallIndex = 3;
962                break;
963            case CALL_RECEIVE_OTHER:
964                validCallIndex = 4;
965                break;
966            }
967            break;
968        }
969
970        // Check the validCall table:
971        if( !validCall[methodID][validCallIndex] ) {
972            throw stdWrapper.invalidPiCall2() ;
973        }
974    }
975
976}
977
978// End of file.
979