ClientRequestInfoImpl.java revision 608:7e06bf1dcb09
1/* 2 * Copyright (c) 2000, 2012, 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 26package com.sun.corba.se.impl.interceptors; 27 28import java.util.HashMap ; 29 30import org.omg.CORBA.Any; 31import org.omg.CORBA.BAD_INV_ORDER; 32import org.omg.CORBA.BAD_PARAM; 33import org.omg.CORBA.CompletionStatus; 34import org.omg.CORBA.Context; 35import org.omg.CORBA.ContextList; 36import org.omg.CORBA.CTX_RESTRICT_SCOPE; 37import org.omg.CORBA.ExceptionList; 38import org.omg.CORBA.LocalObject; 39import org.omg.CORBA.NamedValue; 40import org.omg.CORBA.NO_IMPLEMENT; 41import org.omg.CORBA.NO_RESOURCES; 42import org.omg.CORBA.NVList; 43import org.omg.CORBA.Object; 44import org.omg.CORBA.ParameterMode; 45import org.omg.CORBA.Policy; 46import org.omg.CORBA.SystemException; 47import org.omg.CORBA.TypeCode; 48import org.omg.CORBA.INTERNAL; 49import org.omg.CORBA.UserException; 50import org.omg.CORBA.portable.ApplicationException; 51import org.omg.CORBA.portable.InputStream; 52import com.sun.corba.se.spi.servicecontext.ServiceContexts; 53import com.sun.corba.se.spi.servicecontext.UnknownServiceContext; 54 55import org.omg.IOP.ServiceContext; 56import org.omg.IOP.ServiceContextHelper; 57import org.omg.IOP.TaggedProfile; 58import org.omg.IOP.TaggedProfileHelper; 59import org.omg.IOP.TaggedComponent; 60import org.omg.IOP.TaggedComponentHelper; 61import org.omg.IOP.TAG_INTERNET_IOP; 62import org.omg.Dynamic.Parameter; 63import org.omg.PortableInterceptor.ClientRequestInfo; 64import org.omg.PortableInterceptor.LOCATION_FORWARD; 65import org.omg.PortableInterceptor.SUCCESSFUL; 66import org.omg.PortableInterceptor.SYSTEM_EXCEPTION; 67import org.omg.PortableInterceptor.TRANSPORT_RETRY; 68import org.omg.PortableInterceptor.USER_EXCEPTION; 69 70import com.sun.corba.se.pept.protocol.MessageMediator; 71 72import com.sun.corba.se.spi.ior.IOR; 73import com.sun.corba.se.spi.ior.iiop.IIOPProfileTemplate; 74import com.sun.corba.se.spi.ior.iiop.GIOPVersion; 75import com.sun.corba.se.spi.orb.ORB; 76import com.sun.corba.se.spi.protocol.CorbaMessageMediator; 77import com.sun.corba.se.spi.protocol.RetryType; 78import com.sun.corba.se.spi.transport.CorbaContactInfo; 79import com.sun.corba.se.spi.transport.CorbaContactInfoList; 80import com.sun.corba.se.spi.transport.CorbaContactInfoListIterator; 81 82import com.sun.corba.se.impl.encoding.CDROutputStream; 83import com.sun.corba.se.impl.encoding.CDRInputStream_1_0; 84import com.sun.corba.se.impl.orbutil.ORBUtility; 85import com.sun.corba.se.impl.protocol.CorbaInvocationInfo; 86import com.sun.corba.se.impl.util.RepositoryId; 87 88/** 89 * Implementation of the ClientRequestInfo interface as specified in 90 * orbos/99-12-02 section 5.4.2. 91 */ 92public final class ClientRequestInfoImpl 93 extends RequestInfoImpl 94 implements ClientRequestInfo 95{ 96 97 // The available constants for startingPointCall 98 static final int CALL_SEND_REQUEST = 0; 99 static final int CALL_SEND_POLL = 1; 100 101 // The available constants for endingPointCall 102 static final int CALL_RECEIVE_REPLY = 0; 103 static final int CALL_RECEIVE_EXCEPTION = 1; 104 static final int CALL_RECEIVE_OTHER = 2; 105 106 ////////////////////////////////////////////////////////////////////// 107 // 108 // NOTE: IF AN ATTRIBUTE IS ADDED, PLEASE UPDATE RESET(); 109 // 110 ////////////////////////////////////////////////////////////////////// 111 112 // The current retry request status. True if this request is being 113 // retried and this info object is to be reused, or false otherwise. 114 private RetryType retryRequest; 115 116 // The number of times this info object has been (re)used. This is 117 // incremented every time a request is retried, and decremented every 118 // time a request is complete. When this reaches zero, the info object 119 // is popped from the ClientRequestInfoImpl ThreadLocal stack in the ORB. 120 private int entryCount = 0; 121 122 // The RequestImpl is set when the call is DII based. 123 // The DII query calls like ParameterList, ExceptionList, 124 // ContextList will be delegated to RequestImpl. 125 private org.omg.CORBA.Request request; 126 127 // Sources of client request information 128 private boolean diiInitiate; 129 private CorbaMessageMediator messageMediator; 130 131 // Cached information: 132 private org.omg.CORBA.Object cachedTargetObject; 133 private org.omg.CORBA.Object cachedEffectiveTargetObject; 134 private Parameter[] cachedArguments; 135 private TypeCode[] cachedExceptions; 136 private String[] cachedContexts; 137 private String[] cachedOperationContext; 138 private String cachedReceivedExceptionId; 139 private Any cachedResult; 140 private Any cachedReceivedException; 141 private TaggedProfile cachedEffectiveProfile; 142 // key = Integer, value = IOP.ServiceContext. 143 private HashMap cachedRequestServiceContexts; 144 // key = Integer, value = IOP.ServiceContext. 145 private HashMap cachedReplyServiceContexts; 146 // key = Integer, value = TaggedComponent 147 private HashMap cachedEffectiveComponents; 148 149 150 protected boolean piCurrentPushed; 151 152 ////////////////////////////////////////////////////////////////////// 153 // 154 // NOTE: IF AN ATTRIBUTE IS ADDED, PLEASE UPDATE RESET(); 155 // 156 ////////////////////////////////////////////////////////////////////// 157 158 /** 159 * Reset the info object so that it can be reused for a retry, 160 * for example. 161 */ 162 void reset() { 163 super.reset(); 164 165 // Please keep these in the same order that they're declared above. 166 167 // 6763340 168 retryRequest = RetryType.NONE; 169 170 // Do not reset entryCount because we need to know when to pop this 171 // from the stack. 172 173 request = null; 174 diiInitiate = false; 175 messageMediator = null; 176 177 // Clear cached attributes: 178 cachedTargetObject = null; 179 cachedEffectiveTargetObject = null; 180 cachedArguments = null; 181 cachedExceptions = null; 182 cachedContexts = null; 183 cachedOperationContext = null; 184 cachedReceivedExceptionId = null; 185 cachedResult = null; 186 cachedReceivedException = null; 187 cachedEffectiveProfile = null; 188 cachedRequestServiceContexts = null; 189 cachedReplyServiceContexts = null; 190 cachedEffectiveComponents = null; 191 192 piCurrentPushed = false; 193 194 startingPointCall = CALL_SEND_REQUEST; 195 endingPointCall = CALL_RECEIVE_REPLY; 196 197 } 198 199 /* 200 ********************************************************************** 201 * Access protection 202 **********************************************************************/ 203 204 // Method IDs for all methods in ClientRequestInfo. This allows for a 205 // convenient O(1) lookup for checkAccess(). 206 protected static final int MID_TARGET = MID_RI_LAST + 1; 207 protected static final int MID_EFFECTIVE_TARGET = MID_RI_LAST + 2; 208 protected static final int MID_EFFECTIVE_PROFILE = MID_RI_LAST + 3; 209 protected static final int MID_RECEIVED_EXCEPTION = MID_RI_LAST + 4; 210 protected static final int MID_RECEIVED_EXCEPTION_ID = MID_RI_LAST + 5; 211 protected static final int MID_GET_EFFECTIVE_COMPONENT = MID_RI_LAST + 6; 212 protected static final int MID_GET_EFFECTIVE_COMPONENTS 213 = MID_RI_LAST + 7; 214 protected static final int MID_GET_REQUEST_POLICY = MID_RI_LAST + 8; 215 protected static final int MID_ADD_REQUEST_SERVICE_CONTEXT 216 = MID_RI_LAST + 9; 217 218 // ClientRequestInfo validity table (see ptc/00-08-06 table 21-1). 219 // Note: These must be in the same order as specified in contants. 220 private static final boolean validCall[][] = { 221 // LEGEND: 222 // s_req = send_request r_rep = receive_reply 223 // s_pol = send_poll r_exc = receive_exception 224 // r_oth = receive_other 225 // 226 // A true value indicates call is valid at specified point. 227 // A false value indicates the call is invalid. 228 // 229 // 230 // NOTE: If the order or number of columns change, update 231 // checkAccess() accordingly. 232 // 233 // { s_req, s_pol, r_rep, r_exc, r_oth } 234 // RequestInfo methods: 235 /*request_id*/ { true , true , true , true , true }, 236 /*operation*/ { true , true , true , true , true }, 237 /*arguments*/ { true , false, true , false, false }, 238 /*exceptions*/ { true , false, true , true , true }, 239 /*contexts*/ { true , false, true , true , true }, 240 /*operation_context*/ { true , false, true , true , true }, 241 /*result*/ { false, false, true , false, false }, 242 /*response_expected*/ { true , true , true , true , true }, 243 /*sync_scope*/ { true , false, true , true , true }, 244 /*reply_status*/ { false, false, true , true , true }, 245 /*forward_reference*/ { false, false, false, false, true }, 246 /*get_slot*/ { true , true , true , true , true }, 247 /*get_request_service_context*/ { true , false, true , true , true }, 248 /*get_reply_service_context*/ { false, false, true , true , true }, 249 // 250 // ClientRequestInfo methods:: 251 /*target*/ { true , true , true , true , true }, 252 /*effective_target*/ { true , true , true , true , true }, 253 /*effective_profile*/ { true , true , true , true , true }, 254 /*received_exception*/ { false, false, false, true , false }, 255 /*received_exception_id*/ { false, false, false, true , false }, 256 /*get_effective_component*/ { true , false, true , true , true }, 257 /*get_effective_components*/ { true , false, true , true , true }, 258 /*get_request_policy*/ { true , false, true , true , true }, 259 /*add_request_service_context*/ { true , false, false, false, false } 260 }; 261 262 263 /* 264 ********************************************************************** 265 * Public ClientRequestInfo interfaces 266 **********************************************************************/ 267 268 /** 269 * Creates a new ClientRequestInfo implementation. 270 * The constructor is package scope since no other package need create 271 * an instance of this class. 272 */ 273 protected ClientRequestInfoImpl( ORB myORB ) { 274 super( myORB ); 275 startingPointCall = CALL_SEND_REQUEST; 276 endingPointCall = CALL_RECEIVE_REPLY; 277 } 278 279 /** 280 * The object which the client called to perform the operation. 281 */ 282 public org.omg.CORBA.Object target (){ 283 // access is currently valid for all states: 284 //checkAccess( MID_TARGET ); 285 if (cachedTargetObject == null) { 286 CorbaContactInfo corbaContactInfo = (CorbaContactInfo) 287 messageMediator.getContactInfo(); 288 cachedTargetObject = 289 iorToObject(corbaContactInfo.getTargetIOR()); 290 } 291 return cachedTargetObject; 292 } 293 294 /** 295 * The actual object on which the operation will be invoked. If the 296 * reply_status is LOCATION_FORWARD, then on subsequent requests, 297 * effective_target will contain the forwarded IOR while target will 298 * remain unchanged. 299 */ 300 public org.omg.CORBA.Object effective_target() { 301 // access is currently valid for all states: 302 //checkAccess( MID_EFFECTIVE_TARGET ); 303 304 // Note: This is not necessarily the same as locatedIOR. 305 // Reason: See the way we handle COMM_FAILURES in 306 // ClientRequestDispatcher.createRequest, v1.32 307 308 if (cachedEffectiveTargetObject == null) { 309 CorbaContactInfo corbaContactInfo = (CorbaContactInfo) 310 messageMediator.getContactInfo(); 311 // REVISIT - get through chain like getLocatedIOR helper below. 312 cachedEffectiveTargetObject = 313 iorToObject(corbaContactInfo.getEffectiveTargetIOR()); 314 } 315 return cachedEffectiveTargetObject; 316 } 317 318 /** 319 * The profile that will be used to send the request. If a location 320 * forward has occurred for this operation's object and that object's 321 * profile change accordingly, then this profile will be that located 322 * profile. 323 */ 324 public TaggedProfile effective_profile (){ 325 // access is currently valid for all states: 326 //checkAccess( MID_EFFECTIVE_PROFILE ); 327 328 if( cachedEffectiveProfile == null ) { 329 CorbaContactInfo corbaContactInfo = (CorbaContactInfo) 330 messageMediator.getContactInfo(); 331 cachedEffectiveProfile = 332 corbaContactInfo.getEffectiveProfile().getIOPProfile(); 333 } 334 335 // Good citizen: In the interest of efficiency, we assume interceptors 336 // will not modify the returned TaggedProfile in any way so we need 337 // not make a deep copy of it. 338 339 return cachedEffectiveProfile; 340 } 341 342 /** 343 * Contains the exception to be returned to the client. 344 */ 345 public Any received_exception (){ 346 checkAccess( MID_RECEIVED_EXCEPTION ); 347 348 if( cachedReceivedException == null ) { 349 cachedReceivedException = exceptionToAny( exception ); 350 } 351 352 // Good citizen: In the interest of efficiency, we assume interceptors 353 // will not modify the returned Any in any way so we need 354 // not make a deep copy of it. 355 356 return cachedReceivedException; 357 } 358 359 /** 360 * The CORBA::RepositoryId of the exception to be returned to the client. 361 */ 362 public String received_exception_id (){ 363 checkAccess( MID_RECEIVED_EXCEPTION_ID ); 364 365 if( cachedReceivedExceptionId == null ) { 366 String result = null; 367 368 if( exception == null ) { 369 // Note: exception should never be null here since we will 370 // throw a BAD_INV_ORDER if this is not called from 371 // receive_exception. 372 throw wrapper.exceptionWasNull() ; 373 } else if( exception instanceof SystemException ) { 374 String name = exception.getClass().getName(); 375 result = ORBUtility.repositoryIdOf(name); 376 } else if( exception instanceof ApplicationException ) { 377 result = ((ApplicationException)exception).getId(); 378 } 379 380 // _REVISIT_ We need to be able to handle a UserException in the 381 // DII case. How do we extract the ID from a UserException? 382 383 cachedReceivedExceptionId = result; 384 } 385 386 return cachedReceivedExceptionId; 387 } 388 389 /** 390 * Returns the IOP::TaggedComponent with the given ID from the profile 391 * selected for this request. IF there is more than one component for a 392 * given component ID, it is undefined which component this operation 393 * returns (get_effective_component should be called instead). 394 */ 395 public TaggedComponent get_effective_component (int id){ 396 checkAccess( MID_GET_EFFECTIVE_COMPONENT ); 397 398 return get_effective_components( id )[0]; 399 } 400 401 /** 402 * Returns all the tagged components with the given ID from the profile 403 * selected for this request. 404 */ 405 public TaggedComponent[] get_effective_components (int id){ 406 checkAccess( MID_GET_EFFECTIVE_COMPONENTS ); 407 Integer integerId = new Integer( id ); 408 TaggedComponent[] result = null; 409 boolean justCreatedCache = false; 410 411 if( cachedEffectiveComponents == null ) { 412 cachedEffectiveComponents = new HashMap(); 413 justCreatedCache = true; 414 } 415 else { 416 // Look in cache: 417 result = (TaggedComponent[])cachedEffectiveComponents.get( 418 integerId ); 419 } 420 421 // null could mean we cached null or not in cache. 422 if( (result == null) && 423 (justCreatedCache || 424 !cachedEffectiveComponents.containsKey( integerId ) ) ) 425 { 426 // Not in cache. Get it from the profile: 427 CorbaContactInfo corbaContactInfo = (CorbaContactInfo) 428 messageMediator.getContactInfo(); 429 IIOPProfileTemplate ptemp = 430 (IIOPProfileTemplate)corbaContactInfo.getEffectiveProfile(). 431 getTaggedProfileTemplate(); 432 result = ptemp.getIOPComponents(myORB, id); 433 cachedEffectiveComponents.put( integerId, result ); 434 } 435 436 // As per ptc/00-08-06, section 21.3.13.6., If not found, raise 437 // BAD_PARAM with minor code INVALID_COMPONENT_ID. 438 if( (result == null) || (result.length == 0) ) { 439 throw stdWrapper.invalidComponentId( integerId ) ; 440 } 441 442 // Good citizen: In the interest of efficiency, we will assume 443 // interceptors will not modify the returned TaggedCompoent[], or 444 // the TaggedComponents inside of it. Otherwise, we would need to 445 // clone the array and make a deep copy of its contents. 446 447 return result; 448 } 449 450 /** 451 * Returns the given policy in effect for this operation. 452 */ 453 public Policy get_request_policy (int type){ 454 checkAccess( MID_GET_REQUEST_POLICY ); 455 // _REVISIT_ Our ORB is not policy-based at this time. 456 throw wrapper.piOrbNotPolicyBased() ; 457 } 458 459 /** 460 * Allows interceptors to add service contexts to the request. 461 * <p> 462 * There is no declaration of the order of the service contexts. They 463 * may or may not appear in the order they are added. 464 */ 465 public void add_request_service_context (ServiceContext service_context, 466 boolean replace) 467 { 468 checkAccess( MID_ADD_REQUEST_SERVICE_CONTEXT ); 469 470 if( cachedRequestServiceContexts == null ) { 471 cachedRequestServiceContexts = new HashMap(); 472 } 473 474 addServiceContext( cachedRequestServiceContexts, 475 messageMediator.getRequestServiceContexts(), 476 service_context, replace ); 477 } 478 479 // NOTE: When adding a method, be sure to: 480 // 1. Add a MID_* constant for that method 481 // 2. Call checkAccess at the start of the method 482 // 3. Define entries in the validCall[][] table for interception points. 483 484 /* 485 ********************************************************************** 486 * Public RequestInfo interfaces 487 * 488 * These are implemented here because they have differing 489 * implementations depending on whether this is a client or a server 490 * request info object. 491 **********************************************************************/ 492 493 /** 494 * See RequestInfoImpl for javadoc. 495 */ 496 public int request_id (){ 497 // access is currently valid for all states: 498 //checkAccess( MID_REQUEST_ID ); 499 /* 500 * NOTE: The requestId in client interceptors is the same as the 501 * GIOP request id. This works because both interceptors and 502 * request ids are scoped by the ORB on the client side. 503 */ 504 return messageMediator.getRequestId(); 505 } 506 507 /** 508 * See RequestInfoImpl for javadoc. 509 */ 510 public String operation (){ 511 // access is currently valid for all states: 512 //checkAccess( MID_OPERATION ); 513 return messageMediator.getOperationName(); 514 } 515 516 /** 517 * See RequestInfoImpl for javadoc. 518 */ 519 public Parameter[] arguments (){ 520 checkAccess( MID_ARGUMENTS ); 521 522 if( cachedArguments == null ) { 523 if( request == null ) { 524 throw stdWrapper.piOperationNotSupported1() ; 525 } 526 527 // If it is DII request then get the arguments from the DII req 528 // and convert that into parameters. 529 cachedArguments = nvListToParameterArray( request.arguments() ); 530 } 531 532 // Good citizen: In the interest of efficiency, we assume 533 // interceptors will be "good citizens" in that they will not 534 // modify the contents of the Parameter[] array. We also assume 535 // they will not change the values of the containing Anys. 536 537 return cachedArguments; 538 } 539 540 /** 541 * See RequestInfoImpl for javadoc. 542 */ 543 public TypeCode[] exceptions (){ 544 checkAccess( MID_EXCEPTIONS ); 545 546 if( cachedExceptions == null ) { 547 if( request == null ) { 548 throw stdWrapper.piOperationNotSupported2() ; 549 } 550 551 // Get the list of exceptions from DII request data, If there are 552 // no exceptions raised then this method will return null. 553 ExceptionList excList = request.exceptions( ); 554 int count = excList.count(); 555 TypeCode[] excTCList = new TypeCode[count]; 556 try { 557 for( int i = 0; i < count; i++ ) { 558 excTCList[i] = excList.item( i ); 559 } 560 } catch( Exception e ) { 561 throw wrapper.exceptionInExceptions( e ) ; 562 } 563 564 cachedExceptions = excTCList; 565 } 566 567 // Good citizen: In the interest of efficiency, we assume 568 // interceptors will be "good citizens" in that they will not 569 // modify the contents of the TypeCode[] array. We also assume 570 // they will not change the values of the containing TypeCodes. 571 572 return cachedExceptions; 573 } 574 575 /** 576 * See RequestInfoImpl for javadoc. 577 */ 578 public String[] contexts (){ 579 checkAccess( MID_CONTEXTS ); 580 581 if( cachedContexts == null ) { 582 if( request == null ) { 583 throw stdWrapper.piOperationNotSupported3() ; 584 } 585 586 // Get the list of contexts from DII request data, If there are 587 // no contexts then this method will return null. 588 ContextList ctxList = request.contexts( ); 589 int count = ctxList.count(); 590 String[] ctxListToReturn = new String[count]; 591 try { 592 for( int i = 0; i < count; i++ ) { 593 ctxListToReturn[i] = ctxList.item( i ); 594 } 595 } catch( Exception e ) { 596 throw wrapper.exceptionInContexts( e ) ; 597 } 598 599 cachedContexts = ctxListToReturn; 600 } 601 602 // Good citizen: In the interest of efficiency, we assume 603 // interceptors will be "good citizens" in that they will not 604 // modify the contents of the String[] array. 605 606 return cachedContexts; 607 } 608 609 /** 610 * See RequestInfoImpl for javadoc. 611 */ 612 public String[] operation_context (){ 613 checkAccess( MID_OPERATION_CONTEXT ); 614 615 if( cachedOperationContext == null ) { 616 if( request == null ) { 617 throw stdWrapper.piOperationNotSupported4() ; 618 } 619 620 // Get the list of contexts from DII request data, If there are 621 // no contexts then this method will return null. 622 Context ctx = request.ctx( ); 623 // _REVISIT_ The API for get_values is not compliant with the spec, 624 // Revisit this code once it's fixed. 625 // _REVISIT_ Our ORB doesn't support Operation Context, This code 626 // will not be excerscised until it's supported. 627 // The first parameter in get_values is the start_scope which 628 // if blank makes it as a global scope. 629 // The second parameter is op_flags which is set to RESTRICT_SCOPE 630 // As there is only one defined in the spec. 631 // The Third param is the pattern which is '*' requiring it to 632 // get all the contexts. 633 NVList nvList = ctx.get_values( "", CTX_RESTRICT_SCOPE.value,"*" ); 634 String[] context = new String[(nvList.count() * 2) ]; 635 if( ( nvList != null ) &&( nvList.count() != 0 ) ) { 636 // The String[] array will contain Name and Value for each 637 // context and hence double the size in the array. 638 int index = 0; 639 for( int i = 0; i < nvList.count(); i++ ) { 640 NamedValue nv; 641 try { 642 nv = nvList.item( i ); 643 } 644 catch (Exception e ) { 645 return (String[]) null; 646 } 647 context[index] = nv.name(); 648 index++; 649 context[index] = nv.value().extract_string(); 650 index++; 651 } 652 } 653 654 cachedOperationContext = context; 655 } 656 657 // Good citizen: In the interest of efficiency, we assume 658 // interceptors will be "good citizens" in that they will not 659 // modify the contents of the String[] array. 660 661 return cachedOperationContext; 662 } 663 664 /** 665 * See RequestInfoImpl for javadoc. 666 */ 667 public Any result (){ 668 checkAccess( MID_RESULT ); 669 670 if( cachedResult == null ) { 671 if( request == null ) { 672 throw stdWrapper.piOperationNotSupported5() ; 673 } 674 // Get the result from the DII request data. 675 NamedValue nvResult = request.result( ); 676 677 if( nvResult == null ) { 678 throw wrapper.piDiiResultIsNull() ; 679 } 680 681 cachedResult = nvResult.value(); 682 } 683 684 // Good citizen: In the interest of efficiency, we assume that 685 // interceptors will not modify the contents of the result Any. 686 // Otherwise, we would need to create a deep copy of the Any. 687 688 return cachedResult; 689 } 690 691 /** 692 * See RequestInfoImpl for javadoc. 693 */ 694 public boolean response_expected (){ 695 // access is currently valid for all states: 696 //checkAccess( MID_RESPONSE_EXPECTED ); 697 return ! messageMediator.isOneWay(); 698 } 699 700 /** 701 * See RequestInfoImpl for javadoc. 702 */ 703 public Object forward_reference (){ 704 checkAccess( MID_FORWARD_REFERENCE ); 705 // Check to make sure we are in LOCATION_FORWARD 706 // state as per ptc/00-08-06, table 21-1 707 // footnote 2. 708 if( replyStatus != LOCATION_FORWARD.value ) { 709 throw stdWrapper.invalidPiCall1() ; 710 } 711 712 // Do not cache this value since if an interceptor raises 713 // forward request then the next interceptor in the 714 // list should see the new value. 715 IOR ior = getLocatedIOR(); 716 return iorToObject(ior); 717 } 718 719 private IOR getLocatedIOR() 720 { 721 IOR ior; 722 CorbaContactInfoList contactInfoList = (CorbaContactInfoList) 723 messageMediator.getContactInfo().getContactInfoList(); 724 ior = contactInfoList.getEffectiveTargetIOR(); 725 return ior; 726 } 727 728 protected void setLocatedIOR(IOR ior) 729 { 730 ORB orb = (ORB) messageMediator.getBroker(); 731 732 CorbaContactInfoListIterator iterator = (CorbaContactInfoListIterator) 733 ((CorbaInvocationInfo)orb.getInvocationInfo()) 734 .getContactInfoListIterator(); 735 736 // REVISIT - this most likely causes reportRedirect to happen twice. 737 // Once here and once inside the request dispatcher. 738 iterator.reportRedirect( 739 (CorbaContactInfo)messageMediator.getContactInfo(), 740 ior); 741 } 742 743 /** 744 * See RequestInfoImpl for javadoc. 745 */ 746 public org.omg.IOP.ServiceContext get_request_service_context( int id ) { 747 checkAccess( MID_GET_REQUEST_SERVICE_CONTEXT ); 748 749 if( cachedRequestServiceContexts == null ) { 750 cachedRequestServiceContexts = new HashMap(); 751 } 752 753 return getServiceContext(cachedRequestServiceContexts, 754 messageMediator.getRequestServiceContexts(), 755 id); 756 } 757 758 /** 759 * does not contain an etry for that ID, BAD_PARAM with a minor code of 760 * TBD_BP is raised. 761 */ 762 public org.omg.IOP.ServiceContext get_reply_service_context( int id ) { 763 checkAccess( MID_GET_REPLY_SERVICE_CONTEXT ); 764 765 if( cachedReplyServiceContexts == null ) { 766 cachedReplyServiceContexts = new HashMap(); 767 } 768 769 // In the event this is called from a oneway, we will have no 770 // response object. 771 // 772 // In the event this is called after a IIOPConnection.purgeCalls, 773 // we will have a response object, but that object will 774 // not contain a header (which would hold the service context 775 // container). See bug 4624102. 776 // 777 // REVISIT: this is the only thing used 778 // from response at this time. However, a more general solution 779 // would avoid accessing other parts of response's header. 780 // 781 // Instead of throwing a NullPointer, we will 782 // "gracefully" handle these with a BAD_PARAM with minor code 25. 783 784 try { 785 ServiceContexts serviceContexts = 786 messageMediator.getReplyServiceContexts(); 787 if (serviceContexts == null) { 788 throw new NullPointerException(); 789 } 790 return getServiceContext(cachedReplyServiceContexts, 791 serviceContexts, id); 792 } catch (NullPointerException e) { 793 // REVISIT how this is programmed - not what it does. 794 // See purge calls test. The waiter is woken up by the 795 // call to purge calls - but there is no reply containing 796 // service contexts. 797 throw stdWrapper.invalidServiceContextId( e ) ; 798 } 799 } 800 801 // 802 // REVISIT 803 // Override RequestInfoImpl connection to work in framework. 804 // 805 806 public com.sun.corba.se.spi.legacy.connection.Connection connection() 807 { 808 return (com.sun.corba.se.spi.legacy.connection.Connection) 809 messageMediator.getConnection(); 810 } 811 812 813 814 /* 815 ********************************************************************** 816 * Package-scope interfaces 817 **********************************************************************/ 818 819 protected void setInfo(MessageMediator messageMediator) 820 { 821 this.messageMediator = (CorbaMessageMediator)messageMediator; 822 // REVISIT - so mediator can handle DII in subcontract. 823 this.messageMediator.setDIIInfo(request); 824 } 825 826 /** 827 * Set or reset the retry request flag. 828 */ 829 void setRetryRequest( RetryType retryRequest ) { 830 this.retryRequest = retryRequest; 831 } 832 833 /** 834 * Retrieve the current retry request status. 835 */ 836 RetryType getRetryRequest() { 837 // 6763340 838 return this.retryRequest; 839 } 840 841 /** 842 * Increases the entry count by 1. 843 */ 844 void incrementEntryCount() { 845 this.entryCount++; 846 } 847 848 /** 849 * Decreases the entry count by 1. 850 */ 851 void decrementEntryCount() { 852 this.entryCount--; 853 } 854 855 /** 856 * Retrieve the current entry count 857 */ 858 int getEntryCount() { 859 return this.entryCount; 860 } 861 862 /** 863 * Overridden from RequestInfoImpl. Calls the super class, then 864 * sets the ending point call depending on the reply status. 865 */ 866 protected void setReplyStatus( short replyStatus ) { 867 super.setReplyStatus( replyStatus ); 868 switch( replyStatus ) { 869 case SUCCESSFUL.value: 870 endingPointCall = CALL_RECEIVE_REPLY; 871 break; 872 case SYSTEM_EXCEPTION.value: 873 case USER_EXCEPTION.value: 874 endingPointCall = CALL_RECEIVE_EXCEPTION; 875 break; 876 case LOCATION_FORWARD.value: 877 case TRANSPORT_RETRY.value: 878 endingPointCall = CALL_RECEIVE_OTHER; 879 break; 880 } 881 } 882 883 /** 884 * Sets DII request object in the RequestInfoObject. 885 */ 886 protected void setDIIRequest(org.omg.CORBA.Request req) { 887 request = req; 888 } 889 890 /** 891 * Keeps track of whether initiate was called for a DII request. The ORB 892 * needs to know this so it knows whether to ignore a second call to 893 * initiateClientPIRequest or not. 894 */ 895 protected void setDIIInitiate( boolean diiInitiate ) { 896 this.diiInitiate = diiInitiate; 897 } 898 899 /** 900 * See comment for setDIIInitiate 901 */ 902 protected boolean isDIIInitiate() { 903 return this.diiInitiate; 904 } 905 906 /** 907 * The PICurrent stack should only be popped if it was pushed. 908 * This is generally the case. But exceptions which occur 909 * after the stub's entry to _request but before the push 910 * end up in _releaseReply which will try to pop unless told not to. 911 */ 912 protected void setPICurrentPushed( boolean piCurrentPushed ) { 913 this.piCurrentPushed = piCurrentPushed; 914 } 915 916 protected boolean isPICurrentPushed() { 917 return this.piCurrentPushed; 918 } 919 920 /** 921 * Overridden from RequestInfoImpl. 922 */ 923 protected void setException( Exception exception ) { 924 super.setException( exception ); 925 926 // Clear cached values: 927 cachedReceivedException = null; 928 cachedReceivedExceptionId = null; 929 } 930 931 protected boolean getIsOneWay() { 932 return ! response_expected(); 933 } 934 935 /** 936 * See description for RequestInfoImpl.checkAccess 937 */ 938 protected void checkAccess( int methodID ) 939 throws BAD_INV_ORDER 940 { 941 // Make sure currentPoint matches the appropriate index in the 942 // validCall table: 943 int validCallIndex = 0; 944 switch( currentExecutionPoint ) { 945 case EXECUTION_POINT_STARTING: 946 switch( startingPointCall ) { 947 case CALL_SEND_REQUEST: 948 validCallIndex = 0; 949 break; 950 case CALL_SEND_POLL: 951 validCallIndex = 1; 952 break; 953 } 954 break; 955 case EXECUTION_POINT_ENDING: 956 switch( endingPointCall ) { 957 case CALL_RECEIVE_REPLY: 958 validCallIndex = 2; 959 break; 960 case CALL_RECEIVE_EXCEPTION: 961 validCallIndex = 3; 962 break; 963 case CALL_RECEIVE_OTHER: 964 validCallIndex = 4; 965 break; 966 } 967 break; 968 } 969 970 // Check the validCall table: 971 if( !validCall[methodID][validCallIndex] ) { 972 throw stdWrapper.invalidPiCall2() ; 973 } 974 } 975 976} 977 978// End of file. 979