src/share/classes/com/sun/corba/se/impl/interceptors/ClientRequestInfoImpl.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 371
e324dfb90c9e
permissions
-rw-r--r--

6962318: Update copyright year
Reviewed-by: xdono

duke@1 1 /*
ohair@240 2 * Copyright (c) 2000, 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
duke@1 26 package com.sun.corba.se.impl.interceptors;
duke@1 27
duke@1 28 import java.util.HashMap ;
duke@1 29
duke@1 30 import org.omg.CORBA.Any;
duke@1 31 import org.omg.CORBA.BAD_INV_ORDER;
duke@1 32 import org.omg.CORBA.BAD_PARAM;
duke@1 33 import org.omg.CORBA.CompletionStatus;
duke@1 34 import org.omg.CORBA.Context;
duke@1 35 import org.omg.CORBA.ContextList;
duke@1 36 import org.omg.CORBA.CTX_RESTRICT_SCOPE;
duke@1 37 import org.omg.CORBA.ExceptionList;
duke@1 38 import org.omg.CORBA.LocalObject;
duke@1 39 import org.omg.CORBA.NamedValue;
duke@1 40 import org.omg.CORBA.NO_IMPLEMENT;
duke@1 41 import org.omg.CORBA.NO_RESOURCES;
duke@1 42 import org.omg.CORBA.NVList;
duke@1 43 import org.omg.CORBA.Object;
duke@1 44 import org.omg.CORBA.ParameterMode;
duke@1 45 import org.omg.CORBA.Policy;
duke@1 46 import org.omg.CORBA.SystemException;
duke@1 47 import org.omg.CORBA.TypeCode;
duke@1 48 import org.omg.CORBA.INTERNAL;
duke@1 49 import org.omg.CORBA.UserException;
duke@1 50 import org.omg.CORBA.portable.ApplicationException;
duke@1 51 import org.omg.CORBA.portable.InputStream;
duke@1 52 import com.sun.corba.se.spi.servicecontext.ServiceContexts;
duke@1 53 import com.sun.corba.se.spi.servicecontext.UnknownServiceContext;
duke@1 54
duke@1 55 import org.omg.IOP.ServiceContext;
duke@1 56 import org.omg.IOP.ServiceContextHelper;
duke@1 57 import org.omg.IOP.TaggedProfile;
duke@1 58 import org.omg.IOP.TaggedProfileHelper;
duke@1 59 import org.omg.IOP.TaggedComponent;
duke@1 60 import org.omg.IOP.TaggedComponentHelper;
duke@1 61 import org.omg.IOP.TAG_INTERNET_IOP;
duke@1 62 import org.omg.Dynamic.Parameter;
duke@1 63 import org.omg.PortableInterceptor.ClientRequestInfo;
duke@1 64 import org.omg.PortableInterceptor.LOCATION_FORWARD;
duke@1 65 import org.omg.PortableInterceptor.SUCCESSFUL;
duke@1 66 import org.omg.PortableInterceptor.SYSTEM_EXCEPTION;
duke@1 67 import org.omg.PortableInterceptor.TRANSPORT_RETRY;
duke@1 68 import org.omg.PortableInterceptor.USER_EXCEPTION;
duke@1 69
duke@1 70 import com.sun.corba.se.pept.protocol.MessageMediator;
duke@1 71
duke@1 72 import com.sun.corba.se.spi.ior.IOR;
duke@1 73 import com.sun.corba.se.spi.ior.iiop.IIOPProfileTemplate;
duke@1 74 import com.sun.corba.se.spi.ior.iiop.GIOPVersion;
duke@1 75 import com.sun.corba.se.spi.orb.ORB;
duke@1 76 import com.sun.corba.se.spi.protocol.CorbaMessageMediator;
robm@215 77 import com.sun.corba.se.spi.protocol.RetryType;
duke@1 78 import com.sun.corba.se.spi.transport.CorbaContactInfo;
duke@1 79 import com.sun.corba.se.spi.transport.CorbaContactInfoList;
duke@1 80 import com.sun.corba.se.spi.transport.CorbaContactInfoListIterator;
duke@1 81
duke@1 82 import com.sun.corba.se.impl.encoding.CDROutputStream;
duke@1 83 import com.sun.corba.se.impl.encoding.CDRInputStream_1_0;
duke@1 84 import com.sun.corba.se.impl.orbutil.ORBUtility;
duke@1 85 import com.sun.corba.se.impl.protocol.CorbaInvocationInfo;
duke@1 86 import com.sun.corba.se.impl.util.RepositoryId;
duke@1 87
duke@1 88 /**
duke@1 89 * Implementation of the ClientRequestInfo interface as specified in
duke@1 90 * orbos/99-12-02 section 5.4.2.
duke@1 91 */
duke@1 92 public final class ClientRequestInfoImpl
duke@1 93 extends RequestInfoImpl
duke@1 94 implements ClientRequestInfo
duke@1 95 {
duke@1 96
duke@1 97 // The available constants for startingPointCall
duke@1 98 static final int CALL_SEND_REQUEST = 0;
duke@1 99 static final int CALL_SEND_POLL = 1;
duke@1 100
duke@1 101 // The available constants for endingPointCall
duke@1 102 static final int CALL_RECEIVE_REPLY = 0;
duke@1 103 static final int CALL_RECEIVE_EXCEPTION = 1;
duke@1 104 static final int CALL_RECEIVE_OTHER = 2;
duke@1 105
duke@1 106 //////////////////////////////////////////////////////////////////////
duke@1 107 //
duke@1 108 // NOTE: IF AN ATTRIBUTE IS ADDED, PLEASE UPDATE RESET();
duke@1 109 //
duke@1 110 //////////////////////////////////////////////////////////////////////
duke@1 111
duke@1 112 // The current retry request status. True if this request is being
duke@1 113 // retried and this info object is to be reused, or false otherwise.
robm@215 114 private RetryType retryRequest;
duke@1 115
duke@1 116 // The number of times this info object has been (re)used. This is
duke@1 117 // incremented every time a request is retried, and decremented every
duke@1 118 // time a request is complete. When this reaches zero, the info object
duke@1 119 // is popped from the ClientRequestInfoImpl ThreadLocal stack in the ORB.
duke@1 120 private int entryCount = 0;
duke@1 121
duke@1 122 // The RequestImpl is set when the call is DII based.
duke@1 123 // The DII query calls like ParameterList, ExceptionList,
duke@1 124 // ContextList will be delegated to RequestImpl.
duke@1 125 private org.omg.CORBA.Request request;
duke@1 126
duke@1 127 // Sources of client request information
duke@1 128 private boolean diiInitiate;
duke@1 129 private CorbaMessageMediator messageMediator;
duke@1 130
duke@1 131 // Cached information:
duke@1 132 private org.omg.CORBA.Object cachedTargetObject;
duke@1 133 private org.omg.CORBA.Object cachedEffectiveTargetObject;
duke@1 134 private Parameter[] cachedArguments;
duke@1 135 private TypeCode[] cachedExceptions;
duke@1 136 private String[] cachedContexts;
duke@1 137 private String[] cachedOperationContext;
duke@1 138 private String cachedReceivedExceptionId;
duke@1 139 private Any cachedResult;
duke@1 140 private Any cachedReceivedException;
duke@1 141 private TaggedProfile cachedEffectiveProfile;
duke@1 142 // key = Integer, value = IOP.ServiceContext.
duke@1 143 private HashMap cachedRequestServiceContexts;
duke@1 144 // key = Integer, value = IOP.ServiceContext.
duke@1 145 private HashMap cachedReplyServiceContexts;
duke@1 146 // key = Integer, value = TaggedComponent
duke@1 147 private HashMap cachedEffectiveComponents;
duke@1 148
duke@1 149
duke@1 150 protected boolean piCurrentPushed;
duke@1 151
duke@1 152 //////////////////////////////////////////////////////////////////////
duke@1 153 //
duke@1 154 // NOTE: IF AN ATTRIBUTE IS ADDED, PLEASE UPDATE RESET();
duke@1 155 //
duke@1 156 //////////////////////////////////////////////////////////////////////
duke@1 157
duke@1 158 /**
duke@1 159 * Reset the info object so that it can be reused for a retry,
duke@1 160 * for example.
duke@1 161 */
duke@1 162 void reset() {
duke@1 163 super.reset();
duke@1 164
duke@1 165 // Please keep these in the same order that they're declared above.
duke@1 166
robm@215 167 // 6763340
robm@215 168 retryRequest = RetryType.NONE;
duke@1 169
duke@1 170 // Do not reset entryCount because we need to know when to pop this
duke@1 171 // from the stack.
duke@1 172
duke@1 173 request = null;
duke@1 174 diiInitiate = false;
duke@1 175 messageMediator = null;
duke@1 176
duke@1 177 // Clear cached attributes:
duke@1 178 cachedTargetObject = null;
duke@1 179 cachedEffectiveTargetObject = null;
duke@1 180 cachedArguments = null;
duke@1 181 cachedExceptions = null;
duke@1 182 cachedContexts = null;
duke@1 183 cachedOperationContext = null;
duke@1 184 cachedReceivedExceptionId = null;
duke@1 185 cachedResult = null;
duke@1 186 cachedReceivedException = null;
duke@1 187 cachedEffectiveProfile = null;
duke@1 188 cachedRequestServiceContexts = null;
duke@1 189 cachedReplyServiceContexts = null;
duke@1 190 cachedEffectiveComponents = null;
duke@1 191
duke@1 192 piCurrentPushed = false;
duke@1 193
duke@1 194 startingPointCall = CALL_SEND_REQUEST;
duke@1 195 endingPointCall = CALL_RECEIVE_REPLY;
duke@1 196
duke@1 197 }
duke@1 198
duke@1 199 /*
duke@1 200 **********************************************************************
duke@1 201 * Access protection
duke@1 202 **********************************************************************/
duke@1 203
duke@1 204 // Method IDs for all methods in ClientRequestInfo. This allows for a
duke@1 205 // convenient O(1) lookup for checkAccess().
duke@1 206 protected static final int MID_TARGET = MID_RI_LAST + 1;
duke@1 207 protected static final int MID_EFFECTIVE_TARGET = MID_RI_LAST + 2;
duke@1 208 protected static final int MID_EFFECTIVE_PROFILE = MID_RI_LAST + 3;
duke@1 209 protected static final int MID_RECEIVED_EXCEPTION = MID_RI_LAST + 4;
duke@1 210 protected static final int MID_RECEIVED_EXCEPTION_ID = MID_RI_LAST + 5;
duke@1 211 protected static final int MID_GET_EFFECTIVE_COMPONENT = MID_RI_LAST + 6;
duke@1 212 protected static final int MID_GET_EFFECTIVE_COMPONENTS
duke@1 213 = MID_RI_LAST + 7;
duke@1 214 protected static final int MID_GET_REQUEST_POLICY = MID_RI_LAST + 8;
duke@1 215 protected static final int MID_ADD_REQUEST_SERVICE_CONTEXT
duke@1 216 = MID_RI_LAST + 9;
duke@1 217
duke@1 218 // ClientRequestInfo validity table (see ptc/00-08-06 table 21-1).
duke@1 219 // Note: These must be in the same order as specified in contants.
duke@1 220 protected static final boolean validCall[][] = {
duke@1 221 // LEGEND:
duke@1 222 // s_req = send_request r_rep = receive_reply
duke@1 223 // s_pol = send_poll r_exc = receive_exception
duke@1 224 // r_oth = receive_other
duke@1 225 //
duke@1 226 // A true value indicates call is valid at specified point.
duke@1 227 // A false value indicates the call is invalid.
duke@1 228 //
duke@1 229 //
duke@1 230 // NOTE: If the order or number of columns change, update
duke@1 231 // checkAccess() accordingly.
duke@1 232 //
duke@1 233 // { s_req, s_pol, r_rep, r_exc, r_oth }
duke@1 234 // RequestInfo methods:
duke@1 235 /*request_id*/ { true , true , true , true , true },
duke@1 236 /*operation*/ { true , true , true , true , true },
duke@1 237 /*arguments*/ { true , false, true , false, false },
duke@1 238 /*exceptions*/ { true , false, true , true , true },
duke@1 239 /*contexts*/ { true , false, true , true , true },
duke@1 240 /*operation_context*/ { true , false, true , true , true },
duke@1 241 /*result*/ { false, false, true , false, false },
duke@1 242 /*response_expected*/ { true , true , true , true , true },
duke@1 243 /*sync_scope*/ { true , false, true , true , true },
duke@1 244 /*reply_status*/ { false, false, true , true , true },
duke@1 245 /*forward_reference*/ { false, false, false, false, true },
duke@1 246 /*get_slot*/ { true , true , true , true , true },
duke@1 247 /*get_request_service_context*/ { true , false, true , true , true },
duke@1 248 /*get_reply_service_context*/ { false, false, true , true , true },
duke@1 249 //
duke@1 250 // ClientRequestInfo methods::
duke@1 251 /*target*/ { true , true , true , true , true },
duke@1 252 /*effective_target*/ { true , true , true , true , true },
duke@1 253 /*effective_profile*/ { true , true , true , true , true },
duke@1 254 /*received_exception*/ { false, false, false, true , false },
duke@1 255 /*received_exception_id*/ { false, false, false, true , false },
duke@1 256 /*get_effective_component*/ { true , false, true , true , true },
duke@1 257 /*get_effective_components*/ { true , false, true , true , true },
duke@1 258 /*get_request_policy*/ { true , false, true , true , true },
duke@1 259 /*add_request_service_context*/ { true , false, false, false, false }
duke@1 260 };
duke@1 261
duke@1 262
duke@1 263 /*
duke@1 264 **********************************************************************
duke@1 265 * Public ClientRequestInfo interfaces
duke@1 266 **********************************************************************/
duke@1 267
duke@1 268 /**
duke@1 269 * Creates a new ClientRequestInfo implementation.
duke@1 270 * The constructor is package scope since no other package need create
duke@1 271 * an instance of this class.
duke@1 272 */
duke@1 273 protected ClientRequestInfoImpl( ORB myORB ) {
duke@1 274 super( myORB );
duke@1 275 startingPointCall = CALL_SEND_REQUEST;
duke@1 276 endingPointCall = CALL_RECEIVE_REPLY;
duke@1 277 }
duke@1 278
duke@1 279 /**
duke@1 280 * The object which the client called to perform the operation.
duke@1 281 */
duke@1 282 public org.omg.CORBA.Object target (){
duke@1 283 // access is currently valid for all states:
duke@1 284 //checkAccess( MID_TARGET );
duke@1 285 if (cachedTargetObject == null) {
duke@1 286 CorbaContactInfo corbaContactInfo = (CorbaContactInfo)
duke@1 287 messageMediator.getContactInfo();
duke@1 288 cachedTargetObject =
duke@1 289 iorToObject(corbaContactInfo.getTargetIOR());
duke@1 290 }
duke@1 291 return cachedTargetObject;
duke@1 292 }
duke@1 293
duke@1 294 /**
duke@1 295 * The actual object on which the operation will be invoked. If the
duke@1 296 * reply_status is LOCATION_FORWARD, then on subsequent requests,
duke@1 297 * effective_target will contain the forwarded IOR while target will
duke@1 298 * remain unchanged.
duke@1 299 */
duke@1 300 public org.omg.CORBA.Object effective_target() {
duke@1 301 // access is currently valid for all states:
duke@1 302 //checkAccess( MID_EFFECTIVE_TARGET );
duke@1 303
duke@1 304 // Note: This is not necessarily the same as locatedIOR.
duke@1 305 // Reason: See the way we handle COMM_FAILURES in
duke@1 306 // ClientRequestDispatcher.createRequest, v1.32
duke@1 307
duke@1 308 if (cachedEffectiveTargetObject == null) {
duke@1 309 CorbaContactInfo corbaContactInfo = (CorbaContactInfo)
duke@1 310 messageMediator.getContactInfo();
duke@1 311 // REVISIT - get through chain like getLocatedIOR helper below.
duke@1 312 cachedEffectiveTargetObject =
duke@1 313 iorToObject(corbaContactInfo.getEffectiveTargetIOR());
duke@1 314 }
duke@1 315 return cachedEffectiveTargetObject;
duke@1 316 }
duke@1 317
duke@1 318 /**
duke@1 319 * The profile that will be used to send the request. If a location
duke@1 320 * forward has occurred for this operation's object and that object's
duke@1 321 * profile change accordingly, then this profile will be that located
duke@1 322 * profile.
duke@1 323 */
duke@1 324 public TaggedProfile effective_profile (){
duke@1 325 // access is currently valid for all states:
duke@1 326 //checkAccess( MID_EFFECTIVE_PROFILE );
duke@1 327
duke@1 328 if( cachedEffectiveProfile == null ) {
duke@1 329 CorbaContactInfo corbaContactInfo = (CorbaContactInfo)
duke@1 330 messageMediator.getContactInfo();
duke@1 331 cachedEffectiveProfile =
duke@1 332 corbaContactInfo.getEffectiveProfile().getIOPProfile();
duke@1 333 }
duke@1 334
duke@1 335 // Good citizen: In the interest of efficiency, we assume interceptors
duke@1 336 // will not modify the returned TaggedProfile in any way so we need
duke@1 337 // not make a deep copy of it.
duke@1 338
duke@1 339 return cachedEffectiveProfile;
duke@1 340 }
duke@1 341
duke@1 342 /**
duke@1 343 * Contains the exception to be returned to the client.
duke@1 344 */
duke@1 345 public Any received_exception (){
duke@1 346 checkAccess( MID_RECEIVED_EXCEPTION );
duke@1 347
duke@1 348 if( cachedReceivedException == null ) {
duke@1 349 cachedReceivedException = exceptionToAny( exception );
duke@1 350 }
duke@1 351
duke@1 352 // Good citizen: In the interest of efficiency, we assume interceptors
duke@1 353 // will not modify the returned Any in any way so we need
duke@1 354 // not make a deep copy of it.
duke@1 355
duke@1 356 return cachedReceivedException;
duke@1 357 }
duke@1 358
duke@1 359 /**
duke@1 360 * The CORBA::RepositoryId of the exception to be returned to the client.
duke@1 361 */
duke@1 362 public String received_exception_id (){
duke@1 363 checkAccess( MID_RECEIVED_EXCEPTION_ID );
duke@1 364
duke@1 365 if( cachedReceivedExceptionId == null ) {
duke@1 366 String result = null;
duke@1 367
duke@1 368 if( exception == null ) {
duke@1 369 // Note: exception should never be null here since we will
duke@1 370 // throw a BAD_INV_ORDER if this is not called from
duke@1 371 // receive_exception.
duke@1 372 throw wrapper.exceptionWasNull() ;
duke@1 373 } else if( exception instanceof SystemException ) {
duke@1 374 String name = exception.getClass().getName();
duke@1 375 result = ORBUtility.repositoryIdOf(name);
duke@1 376 } else if( exception instanceof ApplicationException ) {
duke@1 377 result = ((ApplicationException)exception).getId();
duke@1 378 }
duke@1 379
duke@1 380 // _REVISIT_ We need to be able to handle a UserException in the
duke@1 381 // DII case. How do we extract the ID from a UserException?
duke@1 382
duke@1 383 cachedReceivedExceptionId = result;
duke@1 384 }
duke@1 385
duke@1 386 return cachedReceivedExceptionId;
duke@1 387 }
duke@1 388
duke@1 389 /**
duke@1 390 * Returns the IOP::TaggedComponent with the given ID from the profile
duke@1 391 * selected for this request. IF there is more than one component for a
duke@1 392 * given component ID, it is undefined which component this operation
duke@1 393 * returns (get_effective_component should be called instead).
duke@1 394 */
duke@1 395 public TaggedComponent get_effective_component (int id){
duke@1 396 checkAccess( MID_GET_EFFECTIVE_COMPONENT );
duke@1 397
duke@1 398 return get_effective_components( id )[0];
duke@1 399 }
duke@1 400
duke@1 401 /**
duke@1 402 * Returns all the tagged components with the given ID from the profile
duke@1 403 * selected for this request.
duke@1 404 */
duke@1 405 public TaggedComponent[] get_effective_components (int id){
duke@1 406 checkAccess( MID_GET_EFFECTIVE_COMPONENTS );
duke@1 407 Integer integerId = new Integer( id );
duke@1 408 TaggedComponent[] result = null;
duke@1 409 boolean justCreatedCache = false;
duke@1 410
duke@1 411 if( cachedEffectiveComponents == null ) {
duke@1 412 cachedEffectiveComponents = new HashMap();
duke@1 413 justCreatedCache = true;
duke@1 414 }
duke@1 415 else {
duke@1 416 // Look in cache:
duke@1 417 result = (TaggedComponent[])cachedEffectiveComponents.get(
duke@1 418 integerId );
duke@1 419 }
duke@1 420
duke@1 421 // null could mean we cached null or not in cache.
duke@1 422 if( (result == null) &&
duke@1 423 (justCreatedCache ||
duke@1 424 !cachedEffectiveComponents.containsKey( integerId ) ) )
duke@1 425 {
duke@1 426 // Not in cache. Get it from the profile:
duke@1 427 CorbaContactInfo corbaContactInfo = (CorbaContactInfo)
duke@1 428 messageMediator.getContactInfo();
duke@1 429 IIOPProfileTemplate ptemp =
duke@1 430 (IIOPProfileTemplate)corbaContactInfo.getEffectiveProfile().
duke@1 431 getTaggedProfileTemplate();
duke@1 432 result = ptemp.getIOPComponents(myORB, id);
duke@1 433 cachedEffectiveComponents.put( integerId, result );
duke@1 434 }
duke@1 435
duke@1 436 // As per ptc/00-08-06, section 21.3.13.6., If not found, raise
duke@1 437 // BAD_PARAM with minor code INVALID_COMPONENT_ID.
duke@1 438 if( (result == null) || (result.length == 0) ) {
duke@1 439 throw stdWrapper.invalidComponentId( integerId ) ;
duke@1 440 }
duke@1 441
duke@1 442 // Good citizen: In the interest of efficiency, we will assume
duke@1 443 // interceptors will not modify the returned TaggedCompoent[], or
duke@1 444 // the TaggedComponents inside of it. Otherwise, we would need to
duke@1 445 // clone the array and make a deep copy of its contents.
duke@1 446
duke@1 447 return result;
duke@1 448 }
duke@1 449
duke@1 450 /**
duke@1 451 * Returns the given policy in effect for this operation.
duke@1 452 */
duke@1 453 public Policy get_request_policy (int type){
duke@1 454 checkAccess( MID_GET_REQUEST_POLICY );
duke@1 455 // _REVISIT_ Our ORB is not policy-based at this time.
duke@1 456 throw wrapper.piOrbNotPolicyBased() ;
duke@1 457 }
duke@1 458
duke@1 459 /**
duke@1 460 * Allows interceptors to add service contexts to the request.
duke@1 461 * <p>
duke@1 462 * There is no declaration of the order of the service contexts. They
duke@1 463 * may or may not appear in the order they are added.
duke@1 464 */
duke@1 465 public void add_request_service_context (ServiceContext service_context,
duke@1 466 boolean replace)
duke@1 467 {
duke@1 468 checkAccess( MID_ADD_REQUEST_SERVICE_CONTEXT );
duke@1 469
duke@1 470 if( cachedRequestServiceContexts == null ) {
duke@1 471 cachedRequestServiceContexts = new HashMap();
duke@1 472 }
duke@1 473
duke@1 474 addServiceContext( cachedRequestServiceContexts,
duke@1 475 messageMediator.getRequestServiceContexts(),
duke@1 476 service_context, replace );
duke@1 477 }
duke@1 478
duke@1 479 // NOTE: When adding a method, be sure to:
duke@1 480 // 1. Add a MID_* constant for that method
duke@1 481 // 2. Call checkAccess at the start of the method
duke@1 482 // 3. Define entries in the validCall[][] table for interception points.
duke@1 483
duke@1 484 /*
duke@1 485 **********************************************************************
duke@1 486 * Public RequestInfo interfaces
duke@1 487 *
duke@1 488 * These are implemented here because they have differing
duke@1 489 * implementations depending on whether this is a client or a server
duke@1 490 * request info object.
duke@1 491 **********************************************************************/
duke@1 492
duke@1 493 /**
duke@1 494 * See RequestInfoImpl for javadoc.
duke@1 495 */
duke@1 496 public int request_id (){
duke@1 497 // access is currently valid for all states:
duke@1 498 //checkAccess( MID_REQUEST_ID );
duke@1 499 /*
duke@1 500 * NOTE: The requestId in client interceptors is the same as the
duke@1 501 * GIOP request id. This works because both interceptors and
duke@1 502 * request ids are scoped by the ORB on the client side.
duke@1 503 */
duke@1 504 return messageMediator.getRequestId();
duke@1 505 }
duke@1 506
duke@1 507 /**
duke@1 508 * See RequestInfoImpl for javadoc.
duke@1 509 */
duke@1 510 public String operation (){
duke@1 511 // access is currently valid for all states:
duke@1 512 //checkAccess( MID_OPERATION );
duke@1 513 return messageMediator.getOperationName();
duke@1 514 }
duke@1 515
duke@1 516 /**
duke@1 517 * See RequestInfoImpl for javadoc.
duke@1 518 */
duke@1 519 public Parameter[] arguments (){
duke@1 520 checkAccess( MID_ARGUMENTS );
duke@1 521
duke@1 522 if( cachedArguments == null ) {
duke@1 523 if( request == null ) {
duke@1 524 throw stdWrapper.piOperationNotSupported1() ;
duke@1 525 }
duke@1 526
duke@1 527 // If it is DII request then get the arguments from the DII req
duke@1 528 // and convert that into parameters.
duke@1 529 cachedArguments = nvListToParameterArray( request.arguments() );
duke@1 530 }
duke@1 531
duke@1 532 // Good citizen: In the interest of efficiency, we assume
duke@1 533 // interceptors will be "good citizens" in that they will not
duke@1 534 // modify the contents of the Parameter[] array. We also assume
duke@1 535 // they will not change the values of the containing Anys.
duke@1 536
duke@1 537 return cachedArguments;
duke@1 538 }
duke@1 539
duke@1 540 /**
duke@1 541 * See RequestInfoImpl for javadoc.
duke@1 542 */
duke@1 543 public TypeCode[] exceptions (){
duke@1 544 checkAccess( MID_EXCEPTIONS );
duke@1 545
duke@1 546 if( cachedExceptions == null ) {
duke@1 547 if( request == null ) {
duke@1 548 throw stdWrapper.piOperationNotSupported2() ;
duke@1 549 }
duke@1 550
duke@1 551 // Get the list of exceptions from DII request data, If there are
duke@1 552 // no exceptions raised then this method will return null.
duke@1 553 ExceptionList excList = request.exceptions( );
duke@1 554 int count = excList.count();
duke@1 555 TypeCode[] excTCList = new TypeCode[count];
duke@1 556 try {
duke@1 557 for( int i = 0; i < count; i++ ) {
duke@1 558 excTCList[i] = excList.item( i );
duke@1 559 }
duke@1 560 } catch( Exception e ) {
duke@1 561 throw wrapper.exceptionInExceptions( e ) ;
duke@1 562 }
duke@1 563
duke@1 564 cachedExceptions = excTCList;
duke@1 565 }
duke@1 566
duke@1 567 // Good citizen: In the interest of efficiency, we assume
duke@1 568 // interceptors will be "good citizens" in that they will not
duke@1 569 // modify the contents of the TypeCode[] array. We also assume
duke@1 570 // they will not change the values of the containing TypeCodes.
duke@1 571
duke@1 572 return cachedExceptions;
duke@1 573 }
duke@1 574
duke@1 575 /**
duke@1 576 * See RequestInfoImpl for javadoc.
duke@1 577 */
duke@1 578 public String[] contexts (){
duke@1 579 checkAccess( MID_CONTEXTS );
duke@1 580
duke@1 581 if( cachedContexts == null ) {
duke@1 582 if( request == null ) {
duke@1 583 throw stdWrapper.piOperationNotSupported3() ;
duke@1 584 }
duke@1 585
duke@1 586 // Get the list of contexts from DII request data, If there are
duke@1 587 // no contexts then this method will return null.
duke@1 588 ContextList ctxList = request.contexts( );
duke@1 589 int count = ctxList.count();
duke@1 590 String[] ctxListToReturn = new String[count];
duke@1 591 try {
duke@1 592 for( int i = 0; i < count; i++ ) {
duke@1 593 ctxListToReturn[i] = ctxList.item( i );
duke@1 594 }
duke@1 595 } catch( Exception e ) {
duke@1 596 throw wrapper.exceptionInContexts( e ) ;
duke@1 597 }
duke@1 598
duke@1 599 cachedContexts = ctxListToReturn;
duke@1 600 }
duke@1 601
duke@1 602 // Good citizen: In the interest of efficiency, we assume
duke@1 603 // interceptors will be "good citizens" in that they will not
duke@1 604 // modify the contents of the String[] array.
duke@1 605
duke@1 606 return cachedContexts;
duke@1 607 }
duke@1 608
duke@1 609 /**
duke@1 610 * See RequestInfoImpl for javadoc.
duke@1 611 */
duke@1 612 public String[] operation_context (){
duke@1 613 checkAccess( MID_OPERATION_CONTEXT );
duke@1 614
duke@1 615 if( cachedOperationContext == null ) {
duke@1 616 if( request == null ) {
duke@1 617 throw stdWrapper.piOperationNotSupported4() ;
duke@1 618 }
duke@1 619
duke@1 620 // Get the list of contexts from DII request data, If there are
duke@1 621 // no contexts then this method will return null.
duke@1 622 Context ctx = request.ctx( );
duke@1 623 // _REVISIT_ The API for get_values is not compliant with the spec,
duke@1 624 // Revisit this code once it's fixed.
duke@1 625 // _REVISIT_ Our ORB doesn't support Operation Context, This code
duke@1 626 // will not be excerscised until it's supported.
duke@1 627 // The first parameter in get_values is the start_scope which
duke@1 628 // if blank makes it as a global scope.
duke@1 629 // The second parameter is op_flags which is set to RESTRICT_SCOPE
duke@1 630 // As there is only one defined in the spec.
duke@1 631 // The Third param is the pattern which is '*' requiring it to
duke@1 632 // get all the contexts.
duke@1 633 NVList nvList = ctx.get_values( "", CTX_RESTRICT_SCOPE.value,"*" );
duke@1 634 String[] context = new String[(nvList.count() * 2) ];
duke@1 635 if( ( nvList != null ) &&( nvList.count() != 0 ) ) {
duke@1 636 // The String[] array will contain Name and Value for each
duke@1 637 // context and hence double the size in the array.
duke@1 638 int index = 0;
duke@1 639 for( int i = 0; i < nvList.count(); i++ ) {
duke@1 640 NamedValue nv;
duke@1 641 try {
duke@1 642 nv = nvList.item( i );
duke@1 643 }
duke@1 644 catch (Exception e ) {
duke@1 645 return (String[]) null;
duke@1 646 }
duke@1 647 context[index] = nv.name();
duke@1 648 index++;
duke@1 649 context[index] = nv.value().extract_string();
duke@1 650 index++;
duke@1 651 }
duke@1 652 }
duke@1 653
duke@1 654 cachedOperationContext = context;
duke@1 655 }
duke@1 656
duke@1 657 // Good citizen: In the interest of efficiency, we assume
duke@1 658 // interceptors will be "good citizens" in that they will not
duke@1 659 // modify the contents of the String[] array.
duke@1 660
duke@1 661 return cachedOperationContext;
duke@1 662 }
duke@1 663
duke@1 664 /**
duke@1 665 * See RequestInfoImpl for javadoc.
duke@1 666 */
duke@1 667 public Any result (){
duke@1 668 checkAccess( MID_RESULT );
duke@1 669
duke@1 670 if( cachedResult == null ) {
duke@1 671 if( request == null ) {
duke@1 672 throw stdWrapper.piOperationNotSupported5() ;
duke@1 673 }
duke@1 674 // Get the result from the DII request data.
duke@1 675 NamedValue nvResult = request.result( );
duke@1 676
duke@1 677 if( nvResult == null ) {
duke@1 678 throw wrapper.piDiiResultIsNull() ;
duke@1 679 }
duke@1 680
duke@1 681 cachedResult = nvResult.value();
duke@1 682 }
duke@1 683
duke@1 684 // Good citizen: In the interest of efficiency, we assume that
duke@1 685 // interceptors will not modify the contents of the result Any.
duke@1 686 // Otherwise, we would need to create a deep copy of the Any.
duke@1 687
duke@1 688 return cachedResult;
duke@1 689 }
duke@1 690
duke@1 691 /**
duke@1 692 * See RequestInfoImpl for javadoc.
duke@1 693 */
duke@1 694 public boolean response_expected (){
duke@1 695 // access is currently valid for all states:
duke@1 696 //checkAccess( MID_RESPONSE_EXPECTED );
duke@1 697 return ! messageMediator.isOneWay();
duke@1 698 }
duke@1 699
duke@1 700 /**
duke@1 701 * See RequestInfoImpl for javadoc.
duke@1 702 */
duke@1 703 public Object forward_reference (){
duke@1 704 checkAccess( MID_FORWARD_REFERENCE );
duke@1 705 // Check to make sure we are in LOCATION_FORWARD
duke@1 706 // state as per ptc/00-08-06, table 21-1
duke@1 707 // footnote 2.
duke@1 708 if( replyStatus != LOCATION_FORWARD.value ) {
duke@1 709 throw stdWrapper.invalidPiCall1() ;
duke@1 710 }
duke@1 711
duke@1 712 // Do not cache this value since if an interceptor raises
duke@1 713 // forward request then the next interceptor in the
duke@1 714 // list should see the new value.
duke@1 715 IOR ior = getLocatedIOR();
duke@1 716 return iorToObject(ior);
duke@1 717 }
duke@1 718
duke@1 719 private IOR getLocatedIOR()
duke@1 720 {
duke@1 721 IOR ior;
duke@1 722 CorbaContactInfoList contactInfoList = (CorbaContactInfoList)
duke@1 723 messageMediator.getContactInfo().getContactInfoList();
duke@1 724 ior = contactInfoList.getEffectiveTargetIOR();
duke@1 725 return ior;
duke@1 726 }
duke@1 727
duke@1 728 protected void setLocatedIOR(IOR ior)
duke@1 729 {
duke@1 730 ORB orb = (ORB) messageMediator.getBroker();
duke@1 731
duke@1 732 CorbaContactInfoListIterator iterator = (CorbaContactInfoListIterator)
duke@1 733 ((CorbaInvocationInfo)orb.getInvocationInfo())
duke@1 734 .getContactInfoListIterator();
duke@1 735
duke@1 736 // REVISIT - this most likely causes reportRedirect to happen twice.
duke@1 737 // Once here and once inside the request dispatcher.
duke@1 738 iterator.reportRedirect(
duke@1 739 (CorbaContactInfo)messageMediator.getContactInfo(),
duke@1 740 ior);
duke@1 741 }
duke@1 742
duke@1 743 /**
duke@1 744 * See RequestInfoImpl for javadoc.
duke@1 745 */
duke@1 746 public org.omg.IOP.ServiceContext get_request_service_context( int id ) {
duke@1 747 checkAccess( MID_GET_REQUEST_SERVICE_CONTEXT );
duke@1 748
duke@1 749 if( cachedRequestServiceContexts == null ) {
duke@1 750 cachedRequestServiceContexts = new HashMap();
duke@1 751 }
duke@1 752
duke@1 753 return getServiceContext(cachedRequestServiceContexts,
duke@1 754 messageMediator.getRequestServiceContexts(),
duke@1 755 id);
duke@1 756 }
duke@1 757
duke@1 758 /**
duke@1 759 * does not contain an etry for that ID, BAD_PARAM with a minor code of
duke@1 760 * TBD_BP is raised.
duke@1 761 */
duke@1 762 public org.omg.IOP.ServiceContext get_reply_service_context( int id ) {
duke@1 763 checkAccess( MID_GET_REPLY_SERVICE_CONTEXT );
duke@1 764
duke@1 765 if( cachedReplyServiceContexts == null ) {
duke@1 766 cachedReplyServiceContexts = new HashMap();
duke@1 767 }
duke@1 768
duke@1 769 // In the event this is called from a oneway, we will have no
duke@1 770 // response object.
duke@1 771 //
duke@1 772 // In the event this is called after a IIOPConnection.purgeCalls,
duke@1 773 // we will have a response object, but that object will
duke@1 774 // not contain a header (which would hold the service context
duke@1 775 // container). See bug 4624102.
duke@1 776 //
duke@1 777 // REVISIT: this is the only thing used
duke@1 778 // from response at this time. However, a more general solution
duke@1 779 // would avoid accessing other parts of response's header.
duke@1 780 //
duke@1 781 // Instead of throwing a NullPointer, we will
duke@1 782 // "gracefully" handle these with a BAD_PARAM with minor code 25.
duke@1 783
duke@1 784 try {
duke@1 785 ServiceContexts serviceContexts =
duke@1 786 messageMediator.getReplyServiceContexts();
duke@1 787 if (serviceContexts == null) {
duke@1 788 throw new NullPointerException();
duke@1 789 }
duke@1 790 return getServiceContext(cachedReplyServiceContexts,
duke@1 791 serviceContexts, id);
duke@1 792 } catch (NullPointerException e) {
duke@1 793 // REVISIT how this is programmed - not what it does.
duke@1 794 // See purge calls test. The waiter is woken up by the
duke@1 795 // call to purge calls - but there is no reply containing
duke@1 796 // service contexts.
duke@1 797 throw stdWrapper.invalidServiceContextId( e ) ;
duke@1 798 }
duke@1 799 }
duke@1 800
duke@1 801 //
duke@1 802 // REVISIT
duke@1 803 // Override RequestInfoImpl connection to work in framework.
duke@1 804 //
duke@1 805
duke@1 806 public com.sun.corba.se.spi.legacy.connection.Connection connection()
duke@1 807 {
duke@1 808 return (com.sun.corba.se.spi.legacy.connection.Connection)
duke@1 809 messageMediator.getConnection();
duke@1 810 }
duke@1 811
duke@1 812
duke@1 813
duke@1 814 /*
duke@1 815 **********************************************************************
duke@1 816 * Package-scope interfaces
duke@1 817 **********************************************************************/
duke@1 818
duke@1 819 protected void setInfo(MessageMediator messageMediator)
duke@1 820 {
duke@1 821 this.messageMediator = (CorbaMessageMediator)messageMediator;
duke@1 822 // REVISIT - so mediator can handle DII in subcontract.
duke@1 823 this.messageMediator.setDIIInfo(request);
duke@1 824 }
duke@1 825
duke@1 826 /**
duke@1 827 * Set or reset the retry request flag.
duke@1 828 */
robm@215 829 void setRetryRequest( RetryType retryRequest ) {
duke@1 830 this.retryRequest = retryRequest;
duke@1 831 }
duke@1 832
duke@1 833 /**
duke@1 834 * Retrieve the current retry request status.
duke@1 835 */
robm@215 836 RetryType getRetryRequest() {
robm@215 837 // 6763340
duke@1 838 return this.retryRequest;
duke@1 839 }
duke@1 840
duke@1 841 /**
duke@1 842 * Increases the entry count by 1.
duke@1 843 */
duke@1 844 void incrementEntryCount() {
duke@1 845 this.entryCount++;
duke@1 846 }
duke@1 847
duke@1 848 /**
duke@1 849 * Decreases the entry count by 1.
duke@1 850 */
duke@1 851 void decrementEntryCount() {
duke@1 852 this.entryCount--;
duke@1 853 }
duke@1 854
duke@1 855 /**
duke@1 856 * Retrieve the current entry count
duke@1 857 */
duke@1 858 int getEntryCount() {
duke@1 859 return this.entryCount;
duke@1 860 }
duke@1 861
duke@1 862 /**
duke@1 863 * Overridden from RequestInfoImpl. Calls the super class, then
duke@1 864 * sets the ending point call depending on the reply status.
duke@1 865 */
duke@1 866 protected void setReplyStatus( short replyStatus ) {
duke@1 867 super.setReplyStatus( replyStatus );
duke@1 868 switch( replyStatus ) {
duke@1 869 case SUCCESSFUL.value:
duke@1 870 endingPointCall = CALL_RECEIVE_REPLY;
duke@1 871 break;
duke@1 872 case SYSTEM_EXCEPTION.value:
duke@1 873 case USER_EXCEPTION.value:
duke@1 874 endingPointCall = CALL_RECEIVE_EXCEPTION;
duke@1 875 break;
duke@1 876 case LOCATION_FORWARD.value:
duke@1 877 case TRANSPORT_RETRY.value:
duke@1 878 endingPointCall = CALL_RECEIVE_OTHER;
duke@1 879 break;
duke@1 880 }
duke@1 881 }
duke@1 882
duke@1 883 /**
duke@1 884 * Sets DII request object in the RequestInfoObject.
duke@1 885 */
duke@1 886 protected void setDIIRequest(org.omg.CORBA.Request req) {
duke@1 887 request = req;
duke@1 888 }
duke@1 889
duke@1 890 /**
duke@1 891 * Keeps track of whether initiate was called for a DII request. The ORB
duke@1 892 * needs to know this so it knows whether to ignore a second call to
duke@1 893 * initiateClientPIRequest or not.
duke@1 894 */
duke@1 895 protected void setDIIInitiate( boolean diiInitiate ) {
duke@1 896 this.diiInitiate = diiInitiate;
duke@1 897 }
duke@1 898
duke@1 899 /**
duke@1 900 * See comment for setDIIInitiate
duke@1 901 */
duke@1 902 protected boolean isDIIInitiate() {
duke@1 903 return this.diiInitiate;
duke@1 904 }
duke@1 905
duke@1 906 /**
duke@1 907 * The PICurrent stack should only be popped if it was pushed.
duke@1 908 * This is generally the case. But exceptions which occur
duke@1 909 * after the stub's entry to _request but before the push
duke@1 910 * end up in _releaseReply which will try to pop unless told not to.
duke@1 911 */
duke@1 912 protected void setPICurrentPushed( boolean piCurrentPushed ) {
duke@1 913 this.piCurrentPushed = piCurrentPushed;
duke@1 914 }
duke@1 915
duke@1 916 protected boolean isPICurrentPushed() {
duke@1 917 return this.piCurrentPushed;
duke@1 918 }
duke@1 919
duke@1 920 /**
duke@1 921 * Overridden from RequestInfoImpl.
duke@1 922 */
duke@1 923 protected void setException( Exception exception ) {
duke@1 924 super.setException( exception );
duke@1 925
duke@1 926 // Clear cached values:
duke@1 927 cachedReceivedException = null;
duke@1 928 cachedReceivedExceptionId = null;
duke@1 929 }
duke@1 930
duke@1 931 protected boolean getIsOneWay() {
duke@1 932 return ! response_expected();
duke@1 933 }
duke@1 934
duke@1 935 /**
duke@1 936 * See description for RequestInfoImpl.checkAccess
duke@1 937 */
duke@1 938 protected void checkAccess( int methodID )
duke@1 939 throws BAD_INV_ORDER
duke@1 940 {
duke@1 941 // Make sure currentPoint matches the appropriate index in the
duke@1 942 // validCall table:
duke@1 943 int validCallIndex = 0;
duke@1 944 switch( currentExecutionPoint ) {
duke@1 945 case EXECUTION_POINT_STARTING:
duke@1 946 switch( startingPointCall ) {
duke@1 947 case CALL_SEND_REQUEST:
duke@1 948 validCallIndex = 0;
duke@1 949 break;
duke@1 950 case CALL_SEND_POLL:
duke@1 951 validCallIndex = 1;
duke@1 952 break;
duke@1 953 }
duke@1 954 break;
duke@1 955 case EXECUTION_POINT_ENDING:
duke@1 956 switch( endingPointCall ) {
duke@1 957 case CALL_RECEIVE_REPLY:
duke@1 958 validCallIndex = 2;
duke@1 959 break;
duke@1 960 case CALL_RECEIVE_EXCEPTION:
duke@1 961 validCallIndex = 3;
duke@1 962 break;
duke@1 963 case CALL_RECEIVE_OTHER:
duke@1 964 validCallIndex = 4;
duke@1 965 break;
duke@1 966 }
duke@1 967 break;
duke@1 968 }
duke@1 969
duke@1 970 // Check the validCall table:
duke@1 971 if( !validCall[methodID][validCallIndex] ) {
duke@1 972 throw stdWrapper.invalidPiCall2() ;
duke@1 973 }
duke@1 974 }
duke@1 975
duke@1 976 }
duke@1 977
duke@1 978 // End of file.

mercurial