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