0001: package org.jacorb.orb;
0002:
0003: /*
0004: * JacORB - a free Java ORB
0005: *
0006: * Copyright (C) 1997-2004 Gerald Brose.
0007: *
0008: * This library is free software; you can redistribute it and/or
0009: * modify it under the terms of the GNU Library General Public
0010: * License as published by the Free Software Foundation; either
0011: * version 2 of the License, or (at your option) any later version.
0012: *
0013: * This library is distributed in the hope that it will be useful,
0014: * but WITHOUT ANY WARRANTY; without even the implied warranty of
0015: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
0016: * Library General Public License for more details.
0017: *
0018: * You should have received a copy of the GNU Library General Public
0019: * License along with this library; if not, write to the Free
0020: * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
0021: */
0022:
0023: import java.lang.reflect.InvocationTargetException;
0024: import java.lang.reflect.Method;
0025: import java.util.*;
0026:
0027: import org.apache.avalon.framework.logger.Logger;
0028: import org.apache.avalon.framework.configuration.Configurable;
0029: import org.apache.avalon.framework.configuration.ConfigurationException;
0030:
0031: import org.jacorb.ir.RepositoryID;
0032: import org.jacorb.imr.ImRAccessImpl;
0033: import org.jacorb.orb.giop.*;
0034: import org.jacorb.orb.portableInterceptor.*;
0035: import org.jacorb.orb.util.*;
0036: import org.jacorb.poa.util.POAUtil;
0037: import org.jacorb.util.Time;
0038: import org.jacorb.util.ObjectUtil;
0039: import org.jacorb.config.Configuration;
0040:
0041: import org.omg.CORBA.*;
0042: import org.omg.CORBA.portable.*;
0043: import org.omg.GIOP.LocateStatusType_1_2;
0044: import org.omg.Messaging.*;
0045: import org.omg.PortableInterceptor.SUCCESSFUL;
0046: import org.omg.PortableServer.POAPackage.*;
0047: import org.omg.TimeBase.UtcT;
0048: import org.omg.PortableServer.ServantLocatorPackage.CookieHolder;
0049: import org.omg.PortableServer.Servant;
0050: import org.omg.PortableServer.ServantActivator;
0051:
0052: /**
0053: * JacORB implementation of CORBA object reference
0054: *
0055: * @author Gerald Brose
0056: * @version $Id: Delegate.java,v 1.143 2007/02/15 12:56:06 andre.spiegel Exp $
0057: *
0058: */
0059:
0060: public final class Delegate extends org.omg.CORBA_2_3.portable.Delegate
0061: implements Configurable {
0062: // WARNING: DO NOT USE _pior DIRECTLY, BECAUSE THAT IS NOT MT
0063: // SAFE. USE getParsedIOR() INSTEAD, AND KEEP A METHOD-LOCAL COPY
0064: // OF THE REFERENCE.
0065: private ParsedIOR _pior = null;
0066: private org.omg.IOP.IOR ior = null;
0067: private ClientConnection connection = null;
0068: private String objectReference = null;
0069:
0070: /* save original ior for fallback */
0071: private ParsedIOR piorOriginal = null;
0072:
0073: /* save iors to detect and prevent locate forward loop */
0074: private ParsedIOR piorLastFailed = null;
0075:
0076: /* flag to indicate if this is the delegate for the ImR */
0077: private boolean isImR = false;
0078:
0079: private boolean bound = false;
0080: private org.jacorb.poa.POA poa;
0081:
0082: private final org.jacorb.orb.ORB orb;
0083: private Logger logger = null;
0084:
0085: /** set after the first attempt to determine whether
0086: this reference is to a local object */
0087: private boolean resolved_locality = false;
0088:
0089: private final Set pending_replies = new HashSet();
0090: private final Barrier pending_replies_sync = new Barrier();
0091:
0092: private final java.lang.Object bind_sync = new java.lang.Object();
0093:
0094: private boolean locate_on_bind_performed = false;
0095:
0096: private ClientConnectionManager conn_mg = null;
0097:
0098: private Map policy_overrides;
0099:
0100: private boolean doNotCheckExceptions = false; //Setting for Appligator
0101:
0102: private CookieHolder cookie = null;
0103:
0104: private String invokedOperation = null;
0105:
0106: /**
0107: * <code>localInterceptors</code> stores the ClientInterceptorHandler that is
0108: * currently in use during an interceptor invocation. It is held within a
0109: * thread local to prevent thread interaction issues.
0110: */
0111: private static final ThreadLocal localInterceptors = new ThreadLocal();
0112:
0113: /** the configuration object for this delegate */
0114: private org.apache.avalon.framework.configuration.Configuration configuration = null;
0115:
0116: /** configuration properties */
0117: private boolean useIMR;
0118: private boolean locateOnBind;
0119:
0120: /**
0121: * 03-09-04: 1.5.2.2
0122: *
0123: * boolean threadlocal to ensure that
0124: * after servant_preinvoke has returned null the
0125: * next call to is_local will return false
0126: * so that the stub will choose the non-optimized path
0127: */
0128: private static final ThreadLocal ignoreNextCallToIsLocal = new ThreadLocal() {
0129: protected java.lang.Object initialValue() {
0130: return Boolean.FALSE;
0131: }
0132: };
0133:
0134: /**
0135: * A general note on the synchronization concept
0136: *
0137: * The main problem that has to be addressed by synchronization
0138: * means is the case when an object reference is shared by
0139: * threads, and LocationForwards (e.g. thrown by the ImR) or
0140: * ForwardRequest (thrown by ClientInterceptors) involved. In
0141: * these cases, the rebinding to another target can occur while
0142: * there are still other requests active. Therefore, the act of
0143: * rebinding must be synchronized, so every thread sees a
0144: * consistent state.
0145: *
0146: * Synchronization is done via the bind_sync object. Please also
0147: * have a look at the comment for operation bind().
0148: */
0149:
0150: /* constructors: */
0151:
0152: private Delegate(ORB orb) {
0153: super ();
0154:
0155: this .orb = orb;
0156: }
0157:
0158: public Delegate(org.jacorb.orb.ORB orb, ParsedIOR pior) {
0159: this (orb);
0160: _pior = pior;
0161:
0162: checkIfImR(_pior.getTypeId());
0163: conn_mg = orb.getClientConnectionManager();
0164: }
0165:
0166: public Delegate(org.jacorb.orb.ORB orb, String object_reference) {
0167: this (orb);
0168:
0169: if (object_reference.indexOf("IOR:") != 0) {
0170: throw new org.omg.CORBA.INV_OBJREF("Not an IOR: "
0171: + object_reference);
0172: }
0173:
0174: this .objectReference = object_reference;
0175: conn_mg = orb.getClientConnectionManager();
0176: }
0177:
0178: public Delegate(org.jacorb.orb.ORB orb, org.omg.IOP.IOR ior) {
0179: this (orb);
0180: this .ior = ior;
0181: conn_mg = orb.getClientConnectionManager();
0182: }
0183:
0184: /**
0185: * special constructor for appligator
0186: */
0187: public Delegate(org.jacorb.orb.ORB orb, String object_reference,
0188: boolean _donotcheckexceptions) {
0189: this (orb, object_reference);
0190: doNotCheckExceptions = _donotcheckexceptions;
0191: }
0192:
0193: public void configure(
0194: org.apache.avalon.framework.configuration.Configuration config)
0195: throws org.apache.avalon.framework.configuration.ConfigurationException {
0196: this .configuration = config;
0197: logger = ((Configuration) config)
0198: .getNamedLogger("jacorb.orb.delegate");
0199: useIMR = config.getAttribute("jacorb.use_imr", "off").equals(
0200: "on");
0201: locateOnBind = config.getAttribute("jacorb.locate_on_bind",
0202: "off").equals("on");
0203:
0204: if (objectReference != null) {
0205: _pior = new ParsedIOR(orb, objectReference);
0206: } else if (ior != null) {
0207: _pior = new ParsedIOR(orb, ior);
0208: } else if (_pior == null) {
0209: throw new ConfigurationException(
0210: "Neither objectReference nor IOR set!");
0211: }
0212: checkIfImR(_pior.getTypeId());
0213: }
0214:
0215: public boolean doNotCheckExceptions() {
0216: return doNotCheckExceptions;
0217: }
0218:
0219: /**
0220: * Method to determine if this delegate is the delegate for the ImR.
0221: * This information is needed when trying to determine if the ImR has
0222: * gone down and come back up at a different addresss. All delegates
0223: * except the delegate of the ImR itself will try to determine if the
0224: * ImR has gone down and come back up at a new address if a connection
0225: * to the ImR can't be made. If the delegate of the ImR itself has
0226: * failed to connect then the ImR hasn't come back up!
0227: */
0228: private void checkIfImR(String typeId) {
0229: if ("IDL:org/jacorb/imr/ImplementationRepository:1.0"
0230: .equals(typeId)) {
0231: isImR = true;
0232: }
0233: }
0234:
0235: public int _get_TCKind() {
0236: return org.omg.CORBA.TCKind._tk_objref;
0237: }
0238:
0239: /**
0240: * @see #bind(boolean)
0241: */
0242: private void bind() {
0243: bind(false);
0244: }
0245:
0246: /**
0247: * This bind is a combination of the old _init() and bind()
0248: * operations. It first inits this delegate with the information
0249: * supplied by the (parsed) IOR. Then it requests a new
0250: * ClientConnection from the ConnectionsManager. This will *NOT*
0251: * open up a TCP connection, but the connection is needed for the
0252: * GIOP message ids. The actual TCP connection is automatically
0253: * opened up by the ClientConnection, when the first request is
0254: * sent. This has the advantage, that COMM_FAILURES can only occur
0255: * inside of _invoke, where they get handled properly (falling
0256: * back, etc.)
0257: *
0258: * @param rebind a <code>boolean</code> value which denotes if rebind
0259: * was the caller. If so, we will avoid checking client
0260: * protocols as that will have already been done.
0261: */
0262: private void bind(boolean rebind) {
0263: synchronized (bind_sync) {
0264: if (bound) {
0265: return;
0266: }
0267:
0268: if (!rebind) {
0269: // Check if ClientProtocolPolicy set, if so, set profile
0270: // selector for IOR that selects effective profile for protocol
0271: org.omg.RTCORBA.Protocol[] protocols = getClientProtocols();
0272: if (protocols != null) {
0273: _pior
0274: .setProfileSelector(new SpecificProfileSelector(
0275: protocols));
0276: }
0277: }
0278:
0279: org.omg.ETF.Profile profile = _pior.getEffectiveProfile();
0280: if (profile == null) {
0281: throw new org.omg.CORBA.COMM_FAILURE(
0282: "no effective profile");
0283: }
0284:
0285: connection = conn_mg.getConnection(profile);
0286: bound = true;
0287:
0288: /* The delegate could query the server for the object
0289: * location using a GIOP locate request to make sure the
0290: * first call will get through without redirections
0291: * (provided the server's answer is definite):
0292: */
0293: if ((!locate_on_bind_performed) && locateOnBind) {
0294: //only locate once, because bind is called from the
0295: //switch statement below again.
0296: locate_on_bind_performed = true;
0297:
0298: try {
0299: LocateRequestOutputStream lros = new LocateRequestOutputStream(
0300: _pior.get_object_key(), connection.getId(),
0301: _pior.getEffectiveProfile().version().minor);
0302:
0303: LocateReplyReceiver receiver = new LocateReplyReceiver(
0304: orb);
0305:
0306: connection.sendRequest(lros, receiver, lros
0307: .getRequestId(), true); //response expected
0308:
0309: LocateReplyInputStream lris = receiver.getReply();
0310:
0311: switch (lris.rep_hdr.locate_status.value()) {
0312:
0313: case LocateStatusType_1_2._UNKNOWN_OBJECT: {
0314: throw new org.omg.CORBA.UNKNOWN(
0315: "Could not bind to object, server does not know it!");
0316: }
0317:
0318: case LocateStatusType_1_2._OBJECT_HERE: {
0319: break;
0320: }
0321:
0322: case LocateStatusType_1_2._OBJECT_FORWARD: {
0323: //fall through
0324: }
0325:
0326: case LocateStatusType_1_2._OBJECT_FORWARD_PERM: {
0327: //_OBJECT_FORWARD_PERM is actually more or
0328: //less deprecated
0329: rebind(lris.read_Object());
0330: break;
0331: }
0332:
0333: case LocateStatusType_1_2._LOC_SYSTEM_EXCEPTION: {
0334: throw SystemExceptionHelper.read(lris);
0335:
0336: //break;
0337: }
0338:
0339: case LocateStatusType_1_2._LOC_NEEDS_ADDRESSING_MODE: {
0340: throw new org.omg.CORBA.NO_IMPLEMENT(
0341: "Server responded to LocateRequest with a status of LOC_NEEDS_ADDRESSING_MODE, but this isn't yet implemented by JacORB");
0342:
0343: //break;
0344: }
0345:
0346: default: {
0347: throw new IllegalArgumentException(
0348: "Unknown reply status for LOCATE_REQUEST: "
0349: + lris.rep_hdr.locate_status
0350: .value());
0351: }
0352:
0353: }
0354:
0355: } catch (org.omg.CORBA.SystemException se) {
0356: //rethrow
0357: throw se;
0358: } catch (Exception e) {
0359: if (logger.isWarnEnabled()) {
0360: logger.warn(e.getMessage());
0361: }
0362: }
0363:
0364: }
0365:
0366: //wake up threads waiting for the pior
0367: bind_sync.notifyAll();
0368: }
0369: }
0370:
0371: public void rebind(org.omg.CORBA.Object obj) {
0372: String object_reference = orb.object_to_string(obj);
0373:
0374: if (object_reference.indexOf("IOR:") == 0) {
0375: rebind(new ParsedIOR(orb, object_reference));
0376: } else {
0377: throw new INV_OBJREF("Not an IOR: " + object_reference);
0378: }
0379: }
0380:
0381: public void rebind(ParsedIOR ior) {
0382: synchronized (bind_sync) {
0383: // Do the ParsedIORs currently match.
0384: final ParsedIOR originalIOR = getParsedIOR();
0385: boolean originalMatch = originalIOR.equals(ior);
0386:
0387: // Check if ClientProtocolPolicy set, if so, set profile
0388: // selector for IOR that selects effective profile for protocol
0389: org.omg.RTCORBA.Protocol[] protocols = getClientProtocols();
0390:
0391: if (protocols != null) {
0392: ior.setProfileSelector(new SpecificProfileSelector(
0393: protocols));
0394: }
0395:
0396: // While the target override may have altered the effective profile so that
0397: // the IORs are now equal if the original ones do not match we still have to
0398: // disconnect so that the connection is made with the correct effective profile.
0399: if (originalMatch && ior.equals(originalIOR)) {
0400: //already bound to target so just return
0401: return;
0402: }
0403:
0404: if (piorLastFailed != null && piorLastFailed.equals(ior)) {
0405: //we've already failed to bind to the ior
0406: throw new org.omg.CORBA.TRANSIENT();
0407: }
0408:
0409: if (piorOriginal == null) {
0410: //keep original pior for fallback
0411: piorOriginal = _pior;
0412: }
0413:
0414: _pior = ior;
0415:
0416: if (connection != null) {
0417: conn_mg.releaseConnection(connection);
0418: connection = null;
0419: }
0420:
0421: //to tell bind() that it has to take action
0422: bound = false;
0423:
0424: bind();
0425: }
0426: }
0427:
0428: public org.omg.CORBA.Request create_request(
0429: org.omg.CORBA.Object self, org.omg.CORBA.Context ctx,
0430: java.lang.String operation, org.omg.CORBA.NVList args,
0431: org.omg.CORBA.NamedValue result) {
0432: checkORB();
0433:
0434: bind();
0435:
0436: return new org.jacorb.orb.dii.Request(self, orb, connection,
0437: getParsedIOR().get_object_key(), operation, args, ctx,
0438: result);
0439: }
0440:
0441: public org.omg.CORBA.Request create_request(
0442: org.omg.CORBA.Object self, org.omg.CORBA.Context ctx,
0443: String operation, org.omg.CORBA.NVList arg_list,
0444: org.omg.CORBA.NamedValue result,
0445: org.omg.CORBA.ExceptionList exceptions,
0446: org.omg.CORBA.ContextList contexts) {
0447: throw new org.omg.CORBA.NO_IMPLEMENT();
0448: }
0449:
0450: public synchronized org.omg.CORBA.Object duplicate(
0451: org.omg.CORBA.Object self) {
0452: return self;
0453: }
0454:
0455: public boolean equals(java.lang.Object obj) {
0456: return (obj instanceof org.omg.CORBA.Object && toString()
0457: .equals(obj.toString()));
0458: }
0459:
0460: public boolean equals(org.omg.CORBA.Object self,
0461: java.lang.Object obj) {
0462: return equals(obj);
0463: }
0464:
0465: /**
0466: * Called when a client-side stub is garbage-collected.
0467: * In effect, this method causes the Delegate to unregister
0468: * itself from the underlying GIOPConnection. If there are
0469: * no other Delegates using that connection, it will be
0470: * closed and disposed of altogether.
0471: */
0472: protected void finalize() throws Throwable {
0473: try {
0474: release(null);
0475: } finally {
0476: super .finalize();
0477: }
0478: }
0479:
0480: public org.omg.CORBA.DomainManager[] get_domain_managers(
0481: org.omg.CORBA.Object self) {
0482: return null;
0483: }
0484:
0485: /**
0486: * The get_policy operation returns the policy object of the
0487: * specified type, which applies to this object. It returns the
0488: * effective Policy for the object reference. The effective Policy
0489: * is the one that would be used if a request were made. This
0490: * Policy is determined first by obtaining the effective override
0491: * for the PolicyType as returned by get_client_policy. The
0492: * effective override is then compared with the Policy as
0493: * specified in the IOR.
0494: * <p>
0495: * The effective Policy is determined by reconciling the effective
0496: * override and the IOR-specified Policy. If the two policies
0497: * cannot be reconciled, the standard system exception INV_POLICY
0498: * is raised with standard minor code 1. The absence of a Policy
0499: * value in the IOR implies that any legal value may be used.
0500: */
0501:
0502: public org.omg.CORBA.Policy get_policy(org.omg.CORBA.Object self,
0503: int policy_type) {
0504: Policy result = get_client_policy(policy_type);
0505: if (result != null) {
0506: // TODO: "reconcile" with server-side policy
0507: return result;
0508: }
0509: // if not locally overridden, ask the server
0510: return get_policy(self, policy_type, request(self,
0511: "_get_policy", true));
0512: }
0513:
0514: /**
0515: * Gets the effective overriding policy with the given type from
0516: * the client-side, or null if this policy type is unset.
0517: *
0518: * (Implementation is incomplete, we don't check PolicyCurrent, i.e.
0519: * at the thread-level)
0520: */
0521:
0522: public org.omg.CORBA.Policy get_client_policy(int policy_type) {
0523: Policy result = null;
0524:
0525: if (policy_overrides != null) {
0526: Integer key = ObjectUtil.newInteger(policy_type);
0527: result = (Policy) policy_overrides.get(key);
0528: }
0529:
0530: if (result == null) {
0531: // no override at the object level for this type, now
0532: // check at the thread level, ie PolicyCurrent.
0533: // TODO: currently not implemented
0534:
0535: // check at the ORB-level
0536: org.omg.CORBA.PolicyManager policyManager = orb
0537: .getPolicyManager();
0538: if (policyManager != null) {
0539: Policy[] orbPolicies = policyManager
0540: .get_policy_overrides(new int[] { policy_type });
0541: if (orbPolicies != null && orbPolicies.length == 1) {
0542: result = orbPolicies[0];
0543: }
0544: }
0545: }
0546:
0547: return result;
0548: }
0549:
0550: public org.omg.CORBA.Policy get_policy(org.omg.CORBA.Object self,
0551: int policy_type, org.omg.CORBA.portable.OutputStream os) {
0552: // ask object implementation
0553: while (true) {
0554: try {
0555: os.write_Object(self);
0556: os.write_long(policy_type);
0557: org.omg.CORBA.portable.InputStream is = invoke(self, os);
0558: return org.omg.CORBA.PolicyHelper.narrow(is
0559: .read_Object());
0560: } catch (RemarshalException r) // NOPMD
0561: {
0562: // Ignored
0563: } catch (ApplicationException _ax) {
0564: String _id = _ax.getId();
0565: throw new INTERNAL("Unexpected exception " + _id);
0566: }
0567:
0568: }
0569: } // get_policy
0570:
0571: public UtcT getRequestEndTime() {
0572: Policy policy = get_client_policy(REQUEST_END_TIME_POLICY_TYPE.value);
0573: if (policy != null) {
0574: return ((org.omg.Messaging.RequestEndTimePolicy) policy)
0575: .end_time();
0576: }
0577: return null;
0578: }
0579:
0580: public UtcT getReplyEndTime() {
0581: Policy policy = get_client_policy(REPLY_END_TIME_POLICY_TYPE.value);
0582: if (policy != null) {
0583: return ((org.omg.Messaging.ReplyEndTimePolicy) policy)
0584: .end_time();
0585: }
0586: return null;
0587: }
0588:
0589: public UtcT getRequestStartTime() {
0590: Policy policy = get_client_policy(REQUEST_START_TIME_POLICY_TYPE.value);
0591: if (policy != null) {
0592: return ((org.omg.Messaging.RequestStartTimePolicy) policy)
0593: .start_time();
0594: }
0595: return null;
0596: }
0597:
0598: public UtcT getReplyStartTime() {
0599: Policy policy = get_client_policy(REPLY_START_TIME_POLICY_TYPE.value);
0600: if (policy != null) {
0601: return ((org.omg.Messaging.ReplyStartTimePolicy) policy)
0602: .start_time();
0603: }
0604: return null;
0605: }
0606:
0607: public long getRelativeRoundtripTimeout() {
0608: Policy policy = get_client_policy(RELATIVE_RT_TIMEOUT_POLICY_TYPE.value);
0609: if (policy != null) {
0610: return ((org.omg.Messaging.RelativeRoundtripTimeoutPolicy) policy)
0611: .relative_expiry();
0612: }
0613: return -1;
0614: }
0615:
0616: public long getRelativeRequestTimeout() {
0617: Policy policy = get_client_policy(RELATIVE_REQ_TIMEOUT_POLICY_TYPE.value);
0618: if (policy != null) {
0619: return ((org.omg.Messaging.RelativeRequestTimeoutPolicy) policy)
0620: .relative_expiry();
0621: }
0622: return -1;
0623: }
0624:
0625: public short getSyncScope() {
0626: Policy policy = get_client_policy(SYNC_SCOPE_POLICY_TYPE.value);
0627: if (policy != null) {
0628: return ((org.omg.Messaging.SyncScopePolicy) policy)
0629: .synchronization();
0630: }
0631: return org.omg.Messaging.SYNC_WITH_TRANSPORT.value;
0632: }
0633:
0634: public org.omg.RTCORBA.Protocol[] getClientProtocols() {
0635: Policy policy = get_client_policy(org.omg.RTCORBA.CLIENT_PROTOCOL_POLICY_TYPE.value);
0636: if (policy != null) {
0637: return ((org.omg.RTCORBA.ClientProtocolPolicy) policy)
0638: .protocols();
0639: }
0640: return null;
0641: }
0642:
0643: /**
0644: * @deprecated Deprecated by CORBA 2.3
0645: */
0646: public org.omg.CORBA.InterfaceDef get_interface(
0647: org.omg.CORBA.Object self) {
0648: return org.omg.CORBA.InterfaceDefHelper
0649: .narrow(get_interface_def(self));
0650: }
0651:
0652: public org.omg.CORBA.Object get_interface_def(
0653: org.omg.CORBA.Object self) {
0654: checkORB();
0655:
0656: // If local object call _interface directly
0657:
0658: if (is_really_local(self)) {
0659: org.omg.PortableServer.Servant servant;
0660: org.omg.CORBA.portable.ServantObject so;
0661:
0662: so = servant_preinvoke(self, "_interface",
0663: java.lang.Object.class);
0664:
0665: // If preinvoke returns null POA spec, 11.3.4 states OBJ_ADAPTER
0666: // should be thrown.
0667: if (so == null) {
0668: throw new OBJ_ADAPTER(
0669: "Servant from pre_invoke was null");
0670: }
0671: try {
0672: servant = (org.omg.PortableServer.Servant) so.servant;
0673: orb.set_delegate(servant);
0674: return servant._get_interface_def();
0675: } finally {
0676: servant_postinvoke(self, so);
0677: }
0678: }
0679:
0680: org.omg.CORBA.portable.OutputStream os;
0681: org.omg.CORBA.portable.InputStream is;
0682:
0683: while (true) {
0684: try {
0685: os = request(self, "_interface", true);
0686: is = invoke(self, os);
0687: return is.read_Object();
0688: } catch (RemarshalException re) // NOPMD
0689: {
0690: // Ignored
0691: } catch (Exception ex) {
0692: return null;
0693: }
0694: }
0695: }
0696:
0697: ClientConnection getConnection() {
0698: synchronized (bind_sync) {
0699: bind();
0700: return connection;
0701: }
0702: }
0703:
0704: public org.omg.IOP.IOR getIOR() {
0705: synchronized (bind_sync) {
0706: if (piorOriginal != null) {
0707: return piorOriginal.getIOR();
0708: }
0709: return getParsedIOR().getIOR();
0710: }
0711: }
0712:
0713: public byte[] getObjectId() {
0714: synchronized (bind_sync) {
0715: bind();
0716:
0717: return POAUtil.extractOID(getParsedIOR().get_object_key());
0718: }
0719: }
0720:
0721: public byte[] getObjectKey() {
0722: synchronized (bind_sync) {
0723: bind();
0724:
0725: return getParsedIOR().get_object_key();
0726: }
0727: }
0728:
0729: public ParsedIOR getParsedIOR() {
0730: synchronized (bind_sync) {
0731: while (_pior == null) {
0732: try {
0733: bind_sync.wait();
0734: } catch (InterruptedException ie) {
0735: // ignored
0736: }
0737: }
0738:
0739: return _pior;
0740: }
0741: }
0742:
0743: public void resolvePOA(org.omg.CORBA.Object self) {
0744: if (!resolved_locality) {
0745: resolved_locality = true;
0746: org.jacorb.poa.POA local_poa = orb.findPOA(this , self);
0747:
0748: if (local_poa != null) {
0749: poa = local_poa;
0750: }
0751: }
0752: }
0753:
0754: public org.jacorb.poa.POA getPOA() {
0755: return poa;
0756: }
0757:
0758: /**
0759: */
0760:
0761: public org.omg.CORBA.portable.ObjectImpl getReference(
0762: org.jacorb.poa.POA _poa) {
0763: if (logger.isDebugEnabled()) {
0764: logger.debug("Delegate.getReference with POA <"
0765: + (_poa != null ? _poa._getQualifiedName()
0766: : " empty") + ">");
0767: }
0768:
0769: if (_poa != null) // && _poa._localStubsSupported())
0770: {
0771: poa = _poa;
0772: }
0773:
0774: org.omg.CORBA.portable.ObjectImpl reference = new org.jacorb.orb.Reference(
0775: typeId());
0776:
0777: reference._set_delegate(this );
0778:
0779: return reference;
0780: }
0781:
0782: public int hash(org.omg.CORBA.Object self, int x) {
0783: checkORB();
0784:
0785: return hashCode();
0786: }
0787:
0788: public int hashCode() {
0789: return getIDString().hashCode();
0790: }
0791:
0792: public int hashCode(org.omg.CORBA.Object self) {
0793: return hashCode();
0794: }
0795:
0796: /**
0797: * Invokes an asynchronous operation using this object reference by
0798: * sending the request marshalled in the OutputStream. The reply
0799: * will be directed to the supplied ReplyHandler.
0800: */
0801: public void invoke(org.omg.CORBA.Object self,
0802: org.omg.CORBA.portable.OutputStream os,
0803: org.omg.Messaging.ReplyHandler replyHandler)
0804: throws ApplicationException, RemarshalException {
0805: // discard result, it is always null
0806: invoke_internal(self, os, replyHandler, true);
0807: }
0808:
0809: /**
0810: * Invokes a synchronous operation using this object reference
0811: * by sending the request marshalled in the OutputStream.
0812: * @return the reply, if a reply is expected for this request.
0813: * If no reply is expected, returns null.
0814: */
0815: public org.omg.CORBA.portable.InputStream invoke(
0816: org.omg.CORBA.Object self,
0817: org.omg.CORBA.portable.OutputStream os)
0818: throws ApplicationException, RemarshalException {
0819: return invoke_internal(self, os, null, false);
0820: }
0821:
0822: /**
0823: * Internal implementation of both invoke() methods. Note that
0824: * the boolean argument <code>async</code> is necessary to differentiate
0825: * between synchronous and asynchronous calls, because the ReplyHandler
0826: * can be null even for an asynchronous call.
0827: */
0828: private org.omg.CORBA.portable.InputStream invoke_internal(
0829: org.omg.CORBA.Object self,
0830: org.omg.CORBA.portable.OutputStream os,
0831: org.omg.Messaging.ReplyHandler replyHandler, boolean async)
0832: throws ApplicationException, RemarshalException {
0833: checkORB();
0834:
0835: RequestOutputStream ros = (RequestOutputStream) os;
0836: ReplyReceiver receiver = null;
0837: final ClientInterceptorHandler interceptors = new ClientInterceptorHandler(
0838: (ClientInterceptorHandler) localInterceptors.get(),
0839: orb, ros, self, this , piorOriginal, connection);
0840:
0841: orb.notifyTransportListeners(connection.getGIOPConnection());
0842:
0843: if (orb.hasRequestInterceptors()) {
0844: localInterceptors.set(interceptors);
0845:
0846: try {
0847: interceptors.handle_send_request();
0848: } catch (RuntimeException e) {
0849: // If we are throwing a system exception then this will disrupt the call path.
0850: // Therefore nullify localInterceptors so it doesn't appear we are still in an
0851: // interceptor call. RemarshalExceptions are explicitely not caught, because in
0852: // that case, localInterceptors must stay set
0853:
0854: localInterceptors.set(null);
0855: throw e;
0856: }
0857: } else {
0858: interceptors.handle_send_request();
0859: }
0860:
0861: try {
0862: if (!ros.response_expected()) // oneway op
0863: {
0864: invoke_oneway(ros, interceptors);
0865: return null;
0866: }
0867: // response expected, synchronous or asynchronous
0868: receiver = new ReplyReceiver(this , ros.operation(), ros
0869: .getReplyEndTime(), interceptors, replyHandler);
0870: receiver.configure(configuration);
0871:
0872: // Store the receiver in pending_replies, so in the
0873: // case of a LocationForward a RemarshalException can
0874: // be thrown to *all* waiting threads.
0875:
0876: synchronized (pending_replies) {
0877: pending_replies.add(receiver);
0878: }
0879:
0880: synchronized (bind_sync) {
0881: if (ros.getConnection() == connection) {
0882: // RequestOutputStream has been created for
0883: // exactly this connection
0884: connection.sendRequest(ros, receiver, ros
0885: .requestId(), true); // response
0886: // expected
0887: } else {
0888: logger.debug("invoke: RemarshalException");
0889:
0890: // RequestOutputStream has been created for
0891: // another connection, so try again
0892: throw new RemarshalException();
0893: }
0894: }
0895: } catch (org.omg.CORBA.SystemException cfe) {
0896: logger.debug("invoke: SystemException");
0897:
0898: if (!async) {
0899: // Remove ReplyReceiver to break up reference cycle
0900: // Otherwise gc will not detect this Delegate and
0901: // will never finalize it.
0902: synchronized (pending_replies) {
0903: pending_replies.remove(receiver);
0904: }
0905: }
0906:
0907: interceptors.handle_receive_exception(cfe);
0908:
0909: // The exception is a TRANSIENT, so try rebinding.
0910: if (cfe instanceof org.omg.CORBA.TRANSIENT && try_rebind()) {
0911: throw new RemarshalException();
0912: }
0913:
0914: throw cfe;
0915: } finally {
0916: if (orb.hasRequestInterceptors()) {
0917: localInterceptors.set(null);
0918: }
0919: }
0920:
0921: if (!async && receiver != null) {
0922: // Synchronous invocation, response expected.
0923: // This call blocks until the reply arrives.
0924: org.omg.CORBA.portable.InputStream is = receiver.getReply();
0925:
0926: ((CDRInputStream) is).updateMutatorConnection(connection
0927: .getGIOPConnection());
0928:
0929: return is;
0930: }
0931:
0932: return null;
0933: }
0934:
0935: private void invoke_oneway(RequestOutputStream ros,
0936: ClientInterceptorHandler interceptors)
0937: throws RemarshalException, ApplicationException {
0938: switch (ros.syncScope()) {
0939: case SYNC_NONE.value:
0940: passToTransport(ros);
0941: interceptors.handle_receive_other(SUCCESSFUL.value);
0942: break;
0943:
0944: case SYNC_WITH_TRANSPORT.value:
0945: connection.sendRequest(ros, false);
0946: interceptors.handle_receive_other(SUCCESSFUL.value);
0947: break;
0948:
0949: case SYNC_WITH_SERVER.value:
0950: case SYNC_WITH_TARGET.value:
0951: ReplyReceiver rcv = new ReplyReceiver(this ,
0952: ros.operation(), ros.getReplyEndTime(),
0953: interceptors, null);
0954: rcv.configure(configuration);
0955:
0956: connection.sendRequest(ros, rcv, ros.requestId(), true);
0957: ReplyInputStream in = rcv.getReply();
0958: interceptors.handle_receive_reply(in);
0959: break;
0960:
0961: default:
0962: throw new org.omg.CORBA.MARSHAL("Illegal SYNC_SCOPE: "
0963: + ros.syncScope(), 0,
0964: CompletionStatus.COMPLETED_MAYBE);
0965: }
0966: }
0967:
0968: private void passToTransport(final RequestOutputStream ros) {
0969: new Thread(new Runnable() {
0970: public void run() {
0971: connection.sendRequest(ros, false);
0972: }
0973: }, "PassToTransport").start();
0974: }
0975:
0976: private boolean try_rebind() {
0977: synchronized (bind_sync) {
0978: if (logger.isDebugEnabled()) {
0979: logger.debug("Delegate.try_rebind");
0980: }
0981:
0982: if (piorOriginal != null) {
0983: if (logger.isDebugEnabled()) {
0984: logger
0985: .debug("Delegate: falling back to original IOR");
0986: }
0987:
0988: //keep last failed ior to detect forwarding loops
0989: piorLastFailed = getParsedIOR();
0990:
0991: //rebind to the original ior
0992: rebind(piorOriginal);
0993:
0994: //clean up and start fresh
0995: piorOriginal = null;
0996: piorLastFailed = null; // supplied byte Kevin Heifner, OCI
0997:
0998: return true;
0999: } else if (useIMR && !isImR) {
1000: Integer orbTypeId = getParsedIOR().getORBTypeId();
1001:
1002: // only lookup ImR if IOR is generated by JacORB
1003: if (orbTypeId == null
1004: || orbTypeId.intValue() != ORBConstants.JACORB_ORB_ID) {
1005: if (logger.isDebugEnabled()) {
1006: logger.debug("Delegate: foreign IOR detected");
1007: }
1008: return false;
1009: }
1010:
1011: if (logger.isDebugEnabled()) {
1012: logger.debug("Delegate: JacORB IOR detected");
1013: }
1014:
1015: byte[] object_key = getParsedIOR().get_object_key();
1016:
1017: // No backup IOR so it may be that the ImR is down
1018: // Attempt to resolve the ImR again to see if it has
1019: // come back up at a different address
1020:
1021: if (logger.isDebugEnabled()) {
1022: logger.debug("Delegate: attempting to contact ImR");
1023: }
1024:
1025: ImRAccess imr = null;
1026:
1027: try {
1028: imr = ImRAccessImpl.connect(orb);
1029: } catch (Exception e) {
1030: if (logger.isDebugEnabled()) {
1031: logger.debug("Delegate: failed to contact ImR");
1032: }
1033: return false;
1034: }
1035:
1036: //create a corbaloc URL to use to contact the server
1037: StringBuffer corbaloc = new StringBuffer(
1038: "corbaloc:iiop:");
1039:
1040: corbaloc.append(imr.getImRHost());
1041: corbaloc.append(':');
1042: corbaloc.append(imr.getImRPort());
1043: corbaloc.append('/');
1044: corbaloc.append(CorbaLoc.parseKey(object_key));
1045:
1046: //rebind to the new IOR
1047: rebind(new ParsedIOR(orb, corbaloc.toString()));
1048:
1049: //clean up and start fresh
1050: piorOriginal = null;
1051: piorLastFailed = null; //***
1052:
1053: return true;
1054: } else {
1055: return false;
1056: }
1057: }
1058: }
1059:
1060: public void invokeInterceptors(ClientRequestInfoImpl info, short op)
1061: throws RemarshalException {
1062: ClientInterceptorIterator intercept_iter = orb
1063: .getInterceptorManager().getClientIterator();
1064:
1065: try {
1066: intercept_iter.iterate(info, op);
1067: } catch (org.omg.PortableInterceptor.ForwardRequest fwd) {
1068: rebind(fwd.forward);
1069: throw new RemarshalException();
1070: } catch (org.omg.CORBA.UserException ue) {
1071: if (logger.isErrorEnabled()) {
1072: logger.error(ue.getMessage());
1073: }
1074: }
1075: }
1076:
1077: /**
1078: * Determines whether the object denoted by self
1079: * has type logical_type_id or a subtype of it
1080: */
1081:
1082: public boolean is_a(org.omg.CORBA.Object self,
1083: String logical_type_id) {
1084: /* First, try to find out without a remote invocation. */
1085:
1086: /* check most derived type as defined in the IOR first
1087: * (this type might otherwise not be found if the helper
1088: * is consulted and the reference was not narrowed to
1089: * the most derived type. In this case, the ids returned by
1090: * the helper won't contain the most derived type
1091: */
1092:
1093: ParsedIOR pior = getParsedIOR();
1094:
1095: if (pior.getTypeId().equals(logical_type_id)) {
1096: return true;
1097: }
1098:
1099: /* The Ids in ObjectImpl will at least contain the type id
1100: found in the object reference itself.
1101: */
1102: String[] ids = ((org.omg.CORBA.portable.ObjectImpl) self)
1103: ._ids();
1104:
1105: /* the last id will be CORBA.Object, and we know that already... */
1106: for (int i = 0; i < ids.length - 1; i++) {
1107: if (ids[i].equals(logical_type_id)) {
1108: return true;
1109: }
1110: }
1111:
1112: /* ok, we could not affirm by simply looking at the locally available
1113: type ids, so ask the object itself */
1114:
1115: // If local object call _is_a directly
1116: if (is_really_local(self)) {
1117: if (logger.isDebugEnabled()) {
1118: logger.debug("Located " + self
1119: + " on local POA; assuming local.");
1120: }
1121:
1122: org.omg.PortableServer.Servant servant;
1123: org.omg.CORBA.portable.ServantObject so;
1124:
1125: so = servant_preinvoke(self, "_is_a",
1126: java.lang.Object.class);
1127:
1128: // If preinvoke returns null POA spec, 11.3.4 states OBJ_ADAPTER
1129: // should be thrown.
1130: if (so == null) {
1131: throw new OBJ_ADAPTER(
1132: "Servant from pre_invoke was null");
1133: }
1134:
1135: try {
1136: servant = (org.omg.PortableServer.Servant) so.servant;
1137: orb.set_delegate(servant);
1138: return servant._is_a(logical_type_id);
1139: } finally {
1140: servant_postinvoke(self, so);
1141: }
1142: }
1143: // The check below avoids trying to load a stub for CORBA.Object.
1144: // (It would be faster to check that ids.length > 1, but Sun's
1145: // CosNaming JNDI provider calls _is_a() on some weird ObjectImpl
1146: // instances whose _ids() method returns an array of length two,
1147: // containing two Strings equal to "IDL:omg.org/CORBA/Object:1.0".)
1148: if (!ids[0].equals("IDL:omg.org/CORBA/Object:1.0")) {
1149: // Try to avoid remote call - is it a derived type?
1150: try {
1151: // Retrieve the local stub for the object in question. Then call the _ids method
1152: // and see if any match the logical_type_id otherwise fall back to remote.
1153:
1154: final String classname = RepositoryID.className(ids[0],
1155: "Stub", null);
1156:
1157: int lastDot = classname.lastIndexOf('.');
1158: StringBuffer buffer = new StringBuffer(classname
1159: .substring(0, lastDot + 1));
1160: buffer.append('_');
1161: buffer.append(classname.substring(lastDot + 1));
1162:
1163: // This will only work if there is a correspondence between the Java class
1164: // name and the Repository ID. If prefixes have been using then this mapping
1165: // may have been lost.
1166:
1167: // First, search with stub name
1168: // if not found, try with the 'org.omg.stub' prefix to support package
1169: // with javax prefix
1170: Class stub = null;
1171: try {
1172: stub = ObjectUtil.classForName(buffer.toString());
1173: } catch (ClassNotFoundException e) {
1174: stub = ObjectUtil.classForName("org.omg.stub."
1175: + buffer.toString());
1176: }
1177:
1178: Method idm = stub.getMethod("_ids", (Class[]) null);
1179: String newids[] = (String[]) idm.invoke(stub
1180: .newInstance(), (java.lang.Object[]) null);
1181:
1182: for (int i = 0; i < newids.length; i++) {
1183: if (newids[i].equals(logical_type_id)) {
1184: return true;
1185: }
1186: }
1187: }
1188: // If it fails fall back to a remote call.
1189: catch (ClassNotFoundException e) // NOPMD
1190: {
1191: // ignore
1192: } catch (IllegalArgumentException e) // NOPMD
1193: {
1194: // ignore
1195: } catch (SecurityException e) // NOPMD
1196: {
1197: // ignore
1198: } catch (NoSuchMethodException e) // NOPMD
1199: {
1200: // ignore
1201: } catch (IllegalAccessException e) // NOPMD
1202: {
1203: // ignore
1204: } catch (InvocationTargetException e) // NOPMD
1205: {
1206: // ignore
1207: } catch (InstantiationException e) // NOPMD
1208: {
1209: // ignore
1210: } catch (SystemException e) // NOPMD
1211: {
1212: // ignore
1213: }
1214: logger.debug("trying is_a remotely");
1215: }
1216:
1217: org.omg.CORBA.portable.OutputStream os;
1218: org.omg.CORBA.portable.InputStream is;
1219:
1220: while (true) {
1221: try {
1222: os = request(self, "_is_a", true);
1223: os.write_string(logical_type_id);
1224: is = invoke(self, os);
1225: return is.read_boolean();
1226: } catch (RemarshalException re) // NOPMD
1227: {
1228: // Ignored
1229: } catch (ApplicationException ax) {
1230: throw new INTERNAL("Unexpected exception " + ax.getId());
1231: }
1232: }
1233: }
1234:
1235: public boolean is_equivalent(org.omg.CORBA.Object self,
1236: org.omg.CORBA.Object obj) {
1237: checkORB();
1238:
1239: boolean result = true;
1240:
1241: if (self != obj) {
1242: ParsedIOR pior1 = new ParsedIOR(orb, obj.toString());
1243: ParsedIOR pior2 = new ParsedIOR(orb, self.toString());
1244: result = pior2.getIDString().equals(pior1.getIDString());
1245: }
1246:
1247: return result;
1248: }
1249:
1250: public String getIDString() {
1251: return getParsedIOR().getIDString();
1252: }
1253:
1254: /**
1255: * @return true if this object lives on a local POA and
1256: * interceptors are not installed. When interceptors are
1257: * installed this returns false so that stubs do not call
1258: * direct to implementation, avoiding installed interceptors.
1259: */
1260:
1261: public boolean is_local(org.omg.CORBA.Object self) {
1262: if (ignoreNextCallToIsLocal.get() == Boolean.TRUE) {
1263: ignoreNextCallToIsLocal.set(Boolean.FALSE);
1264: return false;
1265: }
1266:
1267: if (localInterceptors.get() == null
1268: && orb.hasRequestInterceptors()) {
1269: return false;
1270: }
1271:
1272: return is_really_local(self);
1273: }
1274:
1275: /**
1276: * @return true if this object lives on a local POA
1277: */
1278:
1279: private boolean is_really_local(org.omg.CORBA.Object self) {
1280: if (poa == null) {
1281: resolvePOA(self);
1282: }
1283:
1284: return poa != null;
1285: }
1286:
1287: public boolean is_nil() {
1288: ParsedIOR pior = getParsedIOR();
1289:
1290: return (pior.getIOR().type_id.equals("") && pior.getIOR().profiles.length == 0);
1291: }
1292:
1293: public boolean non_existent(org.omg.CORBA.Object self) {
1294: // If local object call _non_existent directly
1295:
1296: if (is_really_local(self)) {
1297: org.omg.PortableServer.Servant servant;
1298: org.omg.CORBA.portable.ServantObject so;
1299:
1300: so = servant_preinvoke(self, "_non_existent",
1301: java.lang.Object.class);
1302:
1303: try {
1304: servant = (org.omg.PortableServer.Servant) so.servant;
1305: orb.set_delegate(servant);
1306: return servant._non_existent();
1307: } finally {
1308: servant_postinvoke(self, so);
1309: }
1310: }
1311:
1312: org.omg.CORBA.portable.OutputStream os;
1313: org.omg.CORBA.portable.InputStream is;
1314:
1315: while (true) {
1316: try {
1317: os = request(self, "_non_existent", true);
1318: is = invoke(self, os);
1319: return is.read_boolean();
1320: } catch (RemarshalException re) // NOPMD
1321: {
1322: // ignored
1323: } catch (ApplicationException e) {
1324: throw new INTERNAL("Unexpected exception " + e.getId());
1325: }
1326: }
1327: }
1328:
1329: public org.omg.CORBA.Object get_component(org.omg.CORBA.Object self) {
1330: // If local object call _get_component directly
1331:
1332: if (is_really_local(self)) {
1333: org.omg.PortableServer.Servant servant;
1334: org.omg.CORBA.portable.ServantObject so;
1335:
1336: so = servant_preinvoke(self, "_get_component",
1337: java.lang.Object.class);
1338:
1339: try {
1340: servant = (org.omg.PortableServer.Servant) so.servant;
1341: orb.set_delegate(servant);
1342: return servant._get_component();
1343: } finally {
1344: servant_postinvoke(self, so);
1345: }
1346: }
1347:
1348: org.omg.CORBA.portable.OutputStream os;
1349: org.omg.CORBA.portable.InputStream is;
1350:
1351: while (true) {
1352: try {
1353: os = request(self, "_get_component", true);
1354: is = invoke(self, os);
1355: return is.read_Object();
1356: } catch (RemarshalException re) // NOPMD
1357: {
1358: // ignored
1359: } catch (ApplicationException e) {
1360: throw new INTERNAL("Unexpected exception " + e.getId());
1361: }
1362: }
1363: }
1364:
1365: public org.omg.CORBA.ORB orb(org.omg.CORBA.Object self) {
1366: return orb;
1367: }
1368:
1369: /**
1370: * Called to indicate that this Delegate will no longer be used by
1371: * the client. The Delegate unregisters itself from the underlying
1372: * GIOPConnection. If there are no other Delegates using that
1373: * connection, it will be closed and disposed of altogether.
1374: */
1375: public void release(org.omg.CORBA.Object self) {
1376: synchronized (bind_sync) {
1377: if (!bound) {
1378: return;
1379: }
1380:
1381: if (connection != null) {
1382: conn_mg.releaseConnection(connection);
1383: connection = null;
1384: }
1385: bound = false;
1386:
1387: // Call using string rather than this to prevent data race
1388: // warning.
1389: orb._release(getParsedIOR().getIORString());
1390:
1391: if (logger.isDebugEnabled()) {
1392: logger.debug("Delegate released!");
1393: }
1394: }
1395: }
1396:
1397: /**
1398: * releases the InputStream
1399: */
1400: public void releaseReply(org.omg.CORBA.Object self,
1401: org.omg.CORBA.portable.InputStream is) {
1402: if (is != null) {
1403: try {
1404: is.close();
1405: } catch (java.io.IOException io) {
1406: // ignored
1407: }
1408: }
1409: Time.waitFor(getReplyStartTime());
1410: }
1411:
1412: public org.omg.CORBA.Request request(org.omg.CORBA.Object self,
1413: String operation) {
1414: orb.perform_work();
1415:
1416: synchronized (bind_sync) {
1417: bind();
1418: return new org.jacorb.orb.dii.Request(self, orb,
1419: connection, getParsedIOR().get_object_key(),
1420: operation);
1421: }
1422: }
1423:
1424: /**
1425: */
1426:
1427: public synchronized org.omg.CORBA.portable.OutputStream request(
1428: org.omg.CORBA.Object self, String operation,
1429: boolean responseExpected) {
1430: orb.perform_work();
1431:
1432: // Compute the deadlines for this request based on any absolute or
1433: // relative timing policies that have been specified. Compute this
1434: // now, because it is the earliest possible time, and therefore any
1435: // relative timeouts will cover the entire invocation.
1436:
1437: UtcT requestEndTime = getRequestEndTime();
1438: long requestTimeout = getRelativeRequestTimeout();
1439:
1440: if ((requestTimeout != 0) || (requestEndTime != null)) {
1441: requestEndTime = Time.earliest(Time
1442: .corbaFuture(requestTimeout), requestEndTime);
1443: if (Time.hasPassed(requestEndTime)) {
1444: throw new TIMEOUT(
1445: "Request End Time exceeded prior to invocation",
1446: 0, CompletionStatus.COMPLETED_NO);
1447: }
1448: }
1449:
1450: UtcT replyEndTime = getReplyEndTime();
1451: long roundtripTimeout = getRelativeRoundtripTimeout();
1452:
1453: if ((roundtripTimeout != 0) || (replyEndTime != null)) {
1454: replyEndTime = Time.earliest(Time
1455: .corbaFuture(roundtripTimeout), replyEndTime);
1456: if (Time.hasPassed(replyEndTime)) {
1457: throw new TIMEOUT(
1458: "Reply End Time exceeded prior to invocation",
1459: 0, CompletionStatus.COMPLETED_NO);
1460: }
1461: }
1462:
1463: synchronized (bind_sync) {
1464: bind();
1465:
1466: ParsedIOR ior = getParsedIOR();
1467:
1468: RequestOutputStream out = new RequestOutputStream(orb,
1469: connection, connection.getId(), operation,
1470: responseExpected, getSyncScope(),
1471: getRequestStartTime(), requestEndTime,
1472: replyEndTime, ior.get_object_key(), ior
1473: .getEffectiveProfile().version().minor);
1474:
1475: out.configure(configuration);
1476:
1477: // CodeSets are only negotiated once per connection,
1478: // not for each individual request
1479: // (CORBA 3.0, 13.10.2.6, second paragraph).
1480: if (!connection.isTCSNegotiated()) {
1481: connection.setCodeSet(ior);
1482: }
1483:
1484: //Setting the codesets not until here results in the
1485: //header being writtend using the default codesets. On the
1486: //other hand, the server side must have already read the
1487: //header to discover the codeset service context.
1488: out.setCodeSet(connection.getTCS(), connection.getTCSW());
1489:
1490: out.updateMutatorConnection(connection.getGIOPConnection());
1491:
1492: return out;
1493: }
1494: }
1495:
1496: /**
1497: * Overrides servant_postinvoke() in org.omg.CORBA.portable.Delegate<BR>
1498: * called from generated stubs after a local operation
1499: */
1500:
1501: public void servant_postinvoke(org.omg.CORBA.Object self,
1502: ServantObject servant) {
1503: if (poa != null) {
1504: if (poa.isUseServantManager() && !poa.isRetain()
1505: && cookie != null && invokedOperation != null) {
1506: // ServantManager is a ServantLocator:
1507: // call postinvoke
1508: try {
1509: byte[] oid = POAUtil.extractOID(getParsedIOR()
1510: .get_object_key());
1511: org.omg.PortableServer.ServantLocator sl = (org.omg.PortableServer.ServantLocator) poa
1512: .get_servant_manager();
1513:
1514: sl.postinvoke(oid, poa, invokedOperation,
1515: cookie.value, (Servant) servant.servant);
1516:
1517: // delete stored values
1518: cookie = null;
1519: invokedOperation = null;
1520: } catch (Throwable e) {
1521: if (logger.isWarnEnabled()) {
1522: logger.warn(e.getMessage());
1523: }
1524: }
1525:
1526: }
1527: poa.removeLocalRequest();
1528: }
1529: orb.getPOACurrent()._removeContext(Thread.currentThread());
1530: }
1531:
1532: /**
1533: * Overrides servant_preinvoke() in org.omg.CORBA.portable.Delegate<BR>
1534: * called from generated stubs before a local operation
1535: */
1536:
1537: public ServantObject servant_preinvoke(org.omg.CORBA.Object self,
1538: String operation, Class expectedType) {
1539: if (poa == null) {
1540: resolvePOA(self);
1541: }
1542:
1543: if (poa != null) {
1544: // remember that a local request is outstanding. On
1545: // any exit through an exception, this must be cleared again,
1546: // otherwise the POA will hangon destruction (bug #400).
1547: poa.addLocalRequest();
1548:
1549: ServantObject so = new ServantObject();
1550:
1551: try {
1552: if ((poa.isRetain() && !poa.isUseServantManager())
1553: || poa.useDefaultServant()) {
1554: // no ServantManagers, but AOM use
1555: try {
1556: so.servant = poa.reference_to_servant(self);
1557: } catch (WrongAdapter e) {
1558: // exit on an error condition, but need to clean up first (added to fix bug #400)
1559: poa.removeLocalRequest();
1560: throw new OBJ_ADAPTER(
1561: "WrongAdapter caught when converting servant to reference. "
1562: + e);
1563: } catch (WrongPolicy e) {
1564: // exit on an error condition, but need to clean up first (added to fix bug #400)
1565: poa.removeLocalRequest();
1566: throw new OBJ_ADAPTER("WrongPolicy caught" + e);
1567: } catch (ObjectNotActive e) {
1568: // exit on an error condition, but need to clean up first (added to fix bug #400)
1569: poa.removeLocalRequest();
1570: throw new org.omg.CORBA.OBJECT_NOT_EXIST();
1571: }
1572: } else if (poa.isUseServantManager()) {
1573: byte[] oid = POAUtil.extractOID(getParsedIOR()
1574: .get_object_key());
1575: org.omg.PortableServer.ServantManager sm = poa
1576: .get_servant_manager();
1577:
1578: if (poa.isRetain()) {
1579: // ServantManager is a ServantActivator. Use the AOM to
1580: // incarnate this or return the servant. It will correctly
1581: // synchrnoize the requests.
1582: so.servant = poa._incarnateServant(oid,
1583: (ServantActivator) sm);
1584: } else {
1585: // ServantManager is a ServantLocator:
1586: // locate a servant
1587:
1588: org.omg.PortableServer.ServantLocator sl = (org.omg.PortableServer.ServantLocator) sm;
1589:
1590: // store this for postinvoke
1591:
1592: cookie = new org.omg.PortableServer.ServantLocatorPackage.CookieHolder();
1593:
1594: invokedOperation = operation;
1595:
1596: boolean ok = false;
1597:
1598: try {
1599: so.servant = sl.preinvoke(oid, poa,
1600: operation, cookie);
1601: } finally {
1602: if (!ok) {
1603: // error condition: need to clean up before
1604: // propagating the exception (added to fix
1605: // bug #400)
1606: poa.removeLocalRequest();
1607: }
1608: }
1609: }
1610: } else {
1611: throw new INTERNAL(
1612: "Internal error: we should not have gotten to this piece of code!");
1613: }
1614: } catch (WrongPolicy e) {
1615: // exit on an error condition, but need to clean up first (added to fix bug #400)
1616: poa.removeLocalRequest();
1617: throw new OBJ_ADAPTER("WrongPolicy caught" + e);
1618: } catch (org.omg.PortableServer.ForwardRequest e) {
1619: if (logger.isDebugEnabled()) {
1620: logger.debug("Caught forwardrequest to "
1621: + e.forward_reference + " from " + self);
1622: }
1623: return servant_preinvoke(e.forward_reference,
1624: operation, expectedType);
1625: }
1626:
1627: if (!expectedType.isInstance(so.servant)) {
1628: if (logger.isWarnEnabled()) {
1629: logger.warn("Expected " + expectedType + " got "
1630: + so.servant.getClass());
1631: }
1632:
1633: ignoreNextCallToIsLocal.set(Boolean.TRUE);
1634:
1635: poa.removeLocalRequest();
1636: return null;
1637: }
1638: orb
1639: .getPOACurrent()
1640: ._addContext(
1641: Thread.currentThread(),
1642: new org.jacorb.poa.LocalInvocationContext(
1643: orb,
1644: poa,
1645: getObjectId(),
1646: (org.omg.PortableServer.Servant) so.servant));
1647: return so;
1648: }
1649: if (logger.isWarnEnabled()) {
1650: logger.warn("No POA! servant_preinvoke returns null");
1651: }
1652: return null;
1653: }
1654:
1655: public String toString() {
1656: synchronized (bind_sync) {
1657: if (piorOriginal != null) {
1658: return piorOriginal.getIORString();
1659: }
1660: return getParsedIOR().getIORString();
1661: }
1662: }
1663:
1664: public String toString(org.omg.CORBA.Object self) {
1665: return toString();
1666: }
1667:
1668: public String typeId() {
1669: return getParsedIOR().getIOR().type_id;
1670: }
1671:
1672: public org.omg.CORBA.Object set_policy_override(
1673: org.omg.CORBA.Object self, org.omg.CORBA.Policy[] policies,
1674: org.omg.CORBA.SetOverrideType set_add) {
1675: if (policy_overrides == null) {
1676: policy_overrides = new HashMap();
1677: }
1678: if (set_add == org.omg.CORBA.SetOverrideType.SET_OVERRIDE) {
1679: policy_overrides.clear();
1680: }
1681:
1682: for (int i = 0; i < policies.length; i++) {
1683: policy_overrides.put(ObjectUtil.newInteger(policies[i]
1684: .policy_type()), policies[i]);
1685: }
1686:
1687: return self;
1688: }
1689:
1690: public String get_codebase(org.omg.CORBA.Object self) {
1691: return getParsedIOR().getCodebaseComponent();
1692: }
1693:
1694: public Set get_pending_replies() {
1695: return pending_replies;
1696: }
1697:
1698: public void replyDone(ReplyPlaceholder placeholder) {
1699: synchronized (pending_replies) {
1700: pending_replies.remove(placeholder);
1701: }
1702: }
1703:
1704: public void lockBarrier() {
1705: pending_replies_sync.lockBarrier();
1706: }
1707:
1708: public void waitOnBarrier() {
1709: pending_replies_sync.waitOnBarrier();
1710: }
1711:
1712: public void openBarrier() {
1713: pending_replies_sync.openBarrier();
1714: }
1715:
1716: /**
1717: * Call work_pending as that does a simple boolean check to establish
1718: * if the ORB has been shutdown - otherwise it throws BAD_INV_ORDER.
1719: */
1720: private void checkORB() {
1721: orb.work_pending();
1722: }
1723:
1724: private static class Barrier {
1725: private boolean is_open = true;
1726:
1727: public synchronized void waitOnBarrier() {
1728: while (!is_open) {
1729: try {
1730: this .wait();
1731: } catch (InterruptedException e) {
1732: //ignore
1733: }
1734: }
1735: }
1736:
1737: public synchronized void lockBarrier() {
1738: is_open = false;
1739: }
1740:
1741: public synchronized void openBarrier() {
1742: is_open = true;
1743:
1744: this.notifyAll();
1745: }
1746: }
1747: }
|