package org.jacorb.orb;
/*
* JacORB - a free Java ORB
*
* Copyright (C) 1997-2014 Gerald Brose / The JacORB Team.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayDeque;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.ConcurrentHashMap;
import org.jacorb.config.Configuration;
import org.jacorb.config.ConfigurationException;
import org.jacorb.ir.RepositoryID;
import org.jacorb.orb.giop.ClientConnection;
import org.jacorb.orb.giop.ClientConnectionManager;
import org.jacorb.orb.giop.LocateReplyInputStream;
import org.jacorb.orb.giop.LocateRequestOutputStream;
import org.jacorb.orb.giop.ReplyInputStream;
import org.jacorb.orb.giop.RequestOutputStream;
import org.jacorb.orb.iiop.IIOPProfile;
import org.jacorb.orb.miop.MIOPProfile;
import org.jacorb.orb.policies.PolicyManager;
import org.jacorb.orb.portableInterceptor.ClientInterceptorHandler;
import org.jacorb.orb.portableInterceptor.ClientInterceptorIterator;
import org.jacorb.orb.portableInterceptor.ClientRequestInfoImpl;
import org.jacorb.orb.portableInterceptor.DefaultClientInterceptorHandler;
import org.jacorb.orb.portableInterceptor.InterceptorManager;
import org.jacorb.orb.portableInterceptor.NullClientInterceptorHandler;
import org.jacorb.orb.portableInterceptor.ServerInterceptorIterator;
import org.jacorb.orb.portableInterceptor.ServerRequestInfoImpl;
import org.jacorb.poa.util.POAUtil;
import org.jacorb.util.ObjectUtil;
import org.jacorb.util.SelectorManager;
import org.jacorb.util.Time;
import org.omg.CORBA.BAD_INV_ORDER;
import org.omg.CORBA.BAD_PARAM;
import org.omg.CORBA.COMM_FAILURE;
import org.omg.CORBA.CompletionStatus;
import org.omg.CORBA.INTERNAL;
import org.omg.CORBA.INV_OBJREF;
import org.omg.CORBA.INV_POLICY;
import org.omg.CORBA.OBJECT_NOT_EXIST;
import org.omg.CORBA.OBJ_ADAPTER;
import org.omg.CORBA.Policy;
import org.omg.CORBA.SystemException;
import org.omg.CORBA.TIMEOUT;
import org.omg.CORBA.portable.ApplicationException;
import org.omg.CORBA.portable.ObjectImpl;
import org.omg.CORBA.portable.RemarshalException;
import org.omg.CORBA.portable.ServantObject;
import org.omg.ETF.Profile;
import org.omg.GIOP.LocateStatusType_1_2;
import org.omg.IOP.IOR;
import org.omg.IOP.ServiceContext;
import org.omg.Messaging.RELATIVE_REQ_TIMEOUT_POLICY_TYPE;
import org.omg.Messaging.RELATIVE_RT_TIMEOUT_POLICY_TYPE;
import org.omg.Messaging.REPLY_END_TIME_POLICY_TYPE;
import org.omg.Messaging.REPLY_START_TIME_POLICY_TYPE;
import org.omg.Messaging.REQUEST_END_TIME_POLICY_TYPE;
import org.omg.Messaging.REQUEST_START_TIME_POLICY_TYPE;
import org.omg.Messaging.SYNC_NONE;
import org.omg.Messaging.SYNC_SCOPE_POLICY_TYPE;
import org.omg.Messaging.SYNC_WITH_SERVER;
import org.omg.Messaging.SYNC_WITH_TARGET;
import org.omg.Messaging.SYNC_WITH_TRANSPORT;
import org.omg.PortableInterceptor.ForwardRequest;
import org.omg.PortableInterceptor.LOCATION_FORWARD;
import org.omg.PortableInterceptor.SUCCESSFUL;
import org.omg.PortableInterceptor.SYSTEM_EXCEPTION;
import org.omg.PortableInterceptor.USER_EXCEPTION;
import org.omg.PortableServer.POAPackage.ObjectNotActive;
import org.omg.PortableServer.POAPackage.WrongAdapter;
import org.omg.PortableServer.POAPackage.WrongPolicy;
import org.omg.PortableServer.Servant;
import org.omg.PortableServer.ServantActivator;
import org.omg.PortableServer.ServantLocatorPackage.CookieHolder;
import org.omg.RTCORBA.Protocol;
import org.omg.TimeBase.UtcT;
import org.slf4j.Logger;
/**
* JacORB implementation of CORBA object reference
*
* @author Gerald Brose
*
*/
public final class Delegate
extends org.omg.CORBA_2_3.portable.Delegate
{
// WARNING: DO NOT USE _pior DIRECTLY, BECAUSE THAT IS NOT MT
// SAFE. USE getParsedIOR() INSTEAD, AND KEEP A METHOD-LOCAL COPY
// OF THE REFERENCE.
private ParsedIOR _pior = null;
private IOR ior = null;
/**
* Normally a delegate only has one connection open at a time. With the addition
* of MIOP it is possible for the user to request a two-way operation (via e.g. IIOP)
* and then a one-way operation via MIOP. Rather than repeatedly calling
* ConnectionManager.getConnection the additional MIOP connection will also be cached
* here.
*/
private ClientConnection connections[] = new ClientConnection[2];
private enum TransportType { IIOP, MIOP };
/**
* The current connection; this should be either IIOP or MIOP where
* 0 = IIOP
* 1 = MIOP
*/
private TransportType currentConnection = TransportType.IIOP;
/* save original ior for fallback */
private ParsedIOR piorOriginal = null;
/* save iors to detect and prevent locate forward loop */
private ParsedIOR piorForward = null;
private boolean bound = false;
private org.jacorb.poa.POA poa;
private final org.jacorb.orb.ORB orb;
private final Logger logger;
/** set after the first attempt to determine whether
this reference is to a local object */
private boolean resolved_locality = false;
private final ConcurrentHashMap<org.omg.ETF.Profile, ReplyGroup> groups;
private final java.lang.Object bind_sync = new java.lang.Object();
private boolean locate_on_bind_performed = false;
private final ClientConnectionManager conn_mg;
private final Map<Integer, Policy> policy_overrides;
private CookieHolder cookie = null;
private String invokedOperation = null;
private final SelectorManager selectorManager;
/**
* <code>localInterceptors</code> stores the ClientInterceptorHandler that is
* currently in use during an interceptor invocation. It is held within a
* thread local to prevent thread interaction issues.
*/
private static final ThreadLocal<ClientInterceptorHandler> localInterceptors = new ThreadLocal<ClientInterceptorHandler>();
/** the configuration object for this delegate */
private final Configuration configuration;
/** configuration properties */
private boolean locateOnBind;
/** mitigate the symptom of an infinite loop in some imr failure cases, see bug 810 */
private int maxBuiltinRetries = 0;
/**
* This is the default GIOP minor version configured by JacORB. Most of the time
* JacORB will use whatever is within the effective profile. In the case of MIOP this
* information may not be available to it will use this to set the GIOP version.
*/
private int defaultGiopMinor;
/**
* specify if this Delegate should drop its connection to the remote ORB after
* a non-recoverable SystemException occured. non-recoverable SystemException
* couldn't be handled by rebind.
*/
private boolean disconnectAfterNonRecoverableSystemException;
/**
* Always attempt to locate is_a information locally rather than remotely.
*/
private boolean avoidIsARemoteCall=true;
/**
* Preserve JacORB 2.3.x series behaviour with interceptors which restores the
* 2.3.x behaviour of returning false from an is_local call when interceptors are
* enabled and installed.
*
* This should NOT be required in general and has only been added for certain scenarios
* with legacy applications. Do not remove without checking with Nick Cross (13/April/2012)
*/
private boolean isLocalHistoricalInterceptors = false;
/**
* Denote whether to allow orbPolicies or do optimised version
*/
private boolean disableClientOrbPolicies;
/** delay in millisecs before retrying */
private Random randomDelay = null;
public static enum INVOCATION_KEY
{
REQUEST_END_TIME,
REPLY_END_TIME,
/**
* This is used to indicate that a current context popped from the Delegates
* invocationContext stack was pushed there prior to an interceptor call. We
* need this to ensure that the context is not popped if a CORBA call is made
* by the interceptor. The context must be popped on return from the
* interceptor.
*/
INTERCEPTOR_CALL,
SERVANT_PREINVOKE,
CLEAR_ALLOWED,
/**
* These keys are used to manage automatic retries in some situations.
*/
CORBANAME_RESET,
FORWARD_RESET
};
private static enum SyncScope
{
NONE (org.omg.Messaging.SYNC_NONE.value),
TRANSPORT (org.omg.Messaging.SYNC_WITH_TRANSPORT.value),
SERVER (org.omg.Messaging.SYNC_WITH_SERVER.value),
TARGET (org.omg.Messaging.SYNC_WITH_TARGET.value);
public static SyncScope getSyncScope (String ss) throws ConfigurationException
{
try
{
return valueOf (ss.toUpperCase ());
}
catch (IllegalArgumentException e)
{
throw new ConfigurationException ("Invalid type for SyncScope", e);
}
}
public short getType ()
{
return value;
}
private short value;
private SyncScope(short value)
{
this.value = value;
}
};
private SyncScope defaultSyncScope = SyncScope.TRANSPORT;
/**
* 03-09-04: 1.5.2.2
*
* boolean threadlocal to ensure that
* after servant_preinvoke has returned null the
* next call to is_local will return false
* so that the stub will choose the non-optimized path
*/
private static final ThreadLocal<Boolean> ignoreNextCallToIsLocal = new ThreadLocal<Boolean>()
{
@Override
protected Boolean initialValue()
{
return Boolean.FALSE;
}
};
/**
* @see #getInvocationContext()
* @see #clearInvocationContext()
* This is a <code>ArrayDeque</code> containing HashMaps. The HashMap will
* contain values that apply to the current invocation. A ArrayDeque of
* HashMaps is needed to cater for the fact that invocations can be
* made within invocations and the values may differ for each invocation.
* We need to retain the values for the original invocation as well as
* apply the correct values for any internal invocation.
*/
private static final ThreadLocal<ArrayDeque<Map<INVOCATION_KEY, UtcT>>> invocationContext = new ThreadLocal<ArrayDeque<Map<INVOCATION_KEY, UtcT>>>()
{
@Override
protected ArrayDeque<Map<INVOCATION_KEY, UtcT>> initialValue()
{
return new ArrayDeque<Map<INVOCATION_KEY, UtcT>> ();
}
};
/**
* access the current invocation context (its a ArrayDeque of Maps).
* this context lives as long as the invocation is active.
* especially it outlives RemarshalExceptions and thus
* can be used to share information between mutiple requests
* that are done as part of an invocation.
*/
public static final ArrayDeque<Map<INVOCATION_KEY, UtcT>> getInvocationContext()
{
return invocationContext.get();
}
/**
* clear the current invocation context. must be invoked
* before control is returned to the client
* (exceptions, orderly termination).
* mustn't be reset in case of RemarshalExceptions.
*/
public static void clearInvocationContext()
{
ArrayDeque<Map<INVOCATION_KEY, UtcT>> invocationStack = getInvocationContext();
if (! invocationStack.isEmpty())
{
Map<INVOCATION_KEY, UtcT> currentCtxt = invocationStack.peek();
if ( !(currentCtxt.containsKey (INVOCATION_KEY.INTERCEPTOR_CALL) ||
currentCtxt.containsKey (INVOCATION_KEY.SERVANT_PREINVOKE)) ||
currentCtxt.containsKey (INVOCATION_KEY.CLEAR_ALLOWED))
{
invocationStack.pop();
}
}
}
/**
* A general note on the synchronization concept
*
* The main problem that has to be addressed by synchronization
* means is the case when an object reference is shared by
* threads, and LocationForwards (e.g. thrown by the ImR) or
* ForwardRequest (thrown by ClientInterceptors) involved. In
* these cases, the rebinding to another target can occur while
* there are still other requests active. Therefore, the act of
* rebinding must be synchronized, so every thread sees a
* consistent state.
*
* Synchronization is done via the bind_sync object. Please also
* have a look at the comment for operation bind().
*/
/* constructors: */
private Delegate(ORB orb, Configuration config, boolean parseIORLazy)
{
super();
this.orb = orb;
configuration = config;
conn_mg = orb.getClientConnectionManager();
selectorManager = orb.getSelectorManager ();
logger = config.getLogger("org.jacorb.orb.delegate");
locateOnBind =
config.getAttributeAsBoolean("jacorb.locate_on_bind", false);
avoidIsARemoteCall =
config.getAttributeAsBoolean("jacorb.avoidIsARemoteCall", true);
isLocalHistoricalInterceptors =
config.getAttributeAsBoolean("jacorb.isLocalHistoricalInterceptors", false);
try
{
maxBuiltinRetries =
config.getAttributeAsInteger ("jacorb.maxBuiltinRetries", 0);
if (maxBuiltinRetries < 0)
{
logger.error ("Configuration error - max builtin retries < 0");
throw new INTERNAL ("Configuration error - max builtin retries < 0");
}
}
catch (ConfigurationException ex)
{
logger.error ("Configuration exception retrieving max builtin retries", ex);
throw new INTERNAL ("Configuration exception retrieving max builtin retries" + ex);
}
disconnectAfterNonRecoverableSystemException = config.getAttributeAsBoolean
("jacorb.connection.client.disconnect_after_systemexception", true);
disableClientOrbPolicies = config.getAttributeAsBoolean("jacorb.disableClientOrbPolicies", false);
try
{
defaultGiopMinor = configuration.getAttributeAsInteger ("jacorb.giop_minor_version", 2);
}
catch (ConfigurationException ex)
{
logger.error ("Configuration exception retrieving giop minor version", ex);
throw new INTERNAL ("Configuration exception retrieving giop minor version" + ex);
}
try
{
defaultSyncScope = SyncScope.getSyncScope (configuration.getAttribute("jacorb.default_sync_scope","TRANSPORT"));
}
catch (ConfigurationException ex)
{
logger.error ("Configuration exception retrieving default sync scope ", ex);
throw new INTERNAL ("Configuration exception retrieving default sync scope " + ex);
}
// standard initialization
groups = new ConcurrentHashMap<org.omg.ETF.Profile, ReplyGroup>();
if (parseIORLazy)
{
// reference received across the net
if (disableClientOrbPolicies)
{
policy_overrides = Collections.emptyMap ();
}
else
{
policy_overrides = new HashMap<Integer, Policy>(0);
}
}
else
{
// reference locally created
if (disableClientOrbPolicies)
{
policy_overrides = Collections.emptyMap ();
}
else
{
policy_overrides = new HashMap<Integer, Policy>();
}
}
}
private Delegate(ORB orb, boolean parseIORLazy)
{
this(orb, orb.getConfiguration(), parseIORLazy);
}
public Delegate ( org.jacorb.orb.ORB orb, ParsedIOR pior )
{
this(orb, false);
piorOriginal = pior;
resetPior ();
}
public Delegate(org.jacorb.orb.ORB orb, IOR ior, boolean parseIORLazy)
{
this(orb, parseIORLazy);
this.ior = ior;
if (parseIORLazy)
{
// postpone parsing of IOR.
// see getParsedIOR
}
else
{
getParsedIOR();
}
}
public Delegate(org.jacorb.orb.ORB orb, org.omg.IOP.IOR ior)
{
this(orb, ior, false);
}
public int _get_TCKind()
{
return org.omg.CORBA.TCKind._tk_objref;
}
/**
* This bind is a combination of the old _init() and bind()
* operations. It first inits this delegate with the information
* supplied by the (parsed) IOR. Then it requests a new
* ClientConnection from the ConnectionsManager. This will *NOT*
* open up a TCP connection, but the connection is needed for the
* GIOP message ids. The actual TCP connection is automatically
* opened up by the ClientConnection, when the first request is
* sent. This has the advantage, that COMM_FAILURES can only occur
* inside of _invoke, where they get handled properly (falling
* back, etc.)
*/
private void bind()
{
synchronized (bind_sync)
{
if ( bound )
{
return;
}
final ParsedIOR ior = getParsedIOR();
ior.patchSSL ();
// Check if ClientProtocolPolicy set, if so, set profile
// selector for IOR that selects effective profile for protocol
org.omg.RTCORBA.Protocol[] protocols = getClientProtocols();
if (protocols != null && !ior.isProfileSelectorSet())
{
ior.setProfileSelector (new SpecificProfileSelector(protocols));
}
org.omg.ETF.Profile profile = ior.getEffectiveProfile();
if (profile == null)
{
throw new org.omg.CORBA.COMM_FAILURE ("no effective profile");
}
//MIOP
if(profile instanceof MIOPProfile)
{
connections[TransportType.MIOP.ordinal ()] = conn_mg.getConnection(profile);
profile = ((MIOPProfile)profile).getGroupIIOPProfile();
}
if (profile != null)
{
connections[TransportType.IIOP.ordinal ()] = conn_mg.getConnection(profile);
}
bound = true;
/* The delegate could query the server for the object
* location using a GIOP locate request to make sure the
* first call will get through without redirections
* (provided the server's answer is definite):
*/
if ( locateOnBind && !locate_on_bind_performed )
{
//only locate once, because bind is called from the
//switch statement below again.
locate_on_bind_performed = true;
try
{
LocateRequestOutputStream lros =
new LocateRequestOutputStream( orb,
ior.get_object_key(),
connections[currentConnection.ordinal ()].getId(),
ior.getEffectiveProfile().version().minor );
LocateReplyReceiver receiver = new LocateReplyReceiver();
receiver.configure (configuration);
connections[currentConnection.ordinal ()].sendRequest( lros,
receiver,
lros.getRequestId(),
true ); //response expected
getParsedIOR ().markLastUsedProfile ();
LocateReplyInputStream lris = receiver.getReply();
switch ( lris.rep_hdr.locate_status.value() )
{
case LocateStatusType_1_2._UNKNOWN_OBJECT :
{
throw new org.omg.CORBA.UNKNOWN( "Could not bind to object, server does not know it!" );
}
case LocateStatusType_1_2._OBJECT_HERE :
{
break;
}
case LocateStatusType_1_2._OBJECT_FORWARD :
{
//fall through
}
case LocateStatusType_1_2._OBJECT_FORWARD_PERM :
{
//_OBJECT_FORWARD_PERM is actually more or
//less deprecated
forwardToObj (lris.read_Object());
break;
}
case LocateStatusType_1_2._LOC_SYSTEM_EXCEPTION :
{
throw SystemExceptionHelper.read( lris );
}
case LocateStatusType_1_2._LOC_NEEDS_ADDRESSING_MODE :
{
throw new org.omg.CORBA.NO_IMPLEMENT( "Server responded to LocateRequest with a status of LOC_NEEDS_ADDRESSING_MODE, but this isn't yet implemented by JacORB" );
}
default :
{
throw new IllegalArgumentException( "Unknown reply status for LOCATE_REQUEST: " + lris.rep_hdr.locate_status.value() );
}
}
}
catch ( org.omg.CORBA.SystemException se )
{
//rethrow
throw se;
}
catch ( Exception e )
{
if (logger.isWarnEnabled())
{
logger.warn( e.getMessage() );
}
}
}
}
}
public void forwardToObj (org.omg.CORBA.Object obj)
{
String object_reference = orb.object_to_string(obj);
if (object_reference != null && object_reference.indexOf( "IOR:" ) == 0)
{
Delegate delegate = (Delegate) ((ObjectImpl)obj)._get_delegate();
forwardPior (new ParsedIOR( orb, object_reference));
rebindWithProto (delegate == null ? null : delegate.getClientProtocols());
}
else
{
throw new INV_OBJREF ("Not an IOR: " + object_reference);
}
}
private void rebind ()
{
rebindWithProto (null);
}
private void rebindWithProto (Protocol[] protocols)
{
synchronized ( bind_sync )
{
ParsedIOR pior = getParsedIOR ();
// Check if ClientProtocolPolicy set, if so, set profile
// selector for IOR that selects effective profile for protocol.
//
// If rebind has been passed in a new set of protocols use that.
if (protocols != null)
{
pior.setProfileSelector(new SpecificProfileSelector(protocols));
}
else
{
org.omg.RTCORBA.Protocol[] thisProtocols = getClientProtocols();
if (thisProtocols != null && !pior.isProfileSelectorSet())
{
pior.setProfileSelector(new SpecificProfileSelector(thisProtocols));
}
}
if (connections[TransportType.IIOP.ordinal ()] != null)
{
if (logger.isDebugEnabled ())
logger.debug ("Delegate.rebind, releasing connection");
conn_mg.releaseConnection( connections[TransportType.IIOP.ordinal ()] );
connections[TransportType.IIOP.ordinal ()] = null;
}
if ( connections[TransportType.MIOP.ordinal ()] != null )
{
conn_mg.releaseConnection( connections[TransportType.MIOP.ordinal ()] );
connections[TransportType.MIOP.ordinal ()] = null;
}
//to tell bind() that it has to take action
bound = false;
bind();
}
}
@Override
public org.omg.CORBA.Request create_request( org.omg.CORBA.Object self,
org.omg.CORBA.Context ctx,
String operation,
org.omg.CORBA.NVList args,
org.omg.CORBA.NamedValue result )
{
checkORB();
bind();
return new org.jacorb.orb.dii.Request( self,
orb,
connections[currentConnection.ordinal ()],
getParsedIOR().get_object_key(),
operation,
args,
ctx,
result );
}
@Override
public org.omg.CORBA.Request create_request( org.omg.CORBA.Object self,
org.omg.CORBA.Context ctx,
String operation,
org.omg.CORBA.NVList args,
org.omg.CORBA.NamedValue result,
org.omg.CORBA.ExceptionList exceptions,
org.omg.CORBA.ContextList contexts )
{
checkORB();
bind();
return new org.jacorb.orb.dii.Request( self,
orb,
connections[currentConnection.ordinal ()],
getParsedIOR().get_object_key(),
operation,
args,
ctx,
result,
exceptions,
contexts);
}
@Override
public org.omg.CORBA.Object duplicate( org.omg.CORBA.Object self )
{
return orb._getDelegate (new ParsedIOR( orb, toString()));
}
@Override
public boolean equals(java.lang.Object obj)
{
return ( obj instanceof org.omg.CORBA.Object &&
toString().equals( obj.toString() ) );
}
@Override
public boolean equals( org.omg.CORBA.Object self, java.lang.Object obj )
{
return equals( obj );
}
// The finalize method has been removed due to performance and scalability
// issues.
//
// This method was called when a client-side stub was garbage-collected. In
// effect it caused the Delegate to unregister itself from the underlying
// GIOPConnection and if there were no other Delegates using that
// connection, it was be closed and disposed of altogether.
//
// This therefore moves the responsibility to the client code to call _release.
//
@Override
public org.omg.CORBA.DomainManager[] get_domain_managers( org.omg.CORBA.Object self )
{
return null;
}
/**
* The get_policy operation returns the policy object of the
* specified type, which applies to this object. It returns the
* effective Policy for the object reference. The effective Policy
* is the one that would be used if a request were made. This
* Policy is determined first by obtaining the effective override
* for the PolicyType as returned by get_client_policy. The
* effective override is then compared with the Policy as
* specified in the IOR.
* <p>
* The effective Policy is determined by reconciling the effective
* override and the IOR-specified Policy. If the two policies
* cannot be reconciled, the standard system exception INV_POLICY
* is raised with standard minor code 1. The absence of a Policy
* value in the IOR implies that any legal value may be used.
*/
@Override
public org.omg.CORBA.Policy get_policy( org.omg.CORBA.Object self,
int policy_type )
{
Policy result = get_client_policy(policy_type);
if (result != null)
{
// TODO: "reconcile" with server-side policy
return result;
}
// if not locally overridden, ask the server
return get_policy( self,
policy_type,
request( self, "_get_policy", true ) );
}
/**
* Gets the effective overriding policy with the given type from
* the client-side, or null if this policy type is unset.
*
* (Implementation is incomplete, we don't check PolicyCurrent, i.e.
* at the thread-level)
*/
public org.omg.CORBA.Policy get_client_policy(int policy_type)
{
Policy result = null;
if (disableClientOrbPolicies)
{
return null;
}
synchronized(policy_overrides)
{
final Integer key = Integer.valueOf(policy_type);
result = policy_overrides.get(key);
}
if ( result == null )
{
// no override at the object level for this type, now
// check at the thread level, ie PolicyCurrent.
// TODO: currently not implemented
// check at the ORB-level
final PolicyManager policyManager = orb.getPolicyManager();
if (policyManager != null)
{
Policy[] orbPolicies = policyManager.get_policy_overrides (new int[] {policy_type});
if (orbPolicies!= null && orbPolicies.length == 1)
{
result = orbPolicies[0];
}
}
}
return result;
}
public org.omg.CORBA.Policy get_policy( org.omg.CORBA.Object self,
int policy_type,
org.omg.CORBA.portable.OutputStream os )
{
// ask object implementation
while ( true )
{
try
{
os.write_Object( self );
os.write_long( policy_type );
org.omg.CORBA.portable.InputStream is = invoke( self, os );
return org.omg.CORBA.PolicyHelper.narrow( is.read_Object() );
}
catch ( RemarshalException r )
{
// Ignored
}
catch ( ApplicationException _ax )
{
String _id = _ax.getId();
throw new INTERNAL( "Unexpected exception " + _id );
}
}
} // get_policy
public UtcT getRequestEndTime()
{
Policy policy = get_client_policy(REQUEST_END_TIME_POLICY_TYPE.value);
if (policy != null)
{
return ((org.omg.Messaging.RequestEndTimePolicy)policy).end_time();
}
return null;
}
public UtcT getReplyEndTime()
{
Policy policy = get_client_policy (REPLY_END_TIME_POLICY_TYPE.value);
if (policy != null)
{
return ((org.omg.Messaging.ReplyEndTimePolicy)policy).end_time();
}
return null;
}
public UtcT getRequestStartTime()
{
Policy policy = get_client_policy (REQUEST_START_TIME_POLICY_TYPE.value);
if (policy != null)
{
return ((org.omg.Messaging.RequestStartTimePolicy)policy).start_time();
}
return null;
}
public UtcT getReplyStartTime()
{
Policy policy = get_client_policy (REPLY_START_TIME_POLICY_TYPE.value);
if (policy != null)
{
return ((org.omg.Messaging.ReplyStartTimePolicy)policy).start_time();
}
return null;
}
public long getRelativeRoundtripTimeout()
{
Policy policy = get_client_policy (RELATIVE_RT_TIMEOUT_POLICY_TYPE.value);
if (policy != null)
{
return ((org.omg.Messaging.RelativeRoundtripTimeoutPolicy)policy)
.relative_expiry();
}
return -1;
}
public long getRelativeRequestTimeout()
{
Policy policy = get_client_policy (RELATIVE_REQ_TIMEOUT_POLICY_TYPE.value);
if (policy != null)
{
return ((org.omg.Messaging.RelativeRequestTimeoutPolicy)policy)
.relative_expiry();
}
return -1;
}
public short getSyncScope()
{
Policy policy = get_client_policy (SYNC_SCOPE_POLICY_TYPE.value);
if (policy != null)
{
return ((org.omg.Messaging.SyncScopePolicy)policy).synchronization();
}
return defaultSyncScope.getType();
}
public org.omg.RTCORBA.Protocol[] getClientProtocols ()
{
Policy policy = get_client_policy(org.omg.RTCORBA.CLIENT_PROTOCOL_POLICY_TYPE.value);
if (policy != null)
{
return ((org.omg.RTCORBA.ClientProtocolPolicy)policy).protocols ();
}
return null;
}
/**
* Deprecated by CORBA 2.3
*/
@Override
@Deprecated
public org.omg.CORBA.InterfaceDef get_interface( org.omg.CORBA.Object self )
{
return org.omg.CORBA.InterfaceDefHelper.narrow( get_interface_def( self ) ) ;
}
@Override
public org.omg.CORBA.Object get_interface_def (org.omg.CORBA.Object self)
{
checkORB();
// If local object call _interface directly
if (is_really_local (self))
{
org.omg.PortableServer.Servant servant;
org.omg.CORBA.portable.ServantObject so = null;
while (so == null)
{
so = servant_preinvoke (self, "_interface", java.lang.Object.class);
}
try
{
servant = (org.omg.PortableServer.Servant) so.servant;
orb.set_delegate (servant);
return servant._get_interface_def();
}
finally
{
servant_postinvoke (self, so);
}
}
org.omg.CORBA.portable.InputStream is = invokeBuiltin (self, "_interface", null);
return (is == null) ? null : is.read_Object();
}
ClientConnection getConnection()
{
synchronized ( bind_sync )
{
bind();
return connections[currentConnection.ordinal ()];
}
}
public org.omg.IOP.IOR getIOR()
{
synchronized ( bind_sync )
{
return getBaseIOR().getIOR();
}
}
public byte[] getObjectId()
{
synchronized ( bind_sync )
{
bind();
return POAUtil.extractOID(getBaseIOR().get_object_key());
}
}
public byte[] getObjectKey()
{
synchronized ( bind_sync )
{
bind();
return getParsedIOR().get_object_key();
}
}
public ParsedIOR getBaseIOR ()
{
synchronized ( bind_sync )
{
return (piorOriginal == null) ? getParsedIOR () : piorOriginal;
}
}
public ParsedIOR getParsedIOR()
{
synchronized ( bind_sync )
{
// If the _pior has not been initialised due to the lazy
// initialisation use the ior to create one.
if (_pior == null)
{
if (ior == null)
{
// should never happen due to the checks in configure
throw new INTERNAL ("Internal error - unable to initialise ParsedIOR as IOR is null");
}
else
{
piorOriginal = new ParsedIOR (orb, ior);
resetPior ();
ior = null;
}
}
return _pior;
}
}
private void resetPior ()
{
synchronized ( bind_sync )
{
_pior = piorOriginal;
piorForward = null;
}
}
private void forwardPior (ParsedIOR fwd)
{
synchronized ( bind_sync )
{
if (!fwd.equals (_pior))
{
piorForward = fwd;
_pior = piorForward;
}
}
}
private boolean isPiorForwarded ()
{
return _pior != piorOriginal;
}
public void resolvePOA (org.omg.CORBA.Object self)
{
if (! resolved_locality)
{
resolved_locality = true;
org.jacorb.poa.POA local_poa = orb.findPOA (this, self);
if (local_poa != null)
{
poa = local_poa;
}
}
}
public org.jacorb.poa.POA getPOA()
{
return poa;
}
/**
*/
public org.omg.CORBA.portable.ObjectImpl getReference( org.jacorb.poa.POA _poa )
{
if ( _poa != null )
{
poa = _poa;
}
final String typeId = ior == null ? typeId() : ior.type_id;
org.omg.CORBA.portable.ObjectImpl reference =
new org.jacorb.orb.Reference( typeId );
reference._set_delegate(this);
return reference;
}
@Override
public int hash( org.omg.CORBA.Object self, int x )
{
checkORB();
return hashCode();
}
@Override
public int hashCode()
{
return getIDString().hashCode();
}
@Override
public int hashCode( org.omg.CORBA.Object self )
{
return hashCode();
}
/**
* Invokes an asynchronous operation using this object reference by
* sending the request marshalled in the OutputStream. The reply
* will be directed to the supplied ReplyHandler.
*/
public void invoke( org.omg.CORBA.Object self,
org.omg.CORBA.portable.OutputStream os,
org.omg.Messaging.ReplyHandler replyHandler )
throws ApplicationException, RemarshalException
{
// discard result, it is always null
invoke_internal (self, os, replyHandler, true);
}
/**
* Invokes a synchronous operation using this object reference
* by sending the request marshalled in the OutputStream.
* @return the reply, if a reply is expected for this request.
* If no reply is expected, returns null.
*/
@Override
public org.omg.CORBA.portable.InputStream invoke
( org.omg.CORBA.Object self,
org.omg.CORBA.portable.OutputStream os )
throws ApplicationException, RemarshalException
{
return invoke_internal (self, os, null, false);
}
private org.omg.CORBA.portable.InputStream invoke_internal
( org.omg.CORBA.Object self,
org.omg.CORBA.portable.OutputStream os,
org.omg.Messaging.ReplyHandler replyHandler,
boolean async )
throws ApplicationException, RemarshalException
{
try
{
final org.omg.CORBA.portable.InputStream in =
_invoke_internal(self, os, replyHandler, async);
clearInvocationContext();
return in;
}
catch(ApplicationException e)
{
clearInvocationContext();
throw e;
}
catch(SystemException t)
{
clearInvocationContext();
throw t;
}
}
/**
* Internal implementation of both invoke() methods. Note that
* the boolean argument <code>async</code> is necessary to differentiate
* between synchronous and asynchronous calls, because the ReplyHandler
* can be null even for an asynchronous call.
*/
private org.omg.CORBA.portable.InputStream _invoke_internal
( org.omg.CORBA.Object self,
org.omg.CORBA.portable.OutputStream os,
org.omg.Messaging.ReplyHandler replyHandler,
boolean async )
throws ApplicationException, RemarshalException
{
checkORB();
RequestOutputStream ros = (RequestOutputStream)os;
ArrayDeque<Map<INVOCATION_KEY, UtcT>> invocationStack = invocationContext.get ();
/**
* We must just peek as we do not want to remove the context from
* the ArrayDeque
*/
Map<INVOCATION_KEY, UtcT> currentCtxt = invocationStack.peek();
UtcT reqET = null;
UtcT repET = null;
if (currentCtxt != null)
{
reqET = currentCtxt.get (INVOCATION_KEY.REQUEST_END_TIME);
repET = currentCtxt.get (INVOCATION_KEY.REPLY_END_TIME);
checkTimeout (reqET, repET);
}
ReplyReceiver receiver = null;
final ClientInterceptorHandler interceptors;
if (orb.hasClientRequestInterceptors())
{
interceptors = new DefaultClientInterceptorHandler
(
(DefaultClientInterceptorHandler)localInterceptors.get(),
orb,
ros,
self,
this,
(isPiorForwarded () ? getBaseIOR() : null),
connections[currentConnection.ordinal ()]
);
}
else
{
interceptors = NullClientInterceptorHandler.getInstance();
}
if ( connections[currentConnection.ordinal ()] != null )
{
orb.notifyTransportListeners (connections[currentConnection.ordinal ()].getGIOPConnection());
}
if (orb.hasRequestInterceptors())
{
localInterceptors.set(interceptors);
try
{
interceptors.handle_send_request();
}
catch (ForwardRequest fwd)
{
// Should not happen for remote requests
}
catch (RemarshalException re)
{
// RemarshalExceptions explicitely caught, because in
// that case, localInterceptors must stay set
throw re;
}
catch (RuntimeException e)
{
// If we are throwing a system exception then this will disrupt the call path.
// Therefore nullify localInterceptors so it doesn't appear we are still in an
// interceptor call.
localInterceptors.set(null);
throw e;
}
}
ClientConnection connectionToUse = null;
try
{
ReplyGroup group = null;
try
{
synchronized (bind_sync)
{
if ( ! bound )
{
// Somehow the connection got closed under us
throw new COMM_FAILURE("Connection closed");
}
else if (ros.getConnection() == connections[currentConnection.ordinal ()])
{
// RequestOutputStream has been created for
// exactly this connection
connectionToUse = connections[currentConnection.ordinal ()];
connectionToUse.incClients();
}
else
{
logger.debug("invoke: RemarshalException");
// RequestOutputStream has been created for
// another connection, so try again
throw new RemarshalException();
}
}
group = getReplyGroup (connectionToUse);
if ( !ros.response_expected() ) // oneway op
{
invoke_oneway (ros, connectionToUse, interceptors, group);
}
else
{
// response expected, synchronous or asynchronous
receiver = new ReplyReceiver(this, group,
ros.operation(),
ros.getReplyEndTime(),
interceptors, replyHandler, selectorManager);
try
{
receiver.configure(configuration);
}
catch (ConfigurationException ex)
{
logger.error ("Configuration problem with ReplyReceiver", ex);
throw new INTERNAL ("Caught configuration exception setting up ReplyReceiver.");
}
group.addHolder (receiver);
// Use the local copy of the client connection to avoid trouble
// with something else affecting the real connections[currentConnection].
connectionToUse.sendRequest(ros, receiver, ros.requestId(), true);
getParsedIOR ().markLastUsedProfile ();
}
}
catch ( org.omg.CORBA.SystemException cfe )
{
logger.debug("invoke[-->]: SystemException", cfe);
if( !async )
{
// Remove ReplyReceiver to break up reference cycle
// Otherwise gc will not detect this Delegate and
// will never finalize it.
if (group != null)
group.removeHolder(receiver);
}
try
{
interceptors.handle_receive_exception ( cfe );
}
catch (ForwardRequest fwd)
{
// Should not happen for remote requests
}
catch (RemarshalException e)
{
logger.debug("ClientInterceptors receive_exception threw RemarshalException (via a ForwardRequest)." +
"resetting pior to avoid extraneous forwarding loop.");
resetPior ();
throw e;
}
// The exception is a TRANSIENT, so try rebinding.
if ( cfe instanceof org.omg.CORBA.TRANSIENT )
{
if (checkNextProfile (false))
{
if (logger.isDebugEnabled())
{
logger.debug ("Delegate._invoke_internal: looping on " + cfe);
}
throw new RemarshalException();
}
else
{
if (logger.isDebugEnabled())
{
logger.debug ("Delegate._invoke_internal: Not looping on " + cfe);
}
}
}
if (!(cfe instanceof org.omg.CORBA.TIMEOUT))
{
if (logger.isDebugEnabled())
{
logger.debug ("Delegate._invoke_internal: closing connection due to " + cfe);
}
disconnect(connectionToUse);
}
throw cfe;
}
finally
{
if (orb.hasRequestInterceptors())
{
localInterceptors.set(null);
}
}
try
{
if ( !async && receiver != null )
{
// Synchronous invocation, response expected.
// This call blocks until the reply arrives.
org.omg.CORBA.portable.InputStream is = receiver.getReply();
((CDRInputStream)is).updateMutatorConnection (connectionToUse.getGIOPConnection());
clearInvocationContext();
if (currentCtxt.containsKey (INVOCATION_KEY.INTERCEPTOR_CALL) ||
currentCtxt.containsKey (INVOCATION_KEY.SERVANT_PREINVOKE) )
{
currentCtxt.put (INVOCATION_KEY.CLEAR_ALLOWED, null);
}
return is;
}
}
catch(SystemException e)
{
logger.debug("invoke[<--]: SystemException", e);
// An Object Not Exist on a forwarded reference should retry
// on the original to get forwarded again to the right server
if ( e instanceof org.omg.CORBA.OBJECT_NOT_EXIST)
{
if (e.minor != 0 &&
checkNextProfile (true))
{
throw new RemarshalException();
}
}
// If the attempt to read the reply throws a system exception its
// possible that the pending_replies will not get cleaned up.
if (group != null)
group.removeHolder(receiver);
disconnect(connectionToUse);
throw e;
}
}
finally
{
if (connectionToUse != null)
{
conn_mg.releaseConnection(connectionToUse);
}
}
return null;
}
/**
* Internal method to check whether the timeouts have been exceeded.
* @param reqET the request end time
* @param repET the reply end time param
*/
private void checkTimeout (UtcT reqET, UtcT repET)
{
if (reqET != null)
{
if (Time.hasPassed(reqET))
{
throw new TIMEOUT("Request End Time exceeded",
2,
CompletionStatus.COMPLETED_NO);
}
}
if (repET != null)
{
if (Time.hasPassed(repET))
{
throw new TIMEOUT("Reply End Time exceeded",
3,
CompletionStatus.COMPLETED_NO);
}
}
}
private void disconnect(ClientConnection connectionInUse)
{
if (connectionInUse == null)
{
return;
}
if (!disconnectAfterNonRecoverableSystemException)
{
return;
}
synchronized(bind_sync)
{
if (connections[currentConnection.ordinal ()] == null)
{
return;
}
if (connections[currentConnection.ordinal ()] != connectionInUse)
{
return;
}
logger.debug("release the connection");
conn_mg.releaseConnection( connections[currentConnection.ordinal ()] );
connections[currentConnection.ordinal ()] = null;
bound = false;
}
}
private void invoke_oneway (RequestOutputStream ros,
ClientConnection connectionToUse,
ClientInterceptorHandler interceptors,
ReplyGroup group)
throws RemarshalException, ApplicationException
{
switch (ros.syncScope())
{
case SYNC_NONE.value:
RequestOutputStream copy = new RequestOutputStream(ros);
passToTransport (connectionToUse, copy);
try
{
interceptors.handle_receive_other (SUCCESSFUL.value);
}
catch (ForwardRequest fwd)
{
// Should not happen for remote requests
}
break;
case SYNC_WITH_TRANSPORT.value:
connectionToUse.sendRequest (ros, false);
getParsedIOR ().markLastUsedProfile ();
try
{
interceptors.handle_receive_other (SUCCESSFUL.value);
}
catch (ForwardRequest fwd)
{
/// Should not happen for remote requests
}
break;
case SYNC_WITH_SERVER.value:
case SYNC_WITH_TARGET.value:
ReplyReceiver rcv = new ReplyReceiver (this,
group,
ros.operation(),
ros.getReplyEndTime(),
interceptors,
null, selectorManager);
try
{
rcv.configure(configuration);
}
catch (ConfigurationException ex)
{
logger.error ("Configuration problem with ReplyReceiver", ex);
throw new INTERNAL ("Caught configuration exception setting up ReplyReceiver.");
}
if (connections[TransportType.MIOP.ordinal ()] != null)
{
connections[TransportType.MIOP.ordinal ()].sendRequest(ros,false);
}
else
{
connectionToUse.sendRequest (ros, rcv, ros.requestId(), true);
// connections[TransportType.IIOP.ordinal ()].sendRequest (ros, rcv, ros.requestId(), true);
}
getParsedIOR ().markLastUsedProfile ();
ReplyInputStream in = rcv.getReply();
try
{
interceptors.handle_receive_reply (in);
}
catch (ForwardRequest fwd)
{
/// Should not happen for remote requests
}
break;
default:
throw new org.omg.CORBA.MARSHAL
("Illegal SYNC_SCOPE: " + ros.syncScope(),
0, CompletionStatus.COMPLETED_MAYBE);
}
}
private ReplyGroup getReplyGroup (ClientConnection connectionToUse)
{
// The ReplyGroup collects pending replies for a specific target. This
// allows separation between requests that may have been sent to an IMR
// and those that were sent to the final target, as could be the case
// with massively threaded clients.
org.omg.ETF.Profile profile = connectionToUse.getRegisteredProfile();
ReplyGroup group = groups.get (profile);
if (group == null)
{
if (logger.isDebugEnabled())
{
logger.debug ("Adding new retry group for " + profile);
}
ReplyGroup g = new ReplyGroup (this, profile);
group = groups.putIfAbsent (profile, g);
if (group == null)
{
group = g;
}
}
return group;
}
private void passToTransport (final ClientConnection connectionToUse, final RequestOutputStream ros)
{
new Thread (new Runnable()
{
@Override
public void run()
{
try
{
connectionToUse.sendRequest (ros, false);
getParsedIOR ().markLastUsedProfile ();
}
catch (Throwable e)
{
if (logger.isWarnEnabled())
{
logger.warn ("Caught CORBA SystemException ", e);
}
}
}
},
"PassToTransport").start();
}
private void randomMilliSecDelay()
{
if (randomDelay == null)
{
randomDelay = new Random(10000);
}
// delay time will be between 1-3 seconds
int r = randomDelay.nextInt(3100);
r = (r < 1000? 1000 : r);
try
{
Thread.sleep(r);
}
catch (Exception e)
{
// ignore
}
}
private boolean checkNextProfile (boolean forward_only)
{
boolean doRebind = false;
if (forward_only && (!isPiorForwarded ()))
{
return false;
}
synchronized ( bind_sync )
{
if (getParsedIOR().getProfiles().size() > 1)
{
Profile curProfile = getParsedIOR().getNextEffectiveProfile();
if( logger.isDebugEnabled())
{
Profile lastProfile = getParsedIOR().getLastUsedProfile();
logger.debug("checkNextProfile: new = "
+ curProfile + " last = " + lastProfile);
}
if (curProfile != null &&
!curProfile.equals (getParsedIOR().getLastUsedProfile()))
{
doRebind = true;
}
}
if (!doRebind)
{
ArrayDeque<Map<INVOCATION_KEY, UtcT>> invocationStack = invocationContext.get ();
Map<INVOCATION_KEY, UtcT> currentCtxt = invocationStack.peek();
boolean doCorbaName = false;
if (isPiorForwarded ())
{
if (currentCtxt == null)
{
if (logger.isDebugEnabled ())
logger.debug ("checkNextProfile, current context is null");
return false;
}
if (currentCtxt.containsKey (INVOCATION_KEY.FORWARD_RESET))
{
return false;
}
resetPior ();
doCorbaName = true;
currentCtxt.put (INVOCATION_KEY.FORWARD_RESET, null);
doRebind = true;
}
else
{
doCorbaName = !currentCtxt.containsKey (INVOCATION_KEY.CORBANAME_RESET);
}
if (doCorbaName && getParsedIOR().useCorbaName())
{
currentCtxt.put (INVOCATION_KEY.CORBANAME_RESET, null);
if (logger.isDebugEnabled())
{
logger.debug ("Delegate.checkNextProfile: resetting corbaname for next use");
}
getParsedIOR().reparseCorbaName();
// just resetting for next call
}
}
if (doRebind)
{
rebind();
}
return doRebind;
}
}
public void invokeInterceptors( ClientRequestInfoImpl info, short op )
throws RemarshalException
{
ClientInterceptorIterator intercept_iter =
orb.getInterceptorManager().getClientIterator();
try
{
intercept_iter.iterate( info, op );
}
catch (ForwardRequest fwd )
{
if (logger.isDebugEnabled ())
logger.debug ("Delegate.invokeInterceptors calling rebind on forward");
forwardToObj (fwd.forward);
throw new RemarshalException();
}
catch ( org.omg.CORBA.UserException ue )
{
if (logger.isErrorEnabled())
{
logger.error( ue.getMessage() );
}
}
}
/**
* <code>repository_id</code> returns a repository ID.
*
* @return a <code>String</code> value
*/
@Override
public String repository_id (org.omg.CORBA.Object self)
{
return getParsedIOR().getTypeId();
}
/**
* Determines whether the object denoted by self
* has type logical_type_id or a subtype of it
*/
@Override
public boolean is_a( org.omg.CORBA.Object self, String logical_type_id )
{
/* First, try to find out without a remote invocation. */
/* check most derived type as defined in the IOR first
* (this type might otherwise not be found if the helper
* is consulted and the reference was not narrowed to
* the most derived type. In this case, the ids returned by
* the helper won't contain the most derived type
*/
if (ior != null && ior.type_id.equals(logical_type_id))
{
return true;
}
ParsedIOR pior = getParsedIOR();
if ( pior.getTypeId().equals( logical_type_id ) )
{
return true;
}
/* The Ids in ObjectImpl will at least contain the type id
found in the object reference itself.
*/
String[] ids = ( ( org.omg.CORBA.portable.ObjectImpl ) self )._ids();
/* the last id will be CORBA.Object, and we know that already... */
for ( int i = 0; i < ids.length - 1; i++ )
{
if ( ids[ i ].equals( logical_type_id ) )
{
return true;
}
}
/* ok, we could not affirm by simply looking at the locally available
type ids, so ask the object itself */
// If local object call _is_a directly
if (is_really_local(self))
{
if (logger.isDebugEnabled())
{
logger.debug("Located " + self + " on local POA; assuming local.");
}
org.omg.PortableServer.Servant servant;
org.omg.CORBA.portable.ServantObject so = null;
while (so == null)
{
so = servant_preinvoke (self, "_is_a", java.lang.Object.class);
}
try
{
servant = (org.omg.PortableServer.Servant)so.servant;
orb.set_delegate(servant);
return servant._is_a(logical_type_id);
}
finally
{
servant_postinvoke(self, so);
}
}
// The check below avoids trying to load a stub for CORBA.Object.
// (It would be faster to check that ids.length > 1, but Sun's
// CosNaming JNDI provider calls _is_a() on some weird ObjectImpl
// instances whose _ids() method returns an array of length two,
// containing two Strings equal to "IDL:omg.org/CORBA/Object:1.0".)
if (avoidIsARemoteCall &&
!ids[0].equals("IDL:omg.org/CORBA/Object:1.0"))
{
// Try to avoid remote call - is it a derived type?
try
{
// Retrieve the local stub for the object in question. Then call the _ids method
// and see if any match the logical_type_id otherwise fall back to remote.
final String classname = RepositoryID.className( ids[0], "Stub", null );
int lastDot = classname.lastIndexOf( '.' );
StringBuffer buffer = new StringBuffer( classname.substring( 0, lastDot + 1) );
buffer.append( '_' );
buffer.append( classname.substring( lastDot + 1 ) );
// This will only work if there is a correspondence between the Java class
// name and the Repository ID. If prefixes have been using then this mapping
// may have been lost.
// First, search with stub name
// if not found, try with the 'org.omg.stub' prefix to support package
// with javax prefix
Class<?> stub=null;
try
{
stub = ObjectUtil.classForName( buffer.toString());
}
catch (ClassNotFoundException e)
{
stub = ObjectUtil.classForName("org.omg.stub."+buffer.toString());
}
Method idm = stub.getMethod ( "_ids", (Class[]) null );
String newids[] = (String[] )idm.invoke( stub.newInstance(), (java.lang.Object[]) null );
for ( int i = 0; i < newids.length ; i++ )
{
if (newids[i].equals( logical_type_id ) )
{
return true;
}
}
}
// If it fails fall back to a remote call.
catch (ClassNotFoundException e)
{
// ignore
}
catch (IllegalArgumentException e)
{
// ignore
}
catch (SecurityException e)
{
// ignore
}
catch (NoSuchMethodException e)
{
// ignore
}
catch (IllegalAccessException e)
{
// ignore
}
catch (InvocationTargetException e)
{
// ignore
}
catch (InstantiationException e)
{
// ignore
}
catch (SystemException e)
{
// ignore
}
logger.debug("trying is_a remotely");
}
org.omg.CORBA.portable.InputStream is = invokeBuiltin (self, "_is_a", logical_type_id);
return (is == null) ? false : is.read_boolean();
}
@Override
public boolean is_equivalent(org.omg.CORBA.Object self,
org.omg.CORBA.Object obj)
{
checkORB();
boolean result = true;
if (self != obj)
{
ParsedIOR pior1 = new ParsedIOR( orb, obj.toString() );
ParsedIOR pior2 = new ParsedIOR( orb, self.toString() );
result = pior2.getIDString().equals( pior1.getIDString() );
}
return result;
}
public String getIDString()
{
return getParsedIOR().getIDString();
}
/**
* @return true if this object lives on a local POA and
* interceptors are not installed. When interceptors are
* installed this returns false so that stubs do not call
* direct to implementation, avoiding installed interceptors.
*/
@Override
public boolean is_local(org.omg.CORBA.Object self)
{
if (ignoreNextCallToIsLocal.get() == Boolean.TRUE)
{
ignoreNextCallToIsLocal.set(Boolean.FALSE);
return false;
}
if (isLocalHistoricalInterceptors && localInterceptors.get() == null && orb.hasRequestInterceptors())
{
return false;
}
return is_really_local(self);
}
/**
* @return true if this object lives on a local POA
*/
private boolean is_really_local(org.omg.CORBA.Object self)
{
if (poa == null)
{
resolvePOA(self);
}
return poa != null;
}
public boolean is_nil()
{
ParsedIOR pior = getParsedIOR();
return ( pior.getIOR().type_id.equals( "" ) &&
pior.getIOR().profiles.length == 0 );
}
@Override
public boolean non_existent (org.omg.CORBA.Object self)
{
// If local object call _non_existent directly
if (is_really_local(self))
{
org.omg.PortableServer.Servant servant;
org.omg.CORBA.portable.ServantObject so = null;
try
{
while (so == null)
{
so = servant_preinvoke(self, "_non_existent", java.lang.Object.class);
}
}
catch (OBJECT_NOT_EXIST e)
{
return true;
}
try
{
servant = (org.omg.PortableServer.Servant)so.servant;
orb.set_delegate(servant);
return servant._non_existent();
}
finally
{
servant_postinvoke(self, so);
}
}
org.omg.CORBA.portable.InputStream is = null;
try
{
is = invokeBuiltin (self, "_non_existent", null);
}
catch (OBJECT_NOT_EXIST e)
{
return true;
}
return (is == null) ? false : is.read_boolean();
}
@Override
public org.omg.CORBA.Object get_component (org.omg.CORBA.Object self)
{
// If local object call _get_component directly
if (is_really_local(self))
{
org.omg.PortableServer.Servant servant;
org.omg.CORBA.portable.ServantObject so = null;
while (so == null)
{
so = servant_preinvoke(self, "_get_component", java.lang.Object.class);
}
try
{
servant = (org.omg.PortableServer.Servant)so.servant;
orb.set_delegate(servant);
return servant._get_component();
}
finally
{
servant_postinvoke(self, so);
}
}
org.omg.CORBA.portable.InputStream is = invokeBuiltin (self, "_get_component", null);
return (is == null) ? null : is.read_Object();
}
private org.omg.CORBA.portable.InputStream invokeBuiltin (org.omg.CORBA.Object self, String op, String arg)
{
org.omg.CORBA.portable.OutputStream os;
// The old behavior was to loop forever, which will happen here if maxBuiltinRetries is 0.
for (int retries = 0; maxBuiltinRetries == 0 || retries < maxBuiltinRetries; retries ++)
{
try
{
os = request(self, op, true);
if (arg != null)
os.write_string(arg);
return invoke(self, os);
}
catch (RemarshalException re)
{
// Ignored
}
catch (ApplicationException ax)
{
throw new INTERNAL("Unexpected exception " + ax.getId());
}
}
return null;
}
@Override
public org.omg.CORBA.ORB orb( org.omg.CORBA.Object self )
{
return orb;
}
/**
* Called to indicate that this Delegate will no longer be used by
* the client. The Delegate unregisters itself from the underlying
* GIOPConnection. If there are no other Delegates using that
* connection, it will be closed and disposed of altogether.
*/
@Override
public void release( org.omg.CORBA.Object self )
{
synchronized ( bind_sync )
{
if (!bound)
{
return;
}
if ( connections[currentConnection.ordinal ()] != null )
{
conn_mg.releaseConnection( connections[currentConnection.ordinal ()] );
connections[currentConnection.ordinal ()] = null;
}
bound = false;
// Call using string rather than this to prevent data race
// warning.
orb._release( getParsedIOR().getIORString() );
if ( logger.isDebugEnabled() )
{
logger.debug("Delegate released!");
}
}
}
/**
* releases the InputStream
*/
@Override
public void releaseReply( org.omg.CORBA.Object self,
org.omg.CORBA.portable.InputStream is )
{
if ( is != null )
{
try
{
is.close();
}
catch ( java.io.IOException io )
{
// ignored
}
}
Time.waitFor (getReplyStartTime());
}
@Override
public org.omg.CORBA.Request request( org.omg.CORBA.Object self,
String operation )
{
orb.perform_work();
synchronized ( bind_sync )
{
bind();
return new org.jacorb.orb.dii.Request( self,
orb,
connections[currentConnection.ordinal ()],
getParsedIOR().get_object_key(),
operation );
}
}
/**
*/
@Override
public org.omg.CORBA.portable.OutputStream request(org.omg.CORBA.Object self,
String operation,
boolean responseExpected )
{
orb.perform_work();
ArrayDeque<Map<INVOCATION_KEY, UtcT>> invocationStack = getInvocationContext();
Map<INVOCATION_KEY, UtcT> currentCtxt = null;
if (! invocationStack.isEmpty())
{
currentCtxt = invocationStack.peek();
}
if (currentCtxt == null ||
currentCtxt.containsKey (INVOCATION_KEY.INTERCEPTOR_CALL) ||
currentCtxt.containsKey (INVOCATION_KEY.SERVANT_PREINVOKE))
{
currentCtxt = new HashMap<INVOCATION_KEY, UtcT>();
invocationStack.push (currentCtxt);
}
UtcT requestEndTime = currentCtxt.get (INVOCATION_KEY.REQUEST_END_TIME);
UtcT replyEndTime = currentCtxt.get (INVOCATION_KEY.REPLY_END_TIME);
if (!disableClientOrbPolicies)
{
// Compute the deadlines for this request based on any absolute or
// relative timing policies that have been specified. Compute this
// now, because it is the earliest possible time, and therefore any
// relative timeouts will cover the entire invocation.
if (requestEndTime == null)
{
requestEndTime = getRequestEndTime();
final long requestTimeout = getRelativeRequestTimeout();
if ((requestTimeout > 0) || (requestEndTime != null))
{
requestEndTime = Time.earliest(Time.corbaFuture (requestTimeout), requestEndTime);
if (Time.hasPassed(requestEndTime))
{
clearInvocationContext();
throw new TIMEOUT("Request End Time exceeded prior to invocation",
2,
CompletionStatus.COMPLETED_NO);
}
}
currentCtxt.put (INVOCATION_KEY.REQUEST_END_TIME, requestEndTime);
}
else
{
if (Time.hasPassed (requestEndTime))
{
clearInvocationContext();
throw new TIMEOUT("Request End Time exceeded",
2,
CompletionStatus.COMPLETED_NO);
}
}
if (replyEndTime == null)
{
replyEndTime = getReplyEndTime();
final long roundtripTimeout = getRelativeRoundtripTimeout();
if ((roundtripTimeout > 0) || (replyEndTime != null))
{
replyEndTime = Time.earliest(Time.corbaFuture (roundtripTimeout), replyEndTime);
if (Time.hasPassed(replyEndTime))
{
clearInvocationContext();
throw new TIMEOUT("Reply End Time exceeded prior to invocation",
3,
CompletionStatus.COMPLETED_NO);
}
}
currentCtxt.put (INVOCATION_KEY.REPLY_END_TIME, replyEndTime);
}
else
{
if (Time.hasPassed(replyEndTime))
{
clearInvocationContext();
throw new TIMEOUT("Reply End Time exceeded",
3,
CompletionStatus.COMPLETED_NO);
}
}
}
synchronized ( bind_sync )
{
if ( connections[currentConnection.ordinal ()] != null &&
connections[currentConnection.ordinal ()].isClosed())
{
release(self);
}
bind();
ParsedIOR ior = getParsedIOR();
//MIOP
//the object key must be the representant objectKey if the reply is
//expected and the request is a group request
org.omg.ETF.Profile profile = ior.getEffectiveProfile();
byte[] objectKey = profile.get_object_key();
// Default to the version within the EffectiveProfile
int giopMinor = profile.version().minor;
if (profile instanceof MIOPProfile)
{
if(responseExpected)
{
IIOPProfile ip = ((MIOPProfile)profile).getGroupIIOPProfile();
if (ip == null)
{
throw new INV_OBJREF ("No Group IIOP Profile so unable to send a two-way request.");
}
objectKey = ip.get_object_key();
currentConnection = TransportType.IIOP;
}
else
{
currentConnection = TransportType.MIOP;
}
// If we are using MIOP then it encodes its own version. So at this point we set
// the version for GIOP to be the one configured.
giopMinor = defaultGiopMinor;
}
else
{
currentConnection = TransportType.IIOP;
}
RequestOutputStream out =
new RequestOutputStream( orb,
connections[currentConnection.ordinal ()],
connections[currentConnection.ordinal ()].getId(),
operation,
responseExpected,
getSyncScope(),
getRequestStartTime(),
requestEndTime,
replyEndTime,
objectKey,
giopMinor);
// CodeSets are only negotiated once per connection,
// not for each individual request
// (CORBA 3.0, 13.10.2.6, second paragraph).
if (!connections[currentConnection.ordinal ()].isTCSNegotiated())
{
connections[currentConnection.ordinal ()].setCodeSet(ior);
}
//Setting the codesets not until here results in the
//header being written using the default codesets. On the
//other hand, the server side must have already read the
//header to discover the codeset service context.
out.setCodeSets( connections[currentConnection.ordinal ()].getTCS(), connections[currentConnection.ordinal ()].getTCSW() );
out.updateMutatorConnection (connections[currentConnection.ordinal ()].getGIOPConnection());
return out;
}
}
/**
* Overrides servant_postinvoke() in org.omg.CORBA.portable.Delegate<BR>
* called from generated stubs after a local operation
*/
@Override
public void servant_postinvoke( org.omg.CORBA.Object self, ServantObject servant )
{
try
{
if (orb.hasRequestInterceptors())
{
ServerRequestInfoImpl sinfo = ( (ServantObjectImpl) servant).getServerRequestInfo();
DefaultClientInterceptorHandler interceptors =
( (ServantObjectImpl) servant).getClientInterceptorHandler();
if (sinfo != null && interceptors != null)
{
Collection<ServiceContext> ctx = sinfo.getReplyServiceContexts();
interceptors.getInfo ().setReplyServiceContexts (ctx.toArray (new ServiceContext[ctx.size ()]));
orb.getInterceptorManager().removeLocalPICurrent();
try
{
if (sinfo.reply_status() == SUCCESSFUL.value)
{
interceptors.handle_receive_reply (null);
}
else if (sinfo.reply_status() == SYSTEM_EXCEPTION.value)
{
interceptors.handle_receive_exception (
SystemExceptionHelper.read (sinfo.sending_exception().create_input_stream()));
}
else if (sinfo.reply_status() == LOCATION_FORWARD.value)
{
/**
* If the ForwardRequest was thrown at the send_exception interception
* point we will not be able to get the forward_reference from the
* server info and a BAD_INV_ORDER will be thrown. In that case handle
* as a simple receive_other.
*/
try
{
interceptors.handle_location_forward (null, sinfo.forward_reference());
}
catch (BAD_INV_ORDER bio)
{
interceptors.handle_receive_other(sinfo.reply_status());
}
}
else if (sinfo.reply_status() == USER_EXCEPTION.value)
{
interceptors.handle_receive_other (sinfo.reply_status());
}
}
catch (ForwardRequest fwd)
{
throw new RuntimeException (fwd);
}
catch (RemarshalException re)
{
// Should not happen for a local invocation
}
}
}
if (poa != null)
{
if ( poa.isUseServantManager() &&
! poa.isRetain() &&
cookie != null &&
invokedOperation != null )
{
// ServantManager is a ServantLocator:
// call postinvoke
try
{
byte [] oid =
POAUtil.extractOID( getParsedIOR().get_object_key() );
org.omg.PortableServer.ServantLocator sl =
( org.omg.PortableServer.ServantLocator ) poa.get_servant_manager();
sl.postinvoke( oid, poa, invokedOperation, cookie.value, (Servant)servant.servant );
// delete stored values
cookie = null;
invokedOperation = null;
}
catch ( Throwable e )
{
if (logger.isWarnEnabled())
{
logger.warn( e.getMessage() );
}
}
}
}
}
finally
{
if (poa != null)
{
poa.removeLocalRequest();
}
orb.getPOACurrent()._removeContext( Thread.currentThread() );
if (orb.getInterceptorManager() != null)
{
orb.getInterceptorManager().removeLocalPICurrent ();
}
}
}
/**
* Overrides servant_preinvoke() in org.omg.CORBA.portable.Delegate<BR>
* called from generated stubs before a local operation
*/
@Override
public ServantObject servant_preinvoke( org.omg.CORBA.Object self,
String operation,
@SuppressWarnings("rawtypes") Class expectedType )
{
InterceptorManager manager = null;
ServerInterceptorIterator interceptorIterator = null;
ServerRequestInfoImpl sinfo = null;
Collection<ServiceContext> contexts = null;
DefaultClientInterceptorHandler interceptors = null;
boolean addedContext = false;
if (poa == null)
{
resolvePOA(self);
}
if (poa == null)
{
if (logger.isWarnEnabled())
{
logger.warn("No POA! servant_preinvoke returns null");
}
return null;
}
Map<INVOCATION_KEY, UtcT> currentContext = new HashMap<INVOCATION_KEY, UtcT>();
currentContext.put (INVOCATION_KEY.SERVANT_PREINVOKE, null);
getInvocationContext().push (currentContext);
// remember that a local request is outstanding. On
// any exit through an exception, this must be cleared again,
// otherwise the POA will hangon destruction (bug #400).
poa.addLocalRequest();
final ServantObject servantObject = new ServantObjectImpl();
( (ServantObjectImpl) servantObject).setORB (orb);
try
{
if (orb.hasClientRequestInterceptors())
{
interceptors = new DefaultClientInterceptorHandler(orb,
operation,
true,
SYNC_WITH_TARGET.value,
self,
this,
getBaseIOR());
}
if (orb.hasRequestInterceptors() && interceptors != null)
{
try
{
interceptors.handle_send_request();
}
catch (ForwardRequest fwd)
{
( (ObjectImpl) self)._set_delegate ( ( (ObjectImpl) fwd.forward)._get_delegate());
return null;
}
catch (RemarshalException re)
{
// Should not happen for a local server invocation.
}
}
if (interceptors != null)
{
contexts = interceptors.getInfo().getRequestServiceContexts();
}
if (orb.hasServerRequestInterceptors())
{
sinfo = new ServerRequestInfoImpl
(
orb,
contexts,
(org.omg.PortableServer.Servant) servantObject.servant,
getObjectId(),
operation,
true,
SYNC_WITH_TARGET.value
);
manager = orb.getInterceptorManager();
sinfo.setCurrent (manager.getEmptyCurrent());
interceptorIterator = manager.getServerIterator();
( (org.jacorb.orb.ServantObjectImpl ) servantObject).setServerRequestInfo (sinfo);
// Note: this code is very similar to the below hasServerRequestInterceptors try/catch
try
{
manager.setLocalPICurrent (sinfo.current ());
interceptorIterator.iterate
(
sinfo,
ServerInterceptorIterator.RECEIVE_REQUEST_SERVICE_CONTEXTS
);
}
catch (ForwardRequest fwd)
{
if (interceptors != null)
{
interceptors.handle_location_forward (null, fwd.forward);
}
( (ObjectImpl) self)._set_delegate ( ( (ObjectImpl) fwd.forward)._get_delegate());
return null;
}
catch (Exception ex)
{
if (interceptors != null && orb.hasRequestInterceptors())
{
manager.removeLocalPICurrent ();
try
{
if (ex instanceof SystemException)
{
interceptors.handle_receive_exception ( (SystemException) ex);
}
else if (ex instanceof ApplicationException)
{
interceptors.handle_receive_exception ( (ApplicationException) ex, null);
}
}
catch (ForwardRequest fwd)
{
( (ObjectImpl) self)._set_delegate ( ( (ObjectImpl) fwd.forward)._get_delegate());
return null;
}
}
throw ex;
}
}
try
{
if ( ( poa.isRetain() && !poa.isUseServantManager() ) ||
poa.useDefaultServant() )
{
// no ServantManagers, but AOM use
try
{
servantObject.servant = poa.reference_to_servant( self );
}
catch( WrongAdapter e )
{
throw new OBJ_ADAPTER( "WrongAdapter caught when converting servant to reference. " + e );
}
catch( WrongPolicy e )
{
throw new OBJ_ADAPTER("WrongPolicy caught" + e );
}
catch( ObjectNotActive e )
{
throw new org.omg.CORBA.OBJECT_NOT_EXIST();
}
}
else if ( poa.isUseServantManager() )
{
byte [] oid =
POAUtil.extractOID( getParsedIOR().get_object_key() );
org.omg.PortableServer.ServantManager sm = poa.get_servant_manager();
if ( poa.isRetain() )
{
// ServantManager is a ServantActivator. Use the AOM to
// incarnate this or return the servant. It will correctly
// synchrnoize the requests.
servantObject.servant = poa._incarnateServant(oid, (ServantActivator)sm);
}
else
{
// ServantManager is a ServantLocator: locate a servant
org.omg.PortableServer.ServantLocator sl =
( org.omg.PortableServer.ServantLocator ) sm;
// store this for postinvoke
cookie = new org.omg.PortableServer.ServantLocatorPackage.CookieHolder();
invokedOperation = operation;
servantObject.servant = sl.preinvoke( oid, poa, operation, cookie );
}
((org.omg.CORBA_2_3.ORB)orb).set_delegate(servantObject.servant);
}
else
{
throw new INTERNAL("Internal error: we should not have got to this piece of code!");
}
}
catch( WrongPolicy e )
{
throw new OBJ_ADAPTER( "WrongPolicy caught" + e );
}
catch( org.omg.PortableServer.ForwardRequest e )
{
if( logger.isDebugEnabled() )
{
logger.debug("Caught forwardrequest to " + e.forward_reference + " from " + self );
}
( (ObjectImpl) self)._set_delegate ( ( (ObjectImpl) e.forward_reference)._get_delegate());
return null;
}
if ( !expectedType.isInstance( servantObject.servant ) )
{
if( logger.isWarnEnabled() )
{
logger.warn("Expected " + expectedType +
" got " + servantObject.servant.getClass() );
}
ignoreNextCallToIsLocal.set(Boolean.TRUE);
poa.removeLocalRequest();
return null;
}
orb.getPOACurrent()._addContext
(
Thread.currentThread(),
new org.jacorb.poa.LocalInvocationContext
(
orb,
poa,
getObjectId(),
( org.omg.PortableServer.Servant ) servantObject.servant
)
);
addedContext = true;
( (org.jacorb.orb.ServantObjectImpl )servantObject).setClientInterceptorHandler (interceptors);
if (orb.hasServerRequestInterceptors())
{
sinfo = ( (org.jacorb.orb.ServantObjectImpl ) servantObject).getServerRequestInfo();
sinfo.setServant((org.omg.PortableServer.Servant) servantObject.servant);
interceptorIterator = manager.getServerIterator();
( (org.jacorb.orb.ServantObjectImpl ) servantObject).setServerRequestInfo (sinfo);
// Note: this code is very similar to the above hasServerRequestInterceptors try/catch
try
{
manager.setLocalPICurrent (sinfo.current ());
interceptorIterator.iterate
(
sinfo,
ServerInterceptorIterator.RECEIVE_REQUEST
);
}
catch (ForwardRequest fwd)
{
if (interceptors != null)
{
interceptors.handle_location_forward (null, fwd.forward);
}
( (ObjectImpl) self)._set_delegate ( ( (ObjectImpl) fwd.forward)._get_delegate());
return null;
}
catch (Exception ex)
{
Collection<ServiceContext> ctx = sinfo.getReplyServiceContexts();
interceptors.getInfo ().setReplyServiceContexts (ctx.toArray (new ServiceContext[ctx.size ()]));
manager.removeLocalPICurrent ();
if (interceptors != null && orb.hasRequestInterceptors())
{
try
{
if (ex instanceof SystemException)
{
interceptors.handle_receive_exception ( (SystemException) ex);
}
else if (ex instanceof ApplicationException)
{
interceptors.handle_receive_exception ( (ApplicationException) ex, null);
}
}
catch (ForwardRequest fwd)
{
( (ObjectImpl) self)._set_delegate ( ( (ObjectImpl) fwd.forward)._get_delegate());
return null;
}
}
throw ex;
}
/**
* If this is an internal ORB call from is_a or non_existent then we need
* to complete the interception point SEND_REPLY. In other situations this will
* happen in the stub via the normalCompletion call but this will not be
* the case for internal ORB Calls
*/
if (operation.equals ("_is_a") || operation.equals ("_non_existent") ||
operation.equals("_interface") || operation.equals ("_get_component"))
{
interceptorIterator.iterate
(
sinfo,
ServerInterceptorIterator.SEND_REPLY
);
}
}
return servantObject;
}
catch (Exception e)
{
// Clean up first (added to fix bug #400)
poa.removeLocalRequest();
logger.debug("unexpected exception during servant_preinvoke", e);
if (addedContext)
{
orb.getPOACurrent()._removeContext( Thread.currentThread() );
}
if (orb.getInterceptorManager() != null)
{
orb.getInterceptorManager().removeLocalPICurrent ();
}
if (e instanceof OBJECT_NOT_EXIST)
{
throw (OBJECT_NOT_EXIST)e;
}
if (e instanceof ObjectNotActive)
{
throw new OBJECT_NOT_EXIST();
}
if (e instanceof RuntimeException)
{
throw (RuntimeException) e;
}
throw new OBJ_ADAPTER("unexpected exception: " + e);
}
finally
{
Map<INVOCATION_KEY, UtcT> head = Delegate.getInvocationContext().peek ();
if (head == currentContext)
{
Delegate.getInvocationContext().pop ();
}
}
}
@Override
public String toString()
{
synchronized ( bind_sync )
{
return getBaseIOR().getIORString();
}
}
@Override
public String toString( org.omg.CORBA.Object self )
{
return toString();
}
public String typeId()
{
synchronized ( bind_sync )
{
return getBaseIOR().getIOR().type_id;
}
}
@Override
public org.omg.CORBA.Object set_policy_override( org.omg.CORBA.Object self,
org.omg.CORBA.Policy[] policies,
org.omg.CORBA.SetOverrideType set_add )
{
return set_policy_overrides (self, policies, set_add);
}
@Override
public org.omg.CORBA.Object set_policy_overrides( org.omg.CORBA.Object self,
org.omg.CORBA.Policy[] policies,
org.omg.CORBA.SetOverrideType set_add )
{
if (disableClientOrbPolicies)
{
throw new BAD_PARAM("policy override is disabled per configuration");
}
// According to CORBA 3, 4.3.9.1 this should return a new Object with
// the policies applied to that.
org.omg.CORBA.Object result = duplicate(self);
Delegate delResult = (Delegate)((ObjectImpl)result)._get_delegate();
synchronized(policy_overrides)
{
if ( set_add == org.omg.CORBA.SetOverrideType.ADD_OVERRIDE)
{
// Need to add the overrides within this object to the new one.
delResult.policy_overrides.putAll (policy_overrides);
}
for ( int i = 0; i < policies.length; i++ )
{
delResult.policy_overrides.put(Integer.valueOf(policies[ i ].policy_type()), policies[ i ] );
}
}
return result;
}
@Override
public String get_codebase( org.omg.CORBA.Object self )
{
return getParsedIOR().getCodebaseComponent();
}
/**
* Call work_pending as that does a simple boolean check to establish
* if the ORB has been shutdown - otherwise it throws BAD_INV_ORDER.
*/
private void checkORB()
{
orb.work_pending();
}
@Override
public boolean validate_connection( org.omg.CORBA.Object self,
org.omg.CORBA.PolicyListHolder inconsistent_policies )
{
if (non_existent(self))
{
inconsistent_policies.value = new Policy[ 0 ];
return false;
}
else
{
synchronized ( bind_sync )
{
try
{
bind();
}
catch (final INV_POLICY e)
{
// have some invalid policies.
inconsistent_policies.value = new Policy[ 0 ];
return false;
}
}
}
return true;
}
}