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