| /* |
| * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved. |
| * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
| * |
| * This code is free software; you can redistribute it and/or modify it |
| * under the terms of the GNU General Public License version 2 only, as |
| * published by the Free Software Foundation. Oracle designates this |
| * particular file as subject to the "Classpath" exception as provided |
| * by Oracle in the LICENSE file that accompanied this code. |
| * |
| * This code is distributed in the hope that it will be useful, but WITHOUT |
| * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
| * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
| * version 2 for more details (a copy is included in the LICENSE file that |
| * accompanied this code). |
| * |
| * You should have received a copy of the GNU General Public License version |
| * 2 along with this work; if not, write to the Free Software Foundation, |
| * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
| * |
| * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
| * or visit www.oracle.com if you need additional information or have any |
| * questions. |
| */ |
| |
| package com.sun.corba.se.impl.interceptors; |
| |
| import java.util.HashMap ; |
| |
| import org.omg.CORBA.Any; |
| import org.omg.CORBA.BAD_INV_ORDER; |
| import org.omg.CORBA.BAD_PARAM; |
| import org.omg.CORBA.CompletionStatus; |
| import org.omg.CORBA.Context; |
| import org.omg.CORBA.ContextList; |
| import org.omg.CORBA.CTX_RESTRICT_SCOPE; |
| import org.omg.CORBA.ExceptionList; |
| import org.omg.CORBA.LocalObject; |
| import org.omg.CORBA.NamedValue; |
| import org.omg.CORBA.NO_IMPLEMENT; |
| import org.omg.CORBA.NO_RESOURCES; |
| import org.omg.CORBA.NVList; |
| import org.omg.CORBA.Object; |
| import org.omg.CORBA.ParameterMode; |
| import org.omg.CORBA.Policy; |
| import org.omg.CORBA.SystemException; |
| import org.omg.CORBA.TypeCode; |
| import org.omg.CORBA.INTERNAL; |
| import org.omg.CORBA.UserException; |
| import org.omg.CORBA.portable.ApplicationException; |
| import org.omg.CORBA.portable.InputStream; |
| import com.sun.corba.se.spi.servicecontext.ServiceContexts; |
| import com.sun.corba.se.spi.servicecontext.UnknownServiceContext; |
| |
| import org.omg.IOP.ServiceContext; |
| import org.omg.IOP.ServiceContextHelper; |
| import org.omg.IOP.TaggedProfile; |
| import org.omg.IOP.TaggedProfileHelper; |
| import org.omg.IOP.TaggedComponent; |
| import org.omg.IOP.TaggedComponentHelper; |
| import org.omg.IOP.TAG_INTERNET_IOP; |
| import org.omg.Dynamic.Parameter; |
| import org.omg.PortableInterceptor.ClientRequestInfo; |
| import org.omg.PortableInterceptor.LOCATION_FORWARD; |
| import org.omg.PortableInterceptor.SUCCESSFUL; |
| import org.omg.PortableInterceptor.SYSTEM_EXCEPTION; |
| import org.omg.PortableInterceptor.TRANSPORT_RETRY; |
| import org.omg.PortableInterceptor.USER_EXCEPTION; |
| |
| import com.sun.corba.se.pept.protocol.MessageMediator; |
| |
| import com.sun.corba.se.spi.ior.IOR; |
| import com.sun.corba.se.spi.ior.iiop.IIOPProfileTemplate; |
| import com.sun.corba.se.spi.ior.iiop.GIOPVersion; |
| import com.sun.corba.se.spi.orb.ORB; |
| import com.sun.corba.se.spi.protocol.CorbaMessageMediator; |
| import com.sun.corba.se.spi.protocol.RetryType; |
| import com.sun.corba.se.spi.transport.CorbaContactInfo; |
| import com.sun.corba.se.spi.transport.CorbaContactInfoList; |
| import com.sun.corba.se.spi.transport.CorbaContactInfoListIterator; |
| |
| import com.sun.corba.se.impl.encoding.CDROutputStream; |
| import com.sun.corba.se.impl.encoding.CDRInputStream_1_0; |
| import com.sun.corba.se.impl.orbutil.ORBUtility; |
| import com.sun.corba.se.impl.protocol.CorbaInvocationInfo; |
| import com.sun.corba.se.impl.util.RepositoryId; |
| |
| /** |
| * Implementation of the ClientRequestInfo interface as specified in |
| * orbos/99-12-02 section 5.4.2. |
| */ |
| public final class ClientRequestInfoImpl |
| extends RequestInfoImpl |
| implements ClientRequestInfo |
| { |
| |
| // The available constants for startingPointCall |
| static final int CALL_SEND_REQUEST = 0; |
| static final int CALL_SEND_POLL = 1; |
| |
| // The available constants for endingPointCall |
| static final int CALL_RECEIVE_REPLY = 0; |
| static final int CALL_RECEIVE_EXCEPTION = 1; |
| static final int CALL_RECEIVE_OTHER = 2; |
| |
| ////////////////////////////////////////////////////////////////////// |
| // |
| // NOTE: IF AN ATTRIBUTE IS ADDED, PLEASE UPDATE RESET(); |
| // |
| ////////////////////////////////////////////////////////////////////// |
| |
| // The current retry request status. True if this request is being |
| // retried and this info object is to be reused, or false otherwise. |
| private RetryType retryRequest; |
| |
| // The number of times this info object has been (re)used. This is |
| // incremented every time a request is retried, and decremented every |
| // time a request is complete. When this reaches zero, the info object |
| // is popped from the ClientRequestInfoImpl ThreadLocal stack in the ORB. |
| private int entryCount = 0; |
| |
| // The RequestImpl is set when the call is DII based. |
| // The DII query calls like ParameterList, ExceptionList, |
| // ContextList will be delegated to RequestImpl. |
| private org.omg.CORBA.Request request; |
| |
| // Sources of client request information |
| private boolean diiInitiate; |
| private CorbaMessageMediator messageMediator; |
| |
| // Cached information: |
| private org.omg.CORBA.Object cachedTargetObject; |
| private org.omg.CORBA.Object cachedEffectiveTargetObject; |
| private Parameter[] cachedArguments; |
| private TypeCode[] cachedExceptions; |
| private String[] cachedContexts; |
| private String[] cachedOperationContext; |
| private String cachedReceivedExceptionId; |
| private Any cachedResult; |
| private Any cachedReceivedException; |
| private TaggedProfile cachedEffectiveProfile; |
| // key = Integer, value = IOP.ServiceContext. |
| private HashMap cachedRequestServiceContexts; |
| // key = Integer, value = IOP.ServiceContext. |
| private HashMap cachedReplyServiceContexts; |
| // key = Integer, value = TaggedComponent |
| private HashMap cachedEffectiveComponents; |
| |
| |
| protected boolean piCurrentPushed; |
| |
| ////////////////////////////////////////////////////////////////////// |
| // |
| // NOTE: IF AN ATTRIBUTE IS ADDED, PLEASE UPDATE RESET(); |
| // |
| ////////////////////////////////////////////////////////////////////// |
| |
| /** |
| * Reset the info object so that it can be reused for a retry, |
| * for example. |
| */ |
| void reset() { |
| super.reset(); |
| |
| // Please keep these in the same order that they're declared above. |
| |
| // 6763340 |
| retryRequest = RetryType.NONE; |
| |
| // Do not reset entryCount because we need to know when to pop this |
| // from the stack. |
| |
| request = null; |
| diiInitiate = false; |
| messageMediator = null; |
| |
| // Clear cached attributes: |
| cachedTargetObject = null; |
| cachedEffectiveTargetObject = null; |
| cachedArguments = null; |
| cachedExceptions = null; |
| cachedContexts = null; |
| cachedOperationContext = null; |
| cachedReceivedExceptionId = null; |
| cachedResult = null; |
| cachedReceivedException = null; |
| cachedEffectiveProfile = null; |
| cachedRequestServiceContexts = null; |
| cachedReplyServiceContexts = null; |
| cachedEffectiveComponents = null; |
| |
| piCurrentPushed = false; |
| |
| startingPointCall = CALL_SEND_REQUEST; |
| endingPointCall = CALL_RECEIVE_REPLY; |
| |
| } |
| |
| /* |
| ********************************************************************** |
| * Access protection |
| **********************************************************************/ |
| |
| // Method IDs for all methods in ClientRequestInfo. This allows for a |
| // convenient O(1) lookup for checkAccess(). |
| protected static final int MID_TARGET = MID_RI_LAST + 1; |
| protected static final int MID_EFFECTIVE_TARGET = MID_RI_LAST + 2; |
| protected static final int MID_EFFECTIVE_PROFILE = MID_RI_LAST + 3; |
| protected static final int MID_RECEIVED_EXCEPTION = MID_RI_LAST + 4; |
| protected static final int MID_RECEIVED_EXCEPTION_ID = MID_RI_LAST + 5; |
| protected static final int MID_GET_EFFECTIVE_COMPONENT = MID_RI_LAST + 6; |
| protected static final int MID_GET_EFFECTIVE_COMPONENTS |
| = MID_RI_LAST + 7; |
| protected static final int MID_GET_REQUEST_POLICY = MID_RI_LAST + 8; |
| protected static final int MID_ADD_REQUEST_SERVICE_CONTEXT |
| = MID_RI_LAST + 9; |
| |
| // ClientRequestInfo validity table (see ptc/00-08-06 table 21-1). |
| // Note: These must be in the same order as specified in contants. |
| private static final boolean validCall[][] = { |
| // LEGEND: |
| // s_req = send_request r_rep = receive_reply |
| // s_pol = send_poll r_exc = receive_exception |
| // r_oth = receive_other |
| // |
| // A true value indicates call is valid at specified point. |
| // A false value indicates the call is invalid. |
| // |
| // |
| // NOTE: If the order or number of columns change, update |
| // checkAccess() accordingly. |
| // |
| // { s_req, s_pol, r_rep, r_exc, r_oth } |
| // RequestInfo methods: |
| /*request_id*/ { true , true , true , true , true }, |
| /*operation*/ { true , true , true , true , true }, |
| /*arguments*/ { true , false, true , false, false }, |
| /*exceptions*/ { true , false, true , true , true }, |
| /*contexts*/ { true , false, true , true , true }, |
| /*operation_context*/ { true , false, true , true , true }, |
| /*result*/ { false, false, true , false, false }, |
| /*response_expected*/ { true , true , true , true , true }, |
| /*sync_scope*/ { true , false, true , true , true }, |
| /*reply_status*/ { false, false, true , true , true }, |
| /*forward_reference*/ { false, false, false, false, true }, |
| /*get_slot*/ { true , true , true , true , true }, |
| /*get_request_service_context*/ { true , false, true , true , true }, |
| /*get_reply_service_context*/ { false, false, true , true , true }, |
| // |
| // ClientRequestInfo methods:: |
| /*target*/ { true , true , true , true , true }, |
| /*effective_target*/ { true , true , true , true , true }, |
| /*effective_profile*/ { true , true , true , true , true }, |
| /*received_exception*/ { false, false, false, true , false }, |
| /*received_exception_id*/ { false, false, false, true , false }, |
| /*get_effective_component*/ { true , false, true , true , true }, |
| /*get_effective_components*/ { true , false, true , true , true }, |
| /*get_request_policy*/ { true , false, true , true , true }, |
| /*add_request_service_context*/ { true , false, false, false, false } |
| }; |
| |
| |
| /* |
| ********************************************************************** |
| * Public ClientRequestInfo interfaces |
| **********************************************************************/ |
| |
| /** |
| * Creates a new ClientRequestInfo implementation. |
| * The constructor is package scope since no other package need create |
| * an instance of this class. |
| */ |
| protected ClientRequestInfoImpl( ORB myORB ) { |
| super( myORB ); |
| startingPointCall = CALL_SEND_REQUEST; |
| endingPointCall = CALL_RECEIVE_REPLY; |
| } |
| |
| /** |
| * The object which the client called to perform the operation. |
| */ |
| public org.omg.CORBA.Object target (){ |
| // access is currently valid for all states: |
| //checkAccess( MID_TARGET ); |
| if (cachedTargetObject == null) { |
| CorbaContactInfo corbaContactInfo = (CorbaContactInfo) |
| messageMediator.getContactInfo(); |
| cachedTargetObject = |
| iorToObject(corbaContactInfo.getTargetIOR()); |
| } |
| return cachedTargetObject; |
| } |
| |
| /** |
| * The actual object on which the operation will be invoked. If the |
| * reply_status is LOCATION_FORWARD, then on subsequent requests, |
| * effective_target will contain the forwarded IOR while target will |
| * remain unchanged. |
| */ |
| public org.omg.CORBA.Object effective_target() { |
| // access is currently valid for all states: |
| //checkAccess( MID_EFFECTIVE_TARGET ); |
| |
| // Note: This is not necessarily the same as locatedIOR. |
| // Reason: See the way we handle COMM_FAILURES in |
| // ClientRequestDispatcher.createRequest, v1.32 |
| |
| if (cachedEffectiveTargetObject == null) { |
| CorbaContactInfo corbaContactInfo = (CorbaContactInfo) |
| messageMediator.getContactInfo(); |
| // REVISIT - get through chain like getLocatedIOR helper below. |
| cachedEffectiveTargetObject = |
| iorToObject(corbaContactInfo.getEffectiveTargetIOR()); |
| } |
| return cachedEffectiveTargetObject; |
| } |
| |
| /** |
| * The profile that will be used to send the request. If a location |
| * forward has occurred for this operation's object and that object's |
| * profile change accordingly, then this profile will be that located |
| * profile. |
| */ |
| public TaggedProfile effective_profile (){ |
| // access is currently valid for all states: |
| //checkAccess( MID_EFFECTIVE_PROFILE ); |
| |
| if( cachedEffectiveProfile == null ) { |
| CorbaContactInfo corbaContactInfo = (CorbaContactInfo) |
| messageMediator.getContactInfo(); |
| cachedEffectiveProfile = |
| corbaContactInfo.getEffectiveProfile().getIOPProfile(); |
| } |
| |
| // Good citizen: In the interest of efficiency, we assume interceptors |
| // will not modify the returned TaggedProfile in any way so we need |
| // not make a deep copy of it. |
| |
| return cachedEffectiveProfile; |
| } |
| |
| /** |
| * Contains the exception to be returned to the client. |
| */ |
| public Any received_exception (){ |
| checkAccess( MID_RECEIVED_EXCEPTION ); |
| |
| if( cachedReceivedException == null ) { |
| cachedReceivedException = exceptionToAny( exception ); |
| } |
| |
| // Good citizen: In the interest of efficiency, we assume interceptors |
| // will not modify the returned Any in any way so we need |
| // not make a deep copy of it. |
| |
| return cachedReceivedException; |
| } |
| |
| /** |
| * The CORBA::RepositoryId of the exception to be returned to the client. |
| */ |
| public String received_exception_id (){ |
| checkAccess( MID_RECEIVED_EXCEPTION_ID ); |
| |
| if( cachedReceivedExceptionId == null ) { |
| String result = null; |
| |
| if( exception == null ) { |
| // Note: exception should never be null here since we will |
| // throw a BAD_INV_ORDER if this is not called from |
| // receive_exception. |
| throw wrapper.exceptionWasNull() ; |
| } else if( exception instanceof SystemException ) { |
| String name = exception.getClass().getName(); |
| result = ORBUtility.repositoryIdOf(name); |
| } else if( exception instanceof ApplicationException ) { |
| result = ((ApplicationException)exception).getId(); |
| } |
| |
| // _REVISIT_ We need to be able to handle a UserException in the |
| // DII case. How do we extract the ID from a UserException? |
| |
| cachedReceivedExceptionId = result; |
| } |
| |
| return cachedReceivedExceptionId; |
| } |
| |
| /** |
| * Returns the IOP::TaggedComponent with the given ID from the profile |
| * selected for this request. IF there is more than one component for a |
| * given component ID, it is undefined which component this operation |
| * returns (get_effective_component should be called instead). |
| */ |
| public TaggedComponent get_effective_component (int id){ |
| checkAccess( MID_GET_EFFECTIVE_COMPONENT ); |
| |
| return get_effective_components( id )[0]; |
| } |
| |
| /** |
| * Returns all the tagged components with the given ID from the profile |
| * selected for this request. |
| */ |
| public TaggedComponent[] get_effective_components (int id){ |
| checkAccess( MID_GET_EFFECTIVE_COMPONENTS ); |
| Integer integerId = new Integer( id ); |
| TaggedComponent[] result = null; |
| boolean justCreatedCache = false; |
| |
| if( cachedEffectiveComponents == null ) { |
| cachedEffectiveComponents = new HashMap(); |
| justCreatedCache = true; |
| } |
| else { |
| // Look in cache: |
| result = (TaggedComponent[])cachedEffectiveComponents.get( |
| integerId ); |
| } |
| |
| // null could mean we cached null or not in cache. |
| if( (result == null) && |
| (justCreatedCache || |
| !cachedEffectiveComponents.containsKey( integerId ) ) ) |
| { |
| // Not in cache. Get it from the profile: |
| CorbaContactInfo corbaContactInfo = (CorbaContactInfo) |
| messageMediator.getContactInfo(); |
| IIOPProfileTemplate ptemp = |
| (IIOPProfileTemplate)corbaContactInfo.getEffectiveProfile(). |
| getTaggedProfileTemplate(); |
| result = ptemp.getIOPComponents(myORB, id); |
| cachedEffectiveComponents.put( integerId, result ); |
| } |
| |
| // As per ptc/00-08-06, section 21.3.13.6., If not found, raise |
| // BAD_PARAM with minor code INVALID_COMPONENT_ID. |
| if( (result == null) || (result.length == 0) ) { |
| throw stdWrapper.invalidComponentId( integerId ) ; |
| } |
| |
| // Good citizen: In the interest of efficiency, we will assume |
| // interceptors will not modify the returned TaggedCompoent[], or |
| // the TaggedComponents inside of it. Otherwise, we would need to |
| // clone the array and make a deep copy of its contents. |
| |
| return result; |
| } |
| |
| /** |
| * Returns the given policy in effect for this operation. |
| */ |
| public Policy get_request_policy (int type){ |
| checkAccess( MID_GET_REQUEST_POLICY ); |
| // _REVISIT_ Our ORB is not policy-based at this time. |
| throw wrapper.piOrbNotPolicyBased() ; |
| } |
| |
| /** |
| * Allows interceptors to add service contexts to the request. |
| * <p> |
| * There is no declaration of the order of the service contexts. They |
| * may or may not appear in the order they are added. |
| */ |
| public void add_request_service_context (ServiceContext service_context, |
| boolean replace) |
| { |
| checkAccess( MID_ADD_REQUEST_SERVICE_CONTEXT ); |
| |
| if( cachedRequestServiceContexts == null ) { |
| cachedRequestServiceContexts = new HashMap(); |
| } |
| |
| addServiceContext( cachedRequestServiceContexts, |
| messageMediator.getRequestServiceContexts(), |
| service_context, replace ); |
| } |
| |
| // NOTE: When adding a method, be sure to: |
| // 1. Add a MID_* constant for that method |
| // 2. Call checkAccess at the start of the method |
| // 3. Define entries in the validCall[][] table for interception points. |
| |
| /* |
| ********************************************************************** |
| * Public RequestInfo interfaces |
| * |
| * These are implemented here because they have differing |
| * implementations depending on whether this is a client or a server |
| * request info object. |
| **********************************************************************/ |
| |
| /** |
| * See RequestInfoImpl for javadoc. |
| */ |
| public int request_id (){ |
| // access is currently valid for all states: |
| //checkAccess( MID_REQUEST_ID ); |
| /* |
| * NOTE: The requestId in client interceptors is the same as the |
| * GIOP request id. This works because both interceptors and |
| * request ids are scoped by the ORB on the client side. |
| */ |
| return messageMediator.getRequestId(); |
| } |
| |
| /** |
| * See RequestInfoImpl for javadoc. |
| */ |
| public String operation (){ |
| // access is currently valid for all states: |
| //checkAccess( MID_OPERATION ); |
| return messageMediator.getOperationName(); |
| } |
| |
| /** |
| * See RequestInfoImpl for javadoc. |
| */ |
| public Parameter[] arguments (){ |
| checkAccess( MID_ARGUMENTS ); |
| |
| if( cachedArguments == null ) { |
| if( request == null ) { |
| throw stdWrapper.piOperationNotSupported1() ; |
| } |
| |
| // If it is DII request then get the arguments from the DII req |
| // and convert that into parameters. |
| cachedArguments = nvListToParameterArray( request.arguments() ); |
| } |
| |
| // Good citizen: In the interest of efficiency, we assume |
| // interceptors will be "good citizens" in that they will not |
| // modify the contents of the Parameter[] array. We also assume |
| // they will not change the values of the containing Anys. |
| |
| return cachedArguments; |
| } |
| |
| /** |
| * See RequestInfoImpl for javadoc. |
| */ |
| public TypeCode[] exceptions (){ |
| checkAccess( MID_EXCEPTIONS ); |
| |
| if( cachedExceptions == null ) { |
| if( request == null ) { |
| throw stdWrapper.piOperationNotSupported2() ; |
| } |
| |
| // Get the list of exceptions from DII request data, If there are |
| // no exceptions raised then this method will return null. |
| ExceptionList excList = request.exceptions( ); |
| int count = excList.count(); |
| TypeCode[] excTCList = new TypeCode[count]; |
| try { |
| for( int i = 0; i < count; i++ ) { |
| excTCList[i] = excList.item( i ); |
| } |
| } catch( Exception e ) { |
| throw wrapper.exceptionInExceptions( e ) ; |
| } |
| |
| cachedExceptions = excTCList; |
| } |
| |
| // Good citizen: In the interest of efficiency, we assume |
| // interceptors will be "good citizens" in that they will not |
| // modify the contents of the TypeCode[] array. We also assume |
| // they will not change the values of the containing TypeCodes. |
| |
| return cachedExceptions; |
| } |
| |
| /** |
| * See RequestInfoImpl for javadoc. |
| */ |
| public String[] contexts (){ |
| checkAccess( MID_CONTEXTS ); |
| |
| if( cachedContexts == null ) { |
| if( request == null ) { |
| throw stdWrapper.piOperationNotSupported3() ; |
| } |
| |
| // Get the list of contexts from DII request data, If there are |
| // no contexts then this method will return null. |
| ContextList ctxList = request.contexts( ); |
| int count = ctxList.count(); |
| String[] ctxListToReturn = new String[count]; |
| try { |
| for( int i = 0; i < count; i++ ) { |
| ctxListToReturn[i] = ctxList.item( i ); |
| } |
| } catch( Exception e ) { |
| throw wrapper.exceptionInContexts( e ) ; |
| } |
| |
| cachedContexts = ctxListToReturn; |
| } |
| |
| // Good citizen: In the interest of efficiency, we assume |
| // interceptors will be "good citizens" in that they will not |
| // modify the contents of the String[] array. |
| |
| return cachedContexts; |
| } |
| |
| /** |
| * See RequestInfoImpl for javadoc. |
| */ |
| public String[] operation_context (){ |
| checkAccess( MID_OPERATION_CONTEXT ); |
| |
| if( cachedOperationContext == null ) { |
| if( request == null ) { |
| throw stdWrapper.piOperationNotSupported4() ; |
| } |
| |
| // Get the list of contexts from DII request data, If there are |
| // no contexts then this method will return null. |
| Context ctx = request.ctx( ); |
| // _REVISIT_ The API for get_values is not compliant with the spec, |
| // Revisit this code once it's fixed. |
| // _REVISIT_ Our ORB doesn't support Operation Context, This code |
| // will not be excerscised until it's supported. |
| // The first parameter in get_values is the start_scope which |
| // if blank makes it as a global scope. |
| // The second parameter is op_flags which is set to RESTRICT_SCOPE |
| // As there is only one defined in the spec. |
| // The Third param is the pattern which is '*' requiring it to |
| // get all the contexts. |
| NVList nvList = ctx.get_values( "", CTX_RESTRICT_SCOPE.value,"*" ); |
| String[] context = new String[(nvList.count() * 2) ]; |
| if( ( nvList != null ) &&( nvList.count() != 0 ) ) { |
| // The String[] array will contain Name and Value for each |
| // context and hence double the size in the array. |
| int index = 0; |
| for( int i = 0; i < nvList.count(); i++ ) { |
| NamedValue nv; |
| try { |
| nv = nvList.item( i ); |
| } |
| catch (Exception e ) { |
| return (String[]) null; |
| } |
| context[index] = nv.name(); |
| index++; |
| context[index] = nv.value().extract_string(); |
| index++; |
| } |
| } |
| |
| cachedOperationContext = context; |
| } |
| |
| // Good citizen: In the interest of efficiency, we assume |
| // interceptors will be "good citizens" in that they will not |
| // modify the contents of the String[] array. |
| |
| return cachedOperationContext; |
| } |
| |
| /** |
| * See RequestInfoImpl for javadoc. |
| */ |
| public Any result (){ |
| checkAccess( MID_RESULT ); |
| |
| if( cachedResult == null ) { |
| if( request == null ) { |
| throw stdWrapper.piOperationNotSupported5() ; |
| } |
| // Get the result from the DII request data. |
| NamedValue nvResult = request.result( ); |
| |
| if( nvResult == null ) { |
| throw wrapper.piDiiResultIsNull() ; |
| } |
| |
| cachedResult = nvResult.value(); |
| } |
| |
| // Good citizen: In the interest of efficiency, we assume that |
| // interceptors will not modify the contents of the result Any. |
| // Otherwise, we would need to create a deep copy of the Any. |
| |
| return cachedResult; |
| } |
| |
| /** |
| * See RequestInfoImpl for javadoc. |
| */ |
| public boolean response_expected (){ |
| // access is currently valid for all states: |
| //checkAccess( MID_RESPONSE_EXPECTED ); |
| return ! messageMediator.isOneWay(); |
| } |
| |
| /** |
| * See RequestInfoImpl for javadoc. |
| */ |
| public Object forward_reference (){ |
| checkAccess( MID_FORWARD_REFERENCE ); |
| // Check to make sure we are in LOCATION_FORWARD |
| // state as per ptc/00-08-06, table 21-1 |
| // footnote 2. |
| if( replyStatus != LOCATION_FORWARD.value ) { |
| throw stdWrapper.invalidPiCall1() ; |
| } |
| |
| // Do not cache this value since if an interceptor raises |
| // forward request then the next interceptor in the |
| // list should see the new value. |
| IOR ior = getLocatedIOR(); |
| return iorToObject(ior); |
| } |
| |
| private IOR getLocatedIOR() |
| { |
| IOR ior; |
| CorbaContactInfoList contactInfoList = (CorbaContactInfoList) |
| messageMediator.getContactInfo().getContactInfoList(); |
| ior = contactInfoList.getEffectiveTargetIOR(); |
| return ior; |
| } |
| |
| protected void setLocatedIOR(IOR ior) |
| { |
| ORB orb = (ORB) messageMediator.getBroker(); |
| |
| CorbaContactInfoListIterator iterator = (CorbaContactInfoListIterator) |
| ((CorbaInvocationInfo)orb.getInvocationInfo()) |
| .getContactInfoListIterator(); |
| |
| // REVISIT - this most likely causes reportRedirect to happen twice. |
| // Once here and once inside the request dispatcher. |
| iterator.reportRedirect( |
| (CorbaContactInfo)messageMediator.getContactInfo(), |
| ior); |
| } |
| |
| /** |
| * See RequestInfoImpl for javadoc. |
| */ |
| public org.omg.IOP.ServiceContext get_request_service_context( int id ) { |
| checkAccess( MID_GET_REQUEST_SERVICE_CONTEXT ); |
| |
| if( cachedRequestServiceContexts == null ) { |
| cachedRequestServiceContexts = new HashMap(); |
| } |
| |
| return getServiceContext(cachedRequestServiceContexts, |
| messageMediator.getRequestServiceContexts(), |
| id); |
| } |
| |
| /** |
| * does not contain an etry for that ID, BAD_PARAM with a minor code of |
| * TBD_BP is raised. |
| */ |
| public org.omg.IOP.ServiceContext get_reply_service_context( int id ) { |
| checkAccess( MID_GET_REPLY_SERVICE_CONTEXT ); |
| |
| if( cachedReplyServiceContexts == null ) { |
| cachedReplyServiceContexts = new HashMap(); |
| } |
| |
| // In the event this is called from a oneway, we will have no |
| // response object. |
| // |
| // In the event this is called after a IIOPConnection.purgeCalls, |
| // we will have a response object, but that object will |
| // not contain a header (which would hold the service context |
| // container). See bug 4624102. |
| // |
| // REVISIT: this is the only thing used |
| // from response at this time. However, a more general solution |
| // would avoid accessing other parts of response's header. |
| // |
| // Instead of throwing a NullPointer, we will |
| // "gracefully" handle these with a BAD_PARAM with minor code 25. |
| |
| try { |
| ServiceContexts serviceContexts = |
| messageMediator.getReplyServiceContexts(); |
| if (serviceContexts == null) { |
| throw new NullPointerException(); |
| } |
| return getServiceContext(cachedReplyServiceContexts, |
| serviceContexts, id); |
| } catch (NullPointerException e) { |
| // REVISIT how this is programmed - not what it does. |
| // See purge calls test. The waiter is woken up by the |
| // call to purge calls - but there is no reply containing |
| // service contexts. |
| throw stdWrapper.invalidServiceContextId( e ) ; |
| } |
| } |
| |
| // |
| // REVISIT |
| // Override RequestInfoImpl connection to work in framework. |
| // |
| |
| public com.sun.corba.se.spi.legacy.connection.Connection connection() |
| { |
| return (com.sun.corba.se.spi.legacy.connection.Connection) |
| messageMediator.getConnection(); |
| } |
| |
| |
| |
| /* |
| ********************************************************************** |
| * Package-scope interfaces |
| **********************************************************************/ |
| |
| protected void setInfo(MessageMediator messageMediator) |
| { |
| this.messageMediator = (CorbaMessageMediator)messageMediator; |
| // REVISIT - so mediator can handle DII in subcontract. |
| this.messageMediator.setDIIInfo(request); |
| } |
| |
| /** |
| * Set or reset the retry request flag. |
| */ |
| void setRetryRequest( RetryType retryRequest ) { |
| this.retryRequest = retryRequest; |
| } |
| |
| /** |
| * Retrieve the current retry request status. |
| */ |
| RetryType getRetryRequest() { |
| // 6763340 |
| return this.retryRequest; |
| } |
| |
| /** |
| * Increases the entry count by 1. |
| */ |
| void incrementEntryCount() { |
| this.entryCount++; |
| } |
| |
| /** |
| * Decreases the entry count by 1. |
| */ |
| void decrementEntryCount() { |
| this.entryCount--; |
| } |
| |
| /** |
| * Retrieve the current entry count |
| */ |
| int getEntryCount() { |
| return this.entryCount; |
| } |
| |
| /** |
| * Overridden from RequestInfoImpl. Calls the super class, then |
| * sets the ending point call depending on the reply status. |
| */ |
| protected void setReplyStatus( short replyStatus ) { |
| super.setReplyStatus( replyStatus ); |
| switch( replyStatus ) { |
| case SUCCESSFUL.value: |
| endingPointCall = CALL_RECEIVE_REPLY; |
| break; |
| case SYSTEM_EXCEPTION.value: |
| case USER_EXCEPTION.value: |
| endingPointCall = CALL_RECEIVE_EXCEPTION; |
| break; |
| case LOCATION_FORWARD.value: |
| case TRANSPORT_RETRY.value: |
| endingPointCall = CALL_RECEIVE_OTHER; |
| break; |
| } |
| } |
| |
| /** |
| * Sets DII request object in the RequestInfoObject. |
| */ |
| protected void setDIIRequest(org.omg.CORBA.Request req) { |
| request = req; |
| } |
| |
| /** |
| * Keeps track of whether initiate was called for a DII request. The ORB |
| * needs to know this so it knows whether to ignore a second call to |
| * initiateClientPIRequest or not. |
| */ |
| protected void setDIIInitiate( boolean diiInitiate ) { |
| this.diiInitiate = diiInitiate; |
| } |
| |
| /** |
| * See comment for setDIIInitiate |
| */ |
| protected boolean isDIIInitiate() { |
| return this.diiInitiate; |
| } |
| |
| /** |
| * The PICurrent stack should only be popped if it was pushed. |
| * This is generally the case. But exceptions which occur |
| * after the stub's entry to _request but before the push |
| * end up in _releaseReply which will try to pop unless told not to. |
| */ |
| protected void setPICurrentPushed( boolean piCurrentPushed ) { |
| this.piCurrentPushed = piCurrentPushed; |
| } |
| |
| protected boolean isPICurrentPushed() { |
| return this.piCurrentPushed; |
| } |
| |
| /** |
| * Overridden from RequestInfoImpl. |
| */ |
| protected void setException( Exception exception ) { |
| super.setException( exception ); |
| |
| // Clear cached values: |
| cachedReceivedException = null; |
| cachedReceivedExceptionId = null; |
| } |
| |
| protected boolean getIsOneWay() { |
| return ! response_expected(); |
| } |
| |
| /** |
| * See description for RequestInfoImpl.checkAccess |
| */ |
| protected void checkAccess( int methodID ) |
| throws BAD_INV_ORDER |
| { |
| // Make sure currentPoint matches the appropriate index in the |
| // validCall table: |
| int validCallIndex = 0; |
| switch( currentExecutionPoint ) { |
| case EXECUTION_POINT_STARTING: |
| switch( startingPointCall ) { |
| case CALL_SEND_REQUEST: |
| validCallIndex = 0; |
| break; |
| case CALL_SEND_POLL: |
| validCallIndex = 1; |
| break; |
| } |
| break; |
| case EXECUTION_POINT_ENDING: |
| switch( endingPointCall ) { |
| case CALL_RECEIVE_REPLY: |
| validCallIndex = 2; |
| break; |
| case CALL_RECEIVE_EXCEPTION: |
| validCallIndex = 3; |
| break; |
| case CALL_RECEIVE_OTHER: |
| validCallIndex = 4; |
| break; |
| } |
| break; |
| } |
| |
| // Check the validCall table: |
| if( !validCall[methodID][validCallIndex] ) { |
| throw stdWrapper.invalidPiCall2() ; |
| } |
| } |
| |
| } |
| |
| // End of file. |