CorbaServerRequestDispatcherImpl.java revision 608:7e06bf1dcb09
1/* 2 * Copyright (c) 1998, 2004, 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 * Licensed Materials - Property of IBM 27 * RMI-IIOP v1.0 28 * Copyright IBM Corp. 1998 1999 All Rights Reserved 29 * 30 */ 31 32 33package com.sun.corba.se.impl.protocol; 34 35import org.omg.PortableServer.Servant ; 36 37import org.omg.CORBA.SystemException; 38import org.omg.CORBA.INTERNAL; 39import org.omg.CORBA.UNKNOWN; 40import org.omg.CORBA.CompletionStatus; 41import org.omg.CORBA.Any; 42 43import org.omg.CORBA.portable.InvokeHandler; 44import org.omg.CORBA.portable.InputStream; 45import org.omg.CORBA.portable.OutputStream; 46import org.omg.CORBA.portable.UnknownException; 47import org.omg.CORBA.portable.ResponseHandler; 48 49import com.sun.org.omg.SendingContext.CodeBase; 50 51import com.sun.corba.se.pept.encoding.OutputObject; 52import com.sun.corba.se.pept.protocol.MessageMediator; 53 54import com.sun.corba.se.spi.orb.ORB; 55import com.sun.corba.se.spi.orb.ORBVersion; 56import com.sun.corba.se.spi.orb.ORBVersionFactory; 57import com.sun.corba.se.spi.ior.IOR ; 58import com.sun.corba.se.spi.ior.ObjectKey; 59import com.sun.corba.se.spi.ior.ObjectKeyTemplate; 60import com.sun.corba.se.spi.ior.ObjectAdapterId; 61import com.sun.corba.se.spi.oa.ObjectAdapterFactory; 62import com.sun.corba.se.spi.oa.ObjectAdapter; 63import com.sun.corba.se.spi.oa.OAInvocationInfo; 64import com.sun.corba.se.spi.oa.OADestroyed; 65import com.sun.corba.se.spi.oa.NullServant; 66import com.sun.corba.se.spi.protocol.CorbaMessageMediator; 67import com.sun.corba.se.spi.protocol.CorbaServerRequestDispatcher; 68import com.sun.corba.se.spi.protocol.ForwardException ; 69import com.sun.corba.se.spi.protocol.RequestDispatcherRegistry; 70import com.sun.corba.se.spi.transport.CorbaConnection; 71import com.sun.corba.se.spi.logging.CORBALogDomains; 72import com.sun.corba.se.spi.ior.iiop.GIOPVersion; 73 74import com.sun.corba.se.impl.protocol.SpecialMethod ; 75import com.sun.corba.se.spi.servicecontext.ServiceContext; 76import com.sun.corba.se.spi.servicecontext.ServiceContexts; 77import com.sun.corba.se.spi.servicecontext.UEInfoServiceContext; 78import com.sun.corba.se.spi.servicecontext.CodeSetServiceContext; 79import com.sun.corba.se.spi.servicecontext.SendingContextServiceContext; 80import com.sun.corba.se.spi.servicecontext.ORBVersionServiceContext; 81 82import com.sun.corba.se.impl.corba.ServerRequestImpl ; 83import com.sun.corba.se.impl.encoding.MarshalInputStream; 84import com.sun.corba.se.impl.encoding.MarshalOutputStream; 85import com.sun.corba.se.impl.encoding.CodeSetComponentInfo; 86import com.sun.corba.se.impl.encoding.OSFCodeSetRegistry; 87import com.sun.corba.se.impl.orbutil.ORBConstants; 88import com.sun.corba.se.impl.orbutil.ORBUtility; 89import com.sun.corba.se.impl.protocol.RequestCanceledException; 90import com.sun.corba.se.impl.logging.ORBUtilSystemException; 91import com.sun.corba.se.impl.logging.POASystemException; 92 93public class CorbaServerRequestDispatcherImpl 94 implements CorbaServerRequestDispatcher 95{ 96 protected ORB orb; // my ORB instance 97 private ORBUtilSystemException wrapper ; 98 private POASystemException poaWrapper ; 99 100 // Added from last version because it broke the build - RTW 101 // XXX remove me and rebuild: probably no longer needed 102 // public static final int UNKNOWN_EXCEPTION_INFO_ID = 9; 103 104 public CorbaServerRequestDispatcherImpl(ORB orb) 105 { 106 this.orb = orb; 107 wrapper = ORBUtilSystemException.get( orb, 108 CORBALogDomains.RPC_PROTOCOL ) ; 109 poaWrapper = POASystemException.get( orb, 110 CORBALogDomains.RPC_PROTOCOL ) ; 111 } 112 113 /** XXX/REVISIT: 114 * We do not want to look for a servant in the POA/ServantManager case, 115 * but we could in most other cases. The OA could have a method that 116 * returns true if the servant MAY exist, and false only if the servant 117 * definitely DOES NOT exist. 118 * 119 * XXX/REVISIT: 120 * We may wish to indicate OBJECT_HERE by some mechanism other than 121 * returning a null result. 122 * 123 * Called from ORB.locate when a LocateRequest arrives. 124 * Result is not always absolutely correct: may indicate OBJECT_HERE 125 * for non-existent objects, which is resolved on invocation. This 126 * "bug" is unavoidable, since in general the object may be destroyed 127 * between a locate and a request. Note that this only checks that 128 * the appropriate ObjectAdapter is available, not that the servant 129 * actually exists. 130 * Need to signal one of OBJECT_HERE, OBJECT_FORWARD, OBJECT_NOT_EXIST. 131 * @return Result is null if object is (possibly) implemented here, otherwise 132 * an IOR indicating objref to forward the request to. 133 * @exception OBJECT_NOT_EXIST is thrown if we know the object does not 134 * exist here, and we are not forwarding. 135 */ 136 public IOR locate(ObjectKey okey) 137 { 138 try { 139 if (orb.subcontractDebugFlag) 140 dprint(".locate->"); 141 142 ObjectKeyTemplate oktemp = okey.getTemplate() ; 143 144 try { 145 checkServerId(okey); 146 } catch (ForwardException fex) { 147 return fex.getIOR() ; 148 } 149 150 // Called only for its side-effect of throwing appropriate exceptions 151 findObjectAdapter(oktemp); 152 153 return null ; 154 } finally { 155 if (orb.subcontractDebugFlag) 156 dprint(".locate<-"); 157 } 158 } 159 160 public void dispatch(MessageMediator messageMediator) 161 { 162 CorbaMessageMediator request = (CorbaMessageMediator) messageMediator; 163 try { 164 if (orb.subcontractDebugFlag) { 165 dprint(".dispatch->: " + opAndId(request)); 166 } 167 168 // to set the codebase information, if any transmitted; and also 169 // appropriate ORB Version. 170 consumeServiceContexts(request); 171 172 // Now that we have the service contexts processed and the 173 // correct ORBVersion set, we must finish initializing the 174 // stream. 175 ((MarshalInputStream)request.getInputObject()) 176 .performORBVersionSpecificInit(); 177 178 ObjectKey okey = request.getObjectKey(); 179 180 // Check that this server is the right server 181 try { 182 checkServerId(okey); 183 } catch (ForwardException fex) { 184 if (orb.subcontractDebugFlag) { 185 dprint(".dispatch: " + opAndId(request) 186 + ": bad server id"); 187 } 188 189 request.getProtocolHandler() 190 .createLocationForward(request, fex.getIOR(), null); 191 return; 192 } 193 194 String operation = request.getOperationName(); 195 ObjectAdapter objectAdapter = null ; 196 197 try { 198 byte[] objectId = okey.getId().getId() ; 199 ObjectKeyTemplate oktemp = okey.getTemplate() ; 200 objectAdapter = findObjectAdapter(oktemp); 201 202 java.lang.Object servant = getServantWithPI(request, objectAdapter, 203 objectId, oktemp, operation); 204 205 dispatchToServant(servant, request, objectId, objectAdapter); 206 } catch (ForwardException ex) { 207 if (orb.subcontractDebugFlag) { 208 dprint(".dispatch: " + opAndId(request) 209 + ": ForwardException caught"); 210 } 211 212 // Thrown by Portable Interceptors from InterceptorInvoker, 213 // through Response constructor. 214 request.getProtocolHandler() 215 .createLocationForward(request, ex.getIOR(), null); 216 } catch (OADestroyed ex) { 217 if (orb.subcontractDebugFlag) { 218 dprint(".dispatch: " + opAndId(request) 219 + ": OADestroyed exception caught"); 220 } 221 222 // DO NOT CALL THIS HERE: 223 // releaseServant(objectAdapter); 224 // The problem is that OADestroyed is only thrown by oa.enter, in 225 // which case oa.exit should NOT be called, and neither should 226 // the invocationInfo stack be popped. 227 228 // Destroyed POAs can be recreated by normal adapter activation. 229 // So just restart the dispatch. 230 dispatch(request); 231 } catch (RequestCanceledException ex) { 232 if (orb.subcontractDebugFlag) { 233 dprint(".dispatch: " + opAndId(request) 234 + ": RequestCanceledException caught"); 235 } 236 237 // IDLJ generated non-tie based skeletons do not catch the 238 // RequestCanceledException. Rethrow the exception, which will 239 // cause the worker thread to unwind the dispatch and wait for 240 // other requests. 241 throw ex; 242 } catch (UnknownException ex) { 243 if (orb.subcontractDebugFlag) { 244 dprint(".dispatch: " + opAndId(request) 245 + ": UnknownException caught " + ex); 246 } 247 248 // RMIC generated tie skeletons convert all Throwable exception 249 // types (including RequestCanceledException, ThreadDeath) 250 // thrown during reading fragments into UnknownException. 251 // If RequestCanceledException was indeed raised, 252 // then rethrow it, which will eventually cause the worker 253 // thread to unstack the dispatch and wait for other requests. 254 if (ex.originalEx instanceof RequestCanceledException) { 255 throw (RequestCanceledException) ex.originalEx; 256 } 257 258 ServiceContexts contexts = new ServiceContexts(orb); 259 UEInfoServiceContext usc = new UEInfoServiceContext( 260 ex.originalEx); 261 262 contexts.put( usc ) ; 263 264 SystemException sysex = wrapper.unknownExceptionInDispatch( 265 CompletionStatus.COMPLETED_MAYBE, ex ) ; 266 request.getProtocolHandler() 267 .createSystemExceptionResponse(request, sysex, 268 contexts); 269 } catch (Throwable ex) { 270 if (orb.subcontractDebugFlag) { 271 dprint(".dispatch: " + opAndId(request) 272 + ": other exception " + ex); 273 } 274 request.getProtocolHandler() 275 .handleThrowableDuringServerDispatch( 276 request, ex, CompletionStatus.COMPLETED_MAYBE); 277 } 278 return; 279 } finally { 280 if (orb.subcontractDebugFlag) { 281 dprint(".dispatch<-: " + opAndId(request)); 282 } 283 } 284 } 285 286 private void releaseServant(ObjectAdapter objectAdapter) 287 { 288 try { 289 if (orb.subcontractDebugFlag) { 290 dprint(".releaseServant->"); 291 } 292 293 if (objectAdapter == null) { 294 if (orb.subcontractDebugFlag) { 295 dprint(".releaseServant: null object adapter"); 296 } 297 return ; 298 } 299 300 try { 301 objectAdapter.returnServant(); 302 } finally { 303 objectAdapter.exit(); 304 orb.popInvocationInfo() ; 305 } 306 } finally { 307 if (orb.subcontractDebugFlag) { 308 dprint(".releaseServant<-"); 309 } 310 } 311 } 312 313 // Note that objectAdapter.enter() must be called before getServant. 314 private java.lang.Object getServant(ObjectAdapter objectAdapter, byte[] objectId, 315 String operation) 316 throws OADestroyed 317 { 318 try { 319 if (orb.subcontractDebugFlag) { 320 dprint(".getServant->"); 321 } 322 323 OAInvocationInfo info = objectAdapter.makeInvocationInfo(objectId); 324 info.setOperation(operation); 325 orb.pushInvocationInfo(info); 326 objectAdapter.getInvocationServant(info); 327 return info.getServantContainer() ; 328 } finally { 329 if (orb.subcontractDebugFlag) { 330 dprint(".getServant<-"); 331 } 332 } 333 } 334 335 protected java.lang.Object getServantWithPI(CorbaMessageMediator request, 336 ObjectAdapter objectAdapter, 337 byte[] objectId, ObjectKeyTemplate oktemp, String operation) 338 throws OADestroyed 339 { 340 try { 341 if (orb.subcontractDebugFlag) { 342 dprint(".getServantWithPI->"); 343 } 344 345 // Prepare Portable Interceptors for a new server request 346 // and invoke receive_request_service_contexts. The starting 347 // point may throw a SystemException or ForwardException. 348 orb.getPIHandler().initializeServerPIInfo(request, objectAdapter, 349 objectId, oktemp); 350 orb.getPIHandler().invokeServerPIStartingPoint(); 351 352 objectAdapter.enter() ; 353 354 // This must be set just after the enter so that exceptions thrown by 355 // enter do not cause 356 // the exception reply to pop the thread stack and do an extra oa.exit. 357 if (request != null) 358 request.setExecuteReturnServantInResponseConstructor(true); 359 360 java.lang.Object servant = getServant(objectAdapter, objectId, 361 operation); 362 363 // Note: we do not know the MDI on a null servant. 364 // We only end up in that situation if _non_existent called, 365 // so that the following handleNullServant call does not throw an 366 // exception. 367 String mdi = "unknown" ; 368 369 if (servant instanceof NullServant) 370 handleNullServant(operation, (NullServant)servant); 371 else 372 mdi = objectAdapter.getInterfaces(servant, objectId)[0] ; 373 374 orb.getPIHandler().setServerPIInfo(servant, mdi); 375 376 if (((servant != null) && 377 !(servant instanceof org.omg.CORBA.DynamicImplementation) && 378 !(servant instanceof org.omg.PortableServer.DynamicImplementation)) || 379 (SpecialMethod.getSpecialMethod(operation) != null)) { 380 orb.getPIHandler().invokeServerPIIntermediatePoint(); 381 } 382 383 return servant ; 384 } finally { 385 if (orb.subcontractDebugFlag) { 386 dprint(".getServantWithPI<-"); 387 } 388 } 389 } 390 391 protected void checkServerId(ObjectKey okey) 392 { 393 try { 394 if (orb.subcontractDebugFlag) { 395 dprint(".checkServerId->"); 396 } 397 398 ObjectKeyTemplate oktemp = okey.getTemplate() ; 399 int sId = oktemp.getServerId() ; 400 int scid = oktemp.getSubcontractId() ; 401 402 if (!orb.isLocalServerId(scid, sId)) { 403 if (orb.subcontractDebugFlag) { 404 dprint(".checkServerId: bad server id"); 405 } 406 407 orb.handleBadServerId(okey); 408 } 409 } finally { 410 if (orb.subcontractDebugFlag) { 411 dprint(".checkServerId<-"); 412 } 413 } 414 } 415 416 private ObjectAdapter findObjectAdapter(ObjectKeyTemplate oktemp) 417 { 418 try { 419 if (orb.subcontractDebugFlag) { 420 dprint(".findObjectAdapter->"); 421 } 422 423 RequestDispatcherRegistry scr = orb.getRequestDispatcherRegistry() ; 424 int scid = oktemp.getSubcontractId() ; 425 ObjectAdapterFactory oaf = scr.getObjectAdapterFactory(scid); 426 if (oaf == null) { 427 if (orb.subcontractDebugFlag) { 428 dprint(".findObjectAdapter: failed to find ObjectAdapterFactory"); 429 } 430 431 throw wrapper.noObjectAdapterFactory() ; 432 } 433 434 ObjectAdapterId oaid = oktemp.getObjectAdapterId() ; 435 ObjectAdapter oa = oaf.find(oaid); 436 437 if (oa == null) { 438 if (orb.subcontractDebugFlag) { 439 dprint(".findObjectAdapter: failed to find ObjectAdaptor"); 440 } 441 442 throw wrapper.badAdapterId() ; 443 } 444 445 return oa ; 446 } finally { 447 if (orb.subcontractDebugFlag) { 448 dprint(".findObjectAdapter<-"); 449 } 450 } 451 } 452 453 /** Always throws OBJECT_NOT_EXIST if operation is not a special method. 454 * If operation is _non_existent or _not_existent, this will just 455 * return without performing any action, so that _non_existent can return 456 * false. Always throws OBJECT_NOT_EXIST for any other special method. 457 * Update for issue 4385. 458 */ 459 protected void handleNullServant(String operation, NullServant nserv ) 460 { 461 try { 462 if (orb.subcontractDebugFlag) { 463 dprint(".handleNullServant->: " + operation); 464 } 465 466 SpecialMethod specialMethod = 467 SpecialMethod.getSpecialMethod(operation); 468 469 if ((specialMethod == null) || 470 !specialMethod.isNonExistentMethod()) { 471 if (orb.subcontractDebugFlag) { 472 dprint(".handleNullServant: " + operation 473 + ": throwing OBJECT_NOT_EXIST"); 474 } 475 476 throw nserv.getException() ; 477 } 478 } finally { 479 if (orb.subcontractDebugFlag) { 480 dprint(".handleNullServant<-: " + operation); 481 } 482 } 483 } 484 485 protected void consumeServiceContexts(CorbaMessageMediator request) 486 { 487 try { 488 if (orb.subcontractDebugFlag) { 489 dprint(".consumeServiceContexts->: " 490 + opAndId(request)); 491 } 492 493 ServiceContexts ctxts = request.getRequestServiceContexts(); 494 ServiceContext sc ; 495 496 GIOPVersion giopVersion = request.getGIOPVersion(); 497 498 // we cannot depend on this since for our local case, we do not send 499 // in this service context. Can we rely on just the CodeSetServiceContext? 500 // boolean rtSC = false; // Runtime ServiceContext 501 502 boolean hasCodeSetContext = processCodeSetContext(request, ctxts); 503 504 if (orb.subcontractDebugFlag) { 505 dprint(".consumeServiceContexts: " + opAndId(request) 506 + ": GIOP version: " + giopVersion); 507 dprint(".consumeServiceContexts: " + opAndId(request) 508 + ": as code set context? " + hasCodeSetContext); 509 } 510 511 sc = ctxts.get( 512 SendingContextServiceContext.SERVICE_CONTEXT_ID ) ; 513 514 if (sc != null) { 515 SendingContextServiceContext scsc = 516 (SendingContextServiceContext)sc ; 517 IOR ior = scsc.getIOR() ; 518 519 try { 520 ((CorbaConnection)request.getConnection()) 521 .setCodeBaseIOR(ior); 522 } catch (ThreadDeath td) { 523 throw td ; 524 } catch (Throwable t) { 525 throw wrapper.badStringifiedIor( t ) ; 526 } 527 } 528 529 // the RTSC is sent only once during session establishment. We 530 // need to find out if the CodeBaseRef is already set. If yes, 531 // then also the rtSC flag needs to be set to true 532 // this is not possible for the LocalCase since there is no 533 // IIOPConnection for the LocalCase 534 535 // used for a case where we have JDK 1.3 supporting 1.0 protocol, 536 // but sending 2 service contexts, that is not normal as per 537 // GIOP rules, based on above information, we figure out that we 538 // are talking to the legacy ORB and set the ORB Version Accordingly. 539 540 // this special case tell us that it is legacy SUN orb 541 // and not a foreign one 542 // rtSC is not available for localcase due to which this generic 543 // path would fail if relying on rtSC 544 //if (giopVersion.equals(GIOPVersion.V1_0) && hasCodeSetContext && rtSC) 545 boolean isForeignORB = false; 546 547 if (giopVersion.equals(GIOPVersion.V1_0) && hasCodeSetContext) { 548 if (orb.subcontractDebugFlag) { 549 dprint(".consumeServiceCOntexts: " + opAndId(request) 550 + ": Determined to be an old Sun ORB"); 551 } 552 553 orb.setORBVersion(ORBVersionFactory.getOLD()) ; 554 // System.out.println("setting legacy ORB version"); 555 } else { 556 // If it didn't include our ORB version service context (below), 557 // then it must be a foreign ORB. 558 isForeignORB = true; 559 } 560 561 // try to get the ORBVersion sent as part of the ServiceContext 562 // if any 563 sc = ctxts.get( ORBVersionServiceContext.SERVICE_CONTEXT_ID ) ; 564 if (sc != null) { 565 ORBVersionServiceContext ovsc = 566 (ORBVersionServiceContext) sc; 567 568 ORBVersion version = ovsc.getVersion(); 569 orb.setORBVersion(version); 570 571 isForeignORB = false; 572 } 573 574 if (isForeignORB) { 575 if (orb.subcontractDebugFlag) { 576 dprint(".consumeServiceContexts: " + opAndId(request) 577 + ": Determined to be a foreign ORB"); 578 } 579 580 orb.setORBVersion(ORBVersionFactory.getFOREIGN()); 581 } 582 } finally { 583 if (orb.subcontractDebugFlag) { 584 dprint(".consumeServiceContexts<-: " + opAndId(request)); 585 } 586 } 587 } 588 589 protected CorbaMessageMediator dispatchToServant( 590 java.lang.Object servant, 591 CorbaMessageMediator req, 592 byte[] objectId, ObjectAdapter objectAdapter) 593 { 594 try { 595 if (orb.subcontractDebugFlag) { 596 dprint(".dispatchToServant->: " + opAndId(req)); 597 } 598 599 CorbaMessageMediator response = null ; 600 601 String operation = req.getOperationName() ; 602 603 SpecialMethod method = SpecialMethod.getSpecialMethod(operation) ; 604 if (method != null) { 605 if (orb.subcontractDebugFlag) { 606 dprint(".dispatchToServant: " + opAndId(req) 607 + ": Handling special method"); 608 } 609 610 response = method.invoke(servant, req, objectId, objectAdapter); 611 return response ; 612 } 613 614 // Invoke on the servant using the portable DSI skeleton 615 if (servant instanceof org.omg.CORBA.DynamicImplementation) { 616 if (orb.subcontractDebugFlag) { 617 dprint(".dispatchToServant: " + opAndId(req) 618 + ": Handling old style DSI type servant"); 619 } 620 621 org.omg.CORBA.DynamicImplementation dynimpl = 622 (org.omg.CORBA.DynamicImplementation)servant; 623 ServerRequestImpl sreq = new ServerRequestImpl(req, orb); 624 625 // Note: When/if dynimpl.invoke calls arguments() or 626 // set_exception() then intermediate points are run. 627 dynimpl.invoke(sreq); 628 629 response = handleDynamicResult(sreq, req); 630 } else if (servant instanceof org.omg.PortableServer.DynamicImplementation) { 631 if (orb.subcontractDebugFlag) { 632 dprint(".dispatchToServant: " + opAndId(req) 633 + ": Handling POA DSI type servant"); 634 } 635 636 org.omg.PortableServer.DynamicImplementation dynimpl = 637 (org.omg.PortableServer.DynamicImplementation)servant; 638 ServerRequestImpl sreq = new ServerRequestImpl(req, orb); 639 640 // Note: When/if dynimpl.invoke calls arguments() or 641 // set_exception() then intermediate points are run. 642 dynimpl.invoke(sreq); 643 644 response = handleDynamicResult(sreq, req); 645 } else { 646 if (orb.subcontractDebugFlag) { 647 dprint(".dispatchToServant: " + opAndId(req) 648 + ": Handling invoke handler type servant"); 649 } 650 651 InvokeHandler invhandle = (InvokeHandler)servant ; 652 653 OutputStream stream = 654 (OutputStream)invhandle._invoke( 655 operation, 656 (org.omg.CORBA.portable.InputStream)req.getInputObject(), 657 req); 658 response = (CorbaMessageMediator) 659 ((OutputObject)stream).getMessageMediator(); 660 } 661 662 return response ; 663 } finally { 664 if (orb.subcontractDebugFlag) { 665 dprint(".dispatchToServant<-: " + opAndId(req)); 666 } 667 } 668 } 669 670 protected CorbaMessageMediator handleDynamicResult( 671 ServerRequestImpl sreq, 672 CorbaMessageMediator req) 673 { 674 try { 675 if (orb.subcontractDebugFlag) { 676 dprint(".handleDynamicResult->: " + opAndId(req)); 677 } 678 679 CorbaMessageMediator response = null ; 680 681 // Check if ServerRequestImpl.result() has been called 682 Any excany = sreq.checkResultCalled(); 683 684 if (excany == null) { // normal return 685 if (orb.subcontractDebugFlag) { 686 dprint(".handleDynamicResult: " + opAndId(req) 687 + ": handling normal result"); 688 } 689 690 // Marshal out/inout/return parameters into the ReplyMessage 691 response = sendingReply(req); 692 OutputStream os = (OutputStream) response.getOutputObject(); 693 sreq.marshalReplyParams(os); 694 } else { 695 if (orb.subcontractDebugFlag) { 696 dprint(".handleDynamicResult: " + opAndId(req) 697 + ": handling error"); 698 } 699 700 response = sendingReply(req, excany); 701 } 702 703 return response ; 704 } finally { 705 if (orb.subcontractDebugFlag) { 706 dprint(".handleDynamicResult<-: " + opAndId(req)); 707 } 708 } 709 } 710 711 protected CorbaMessageMediator sendingReply(CorbaMessageMediator req) 712 { 713 try { 714 if (orb.subcontractDebugFlag) { 715 dprint(".sendingReply->: " + opAndId(req)); 716 } 717 718 ServiceContexts scs = new ServiceContexts(orb); 719 return req.getProtocolHandler().createResponse(req, scs); 720 } finally { 721 if (orb.subcontractDebugFlag) { 722 dprint(".sendingReply<-: " + opAndId(req)); 723 } 724 } 725 } 726 727 /** Must always be called, just after the servant's method returns. 728 * Creates the ReplyMessage header and puts in the transaction context 729 * if necessary. 730 */ 731 protected CorbaMessageMediator sendingReply(CorbaMessageMediator req, Any excany) 732 { 733 try { 734 if (orb.subcontractDebugFlag) { 735 dprint(".sendingReply/Any->: " + opAndId(req)); 736 } 737 738 ServiceContexts scs = new ServiceContexts(orb); 739 740 // Check if the servant set a SystemException or 741 // UserException 742 CorbaMessageMediator resp; 743 String repId=null; 744 try { 745 repId = excany.type().id(); 746 } catch (org.omg.CORBA.TypeCodePackage.BadKind e) { 747 throw wrapper.problemWithExceptionTypecode( e ) ; 748 } 749 750 if (ORBUtility.isSystemException(repId)) { 751 if (orb.subcontractDebugFlag) { 752 dprint(".sendingReply/Any: " + opAndId(req) 753 + ": handling system exception"); 754 } 755 756 // Get the exception object from the Any 757 InputStream in = excany.create_input_stream(); 758 SystemException ex = ORBUtility.readSystemException(in); 759 // Marshal the exception back 760 resp = req.getProtocolHandler() 761 .createSystemExceptionResponse(req, ex, scs); 762 } else { 763 if (orb.subcontractDebugFlag) { 764 dprint(".sendingReply/Any: " + opAndId(req) 765 + ": handling user exception"); 766 } 767 768 resp = req.getProtocolHandler() 769 .createUserExceptionResponse(req, scs); 770 OutputStream os = (OutputStream)resp.getOutputObject(); 771 excany.write_value(os); 772 } 773 774 return resp; 775 } finally { 776 if (orb.subcontractDebugFlag) { 777 dprint(".sendingReply/Any<-: " + opAndId(req)); 778 } 779 } 780 } 781 782 /** 783 * Handles setting the connection's code sets if required. 784 * Returns true if the CodeSetContext was in the request, false 785 * otherwise. 786 */ 787 protected boolean processCodeSetContext( 788 CorbaMessageMediator request, ServiceContexts contexts) 789 { 790 try { 791 if (orb.subcontractDebugFlag) { 792 dprint(".processCodeSetContext->: " + opAndId(request)); 793 } 794 795 ServiceContext sc = contexts.get( 796 CodeSetServiceContext.SERVICE_CONTEXT_ID); 797 if (sc != null) { 798 // Somehow a code set service context showed up in the local case. 799 if (request.getConnection() == null) { 800 return true; 801 } 802 803 // If it's GIOP 1.0, it shouldn't have this context at all. Our legacy 804 // ORBs sent it and we need to know if it's here to make ORB versioning 805 // decisions, but we don't use the contents. 806 if (request.getGIOPVersion().equals(GIOPVersion.V1_0)) { 807 return true; 808 } 809 810 CodeSetServiceContext cssc = (CodeSetServiceContext)sc ; 811 CodeSetComponentInfo.CodeSetContext csctx = cssc.getCodeSetContext(); 812 813 // Note on threading: 814 // 815 // getCodeSetContext and setCodeSetContext are synchronized 816 // on the Connection. At worst, this will result in 817 // multiple threads entering this block and calling 818 // setCodeSetContext but not actually changing the 819 // values on the Connection. 820 // 821 // Alternative would be to lock the connection for the 822 // whole block, but it's fine either way. 823 824 // The connection's codeSetContext is null until we've received a 825 // request with a code set context with the negotiated code sets. 826 if (((CorbaConnection)request.getConnection()) 827 .getCodeSetContext() == null) 828 { 829 830 // Use these code sets on this connection 831 if (orb.subcontractDebugFlag) { 832 dprint(".processCodeSetContext: " + opAndId(request) 833 + ": Setting code sets to: " + csctx); 834 } 835 836 ((CorbaConnection)request.getConnection()) 837 .setCodeSetContext(csctx); 838 839 // We had to read the method name using ISO 8859-1 840 // (which is the default in the CDRInputStream for 841 // char data), but now we may have a new char 842 // code set. If it isn't ISO8859-1, we must tell 843 // the CDR stream to null any converter references 844 // it has created so that it will reacquire 845 // the code sets again using the new info. 846 // 847 // This should probably compare with the stream's 848 // char code set rather than assuming it's ISO8859-1. 849 // (However, the operation name is almost certainly 850 // ISO8859-1 or ASCII.) 851 if (csctx.getCharCodeSet() != 852 OSFCodeSetRegistry.ISO_8859_1.getNumber()) { 853 ((MarshalInputStream)request.getInputObject()) 854 .resetCodeSetConverters(); 855 } 856 } 857 } 858 859 // If no code set information is ever sent from the client, 860 // the server will use ISO8859-1 for char and throw an 861 // exception for any wchar transmissions. 862 // 863 // In the local case, we use ORB provided streams for 864 // marshaling and unmarshaling. Currently, they use 865 // ISO8859-1 for char/string and UTF16 for wchar/wstring. 866 return sc != null ; 867 } finally { 868 if (orb.subcontractDebugFlag) { 869 dprint(".processCodeSetContext<-: " + opAndId(request)); 870 } 871 } 872 } 873 874 protected void dprint(String msg) 875 { 876 ORBUtility.dprint("CorbaServerRequestDispatcherImpl", msg); 877 } 878 879 protected String opAndId(CorbaMessageMediator mediator) 880 { 881 return ORBUtility.operationNameAndRequestId(mediator); 882 } 883} 884 885// End of file. 886