1 /* 2 * Copyright (c) 2002, 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 package com.sun.corba.se.impl.interceptors; 26 27 import java.util.*; 28 import java.io.IOException; 29 30 import org.omg.CORBA.Any; 31 import org.omg.CORBA.BAD_PARAM; 32 import org.omg.CORBA.BAD_POLICY; 33 import org.omg.CORBA.BAD_INV_ORDER; 34 import org.omg.CORBA.COMM_FAILURE; 35 import org.omg.CORBA.CompletionStatus; 36 import org.omg.CORBA.INTERNAL; 37 import org.omg.CORBA.NVList; 38 import org.omg.CORBA.OBJECT_NOT_EXIST; 39 import org.omg.CORBA.ORBPackage.InvalidName; 40 import org.omg.CORBA.SystemException; 41 import org.omg.CORBA.UserException; 42 import org.omg.CORBA.UNKNOWN; 43 44 import org.omg.CORBA.portable.ApplicationException; 45 import org.omg.CORBA.portable.RemarshalException; 46 47 import org.omg.IOP.CodecFactory; 48 49 import org.omg.PortableInterceptor.ForwardRequest; 50 import org.omg.PortableInterceptor.Current; 51 import org.omg.PortableInterceptor.Interceptor; 52 import org.omg.PortableInterceptor.LOCATION_FORWARD; 53 import org.omg.PortableInterceptor.ORBInitializer; 54 import org.omg.PortableInterceptor.ORBInitInfo; 55 import org.omg.PortableInterceptor.ORBInitInfoPackage.DuplicateName; 56 import org.omg.PortableInterceptor.SUCCESSFUL; 57 import org.omg.PortableInterceptor.SYSTEM_EXCEPTION; 58 import org.omg.PortableInterceptor.TRANSPORT_RETRY; 59 import org.omg.PortableInterceptor.USER_EXCEPTION; 60 import org.omg.PortableInterceptor.PolicyFactory; 61 import org.omg.PortableInterceptor.ObjectReferenceTemplate; 62 63 import com.sun.corba.se.pept.encoding.OutputObject; 64 65 import com.sun.corba.se.spi.ior.IOR; 66 import com.sun.corba.se.spi.ior.ObjectKeyTemplate; 67 import com.sun.corba.se.spi.oa.ObjectAdapter; 68 import com.sun.corba.se.spi.orb.ORB; 69 import com.sun.corba.se.spi.orbutil.closure.ClosureFactory; 70 import com.sun.corba.se.spi.protocol.CorbaMessageMediator; 71 import com.sun.corba.se.spi.protocol.ForwardException; 72 import com.sun.corba.se.spi.protocol.PIHandler; 73 import com.sun.corba.se.spi.protocol.RetryType; 74 import com.sun.corba.se.spi.logging.CORBALogDomains; 75 76 import com.sun.corba.se.impl.logging.InterceptorsSystemException; 77 import com.sun.corba.se.impl.logging.ORBUtilSystemException; 78 import com.sun.corba.se.impl.logging.OMGSystemException; 79 import com.sun.corba.se.impl.corba.RequestImpl; 80 import com.sun.corba.se.impl.orbutil.ORBClassLoader; 81 import com.sun.corba.se.impl.orbutil.ORBConstants; 82 import com.sun.corba.se.impl.orbutil.ORBUtility; 83 import com.sun.corba.se.impl.orbutil.StackImpl; 84 import com.sun.corba.se.impl.protocol.giopmsgheaders.ReplyMessage; 85 86 /** 87 * Provides portable interceptor functionality. 88 */ 89 public class PIHandlerImpl implements PIHandler 90 { 91 // REVISIT - delete these after framework merging. 92 boolean printPushPopEnabled = false; 93 int pushLevel = 0; 94 private void printPush() 95 { 96 if (! printPushPopEnabled) return; 97 printSpaces(pushLevel); 98 pushLevel++; 99 System.out.println("PUSH"); 100 } 101 private void printPop() 102 { 103 if (! printPushPopEnabled) return; 104 pushLevel--; 105 printSpaces(pushLevel); 106 System.out.println("POP"); 107 } 108 private void printSpaces(int n) 109 { 110 for (int i = 0; i < n; i++) { 111 System.out.print(" "); 112 } 113 } 114 115 private ORB orb; 116 InterceptorsSystemException wrapper; 117 ORBUtilSystemException orbutilWrapper; 118 OMGSystemException omgWrapper; 119 120 // A unique id used in ServerRequestInfo. 121 // This does not correspond to the GIOP request id. 122 private int serverRequestIdCounter = 0; 123 124 // Stores the codec factory for producing codecs 125 CodecFactory codecFactory = null; 126 127 // The arguments passed to the application's main method. May be null. 128 // This is used for ORBInitializers and set from set_parameters. 129 String[] arguments = null; 130 131 // The list of portable interceptors, organized by type: 132 private InterceptorList interceptorList; 133 134 // Cached information for optimization - do we have any interceptors 135 // registered of the given types? Set during ORB initialization. 136 private boolean hasIORInterceptors; 137 private boolean hasClientInterceptors; // temp always true 138 private boolean hasServerInterceptors; 139 140 // The class responsible for invoking interceptors 141 private InterceptorInvoker interceptorInvoker; 142 143 // There will be one PICurrent instantiated for every ORB. 144 private PICurrent current; 145 146 // This table contains a list of PolicyFactories registered using 147 // ORBInitInfo.registerPolicyFactory() method. 148 // Key for the table is PolicyType which is an Integer 149 // Value is PolicyFactory. 150 private HashMap policyFactoryTable; 151 152 // Table to convert from a ReplyMessage.? to a PI replyStatus short. 153 // Note that this table relies on the order and constants of 154 // ReplyMessage not to change. 155 private final static short REPLY_MESSAGE_TO_PI_REPLY_STATUS[] = { 156 SUCCESSFUL.value, // = ReplyMessage.NO_EXCEPTION 157 USER_EXCEPTION.value, // = ReplyMessage.USER_EXCEPTION 158 SYSTEM_EXCEPTION.value, // = ReplyMessage.SYSTEM_EXCEPTION 159 LOCATION_FORWARD.value, // = ReplyMessage.LOCATION_FORWARD 160 LOCATION_FORWARD.value, // = ReplyMessage.LOCATION_FORWARD_PERM 161 TRANSPORT_RETRY.value // = ReplyMessage.NEEDS_ADDRESSING_MODE 162 }; 163 164 // ThreadLocal containing a stack to store client request info objects 165 // and a disable count. 166 private ThreadLocal threadLocalClientRequestInfoStack = 167 new ThreadLocal() { 168 protected Object initialValue() { 169 return new RequestInfoStack(); 170 } 171 }; 172 173 // ThreadLocal containing the current server request info object. 174 private ThreadLocal threadLocalServerRequestInfoStack = 175 new ThreadLocal() { 176 protected Object initialValue() { 177 return new RequestInfoStack(); 178 } 179 }; 180 181 public void close() { 182 orb = null; 183 wrapper = null; 184 orbutilWrapper = null; 185 omgWrapper = null; 186 codecFactory = null; 187 arguments = null; 188 interceptorList = null; 189 interceptorInvoker = null; 190 current = null; 191 policyFactoryTable = null; 192 threadLocalClientRequestInfoStack = null; 193 threadLocalServerRequestInfoStack = null; 194 } 195 196 // Class to contain all ThreadLocal data for ClientRequestInfo 197 // maintenance. 198 // 199 // We use an ArrayList instead since it is not thread-safe. 200 // RequestInfoStack is used quite frequently. 201 private final class RequestInfoStack extends Stack { 202 // Number of times a request has been made to disable interceptors. 203 // When this reaches 0, interception hooks are disabled. Any higher 204 // value indicates they are enabled. 205 // NOTE: The is only currently used on the client side. 206 public int disableCount = 0; 207 } 208 209 public PIHandlerImpl( ORB orb, String[] args ) { 210 this.orb = orb ; 211 wrapper = InterceptorsSystemException.get( orb, 212 CORBALogDomains.RPC_PROTOCOL ) ; 213 orbutilWrapper = ORBUtilSystemException.get( orb, 214 CORBALogDomains.RPC_PROTOCOL ) ; 215 omgWrapper = OMGSystemException.get( orb, 216 CORBALogDomains.RPC_PROTOCOL ) ; 217 arguments = args ; 218 219 // Create codec factory: 220 codecFactory = new CodecFactoryImpl( orb ); 221 222 // Create new interceptor list: 223 interceptorList = new InterceptorList( wrapper ); 224 225 // Create a new PICurrent. 226 current = new PICurrent( orb ); 227 228 // Create new interceptor invoker, initially disabled: 229 interceptorInvoker = new InterceptorInvoker( orb, interceptorList, 230 current ); 231 232 // Register the PI current and Codec factory objects 233 orb.getLocalResolver().register( ORBConstants.PI_CURRENT_NAME, 234 ClosureFactory.makeConstant( current ) ) ; 235 orb.getLocalResolver().register( ORBConstants.CODEC_FACTORY_NAME, 236 ClosureFactory.makeConstant( codecFactory ) ) ; 237 } 238 239 public void initialize() { 240 // If we have any orb initializers, make use of them: 241 if( orb.getORBData().getORBInitializers() != null ) { 242 // Create the ORBInitInfo object to pass to ORB intializers: 243 ORBInitInfoImpl orbInitInfo = createORBInitInfo(); 244 245 // Make sure get_slot and set_slot are not called from within 246 // ORB initializers: 247 current.setORBInitializing( true ); 248 249 // Call pre_init on all ORB initializers: 250 preInitORBInitializers( orbInitInfo ); 251 252 // Call post_init on all ORB initializers: 253 postInitORBInitializers( orbInitInfo ); 254 255 // Proprietary: sort interceptors: 256 interceptorList.sortInterceptors(); 257 258 // Re-enable get_slot and set_slot to be called from within 259 // ORB initializers: 260 current.setORBInitializing( false ); 261 262 // Ensure nobody makes any more calls on this object. 263 orbInitInfo.setStage( ORBInitInfoImpl.STAGE_CLOSED ); 264 265 // Set cached flags indicating whether we have interceptors 266 // registered of a given type. 267 hasIORInterceptors = interceptorList.hasInterceptorsOfType( 268 InterceptorList.INTERCEPTOR_TYPE_IOR ); 269 // XXX This must always be true, so that using the new generic 270 // RPC framework can pass info between the PI stack and the 271 // framework invocation stack. Temporary until Harold fixes 272 // this. Note that this must never be true until after the 273 // ORBInitializer instances complete executing. 274 //hasClientInterceptors = interceptorList.hasInterceptorsOfType( 275 //InterceptorList.INTERCEPTOR_TYPE_CLIENT ); 276 hasClientInterceptors = true; 277 hasServerInterceptors = interceptorList.hasInterceptorsOfType( 278 InterceptorList.INTERCEPTOR_TYPE_SERVER ); 279 280 // Enable interceptor invoker (not necessary if no interceptors 281 // are registered). This should be the last stage of ORB 282 // initialization. 283 interceptorInvoker.setEnabled( true ); 284 } 285 } 286 287 /** 288 * ptc/00-08-06 p 205: "When an application calls ORB::destroy, the ORB 289 * 1) waits for all requests in progress to complete 290 * 2) calls the Interceptor::destroy operation for each interceptor 291 * 3) completes destruction of the ORB" 292 * 293 * This must be called at the end of ORB.destroy. Note that this is not 294 * part of the PIHandler interface, since ORBImpl implements the ORB interface. 295 */ 296 public void destroyInterceptors() { 297 interceptorList.destroyAll(); 298 } 299 300 public void objectAdapterCreated( ObjectAdapter oa ) 301 { 302 if (!hasIORInterceptors) 303 return ; 304 305 interceptorInvoker.objectAdapterCreated( oa ) ; 306 } 307 308 public void adapterManagerStateChanged( int managerId, 309 short newState ) 310 { 311 if (!hasIORInterceptors) 312 return ; 313 314 interceptorInvoker.adapterManagerStateChanged( managerId, newState ) ; 315 } 316 317 public void adapterStateChanged( ObjectReferenceTemplate[] 318 templates, short newState ) 319 { 320 if (!hasIORInterceptors) 321 return ; 322 323 interceptorInvoker.adapterStateChanged( templates, newState ) ; 324 } 325 326 /* 327 ***************** 328 * Client PI hooks 329 *****************/ 330 331 public void disableInterceptorsThisThread() { 332 if( !hasClientInterceptors ) return; 333 334 RequestInfoStack infoStack = 335 (RequestInfoStack)threadLocalClientRequestInfoStack.get(); 336 infoStack.disableCount++; 337 } 338 339 public void enableInterceptorsThisThread() { 340 if( !hasClientInterceptors ) return; 341 342 RequestInfoStack infoStack = 343 (RequestInfoStack)threadLocalClientRequestInfoStack.get(); 344 infoStack.disableCount--; 345 } 346 347 public void invokeClientPIStartingPoint() 348 throws RemarshalException 349 { 350 if( !hasClientInterceptors ) return; 351 if( !isClientPIEnabledForThisThread() ) return; 352 353 // Invoke the starting interception points and record exception 354 // and reply status info in the info object: 355 ClientRequestInfoImpl info = peekClientRequestInfoImplStack(); 356 interceptorInvoker.invokeClientInterceptorStartingPoint( info ); 357 358 // Check reply status. If we will not have another chance later 359 // to invoke the client ending points, do it now. 360 short replyStatus = info.getReplyStatus(); 361 if( (replyStatus == SYSTEM_EXCEPTION.value) || 362 (replyStatus == LOCATION_FORWARD.value) ) 363 { 364 // Note: Transport retry cannot happen here since this happens 365 // before the request hits the wire. 366 367 Exception exception = invokeClientPIEndingPoint( 368 convertPIReplyStatusToReplyMessage( replyStatus ), 369 info.getException() ); 370 if( exception == null ) { 371 // Do not throw anything. Otherwise, it must be a 372 // SystemException, UserException or RemarshalException. 373 } if( exception instanceof SystemException ) { 374 throw (SystemException)exception; 375 } else if( exception instanceof RemarshalException ) { 376 throw (RemarshalException)exception; 377 } else if( (exception instanceof UserException) || 378 (exception instanceof ApplicationException) ) { 379 // It should not be possible for an interceptor to throw 380 // a UserException. By asserting instead of throwing the 381 // UserException, we need not declare anything but 382 // RemarshalException in the throws clause. 383 throw wrapper.exceptionInvalid() ; 384 } 385 } 386 else if( replyStatus != ClientRequestInfoImpl.UNINITIALIZED ) { 387 throw wrapper.replyStatusNotInit() ; 388 } 389 } 390 391 // Needed when an error forces a retry AFTER initiateClientPIRequest 392 // but BEFORE invokeClientPIStartingPoint. 393 public Exception makeCompletedClientRequest( int replyStatus, 394 Exception exception ) { 395 396 // 6763340 397 return handleClientPIEndingPoint( replyStatus, exception, false ) ; 398 } 399 400 public Exception invokeClientPIEndingPoint( int replyStatus, 401 Exception exception ) { 402 403 // 6763340 404 return handleClientPIEndingPoint( replyStatus, exception, true ) ; 405 } 406 407 public Exception handleClientPIEndingPoint( 408 int replyStatus, Exception exception, boolean invokeEndingPoint ) { 409 if( !hasClientInterceptors ) return exception; 410 if( !isClientPIEnabledForThisThread() ) return exception; 411 412 // Translate ReplyMessage.replyStatus into PI replyStatus: 413 // Note: this is also an assertion to make sure a valid replyStatus 414 // is passed in (IndexOutOfBoundsException will be thrown otherwise) 415 short piReplyStatus = REPLY_MESSAGE_TO_PI_REPLY_STATUS[replyStatus]; 416 417 // Invoke the ending interception points and record exception 418 // and reply status info in the info object: 419 ClientRequestInfoImpl info = peekClientRequestInfoImplStack(); 420 info.setReplyStatus( piReplyStatus ); 421 info.setException( exception ); 422 423 if (invokeEndingPoint) { 424 // 6763340 425 interceptorInvoker.invokeClientInterceptorEndingPoint( info ); 426 piReplyStatus = info.getReplyStatus(); 427 } 428 429 // Check reply status: 430 if( (piReplyStatus == LOCATION_FORWARD.value) || 431 (piReplyStatus == TRANSPORT_RETRY.value) ) { 432 // If this is a forward or a retry, reset and reuse 433 // info object: 434 info.reset(); 435 436 // fix for 6763340: 437 if (invokeEndingPoint) { 438 info.setRetryRequest( RetryType.AFTER_RESPONSE ) ; 439 } else { 440 info.setRetryRequest( RetryType.BEFORE_RESPONSE ) ; 441 } 442 443 // ... and return a RemarshalException so the orb internals know 444 exception = new RemarshalException(); 445 } else if( (piReplyStatus == SYSTEM_EXCEPTION.value) || 446 (piReplyStatus == USER_EXCEPTION.value) ) { 447 exception = info.getException(); 448 } 449 450 return exception; 451 } 452 453 public void initiateClientPIRequest( boolean diiRequest ) { 454 if( !hasClientInterceptors ) return; 455 if( !isClientPIEnabledForThisThread() ) return; 456 457 // Get the most recent info object from the thread local 458 // ClientRequestInfoImpl stack: 459 RequestInfoStack infoStack = 460 (RequestInfoStack)threadLocalClientRequestInfoStack.get(); 461 ClientRequestInfoImpl info = null; 462 463 if (!infoStack.empty() ) { 464 info = (ClientRequestInfoImpl)infoStack.peek(); 465 } 466 467 if (!diiRequest && (info != null) && info.isDIIInitiate() ) { 468 // In RequestImpl.doInvocation we already called 469 // initiateClientPIRequest( true ), so ignore this initiate. 470 info.setDIIInitiate( false ); 471 } else { 472 // If there is no info object or if we are not retrying a request, 473 // push a new ClientRequestInfoImpl on the stack: 474 475 // 6763340: don't push unless this is not a retry 476 if( (info == null) || !info.getRetryRequest().isRetry() ) { 477 info = new ClientRequestInfoImpl( orb ); 478 infoStack.push( info ); 479 printPush(); 480 // Note: the entry count is automatically initialized to 0. 481 } 482 483 // Reset the retry request flag so that recursive calls will 484 // push a new info object, and bump up entry count so we know 485 // when to pop this info object: 486 info.setRetryRequest( RetryType.NONE ); 487 info.incrementEntryCount(); 488 489 // KMC 6763340: I don't know why this wasn't set earlier, 490 // but we do not want a retry to pick up the previous 491 // reply status, so clear it here. Most likely a new 492 // info was pushed before, so that this was not a problem. 493 info.setReplyStatus( RequestInfoImpl.UNINITIALIZED ) ; 494 495 // If this is a DII request, make sure we ignore the next initiate. 496 if( diiRequest ) { 497 info.setDIIInitiate( true ); 498 } 499 } 500 } 501 502 public void cleanupClientPIRequest() { 503 if( !hasClientInterceptors ) return; 504 if( !isClientPIEnabledForThisThread() ) return; 505 506 ClientRequestInfoImpl info = peekClientRequestInfoImplStack(); 507 RetryType rt = info.getRetryRequest() ; 508 509 // fix for 6763340 510 if (!rt.equals( RetryType.BEFORE_RESPONSE )) { 511 512 // If the replyStatus has not yet been set, this is an indication 513 // that the ORB threw an exception before we had a chance to 514 // invoke the client interceptor ending points. 515 // 516 // _REVISIT_ We cannot handle any exceptions or ForwardRequests 517 // flagged by the ending points here because there is no way 518 // to gracefully handle this in any of the calling code. 519 // This is a rare corner case, so we will ignore this for now. 520 short replyStatus = info.getReplyStatus(); 521 if (replyStatus == info.UNINITIALIZED ) { 522 invokeClientPIEndingPoint( ReplyMessage.SYSTEM_EXCEPTION, 523 wrapper.unknownRequestInvoke( 524 CompletionStatus.COMPLETED_MAYBE ) ) ; 525 } 526 } 527 528 // Decrement entry count, and if it is zero, pop it from the stack. 529 info.decrementEntryCount(); 530 531 // fix for 6763340, and probably other cases (non-recursive retry) 532 if (info.getEntryCount() == 0 && !info.getRetryRequest().isRetry()) { 533 // RequestInfoStack<ClientRequestInfoImpl> infoStack = 534 // threadLocalClientRequestInfoStack.get(); 535 RequestInfoStack infoStack = 536 (RequestInfoStack)threadLocalClientRequestInfoStack.get(); 537 infoStack.pop(); 538 printPop(); 539 } 540 } 541 542 public void setClientPIInfo(CorbaMessageMediator messageMediator) 543 { 544 if( !hasClientInterceptors ) return; 545 if( !isClientPIEnabledForThisThread() ) return; 546 547 peekClientRequestInfoImplStack().setInfo(messageMediator); 548 } 549 550 public void setClientPIInfo( RequestImpl requestImpl ) { 551 if( !hasClientInterceptors ) return; 552 if( !isClientPIEnabledForThisThread() ) return; 553 554 peekClientRequestInfoImplStack().setDIIRequest( requestImpl ); 555 } 556 557 /* 558 ***************** 559 * Server PI hooks 560 *****************/ 561 562 public void invokeServerPIStartingPoint() 563 { 564 if( !hasServerInterceptors ) return; 565 566 ServerRequestInfoImpl info = peekServerRequestInfoImplStack(); 567 interceptorInvoker.invokeServerInterceptorStartingPoint( info ); 568 569 // Handle SystemException or ForwardRequest: 570 serverPIHandleExceptions( info ); 571 } 572 573 public void invokeServerPIIntermediatePoint() 574 { 575 if( !hasServerInterceptors ) return; 576 577 ServerRequestInfoImpl info = peekServerRequestInfoImplStack(); 578 interceptorInvoker.invokeServerInterceptorIntermediatePoint( info ); 579 580 // Clear servant from info object so that the user has control over 581 // its lifetime: 582 info.releaseServant(); 583 584 // Handle SystemException or ForwardRequest: 585 serverPIHandleExceptions( info ); 586 } 587 588 public void invokeServerPIEndingPoint( ReplyMessage replyMessage ) 589 { 590 if( !hasServerInterceptors ) return; 591 ServerRequestInfoImpl info = peekServerRequestInfoImplStack(); 592 593 // REVISIT: This needs to be done "early" for the following workaround. 594 info.setReplyMessage( replyMessage ); 595 596 // REVISIT: This was done inside of invokeServerInterceptorEndingPoint 597 // but needs to be here for now. See comment in that method for why. 598 info.setCurrentExecutionPoint( info.EXECUTION_POINT_ENDING ); 599 600 // It is possible we might have entered this method more than 601 // once (e.g. if an ending point threw a SystemException, then 602 // a new ServerResponseImpl is created). 603 if( !info.getAlreadyExecuted() ) { 604 int replyStatus = replyMessage.getReplyStatus(); 605 606 // Translate ReplyMessage.replyStatus into PI replyStatus: 607 // Note: this is also an assertion to make sure a valid 608 // replyStatus is passed in (IndexOutOfBoundsException will be 609 // thrown otherwise) 610 short piReplyStatus = 611 REPLY_MESSAGE_TO_PI_REPLY_STATUS[replyStatus]; 612 613 // Make forwarded IOR available to interceptors, if applicable: 614 if( ( piReplyStatus == LOCATION_FORWARD.value ) || 615 ( piReplyStatus == TRANSPORT_RETRY.value ) ) 616 { 617 info.setForwardRequest( replyMessage.getIOR() ); 618 } 619 620 // REVISIT: Do early above for now. 621 // Make reply message available to interceptors: 622 //info.setReplyMessage( replyMessage ); 623 624 // Remember exception so we can tell if an interceptor changed it. 625 Exception prevException = info.getException(); 626 627 // _REVISIT_ We do not have access to the User Exception at 628 // this point, so treat it as an UNKNOWN for now. 629 // Note that if this is a DSI call, we do have the user exception. 630 if( !info.isDynamic() && 631 (piReplyStatus == USER_EXCEPTION.value) ) 632 { 633 info.setException( omgWrapper.unknownUserException( 634 CompletionStatus.COMPLETED_MAYBE ) ) ; 635 } 636 637 // Invoke the ending interception points: 638 info.setReplyStatus( piReplyStatus ); 639 interceptorInvoker.invokeServerInterceptorEndingPoint( info ); 640 short newPIReplyStatus = info.getReplyStatus(); 641 Exception newException = info.getException(); 642 643 // Check reply status. If an interceptor threw a SystemException 644 // and it is different than the one that we came in with, 645 // rethrow it so the proper response can be constructed: 646 if( ( newPIReplyStatus == SYSTEM_EXCEPTION.value ) && 647 ( newException != prevException ) ) 648 { 649 throw (SystemException)newException; 650 } 651 652 // If we are to forward the location: 653 if( newPIReplyStatus == LOCATION_FORWARD.value ) { 654 if( piReplyStatus != LOCATION_FORWARD.value ) { 655 // Treat a ForwardRequest as a ForwardException. 656 IOR ior = info.getForwardRequestIOR(); 657 throw new ForwardException( orb, ior ) ; 658 } 659 else if( info.isForwardRequestRaisedInEnding() ) { 660 // Treat a ForwardRequest by changing the IOR. 661 replyMessage.setIOR( info.getForwardRequestIOR() ); 662 } 663 } 664 } 665 } 666 667 public void setServerPIInfo( Exception exception ) { 668 if( !hasServerInterceptors ) return; 669 670 ServerRequestInfoImpl info = peekServerRequestInfoImplStack(); 671 info.setException( exception ); 672 } 673 674 public void setServerPIInfo( NVList arguments ) 675 { 676 if( !hasServerInterceptors ) return; 677 678 ServerRequestInfoImpl info = peekServerRequestInfoImplStack(); 679 info.setDSIArguments( arguments ); 680 } 681 682 public void setServerPIExceptionInfo( Any exception ) 683 { 684 if( !hasServerInterceptors ) return; 685 686 ServerRequestInfoImpl info = peekServerRequestInfoImplStack(); 687 info.setDSIException( exception ); 688 } 689 690 public void setServerPIInfo( Any result ) 691 { 692 if( !hasServerInterceptors ) return; 693 694 ServerRequestInfoImpl info = peekServerRequestInfoImplStack(); 695 info.setDSIResult( result ); 696 } 697 698 public void initializeServerPIInfo( CorbaMessageMediator request, 699 ObjectAdapter oa, byte[] objectId, ObjectKeyTemplate oktemp ) 700 { 701 if( !hasServerInterceptors ) return; 702 703 RequestInfoStack infoStack = 704 (RequestInfoStack)threadLocalServerRequestInfoStack.get(); 705 ServerRequestInfoImpl info = new ServerRequestInfoImpl( orb ); 706 infoStack.push( info ); 707 printPush(); 708 709 // Notify request object that once response is constructed, make 710 // sure we execute ending points. 711 request.setExecutePIInResponseConstructor( true ); 712 713 info.setInfo( request, oa, objectId, oktemp ); 714 } 715 716 public void setServerPIInfo( java.lang.Object servant, 717 String targetMostDerivedInterface ) 718 { 719 if( !hasServerInterceptors ) return; 720 721 ServerRequestInfoImpl info = peekServerRequestInfoImplStack(); 722 info.setInfo( servant, targetMostDerivedInterface ); 723 } 724 725 public void cleanupServerPIRequest() { 726 if( !hasServerInterceptors ) return; 727 728 RequestInfoStack infoStack = 729 (RequestInfoStack)threadLocalServerRequestInfoStack.get(); 730 infoStack.pop(); 731 printPop(); 732 } 733 734 /* 735 ********************************************************************** 736 * The following methods are private utility methods. 737 ************************************************************************/ 738 739 /** 740 * Handles exceptions for the starting and intermediate points for 741 * server request interceptors. This is common code that has been 742 * factored out into this utility method. 743 * <p> 744 * This method will NOT work for ending points. 745 */ 746 private void serverPIHandleExceptions( ServerRequestInfoImpl info ) 747 { 748 int endingPointCall = info.getEndingPointCall(); 749 if(endingPointCall == ServerRequestInfoImpl.CALL_SEND_EXCEPTION) { 750 // If a system exception was thrown, throw it to caller: 751 throw (SystemException)info.getException(); 752 } 753 else if( (endingPointCall == ServerRequestInfoImpl.CALL_SEND_OTHER) && 754 (info.getForwardRequestException() != null) ) 755 { 756 // If an interceptor throws a forward request, convert it 757 // into a ForwardException for easier handling: 758 IOR ior = info.getForwardRequestIOR(); 759 throw new ForwardException( orb, ior ); 760 } 761 } 762 763 /** 764 * Utility method to convert a PI reply status short to a ReplyMessage 765 * constant. This is a reverse lookup on the table defined in 766 * REPLY_MESSAGE_TO_PI_REPLY_STATUS. The reverse lookup need not be 767 * performed as quickly since it is only executed in exception 768 * conditions. 769 */ 770 private int convertPIReplyStatusToReplyMessage( short replyStatus ) { 771 int result = 0; 772 for( int i = 0; i < REPLY_MESSAGE_TO_PI_REPLY_STATUS.length; i++ ) { 773 if( REPLY_MESSAGE_TO_PI_REPLY_STATUS[i] == replyStatus ) { 774 result = i; 775 break; 776 } 777 } 778 return result; 779 } 780 781 /** 782 * Convenience method to get the ClientRequestInfoImpl object off the 783 * top of the ThreadLocal stack. Throws an INTERNAL exception if 784 * the Info stack is empty. 785 */ 786 private ClientRequestInfoImpl peekClientRequestInfoImplStack() { 787 RequestInfoStack infoStack = 788 (RequestInfoStack)threadLocalClientRequestInfoStack.get(); 789 ClientRequestInfoImpl info = null; 790 if( !infoStack.empty() ) { 791 info = (ClientRequestInfoImpl)infoStack.peek(); 792 } else { 793 throw wrapper.clientInfoStackNull() ; 794 } 795 796 return info; 797 } 798 799 /** 800 * Convenience method to get the ServerRequestInfoImpl object off the 801 * top of the ThreadLocal stack. Returns null if there are none. 802 */ 803 private ServerRequestInfoImpl peekServerRequestInfoImplStack() { 804 RequestInfoStack infoStack = 805 (RequestInfoStack)threadLocalServerRequestInfoStack.get(); 806 ServerRequestInfoImpl info = null; 807 808 if( !infoStack.empty() ) { 809 info = (ServerRequestInfoImpl)infoStack.peek(); 810 } else { 811 throw wrapper.serverInfoStackNull() ; 812 } 813 814 return info; 815 } 816 817 /** 818 * Convenience method to determine whether Client PI is enabled 819 * for requests on this thread. 820 */ 821 private boolean isClientPIEnabledForThisThread() { 822 RequestInfoStack infoStack = 823 (RequestInfoStack)threadLocalClientRequestInfoStack.get(); 824 return (infoStack.disableCount == 0); 825 } 826 827 /** 828 * Call pre_init on all ORB initializers 829 */ 830 private void preInitORBInitializers( ORBInitInfoImpl info ) { 831 832 // Inform ORBInitInfo we are in pre_init stage 833 info.setStage( ORBInitInfoImpl.STAGE_PRE_INIT ); 834 835 // Step through each initializer instantiation and call its 836 // pre_init. Ignore any exceptions. 837 for( int i = 0; i < orb.getORBData().getORBInitializers().length; 838 i++ ) { 839 ORBInitializer init = orb.getORBData().getORBInitializers()[i]; 840 if( init != null ) { 841 try { 842 init.pre_init( info ); 843 } 844 catch( Exception e ) { 845 // As per orbos/99-12-02, section 9.3.1.2, "If there are 846 // any exceptions, the ORB shall ignore them and proceed." 847 } 848 } 849 } 850 } 851 852 /** 853 * Call post_init on all ORB initializers 854 */ 855 private void postInitORBInitializers( ORBInitInfoImpl info ) { 856 857 // Inform ORBInitInfo we are in post_init stage 858 info.setStage( ORBInitInfoImpl.STAGE_POST_INIT ); 859 860 // Step through each initializer instantiation and call its post_init. 861 // Ignore any exceptions. 862 for( int i = 0; i < orb.getORBData().getORBInitializers().length; 863 i++ ) { 864 ORBInitializer init = orb.getORBData().getORBInitializers()[i]; 865 if( init != null ) { 866 try { 867 init.post_init( info ); 868 } 869 catch( Exception e ) { 870 // As per orbos/99-12-02, section 9.3.1.2, "If there are 871 // any exceptions, the ORB shall ignore them and proceed." 872 } 873 } 874 } 875 } 876 877 /** 878 * Creates the ORBInitInfo object to be passed to ORB intializers' 879 * pre_init and post_init methods 880 */ 881 private ORBInitInfoImpl createORBInitInfo() { 882 ORBInitInfoImpl result = null; 883 884 // arguments comes from set_parameters. May be null. 885 886 // _REVISIT_ The spec does not specify which ID this is to be. 887 // We currently get this from the corba.ORB, which reads it from 888 // the ORB_ID_PROPERTY property. 889 String orbId = orb.getORBData().getORBId() ; 890 891 result = new ORBInitInfoImpl( orb, arguments, orbId, codecFactory ); 892 893 return result; 894 } 895 896 /** 897 * Called by ORBInitInfo when an interceptor needs to be registered. 898 * The type is one of: 899 * <ul> 900 * <li>INTERCEPTOR_TYPE_CLIENT - ClientRequestInterceptor 901 * <li>INTERCEPTOR_TYPE_SERVER - ServerRequestInterceptor 902 * <li>INTERCEPTOR_TYPE_IOR - IORInterceptor 903 * </ul> 904 * 905 * @exception DuplicateName Thrown if an interceptor of the given 906 * name already exists for the given type. 907 */ 908 public void register_interceptor( Interceptor interceptor, int type ) 909 throws DuplicateName 910 { 911 // We will assume interceptor is not null, since it is called 912 // internally. 913 if( (type >= InterceptorList.NUM_INTERCEPTOR_TYPES) || (type < 0) ) { 914 throw wrapper.typeOutOfRange( new Integer( type ) ) ; 915 } 916 917 String interceptorName = interceptor.name(); 918 919 if( interceptorName == null ) { 920 throw wrapper.nameNull() ; 921 } 922 923 // Register with interceptor list: 924 interceptorList.register_interceptor( interceptor, type ); 925 } 926 927 public Current getPICurrent( ) { 928 return current; 929 } 930 931 /** 932 * Called when an invalid null parameter was passed. Throws a 933 * BAD_PARAM with a minor code of 1 934 */ 935 private void nullParam() 936 throws BAD_PARAM 937 { 938 throw orbutilWrapper.nullParam() ; 939 } 940 941 /** This is the implementation of standard API defined in org.omg.CORBA.ORB 942 * class. This method finds the Policy Factory for the given Policy Type 943 * and instantiates the Policy object from the Factory. It will throw 944 * PolicyError exception, If the PolicyFactory for the given type is 945 * not registered. 946 * _REVISIT_, Once Policy Framework work is completed, Reorganize 947 * this method to com.sun.corba.se.spi.orb.ORB. 948 */ 949 public org.omg.CORBA.Policy create_policy(int type, org.omg.CORBA.Any val) 950 throws org.omg.CORBA.PolicyError 951 { 952 if( val == null ) { 953 nullParam( ); 954 } 955 if( policyFactoryTable == null ) { 956 throw new org.omg.CORBA.PolicyError( 957 "There is no PolicyFactory Registered for type " + type, 958 BAD_POLICY.value ); 959 } 960 PolicyFactory factory = (PolicyFactory)policyFactoryTable.get( 961 new Integer(type) ); 962 if( factory == null ) { 963 throw new org.omg.CORBA.PolicyError( 964 " Could Not Find PolicyFactory for the Type " + type, 965 BAD_POLICY.value); 966 } 967 org.omg.CORBA.Policy policy = factory.create_policy( type, val ); 968 return policy; 969 } 970 971 /** This method registers the Policy Factory in the policyFactoryTable, 972 * which is a HashMap. This method is made package private, because 973 * it is used internally by the Interceptors. 974 */ 975 public void registerPolicyFactory( int type, PolicyFactory factory ) { 976 if( policyFactoryTable == null ) { 977 policyFactoryTable = new HashMap(); 978 } 979 Integer key = new Integer( type ); 980 java.lang.Object val = policyFactoryTable.get( key ); 981 if( val == null ) { 982 policyFactoryTable.put( key, factory ); 983 } 984 else { 985 throw omgWrapper.policyFactoryRegFailed( new Integer( type ) ) ; 986 } 987 } 988 989 public synchronized int allocateServerRequestId () 990 { 991 return serverRequestIdCounter++; 992 } 993 }