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