1 /* 2 * Copyright (c) 2000, 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 package com.sun.corba.se.impl.interceptors; 26 27 import java.io.IOException ; 28 29 import java.lang.reflect.Method ; 30 import java.lang.reflect.InvocationTargetException ; 31 32 import java.util.HashMap ; 33 34 import org.omg.PortableInterceptor.ForwardRequest; 35 import org.omg.PortableInterceptor.InvalidSlot; 36 import org.omg.PortableInterceptor.RequestInfo; 37 import org.omg.PortableInterceptor.LOCATION_FORWARD; 38 import org.omg.IOP.TaggedProfile; 39 import org.omg.IOP.TaggedComponent; 40 import org.omg.IOP.ServiceContextHelper; 41 import org.omg.Messaging.SYNC_WITH_TRANSPORT; 42 import org.omg.CORBA.ParameterMode; 43 44 import org.omg.CORBA.Any; 45 import org.omg.CORBA.BAD_INV_ORDER; 46 import org.omg.CORBA.BAD_PARAM; 47 import org.omg.CORBA.CompletionStatus; 48 import org.omg.CORBA.Context; 49 import org.omg.CORBA.ContextList; 50 import org.omg.CORBA.CTX_RESTRICT_SCOPE; 51 import org.omg.CORBA.ExceptionList; 52 import org.omg.CORBA.INTERNAL; 53 import org.omg.CORBA.LocalObject; 54 import org.omg.CORBA.NamedValue; 55 import org.omg.CORBA.NO_IMPLEMENT; 56 import org.omg.CORBA.NO_RESOURCES; 57 import org.omg.CORBA.NVList; 58 import org.omg.CORBA.Object; 59 import org.omg.CORBA.Policy; 60 import org.omg.CORBA.SystemException; 61 import org.omg.CORBA.TypeCode; 62 import org.omg.CORBA.UNKNOWN; 63 import org.omg.CORBA.UserException; 64 import org.omg.CORBA.portable.ApplicationException; 65 import org.omg.CORBA.portable.Delegate; 66 import org.omg.CORBA.portable.InputStream; 67 68 import org.omg.Dynamic.Parameter; 69 70 import com.sun.corba.se.spi.legacy.connection.Connection; 71 72 import com.sun.corba.se.spi.legacy.interceptor.RequestInfoExt; 73 74 import com.sun.corba.se.spi.ior.IOR; 75 76 import com.sun.corba.se.spi.ior.iiop.GIOPVersion; 77 78 import com.sun.corba.se.spi.orb.ORB; 79 80 import com.sun.corba.se.spi.logging.CORBALogDomains; 81 82 import com.sun.corba.se.spi.servicecontext.ServiceContexts; 83 import com.sun.corba.se.spi.servicecontext.UnknownServiceContext; 84 85 import com.sun.corba.se.impl.encoding.CDRInputStream_1_0; 86 import com.sun.corba.se.impl.encoding.EncapsOutputStream; 87 88 import com.sun.corba.se.impl.orbutil.ORBUtility; 89 import com.sun.corba.se.impl.orbutil.ORBClassLoader; 90 91 import com.sun.corba.se.impl.util.RepositoryId; 92 93 import com.sun.corba.se.impl.logging.InterceptorsSystemException; 94 import com.sun.corba.se.impl.logging.OMGSystemException; 95 96 /** 97 * Implementation of the RequestInfo interface as specified in 98 * orbos/99-12-02 section 5.4.1. 99 */ 100 public abstract class RequestInfoImpl 101 extends LocalObject 102 implements RequestInfo, RequestInfoExt 103 { 104 ////////////////////////////////////////////////////////////////////// 105 // 106 // NOTE: IF AN ATTRIBUTE IS ADDED, PLEASE UPDATE RESET(); 107 // 108 ////////////////////////////////////////////////////////////////////// 109 110 // The ORB from which to get PICurrent and other info 111 protected ORB myORB; 112 protected InterceptorsSystemException wrapper ; 113 protected OMGSystemException stdWrapper ; 114 115 // The number of interceptors actually invoked for this client request. 116 // See setFlowStackIndex for a detailed description. 117 protected int flowStackIndex = 0; 118 119 // The type of starting point call to make to the interceptors 120 // See ClientRequestInfoImpl and ServerRequestInfoImpl for a list of 121 // appropriate constants. 122 protected int startingPointCall; 123 124 // The type of intermediate point call to make to the interceptors 125 // See ServerRequestInfoImpl for a list of appropriate constants. 126 // This does not currently apply to client request interceptors but is 127 // here in case intermediate points are introduced in the future. 128 protected int intermediatePointCall; 129 130 // The type of ending point call to make to the interceptors 131 // See ClientRequestInfoImpl and ServerRequestInfoImpl for a list of 132 // appropriate constants. 133 protected int endingPointCall; 134 135 // The reply status to return in reply_status. This is initialized 136 // to UNINITIALIZED so that we can tell if this has been set or not. 137 protected short replyStatus = UNINITIALIZED; 138 139 // Constant for an uninitizlied reply status. 140 protected static final short UNINITIALIZED = -1; 141 142 // Which points we are currently executing (so we can implement the 143 // validity table). 144 protected int currentExecutionPoint; 145 protected static final int EXECUTION_POINT_STARTING = 0; 146 protected static final int EXECUTION_POINT_INTERMEDIATE = 1; 147 protected static final int EXECUTION_POINT_ENDING = 2; 148 149 // Set to true if all interceptors have had all their points 150 // executed. 151 protected boolean alreadyExecuted; 152 153 // Sources of request information 154 protected Connection connection; 155 protected ServiceContexts serviceContexts; 156 157 // The ForwardRequest object if this request is being forwarded. 158 // Either the forwardRequest or the forwardRequestIOR field is set. 159 // When set, the other field is set to null initially. If the other 160 // field is queried, it is lazily calculated and cached. These 161 // two attributes are always kept in sync. 162 protected ForwardRequest forwardRequest; 163 protected IOR forwardRequestIOR; 164 165 // PICurrent's SlotTable 166 protected SlotTable slotTable; 167 168 // The exception to be returned by received_exception and 169 // received_exception_id 170 protected Exception exception; 171 172 ////////////////////////////////////////////////////////////////////// 173 // 174 // NOTE: IF AN ATTRIBUTE IS ADDED, PLEASE UPDATE RESET(); 175 // 176 ////////////////////////////////////////////////////////////////////// 177 178 /** 179 * Reset the info object so that it can be reused for a retry, 180 * for example. 181 */ 182 void reset() { 183 184 // Please keep these in the same order as declared above. 185 186 flowStackIndex = 0; 187 startingPointCall = 0; 188 intermediatePointCall = 0; 189 endingPointCall = 0; 190 // 6763340 191 setReplyStatus( UNINITIALIZED ) ; 192 currentExecutionPoint = EXECUTION_POINT_STARTING; 193 alreadyExecuted = false; 194 connection = null; 195 serviceContexts = null; 196 forwardRequest = null; 197 forwardRequestIOR = null; 198 exception = null; 199 200 // We don't need to reset the Slots because they are 201 // already in the clean state after recieve_<point> interceptor 202 // are called. 203 } 204 205 /* 206 ********************************************************************** 207 * Access protection 208 **********************************************************************/ 209 210 // Method IDs for all methods in RequestInfo. This allows for a 211 // convenient O(1) lookup for checkAccess(). 212 protected static final int MID_REQUEST_ID = 0; 213 protected static final int MID_OPERATION = 1; 214 protected static final int MID_ARGUMENTS = 2; 215 protected static final int MID_EXCEPTIONS = 3; 216 protected static final int MID_CONTEXTS = 4; 217 protected static final int MID_OPERATION_CONTEXT = 5; 218 protected static final int MID_RESULT = 6; 219 protected static final int MID_RESPONSE_EXPECTED = 7; 220 protected static final int MID_SYNC_SCOPE = 8; 221 protected static final int MID_REPLY_STATUS = 9; 222 protected static final int MID_FORWARD_REFERENCE = 10; 223 protected static final int MID_GET_SLOT = 11; 224 protected static final int MID_GET_REQUEST_SERVICE_CONTEXT = 12; 225 protected static final int MID_GET_REPLY_SERVICE_CONTEXT = 13; 226 // The last value from RequestInfo (be sure to update this): 227 protected static final int MID_RI_LAST = 13; 228 229 /* 230 ********************************************************************** 231 * Public interfaces 232 **********************************************************************/ 233 234 /** 235 * Creates a new RequestInfoImpl object. 236 */ 237 public RequestInfoImpl( ORB myORB ) { 238 super(); 239 240 this.myORB = myORB; 241 wrapper = InterceptorsSystemException.get( myORB, 242 CORBALogDomains.RPC_PROTOCOL ) ; 243 stdWrapper = OMGSystemException.get( myORB, 244 CORBALogDomains.RPC_PROTOCOL ) ; 245 246 // Capture the current TSC and make it the RSC of this request. 247 PICurrent current = (PICurrent)(myORB.getPIHandler().getPICurrent()); 248 slotTable = current.getSlotTable( ); 249 } 250 251 /** 252 * Implementation for request_id() differs for client and server 253 * implementations. 254 * 255 * Uniquely identifies an active request/reply sequence. Once a 256 * request/reply sequence is concluded this ID may be reused. (this 257 * is NOT necessarily the same as the GIOP request_id). 258 */ 259 abstract public int request_id (); 260 261 /** 262 * Implementation for operation() differs for client and server 263 * implementations. 264 * 265 * The name of the operation being invoked. 266 */ 267 abstract public String operation (); 268 269 270 /** 271 * This method returns the list of arguments for the operation that was 272 * invoked. It raises NO_RESOURCES exception if the operation is not invoked 273 * by using DII mechanism. 274 */ 275 abstract public Parameter[] arguments (); 276 277 /** 278 * This method returns the list of exceptios that was raised when the 279 * operation was invoked. It raises NO_RESOURCES exception if the operation 280 * is not invoked by using DII mechanism. 281 */ 282 abstract public TypeCode[] exceptions (); 283 284 /** 285 * This method returns the list of contexts for the DII operation. 286 * It raises NO_RESOURCES exception if the operation is not invoked by 287 * using DII mechanism. 288 */ 289 abstract public String[] contexts (); 290 291 /** 292 * This method returns the list of operation_context for the DII operation. 293 * It raises NO_RESOURCES exception if the operation is not invoked by 294 * using DII mechanism. 295 */ 296 abstract public String[] operation_context (); 297 298 /** 299 * This method returns the result from the invoked DII operation. 300 * It raises NO_RESOURCES exception if the operation is not invoked by 301 * using DII mechanism. 302 */ 303 abstract public Any result (); 304 305 /** 306 * Implementation for response_expected() differs for client and server 307 * implementations. 308 * 309 * Indicates whether a response is expected. On the client, a reply is 310 * not returned when response_expected is false, so receive_reply cannot 311 * be called. receive_other is called unless an exception occurs, in 312 * which case receive_exception is called. On the client, within 313 * send_poll, this attribute is true. 314 */ 315 abstract public boolean response_expected (); 316 317 /** 318 * Defined in the Messaging specification. Pertinent only when 319 * response_expected is false. If response_expected is true, the value 320 * of sync_scope is undefined. It defines how far the request shall 321 * progress before control is returned to the client. This attribute may 322 * have one of the follwing values: 323 * <ul> 324 * <li>Messaging::SYNC_NONE</li> 325 * <li>Messaging::SYNC_WITH_TRANSPORT</li> 326 * <li>Messaging::SYNC_WITH_SERVER</li> 327 * <li>Messaging::SYNC_WITH_TARGET</li> 328 * </ul> 329 */ 330 public short sync_scope (){ 331 checkAccess( MID_SYNC_SCOPE ); 332 return SYNC_WITH_TRANSPORT.value; // REVISIT - get from MessageMediator 333 } 334 335 /** 336 * Describes the state of the result of the operation invocation. Its 337 * value can be one of the following: 338 * <ul> 339 * <li>PortableInterceptor::SUCCESSFUL</li> 340 * <li>PortableInterceptor::SYSTEM_EXCEPTION</li> 341 * <li>PortableInterceptor::USER_EXCEPTION</li> 342 * <li>PortableInterceptor::LOCATION_FORWARD</li> 343 * <li>PortableInterceptor::TRANSPORT_RETRY</li> 344 * </ul> 345 */ 346 public short reply_status (){ 347 checkAccess( MID_REPLY_STATUS ); 348 return replyStatus; 349 } 350 351 /** 352 * Implementation for forward_reference() differs for client and server 353 * implementations. 354 * 355 * If the reply_status attribute is LOCATION_FORWARD 356 * then this attribute will contain the object 357 * to which the request will be forwarded. It is indeterminate whether a 358 * forwarded request will actually occur. 359 */ 360 abstract public Object forward_reference (); 361 362 363 /** 364 * Returns the data from the given slot of the PortableInterceptor::Current 365 * that is in the scope of the request. 366 * <p> 367 * If the given slot has not been set, then an any containing a type code 368 * with a TCKind value of tk_null is returned. 369 * <p> 370 * If the ID does not define an allocated slot, InvalidSlot is raised. 371 */ 372 public Any get_slot (int id) 373 throws InvalidSlot 374 { 375 // access is currently valid for all states: 376 //checkAccess( MID_GET_SLOT ); 377 // Delegate the call to the slotTable which was set when RequestInfo was 378 // created. 379 return slotTable.get_slot( id ); 380 } 381 382 /** 383 * Implementation for get_request_service_context() differs for client 384 * and server implementations. 385 * 386 * This operation returns a copy of the service context with the given ID 387 * that is associated with the request. If the request's service context 388 * does not contain an etry for that ID, BAD_PARAM with a minor code of 389 * TBD_BP is raised. 390 */ 391 abstract public org.omg.IOP.ServiceContext 392 get_request_service_context(int id); 393 394 /** 395 * Implementation for get_reply_service_context() differs for client 396 * and server implementations. 397 * 398 * This operation returns a copy of the service context with the given ID 399 * that is associated with the reply. IF the request's service context 400 * does not contain an entry for that ID, BAD_PARAM with a minor code of 401 * TBD_BP is raised. 402 */ 403 abstract public org.omg.IOP.ServiceContext 404 get_reply_service_context (int id); 405 406 407 // NOTE: When adding a method, be sure to: 408 // 1. Add a MID_* constant for that method 409 // 2. Call checkAccess at the start of the method 410 // 3. Define entries in the validCall[][] table for interception points 411 // in both ClientRequestInfoImpl and ServerRequestInfoImpl. 412 413 414 415 /* 416 ********************************************************************** 417 * Proprietary methods 418 **********************************************************************/ 419 420 /** 421 * @return The connection on which the request is made. 422 * 423 * Note: we store the connection as an internal type but 424 * expose it here as an external type. 425 */ 426 public com.sun.corba.se.spi.legacy.connection.Connection connection() 427 { 428 return connection; 429 } 430 431 /* 432 ********************************************************************** 433 * Private utility methods 434 **********************************************************************/ 435 436 /** 437 * Inserts the UserException inside the given ApplicationException 438 * into the given Any. Throws an UNKNOWN with minor code 439 * OMGSYstemException.UNKNOWN_USER_EXCEPTION if the Helper class could not be 440 * found to insert it with. 441 */ 442 private void insertApplicationException( ApplicationException appException, 443 Any result ) 444 throws UNKNOWN 445 { 446 try { 447 // Extract the UserException from the ApplicationException. 448 // Look up class name from repository id: 449 RepositoryId repId = RepositoryId.cache.getId( 450 appException.getId() ); 451 String className = repId.getClassName(); 452 453 // Find the read method on the helper class: 454 String helperClassName = className + "Helper"; 455 Class helperClass = ORBClassLoader.loadClass( helperClassName ); 456 Class[] readParams = new Class[1]; 457 readParams[0] = org.omg.CORBA.portable.InputStream.class; 458 Method readMethod = helperClass.getMethod( "read", readParams ); 459 460 // Invoke the read method, passing in the input stream to 461 // retrieve the user exception. Mark and reset the stream 462 // as to not disturb it. 463 InputStream ueInputStream = appException.getInputStream(); 464 ueInputStream.mark( 0 ); 465 UserException userException = null; 466 try { 467 java.lang.Object[] readArguments = new java.lang.Object[1]; 468 readArguments[0] = ueInputStream; 469 userException = (UserException)readMethod.invoke( 470 null, readArguments ); 471 } 472 finally { 473 try { 474 ueInputStream.reset(); 475 } 476 catch( IOException e ) { 477 throw wrapper.markAndResetFailed( e ) ; 478 } 479 } 480 481 // Insert this UserException into the provided Any using the 482 // helper class. 483 insertUserException( userException, result ); 484 } catch( ClassNotFoundException e ) { 485 throw stdWrapper.unknownUserException( CompletionStatus.COMPLETED_MAYBE, e ) ; 486 } catch( NoSuchMethodException e ) { 487 throw stdWrapper.unknownUserException( CompletionStatus.COMPLETED_MAYBE, e ) ; 488 } catch( SecurityException e ) { 489 throw stdWrapper.unknownUserException( CompletionStatus.COMPLETED_MAYBE, e ) ; 490 } catch( IllegalAccessException e ) { 491 throw stdWrapper.unknownUserException( CompletionStatus.COMPLETED_MAYBE, e ) ; 492 } catch( IllegalArgumentException e ) { 493 throw stdWrapper.unknownUserException( CompletionStatus.COMPLETED_MAYBE, e ) ; 494 } catch( InvocationTargetException e ) { 495 throw stdWrapper.unknownUserException( CompletionStatus.COMPLETED_MAYBE, e ) ; 496 } 497 } 498 499 /** 500 * Inserts the UserException into the given Any. 501 * Throws an UNKNOWN with minor code 502 * OMGSYstemException.UNKNOWN_USER_EXCEPTION if the Helper class could not be 503 * found to insert it with. 504 */ 505 private void insertUserException( UserException userException, Any result ) 506 throws UNKNOWN 507 { 508 try { 509 // Insert this UserException into the provided Any using the 510 // helper class. 511 if( userException != null ) { 512 Class exceptionClass = userException.getClass(); 513 String className = exceptionClass.getName(); 514 String helperClassName = className + "Helper"; 515 Class helperClass = ORBClassLoader.loadClass( helperClassName ); 516 517 // Find insert( Any, class ) method 518 Class[] insertMethodParams = new Class[2]; 519 insertMethodParams[0] = org.omg.CORBA.Any.class; 520 insertMethodParams[1] = exceptionClass; 521 Method insertMethod = helperClass.getMethod( 522 "insert", insertMethodParams ); 523 524 // Call helper.insert( result, userException ): 525 java.lang.Object[] insertMethodArguments = 526 new java.lang.Object[2]; 527 insertMethodArguments[0] = result; 528 insertMethodArguments[1] = userException; 529 insertMethod.invoke( null, insertMethodArguments ); 530 } 531 } catch( ClassNotFoundException e ) { 532 throw stdWrapper.unknownUserException( CompletionStatus.COMPLETED_MAYBE, e ); 533 } catch( NoSuchMethodException e ) { 534 throw stdWrapper.unknownUserException( CompletionStatus.COMPLETED_MAYBE, e ); 535 } catch( SecurityException e ) { 536 throw stdWrapper.unknownUserException( CompletionStatus.COMPLETED_MAYBE, e ); 537 } catch( IllegalAccessException e ) { 538 throw stdWrapper.unknownUserException( CompletionStatus.COMPLETED_MAYBE, e ); 539 } catch( IllegalArgumentException e ) { 540 throw stdWrapper.unknownUserException( CompletionStatus.COMPLETED_MAYBE, e ); 541 } catch( InvocationTargetException e ) { 542 throw stdWrapper.unknownUserException( CompletionStatus.COMPLETED_MAYBE, e ); 543 } 544 } 545 546 /* 547 ********************************************************************** 548 * Protected utility methods 549 **********************************************************************/ 550 551 /** 552 * Internal utility method to convert an NVList into a PI Parameter[] 553 */ 554 protected Parameter[] nvListToParameterArray( NVList parNVList ) { 555 556 // _REVISIT_ This utility method should probably be doing a deep 557 // copy so interceptor can't accidentally change the arguments. 558 559 int count = parNVList.count(); 560 Parameter[] plist = new Parameter[count]; 561 try { 562 for( int i = 0; i < count; i++ ) { 563 Parameter p = new Parameter(); 564 plist[i] = p; 565 NamedValue nv = parNVList.item( i ); 566 plist[i].argument = nv.value(); 567 // ParameterMode spec can be found in 99-10-07.pdf 568 // Section:10.5.22 569 // nv.flags spec can be found in 99-10-07.pdf 570 // Section 7.1.1 571 // nv.flags has ARG_IN as 1, ARG_OUT as 2 and ARG_INOUT as 3 572 // To convert this into enum PARAM_IN, PARAM_OUT and 573 // PARAM_INOUT the value is subtracted by 1. 574 plist[i].mode = ParameterMode.from_int( nv.flags() - 1 ); 575 } 576 } catch ( Exception e ) { 577 throw wrapper.exceptionInArguments( e ) ; 578 } 579 580 return plist; 581 } 582 583 /** 584 * Utility to wrap the given Exception in an Any object and return it. 585 * If the exception is a UserException which cannot be inserted into 586 * an any, then this returns an Any containing the system exception 587 * UNKNOWN. 588 */ 589 protected Any exceptionToAny( Exception exception ){ 590 Any result = myORB.create_any(); 591 592 if( exception == null ) { 593 // Note: exception should never be null here since we will throw 594 // a BAD_INV_ORDER if this is not called from receive_exception. 595 throw wrapper.exceptionWasNull2() ; 596 } else if( exception instanceof SystemException ) { 597 ORBUtility.insertSystemException( 598 (SystemException)exception, result ); 599 } else if( exception instanceof ApplicationException ) { 600 // Use the Helper class for this exception to insert it into an 601 // Any. 602 try { 603 // Insert the user exception inside the application exception 604 // into the Any result: 605 ApplicationException appException = 606 (ApplicationException)exception; 607 insertApplicationException( appException, result ); 608 } catch( UNKNOWN e ) { 609 // As per ptc/00-08-06, 21.3.13.4. if we cannot find the 610 // appropriate class, then return an any containing UNKNOWN, 611 // with a minor code of 1. This is conveniently the same 612 // exception that is returned from the 613 // insertApplicationException utility method. 614 ORBUtility.insertSystemException( e, result ); 615 } 616 } else if( exception instanceof UserException ) { 617 try { 618 UserException userException = (UserException)exception; 619 insertUserException( userException, result ); 620 } catch( UNKNOWN e ) { 621 ORBUtility.insertSystemException( e, result ); 622 } 623 } 624 625 626 return result; 627 } 628 629 /** 630 * Utility method to look up a service context with the given id and 631 * convert it to an IOP.ServiceContext. Uses the given HashMap as 632 * a cache. If not found in cache, the result is inserted in the cache. 633 */ 634 protected org.omg.IOP.ServiceContext 635 getServiceContext ( HashMap cachedServiceContexts, 636 ServiceContexts serviceContexts, int id ) 637 { 638 org.omg.IOP.ServiceContext result = null; 639 Integer integerId = new Integer( id ); 640 641 // Search cache first: 642 result = (org.omg.IOP.ServiceContext) 643 cachedServiceContexts.get( integerId ); 644 645 // null could normally mean that either we cached the value null 646 // or it's not in the cache. However, there is no way for us to 647 // cache the value null in the following code. 648 if( result == null ) { 649 // Not in cache. Find it and put in cache. 650 // Get the desired "core" service context. 651 com.sun.corba.se.spi.servicecontext.ServiceContext context = 652 serviceContexts.get( id ); 653 if (context == null) 654 throw stdWrapper.invalidServiceContextId() ; 655 656 // Convert the "core" service context to an 657 // "IOP" ServiceContext by writing it to a 658 // CDROutputStream and reading it back. 659 EncapsOutputStream out = new EncapsOutputStream(myORB); 660 661 context.write( out, GIOPVersion.V1_2 ); 662 InputStream inputStream = out.create_input_stream(); 663 result = ServiceContextHelper.read( inputStream ); 664 665 cachedServiceContexts.put( integerId, result ); 666 } 667 668 // Good citizen: For increased efficiency, we assume that interceptors 669 // will not modify the returned ServiceContext. Otherwise, we would 670 // have to make a deep copy. 671 672 return result; 673 } 674 675 676 /** 677 * Utility method to add an IOP.ServiceContext to a core.ServiceContexts 678 * object. If replace is true, any service context with the given id 679 * is replaced. 680 * <p> 681 * Raises BAD_INV_ORDER if replace is false and a service context with 682 * the given id already exists. 683 * <p> 684 * Uses the given HashMap as a cache. If a service context is placed 685 * in the container, it goes in the HashMap as well. 686 */ 687 protected void addServiceContext( 688 HashMap cachedServiceContexts, 689 ServiceContexts serviceContexts, 690 org.omg.IOP.ServiceContext service_context, 691 boolean replace ) 692 { 693 int id = 0 ; 694 // Convert IOP.service_context to core.ServiceContext: 695 EncapsOutputStream outputStream = new EncapsOutputStream( 696 myORB ); 697 InputStream inputStream = null; 698 UnknownServiceContext coreServiceContext = null; 699 ServiceContextHelper.write( outputStream, service_context ); 700 inputStream = outputStream.create_input_stream(); 701 702 // Constructor expects id to already have been read from stream. 703 coreServiceContext = new UnknownServiceContext( 704 inputStream.read_long(), 705 (org.omg.CORBA_2_3.portable.InputStream)inputStream ); 706 707 id = coreServiceContext.getId(); 708 709 if (serviceContexts.get(id) != null) 710 if (replace) 711 serviceContexts.delete( id ); 712 else 713 throw stdWrapper.serviceContextAddFailed( new Integer(id) ) ; 714 715 serviceContexts.put( coreServiceContext ); 716 717 // Place IOP.ServiceContext in cache as well: 718 cachedServiceContexts.put( new Integer( id ), service_context ); 719 } 720 721 /** 722 * Sets the number of interceptors whose starting interception 723 * points were successfully invoked on this client call. As specified 724 * in orbos/99-12-02, section 5.2.1., not all interceptors will 725 * be invoked if a ForwardRequest exception or a system exception 726 * is raised. This keeps track of how many were successfully executed 727 * so we know not to execute the corresponding ending interception 728 * points for the interceptors whose starting interception points 729 * were not completed. This simulates the "Flow Stack Visual Model" 730 * presented in section 5.1.3.*/ 731 protected void setFlowStackIndex(int num ) { 732 this.flowStackIndex = num; 733 } 734 735 /** 736 * Returns the number of interceptors whose starting interception 737 * points were actually invoked on this client request. See 738 * setFlowStackIndex for more details. 739 */ 740 protected int getFlowStackIndex() { 741 return this.flowStackIndex; 742 } 743 744 /** 745 * Sets which ending interception point should be called 746 * for each interceptor in the virtual flow stack. 747 */ 748 protected void setEndingPointCall( int call ) { 749 this.endingPointCall = call; 750 } 751 752 /** 753 * Retrieves the current ending point call type (see 754 * setEndingPointCall for more details). 755 */ 756 protected int getEndingPointCall() { 757 return this.endingPointCall; 758 } 759 760 /** 761 * Sets which intermediate interception point should be called 762 * for each interceptor in the virtual flow stack. 763 */ 764 protected void setIntermediatePointCall( int call ) { 765 this.intermediatePointCall = call; 766 } 767 768 /** 769 * Retrieves the current intermediate point call type (see 770 * setEndingPointCall for more details). 771 */ 772 protected int getIntermediatePointCall() { 773 return this.intermediatePointCall; 774 } 775 776 /** 777 * Sets which starting interception point should be called 778 * for each interceptor in the virtual flow stack. 779 */ 780 protected void setStartingPointCall( int call ) { 781 this.startingPointCall = call; 782 } 783 784 /** 785 * Retrieves the current starting point call type (see 786 * setStartingPointCall for more details). 787 */ 788 protected int getStartingPointCall() { 789 return this.startingPointCall; 790 } 791 792 /** 793 * Returns true if all interceptors' starting and ending points 794 * have already executed to completion, or false if not yet. 795 */ 796 protected boolean getAlreadyExecuted() { 797 return this.alreadyExecuted; 798 } 799 800 /** 801 * Sets whether all interceotrs' starting and ending points 802 * have already been executed to completion. 803 */ 804 protected void setAlreadyExecuted( boolean alreadyExecuted ) { 805 this.alreadyExecuted = alreadyExecuted; 806 } 807 808 /** 809 * Sets the value to be returned by reply_status 810 */ 811 protected void setReplyStatus( short replyStatus ) { 812 this.replyStatus = replyStatus; 813 } 814 815 /** 816 * Gets the current reply_status without doing an access check 817 * (available only to package and subclasses) 818 */ 819 protected short getReplyStatus() { 820 return this.replyStatus; 821 } 822 823 /** 824 * Stores the given ForwardRequest object for later analysis. 825 * This version supplements setForwardRequest( IOR ); 826 */ 827 protected void setForwardRequest( ForwardRequest forwardRequest ) { 828 this.forwardRequest = forwardRequest; 829 this.forwardRequestIOR = null; 830 } 831 832 /** 833 * Stores the given IOR for later forward request analysis. 834 * This version supplements setForwardRequest( ForwardRequest ); 835 */ 836 protected void setForwardRequest( IOR ior ) { 837 this.forwardRequestIOR = ior; 838 this.forwardRequest = null; 839 } 840 841 /** 842 * Retrieves the ForwardRequest object as a ForwardRequest exception. 843 */ 844 protected ForwardRequest getForwardRequestException() { 845 if( this.forwardRequest == null ) { 846 if( this.forwardRequestIOR != null ) { 847 // Convert the internal IOR to a forward request exception 848 // by creating an object reference. 849 org.omg.CORBA.Object obj = iorToObject(this.forwardRequestIOR); 850 this.forwardRequest = new ForwardRequest( obj ); 851 } 852 } 853 854 return this.forwardRequest; 855 } 856 857 /** 858 * Retrieves the IOR of the ForwardRequest exception. 859 */ 860 protected IOR getForwardRequestIOR() { 861 if( this.forwardRequestIOR == null ) { 862 if( this.forwardRequest != null ) { 863 this.forwardRequestIOR = ORBUtility.getIOR( 864 this.forwardRequest.forward ) ; 865 } 866 } 867 868 return this.forwardRequestIOR; 869 } 870 871 /** 872 * Sets the exception to be returned by received_exception and 873 * received_exception_id. 874 */ 875 protected void setException( Exception exception ) { 876 this.exception = exception; 877 } 878 879 /** 880 * Returns the exception to be returned by received_exception and 881 * received_exception_id. 882 */ 883 Exception getException() { 884 return this.exception; 885 } 886 887 /** 888 * Sets the execution point that we are currently executing 889 * (starting points, intermediate points, or ending points). 890 * This allows us to enforce the validity table. 891 */ 892 protected void setCurrentExecutionPoint( int executionPoint ) { 893 this.currentExecutionPoint = executionPoint; 894 } 895 896 /** 897 * Check whether the caller is allowed to access this method at 898 * this particular time. This is overridden in subclasses to implement 899 * the validity table specified in ptc/00-04-05, table 21-1 and 21-2. 900 * The currentExecutionPoint attribute is checked, and if access is 901 * forbidden at this time, BAD_INV_ORDER is raised with a minor code of 902 * TBD_BIO. 903 * 904 * @param methodID The ID of this method, one of the MID_* constants. 905 * This allows us to easily look up the method access in a table. 906 * Note that method ids may overlap between subclasses. 907 */ 908 protected abstract void checkAccess( int methodID ) 909 throws BAD_INV_ORDER; 910 911 /** 912 * The server side does an explicit set rather than taking the 913 * current PICurrent table as is done in the general RequestInfoImpl 914 * constructor. 915 */ 916 void setSlotTable(SlotTable slotTable) 917 { 918 this.slotTable = slotTable; 919 } 920 921 protected org.omg.CORBA.Object iorToObject( IOR ior ) 922 { 923 return ORBUtility.makeObjectReference( ior ) ; 924 } 925 }