Mon, 29 Nov 2010 22:10:46 -0800
6382377: incorrect Exception is given to interceptor
6828768: RMI-IIOP EJB clients do not fail over due to defect in JDK 1.6.0_12
Summary: Also reviewed by ken.cavanaugh@oracle.com
Reviewed-by: skoppar
duke@1 | 1 | /* |
skoppar@229 | 2 | * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved. |
duke@1 | 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
duke@1 | 4 | * |
duke@1 | 5 | * This code is free software; you can redistribute it and/or modify it |
duke@1 | 6 | * under the terms of the GNU General Public License version 2 only, as |
ohair@158 | 7 | * published by the Free Software Foundation. Oracle designates this |
duke@1 | 8 | * particular file as subject to the "Classpath" exception as provided |
ohair@158 | 9 | * by Oracle in the LICENSE file that accompanied this code. |
duke@1 | 10 | * |
duke@1 | 11 | * This code is distributed in the hope that it will be useful, but WITHOUT |
duke@1 | 12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
duke@1 | 13 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
duke@1 | 14 | * version 2 for more details (a copy is included in the LICENSE file that |
duke@1 | 15 | * accompanied this code). |
duke@1 | 16 | * |
duke@1 | 17 | * You should have received a copy of the GNU General Public License version |
duke@1 | 18 | * 2 along with this work; if not, write to the Free Software Foundation, |
duke@1 | 19 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
duke@1 | 20 | * |
ohair@158 | 21 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
ohair@158 | 22 | * or visit www.oracle.com if you need additional information or have any |
ohair@158 | 23 | * questions. |
duke@1 | 24 | */ |
duke@1 | 25 | |
duke@1 | 26 | /* |
duke@1 | 27 | * Licensed Materials - Property of IBM |
duke@1 | 28 | * RMI-IIOP v1.0 |
duke@1 | 29 | * Copyright IBM Corp. 1998 1999 All Rights Reserved |
duke@1 | 30 | * |
duke@1 | 31 | */ |
duke@1 | 32 | |
duke@1 | 33 | package com.sun.corba.se.impl.protocol; |
duke@1 | 34 | |
duke@1 | 35 | import java.io.IOException; |
duke@1 | 36 | import java.util.Iterator; |
duke@1 | 37 | import java.rmi.RemoteException; |
duke@1 | 38 | |
duke@1 | 39 | import javax.rmi.CORBA.Util; |
duke@1 | 40 | import javax.rmi.CORBA.Tie; |
duke@1 | 41 | |
duke@1 | 42 | import org.omg.CORBA.COMM_FAILURE; |
duke@1 | 43 | import org.omg.CORBA.INTERNAL; |
duke@1 | 44 | import org.omg.CORBA.SystemException; |
duke@1 | 45 | import org.omg.CORBA.Request; |
duke@1 | 46 | import org.omg.CORBA.NamedValue; |
duke@1 | 47 | import org.omg.CORBA.NVList; |
duke@1 | 48 | import org.omg.CORBA.Context; |
duke@1 | 49 | import org.omg.CORBA.ContextList; |
duke@1 | 50 | import org.omg.CORBA.ExceptionList; |
duke@1 | 51 | import org.omg.CORBA.TypeCode; |
duke@1 | 52 | import org.omg.CORBA.portable.RemarshalException; |
duke@1 | 53 | import org.omg.CORBA_2_3.portable.InputStream; |
duke@1 | 54 | import org.omg.CORBA_2_3.portable.OutputStream; |
duke@1 | 55 | import org.omg.CORBA.portable.Delegate; |
duke@1 | 56 | import org.omg.CORBA.portable.ServantObject; |
duke@1 | 57 | import org.omg.CORBA.portable.ApplicationException; |
duke@1 | 58 | import org.omg.CORBA.portable.UnknownException; |
duke@1 | 59 | import org.omg.IOP.ExceptionDetailMessage; |
duke@1 | 60 | import org.omg.IOP.TAG_CODE_SETS; |
duke@1 | 61 | |
duke@1 | 62 | import com.sun.org.omg.SendingContext.CodeBase; |
duke@1 | 63 | |
duke@1 | 64 | import com.sun.corba.se.pept.broker.Broker; |
duke@1 | 65 | import com.sun.corba.se.pept.encoding.InputObject; |
duke@1 | 66 | import com.sun.corba.se.pept.encoding.OutputObject; |
duke@1 | 67 | import com.sun.corba.se.pept.protocol.ClientRequestDispatcher; |
duke@1 | 68 | import com.sun.corba.se.pept.protocol.MessageMediator; |
duke@1 | 69 | import com.sun.corba.se.pept.transport.Connection; |
duke@1 | 70 | import com.sun.corba.se.pept.transport.OutboundConnectionCache; |
duke@1 | 71 | import com.sun.corba.se.pept.transport.ContactInfo; |
duke@1 | 72 | |
duke@1 | 73 | import com.sun.corba.se.spi.ior.IOR; |
duke@1 | 74 | import com.sun.corba.se.spi.ior.iiop.GIOPVersion; |
duke@1 | 75 | import com.sun.corba.se.spi.ior.iiop.IIOPProfileTemplate; |
duke@1 | 76 | import com.sun.corba.se.spi.ior.iiop.CodeSetsComponent; |
duke@1 | 77 | import com.sun.corba.se.spi.oa.OAInvocationInfo; |
duke@1 | 78 | import com.sun.corba.se.spi.oa.ObjectAdapterFactory; |
duke@1 | 79 | import com.sun.corba.se.spi.orb.ORB; |
duke@1 | 80 | import com.sun.corba.se.spi.orb.ORBVersion; |
duke@1 | 81 | import com.sun.corba.se.spi.orb.ORBVersionFactory; |
duke@1 | 82 | import com.sun.corba.se.spi.protocol.CorbaMessageMediator; |
duke@1 | 83 | import com.sun.corba.se.spi.protocol.RequestDispatcherRegistry; |
duke@1 | 84 | import com.sun.corba.se.spi.transport.CorbaContactInfo ; |
duke@1 | 85 | import com.sun.corba.se.spi.transport.CorbaContactInfoList ; |
duke@1 | 86 | import com.sun.corba.se.spi.transport.CorbaContactInfoListIterator ; |
duke@1 | 87 | import com.sun.corba.se.spi.transport.CorbaConnection; |
duke@1 | 88 | import com.sun.corba.se.spi.logging.CORBALogDomains; |
duke@1 | 89 | |
duke@1 | 90 | import com.sun.corba.se.spi.servicecontext.MaxStreamFormatVersionServiceContext; |
duke@1 | 91 | import com.sun.corba.se.spi.servicecontext.ServiceContext; |
duke@1 | 92 | import com.sun.corba.se.spi.servicecontext.ServiceContexts; |
duke@1 | 93 | import com.sun.corba.se.spi.servicecontext.UEInfoServiceContext; |
duke@1 | 94 | import com.sun.corba.se.spi.servicecontext.CodeSetServiceContext; |
duke@1 | 95 | import com.sun.corba.se.spi.servicecontext.SendingContextServiceContext; |
duke@1 | 96 | import com.sun.corba.se.spi.servicecontext.ORBVersionServiceContext; |
duke@1 | 97 | import com.sun.corba.se.spi.servicecontext.MaxStreamFormatVersionServiceContext; |
duke@1 | 98 | import com.sun.corba.se.spi.servicecontext.UnknownServiceContext; |
duke@1 | 99 | |
duke@1 | 100 | import com.sun.corba.se.impl.encoding.CDRInputObject; |
duke@1 | 101 | import com.sun.corba.se.impl.encoding.CodeSetComponentInfo; |
duke@1 | 102 | import com.sun.corba.se.impl.encoding.CodeSetConversion; |
duke@1 | 103 | import com.sun.corba.se.impl.encoding.EncapsInputStream; |
duke@1 | 104 | import com.sun.corba.se.impl.encoding.MarshalOutputStream; |
duke@1 | 105 | import com.sun.corba.se.impl.encoding.MarshalInputStream; |
duke@1 | 106 | import com.sun.corba.se.impl.logging.ORBUtilSystemException; |
duke@1 | 107 | import com.sun.corba.se.impl.orbutil.ORBUtility; |
duke@1 | 108 | import com.sun.corba.se.impl.orbutil.ORBConstants; |
duke@1 | 109 | import com.sun.corba.se.impl.protocol.giopmsgheaders.ReplyMessage; |
duke@1 | 110 | import com.sun.corba.se.impl.protocol.giopmsgheaders.KeyAddr; |
duke@1 | 111 | import com.sun.corba.se.impl.protocol.giopmsgheaders.ProfileAddr; |
duke@1 | 112 | import com.sun.corba.se.impl.protocol.giopmsgheaders.ReferenceAddr; |
duke@1 | 113 | import com.sun.corba.se.impl.transport.CorbaContactInfoListIteratorImpl; |
duke@1 | 114 | import com.sun.corba.se.impl.util.JDKBridge; |
duke@1 | 115 | |
duke@1 | 116 | /** |
duke@1 | 117 | * ClientDelegate is the RMI client-side subcontract or representation |
duke@1 | 118 | * It implements RMI delegate as well as our internal ClientRequestDispatcher |
duke@1 | 119 | * interface. |
duke@1 | 120 | */ |
duke@1 | 121 | public class CorbaClientRequestDispatcherImpl |
duke@1 | 122 | implements |
duke@1 | 123 | ClientRequestDispatcher |
duke@1 | 124 | { |
duke@1 | 125 | public OutputObject beginRequest(Object self, String opName, |
duke@1 | 126 | boolean isOneWay, ContactInfo contactInfo) |
duke@1 | 127 | { |
duke@1 | 128 | ORB orb = null; |
duke@1 | 129 | try { |
duke@1 | 130 | CorbaContactInfo corbaContactInfo = (CorbaContactInfo) contactInfo; |
duke@1 | 131 | orb = (ORB)contactInfo.getBroker(); |
duke@1 | 132 | |
duke@1 | 133 | if (orb.subcontractDebugFlag) { |
duke@1 | 134 | dprint(".beginRequest->: op/" + opName); |
duke@1 | 135 | } |
duke@1 | 136 | |
duke@1 | 137 | // |
duke@1 | 138 | // Portable Interceptor initialization. |
duke@1 | 139 | // |
duke@1 | 140 | |
duke@1 | 141 | orb.getPIHandler().initiateClientPIRequest( false ); |
duke@1 | 142 | |
duke@1 | 143 | // |
duke@1 | 144 | // Connection. |
duke@1 | 145 | // |
duke@1 | 146 | |
duke@1 | 147 | CorbaConnection connection = null; |
duke@1 | 148 | |
duke@1 | 149 | // This locking is done so that multiple connections are not created |
duke@1 | 150 | // for the same endpoint |
skoppar@229 | 151 | //6929137 - Synchronized on contactInfo to avoid blocking across multiple endpoints |
skoppar@229 | 152 | synchronized (contactInfo) { |
duke@1 | 153 | if (contactInfo.isConnectionBased()) { |
duke@1 | 154 | if (contactInfo.shouldCacheConnection()) { |
duke@1 | 155 | connection = (CorbaConnection) |
duke@1 | 156 | orb.getTransportManager() |
duke@1 | 157 | .getOutboundConnectionCache(contactInfo).get(contactInfo); |
duke@1 | 158 | } |
duke@1 | 159 | if (connection != null) { |
duke@1 | 160 | if (orb.subcontractDebugFlag) { |
duke@1 | 161 | dprint(".beginRequest: op/" + opName |
duke@1 | 162 | + ": Using cached connection: " + connection); |
duke@1 | 163 | } |
duke@1 | 164 | } else { |
duke@1 | 165 | try { |
duke@1 | 166 | connection = (CorbaConnection) |
duke@1 | 167 | contactInfo.createConnection(); |
duke@1 | 168 | if (orb.subcontractDebugFlag) { |
duke@1 | 169 | dprint(".beginRequest: op/" + opName |
duke@1 | 170 | + ": Using created connection: " + connection); |
duke@1 | 171 | } |
duke@1 | 172 | } catch (RuntimeException e) { |
duke@1 | 173 | if (orb.subcontractDebugFlag) { |
duke@1 | 174 | dprint(".beginRequest: op/" + opName |
duke@1 | 175 | + ": failed to create connection: " + e); |
duke@1 | 176 | } |
duke@1 | 177 | // REVISIT: this part similar to marshalingComplete below. |
duke@1 | 178 | boolean retry = getContactInfoListIterator(orb) |
duke@1 | 179 | .reportException(contactInfo, e); |
duke@1 | 180 | // REVISIT: |
duke@1 | 181 | // this part similar to Remarshal in this method below |
duke@1 | 182 | if (retry) { |
duke@1 | 183 | if(getContactInfoListIterator(orb).hasNext()) { |
duke@1 | 184 | contactInfo = (ContactInfo) |
duke@1 | 185 | getContactInfoListIterator(orb).next(); |
robm@215 | 186 | unregisterWaiter(orb); |
duke@1 | 187 | return beginRequest(self, opName, |
duke@1 | 188 | isOneWay, contactInfo); |
duke@1 | 189 | } else { |
duke@1 | 190 | throw e; |
duke@1 | 191 | } |
duke@1 | 192 | } else { |
duke@1 | 193 | throw e; |
duke@1 | 194 | } |
duke@1 | 195 | } |
duke@1 | 196 | if (connection.shouldRegisterReadEvent()) { |
duke@1 | 197 | // REVISIT: cast |
duke@1 | 198 | orb.getTransportManager().getSelector(0) |
duke@1 | 199 | .registerForEvent(connection.getEventHandler()); |
duke@1 | 200 | connection.setState("ESTABLISHED"); |
duke@1 | 201 | } |
duke@1 | 202 | // Do not do connection reclaim here since the connections |
duke@1 | 203 | // are marked in use by registerWaiter() call and since this |
duke@1 | 204 | // call happens later do it after that. |
duke@1 | 205 | if (contactInfo.shouldCacheConnection()) { |
duke@1 | 206 | OutboundConnectionCache connectionCache = |
duke@1 | 207 | orb.getTransportManager() |
duke@1 | 208 | .getOutboundConnectionCache(contactInfo); |
duke@1 | 209 | connectionCache.stampTime(connection); |
duke@1 | 210 | connectionCache.put(contactInfo, connection); |
duke@1 | 211 | // connectionCache.reclaim(); |
duke@1 | 212 | } |
duke@1 | 213 | } |
duke@1 | 214 | } |
duke@1 | 215 | } |
duke@1 | 216 | |
duke@1 | 217 | CorbaMessageMediator messageMediator = (CorbaMessageMediator) |
duke@1 | 218 | contactInfo.createMessageMediator( |
duke@1 | 219 | orb, contactInfo, connection, opName, isOneWay); |
duke@1 | 220 | if (orb.subcontractDebugFlag) { |
duke@1 | 221 | dprint(".beginRequest: " + opAndId(messageMediator) |
duke@1 | 222 | + ": created message mediator: " + messageMediator); |
duke@1 | 223 | } |
duke@1 | 224 | |
duke@1 | 225 | // NOTE: Thread data so we can get the mediator in release reply |
duke@1 | 226 | // in order to remove the waiter in CorbaConnection. |
duke@1 | 227 | // We cannot depend on obtaining information in releaseReply |
duke@1 | 228 | // via its InputStream argument since, on certain errors |
duke@1 | 229 | // (e.g., client marshaling errors), the stream may be null. |
duke@1 | 230 | // Likewise for releaseReply "self". |
duke@1 | 231 | // NOTE: This must be done before initializing the message since |
duke@1 | 232 | // that may start sending fragments which may end up in "early" |
duke@1 | 233 | // replies or client marshaling exceptions. |
duke@1 | 234 | |
duke@1 | 235 | orb.getInvocationInfo().setMessageMediator(messageMediator); |
duke@1 | 236 | |
duke@1 | 237 | if (connection != null && connection.getCodeSetContext() == null) { |
duke@1 | 238 | performCodeSetNegotiation(messageMediator); |
duke@1 | 239 | } |
duke@1 | 240 | |
duke@1 | 241 | addServiceContexts(messageMediator); |
duke@1 | 242 | |
duke@1 | 243 | OutputObject outputObject = |
duke@1 | 244 | contactInfo.createOutputObject(messageMediator); |
duke@1 | 245 | if (orb.subcontractDebugFlag) { |
duke@1 | 246 | dprint(".beginRequest: " + opAndId(messageMediator) |
duke@1 | 247 | + ": created output object: " + outputObject); |
duke@1 | 248 | } |
duke@1 | 249 | |
duke@1 | 250 | |
duke@1 | 251 | // NOTE: Not necessary for oneways, but useful for debugging. |
duke@1 | 252 | // This must be done BEFORE message initialization since fragments |
duke@1 | 253 | // may be sent at that time. |
duke@1 | 254 | registerWaiter(messageMediator); |
duke@1 | 255 | |
duke@1 | 256 | // Do connection reclaim now |
skoppar@229 | 257 | synchronized (contactInfo) { |
duke@1 | 258 | if (contactInfo.isConnectionBased()) { |
duke@1 | 259 | if (contactInfo.shouldCacheConnection()) { |
duke@1 | 260 | OutboundConnectionCache connectionCache = |
duke@1 | 261 | orb.getTransportManager() |
duke@1 | 262 | .getOutboundConnectionCache(contactInfo); |
duke@1 | 263 | connectionCache.reclaim(); |
duke@1 | 264 | } |
duke@1 | 265 | } |
duke@1 | 266 | } |
duke@1 | 267 | |
duke@1 | 268 | orb.getPIHandler().setClientPIInfo(messageMediator); |
duke@1 | 269 | try { |
duke@1 | 270 | // This MUST come before message is initialized so |
duke@1 | 271 | // service contexts may be added by PI because |
duke@1 | 272 | // initial fragments may be sent during message initialization. |
duke@1 | 273 | orb.getPIHandler().invokeClientPIStartingPoint(); |
duke@1 | 274 | } catch( RemarshalException e ) { |
duke@1 | 275 | if (orb.subcontractDebugFlag) { |
duke@1 | 276 | dprint(".beginRequest: " + opAndId(messageMediator) |
duke@1 | 277 | + ": Remarshal"); |
duke@1 | 278 | } |
duke@1 | 279 | |
duke@1 | 280 | // NOTE: We get here because an interceptor raised ForwardRequest |
duke@1 | 281 | // and updated the IOR/Iterator. Since we have a fresh iterator |
duke@1 | 282 | // hasNext should succeed. |
duke@1 | 283 | |
duke@1 | 284 | // REVISIT: We should feed ALL interceptor exceptions to |
duke@1 | 285 | // iterator.reportException so it can determine if it wants |
duke@1 | 286 | // to retry. Right now, SystemExceptions will flow to the |
duke@1 | 287 | // client code. |
duke@1 | 288 | |
duke@1 | 289 | // REVISIT: |
duke@1 | 290 | // This assumes that interceptors update |
duke@1 | 291 | // ContactInfoList outside of subcontract. |
duke@1 | 292 | // Want to move that update to here. |
duke@1 | 293 | if (getContactInfoListIterator(orb).hasNext()) { |
robm@215 | 294 | contactInfo = (ContactInfo)getContactInfoListIterator(orb).next(); |
robm@215 | 295 | if (orb.subcontractDebugFlag) { |
robm@215 | 296 | dprint( "RemarshalException: hasNext true\ncontact info " + contactInfo ); |
robm@215 | 297 | } |
robm@215 | 298 | |
robm@215 | 299 | // Fix for 6763340: Complete the first attempt before starting another. |
robm@215 | 300 | orb.getPIHandler().makeCompletedClientRequest( |
robm@215 | 301 | ReplyMessage.LOCATION_FORWARD, null ) ; |
robm@215 | 302 | unregisterWaiter(orb); |
robm@215 | 303 | orb.getPIHandler().cleanupClientPIRequest() ; |
robm@215 | 304 | |
duke@1 | 305 | return beginRequest(self, opName, isOneWay, contactInfo); |
duke@1 | 306 | } else { |
robm@215 | 307 | if (orb.subcontractDebugFlag) { |
robm@215 | 308 | dprint( "RemarshalException: hasNext false" ); |
robm@215 | 309 | } |
duke@1 | 310 | ORBUtilSystemException wrapper = |
duke@1 | 311 | ORBUtilSystemException.get(orb, |
duke@1 | 312 | CORBALogDomains.RPC_PROTOCOL); |
duke@1 | 313 | throw wrapper.remarshalWithNowhereToGo(); |
duke@1 | 314 | } |
duke@1 | 315 | } |
duke@1 | 316 | |
duke@1 | 317 | messageMediator.initializeMessage(); |
duke@1 | 318 | if (orb.subcontractDebugFlag) { |
duke@1 | 319 | dprint(".beginRequest: " + opAndId(messageMediator) |
duke@1 | 320 | + ": initialized message"); |
duke@1 | 321 | } |
duke@1 | 322 | |
duke@1 | 323 | return outputObject; |
duke@1 | 324 | |
duke@1 | 325 | } finally { |
duke@1 | 326 | if (orb.subcontractDebugFlag) { |
duke@1 | 327 | dprint(".beginRequest<-: op/" + opName); |
duke@1 | 328 | } |
duke@1 | 329 | } |
duke@1 | 330 | } |
duke@1 | 331 | |
duke@1 | 332 | public InputObject marshalingComplete(java.lang.Object self, |
duke@1 | 333 | OutputObject outputObject) |
duke@1 | 334 | throws |
duke@1 | 335 | ApplicationException, |
duke@1 | 336 | org.omg.CORBA.portable.RemarshalException |
duke@1 | 337 | { |
duke@1 | 338 | ORB orb = null; |
duke@1 | 339 | CorbaMessageMediator messageMediator = null; |
duke@1 | 340 | try { |
duke@1 | 341 | messageMediator = (CorbaMessageMediator) |
duke@1 | 342 | outputObject.getMessageMediator(); |
duke@1 | 343 | |
duke@1 | 344 | orb = (ORB) messageMediator.getBroker(); |
duke@1 | 345 | |
duke@1 | 346 | if (orb.subcontractDebugFlag) { |
duke@1 | 347 | dprint(".marshalingComplete->: " + opAndId(messageMediator)); |
duke@1 | 348 | } |
duke@1 | 349 | |
duke@1 | 350 | InputObject inputObject = |
duke@1 | 351 | marshalingComplete1(orb, messageMediator); |
duke@1 | 352 | |
duke@1 | 353 | return processResponse(orb, messageMediator, inputObject); |
duke@1 | 354 | |
duke@1 | 355 | } finally { |
duke@1 | 356 | if (orb.subcontractDebugFlag) { |
duke@1 | 357 | dprint(".marshalingComplete<-: " + opAndId(messageMediator)); |
duke@1 | 358 | } |
duke@1 | 359 | } |
duke@1 | 360 | } |
duke@1 | 361 | |
duke@1 | 362 | public InputObject marshalingComplete1( |
duke@1 | 363 | ORB orb, CorbaMessageMediator messageMediator) |
duke@1 | 364 | throws |
duke@1 | 365 | ApplicationException, |
duke@1 | 366 | org.omg.CORBA.portable.RemarshalException |
duke@1 | 367 | { |
duke@1 | 368 | try { |
duke@1 | 369 | messageMediator.finishSendingRequest(); |
duke@1 | 370 | |
duke@1 | 371 | if (orb.subcontractDebugFlag) { |
duke@1 | 372 | dprint(".marshalingComplete: " + opAndId(messageMediator) |
duke@1 | 373 | + ": finished sending request"); |
duke@1 | 374 | } |
duke@1 | 375 | |
duke@1 | 376 | return messageMediator.waitForResponse(); |
duke@1 | 377 | |
duke@1 | 378 | } catch (RuntimeException e) { |
duke@1 | 379 | |
duke@1 | 380 | if (orb.subcontractDebugFlag) { |
duke@1 | 381 | dprint(".marshalingComplete: " + opAndId(messageMediator) |
duke@1 | 382 | + ": exception: " + e.toString()); |
duke@1 | 383 | } |
duke@1 | 384 | |
duke@1 | 385 | boolean retry = |
duke@1 | 386 | getContactInfoListIterator(orb) |
duke@1 | 387 | .reportException(messageMediator.getContactInfo(), e); |
vikram@231 | 388 | |
vikram@231 | 389 | //Bug 6382377: must not lose exception in PI |
vikram@231 | 390 | |
vikram@231 | 391 | // Must run interceptor end point before retrying. |
vikram@231 | 392 | Exception newException = |
vikram@231 | 393 | orb.getPIHandler().invokeClientPIEndingPoint( |
vikram@231 | 394 | ReplyMessage.SYSTEM_EXCEPTION, e); |
vikram@231 | 395 | |
duke@1 | 396 | if (retry) { |
duke@1 | 397 | if (newException == e) { |
duke@1 | 398 | continueOrThrowSystemOrRemarshal(messageMediator, |
duke@1 | 399 | new RemarshalException()); |
duke@1 | 400 | } else { |
duke@1 | 401 | continueOrThrowSystemOrRemarshal(messageMediator, |
duke@1 | 402 | newException); |
duke@1 | 403 | } |
duke@1 | 404 | } else { |
vikram@231 | 405 | if (newException instanceof RuntimeException){ |
vikram@231 | 406 | throw (RuntimeException)newException; |
vikram@231 | 407 | } |
vikram@231 | 408 | else if (newException instanceof RemarshalException) |
vikram@231 | 409 | { |
vikram@231 | 410 | throw (RemarshalException)newException; |
vikram@231 | 411 | } |
vikram@231 | 412 | |
duke@1 | 413 | // NOTE: Interceptor ending point will run in releaseReply. |
duke@1 | 414 | throw e; |
duke@1 | 415 | } |
duke@1 | 416 | return null; // for compiler |
duke@1 | 417 | } |
duke@1 | 418 | } |
duke@1 | 419 | |
duke@1 | 420 | protected InputObject processResponse(ORB orb, |
duke@1 | 421 | CorbaMessageMediator messageMediator, |
duke@1 | 422 | InputObject inputObject) |
duke@1 | 423 | throws |
duke@1 | 424 | ApplicationException, |
duke@1 | 425 | org.omg.CORBA.portable.RemarshalException |
duke@1 | 426 | { |
duke@1 | 427 | ORBUtilSystemException wrapper = |
duke@1 | 428 | ORBUtilSystemException.get( orb, |
duke@1 | 429 | CORBALogDomains.RPC_PROTOCOL ) ; |
duke@1 | 430 | |
duke@1 | 431 | if (orb.subcontractDebugFlag) { |
duke@1 | 432 | dprint(".processResponse: " + opAndId(messageMediator) |
duke@1 | 433 | + ": response received"); |
duke@1 | 434 | } |
duke@1 | 435 | |
duke@1 | 436 | // We know for sure now that we've sent a message. |
duke@1 | 437 | // So OK to not send initial again. |
duke@1 | 438 | if (messageMediator.getConnection() != null) { |
duke@1 | 439 | ((CorbaConnection)messageMediator.getConnection()) |
duke@1 | 440 | .setPostInitialContexts(); |
duke@1 | 441 | } |
duke@1 | 442 | |
duke@1 | 443 | // NOTE: not necessary to set MessageMediator for PI. |
duke@1 | 444 | // It already has it. |
duke@1 | 445 | |
duke@1 | 446 | // Process the response. |
duke@1 | 447 | |
duke@1 | 448 | Exception exception = null; |
duke@1 | 449 | |
duke@1 | 450 | if (messageMediator.isOneWay()) { |
duke@1 | 451 | getContactInfoListIterator(orb) |
duke@1 | 452 | .reportSuccess(messageMediator.getContactInfo()); |
duke@1 | 453 | // Invoke Portable Interceptors with receive_other |
duke@1 | 454 | exception = orb.getPIHandler().invokeClientPIEndingPoint( |
duke@1 | 455 | ReplyMessage.NO_EXCEPTION, exception ); |
duke@1 | 456 | continueOrThrowSystemOrRemarshal(messageMediator, exception); |
duke@1 | 457 | return null; |
duke@1 | 458 | } |
duke@1 | 459 | |
duke@1 | 460 | consumeServiceContexts(orb, messageMediator); |
duke@1 | 461 | |
duke@1 | 462 | // Now that we have the service contexts processed and the |
duke@1 | 463 | // correct ORBVersion set, we must finish initializing the stream. |
duke@1 | 464 | // REVISIT - need interface for this operation. |
duke@1 | 465 | ((CDRInputObject)inputObject).performORBVersionSpecificInit(); |
duke@1 | 466 | |
duke@1 | 467 | if (messageMediator.isSystemExceptionReply()) { |
duke@1 | 468 | |
duke@1 | 469 | SystemException se = messageMediator.getSystemExceptionReply(); |
duke@1 | 470 | |
duke@1 | 471 | if (orb.subcontractDebugFlag) { |
duke@1 | 472 | dprint(".processResponse: " + opAndId(messageMediator) |
duke@1 | 473 | + ": received system exception: " + se); |
duke@1 | 474 | } |
duke@1 | 475 | |
duke@1 | 476 | boolean doRemarshal = |
duke@1 | 477 | getContactInfoListIterator(orb) |
duke@1 | 478 | .reportException(messageMediator.getContactInfo(), se); |
duke@1 | 479 | |
duke@1 | 480 | if (doRemarshal) { |
duke@1 | 481 | |
duke@1 | 482 | // Invoke Portable Interceptors with receive_exception: |
duke@1 | 483 | exception = orb.getPIHandler().invokeClientPIEndingPoint( |
duke@1 | 484 | ReplyMessage.SYSTEM_EXCEPTION, se ); |
duke@1 | 485 | |
duke@1 | 486 | // If PI did not change the exception, throw a |
duke@1 | 487 | // Remarshal. |
duke@1 | 488 | if( se == exception ) { |
duke@1 | 489 | // exception = null is to maintain symmetry with |
duke@1 | 490 | // GenericPOAClientSC. |
duke@1 | 491 | exception = null; |
duke@1 | 492 | continueOrThrowSystemOrRemarshal(messageMediator, |
duke@1 | 493 | new RemarshalException()); |
duke@1 | 494 | throw wrapper.statementNotReachable1() ; |
duke@1 | 495 | } else { |
duke@1 | 496 | // Otherwise, throw the exception PI wants thrown. |
duke@1 | 497 | continueOrThrowSystemOrRemarshal(messageMediator, |
duke@1 | 498 | exception); |
duke@1 | 499 | throw wrapper.statementNotReachable2() ; |
duke@1 | 500 | } |
duke@1 | 501 | } |
duke@1 | 502 | |
duke@1 | 503 | // No retry, so see if was unknown. |
duke@1 | 504 | |
duke@1 | 505 | ServiceContexts contexts = |
duke@1 | 506 | messageMediator.getReplyServiceContexts(); |
duke@1 | 507 | if (contexts != null) { |
duke@1 | 508 | UEInfoServiceContext usc = |
duke@1 | 509 | (UEInfoServiceContext) |
duke@1 | 510 | contexts.get(UEInfoServiceContext.SERVICE_CONTEXT_ID); |
duke@1 | 511 | |
duke@1 | 512 | if (usc != null) { |
duke@1 | 513 | Throwable unknown = usc.getUE() ; |
duke@1 | 514 | UnknownException ue = new UnknownException(unknown); |
duke@1 | 515 | |
duke@1 | 516 | // Invoke Portable Interceptors with receive_exception: |
duke@1 | 517 | exception = orb.getPIHandler().invokeClientPIEndingPoint( |
duke@1 | 518 | ReplyMessage.SYSTEM_EXCEPTION, ue ); |
duke@1 | 519 | |
duke@1 | 520 | continueOrThrowSystemOrRemarshal(messageMediator, exception); |
duke@1 | 521 | throw wrapper.statementNotReachable3() ; |
duke@1 | 522 | } |
duke@1 | 523 | } |
duke@1 | 524 | |
duke@1 | 525 | // It was not a comm failure nor unknown. |
duke@1 | 526 | // This is the general case. |
duke@1 | 527 | |
duke@1 | 528 | // Invoke Portable Interceptors with receive_exception: |
duke@1 | 529 | exception = orb.getPIHandler().invokeClientPIEndingPoint( |
duke@1 | 530 | ReplyMessage.SYSTEM_EXCEPTION, se ); |
duke@1 | 531 | |
duke@1 | 532 | continueOrThrowSystemOrRemarshal(messageMediator, exception); |
duke@1 | 533 | |
duke@1 | 534 | // Note: We should never need to execute this line, but |
duke@1 | 535 | // we should assert in case exception is null somehow. |
duke@1 | 536 | throw wrapper.statementNotReachable4() ; |
duke@1 | 537 | } else if (messageMediator.isUserExceptionReply()) { |
duke@1 | 538 | |
duke@1 | 539 | if (orb.subcontractDebugFlag) { |
duke@1 | 540 | dprint(".processResponse: " + opAndId(messageMediator) |
duke@1 | 541 | + ": received user exception"); |
duke@1 | 542 | } |
duke@1 | 543 | |
duke@1 | 544 | getContactInfoListIterator(orb) |
duke@1 | 545 | .reportSuccess(messageMediator.getContactInfo()); |
duke@1 | 546 | |
duke@1 | 547 | String exceptionRepoId = peekUserExceptionId(inputObject); |
duke@1 | 548 | Exception newException = null; |
duke@1 | 549 | |
duke@1 | 550 | if (messageMediator.isDIIRequest()) { |
duke@1 | 551 | exception = messageMediator.unmarshalDIIUserException( |
duke@1 | 552 | exceptionRepoId, (InputStream)inputObject); |
duke@1 | 553 | newException = orb.getPIHandler().invokeClientPIEndingPoint( |
duke@1 | 554 | ReplyMessage.USER_EXCEPTION, exception ); |
duke@1 | 555 | messageMediator.setDIIException(newException); |
duke@1 | 556 | |
duke@1 | 557 | } else { |
duke@1 | 558 | ApplicationException appException = |
duke@1 | 559 | new ApplicationException( |
duke@1 | 560 | exceptionRepoId, |
duke@1 | 561 | (org.omg.CORBA.portable.InputStream)inputObject); |
duke@1 | 562 | exception = appException; |
duke@1 | 563 | newException = orb.getPIHandler().invokeClientPIEndingPoint( |
duke@1 | 564 | ReplyMessage.USER_EXCEPTION, appException ); |
duke@1 | 565 | } |
duke@1 | 566 | |
duke@1 | 567 | if (newException != exception) { |
duke@1 | 568 | continueOrThrowSystemOrRemarshal(messageMediator,newException); |
duke@1 | 569 | } |
duke@1 | 570 | |
duke@1 | 571 | if (newException instanceof ApplicationException) { |
duke@1 | 572 | throw (ApplicationException)newException; |
duke@1 | 573 | } |
duke@1 | 574 | // For DII: |
duke@1 | 575 | // This return will be ignored - already unmarshaled above. |
duke@1 | 576 | return inputObject; |
duke@1 | 577 | |
duke@1 | 578 | } else if (messageMediator.isLocationForwardReply()) { |
duke@1 | 579 | |
duke@1 | 580 | if (orb.subcontractDebugFlag) { |
duke@1 | 581 | dprint(".processResponse: " + opAndId(messageMediator) |
duke@1 | 582 | + ": received location forward"); |
duke@1 | 583 | } |
duke@1 | 584 | |
duke@1 | 585 | // NOTE: Expects iterator to update target IOR |
duke@1 | 586 | getContactInfoListIterator(orb).reportRedirect( |
duke@1 | 587 | (CorbaContactInfo)messageMediator.getContactInfo(), |
duke@1 | 588 | messageMediator.getForwardedIOR()); |
duke@1 | 589 | |
duke@1 | 590 | // Invoke Portable Interceptors with receive_other: |
duke@1 | 591 | Exception newException = orb.getPIHandler().invokeClientPIEndingPoint( |
duke@1 | 592 | ReplyMessage.LOCATION_FORWARD, null ); |
duke@1 | 593 | |
duke@1 | 594 | if( !(newException instanceof RemarshalException) ) { |
duke@1 | 595 | exception = newException; |
duke@1 | 596 | } |
duke@1 | 597 | |
duke@1 | 598 | // If PI did not change exception, throw Remarshal, else |
duke@1 | 599 | // throw the exception PI wants thrown. |
duke@1 | 600 | // KMC: GenericPOAClientSC did not check exception != null |
duke@1 | 601 | if( exception != null ) { |
duke@1 | 602 | continueOrThrowSystemOrRemarshal(messageMediator, exception); |
duke@1 | 603 | } |
duke@1 | 604 | continueOrThrowSystemOrRemarshal(messageMediator, |
duke@1 | 605 | new RemarshalException()); |
duke@1 | 606 | throw wrapper.statementNotReachable5() ; |
duke@1 | 607 | |
duke@1 | 608 | } else if (messageMediator.isDifferentAddrDispositionRequestedReply()){ |
duke@1 | 609 | |
duke@1 | 610 | if (orb.subcontractDebugFlag) { |
duke@1 | 611 | dprint(".processResponse: " + opAndId(messageMediator) |
duke@1 | 612 | + ": received different addressing dispostion request"); |
duke@1 | 613 | } |
duke@1 | 614 | |
duke@1 | 615 | // Set the desired target addressing disposition. |
duke@1 | 616 | getContactInfoListIterator(orb).reportAddrDispositionRetry( |
duke@1 | 617 | (CorbaContactInfo)messageMediator.getContactInfo(), |
duke@1 | 618 | messageMediator.getAddrDispositionReply()); |
duke@1 | 619 | |
duke@1 | 620 | // Invoke Portable Interceptors with receive_other: |
duke@1 | 621 | Exception newException = orb.getPIHandler().invokeClientPIEndingPoint( |
duke@1 | 622 | ReplyMessage.NEEDS_ADDRESSING_MODE, null); |
duke@1 | 623 | |
duke@1 | 624 | // For consistency with corresponding code in GenericPOAClientSC: |
duke@1 | 625 | if( !(newException instanceof RemarshalException) ) { |
duke@1 | 626 | exception = newException; |
duke@1 | 627 | } |
duke@1 | 628 | |
duke@1 | 629 | // If PI did not change exception, throw Remarshal, else |
duke@1 | 630 | // throw the exception PI wants thrown. |
duke@1 | 631 | // KMC: GenericPOAClientSC did not include exception != null check |
duke@1 | 632 | if( exception != null ) { |
duke@1 | 633 | continueOrThrowSystemOrRemarshal(messageMediator, exception); |
duke@1 | 634 | } |
duke@1 | 635 | continueOrThrowSystemOrRemarshal(messageMediator, |
duke@1 | 636 | new RemarshalException()); |
duke@1 | 637 | throw wrapper.statementNotReachable6() ; |
duke@1 | 638 | } else /* normal response */ { |
duke@1 | 639 | |
duke@1 | 640 | if (orb.subcontractDebugFlag) { |
duke@1 | 641 | dprint(".processResponse: " + opAndId(messageMediator) |
duke@1 | 642 | + ": received normal response"); |
duke@1 | 643 | } |
duke@1 | 644 | |
duke@1 | 645 | getContactInfoListIterator(orb) |
duke@1 | 646 | .reportSuccess(messageMediator.getContactInfo()); |
duke@1 | 647 | |
duke@1 | 648 | messageMediator.handleDIIReply((InputStream)inputObject); |
duke@1 | 649 | |
duke@1 | 650 | // Invoke Portable Interceptors with receive_reply: |
duke@1 | 651 | exception = orb.getPIHandler().invokeClientPIEndingPoint( |
duke@1 | 652 | ReplyMessage.NO_EXCEPTION, null ); |
duke@1 | 653 | |
duke@1 | 654 | // Remember: not thrown if exception is null. |
duke@1 | 655 | continueOrThrowSystemOrRemarshal(messageMediator, exception); |
duke@1 | 656 | |
duke@1 | 657 | return inputObject; |
duke@1 | 658 | } |
duke@1 | 659 | } |
duke@1 | 660 | |
duke@1 | 661 | // Filters the given exception into a SystemException or a |
duke@1 | 662 | // RemarshalException and throws it. Assumes the given exception is |
duke@1 | 663 | // of one of these two types. This is a utility method for |
duke@1 | 664 | // the above invoke code which must do this numerous times. |
duke@1 | 665 | // If the exception is null, no exception is thrown. |
duke@1 | 666 | // |
duke@1 | 667 | // Note that this code is duplicated in GenericPOAClientSC.java |
duke@1 | 668 | protected void continueOrThrowSystemOrRemarshal( |
duke@1 | 669 | CorbaMessageMediator messageMediator, Exception exception) |
duke@1 | 670 | throws |
duke@1 | 671 | SystemException, RemarshalException |
duke@1 | 672 | { |
duke@1 | 673 | |
duke@1 | 674 | ORB orb = (ORB) messageMediator.getBroker(); |
duke@1 | 675 | |
duke@1 | 676 | if( exception == null ) { |
duke@1 | 677 | |
duke@1 | 678 | // do nothing. |
duke@1 | 679 | |
duke@1 | 680 | } else if( exception instanceof RemarshalException ) { |
duke@1 | 681 | |
duke@1 | 682 | // REVISIT - unify with PI handling |
duke@1 | 683 | orb.getInvocationInfo().setIsRetryInvocation(true); |
duke@1 | 684 | |
duke@1 | 685 | // NOTE - We must unregister the waiter NOW for this request |
duke@1 | 686 | // since the retry will result in a new request id. Therefore |
duke@1 | 687 | // the old request id would be lost and we would have a memory |
duke@1 | 688 | // leak in the responseWaitingRoom. |
duke@1 | 689 | unregisterWaiter(orb); |
duke@1 | 690 | |
duke@1 | 691 | if (orb.subcontractDebugFlag) { |
duke@1 | 692 | dprint(".continueOrThrowSystemOrRemarshal: " |
duke@1 | 693 | + opAndId(messageMediator) |
duke@1 | 694 | + ": throwing Remarshal"); |
duke@1 | 695 | } |
duke@1 | 696 | |
duke@1 | 697 | throw (RemarshalException)exception; |
duke@1 | 698 | |
duke@1 | 699 | } else { |
duke@1 | 700 | |
duke@1 | 701 | if (orb.subcontractDebugFlag) { |
duke@1 | 702 | dprint(".continueOrThrowSystemOrRemarshal: " |
duke@1 | 703 | + opAndId(messageMediator) |
duke@1 | 704 | + ": throwing sex:" |
duke@1 | 705 | + exception); |
duke@1 | 706 | } |
duke@1 | 707 | |
duke@1 | 708 | throw (SystemException)exception; |
duke@1 | 709 | } |
duke@1 | 710 | } |
duke@1 | 711 | |
duke@1 | 712 | protected CorbaContactInfoListIterator getContactInfoListIterator(ORB orb) |
duke@1 | 713 | { |
duke@1 | 714 | return (CorbaContactInfoListIterator) |
duke@1 | 715 | ((CorbaInvocationInfo)orb.getInvocationInfo()) |
duke@1 | 716 | .getContactInfoListIterator(); |
duke@1 | 717 | } |
duke@1 | 718 | |
duke@1 | 719 | protected void registerWaiter(CorbaMessageMediator messageMediator) |
duke@1 | 720 | { |
duke@1 | 721 | if (messageMediator.getConnection() != null) { |
duke@1 | 722 | messageMediator.getConnection().registerWaiter(messageMediator); |
duke@1 | 723 | } |
duke@1 | 724 | } |
duke@1 | 725 | |
duke@1 | 726 | protected void unregisterWaiter(ORB orb) |
duke@1 | 727 | { |
duke@1 | 728 | MessageMediator messageMediator = |
duke@1 | 729 | orb.getInvocationInfo().getMessageMediator(); |
duke@1 | 730 | if (messageMediator!=null && messageMediator.getConnection() != null) { |
duke@1 | 731 | // REVISIT: |
duke@1 | 732 | // The messageMediator may be null if COMM_FAILURE before |
duke@1 | 733 | // it is created. |
duke@1 | 734 | messageMediator.getConnection().unregisterWaiter(messageMediator); |
duke@1 | 735 | } |
duke@1 | 736 | } |
duke@1 | 737 | |
duke@1 | 738 | protected void addServiceContexts(CorbaMessageMediator messageMediator) |
duke@1 | 739 | { |
duke@1 | 740 | ORB orb = (ORB)messageMediator.getBroker(); |
duke@1 | 741 | CorbaConnection c = (CorbaConnection) messageMediator.getConnection(); |
duke@1 | 742 | GIOPVersion giopVersion = messageMediator.getGIOPVersion(); |
duke@1 | 743 | |
duke@1 | 744 | ServiceContexts contexts = messageMediator.getRequestServiceContexts(); |
duke@1 | 745 | |
duke@1 | 746 | addCodeSetServiceContext(c, contexts, giopVersion); |
duke@1 | 747 | |
duke@1 | 748 | // Add the RMI-IIOP max stream format version |
duke@1 | 749 | // service context to every request. Once we have GIOP 1.3, |
duke@1 | 750 | // we could skip it since we now support version 2, but |
duke@1 | 751 | // probably safer to always send it. |
duke@1 | 752 | contexts.put(MaxStreamFormatVersionServiceContext.singleton); |
duke@1 | 753 | |
duke@1 | 754 | // ORBVersion servicecontext needs to be sent |
duke@1 | 755 | ORBVersionServiceContext ovsc = new ORBVersionServiceContext( |
duke@1 | 756 | ORBVersionFactory.getORBVersion() ) ; |
duke@1 | 757 | contexts.put( ovsc ) ; |
duke@1 | 758 | |
duke@1 | 759 | // NOTE : We only want to send the runtime context the first time |
duke@1 | 760 | if ((c != null) && !c.isPostInitialContexts()) { |
duke@1 | 761 | // Do not do c.setPostInitialContexts() here. |
duke@1 | 762 | // If a client interceptor send_request does a ForwardRequest |
duke@1 | 763 | // which ends up using the same connection then the service |
duke@1 | 764 | // context would not be sent. |
duke@1 | 765 | SendingContextServiceContext scsc = |
duke@1 | 766 | new SendingContextServiceContext( orb.getFVDCodeBaseIOR() ) ; //d11638 |
duke@1 | 767 | contexts.put( scsc ) ; |
duke@1 | 768 | } |
duke@1 | 769 | } |
duke@1 | 770 | |
duke@1 | 771 | protected void consumeServiceContexts(ORB orb, |
duke@1 | 772 | CorbaMessageMediator messageMediator) |
duke@1 | 773 | { |
duke@1 | 774 | ServiceContexts ctxts = messageMediator.getReplyServiceContexts(); |
duke@1 | 775 | ServiceContext sc ; |
duke@1 | 776 | ORBUtilSystemException wrapper = ORBUtilSystemException.get( orb, |
duke@1 | 777 | CORBALogDomains.RPC_PROTOCOL ) ; |
duke@1 | 778 | |
duke@1 | 779 | if (ctxts == null) { |
duke@1 | 780 | return; // no service context available, return gracefully. |
duke@1 | 781 | } |
duke@1 | 782 | |
duke@1 | 783 | sc = ctxts.get( SendingContextServiceContext.SERVICE_CONTEXT_ID ) ; |
duke@1 | 784 | |
duke@1 | 785 | if (sc != null) { |
duke@1 | 786 | SendingContextServiceContext scsc = |
duke@1 | 787 | (SendingContextServiceContext)sc ; |
duke@1 | 788 | IOR ior = scsc.getIOR() ; |
duke@1 | 789 | |
duke@1 | 790 | try { |
duke@1 | 791 | // set the codebase returned by the server |
duke@1 | 792 | if (messageMediator.getConnection() != null) { |
duke@1 | 793 | ((CorbaConnection)messageMediator.getConnection()).setCodeBaseIOR(ior); |
duke@1 | 794 | } |
duke@1 | 795 | } catch (ThreadDeath td) { |
duke@1 | 796 | throw td ; |
duke@1 | 797 | } catch (Throwable t) { |
duke@1 | 798 | throw wrapper.badStringifiedIor( t ) ; |
duke@1 | 799 | } |
duke@1 | 800 | } |
duke@1 | 801 | |
duke@1 | 802 | // see if the version subcontract is present, if yes, then set |
duke@1 | 803 | // the ORBversion |
duke@1 | 804 | sc = ctxts.get( ORBVersionServiceContext.SERVICE_CONTEXT_ID ) ; |
duke@1 | 805 | |
duke@1 | 806 | if (sc != null) { |
duke@1 | 807 | ORBVersionServiceContext ovsc = |
duke@1 | 808 | (ORBVersionServiceContext) sc; |
duke@1 | 809 | |
duke@1 | 810 | ORBVersion version = ovsc.getVersion(); |
duke@1 | 811 | orb.setORBVersion( version ) ; |
duke@1 | 812 | } |
duke@1 | 813 | |
duke@1 | 814 | getExceptionDetailMessage(messageMediator, wrapper); |
duke@1 | 815 | } |
duke@1 | 816 | |
duke@1 | 817 | protected void getExceptionDetailMessage( |
duke@1 | 818 | CorbaMessageMediator messageMediator, |
duke@1 | 819 | ORBUtilSystemException wrapper) |
duke@1 | 820 | { |
duke@1 | 821 | ServiceContext sc = messageMediator.getReplyServiceContexts() |
duke@1 | 822 | .get(ExceptionDetailMessage.value); |
duke@1 | 823 | if (sc == null) |
duke@1 | 824 | return ; |
duke@1 | 825 | |
duke@1 | 826 | if (! (sc instanceof UnknownServiceContext)) { |
duke@1 | 827 | throw wrapper.badExceptionDetailMessageServiceContextType(); |
duke@1 | 828 | } |
duke@1 | 829 | byte[] data = ((UnknownServiceContext)sc).getData(); |
duke@1 | 830 | EncapsInputStream in = |
duke@1 | 831 | new EncapsInputStream((ORB)messageMediator.getBroker(), |
duke@1 | 832 | data, data.length); |
duke@1 | 833 | in.consumeEndian(); |
duke@1 | 834 | |
duke@1 | 835 | String msg = |
duke@1 | 836 | "----------BEGIN server-side stack trace----------\n" |
duke@1 | 837 | + in.read_wstring() + "\n" |
duke@1 | 838 | + "----------END server-side stack trace----------"; |
duke@1 | 839 | |
duke@1 | 840 | messageMediator.setReplyExceptionDetailMessage(msg); |
duke@1 | 841 | } |
duke@1 | 842 | |
duke@1 | 843 | public void endRequest(Broker broker, Object self, InputObject inputObject) |
duke@1 | 844 | { |
duke@1 | 845 | ORB orb = (ORB)broker ; |
duke@1 | 846 | |
duke@1 | 847 | try { |
duke@1 | 848 | if (orb.subcontractDebugFlag) { |
duke@1 | 849 | dprint(".endRequest->"); |
duke@1 | 850 | } |
duke@1 | 851 | |
duke@1 | 852 | // Note: the inputObject may be null if an error occurs |
duke@1 | 853 | // in request or before _invoke returns. |
duke@1 | 854 | // Note: self may be null also (e.g., compiler generates null in stub). |
duke@1 | 855 | |
duke@1 | 856 | MessageMediator messageMediator = |
duke@1 | 857 | orb.getInvocationInfo().getMessageMediator(); |
duke@1 | 858 | if (messageMediator != null) |
duke@1 | 859 | { |
duke@1 | 860 | if (messageMediator.getConnection() != null) |
duke@1 | 861 | { |
duke@1 | 862 | ((CorbaMessageMediator)messageMediator) |
duke@1 | 863 | .sendCancelRequestIfFinalFragmentNotSent(); |
duke@1 | 864 | } |
duke@1 | 865 | |
duke@1 | 866 | // Release any outstanding NIO ByteBuffers to the ByteBufferPool |
duke@1 | 867 | |
duke@1 | 868 | InputObject inputObj = messageMediator.getInputObject(); |
duke@1 | 869 | if (inputObj != null) { |
duke@1 | 870 | inputObj.close(); |
duke@1 | 871 | } |
duke@1 | 872 | |
duke@1 | 873 | OutputObject outputObj = messageMediator.getOutputObject(); |
duke@1 | 874 | if (outputObj != null) { |
duke@1 | 875 | outputObj.close(); |
duke@1 | 876 | } |
duke@1 | 877 | |
duke@1 | 878 | } |
duke@1 | 879 | |
duke@1 | 880 | // XREVISIT NOTE - Assumes unregistering the waiter for |
duke@1 | 881 | // location forwards has already happened somewhere else. |
duke@1 | 882 | // The code below is only going to unregister the final successful |
duke@1 | 883 | // request. |
duke@1 | 884 | |
duke@1 | 885 | // NOTE: In the case of a recursive stack of endRequests in a |
duke@1 | 886 | // finally block (because of Remarshal) only the first call to |
duke@1 | 887 | // unregisterWaiter will remove the waiter. The rest will be |
duke@1 | 888 | // noops. |
duke@1 | 889 | unregisterWaiter(orb); |
duke@1 | 890 | |
duke@1 | 891 | // Invoke Portable Interceptors cleanup. This is done to handle |
duke@1 | 892 | // exceptions during stream marshaling. More generally, exceptions |
duke@1 | 893 | // that occur in the ORB after send_request (which includes |
duke@1 | 894 | // after returning from _request) before _invoke: |
duke@1 | 895 | orb.getPIHandler().cleanupClientPIRequest(); |
duke@1 | 896 | |
duke@1 | 897 | // REVISIT: Early replies? |
duke@1 | 898 | } catch (IOException ex) { |
duke@1 | 899 | // See CDRInput/OutputObject.close() for more info. |
duke@1 | 900 | // This won't result in a Corba error if an IOException happens. |
duke@1 | 901 | if (orb.subcontractDebugFlag) |
duke@1 | 902 | { |
duke@1 | 903 | dprint(".endRequest: ignoring IOException - " + ex.toString()); |
duke@1 | 904 | } |
duke@1 | 905 | } finally { |
duke@1 | 906 | if (orb.subcontractDebugFlag) { |
duke@1 | 907 | dprint(".endRequest<-"); |
duke@1 | 908 | } |
duke@1 | 909 | } |
duke@1 | 910 | } |
duke@1 | 911 | |
duke@1 | 912 | |
duke@1 | 913 | protected void performCodeSetNegotiation(CorbaMessageMediator messageMediator) |
duke@1 | 914 | { |
duke@1 | 915 | CorbaConnection conn = |
duke@1 | 916 | (CorbaConnection) messageMediator.getConnection(); |
duke@1 | 917 | IOR ior = |
duke@1 | 918 | ((CorbaContactInfo)messageMediator.getContactInfo()) |
duke@1 | 919 | .getEffectiveTargetIOR(); |
duke@1 | 920 | GIOPVersion giopVersion = messageMediator.getGIOPVersion(); |
duke@1 | 921 | |
duke@1 | 922 | // XXX This seems to be a broken double checked locking idiom: FIX IT! |
duke@1 | 923 | |
duke@1 | 924 | // conn.getCodeSetContext() is null when no other requests have |
duke@1 | 925 | // been made on this connection to trigger code set negotation. |
duke@1 | 926 | if (conn != null && |
duke@1 | 927 | conn.getCodeSetContext() == null && |
duke@1 | 928 | !giopVersion.equals(GIOPVersion.V1_0)) { |
duke@1 | 929 | |
duke@1 | 930 | synchronized(conn) { |
duke@1 | 931 | // Double checking. Don't let any other |
duke@1 | 932 | // threads use this connection until the |
duke@1 | 933 | // code sets are straight. |
duke@1 | 934 | if (conn.getCodeSetContext() != null) |
duke@1 | 935 | return; |
duke@1 | 936 | |
duke@1 | 937 | // This only looks at the first code set component. If |
duke@1 | 938 | // there can be multiple locations with multiple code sets, |
duke@1 | 939 | // this requires more work. |
duke@1 | 940 | IIOPProfileTemplate temp = |
duke@1 | 941 | (IIOPProfileTemplate)ior.getProfile(). |
duke@1 | 942 | getTaggedProfileTemplate(); |
duke@1 | 943 | Iterator iter = temp.iteratorById(TAG_CODE_SETS.value); |
duke@1 | 944 | if (!iter.hasNext()) { |
duke@1 | 945 | // Didn't have a code set component. The default will |
duke@1 | 946 | // be to use ISO8859-1 for char data and throw an |
duke@1 | 947 | // exception if wchar data is used. |
duke@1 | 948 | return; |
duke@1 | 949 | } |
duke@1 | 950 | |
duke@1 | 951 | // Get the native and conversion code sets the |
duke@1 | 952 | // server specified in its IOR |
duke@1 | 953 | CodeSetComponentInfo serverCodeSets |
duke@1 | 954 | = ((CodeSetsComponent)iter.next()).getCodeSetComponentInfo(); |
duke@1 | 955 | |
duke@1 | 956 | // Perform the negotiation between this ORB's code sets and |
duke@1 | 957 | // the ones from the IOR |
duke@1 | 958 | CodeSetComponentInfo.CodeSetContext result |
duke@1 | 959 | = CodeSetConversion.impl().negotiate( |
duke@1 | 960 | conn.getBroker().getORBData().getCodeSetComponentInfo(), |
duke@1 | 961 | serverCodeSets); |
duke@1 | 962 | |
duke@1 | 963 | conn.setCodeSetContext(result); |
duke@1 | 964 | } |
duke@1 | 965 | } |
duke@1 | 966 | } |
duke@1 | 967 | |
duke@1 | 968 | protected void addCodeSetServiceContext(CorbaConnection conn, |
duke@1 | 969 | ServiceContexts ctxs, |
duke@1 | 970 | GIOPVersion giopVersion) { |
duke@1 | 971 | |
duke@1 | 972 | // REVISIT. OMG issue 3318 concerning sending the code set |
duke@1 | 973 | // service context more than once was deemed too much for the |
duke@1 | 974 | // RTF. Here's our strategy for the moment: |
duke@1 | 975 | // |
duke@1 | 976 | // Send it on every request (necessary in cases of fragmentation |
duke@1 | 977 | // with multithreaded clients or when the first thing on a |
duke@1 | 978 | // connection is a LocateRequest). Provide an ORB property |
duke@1 | 979 | // to disable multiple sends. |
duke@1 | 980 | // |
duke@1 | 981 | // Note that the connection is null in the local case and no |
duke@1 | 982 | // service context is included. We use the ORB provided |
duke@1 | 983 | // encapsulation streams. |
duke@1 | 984 | // |
duke@1 | 985 | // Also, there will be no negotiation or service context |
duke@1 | 986 | // in GIOP 1.0. ISO8859-1 is used for char/string, and |
duke@1 | 987 | // wchar/wstring are illegal. |
duke@1 | 988 | // |
duke@1 | 989 | if (giopVersion.equals(GIOPVersion.V1_0) || conn == null) |
duke@1 | 990 | return; |
duke@1 | 991 | |
duke@1 | 992 | CodeSetComponentInfo.CodeSetContext codeSetCtx = null; |
duke@1 | 993 | |
duke@1 | 994 | if (conn.getBroker().getORBData().alwaysSendCodeSetServiceContext() || |
duke@1 | 995 | !conn.isPostInitialContexts()) { |
duke@1 | 996 | |
duke@1 | 997 | // Get the negotiated code sets (if any) out of the connection |
duke@1 | 998 | codeSetCtx = conn.getCodeSetContext(); |
duke@1 | 999 | } |
duke@1 | 1000 | |
duke@1 | 1001 | // Either we shouldn't send the code set service context, or |
duke@1 | 1002 | // for some reason, the connection doesn't have its code sets. |
duke@1 | 1003 | // Perhaps the server didn't include them in the IOR. Uses |
duke@1 | 1004 | // ISO8859-1 for char and makes wchar/wstring illegal. |
duke@1 | 1005 | if (codeSetCtx == null) |
duke@1 | 1006 | return; |
duke@1 | 1007 | |
duke@1 | 1008 | CodeSetServiceContext cssc = new CodeSetServiceContext(codeSetCtx); |
duke@1 | 1009 | ctxs.put(cssc); |
duke@1 | 1010 | } |
duke@1 | 1011 | |
duke@1 | 1012 | protected String peekUserExceptionId(InputObject inputObject) |
duke@1 | 1013 | { |
duke@1 | 1014 | CDRInputObject cdrInputObject = (CDRInputObject) inputObject; |
duke@1 | 1015 | // REVISIT - need interface for mark/reset |
duke@1 | 1016 | cdrInputObject.mark(Integer.MAX_VALUE); |
duke@1 | 1017 | String result = cdrInputObject.read_string(); |
duke@1 | 1018 | cdrInputObject.reset(); |
duke@1 | 1019 | return result; |
duke@1 | 1020 | } |
duke@1 | 1021 | |
duke@1 | 1022 | protected void dprint(String msg) |
duke@1 | 1023 | { |
duke@1 | 1024 | ORBUtility.dprint("CorbaClientRequestDispatcherImpl", msg); |
duke@1 | 1025 | } |
duke@1 | 1026 | |
duke@1 | 1027 | protected String opAndId(CorbaMessageMediator mediator) |
duke@1 | 1028 | { |
duke@1 | 1029 | return ORBUtility.operationNameAndRequestId(mediator); |
duke@1 | 1030 | } |
duke@1 | 1031 | } |
duke@1 | 1032 | |
duke@1 | 1033 | // End of file. |