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