1 /*
   2  * Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package com.sun.corba.se.impl.orb;
  27 
  28 import java.applet.Applet;
  29 
  30 import java.io.IOException;
  31 
  32 import java.lang.reflect.Constructor;
  33 import java.lang.reflect.Field;
  34 import java.lang.reflect.Modifier;
  35 import java.lang.reflect.InvocationTargetException;
  36 
  37 import java.util.Set;
  38 import java.util.HashSet;
  39 import java.util.ArrayList;
  40 import java.util.Iterator;
  41 import java.util.Properties;
  42 import java.util.Vector;
  43 import java.util.Hashtable;
  44 import java.util.Map;
  45 import java.util.HashMap;
  46 import java.util.LinkedList;
  47 import java.util.Collection;
  48 import java.util.Collections;
  49 import java.util.StringTokenizer;
  50 import java.util.Enumeration;
  51 import java.util.WeakHashMap;
  52 
  53 import java.net.InetAddress;
  54 
  55 import java.security.PrivilegedAction;
  56 import java.security.AccessController;
  57 
  58 import javax.rmi.CORBA.Util;
  59 import javax.rmi.CORBA.ValueHandler;
  60 
  61 import org.omg.CORBA.Context;
  62 import org.omg.CORBA.ContextList;
  63 import org.omg.CORBA.Environment;
  64 import org.omg.CORBA.ExceptionList;
  65 import org.omg.CORBA.ORBPackage.InvalidName;
  66 import org.omg.CORBA.NVList;
  67 import org.omg.CORBA.TCKind;
  68 import org.omg.CORBA.NamedValue;
  69 import org.omg.CORBA.Request;
  70 import org.omg.CORBA.SystemException;
  71 import org.omg.CORBA.CompletionStatus;
  72 import org.omg.CORBA.TypeCode;
  73 import org.omg.CORBA.Any;
  74 import org.omg.CORBA.StructMember;
  75 import org.omg.CORBA.UnionMember;
  76 import org.omg.CORBA.ValueMember;
  77 import org.omg.CORBA.BAD_PARAM;
  78 import org.omg.CORBA.MARSHAL;
  79 
  80 import org.omg.CORBA.portable.ValueFactory;
  81 
  82 import org.omg.CORBA.ORBPackage.InvalidName;
  83 
  84 import com.sun.org.omg.SendingContext.CodeBase;
  85 
  86 import com.sun.corba.se.pept.broker.Broker;
  87 import com.sun.corba.se.pept.protocol.ClientInvocationInfo;
  88 import com.sun.corba.se.pept.transport.ContactInfo;
  89 import com.sun.corba.se.pept.transport.ConnectionCache;
  90 import com.sun.corba.se.pept.transport.TransportManager;
  91 
  92 import com.sun.corba.se.spi.ior.IOR;
  93 import com.sun.corba.se.spi.ior.IdentifiableFactoryFinder;
  94 import com.sun.corba.se.spi.ior.TaggedComponentFactoryFinder;
  95 import com.sun.corba.se.spi.ior.IORFactories;
  96 import com.sun.corba.se.spi.ior.ObjectKey;
  97 import com.sun.corba.se.spi.ior.ObjectKeyFactory;
  98 import com.sun.corba.se.spi.ior.iiop.IIOPFactories;
  99 import com.sun.corba.se.spi.ior.iiop.GIOPVersion;
 100 import com.sun.corba.se.spi.oa.OAInvocationInfo;
 101 import com.sun.corba.se.spi.oa.ObjectAdapterFactory;
 102 import com.sun.corba.se.spi.orb.DataCollector;
 103 import com.sun.corba.se.spi.orb.Operation;
 104 import com.sun.corba.se.spi.orb.ORBData;
 105 import com.sun.corba.se.spi.orb.ORBConfigurator;
 106 import com.sun.corba.se.spi.orb.ParserImplBase;
 107 import com.sun.corba.se.spi.orb.PropertyParser;
 108 import com.sun.corba.se.spi.orb.OperationFactory;
 109 import com.sun.corba.se.spi.orb.ORBVersion;
 110 import com.sun.corba.se.spi.orb.ORBVersionFactory;
 111 import com.sun.corba.se.spi.orbutil.closure.ClosureFactory;
 112 import com.sun.corba.se.spi.orbutil.threadpool.ThreadPoolManager;
 113 import com.sun.corba.se.spi.protocol.ClientDelegateFactory;
 114 import com.sun.corba.se.spi.protocol.RequestDispatcherRegistry;
 115 import com.sun.corba.se.spi.protocol.CorbaServerRequestDispatcher;
 116 import com.sun.corba.se.spi.protocol.RequestDispatcherDefault;
 117 import com.sun.corba.se.spi.protocol.PIHandler;
 118 import com.sun.corba.se.spi.protocol.CorbaMessageMediator;
 119 import com.sun.corba.se.spi.protocol.ForwardException;
 120 import com.sun.corba.se.spi.resolver.Resolver;
 121 import com.sun.corba.se.spi.resolver.LocalResolver;
 122 import com.sun.corba.se.spi.orb.StringPair;
 123 import com.sun.corba.se.spi.orb.StringPair;
 124 import com.sun.corba.se.spi.transport.CorbaContactInfoListFactory;
 125 import com.sun.corba.se.spi.transport.CorbaTransportManager;
 126 import com.sun.corba.se.spi.legacy.connection.LegacyServerSocketManager;
 127 import com.sun.corba.se.spi.copyobject.CopierManager;
 128 import com.sun.corba.se.spi.presentation.rmi.PresentationDefaults;
 129 import com.sun.corba.se.spi.presentation.rmi.PresentationManager;
 130 import com.sun.corba.se.spi.presentation.rmi.StubAdapter;
 131 import com.sun.corba.se.spi.servicecontext.ServiceContextRegistry;
 132 
 133 import com.sun.corba.se.impl.corba.TypeCodeFactory;
 134 import com.sun.corba.se.impl.corba.TypeCodeImpl;
 135 import com.sun.corba.se.impl.corba.NVListImpl;
 136 import com.sun.corba.se.impl.corba.ExceptionListImpl;
 137 import com.sun.corba.se.impl.corba.ContextListImpl;
 138 import com.sun.corba.se.impl.corba.NamedValueImpl;
 139 import com.sun.corba.se.impl.corba.EnvironmentImpl;
 140 import com.sun.corba.se.impl.corba.AsynchInvoke;
 141 import com.sun.corba.se.impl.corba.AnyImpl;
 142 import com.sun.corba.se.impl.corba.RequestImpl;
 143 import com.sun.corba.se.impl.dynamicany.DynAnyFactoryImpl;
 144 import com.sun.corba.se.impl.encoding.EncapsOutputStream;
 145 import com.sun.corba.se.impl.encoding.CachedCodeBase;
 146 import com.sun.corba.se.impl.interceptors.PIHandlerImpl;
 147 import com.sun.corba.se.impl.interceptors.PINoOpHandlerImpl;
 148 import com.sun.corba.se.impl.ior.TaggedComponentFactoryFinderImpl;
 149 import com.sun.corba.se.impl.ior.TaggedProfileFactoryFinderImpl;
 150 import com.sun.corba.se.impl.ior.TaggedProfileTemplateFactoryFinderImpl;
 151 import com.sun.corba.se.impl.oa.toa.TOAFactory;
 152 import com.sun.corba.se.impl.oa.poa.BadServerIdHandler;
 153 import com.sun.corba.se.impl.oa.poa.DelegateImpl;
 154 import com.sun.corba.se.impl.oa.poa.POAFactory;
 155 import com.sun.corba.se.impl.orbutil.ORBConstants;
 156 import com.sun.corba.se.impl.orbutil.ORBUtility;
 157 import com.sun.corba.se.impl.orbutil.StackImpl;
 158 import com.sun.corba.se.impl.orbutil.threadpool.ThreadPoolImpl;
 159 import com.sun.corba.se.impl.orbutil.threadpool.ThreadPoolManagerImpl;
 160 import com.sun.corba.se.impl.protocol.RequestDispatcherRegistryImpl;
 161 import com.sun.corba.se.impl.protocol.CorbaInvocationInfo;
 162 import com.sun.corba.se.impl.transport.CorbaTransportManagerImpl;
 163 import com.sun.corba.se.impl.legacy.connection.LegacyServerSocketManagerImpl;
 164 import com.sun.corba.se.impl.util.Utility;
 165 import com.sun.corba.se.impl.logging.ORBUtilSystemException;
 166 import com.sun.corba.se.impl.copyobject.CopierManagerImpl;
 167 import com.sun.corba.se.impl.presentation.rmi.PresentationManagerImpl;
 168 import com.sun.corba.se.impl.transport.ManagedLocalsThread;
 169 
 170 /**
 171  * The JavaIDL ORB implementation.
 172  */
 173 public class ORBImpl extends com.sun.corba.se.spi.orb.ORB
 174 {
 175     protected TransportManager transportManager;
 176     protected LegacyServerSocketManager legacyServerSocketManager;
 177 
 178     private ThreadLocal OAInvocationInfoStack ;
 179 
 180     private ThreadLocal clientInvocationInfoStack ;
 181 
 182     // pure java orb, caching the servant IOR per ORB
 183     private static IOR codeBaseIOR ;
 184 
 185     // Vector holding deferred Requests
 186     private Vector            dynamicRequests ;
 187     private SynchVariable     svResponseReceived ;
 188 
 189     private java.lang.Object runObj = new java.lang.Object();
 190     private java.lang.Object shutdownObj = new java.lang.Object();
 191     private java.lang.Object waitForCompletionObj = new java.lang.Object();
 192     private static final byte STATUS_OPERATING = 1;
 193     private static final byte STATUS_SHUTTING_DOWN = 2;
 194     private static final byte STATUS_SHUTDOWN = 3;
 195     private static final byte STATUS_DESTROYED = 4;
 196     private byte status = STATUS_OPERATING;
 197 
 198     // XXX Should we move invocation tracking to the first level server dispatcher?
 199     private java.lang.Object invocationObj = new java.lang.Object();
 200     private int numInvocations = 0;
 201 
 202     // thread local variable to store a boolean to detect deadlock in
 203     // ORB.shutdown(true).
 204     private ThreadLocal isProcessingInvocation = new ThreadLocal () {
 205         protected java.lang.Object initialValue() {
 206             return Boolean.FALSE;
 207         }
 208     };
 209 
 210     // This map is caching TypeCodes created for a certain class (key)
 211     // and is used in Util.writeAny()
 212     private Map typeCodeForClassMap ;
 213 
 214     // Cache to hold ValueFactories (Helper classes) keyed on repository ids
 215     private Hashtable valueFactoryCache = new Hashtable();
 216 
 217     // thread local variable to store the current ORB version.
 218     // default ORB version is the version of ORB with correct Rep-id
 219     // changes
 220     private ThreadLocal orbVersionThreadLocal ;
 221 
 222     private RequestDispatcherRegistry requestDispatcherRegistry ;
 223 
 224     private CopierManager copierManager ;
 225 
 226     private int transientServerId ;
 227 
 228     private ServiceContextRegistry serviceContextRegistry ;
 229 
 230     // Needed here to implement connect/disconnect
 231     private TOAFactory toaFactory ;
 232 
 233     // Needed here for set_delegate
 234     private POAFactory poaFactory ;
 235 
 236     // The interceptor handler, which provides portable interceptor services for
 237     // subcontracts and object adapters.
 238     private PIHandler pihandler ;
 239 
 240     private ORBData configData ;
 241 
 242     private BadServerIdHandler badServerIdHandler ;
 243 
 244     private ClientDelegateFactory clientDelegateFactory ;
 245 
 246     private CorbaContactInfoListFactory corbaContactInfoListFactory ;
 247 
 248     // All access to resolver, localResolver, and urlOperation must be protected using
 249     // resolverLock.  Do not hold the ORBImpl lock while accessing
 250     // resolver, or deadlocks may occur.
 251     // Note that we now have separate locks for each resolver type.  This is due
 252     // to bug 6980681 and 6238477, which was caused by a deadlock while resolving a
 253     // corbaname: URL that contained a reference to the same ORB as the
 254     // ORB making the call to string_to_object.  This caused a deadlock between the
 255     // client thread holding the single lock for access to the urlOperation,
 256     // and the server thread handling the client is_a request waiting on the
 257     // same lock to access the localResolver.
 258 
 259 
 260     // Used for resolver_initial_references and list_initial_services
 261     private Resolver resolver ;
 262 
 263     // Used for register_initial_references
 264     private LocalResolver localResolver ;
 265 
 266     // Converts strings to object references for resolvers and string_to_object
 267     private Operation urlOperation ;
 268     private final Object urlOperationLock = new java.lang.Object() ;
 269 
 270     private CorbaServerRequestDispatcher insNamingDelegate ;
 271 
 272     // resolverLock must be used for all access to either resolver or
 273     // localResolver, since it is possible for the resolver to indirectly
 274     // refer to the localResolver.  Also used to protect access to
 275     // insNamingDelegate.
 276     private final Object resolverLock = new Object() ;
 277 
 278     private TaggedComponentFactoryFinder taggedComponentFactoryFinder ;
 279 
 280     private IdentifiableFactoryFinder taggedProfileFactoryFinder ;
 281 
 282     private IdentifiableFactoryFinder taggedProfileTemplateFactoryFinder ;
 283 
 284     private ObjectKeyFactory objectKeyFactory ;
 285 
 286     private boolean orbOwnsThreadPoolManager = false ;
 287 
 288     private ThreadPoolManager threadpoolMgr;
 289 
 290     private void dprint( String msg )
 291     {
 292         ORBUtility.dprint( this, msg ) ;
 293     }
 294 
 295     ////////////////////////////////////////////////////
 296     //
 297     // NOTE:
 298     //
 299     // Methods that are synchronized MUST stay synchronized.
 300     //
 301     // Methods that are NOT synchronized must stay that way to avoid deadlock.
 302     //
 303     //
 304     // REVISIT:
 305     //
 306     // checkShutDownState - lock on different object - and normalize usage.
 307     // starting/FinishDispatch and Shutdown
 308     //
 309 
 310     public ORBData getORBData()
 311     {
 312         return configData ;
 313     }
 314 
 315     public PIHandler getPIHandler()
 316     {
 317         return pihandler ;
 318     }
 319 
 320     /**
 321      * Create a new ORB. Should be followed by the appropriate
 322      * set_parameters() call.
 323      */
 324     public ORBImpl()
 325     {
 326         // All initialization is done through set_parameters().
 327     }
 328 
 329     public ORBVersion getORBVersion()
 330     {
 331         synchronized (this) {
 332                 checkShutdownState();
 333         }
 334         return (ORBVersion)(orbVersionThreadLocal.get()) ;
 335     }
 336 
 337     public void setORBVersion(ORBVersion verObj)
 338     {
 339         synchronized (this) {
 340                 checkShutdownState();
 341         }
 342         orbVersionThreadLocal.set(verObj);
 343     }
 344 
 345 /****************************************************************************
 346  * The following methods are ORB initialization
 347  ****************************************************************************/
 348 
 349     // preInit initializes all non-pluggable ORB data that is independent
 350     // of the property parsing.
 351     private void preInit( String[] params, Properties props )
 352     {
 353         // Before ORBConfiguration we need to set a PINoOpHandlerImpl,
 354         // because PersisentServer Initialization inside configurator will
 355         // invoke orb.resolve_initial_references( ) which will result in a
 356         // check on piHandler to invoke Interceptors. We do not want any
 357         // Interceptors to be invoked before the complete ORB initialization.
 358         // piHandler will be replaced by a real PIHandler implementation at the
 359         // end of this method.
 360         pihandler = new PINoOpHandlerImpl( );
 361 
 362         // This is the unique id of this server (JVM). Multiple incarnations
 363         // of this server will get different ids.
 364         // Compute transientServerId = milliseconds since Jan 1, 1970
 365         // Note: transientServerId will wrap in about 2^32 / 86400000 = 49.7 days.
 366         // If two ORBS are started at the same time then there is a possibility
 367         // of having the same transientServerId. This may result in collision
 368         // and may be a problem in ior.isLocal() check to see if the object
 369         // belongs to the current ORB. This problem is taken care of by checking
 370         // to see if the IOR port matches ORB server port in legacyIsLocalServerPort()
 371         // method.
 372         //
 373         // XXX need to move server ID to a string for CORBA 3.0.  At that point,
 374         // make this more unique (possibly use java.rmi.server.UID).
 375         transientServerId = (int)System.currentTimeMillis();
 376 
 377         orbVersionThreadLocal  = new ThreadLocal () {
 378             protected java.lang.Object initialValue() {
 379                 // set default to version of the ORB with correct Rep-ids
 380                 return ORBVersionFactory.getORBVersion() ;
 381             }
 382         };
 383 
 384 
 385         requestDispatcherRegistry = new RequestDispatcherRegistryImpl(
 386             this, ORBConstants.DEFAULT_SCID);
 387         copierManager = new CopierManagerImpl( this ) ;
 388 
 389         taggedComponentFactoryFinder =
 390             new TaggedComponentFactoryFinderImpl(this) ;
 391         taggedProfileFactoryFinder =
 392             new TaggedProfileFactoryFinderImpl(this) ;
 393         taggedProfileTemplateFactoryFinder =
 394             new TaggedProfileTemplateFactoryFinderImpl(this) ;
 395 
 396         dynamicRequests = new Vector();
 397         svResponseReceived = new SynchVariable();
 398 
 399         OAInvocationInfoStack =
 400             new ThreadLocal () {
 401                 protected java.lang.Object initialValue()
 402                 {
 403                     return new StackImpl();
 404                 }
 405             };
 406 
 407         clientInvocationInfoStack =
 408             new ThreadLocal() {
 409                 protected java.lang.Object initialValue() {
 410                     return new StackImpl();
 411                 }
 412             };
 413 
 414         serviceContextRegistry = new ServiceContextRegistry( this ) ;
 415     }
 416 
 417     protected void setDebugFlags( String[] args )
 418     {
 419         for (int ctr=0; ctr<args.length; ctr++ ) {
 420             String token = args[ctr] ;
 421 
 422             // If there is a public boolean data member in this class
 423             // named token + "DebugFlag", set it to true.
 424             try {
 425                 Field fld = this.getClass().getField( token + "DebugFlag" ) ;
 426                 int mod = fld.getModifiers() ;
 427                 if (Modifier.isPublic( mod ) && !Modifier.isStatic( mod ))
 428                     if (fld.getType() == boolean.class)
 429                         fld.setBoolean( this, true ) ;
 430             } catch (Exception exc) {
 431                 // ignore it XXX log this as info
 432             }
 433         }
 434     }
 435 
 436     // Class that defines a parser that gets the name of the
 437     // ORBConfigurator class.
 438     private static class ConfigParser extends ParserImplBase {
 439         // The default here is the ORBConfiguratorImpl that we define,
 440         // but this can be replaced.
 441         public Class configurator = ORBConfiguratorImpl.class ;
 442 
 443         public PropertyParser makeParser()
 444         {
 445             PropertyParser parser = new PropertyParser() ;
 446             parser.add( ORBConstants.SUN_PREFIX + "ORBConfigurator",
 447                 OperationFactory.classAction(), "configurator" ) ;
 448             return parser ;
 449         }
 450     }
 451 
 452     private void postInit( String[] params, DataCollector dataCollector )
 453     {
 454         // First, create the standard ORB config data.
 455         // This must be initialized before the ORBConfigurator
 456         // is executed.
 457         configData = new ORBDataParserImpl( this, dataCollector) ;
 458 
 459         // Set the debug flags early so they can be used by other
 460         // parts of the initialization.
 461         setDebugFlags( configData.getORBDebugFlags() ) ;
 462 
 463         // REVISIT: this should go away after more transport init cleanup
 464         // and going to ORT based ORBD.
 465         getTransportManager();
 466         getLegacyServerSocketManager();
 467 
 468         // Create a parser to get the configured ORBConfigurator.
 469         ConfigParser parser = new ConfigParser() ;
 470         parser.init( dataCollector ) ;
 471 
 472         ORBConfigurator configurator =  null ;
 473         try {
 474             configurator =
 475                 (ORBConfigurator)(parser.configurator.newInstance()) ;
 476         } catch (Exception iexc) {
 477             throw wrapper.badOrbConfigurator( iexc, parser.configurator.getName() ) ;
 478         }
 479 
 480         // Finally, run the configurator.  Note that the default implementation allows
 481         // other configurators with their own parsers to run,
 482         // using the same DataCollector.
 483         try {
 484             configurator.configure( dataCollector, this ) ;
 485         } catch (Exception exc) {
 486             throw wrapper.orbConfiguratorError( exc ) ;
 487         }
 488 
 489         // Last of all, create the PIHandler and run the ORB initializers.
 490         pihandler = new PIHandlerImpl( this, params) ;
 491         pihandler.initialize() ;
 492 
 493         // Initialize the thread manager pool and byte buffer pool
 494         // so they may be initialized & accessed without synchronization
 495         getThreadPoolManager();
 496 
 497         super.getByteBufferPool();
 498     }
 499 
 500     private synchronized POAFactory getPOAFactory()
 501     {
 502         if (poaFactory == null) {
 503             poaFactory = (POAFactory)requestDispatcherRegistry.getObjectAdapterFactory(
 504                 ORBConstants.TRANSIENT_SCID ) ;
 505         }
 506 
 507         return poaFactory ;
 508     }
 509 
 510     private synchronized TOAFactory getTOAFactory()
 511     {
 512         if (toaFactory == null) {
 513             toaFactory = (TOAFactory)requestDispatcherRegistry.getObjectAdapterFactory(
 514                 ORBConstants.TOA_SCID ) ;
 515         }
 516 
 517         return toaFactory ;
 518     }
 519 
 520     public void set_parameters( Properties props )
 521     {
 522         synchronized (this) {
 523                 checkShutdownState();
 524         }
 525         preInit( null, props ) ;
 526         DataCollector dataCollector =
 527             DataCollectorFactory.create( props, getLocalHostName() ) ;
 528         postInit( null, dataCollector ) ;
 529     }
 530 
 531     protected void set_parameters(Applet app, Properties props)
 532     {
 533         preInit( null, props ) ;
 534         DataCollector dataCollector =
 535             DataCollectorFactory.create( app, props, getLocalHostName() ) ;
 536         postInit( null, dataCollector ) ;
 537     }
 538 
 539     protected void set_parameters (String[] params, Properties props)
 540     {
 541         preInit( params, props ) ;
 542         DataCollector dataCollector =
 543             DataCollectorFactory.create( params, props, getLocalHostName() ) ;
 544         postInit( params, dataCollector ) ;
 545     }
 546 
 547 /****************************************************************************
 548  * The following methods are standard public CORBA ORB APIs
 549  ****************************************************************************/
 550 
 551     public synchronized org.omg.CORBA.portable.OutputStream create_output_stream()
 552     {
 553         checkShutdownState();
 554         return sun.corba.OutputStreamFactory.newEncapsOutputStream(this);
 555     }
 556 
 557     /**
 558      * Get a Current pseudo-object.
 559      * The Current interface is used to manage thread-specific
 560      * information for use by the transactions, security and other
 561      * services. This method is deprecated,
 562      * and replaced by ORB.resolve_initial_references("NameOfCurrentObject");
 563      *
 564      * @return          a Current pseudo-object.
 565      * @deprecated
 566      */
 567     public synchronized org.omg.CORBA.Current get_current()
 568     {
 569         checkShutdownState();
 570 
 571         /* _REVISIT_
 572            The implementation of get_current is not clear. How would
 573            ORB know whether the caller wants a Current for transactions
 574            or security ?? Or is it assumed that there is just one
 575            implementation for both ? If Current is thread-specific,
 576            then it should not be instantiated; so where does the
 577            ORB get a Current ?
 578 
 579            This should probably be deprecated. */
 580 
 581         throw wrapper.genericNoImpl() ;
 582     }
 583 
 584     /**
 585      * Create an NVList
 586      *
 587      * @param count     size of list to create
 588      * @return          NVList created
 589      *
 590      * @see NVList
 591      */
 592     public synchronized NVList create_list(int count)
 593     {
 594         checkShutdownState();
 595         return new NVListImpl(this, count);
 596     }
 597 
 598     /**
 599      * Create an NVList corresponding to an OperationDef
 600      *
 601      * @param oper      operation def to use to create list
 602      * @return          NVList created
 603      *
 604      * @see NVList
 605      */
 606     public synchronized NVList create_operation_list(org.omg.CORBA.Object oper)
 607     {
 608         checkShutdownState();
 609         throw wrapper.genericNoImpl() ;
 610     }
 611 
 612     /**
 613      * Create a NamedValue
 614      *
 615      * @return          NamedValue created
 616      */
 617     public synchronized NamedValue create_named_value(String s, Any any, int flags)
 618     {
 619         checkShutdownState();
 620         return new NamedValueImpl(this, s, any, flags);
 621     }
 622 
 623     /**
 624      * Create an ExceptionList
 625      *
 626      * @return          ExceptionList created
 627      */
 628     public synchronized org.omg.CORBA.ExceptionList create_exception_list()
 629     {
 630         checkShutdownState();
 631         return new ExceptionListImpl();
 632     }
 633 
 634     /**
 635      * Create a ContextList
 636      *
 637      * @return          ContextList created
 638      */
 639     public synchronized org.omg.CORBA.ContextList create_context_list()
 640     {
 641         checkShutdownState();
 642         return new ContextListImpl(this);
 643     }
 644 
 645     /**
 646      * Get the default Context object
 647      *
 648      * @return          the default Context object
 649      */
 650     public synchronized org.omg.CORBA.Context get_default_context()
 651     {
 652         checkShutdownState();
 653         throw wrapper.genericNoImpl() ;
 654     }
 655 
 656     /**
 657      * Create an Environment
 658      *
 659      * @return          Environment created
 660      */
 661     public synchronized org.omg.CORBA.Environment create_environment()
 662     {
 663         checkShutdownState();
 664         return new EnvironmentImpl();
 665     }
 666 
 667     public synchronized void send_multiple_requests_oneway(Request[] req)
 668     {
 669         checkShutdownState();
 670 
 671         // Invoke the send_oneway on each new Request
 672         for (int i = 0; i < req.length; i++) {
 673             req[i].send_oneway();
 674         }
 675     }
 676 
 677     /**
 678      * Send multiple dynamic requests asynchronously.
 679      *
 680      * @param req         an array of request objects.
 681      */
 682     public synchronized void send_multiple_requests_deferred(Request[] req)
 683     {
 684         checkShutdownState();
 685 
 686         // add the new Requests to pending dynamic Requests
 687         for (int i = 0; i < req.length; i++) {
 688             dynamicRequests.addElement(req[i]);
 689         }
 690 
 691         // Invoke the send_deferred on each new Request
 692         for (int i = 0; i < req.length; i++) {
 693             AsynchInvoke invokeObject = new AsynchInvoke( this,
 694                 (com.sun.corba.se.impl.corba.RequestImpl)req[i], true);
 695             new ManagedLocalsThread(invokeObject).start();
 696         }
 697     }
 698 
 699     /**
 700      * Find out if any of the deferred invocations have a response yet.
 701      */
 702     public synchronized boolean poll_next_response()
 703     {
 704         checkShutdownState();
 705 
 706         Request currRequest;
 707 
 708         // poll on each pending request
 709         Enumeration ve = dynamicRequests.elements();
 710         while (ve.hasMoreElements() == true) {
 711             currRequest = (Request)ve.nextElement();
 712             if (currRequest.poll_response() == true) {
 713                 return true;
 714             }
 715         }
 716         return false;
 717     }
 718 
 719     /**
 720      * Get the next request that has gotten a response.
 721      *
 722      * @return            the next request ready with a response.
 723      */
 724     public org.omg.CORBA.Request get_next_response()
 725         throws org.omg.CORBA.WrongTransaction
 726     {
 727         synchronized( this ) {
 728             checkShutdownState();
 729         }
 730 
 731         while (true) {
 732             // check if there already is a response
 733             synchronized ( dynamicRequests ) {
 734                 Enumeration elems = dynamicRequests.elements();
 735                 while ( elems.hasMoreElements() ) {
 736                     Request currRequest = (Request)elems.nextElement();
 737                     if ( currRequest.poll_response() ) {
 738                         // get the response for this successfully polled Request
 739                         currRequest.get_response();
 740                         dynamicRequests.removeElement(currRequest);
 741                         return currRequest;
 742                     }
 743                 }
 744             }
 745 
 746             // wait for a response
 747             synchronized(this.svResponseReceived) {
 748                 while (!this.svResponseReceived.value()) {
 749                     try {
 750                         this.svResponseReceived.wait();
 751                     } catch(java.lang.InterruptedException ex) {
 752                         // NO-OP
 753                     }
 754                 }
 755                 // reinitialize the response flag
 756                 this.svResponseReceived.reset();
 757             }
 758         }
 759     }
 760 
 761     /**
 762      * Notify response to ORB for get_next_response
 763      */
 764     public void notifyORB()
 765     {
 766         synchronized (this) {
 767                 checkShutdownState();
 768         }
 769         synchronized (this.svResponseReceived) {
 770             this.svResponseReceived.set();
 771             this.svResponseReceived.notify();
 772         }
 773     }
 774 
 775     /**
 776      * Convert an object ref to a string.
 777      * @param obj The object to stringify.
 778      * @return A stringified object reference.
 779      */
 780     public synchronized String object_to_string(org.omg.CORBA.Object obj)
 781     {
 782         checkShutdownState();
 783 
 784         // Handle the null objref case
 785         if (obj == null) {
 786             IOR nullIOR = IORFactories.makeIOR( this ) ;
 787             return nullIOR.stringify();
 788         }
 789 
 790         IOR ior = null ;
 791 
 792         try {
 793             ior = ORBUtility.connectAndGetIOR( this, obj ) ;
 794         } catch (BAD_PARAM bp) {
 795             // Throw MARSHAL instead if this is a LOCAL_OBJECT_NOT_ALLOWED error.
 796             if (bp.minor == ORBUtilSystemException.LOCAL_OBJECT_NOT_ALLOWED) {
 797                 throw omgWrapper.notAnObjectImpl( bp ) ;
 798             } else
 799                 // Not a local object problem: just rethrow the exception.
 800                 // Do not wrap and log this, since it was already logged at its
 801                 // point of origin.
 802                 throw bp ;
 803         }
 804 
 805         return ior.stringify() ;
 806     }
 807 
 808     /**
 809      * Convert a stringified object reference to the object it represents.
 810      * @param str The stringified object reference.
 811      * @return The unstringified object reference.
 812      */
 813     public org.omg.CORBA.Object string_to_object(String str)
 814     {
 815         Operation op ;
 816 
 817         synchronized (this) {
 818             checkShutdownState();
 819             op = urlOperation ;
 820         }
 821 
 822         if (str == null)
 823             throw wrapper.nullParam() ;
 824 
 825         synchronized (urlOperationLock) {
 826             org.omg.CORBA.Object obj = (org.omg.CORBA.Object)op.operate( str ) ;
 827             return obj ;
 828         }
 829     }
 830 
 831     // pure java orb support, moved this method from FVDCodeBaseImpl.
 832     // Note that we connect this if we have not already done so.
 833     public synchronized IOR getFVDCodeBaseIOR()
 834     {
 835         checkShutdownState();
 836 
 837         if (codeBaseIOR != null) // i.e. We are already connected to it
 838             return codeBaseIOR;
 839 
 840         // backward compatability 4365188
 841         CodeBase cb;
 842 
 843         ValueHandler vh = ORBUtility.createValueHandler();
 844 
 845         cb = (CodeBase)vh.getRunTimeCodeBase();
 846         return ORBUtility.connectAndGetIOR( this, cb ) ;
 847     }
 848 
 849     /**
 850      * Get the TypeCode for a primitive type.
 851      *
 852      * @param tcKind    the integer kind for the primitive type
 853      * @return          the requested TypeCode
 854      */
 855     public synchronized TypeCode get_primitive_tc(TCKind tcKind)
 856     {
 857         checkShutdownState();
 858         return get_primitive_tc( tcKind.value() ) ;
 859     }
 860 
 861     /**
 862      * Create a TypeCode for a structure.
 863      *
 864      * @param id                the logical id for the typecode.
 865      * @param name      the name for the typecode.
 866      * @param members   an array describing the members of the TypeCode.
 867      * @return          the requested TypeCode.
 868      */
 869     public synchronized TypeCode create_struct_tc(String id,
 870                                      String name,
 871                                      StructMember[] members)
 872     {
 873         checkShutdownState();
 874         return new TypeCodeImpl(this, TCKind._tk_struct, id, name, members);
 875     }
 876 
 877     /**
 878      * Create a TypeCode for a union.
 879      *
 880      * @param id                the logical id for the typecode.
 881      * @param name      the name for the typecode.
 882      * @param discriminator_type
 883      *                  the type of the union discriminator.
 884      * @param members   an array describing the members of the TypeCode.
 885      * @return          the requested TypeCode.
 886      */
 887     public synchronized TypeCode create_union_tc(String id,
 888                                     String name,
 889                                     TypeCode discriminator_type,
 890                                     UnionMember[] members)
 891     {
 892         checkShutdownState();
 893         return new TypeCodeImpl(this,
 894                                 TCKind._tk_union,
 895                                 id,
 896                                 name,
 897                                 discriminator_type,
 898                                 members);
 899     }
 900 
 901     /**
 902      * Create a TypeCode for an enum.
 903      *
 904      * @param id                the logical id for the typecode.
 905      * @param name      the name for the typecode.
 906      * @param members   an array describing the members of the TypeCode.
 907      * @return          the requested TypeCode.
 908      */
 909     public synchronized TypeCode create_enum_tc(String id,
 910                                    String name,
 911                                    String[] members)
 912     {
 913         checkShutdownState();
 914         return new TypeCodeImpl(this, TCKind._tk_enum, id, name, members);
 915     }
 916 
 917     /**
 918      * Create a TypeCode for an alias.
 919      *
 920      * @param id                the logical id for the typecode.
 921      * @param name      the name for the typecode.
 922      * @param original_type
 923      *                  the type this is an alias for.
 924      * @return          the requested TypeCode.
 925      */
 926     public synchronized TypeCode create_alias_tc(String id,
 927                                     String name,
 928                                     TypeCode original_type)
 929     {
 930         checkShutdownState();
 931         return new TypeCodeImpl(this, TCKind._tk_alias, id, name, original_type);
 932     }
 933 
 934     /**
 935      * Create a TypeCode for an exception.
 936      *
 937      * @param id                the logical id for the typecode.
 938      * @param name      the name for the typecode.
 939      * @param members   an array describing the members of the TypeCode.
 940      * @return          the requested TypeCode.
 941      */
 942     public synchronized TypeCode create_exception_tc(String id,
 943                                         String name,
 944                                         StructMember[] members)
 945     {
 946         checkShutdownState();
 947         return new TypeCodeImpl(this, TCKind._tk_except, id, name, members);
 948     }
 949 
 950     /**
 951      * Create a TypeCode for an interface.
 952      *
 953      * @param id                the logical id for the typecode.
 954      * @param name      the name for the typecode.
 955      * @return          the requested TypeCode.
 956      */
 957     public synchronized TypeCode create_interface_tc(String id,
 958                                         String name)
 959     {
 960         checkShutdownState();
 961         return new TypeCodeImpl(this, TCKind._tk_objref, id, name);
 962     }
 963 
 964     /**
 965      * Create a TypeCode for a string.
 966      *
 967      * @param bound     the bound for the string.
 968      * @return          the requested TypeCode.
 969      */
 970     public synchronized TypeCode create_string_tc(int bound)
 971     {
 972         checkShutdownState();
 973         return new TypeCodeImpl(this, TCKind._tk_string, bound);
 974     }
 975 
 976     /**
 977      * Create a TypeCode for a wide string.
 978      *
 979      * @param bound     the bound for the string.
 980      * @return          the requested TypeCode.
 981      */
 982     public synchronized TypeCode create_wstring_tc(int bound)
 983     {
 984         checkShutdownState();
 985         return new TypeCodeImpl(this, TCKind._tk_wstring, bound);
 986     }
 987 
 988     /**
 989      * Create a TypeCode for a sequence.
 990      *
 991      * @param bound     the bound for the sequence.
 992      * @param element_type
 993      *                  the type of elements of the sequence.
 994      * @return          the requested TypeCode.
 995      */
 996     public synchronized TypeCode create_sequence_tc(int bound,
 997                                        TypeCode element_type)
 998     {
 999         checkShutdownState();
1000         return new TypeCodeImpl(this, TCKind._tk_sequence, bound, element_type);
1001     }
1002 
1003 
1004     /**
1005      * Create a recursive TypeCode in a sequence.
1006      *
1007      * @param bound     the bound for the sequence.
1008      * @param offset    the index to the enclosing TypeCode that is
1009      *                  being referenced.
1010      * @return          the requested TypeCode.
1011      */
1012     public synchronized TypeCode create_recursive_sequence_tc(int bound,
1013                                                  int offset)
1014     {
1015         checkShutdownState();
1016         return new TypeCodeImpl(this, TCKind._tk_sequence, bound, offset);
1017     }
1018 
1019 
1020     /**
1021      * Create a TypeCode for an array.
1022      *
1023      * @param length    the length of the array.
1024      * @param element_type
1025      *                  the type of elements of the array.
1026      * @return          the requested TypeCode.
1027      */
1028     public synchronized TypeCode create_array_tc(int length,
1029                                     TypeCode element_type)
1030     {
1031         checkShutdownState();
1032         return new TypeCodeImpl(this, TCKind._tk_array, length, element_type);
1033     }
1034 
1035 
1036     public synchronized org.omg.CORBA.TypeCode create_native_tc(String id,
1037                                                    String name)
1038     {
1039         checkShutdownState();
1040         return new TypeCodeImpl(this, TCKind._tk_native, id, name);
1041     }
1042 
1043     public synchronized org.omg.CORBA.TypeCode create_abstract_interface_tc(
1044                                                                String id,
1045                                                                String name)
1046     {
1047         checkShutdownState();
1048         return new TypeCodeImpl(this, TCKind._tk_abstract_interface, id, name);
1049     }
1050 
1051     public synchronized org.omg.CORBA.TypeCode create_fixed_tc(short digits, short scale)
1052     {
1053         checkShutdownState();
1054         return new TypeCodeImpl(this, TCKind._tk_fixed, digits, scale);
1055     }
1056 
1057     public synchronized org.omg.CORBA.TypeCode create_value_tc(String id,
1058                                                   String name,
1059                                                   short type_modifier,
1060                                                   TypeCode concrete_base,
1061                                                   ValueMember[] members)
1062     {
1063         checkShutdownState();
1064         return new TypeCodeImpl(this, TCKind._tk_value, id, name,
1065                                 type_modifier, concrete_base, members);
1066     }
1067 
1068     public synchronized org.omg.CORBA.TypeCode create_recursive_tc(String id) {
1069         checkShutdownState();
1070         return new TypeCodeImpl(this, id);
1071     }
1072 
1073     public synchronized org.omg.CORBA.TypeCode create_value_box_tc(String id,
1074                                                       String name,
1075                                                       TypeCode boxed_type)
1076     {
1077         checkShutdownState();
1078         return new TypeCodeImpl(this, TCKind._tk_value_box, id, name,
1079             boxed_type);
1080     }
1081 
1082     /**
1083      * Create a new Any
1084      *
1085      * @return          the new Any created.
1086      */
1087     public synchronized Any create_any()
1088     {
1089         checkShutdownState();
1090         return new AnyImpl(this);
1091     }
1092 
1093     // TypeCodeFactory interface methods.
1094     // Keeping track of type codes by repository id.
1095 
1096     // Keeping a cache of TypeCodes associated with the class
1097     // they got created from in Util.writeAny().
1098 
1099     public synchronized void setTypeCodeForClass(Class c, TypeCodeImpl tci)
1100     {
1101         checkShutdownState();
1102 
1103         if (typeCodeForClassMap == null)
1104             typeCodeForClassMap = Collections.synchronizedMap(
1105                 new WeakHashMap(64));
1106         // Store only one TypeCode per class.
1107         if ( ! typeCodeForClassMap.containsKey(c))
1108             typeCodeForClassMap.put(c, tci);
1109     }
1110 
1111     public synchronized TypeCodeImpl getTypeCodeForClass(Class c)
1112     {
1113         checkShutdownState();
1114 
1115         if (typeCodeForClassMap == null)
1116             return null;
1117         return (TypeCodeImpl)typeCodeForClassMap.get(c);
1118     }
1119 
1120 /****************************************************************************
1121  * The following methods deal with listing and resolving the initial
1122  * (bootstrap) object references such as "NameService".
1123  ****************************************************************************/
1124 
1125     /**
1126      * Get a list of the initially available CORBA services.
1127      * This does not work unless an ORBInitialHost is specified during
1128      * initialization (or unless there is an ORB running on the AppletHost)
1129      * since the localhostname
1130      * is inaccessible to applets. If a service properties URL was specified,
1131      * then it is used, otherwise the bootstrapping protocol is used.
1132      * @return A list of the initial services available.
1133      */
1134     public String[] list_initial_services()
1135     {
1136         Resolver res ;
1137 
1138         synchronized( this ) {
1139             checkShutdownState();
1140             res = resolver ;
1141         }
1142 
1143         synchronized (resolverLock) {
1144             java.util.Set keys = res.list() ;
1145             return (String[])keys.toArray( new String[keys.size()] ) ;
1146         }
1147     }
1148 
1149     /**
1150      * Resolve the stringified reference of one of the initially
1151      * available CORBA services.
1152      * @param identifier The stringified object reference of the
1153      * desired service.
1154      * @return An object reference for the desired service.
1155      * @exception InvalidName The supplied identifier is not associated
1156      * with a known service.
1157      * @exception SystemException One of a fixed set of Corba system exceptions.
1158      */
1159     public org.omg.CORBA.Object resolve_initial_references(
1160         String identifier) throws InvalidName
1161     {
1162         Resolver res ;
1163 
1164         synchronized( this ) {
1165             checkShutdownState();
1166             res = resolver ;
1167         }
1168 
1169         synchronized (resolverLock) {
1170             org.omg.CORBA.Object result = res.resolve( identifier ) ;
1171 
1172             if (result == null)
1173                 throw new InvalidName() ;
1174             else
1175                 return result ;
1176         }
1177     }
1178 
1179     /**
1180      * If this operation is called with an id, <code>"Y"</code>, and an
1181      * object, <code>YY</code>, then a subsequent call to
1182      * <code>ORB.resolve_initial_references( "Y" )</code> will
1183      * return object <code>YY</code>.
1184      *
1185      * @param id The ID by which the initial reference will be known.
1186      * @param obj The initial reference itself.
1187      * @throws InvalidName if this operation is called with an empty string id
1188      *     or this operation is called with an id that is already registered,
1189      *     including the default names defined by OMG.
1190      * @throws BAD_PARAM if the obj parameter is null.
1191      */
1192     public void register_initial_reference(
1193         String id, org.omg.CORBA.Object obj ) throws InvalidName
1194     {
1195         CorbaServerRequestDispatcher insnd ;
1196 
1197         synchronized (this) {
1198             checkShutdownState();
1199         }
1200 
1201         if ((id == null) || (id.length() == 0))
1202             throw new InvalidName() ;
1203 
1204         synchronized (this) {
1205             checkShutdownState();
1206         }
1207 
1208         synchronized (resolverLock) {
1209             insnd = insNamingDelegate ;
1210 
1211             java.lang.Object obj2 = localResolver.resolve( id ) ;
1212             if (obj2 != null)
1213                 throw new InvalidName(id + " already registered") ;
1214 
1215             localResolver.register( id, ClosureFactory.makeConstant( obj )) ;
1216         }
1217 
1218         synchronized (this) {
1219             if (StubAdapter.isStub(obj))
1220                 // Make all remote object references available for INS.
1221                 requestDispatcherRegistry.registerServerRequestDispatcher(
1222                     insnd, id ) ;
1223         }
1224     }
1225 
1226 /****************************************************************************
1227  * The following methods (introduced in POA / CORBA2.1) deal with
1228  * shutdown / single threading.
1229  ****************************************************************************/
1230 
1231     public void run()
1232     {
1233         synchronized (this) {
1234             checkShutdownState();
1235         }
1236 
1237         synchronized (runObj) {
1238             try {
1239                 runObj.wait();
1240             } catch ( InterruptedException ex ) {}
1241         }
1242     }
1243 
1244     public void shutdown(boolean wait_for_completion) {
1245         boolean wait = false;
1246 
1247         synchronized (this) {
1248             checkShutdownState();
1249 
1250             // This is to avoid deadlock: don't allow a thread that is
1251             // processing a request to call shutdown( true ), because
1252             // the shutdown would block waiting for the request to complete,
1253             // while the request would block waiting for shutdown to complete.
1254             if (wait_for_completion &&
1255                 isProcessingInvocation.get() == Boolean.TRUE) {
1256                 throw omgWrapper.shutdownWaitForCompletionDeadlock();
1257             }
1258 
1259             if (status == STATUS_SHUTTING_DOWN) {
1260                 if (wait_for_completion) {
1261                     wait = true;
1262                 } else {
1263                     return;
1264                 }
1265             }
1266 
1267             status = STATUS_SHUTTING_DOWN;
1268         }
1269 
1270         // Avoid more than one thread performing shutdown at a time.
1271         synchronized (shutdownObj) {
1272             // At this point, the ORB status is certainly STATUS_SHUTTING_DOWN.
1273             // If wait is true, another thread already called shutdown( true ),
1274             // and so we wait for completion
1275             if (wait) {
1276                 while (true) {
1277                     synchronized (this) {
1278                         if (status == STATUS_SHUTDOWN)
1279                             break;
1280                     }
1281 
1282                     try {
1283                         shutdownObj.wait();
1284                     } catch (InterruptedException exc) {
1285                         // NOP: just loop and wait until state is changed
1286                     }
1287                 }
1288             } else {
1289                 // perform the actual shutdown
1290                 shutdownServants(wait_for_completion);
1291 
1292                 if (wait_for_completion) {
1293                     synchronized ( waitForCompletionObj ) {
1294                         while (numInvocations > 0) {
1295                             try {
1296                                 waitForCompletionObj.wait();
1297                             } catch (InterruptedException ex) {}
1298                         }
1299                     }
1300                 }
1301 
1302                 synchronized (runObj) {
1303                     runObj.notifyAll();
1304                 }
1305 
1306                 status = STATUS_SHUTDOWN;
1307 
1308                 shutdownObj.notifyAll();
1309             }
1310         }
1311     }
1312 
1313     // Cause all ObjectAdapaterFactories to clean up all of their internal state, which
1314     // may include activated objects that have associated state and callbacks that must
1315     // complete in order to shutdown.  This will cause new request to be rejected.
1316     protected void shutdownServants(boolean wait_for_completion) {
1317         Set<ObjectAdapterFactory> oaset;
1318         synchronized (this) {
1319             oaset = new HashSet<>(requestDispatcherRegistry.getObjectAdapterFactories());
1320         }
1321 
1322         for (ObjectAdapterFactory oaf : oaset)
1323             oaf.shutdown(wait_for_completion);
1324     }
1325 
1326     // Note that the caller must hold the ORBImpl lock.
1327     public void checkShutdownState()
1328     {
1329         if (status == STATUS_DESTROYED) {
1330             throw wrapper.orbDestroyed() ;
1331         }
1332 
1333         if (status == STATUS_SHUTDOWN) {
1334             throw omgWrapper.badOperationAfterShutdown() ;
1335         }
1336     }
1337 
1338     public boolean isDuringDispatch()
1339     {
1340         synchronized (this) {
1341                 checkShutdownState();
1342         }
1343         Boolean value = (Boolean)(isProcessingInvocation.get()) ;
1344         return value.booleanValue() ;
1345     }
1346 
1347     public void startingDispatch()
1348     {
1349         synchronized (this) {
1350                 checkShutdownState();
1351         }
1352         synchronized (invocationObj) {
1353             isProcessingInvocation.set(Boolean.TRUE);
1354             numInvocations++;
1355         }
1356     }
1357 
1358     public void finishedDispatch()
1359     {
1360         synchronized (this) {
1361                 checkShutdownState();
1362         }
1363         synchronized (invocationObj) {
1364             numInvocations--;
1365             isProcessingInvocation.set(false);
1366             if (numInvocations == 0) {
1367                 synchronized (waitForCompletionObj) {
1368                     waitForCompletionObj.notifyAll();
1369                 }
1370             } else if (numInvocations < 0) {
1371                 throw wrapper.numInvocationsAlreadyZero(
1372                     CompletionStatus.COMPLETED_YES);
1373             }
1374         }
1375     }
1376 
1377     /**
1378      *  formal/99-10-07 p 159: "If destroy is called on an ORB that has
1379      *  not been shut down, it will start the shutdown process and block until
1380      *  the ORB has shut down before it destroys the ORB."
1381      */
1382     public void destroy()
1383     {
1384         boolean shutdownFirst = false;
1385 
1386         synchronized (this) {
1387             shutdownFirst = (status == STATUS_OPERATING);
1388         }
1389 
1390         if (shutdownFirst) {
1391             shutdown(true);
1392         }
1393 
1394         synchronized (this) {
1395             if (status < STATUS_DESTROYED) {
1396                 getCorbaTransportManager().close();
1397                 getPIHandler().destroyInterceptors();
1398                 status = STATUS_DESTROYED;
1399             }
1400         }
1401         synchronized (threadPoolManagerAccessLock) {
1402             if (orbOwnsThreadPoolManager) {
1403                 try {
1404                     threadpoolMgr.close();
1405                     threadpoolMgr = null;
1406                 } catch (IOException exc) {
1407                     wrapper.ioExceptionOnClose(exc);
1408                 }
1409             }
1410         }
1411 
1412         try {
1413             monitoringManager.close();
1414             monitoringManager = null;
1415         } catch (IOException exc) {
1416             wrapper.ioExceptionOnClose(exc);
1417         }
1418 
1419         CachedCodeBase.cleanCache(this);
1420         try {
1421             pihandler.close();
1422         } catch (IOException exc) {
1423             wrapper.ioExceptionOnClose(exc);
1424         }
1425 
1426         super.destroy();
1427 
1428         badServerIdHandlerAccessLock = null;
1429         clientDelegateFactoryAccessorLock = null;
1430         corbaContactInfoListFactoryAccessLock = null;
1431 
1432         objectKeyFactoryAccessLock = null;
1433         legacyServerSocketManagerAccessLock = null;
1434         threadPoolManagerAccessLock = null;
1435         transportManager = null;
1436         legacyServerSocketManager = null;
1437         OAInvocationInfoStack  = null;
1438         clientInvocationInfoStack  = null;
1439         codeBaseIOR = null;
1440         dynamicRequests  = null;
1441         svResponseReceived  = null;
1442         runObj = null;
1443         shutdownObj = null;
1444         waitForCompletionObj = null;
1445         invocationObj = null;
1446         isProcessingInvocation = null;
1447         typeCodeForClassMap  = null;
1448         valueFactoryCache = null;
1449         orbVersionThreadLocal = null;
1450         requestDispatcherRegistry = null;
1451         copierManager = null;
1452         toaFactory = null;
1453         poaFactory = null;
1454         pihandler = null;
1455         configData = null;
1456         badServerIdHandler = null;
1457         clientDelegateFactory = null;
1458         corbaContactInfoListFactory = null;
1459         resolver = null;
1460         localResolver = null;
1461         insNamingDelegate = null;
1462         urlOperation = null;
1463         taggedComponentFactoryFinder = null;
1464         taggedProfileFactoryFinder = null;
1465         taggedProfileTemplateFactoryFinder = null;
1466         objectKeyFactory = null;
1467     }
1468 
1469     /**
1470      * Registers a value factory for a particular repository ID.
1471      *
1472      * @param repositoryID the repository ID.
1473      * @param factory the factory.
1474      * @return the previously registered factory for the given repository ID,
1475      * or null if no such factory was previously registered.
1476      * @exception org.omg.CORBA.BAD_PARAM if the registration fails.
1477      **/
1478     public synchronized ValueFactory register_value_factory(String repositoryID,
1479         ValueFactory factory)
1480     {
1481         checkShutdownState();
1482 
1483         if ((repositoryID == null) || (factory == null))
1484             throw omgWrapper.unableRegisterValueFactory() ;
1485 
1486         return (ValueFactory)valueFactoryCache.put(repositoryID, factory);
1487     }
1488 
1489     /**
1490      * Unregisters a value factory for a particular repository ID.
1491      *
1492      * @param repositoryID the repository ID.
1493      **/
1494     public synchronized void unregister_value_factory(String repositoryID)
1495     {
1496         checkShutdownState();
1497 
1498         if (valueFactoryCache.remove(repositoryID) == null)
1499             throw wrapper.nullParam() ;
1500     }
1501 
1502     /**
1503      * Finds and returns a value factory for the given repository ID.
1504      * The value factory returned was previously registered by a call to
1505      * {@link #register_value_factory} or is the default factory.
1506      *
1507      * @param repositoryID the repository ID.
1508      * @return the value factory.
1509      * @exception org.omg.CORBA.BAD_PARAM if unable to locate a factory.
1510      **/
1511     public synchronized ValueFactory lookup_value_factory(String repositoryID)
1512     {
1513         checkShutdownState();
1514 
1515         ValueFactory factory =
1516             (ValueFactory)valueFactoryCache.get(repositoryID);
1517 
1518         if (factory == null) {
1519             try {
1520                 factory = Utility.getFactory(null, null, null, repositoryID);
1521             } catch(org.omg.CORBA.MARSHAL ex) {
1522                 throw wrapper.unableFindValueFactory( ex ) ;
1523             }
1524         }
1525 
1526         return factory ;
1527     }
1528 
1529     public OAInvocationInfo peekInvocationInfo()
1530     {
1531         synchronized (this) {
1532                 checkShutdownState();
1533         }
1534         StackImpl stack = (StackImpl)(OAInvocationInfoStack.get()) ;
1535         return (OAInvocationInfo)(stack.peek()) ;
1536     }
1537 
1538     public void pushInvocationInfo( OAInvocationInfo info )
1539     {
1540         synchronized (this) {
1541                 checkShutdownState();
1542         }
1543         StackImpl stack = (StackImpl)(OAInvocationInfoStack.get()) ;
1544         stack.push( info ) ;
1545     }
1546 
1547     public OAInvocationInfo popInvocationInfo()
1548     {
1549         synchronized (this) {
1550                 checkShutdownState();
1551         }
1552         StackImpl stack = (StackImpl)(OAInvocationInfoStack.get()) ;
1553         return (OAInvocationInfo)(stack.pop()) ;
1554     }
1555 
1556     /**
1557      * The bad server id handler is used by the Locator to
1558      * send back the location of a persistant server to the client.
1559      */
1560 
1561     private Object badServerIdHandlerAccessLock = new Object();
1562 
1563     public void initBadServerIdHandler()
1564     {
1565         synchronized (this) {
1566                 checkShutdownState();
1567         }
1568         synchronized (badServerIdHandlerAccessLock) {
1569             Class cls = configData.getBadServerIdHandler() ;
1570             if (cls != null) {
1571                 try {
1572                     Class[] params = new Class[] { org.omg.CORBA.ORB.class };
1573                     java.lang.Object[] args = new java.lang.Object[]{this};
1574                     Constructor cons = cls.getConstructor(params);
1575                     badServerIdHandler =
1576                         (BadServerIdHandler) cons.newInstance(args);
1577                 } catch (Exception e) {
1578                     throw wrapper.errorInitBadserveridhandler( e ) ;
1579                 }
1580             }
1581         }
1582     }
1583 
1584     public void setBadServerIdHandler( BadServerIdHandler handler )
1585     {
1586         synchronized (this) {
1587                 checkShutdownState();
1588         }
1589         synchronized (badServerIdHandlerAccessLock) {
1590             badServerIdHandler = handler;
1591         }
1592     }
1593 
1594     public void handleBadServerId( ObjectKey okey )
1595     {
1596         synchronized (this) {
1597                 checkShutdownState();
1598         }
1599         synchronized (badServerIdHandlerAccessLock) {
1600             if (badServerIdHandler == null)
1601                 throw wrapper.badServerId() ;
1602             else
1603                 badServerIdHandler.handle( okey ) ;
1604         }
1605     }
1606 
1607     public synchronized org.omg.CORBA.Policy create_policy( int type,
1608         org.omg.CORBA.Any val ) throws org.omg.CORBA.PolicyError
1609     {
1610         checkShutdownState() ;
1611 
1612         return pihandler.create_policy( type, val ) ;
1613     }
1614 
1615     /** This is the implementation of the public API used to connect
1616      *  a servant-skeleton to the ORB.
1617      */
1618     public synchronized void connect(org.omg.CORBA.Object servant)
1619     {
1620         checkShutdownState();
1621         if (getTOAFactory() == null)
1622             throw wrapper.noToa() ;
1623 
1624         try {
1625             String codebase = javax.rmi.CORBA.Util.getCodebase( servant.getClass() ) ;
1626             getTOAFactory().getTOA( codebase ).connect( servant ) ;
1627         } catch ( Exception ex ) {
1628             throw wrapper.orbConnectError( ex ) ;
1629         }
1630     }
1631 
1632     public synchronized void disconnect(org.omg.CORBA.Object obj)
1633     {
1634         checkShutdownState();
1635         if (getTOAFactory() == null)
1636             throw wrapper.noToa() ;
1637 
1638         try {
1639             getTOAFactory().getTOA().disconnect( obj ) ;
1640         } catch ( Exception ex ) {
1641             throw wrapper.orbConnectError( ex ) ;
1642         }
1643     }
1644 
1645     public int getTransientServerId()
1646     {
1647         synchronized (this) {
1648                 checkShutdownState();
1649         }
1650         if( configData.getORBServerIdPropertySpecified( ) ) {
1651             // ORBServerId is specified then use that value
1652             return configData.getPersistentServerId( );
1653         }
1654         return transientServerId;
1655     }
1656 
1657     public RequestDispatcherRegistry getRequestDispatcherRegistry()
1658     {
1659         synchronized (this) {
1660                 checkShutdownState();
1661         }
1662         return requestDispatcherRegistry;
1663     }
1664 
1665     public ServiceContextRegistry getServiceContextRegistry()
1666     {
1667         synchronized (this) {
1668                 checkShutdownState();
1669         }
1670         return serviceContextRegistry ;
1671     }
1672 
1673     // XXX All of the isLocalXXX checking needs to be revisited.
1674     // First of all, all three of these methods are called from
1675     // only one place in impl.ior.IORImpl.  Second, we have problems
1676     // both with multi-homed hosts and with multi-profile IORs.
1677     // A possible strategy: like the LocalClientRequestDispatcher, we need
1678     // to determine this more abstractly at the ContactInfo level.
1679     // This level should probably just get the CorbaContactInfoList from
1680     // the IOR, then iterator over ContactInfo.  If any ContactInfo is
1681     // local, the IOR is local, and we can pick one to create the
1682     // LocalClientRequestDispatcher as well.  Bottom line: this code needs to move.
1683 
1684     // XXX What about multi-homed host?
1685     public boolean isLocalHost( String hostName )
1686     {
1687         synchronized (this) {
1688                 checkShutdownState();
1689         }
1690         return hostName.equals( configData.getORBServerHost() ) ||
1691             hostName.equals( getLocalHostName() ) ;
1692     }
1693 
1694     public boolean isLocalServerId( int subcontractId, int serverId )
1695     {
1696         synchronized (this) {
1697                 checkShutdownState();
1698         }
1699         if ((subcontractId < ORBConstants.FIRST_POA_SCID) ||
1700             (subcontractId > ORBConstants.MAX_POA_SCID))
1701             return serverId == getTransientServerId( ) ;
1702 
1703         // XXX isTransient info should be stored in subcontract registry
1704         if (ORBConstants.isTransient( subcontractId ))
1705             return (serverId == getTransientServerId()) ;
1706         else if (configData.getPersistentServerIdInitialized())
1707             return (serverId == configData.getPersistentServerId()) ;
1708         else
1709             return false ;
1710     }
1711 
1712     /*************************************************************************
1713      *  The following public methods are for ORB shutdown.
1714      *************************************************************************/
1715 
1716     private String getHostName(String host)
1717         throws java.net.UnknownHostException
1718     {
1719         return InetAddress.getByName( host ).getHostAddress();
1720     }
1721 
1722     /* keeping a copy of the getLocalHostName so that it can only be called
1723      * internally and the unauthorized clients cannot have access to the
1724      * localHost information, originally, the above code was calling
1725      * getLocalHostName from Connection.java.  If the hostname is cached in
1726      * Connection.java, then
1727      * it is a security hole, since any unauthorized client has access to
1728      * the host information.  With this change it is used internally so the
1729      * security problem is resolved.  Also in Connection.java, the
1730      * getLocalHost() implementation has changed to always call the
1731      * InetAddress.getLocalHost().getHostAddress()
1732      * The above mentioned method has been removed from the connection class
1733      */
1734 
1735     private static String localHostString = null;
1736 
1737     private synchronized String getLocalHostName()
1738     {
1739         if (localHostString == null) {
1740             try {
1741                 localHostString = InetAddress.getLocalHost().getHostAddress();
1742             } catch (Exception ex) {
1743                 throw wrapper.getLocalHostFailed( ex ) ;
1744             }
1745         }
1746         return localHostString ;
1747     }
1748 
1749  /******************************************************************************
1750  *  The following public methods are for ORB shutdown.
1751  *
1752  ******************************************************************************/
1753 
1754     /** This method always returns false because the ORB never needs the
1755      *  main thread to do work.
1756      */
1757     public synchronized boolean work_pending()
1758     {
1759         checkShutdownState();
1760         throw wrapper.genericNoImpl() ;
1761     }
1762 
1763     /** This method does nothing. It is not required by the spec to do anything!
1764      */
1765     public synchronized void perform_work()
1766     {
1767         checkShutdownState();
1768         throw wrapper.genericNoImpl() ;
1769     }
1770 
1771     public synchronized void set_delegate(java.lang.Object servant){
1772         checkShutdownState();
1773 
1774         POAFactory poaFactory = getPOAFactory() ;
1775         if (poaFactory != null)
1776             ((org.omg.PortableServer.Servant)servant)
1777                 ._set_delegate( poaFactory.getDelegateImpl() ) ;
1778         else
1779             throw wrapper.noPoa() ;
1780     }
1781 
1782     ////////////////////////////////////////////////////
1783     //
1784     // pept.broker.Broker
1785     //
1786 
1787     public ClientInvocationInfo createOrIncrementInvocationInfo()
1788     {
1789         synchronized (this) {
1790                 checkShutdownState();
1791         }
1792         StackImpl invocationInfoStack =
1793             (StackImpl) clientInvocationInfoStack.get();
1794         ClientInvocationInfo clientInvocationInfo = null;
1795         if (!invocationInfoStack.empty()) {
1796             clientInvocationInfo =
1797                 (ClientInvocationInfo) invocationInfoStack.peek();
1798         }
1799         if ((clientInvocationInfo == null) ||
1800             (!clientInvocationInfo.isRetryInvocation()))
1801         {
1802             // This is a new call - not a retry.
1803             clientInvocationInfo = new CorbaInvocationInfo(this);
1804             startingDispatch();
1805             invocationInfoStack.push(clientInvocationInfo);
1806         }
1807         // Reset retry so recursive calls will get a new info object.
1808         clientInvocationInfo.setIsRetryInvocation(false);
1809         clientInvocationInfo.incrementEntryCount();
1810         return clientInvocationInfo;
1811     }
1812 
1813     public void releaseOrDecrementInvocationInfo()
1814     {
1815         synchronized (this) {
1816                 checkShutdownState();
1817         }
1818         int entryCount = -1;
1819         ClientInvocationInfo clientInvocationInfo = null;
1820         StackImpl invocationInfoStack =
1821             (StackImpl)clientInvocationInfoStack.get();
1822         if (!invocationInfoStack.empty()) {
1823             clientInvocationInfo =
1824                 (ClientInvocationInfo)invocationInfoStack.peek();
1825         } else {
1826             throw wrapper.invocationInfoStackEmpty() ;
1827         }
1828         clientInvocationInfo.decrementEntryCount();
1829         entryCount = clientInvocationInfo.getEntryCount();
1830         if (clientInvocationInfo.getEntryCount() == 0) {
1831             // 6763340: don't pop if this is a retry!
1832             if (!clientInvocationInfo.isRetryInvocation()) {
1833                 invocationInfoStack.pop();
1834             }
1835             finishedDispatch();
1836         }
1837     }
1838 
1839     public ClientInvocationInfo getInvocationInfo()
1840     {
1841         synchronized (this) {
1842                 checkShutdownState();
1843         }
1844         StackImpl invocationInfoStack =
1845             (StackImpl) clientInvocationInfoStack.get();
1846         return (ClientInvocationInfo) invocationInfoStack.peek();
1847     }
1848 
1849     ////////////////////////////////////////////////////
1850     //
1851     //
1852     //
1853 
1854     private Object clientDelegateFactoryAccessorLock = new Object();
1855 
1856     public void setClientDelegateFactory( ClientDelegateFactory factory )
1857     {
1858         synchronized (this) {
1859                 checkShutdownState();
1860         }
1861         synchronized (clientDelegateFactoryAccessorLock) {
1862             clientDelegateFactory = factory ;
1863         }
1864     }
1865 
1866     public ClientDelegateFactory getClientDelegateFactory()
1867     {
1868         synchronized (this) {
1869                 checkShutdownState();
1870         }
1871         synchronized (clientDelegateFactoryAccessorLock) {
1872             return clientDelegateFactory ;
1873         }
1874     }
1875 
1876     private Object corbaContactInfoListFactoryAccessLock = new Object();
1877 
1878     public void setCorbaContactInfoListFactory( CorbaContactInfoListFactory factory )
1879     {
1880         synchronized (this) {
1881                 checkShutdownState();
1882         }
1883         synchronized (corbaContactInfoListFactoryAccessLock) {
1884             corbaContactInfoListFactory = factory ;
1885         }
1886     }
1887 
1888     public synchronized CorbaContactInfoListFactory getCorbaContactInfoListFactory()
1889     {
1890         checkShutdownState();
1891         return corbaContactInfoListFactory ;
1892     }
1893 
1894     /** Set the resolver used in this ORB.  This resolver will be used for list_initial_services
1895      * and resolve_initial_references.
1896      */
1897     public void setResolver( Resolver resolver )
1898     {
1899         synchronized (this) {
1900                 checkShutdownState();
1901         }
1902         synchronized (resolverLock) {
1903             this.resolver = resolver ;
1904         }
1905     }
1906 
1907     /** Get the resolver used in this ORB.  This resolver will be used for list_initial_services
1908      * and resolve_initial_references.
1909      */
1910     public Resolver getResolver()
1911     {
1912         synchronized (this) {
1913                 checkShutdownState();
1914         }
1915         synchronized (resolverLock) {
1916             return resolver ;
1917         }
1918     }
1919 
1920     /** Set the LocalResolver used in this ORB.  This LocalResolver is used for
1921      * register_initial_reference only.
1922      */
1923     public void setLocalResolver( LocalResolver resolver )
1924     {
1925         synchronized (this) {
1926                 checkShutdownState();
1927         }
1928         synchronized (resolverLock) {
1929             this.localResolver = resolver ;
1930         }
1931     }
1932 
1933     /** Get the LocalResolver used in this ORB.  This LocalResolver is used for
1934      * register_initial_reference only.
1935      */
1936     public LocalResolver getLocalResolver()
1937     {
1938         synchronized (this) {
1939                 checkShutdownState();
1940         }
1941         synchronized (resolverLock) {
1942             return localResolver ;
1943         }
1944     }
1945 
1946     /** Set the operation used in string_to_object calls.  The Operation must expect a
1947      * String and return an org.omg.CORBA.Object.
1948      */
1949     public void setURLOperation( Operation stringToObject )
1950     {
1951         synchronized (this) {
1952                 checkShutdownState();
1953         }
1954         synchronized (urlOperationLock) {
1955             urlOperation = stringToObject ;
1956         }
1957     }
1958 
1959     /** Get the operation used in string_to_object calls.  The Operation must expect a
1960      * String and return an org.omg.CORBA.Object.
1961      */
1962     public Operation getURLOperation()
1963     {
1964         synchronized (this) {
1965                 checkShutdownState();
1966         }
1967         synchronized (urlOperationLock) {
1968             return urlOperation ;
1969         }
1970     }
1971 
1972     public void setINSDelegate( CorbaServerRequestDispatcher sdel )
1973     {
1974         synchronized (this) {
1975                 checkShutdownState();
1976         }
1977         synchronized (resolverLock) {
1978             insNamingDelegate = sdel ;
1979         }
1980     }
1981 
1982     public TaggedComponentFactoryFinder getTaggedComponentFactoryFinder()
1983     {
1984         synchronized (this) {
1985                 checkShutdownState();
1986         }
1987         return taggedComponentFactoryFinder ;
1988     }
1989 
1990     public IdentifiableFactoryFinder getTaggedProfileFactoryFinder()
1991     {
1992         synchronized (this) {
1993                 checkShutdownState();
1994         }
1995         return taggedProfileFactoryFinder ;
1996     }
1997 
1998     public IdentifiableFactoryFinder getTaggedProfileTemplateFactoryFinder()
1999     {
2000         synchronized (this) {
2001                 checkShutdownState();
2002         }
2003         return taggedProfileTemplateFactoryFinder ;
2004     }
2005 
2006     private Object objectKeyFactoryAccessLock = new Object();
2007 
2008     public ObjectKeyFactory getObjectKeyFactory()
2009     {
2010         synchronized (this) {
2011                 checkShutdownState();
2012         }
2013         synchronized (objectKeyFactoryAccessLock) {
2014             return objectKeyFactory ;
2015         }
2016     }
2017 
2018     public void setObjectKeyFactory( ObjectKeyFactory factory )
2019     {
2020         synchronized (this) {
2021                 checkShutdownState();
2022         }
2023         synchronized (objectKeyFactoryAccessLock) {
2024             objectKeyFactory = factory ;
2025         }
2026     }
2027 
2028     private Object transportManagerAccessorLock = new Object();
2029 
2030     public TransportManager getTransportManager()
2031     {
2032         synchronized (transportManagerAccessorLock) {
2033             if (transportManager == null) {
2034                 transportManager = new CorbaTransportManagerImpl(this);
2035             }
2036             return transportManager;
2037         }
2038     }
2039 
2040     public CorbaTransportManager getCorbaTransportManager()
2041     {
2042         return (CorbaTransportManager) getTransportManager();
2043     }
2044 
2045     private Object legacyServerSocketManagerAccessLock = new Object();
2046 
2047     public LegacyServerSocketManager getLegacyServerSocketManager()
2048     {
2049         synchronized (this) {
2050                 checkShutdownState();
2051         }
2052         synchronized (legacyServerSocketManagerAccessLock) {
2053             if (legacyServerSocketManager == null) {
2054                 legacyServerSocketManager = new LegacyServerSocketManagerImpl(this);
2055             }
2056             return legacyServerSocketManager;
2057         }
2058     }
2059 
2060     private Object threadPoolManagerAccessLock = new Object();
2061 
2062     public void setThreadPoolManager(ThreadPoolManager mgr)
2063     {
2064         synchronized (this) {
2065                 checkShutdownState();
2066         }
2067         synchronized (threadPoolManagerAccessLock) {
2068             threadpoolMgr = mgr;
2069         }
2070     }
2071 
2072     public ThreadPoolManager getThreadPoolManager()
2073     {
2074         synchronized (this) {
2075                 checkShutdownState();
2076         }
2077         synchronized (threadPoolManagerAccessLock) {
2078             if (threadpoolMgr == null) {
2079                 threadpoolMgr = new ThreadPoolManagerImpl();
2080                 orbOwnsThreadPoolManager = true;
2081             }
2082             return threadpoolMgr;
2083         }
2084     }
2085 
2086     public CopierManager getCopierManager()
2087     {
2088         synchronized (this) {
2089                 checkShutdownState();
2090         }
2091         return copierManager ;
2092     }
2093 } // Class ORBImpl
2094 
2095 ////////////////////////////////////////////////////////////////////////
2096 /// Helper class for a Synchronization Variable
2097 ////////////////////////////////////////////////////////////////////////
2098 
2099 class SynchVariable
2100 {
2101     // Synchronization Variable
2102     public boolean _flag;
2103 
2104     // Constructor
2105     SynchVariable()
2106     {
2107         _flag = false;
2108     }
2109 
2110     // set Flag to true
2111     public void set()
2112     {
2113         _flag = true;
2114     }
2115 
2116         // get value
2117     public boolean value()
2118     {
2119         return _flag;
2120     }
2121 
2122     // reset Flag to true
2123     public void reset()
2124     {
2125         _flag = false;
2126     }
2127 }
2128 
2129 // End of file.