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