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