blob: 94e3f957c31d7c9b0b58f83e20cb1ec474542622 [file] [log] [blame]
/*
* 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.