src/share/classes/com/sun/corba/se/impl/interceptors/PIHandlerImpl.java

Tue, 28 Dec 2010 15:52:36 -0800

author
ohair
date
Tue, 28 Dec 2010 15:52:36 -0800
changeset 240
f90b3e014e83
parent 215
cff5a173ec1e
child 380
47adb42076f1
permissions
-rw-r--r--

6962318: Update copyright year
Reviewed-by: xdono

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

mercurial