duke@1: /* skoppar@229: * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved. duke@1: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. duke@1: * duke@1: * This code is free software; you can redistribute it and/or modify it duke@1: * under the terms of the GNU General Public License version 2 only, as ohair@158: * published by the Free Software Foundation. Oracle designates this duke@1: * particular file as subject to the "Classpath" exception as provided ohair@158: * by Oracle in the LICENSE file that accompanied this code. duke@1: * duke@1: * This code is distributed in the hope that it will be useful, but WITHOUT duke@1: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or duke@1: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License duke@1: * version 2 for more details (a copy is included in the LICENSE file that duke@1: * accompanied this code). duke@1: * duke@1: * You should have received a copy of the GNU General Public License version duke@1: * 2 along with this work; if not, write to the Free Software Foundation, duke@1: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. duke@1: * ohair@158: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA ohair@158: * or visit www.oracle.com if you need additional information or have any ohair@158: * questions. duke@1: */ duke@1: duke@1: /* duke@1: * Licensed Materials - Property of IBM duke@1: * RMI-IIOP v1.0 duke@1: * Copyright IBM Corp. 1998 1999 All Rights Reserved duke@1: * duke@1: */ duke@1: duke@1: package com.sun.corba.se.impl.protocol; duke@1: duke@1: import java.io.IOException; duke@1: import java.util.Iterator; duke@1: import java.rmi.RemoteException; duke@1: duke@1: import javax.rmi.CORBA.Util; duke@1: import javax.rmi.CORBA.Tie; duke@1: duke@1: import org.omg.CORBA.COMM_FAILURE; duke@1: import org.omg.CORBA.INTERNAL; duke@1: import org.omg.CORBA.SystemException; duke@1: import org.omg.CORBA.Request; duke@1: import org.omg.CORBA.NamedValue; duke@1: import org.omg.CORBA.NVList; duke@1: import org.omg.CORBA.Context; duke@1: import org.omg.CORBA.ContextList; duke@1: import org.omg.CORBA.ExceptionList; duke@1: import org.omg.CORBA.TypeCode; duke@1: import org.omg.CORBA.portable.RemarshalException; duke@1: import org.omg.CORBA_2_3.portable.InputStream; duke@1: import org.omg.CORBA_2_3.portable.OutputStream; duke@1: import org.omg.CORBA.portable.Delegate; duke@1: import org.omg.CORBA.portable.ServantObject; duke@1: import org.omg.CORBA.portable.ApplicationException; duke@1: import org.omg.CORBA.portable.UnknownException; duke@1: import org.omg.IOP.ExceptionDetailMessage; duke@1: import org.omg.IOP.TAG_CODE_SETS; duke@1: duke@1: import com.sun.org.omg.SendingContext.CodeBase; duke@1: duke@1: import com.sun.corba.se.pept.broker.Broker; duke@1: import com.sun.corba.se.pept.encoding.InputObject; duke@1: import com.sun.corba.se.pept.encoding.OutputObject; duke@1: import com.sun.corba.se.pept.protocol.ClientRequestDispatcher; duke@1: import com.sun.corba.se.pept.protocol.MessageMediator; duke@1: import com.sun.corba.se.pept.transport.Connection; duke@1: import com.sun.corba.se.pept.transport.OutboundConnectionCache; duke@1: import com.sun.corba.se.pept.transport.ContactInfo; duke@1: duke@1: import com.sun.corba.se.spi.ior.IOR; duke@1: import com.sun.corba.se.spi.ior.iiop.GIOPVersion; duke@1: import com.sun.corba.se.spi.ior.iiop.IIOPProfileTemplate; duke@1: import com.sun.corba.se.spi.ior.iiop.CodeSetsComponent; duke@1: import com.sun.corba.se.spi.oa.OAInvocationInfo; duke@1: import com.sun.corba.se.spi.oa.ObjectAdapterFactory; duke@1: import com.sun.corba.se.spi.orb.ORB; duke@1: import com.sun.corba.se.spi.orb.ORBVersion; duke@1: import com.sun.corba.se.spi.orb.ORBVersionFactory; duke@1: import com.sun.corba.se.spi.protocol.CorbaMessageMediator; duke@1: import com.sun.corba.se.spi.protocol.RequestDispatcherRegistry; duke@1: import com.sun.corba.se.spi.transport.CorbaContactInfo ; duke@1: import com.sun.corba.se.spi.transport.CorbaContactInfoList ; duke@1: import com.sun.corba.se.spi.transport.CorbaContactInfoListIterator ; duke@1: import com.sun.corba.se.spi.transport.CorbaConnection; duke@1: import com.sun.corba.se.spi.logging.CORBALogDomains; duke@1: duke@1: import com.sun.corba.se.spi.servicecontext.MaxStreamFormatVersionServiceContext; duke@1: import com.sun.corba.se.spi.servicecontext.ServiceContext; duke@1: import com.sun.corba.se.spi.servicecontext.ServiceContexts; duke@1: import com.sun.corba.se.spi.servicecontext.UEInfoServiceContext; duke@1: import com.sun.corba.se.spi.servicecontext.CodeSetServiceContext; duke@1: import com.sun.corba.se.spi.servicecontext.SendingContextServiceContext; duke@1: import com.sun.corba.se.spi.servicecontext.ORBVersionServiceContext; duke@1: import com.sun.corba.se.spi.servicecontext.MaxStreamFormatVersionServiceContext; duke@1: import com.sun.corba.se.spi.servicecontext.UnknownServiceContext; duke@1: duke@1: import com.sun.corba.se.impl.encoding.CDRInputObject; duke@1: import com.sun.corba.se.impl.encoding.CodeSetComponentInfo; duke@1: import com.sun.corba.se.impl.encoding.CodeSetConversion; duke@1: import com.sun.corba.se.impl.encoding.EncapsInputStream; duke@1: import com.sun.corba.se.impl.encoding.MarshalOutputStream; duke@1: import com.sun.corba.se.impl.encoding.MarshalInputStream; duke@1: import com.sun.corba.se.impl.logging.ORBUtilSystemException; duke@1: import com.sun.corba.se.impl.orbutil.ORBUtility; duke@1: import com.sun.corba.se.impl.orbutil.ORBConstants; duke@1: import com.sun.corba.se.impl.protocol.giopmsgheaders.ReplyMessage; duke@1: import com.sun.corba.se.impl.protocol.giopmsgheaders.KeyAddr; duke@1: import com.sun.corba.se.impl.protocol.giopmsgheaders.ProfileAddr; duke@1: import com.sun.corba.se.impl.protocol.giopmsgheaders.ReferenceAddr; duke@1: import com.sun.corba.se.impl.transport.CorbaContactInfoListIteratorImpl; duke@1: import com.sun.corba.se.impl.util.JDKBridge; duke@1: duke@1: /** duke@1: * ClientDelegate is the RMI client-side subcontract or representation duke@1: * It implements RMI delegate as well as our internal ClientRequestDispatcher duke@1: * interface. duke@1: */ duke@1: public class CorbaClientRequestDispatcherImpl duke@1: implements duke@1: ClientRequestDispatcher duke@1: { duke@1: public OutputObject beginRequest(Object self, String opName, duke@1: boolean isOneWay, ContactInfo contactInfo) duke@1: { duke@1: ORB orb = null; duke@1: try { duke@1: CorbaContactInfo corbaContactInfo = (CorbaContactInfo) contactInfo; duke@1: orb = (ORB)contactInfo.getBroker(); duke@1: duke@1: if (orb.subcontractDebugFlag) { duke@1: dprint(".beginRequest->: op/" + opName); duke@1: } duke@1: duke@1: // duke@1: // Portable Interceptor initialization. duke@1: // duke@1: duke@1: orb.getPIHandler().initiateClientPIRequest( false ); duke@1: duke@1: // duke@1: // Connection. duke@1: // duke@1: duke@1: CorbaConnection connection = null; duke@1: duke@1: // This locking is done so that multiple connections are not created duke@1: // for the same endpoint skoppar@229: //6929137 - Synchronized on contactInfo to avoid blocking across multiple endpoints skoppar@229: synchronized (contactInfo) { duke@1: if (contactInfo.isConnectionBased()) { duke@1: if (contactInfo.shouldCacheConnection()) { duke@1: connection = (CorbaConnection) duke@1: orb.getTransportManager() duke@1: .getOutboundConnectionCache(contactInfo).get(contactInfo); duke@1: } duke@1: if (connection != null) { duke@1: if (orb.subcontractDebugFlag) { duke@1: dprint(".beginRequest: op/" + opName duke@1: + ": Using cached connection: " + connection); duke@1: } duke@1: } else { duke@1: try { duke@1: connection = (CorbaConnection) duke@1: contactInfo.createConnection(); duke@1: if (orb.subcontractDebugFlag) { duke@1: dprint(".beginRequest: op/" + opName duke@1: + ": Using created connection: " + connection); duke@1: } duke@1: } catch (RuntimeException e) { duke@1: if (orb.subcontractDebugFlag) { duke@1: dprint(".beginRequest: op/" + opName duke@1: + ": failed to create connection: " + e); duke@1: } duke@1: // REVISIT: this part similar to marshalingComplete below. duke@1: boolean retry = getContactInfoListIterator(orb) duke@1: .reportException(contactInfo, e); duke@1: // REVISIT: duke@1: // this part similar to Remarshal in this method below duke@1: if (retry) { duke@1: if(getContactInfoListIterator(orb).hasNext()) { duke@1: contactInfo = (ContactInfo) duke@1: getContactInfoListIterator(orb).next(); robm@215: unregisterWaiter(orb); duke@1: return beginRequest(self, opName, duke@1: isOneWay, contactInfo); duke@1: } else { duke@1: throw e; duke@1: } duke@1: } else { duke@1: throw e; duke@1: } duke@1: } duke@1: if (connection.shouldRegisterReadEvent()) { duke@1: // REVISIT: cast duke@1: orb.getTransportManager().getSelector(0) duke@1: .registerForEvent(connection.getEventHandler()); duke@1: connection.setState("ESTABLISHED"); duke@1: } duke@1: // Do not do connection reclaim here since the connections duke@1: // are marked in use by registerWaiter() call and since this duke@1: // call happens later do it after that. duke@1: if (contactInfo.shouldCacheConnection()) { duke@1: OutboundConnectionCache connectionCache = duke@1: orb.getTransportManager() duke@1: .getOutboundConnectionCache(contactInfo); duke@1: connectionCache.stampTime(connection); duke@1: connectionCache.put(contactInfo, connection); duke@1: // connectionCache.reclaim(); duke@1: } duke@1: } duke@1: } duke@1: } duke@1: duke@1: CorbaMessageMediator messageMediator = (CorbaMessageMediator) duke@1: contactInfo.createMessageMediator( duke@1: orb, contactInfo, connection, opName, isOneWay); duke@1: if (orb.subcontractDebugFlag) { duke@1: dprint(".beginRequest: " + opAndId(messageMediator) duke@1: + ": created message mediator: " + messageMediator); duke@1: } duke@1: duke@1: // NOTE: Thread data so we can get the mediator in release reply duke@1: // in order to remove the waiter in CorbaConnection. duke@1: // We cannot depend on obtaining information in releaseReply duke@1: // via its InputStream argument since, on certain errors duke@1: // (e.g., client marshaling errors), the stream may be null. duke@1: // Likewise for releaseReply "self". duke@1: // NOTE: This must be done before initializing the message since duke@1: // that may start sending fragments which may end up in "early" duke@1: // replies or client marshaling exceptions. duke@1: duke@1: orb.getInvocationInfo().setMessageMediator(messageMediator); duke@1: duke@1: if (connection != null && connection.getCodeSetContext() == null) { duke@1: performCodeSetNegotiation(messageMediator); duke@1: } duke@1: duke@1: addServiceContexts(messageMediator); duke@1: duke@1: OutputObject outputObject = duke@1: contactInfo.createOutputObject(messageMediator); duke@1: if (orb.subcontractDebugFlag) { duke@1: dprint(".beginRequest: " + opAndId(messageMediator) duke@1: + ": created output object: " + outputObject); duke@1: } duke@1: duke@1: duke@1: // NOTE: Not necessary for oneways, but useful for debugging. duke@1: // This must be done BEFORE message initialization since fragments duke@1: // may be sent at that time. duke@1: registerWaiter(messageMediator); duke@1: duke@1: // Do connection reclaim now skoppar@229: synchronized (contactInfo) { duke@1: if (contactInfo.isConnectionBased()) { duke@1: if (contactInfo.shouldCacheConnection()) { duke@1: OutboundConnectionCache connectionCache = duke@1: orb.getTransportManager() duke@1: .getOutboundConnectionCache(contactInfo); duke@1: connectionCache.reclaim(); duke@1: } duke@1: } duke@1: } duke@1: duke@1: orb.getPIHandler().setClientPIInfo(messageMediator); duke@1: try { duke@1: // This MUST come before message is initialized so duke@1: // service contexts may be added by PI because duke@1: // initial fragments may be sent during message initialization. duke@1: orb.getPIHandler().invokeClientPIStartingPoint(); duke@1: } catch( RemarshalException e ) { duke@1: if (orb.subcontractDebugFlag) { duke@1: dprint(".beginRequest: " + opAndId(messageMediator) duke@1: + ": Remarshal"); duke@1: } duke@1: duke@1: // NOTE: We get here because an interceptor raised ForwardRequest duke@1: // and updated the IOR/Iterator. Since we have a fresh iterator duke@1: // hasNext should succeed. duke@1: duke@1: // REVISIT: We should feed ALL interceptor exceptions to duke@1: // iterator.reportException so it can determine if it wants duke@1: // to retry. Right now, SystemExceptions will flow to the duke@1: // client code. duke@1: duke@1: // REVISIT: duke@1: // This assumes that interceptors update duke@1: // ContactInfoList outside of subcontract. duke@1: // Want to move that update to here. duke@1: if (getContactInfoListIterator(orb).hasNext()) { robm@215: contactInfo = (ContactInfo)getContactInfoListIterator(orb).next(); robm@215: if (orb.subcontractDebugFlag) { robm@215: dprint( "RemarshalException: hasNext true\ncontact info " + contactInfo ); robm@215: } robm@215: robm@215: // Fix for 6763340: Complete the first attempt before starting another. robm@215: orb.getPIHandler().makeCompletedClientRequest( robm@215: ReplyMessage.LOCATION_FORWARD, null ) ; robm@215: unregisterWaiter(orb); robm@215: orb.getPIHandler().cleanupClientPIRequest() ; robm@215: duke@1: return beginRequest(self, opName, isOneWay, contactInfo); duke@1: } else { robm@215: if (orb.subcontractDebugFlag) { robm@215: dprint( "RemarshalException: hasNext false" ); robm@215: } duke@1: ORBUtilSystemException wrapper = duke@1: ORBUtilSystemException.get(orb, duke@1: CORBALogDomains.RPC_PROTOCOL); duke@1: throw wrapper.remarshalWithNowhereToGo(); duke@1: } duke@1: } duke@1: duke@1: messageMediator.initializeMessage(); duke@1: if (orb.subcontractDebugFlag) { duke@1: dprint(".beginRequest: " + opAndId(messageMediator) duke@1: + ": initialized message"); duke@1: } duke@1: duke@1: return outputObject; duke@1: duke@1: } finally { duke@1: if (orb.subcontractDebugFlag) { duke@1: dprint(".beginRequest<-: op/" + opName); duke@1: } duke@1: } duke@1: } duke@1: duke@1: public InputObject marshalingComplete(java.lang.Object self, duke@1: OutputObject outputObject) duke@1: throws duke@1: ApplicationException, duke@1: org.omg.CORBA.portable.RemarshalException duke@1: { duke@1: ORB orb = null; duke@1: CorbaMessageMediator messageMediator = null; duke@1: try { duke@1: messageMediator = (CorbaMessageMediator) duke@1: outputObject.getMessageMediator(); duke@1: duke@1: orb = (ORB) messageMediator.getBroker(); duke@1: duke@1: if (orb.subcontractDebugFlag) { duke@1: dprint(".marshalingComplete->: " + opAndId(messageMediator)); duke@1: } duke@1: duke@1: InputObject inputObject = duke@1: marshalingComplete1(orb, messageMediator); duke@1: duke@1: return processResponse(orb, messageMediator, inputObject); duke@1: duke@1: } finally { duke@1: if (orb.subcontractDebugFlag) { duke@1: dprint(".marshalingComplete<-: " + opAndId(messageMediator)); duke@1: } duke@1: } duke@1: } duke@1: duke@1: public InputObject marshalingComplete1( duke@1: ORB orb, CorbaMessageMediator messageMediator) duke@1: throws duke@1: ApplicationException, duke@1: org.omg.CORBA.portable.RemarshalException duke@1: { duke@1: try { duke@1: messageMediator.finishSendingRequest(); duke@1: duke@1: if (orb.subcontractDebugFlag) { duke@1: dprint(".marshalingComplete: " + opAndId(messageMediator) duke@1: + ": finished sending request"); duke@1: } duke@1: duke@1: return messageMediator.waitForResponse(); duke@1: duke@1: } catch (RuntimeException e) { duke@1: duke@1: if (orb.subcontractDebugFlag) { duke@1: dprint(".marshalingComplete: " + opAndId(messageMediator) duke@1: + ": exception: " + e.toString()); duke@1: } duke@1: duke@1: boolean retry = duke@1: getContactInfoListIterator(orb) duke@1: .reportException(messageMediator.getContactInfo(), e); vikram@231: vikram@231: //Bug 6382377: must not lose exception in PI vikram@231: vikram@231: // Must run interceptor end point before retrying. vikram@231: Exception newException = vikram@231: orb.getPIHandler().invokeClientPIEndingPoint( vikram@231: ReplyMessage.SYSTEM_EXCEPTION, e); vikram@231: duke@1: if (retry) { duke@1: if (newException == e) { duke@1: continueOrThrowSystemOrRemarshal(messageMediator, duke@1: new RemarshalException()); duke@1: } else { duke@1: continueOrThrowSystemOrRemarshal(messageMediator, duke@1: newException); duke@1: } duke@1: } else { vikram@231: if (newException instanceof RuntimeException){ vikram@231: throw (RuntimeException)newException; vikram@231: } vikram@231: else if (newException instanceof RemarshalException) vikram@231: { vikram@231: throw (RemarshalException)newException; vikram@231: } vikram@231: duke@1: // NOTE: Interceptor ending point will run in releaseReply. duke@1: throw e; duke@1: } duke@1: return null; // for compiler duke@1: } duke@1: } duke@1: duke@1: protected InputObject processResponse(ORB orb, duke@1: CorbaMessageMediator messageMediator, duke@1: InputObject inputObject) duke@1: throws duke@1: ApplicationException, duke@1: org.omg.CORBA.portable.RemarshalException duke@1: { duke@1: ORBUtilSystemException wrapper = duke@1: ORBUtilSystemException.get( orb, duke@1: CORBALogDomains.RPC_PROTOCOL ) ; duke@1: duke@1: if (orb.subcontractDebugFlag) { duke@1: dprint(".processResponse: " + opAndId(messageMediator) duke@1: + ": response received"); duke@1: } duke@1: duke@1: // We know for sure now that we've sent a message. duke@1: // So OK to not send initial again. duke@1: if (messageMediator.getConnection() != null) { duke@1: ((CorbaConnection)messageMediator.getConnection()) duke@1: .setPostInitialContexts(); duke@1: } duke@1: duke@1: // NOTE: not necessary to set MessageMediator for PI. duke@1: // It already has it. duke@1: duke@1: // Process the response. duke@1: duke@1: Exception exception = null; duke@1: duke@1: if (messageMediator.isOneWay()) { duke@1: getContactInfoListIterator(orb) duke@1: .reportSuccess(messageMediator.getContactInfo()); duke@1: // Invoke Portable Interceptors with receive_other duke@1: exception = orb.getPIHandler().invokeClientPIEndingPoint( duke@1: ReplyMessage.NO_EXCEPTION, exception ); duke@1: continueOrThrowSystemOrRemarshal(messageMediator, exception); duke@1: return null; duke@1: } duke@1: duke@1: consumeServiceContexts(orb, messageMediator); duke@1: duke@1: // Now that we have the service contexts processed and the duke@1: // correct ORBVersion set, we must finish initializing the stream. duke@1: // REVISIT - need interface for this operation. duke@1: ((CDRInputObject)inputObject).performORBVersionSpecificInit(); duke@1: duke@1: if (messageMediator.isSystemExceptionReply()) { duke@1: duke@1: SystemException se = messageMediator.getSystemExceptionReply(); duke@1: duke@1: if (orb.subcontractDebugFlag) { duke@1: dprint(".processResponse: " + opAndId(messageMediator) duke@1: + ": received system exception: " + se); duke@1: } duke@1: duke@1: boolean doRemarshal = duke@1: getContactInfoListIterator(orb) duke@1: .reportException(messageMediator.getContactInfo(), se); duke@1: duke@1: if (doRemarshal) { duke@1: duke@1: // Invoke Portable Interceptors with receive_exception: duke@1: exception = orb.getPIHandler().invokeClientPIEndingPoint( duke@1: ReplyMessage.SYSTEM_EXCEPTION, se ); duke@1: duke@1: // If PI did not change the exception, throw a duke@1: // Remarshal. duke@1: if( se == exception ) { duke@1: // exception = null is to maintain symmetry with duke@1: // GenericPOAClientSC. duke@1: exception = null; duke@1: continueOrThrowSystemOrRemarshal(messageMediator, duke@1: new RemarshalException()); duke@1: throw wrapper.statementNotReachable1() ; duke@1: } else { duke@1: // Otherwise, throw the exception PI wants thrown. duke@1: continueOrThrowSystemOrRemarshal(messageMediator, duke@1: exception); duke@1: throw wrapper.statementNotReachable2() ; duke@1: } duke@1: } duke@1: duke@1: // No retry, so see if was unknown. duke@1: duke@1: ServiceContexts contexts = duke@1: messageMediator.getReplyServiceContexts(); duke@1: if (contexts != null) { duke@1: UEInfoServiceContext usc = duke@1: (UEInfoServiceContext) duke@1: contexts.get(UEInfoServiceContext.SERVICE_CONTEXT_ID); duke@1: duke@1: if (usc != null) { duke@1: Throwable unknown = usc.getUE() ; duke@1: UnknownException ue = new UnknownException(unknown); duke@1: duke@1: // Invoke Portable Interceptors with receive_exception: duke@1: exception = orb.getPIHandler().invokeClientPIEndingPoint( duke@1: ReplyMessage.SYSTEM_EXCEPTION, ue ); duke@1: duke@1: continueOrThrowSystemOrRemarshal(messageMediator, exception); duke@1: throw wrapper.statementNotReachable3() ; duke@1: } duke@1: } duke@1: duke@1: // It was not a comm failure nor unknown. duke@1: // This is the general case. duke@1: duke@1: // Invoke Portable Interceptors with receive_exception: duke@1: exception = orb.getPIHandler().invokeClientPIEndingPoint( duke@1: ReplyMessage.SYSTEM_EXCEPTION, se ); duke@1: duke@1: continueOrThrowSystemOrRemarshal(messageMediator, exception); duke@1: duke@1: // Note: We should never need to execute this line, but duke@1: // we should assert in case exception is null somehow. duke@1: throw wrapper.statementNotReachable4() ; duke@1: } else if (messageMediator.isUserExceptionReply()) { duke@1: duke@1: if (orb.subcontractDebugFlag) { duke@1: dprint(".processResponse: " + opAndId(messageMediator) duke@1: + ": received user exception"); duke@1: } duke@1: duke@1: getContactInfoListIterator(orb) duke@1: .reportSuccess(messageMediator.getContactInfo()); duke@1: duke@1: String exceptionRepoId = peekUserExceptionId(inputObject); duke@1: Exception newException = null; duke@1: duke@1: if (messageMediator.isDIIRequest()) { duke@1: exception = messageMediator.unmarshalDIIUserException( duke@1: exceptionRepoId, (InputStream)inputObject); duke@1: newException = orb.getPIHandler().invokeClientPIEndingPoint( duke@1: ReplyMessage.USER_EXCEPTION, exception ); duke@1: messageMediator.setDIIException(newException); duke@1: duke@1: } else { duke@1: ApplicationException appException = duke@1: new ApplicationException( duke@1: exceptionRepoId, duke@1: (org.omg.CORBA.portable.InputStream)inputObject); duke@1: exception = appException; duke@1: newException = orb.getPIHandler().invokeClientPIEndingPoint( duke@1: ReplyMessage.USER_EXCEPTION, appException ); duke@1: } duke@1: duke@1: if (newException != exception) { duke@1: continueOrThrowSystemOrRemarshal(messageMediator,newException); duke@1: } duke@1: duke@1: if (newException instanceof ApplicationException) { duke@1: throw (ApplicationException)newException; duke@1: } duke@1: // For DII: duke@1: // This return will be ignored - already unmarshaled above. duke@1: return inputObject; duke@1: duke@1: } else if (messageMediator.isLocationForwardReply()) { duke@1: duke@1: if (orb.subcontractDebugFlag) { duke@1: dprint(".processResponse: " + opAndId(messageMediator) duke@1: + ": received location forward"); duke@1: } duke@1: duke@1: // NOTE: Expects iterator to update target IOR duke@1: getContactInfoListIterator(orb).reportRedirect( duke@1: (CorbaContactInfo)messageMediator.getContactInfo(), duke@1: messageMediator.getForwardedIOR()); duke@1: duke@1: // Invoke Portable Interceptors with receive_other: duke@1: Exception newException = orb.getPIHandler().invokeClientPIEndingPoint( duke@1: ReplyMessage.LOCATION_FORWARD, null ); duke@1: duke@1: if( !(newException instanceof RemarshalException) ) { duke@1: exception = newException; duke@1: } duke@1: duke@1: // If PI did not change exception, throw Remarshal, else duke@1: // throw the exception PI wants thrown. duke@1: // KMC: GenericPOAClientSC did not check exception != null duke@1: if( exception != null ) { duke@1: continueOrThrowSystemOrRemarshal(messageMediator, exception); duke@1: } duke@1: continueOrThrowSystemOrRemarshal(messageMediator, duke@1: new RemarshalException()); duke@1: throw wrapper.statementNotReachable5() ; duke@1: duke@1: } else if (messageMediator.isDifferentAddrDispositionRequestedReply()){ duke@1: duke@1: if (orb.subcontractDebugFlag) { duke@1: dprint(".processResponse: " + opAndId(messageMediator) duke@1: + ": received different addressing dispostion request"); duke@1: } duke@1: duke@1: // Set the desired target addressing disposition. duke@1: getContactInfoListIterator(orb).reportAddrDispositionRetry( duke@1: (CorbaContactInfo)messageMediator.getContactInfo(), duke@1: messageMediator.getAddrDispositionReply()); duke@1: duke@1: // Invoke Portable Interceptors with receive_other: duke@1: Exception newException = orb.getPIHandler().invokeClientPIEndingPoint( duke@1: ReplyMessage.NEEDS_ADDRESSING_MODE, null); duke@1: duke@1: // For consistency with corresponding code in GenericPOAClientSC: duke@1: if( !(newException instanceof RemarshalException) ) { duke@1: exception = newException; duke@1: } duke@1: duke@1: // If PI did not change exception, throw Remarshal, else duke@1: // throw the exception PI wants thrown. duke@1: // KMC: GenericPOAClientSC did not include exception != null check duke@1: if( exception != null ) { duke@1: continueOrThrowSystemOrRemarshal(messageMediator, exception); duke@1: } duke@1: continueOrThrowSystemOrRemarshal(messageMediator, duke@1: new RemarshalException()); duke@1: throw wrapper.statementNotReachable6() ; duke@1: } else /* normal response */ { duke@1: duke@1: if (orb.subcontractDebugFlag) { duke@1: dprint(".processResponse: " + opAndId(messageMediator) duke@1: + ": received normal response"); duke@1: } duke@1: duke@1: getContactInfoListIterator(orb) duke@1: .reportSuccess(messageMediator.getContactInfo()); duke@1: duke@1: messageMediator.handleDIIReply((InputStream)inputObject); duke@1: duke@1: // Invoke Portable Interceptors with receive_reply: duke@1: exception = orb.getPIHandler().invokeClientPIEndingPoint( duke@1: ReplyMessage.NO_EXCEPTION, null ); duke@1: duke@1: // Remember: not thrown if exception is null. duke@1: continueOrThrowSystemOrRemarshal(messageMediator, exception); duke@1: duke@1: return inputObject; duke@1: } duke@1: } duke@1: duke@1: // Filters the given exception into a SystemException or a duke@1: // RemarshalException and throws it. Assumes the given exception is duke@1: // of one of these two types. This is a utility method for duke@1: // the above invoke code which must do this numerous times. duke@1: // If the exception is null, no exception is thrown. duke@1: // duke@1: // Note that this code is duplicated in GenericPOAClientSC.java duke@1: protected void continueOrThrowSystemOrRemarshal( duke@1: CorbaMessageMediator messageMediator, Exception exception) duke@1: throws duke@1: SystemException, RemarshalException duke@1: { duke@1: duke@1: ORB orb = (ORB) messageMediator.getBroker(); duke@1: duke@1: if( exception == null ) { duke@1: duke@1: // do nothing. duke@1: duke@1: } else if( exception instanceof RemarshalException ) { duke@1: duke@1: // REVISIT - unify with PI handling duke@1: orb.getInvocationInfo().setIsRetryInvocation(true); duke@1: duke@1: // NOTE - We must unregister the waiter NOW for this request duke@1: // since the retry will result in a new request id. Therefore duke@1: // the old request id would be lost and we would have a memory duke@1: // leak in the responseWaitingRoom. duke@1: unregisterWaiter(orb); duke@1: duke@1: if (orb.subcontractDebugFlag) { duke@1: dprint(".continueOrThrowSystemOrRemarshal: " duke@1: + opAndId(messageMediator) duke@1: + ": throwing Remarshal"); duke@1: } duke@1: duke@1: throw (RemarshalException)exception; duke@1: duke@1: } else { duke@1: duke@1: if (orb.subcontractDebugFlag) { duke@1: dprint(".continueOrThrowSystemOrRemarshal: " duke@1: + opAndId(messageMediator) duke@1: + ": throwing sex:" duke@1: + exception); duke@1: } duke@1: duke@1: throw (SystemException)exception; duke@1: } duke@1: } duke@1: duke@1: protected CorbaContactInfoListIterator getContactInfoListIterator(ORB orb) duke@1: { duke@1: return (CorbaContactInfoListIterator) duke@1: ((CorbaInvocationInfo)orb.getInvocationInfo()) duke@1: .getContactInfoListIterator(); duke@1: } duke@1: duke@1: protected void registerWaiter(CorbaMessageMediator messageMediator) duke@1: { duke@1: if (messageMediator.getConnection() != null) { duke@1: messageMediator.getConnection().registerWaiter(messageMediator); duke@1: } duke@1: } duke@1: duke@1: protected void unregisterWaiter(ORB orb) duke@1: { duke@1: MessageMediator messageMediator = duke@1: orb.getInvocationInfo().getMessageMediator(); duke@1: if (messageMediator!=null && messageMediator.getConnection() != null) { duke@1: // REVISIT: duke@1: // The messageMediator may be null if COMM_FAILURE before duke@1: // it is created. duke@1: messageMediator.getConnection().unregisterWaiter(messageMediator); duke@1: } duke@1: } duke@1: duke@1: protected void addServiceContexts(CorbaMessageMediator messageMediator) duke@1: { duke@1: ORB orb = (ORB)messageMediator.getBroker(); duke@1: CorbaConnection c = (CorbaConnection) messageMediator.getConnection(); duke@1: GIOPVersion giopVersion = messageMediator.getGIOPVersion(); duke@1: duke@1: ServiceContexts contexts = messageMediator.getRequestServiceContexts(); duke@1: duke@1: addCodeSetServiceContext(c, contexts, giopVersion); duke@1: duke@1: // Add the RMI-IIOP max stream format version duke@1: // service context to every request. Once we have GIOP 1.3, duke@1: // we could skip it since we now support version 2, but duke@1: // probably safer to always send it. duke@1: contexts.put(MaxStreamFormatVersionServiceContext.singleton); duke@1: duke@1: // ORBVersion servicecontext needs to be sent duke@1: ORBVersionServiceContext ovsc = new ORBVersionServiceContext( duke@1: ORBVersionFactory.getORBVersion() ) ; duke@1: contexts.put( ovsc ) ; duke@1: duke@1: // NOTE : We only want to send the runtime context the first time duke@1: if ((c != null) && !c.isPostInitialContexts()) { duke@1: // Do not do c.setPostInitialContexts() here. duke@1: // If a client interceptor send_request does a ForwardRequest duke@1: // which ends up using the same connection then the service duke@1: // context would not be sent. duke@1: SendingContextServiceContext scsc = duke@1: new SendingContextServiceContext( orb.getFVDCodeBaseIOR() ) ; //d11638 duke@1: contexts.put( scsc ) ; duke@1: } duke@1: } duke@1: duke@1: protected void consumeServiceContexts(ORB orb, duke@1: CorbaMessageMediator messageMediator) duke@1: { duke@1: ServiceContexts ctxts = messageMediator.getReplyServiceContexts(); duke@1: ServiceContext sc ; duke@1: ORBUtilSystemException wrapper = ORBUtilSystemException.get( orb, duke@1: CORBALogDomains.RPC_PROTOCOL ) ; duke@1: duke@1: if (ctxts == null) { duke@1: return; // no service context available, return gracefully. duke@1: } duke@1: duke@1: sc = ctxts.get( SendingContextServiceContext.SERVICE_CONTEXT_ID ) ; duke@1: duke@1: if (sc != null) { duke@1: SendingContextServiceContext scsc = duke@1: (SendingContextServiceContext)sc ; duke@1: IOR ior = scsc.getIOR() ; duke@1: duke@1: try { duke@1: // set the codebase returned by the server duke@1: if (messageMediator.getConnection() != null) { duke@1: ((CorbaConnection)messageMediator.getConnection()).setCodeBaseIOR(ior); duke@1: } duke@1: } catch (ThreadDeath td) { duke@1: throw td ; duke@1: } catch (Throwable t) { duke@1: throw wrapper.badStringifiedIor( t ) ; duke@1: } duke@1: } duke@1: duke@1: // see if the version subcontract is present, if yes, then set duke@1: // the ORBversion duke@1: sc = ctxts.get( ORBVersionServiceContext.SERVICE_CONTEXT_ID ) ; duke@1: duke@1: if (sc != null) { duke@1: ORBVersionServiceContext ovsc = duke@1: (ORBVersionServiceContext) sc; duke@1: duke@1: ORBVersion version = ovsc.getVersion(); duke@1: orb.setORBVersion( version ) ; duke@1: } duke@1: duke@1: getExceptionDetailMessage(messageMediator, wrapper); duke@1: } duke@1: duke@1: protected void getExceptionDetailMessage( duke@1: CorbaMessageMediator messageMediator, duke@1: ORBUtilSystemException wrapper) duke@1: { duke@1: ServiceContext sc = messageMediator.getReplyServiceContexts() duke@1: .get(ExceptionDetailMessage.value); duke@1: if (sc == null) duke@1: return ; duke@1: duke@1: if (! (sc instanceof UnknownServiceContext)) { duke@1: throw wrapper.badExceptionDetailMessageServiceContextType(); duke@1: } duke@1: byte[] data = ((UnknownServiceContext)sc).getData(); duke@1: EncapsInputStream in = duke@1: new EncapsInputStream((ORB)messageMediator.getBroker(), duke@1: data, data.length); duke@1: in.consumeEndian(); duke@1: duke@1: String msg = duke@1: "----------BEGIN server-side stack trace----------\n" duke@1: + in.read_wstring() + "\n" duke@1: + "----------END server-side stack trace----------"; duke@1: duke@1: messageMediator.setReplyExceptionDetailMessage(msg); duke@1: } duke@1: duke@1: public void endRequest(Broker broker, Object self, InputObject inputObject) duke@1: { duke@1: ORB orb = (ORB)broker ; duke@1: duke@1: try { duke@1: if (orb.subcontractDebugFlag) { duke@1: dprint(".endRequest->"); duke@1: } duke@1: duke@1: // Note: the inputObject may be null if an error occurs duke@1: // in request or before _invoke returns. duke@1: // Note: self may be null also (e.g., compiler generates null in stub). duke@1: duke@1: MessageMediator messageMediator = duke@1: orb.getInvocationInfo().getMessageMediator(); duke@1: if (messageMediator != null) duke@1: { duke@1: if (messageMediator.getConnection() != null) duke@1: { duke@1: ((CorbaMessageMediator)messageMediator) duke@1: .sendCancelRequestIfFinalFragmentNotSent(); duke@1: } duke@1: duke@1: // Release any outstanding NIO ByteBuffers to the ByteBufferPool duke@1: duke@1: InputObject inputObj = messageMediator.getInputObject(); duke@1: if (inputObj != null) { duke@1: inputObj.close(); duke@1: } duke@1: duke@1: OutputObject outputObj = messageMediator.getOutputObject(); duke@1: if (outputObj != null) { duke@1: outputObj.close(); duke@1: } duke@1: duke@1: } duke@1: duke@1: // XREVISIT NOTE - Assumes unregistering the waiter for duke@1: // location forwards has already happened somewhere else. duke@1: // The code below is only going to unregister the final successful duke@1: // request. duke@1: duke@1: // NOTE: In the case of a recursive stack of endRequests in a duke@1: // finally block (because of Remarshal) only the first call to duke@1: // unregisterWaiter will remove the waiter. The rest will be duke@1: // noops. duke@1: unregisterWaiter(orb); duke@1: duke@1: // Invoke Portable Interceptors cleanup. This is done to handle duke@1: // exceptions during stream marshaling. More generally, exceptions duke@1: // that occur in the ORB after send_request (which includes duke@1: // after returning from _request) before _invoke: duke@1: orb.getPIHandler().cleanupClientPIRequest(); duke@1: duke@1: // REVISIT: Early replies? duke@1: } catch (IOException ex) { duke@1: // See CDRInput/OutputObject.close() for more info. duke@1: // This won't result in a Corba error if an IOException happens. duke@1: if (orb.subcontractDebugFlag) duke@1: { duke@1: dprint(".endRequest: ignoring IOException - " + ex.toString()); duke@1: } duke@1: } finally { duke@1: if (orb.subcontractDebugFlag) { duke@1: dprint(".endRequest<-"); duke@1: } duke@1: } duke@1: } duke@1: duke@1: duke@1: protected void performCodeSetNegotiation(CorbaMessageMediator messageMediator) duke@1: { duke@1: CorbaConnection conn = duke@1: (CorbaConnection) messageMediator.getConnection(); duke@1: IOR ior = duke@1: ((CorbaContactInfo)messageMediator.getContactInfo()) duke@1: .getEffectiveTargetIOR(); duke@1: GIOPVersion giopVersion = messageMediator.getGIOPVersion(); duke@1: duke@1: // XXX This seems to be a broken double checked locking idiom: FIX IT! duke@1: duke@1: // conn.getCodeSetContext() is null when no other requests have duke@1: // been made on this connection to trigger code set negotation. duke@1: if (conn != null && duke@1: conn.getCodeSetContext() == null && duke@1: !giopVersion.equals(GIOPVersion.V1_0)) { duke@1: duke@1: synchronized(conn) { duke@1: // Double checking. Don't let any other duke@1: // threads use this connection until the duke@1: // code sets are straight. duke@1: if (conn.getCodeSetContext() != null) duke@1: return; duke@1: duke@1: // This only looks at the first code set component. If duke@1: // there can be multiple locations with multiple code sets, duke@1: // this requires more work. duke@1: IIOPProfileTemplate temp = duke@1: (IIOPProfileTemplate)ior.getProfile(). duke@1: getTaggedProfileTemplate(); duke@1: Iterator iter = temp.iteratorById(TAG_CODE_SETS.value); duke@1: if (!iter.hasNext()) { duke@1: // Didn't have a code set component. The default will duke@1: // be to use ISO8859-1 for char data and throw an duke@1: // exception if wchar data is used. duke@1: return; duke@1: } duke@1: duke@1: // Get the native and conversion code sets the duke@1: // server specified in its IOR duke@1: CodeSetComponentInfo serverCodeSets duke@1: = ((CodeSetsComponent)iter.next()).getCodeSetComponentInfo(); duke@1: duke@1: // Perform the negotiation between this ORB's code sets and duke@1: // the ones from the IOR duke@1: CodeSetComponentInfo.CodeSetContext result duke@1: = CodeSetConversion.impl().negotiate( duke@1: conn.getBroker().getORBData().getCodeSetComponentInfo(), duke@1: serverCodeSets); duke@1: duke@1: conn.setCodeSetContext(result); duke@1: } duke@1: } duke@1: } duke@1: duke@1: protected void addCodeSetServiceContext(CorbaConnection conn, duke@1: ServiceContexts ctxs, duke@1: GIOPVersion giopVersion) { duke@1: duke@1: // REVISIT. OMG issue 3318 concerning sending the code set duke@1: // service context more than once was deemed too much for the duke@1: // RTF. Here's our strategy for the moment: duke@1: // duke@1: // Send it on every request (necessary in cases of fragmentation duke@1: // with multithreaded clients or when the first thing on a duke@1: // connection is a LocateRequest). Provide an ORB property duke@1: // to disable multiple sends. duke@1: // duke@1: // Note that the connection is null in the local case and no duke@1: // service context is included. We use the ORB provided duke@1: // encapsulation streams. duke@1: // duke@1: // Also, there will be no negotiation or service context duke@1: // in GIOP 1.0. ISO8859-1 is used for char/string, and duke@1: // wchar/wstring are illegal. duke@1: // duke@1: if (giopVersion.equals(GIOPVersion.V1_0) || conn == null) duke@1: return; duke@1: duke@1: CodeSetComponentInfo.CodeSetContext codeSetCtx = null; duke@1: duke@1: if (conn.getBroker().getORBData().alwaysSendCodeSetServiceContext() || duke@1: !conn.isPostInitialContexts()) { duke@1: duke@1: // Get the negotiated code sets (if any) out of the connection duke@1: codeSetCtx = conn.getCodeSetContext(); duke@1: } duke@1: duke@1: // Either we shouldn't send the code set service context, or duke@1: // for some reason, the connection doesn't have its code sets. duke@1: // Perhaps the server didn't include them in the IOR. Uses duke@1: // ISO8859-1 for char and makes wchar/wstring illegal. duke@1: if (codeSetCtx == null) duke@1: return; duke@1: duke@1: CodeSetServiceContext cssc = new CodeSetServiceContext(codeSetCtx); duke@1: ctxs.put(cssc); duke@1: } duke@1: duke@1: protected String peekUserExceptionId(InputObject inputObject) duke@1: { duke@1: CDRInputObject cdrInputObject = (CDRInputObject) inputObject; duke@1: // REVISIT - need interface for mark/reset duke@1: cdrInputObject.mark(Integer.MAX_VALUE); duke@1: String result = cdrInputObject.read_string(); duke@1: cdrInputObject.reset(); duke@1: return result; duke@1: } duke@1: duke@1: protected void dprint(String msg) duke@1: { duke@1: ORBUtility.dprint("CorbaClientRequestDispatcherImpl", msg); duke@1: } duke@1: duke@1: protected String opAndId(CorbaMessageMediator mediator) duke@1: { duke@1: return ORBUtility.operationNameAndRequestId(mediator); duke@1: } duke@1: } duke@1: duke@1: // End of file.