1 /*
   2  * Copyright (c) 1997, 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.oa.poa;
  27 
  28 import java.util.Collection ;
  29 import java.util.Set ;
  30 import java.util.HashSet ;
  31 import java.util.Map ;
  32 import java.util.HashMap ;
  33 import java.util.Iterator ;
  34 
  35 import org.omg.CORBA.Policy ;
  36 import org.omg.CORBA.SystemException ;
  37 
  38 import org.omg.PortableServer.POA ;
  39 import org.omg.PortableServer.Servant ;
  40 import org.omg.PortableServer.POAManager ;
  41 import org.omg.PortableServer.AdapterActivator ;
  42 import org.omg.PortableServer.ServantManager ;
  43 import org.omg.PortableServer.ForwardRequest ;
  44 import org.omg.PortableServer.ThreadPolicy;
  45 import org.omg.PortableServer.LifespanPolicy;
  46 import org.omg.PortableServer.IdUniquenessPolicy;
  47 import org.omg.PortableServer.IdAssignmentPolicy;
  48 import org.omg.PortableServer.ImplicitActivationPolicy;
  49 import org.omg.PortableServer.ServantRetentionPolicy;
  50 import org.omg.PortableServer.RequestProcessingPolicy;
  51 import org.omg.PortableServer.ThreadPolicyValue ;
  52 import org.omg.PortableServer.LifespanPolicyValue ;
  53 import org.omg.PortableServer.IdUniquenessPolicyValue ;
  54 import org.omg.PortableServer.IdAssignmentPolicyValue ;
  55 import org.omg.PortableServer.ImplicitActivationPolicyValue ;
  56 import org.omg.PortableServer.ServantRetentionPolicyValue ;
  57 import org.omg.PortableServer.RequestProcessingPolicyValue ;
  58 import org.omg.PortableServer.POAPackage.AdapterAlreadyExists ;
  59 import org.omg.PortableServer.POAPackage.AdapterNonExistent ;
  60 import org.omg.PortableServer.POAPackage.InvalidPolicy ;
  61 import org.omg.PortableServer.POAPackage.WrongPolicy ;
  62 import org.omg.PortableServer.POAPackage.WrongAdapter ;
  63 import org.omg.PortableServer.POAPackage.NoServant ;
  64 import org.omg.PortableServer.POAPackage.ServantAlreadyActive ;
  65 import org.omg.PortableServer.POAPackage.ObjectAlreadyActive ;
  66 import org.omg.PortableServer.POAPackage.ServantNotActive ;
  67 import org.omg.PortableServer.POAPackage.ObjectNotActive ;
  68 
  69 import org.omg.PortableInterceptor.ObjectReferenceFactory ;
  70 import org.omg.PortableInterceptor.ObjectReferenceTemplate ;
  71 import org.omg.PortableInterceptor.NON_EXISTENT ;
  72 
  73 import org.omg.IOP.TAG_INTERNET_IOP ;
  74 
  75 import com.sun.corba.se.spi.copyobject.CopierManager ;
  76 import com.sun.corba.se.spi.copyobject.ObjectCopier ;
  77 import com.sun.corba.se.spi.copyobject.ObjectCopierFactory ;
  78 import com.sun.corba.se.spi.oa.OADestroyed ;
  79 import com.sun.corba.se.spi.oa.OAInvocationInfo ;
  80 import com.sun.corba.se.spi.oa.ObjectAdapter ;
  81 import com.sun.corba.se.spi.oa.ObjectAdapterBase ;
  82 import com.sun.corba.se.spi.oa.ObjectAdapterFactory ;
  83 import com.sun.corba.se.spi.ior.ObjectKeyTemplate ;
  84 import com.sun.corba.se.spi.ior.ObjectId ;
  85 import com.sun.corba.se.spi.ior.ObjectAdapterId ;
  86 import com.sun.corba.se.spi.ior.IOR ;
  87 import com.sun.corba.se.spi.ior.IORFactories ;
  88 import com.sun.corba.se.spi.ior.IORTemplate ;
  89 import com.sun.corba.se.spi.ior.IORTemplateList ;
  90 import com.sun.corba.se.spi.ior.TaggedProfile ;
  91 import com.sun.corba.se.spi.ior.iiop.IIOPProfile ;
  92 import com.sun.corba.se.spi.ior.iiop.IIOPAddress ;
  93 import com.sun.corba.se.spi.ior.iiop.IIOPFactories ;
  94 import com.sun.corba.se.spi.orb.ORB ;
  95 import com.sun.corba.se.spi.protocol.ForwardException ;
  96 import com.sun.corba.se.spi.transport.SocketOrChannelAcceptor;
  97 
  98 import com.sun.corba.se.impl.ior.POAObjectKeyTemplate ;
  99 import com.sun.corba.se.impl.ior.ObjectAdapterIdArray ;
 100 import com.sun.corba.se.impl.orbutil.ORBUtility;
 101 import com.sun.corba.se.impl.orbutil.ORBConstants;
 102 import com.sun.corba.se.impl.orbutil.concurrent.Sync ;
 103 import com.sun.corba.se.impl.orbutil.concurrent.SyncUtil ;
 104 import com.sun.corba.se.impl.orbutil.concurrent.ReentrantMutex ;
 105 import com.sun.corba.se.impl.orbutil.concurrent.CondVar ;
 106 
 107 /**
 108  * POAImpl is the implementation of the Portable Object Adapter. It
 109  * contains an implementation of the POA interfaces specified in
 110  * COBRA 2.3.1 chapter 11 (formal/99-10-07).  This implementation
 111  * is moving to comply with CORBA 3.0 due to the many clarifications
 112  * that have been made to the POA semantics since CORBA 2.3.1.
 113  * Specific comments have been added where 3.0 applies, but note that
 114  * we do not have the new 3.0 APIs yet.
 115  */
 116 public class POAImpl extends ObjectAdapterBase implements POA
 117 {
 118     private boolean debug ;
 119 
 120     /* POA creation takes place in 2 stages: first, the POAImpl constructor is
 121        called, then the initialize method is called.  This separation is
 122        needed because an AdapterActivator does not know the POAManager or
 123        the policies when
 124        the unknown_adapter method is invoked.  However, the POA must be created
 125        before the unknown_adapter method is invoked, so that the parent knows
 126        when concurrent attempts are made to create the same POA.
 127        Calling the POAImpl constructor results in a new POA in state STATE_START.
 128        Calling initialize( POAManager, Policies ) results in state STATE_RUN.
 129        Calling destroy results in STATE_DESTROY, which marks the beginning of
 130        POA destruction.
 131     */
 132 
 133     // Notes on concurrency.
 134     // The POA requires careful design for concurrency management to correctly
 135     // implement the specification and avoid deadlocks.  The order of acquiring
 136     // locks must respect the following locking hierarchy:
 137     //
 138     // 1. Lock POAs before POAManagers
 139     // 2. Lock a POA before locking its child POA
 140     //
 141     // Also note that there are 3 separate conditions on which threads may wait
 142     // in the POA, as defined by invokeCV, beingDestroyedCV, and
 143     // adapterActivatorCV.  This means that (for this reason as well as others)
 144     // we cannot simply use the standard Java synchronized primitive.
 145     // This implementation uses a modified version of Doug Lea's
 146     // util.concurrent (version 1.3.0) that supports reentrant
 147     // mutexes to handle the locking.  This will all be replaced by the new JSR
 148     // 166 concurrency primitives in J2SE 1.5 and later once the ORB moves to
 149     // J2SE 1.5.
 150 
 151     // POA state constants
 152     //
 153     // Note that ordering is important here: we must have the state defined in
 154     // this order so that ordered comparison is possible.
 155     // DO NOT CHANGE THE VALUES OF THE STATE CONSTANTS!!!  In particular, the
 156     // initialization related states must be lower than STATE_RUN.
 157     //
 158     // POA is created in STATE_START
 159     //
 160     // Valid state transitions:
 161     //
 162     // START to INIT                        after find_POA constructor call
 163     // START to RUN                         after initialize completes
 164     // INIT to INIT_DONE                    after initialize completes
 165     // INIT to DESTROYED                    after failed unknown_adapter
 166     // INIT_DONE to RUN                     after successful unknown_adapter
 167     // STATE_RUN to STATE_DESTROYING        after start of destruction
 168     // STATE_DESTROYING to STATE_DESTROYED  after destruction completes.
 169 
 170     private static final int STATE_START        = 0 ; // constructor complete
 171     private static final int STATE_INIT         = 1 ; // waiting for adapter activator
 172     private static final int STATE_INIT_DONE    = 2 ; // adapter activator called create_POA
 173     private static final int STATE_RUN          = 3 ; // initialized and running
 174     private static final int STATE_DESTROYING   = 4 ; // being destroyed
 175     private static final int STATE_DESTROYED    = 5 ; // destruction complete
 176 
 177     private String stateToString()
 178     {
 179         switch (state) {
 180             case STATE_START :
 181                 return "START" ;
 182             case STATE_INIT :
 183                 return "INIT" ;
 184             case STATE_INIT_DONE :
 185                 return "INIT_DONE" ;
 186             case STATE_RUN :
 187                 return "RUN" ;
 188             case STATE_DESTROYING :
 189                 return "DESTROYING" ;
 190             case STATE_DESTROYED :
 191                 return "DESTROYED" ;
 192             default :
 193                 return "UNKNOWN(" + state + ")" ;
 194         }
 195     }
 196 
 197     // Current state of the POA
 198     private int state ;
 199 
 200     // The POA request handler that performs all policy specific operations
 201     // Note that POAImpl handles all synchronization, so mediator is (mostly)
 202     // unsynchronized.
 203     private POAPolicyMediator mediator;
 204 
 205     // Representation of object adapter ID
 206     private int numLevels;          // counts depth of tree.  Root = 1.
 207     private ObjectAdapterId poaId ; // the actual object adapter ID for this POA
 208     private String name;            // the name of this POA
 209 
 210     private POAManagerImpl manager; // This POA's POAManager
 211     private int uniquePOAId ;       // ID for this POA that is unique relative
 212                                     // to the POAFactory, which has the same
 213                                     // lifetime as the ORB.
 214     private POAImpl parent;         // The POA that created this POA.
 215     private Map children;           // Map from name to POA of POAs created by
 216                                     // this POA.
 217 
 218     private AdapterActivator activator;
 219     private int invocationCount ; // pending invocations on this POA.
 220 
 221     // Data used to control POA concurrency
 222     // XXX revisit for JSR 166
 223 
 224     // Master lock for all POA synchronization.  See lock and unlock.
 225     // package private for access by AOMEntry.
 226     Sync poaMutex ;
 227 
 228     // Wait on this CV for AdapterActivator upcalls to complete
 229     private CondVar adapterActivatorCV ;
 230 
 231     // Wait on this CV for all active invocations to complete
 232     private CondVar invokeCV ;
 233 
 234     // Wait on this CV for the destroy method to complete doing its work
 235     private CondVar beingDestroyedCV ;
 236 
 237     // thread local variable to store a boolean to detect deadlock in
 238     // POA.destroy().
 239     protected ThreadLocal isDestroying ;
 240 
 241     // This includes the most important information for debugging
 242     // POA problems.
 243     public String toString()
 244     {
 245         return "POA[" + poaId.toString() +
 246             ", uniquePOAId=" + uniquePOAId +
 247             ", state=" + stateToString() +
 248             ", invocationCount=" + invocationCount + "]" ;
 249     }
 250 
 251     // package private for mediator implementations.
 252     boolean getDebug()
 253     {
 254         return debug ;
 255     }
 256 
 257     // package private for access to servant to POA map
 258     static POAFactory getPOAFactory( ORB orb )
 259     {
 260         return (POAFactory)orb.getRequestDispatcherRegistry().
 261             getObjectAdapterFactory( ORBConstants.TRANSIENT_SCID ) ;
 262     }
 263 
 264     // package private so that POAFactory can access it.
 265     static POAImpl makeRootPOA( ORB orb )
 266     {
 267         POAManagerImpl poaManager = new POAManagerImpl( getPOAFactory( orb ),
 268             orb.getPIHandler() ) ;
 269 
 270         POAImpl result = new POAImpl( ORBConstants.ROOT_POA_NAME,
 271             null, orb, STATE_START ) ;
 272         result.initialize( poaManager, Policies.rootPOAPolicies ) ;
 273 
 274         return result ;
 275     }
 276 
 277     // package private so that POAPolicyMediatorBase can access it.
 278     int getPOAId()
 279     {
 280         return uniquePOAId ;
 281     }
 282 
 283 
 284     // package private so that POAPolicyMediator can access it.
 285     void lock()
 286     {
 287         SyncUtil.acquire( poaMutex ) ;
 288 
 289         if (debug) {
 290             ORBUtility.dprint( this, "LOCKED poa " + this ) ;
 291         }
 292     }
 293 
 294     // package private so that POAPolicyMediator can access it.
 295     void unlock()
 296     {
 297         if (debug) {
 298             ORBUtility.dprint( this, "UNLOCKED poa " + this ) ;
 299         }
 300 
 301         poaMutex.release() ;
 302     }
 303 
 304     // package private so that DelegateImpl can access it.
 305     Policies getPolicies()
 306     {
 307         return mediator.getPolicies() ;
 308     }
 309 
 310     // Note that the parent POA must be locked when this constructor is called.
 311     private POAImpl( String name, POAImpl parent, ORB orb, int initialState )
 312     {
 313         super( orb ) ;
 314 
 315         debug = orb.poaDebugFlag ;
 316 
 317         if (debug) {
 318             ORBUtility.dprint( this, "Creating POA with name=" + name +
 319                 " parent=" + parent ) ;
 320         }
 321 
 322         this.state     = initialState ;
 323         this.name      = name ;
 324         this.parent    = parent;
 325         children = new HashMap();
 326         activator = null ;
 327 
 328         // This was done in initialize, but I moved it here
 329         // to get better searchability when tracing.
 330         uniquePOAId = getPOAFactory( orb ).newPOAId() ;
 331 
 332         if (parent == null) {
 333             // This is the root POA, which counts as 1 level
 334             numLevels = 1 ;
 335         } else {
 336             // My level is one more than that of my parent
 337             numLevels = parent.numLevels + 1 ;
 338 
 339             parent.children.put(name, this);
 340         }
 341 
 342         // Get an array of all of the POA names in order to
 343         // create the poaid.
 344         String[] names = new String[ numLevels ] ;
 345         POAImpl poaImpl = this ;
 346         int ctr = numLevels - 1 ;
 347         while (poaImpl != null) {
 348             names[ctr--] = poaImpl.name ;
 349             poaImpl = poaImpl.parent ;
 350         }
 351 
 352         poaId = new ObjectAdapterIdArray( names ) ;
 353 
 354         invocationCount = 0;
 355 
 356         poaMutex = new ReentrantMutex( orb.poaConcurrencyDebugFlag ) ;
 357 
 358         adapterActivatorCV = new CondVar( poaMutex,
 359             orb.poaConcurrencyDebugFlag ) ;
 360         invokeCV           = new CondVar( poaMutex,
 361             orb.poaConcurrencyDebugFlag ) ;
 362         beingDestroyedCV   = new CondVar( poaMutex,
 363             orb.poaConcurrencyDebugFlag ) ;
 364 
 365         isDestroying = new ThreadLocal () {
 366             protected java.lang.Object initialValue() {
 367                 return Boolean.FALSE;
 368             }
 369         };
 370     }
 371 
 372     // The POA lock must be held when this method is called.
 373     private void initialize( POAManagerImpl manager, Policies policies )
 374     {
 375         if (debug) {
 376             ORBUtility.dprint( this, "Initializing poa " + this +
 377                 " with POAManager=" + manager + " policies=" + policies ) ;
 378         }
 379 
 380         this.manager = manager;
 381         manager.addPOA(this);
 382 
 383         mediator = POAPolicyMediatorFactory.create( policies, this ) ;
 384 
 385         // Construct the object key template
 386         int serverid = mediator.getServerId() ;
 387         int scid = mediator.getScid() ;
 388         String orbId = getORB().getORBData().getORBId();
 389 
 390         ObjectKeyTemplate oktemp = new POAObjectKeyTemplate( getORB(),
 391             scid, serverid, orbId, poaId ) ;
 392 
 393         if (debug) {
 394             ORBUtility.dprint( this, "Initializing poa: oktemp=" + oktemp ) ;
 395         }
 396 
 397         // Note that parent == null iff this is the root POA.
 398         // This was used to avoid executing interceptors on the RootPOA.
 399         // That is no longer necessary.
 400         boolean objectAdapterCreated = true; // parent != null ;
 401 
 402         // XXX extract codebase from policies and pass into initializeTemplate
 403         // after the codebase policy change is finalized.
 404         initializeTemplate( oktemp, objectAdapterCreated,
 405                             policies,
 406                             null, // codebase
 407                             null, // manager id
 408                             oktemp.getObjectAdapterId()
 409                             ) ;
 410 
 411         if (state == STATE_START)
 412             state = STATE_RUN ;
 413         else if (state == STATE_INIT)
 414             state = STATE_INIT_DONE ;
 415         else
 416             throw lifecycleWrapper().illegalPoaStateTrans() ;
 417     }
 418 
 419     // The poaMutex must be held when this method is called
 420     private boolean waitUntilRunning()
 421     {
 422         if (debug) {
 423             ORBUtility.dprint( this,
 424                 "Calling waitUntilRunning on poa " + this ) ;
 425         }
 426 
 427         while (state < STATE_RUN) {
 428             try {
 429                 adapterActivatorCV.await() ;
 430             } catch (InterruptedException exc) {
 431                 // NO-OP
 432             }
 433         }
 434 
 435         if (debug) {
 436             ORBUtility.dprint( this,
 437                 "Exiting waitUntilRunning on poa " + this ) ;
 438         }
 439 
 440         // Note that a POA could be destroyed while in STATE_INIT due to a
 441         // failure in the AdapterActivator upcall.
 442         return (state == STATE_RUN) ;
 443     }
 444 
 445     // This method checks that the AdapterActivator finished the
 446     // initialization of a POA activated in find_POA.  This is
 447     // determined by checking the state of the POA.  If the state is
 448     // STATE_INIT, the AdapterActivator did not complete the
 449     // inialization.  In this case, we destroy the POA that was
 450     // partially created and return false.  Otherwise, we return true.
 451     // In any case, we must wake up all threads waiting for the adapter
 452     // activator, either to continue their invocations, or to return
 453     // errors to their client.
 454     //
 455     // The poaMutex must NOT be held when this method is called.
 456     private boolean destroyIfNotInitDone()
 457     {
 458         try {
 459             lock() ;
 460 
 461             if (debug) {
 462                 ORBUtility.dprint( this,
 463                     "Calling destroyIfNotInitDone on poa " + this ) ;
 464             }
 465 
 466             boolean success = (state == STATE_INIT_DONE) ;
 467 
 468             if (success)
 469                 state = STATE_RUN ;
 470             else {
 471                 // Don't just use destroy, because the check for
 472                 // deadlock is too general, and can prevent this from
 473                 // functioning properly.
 474                 DestroyThread destroyer = new DestroyThread( false, debug );
 475                 destroyer.doIt( this, true ) ;
 476             }
 477 
 478             return success ;
 479         } finally {
 480             adapterActivatorCV.broadcast() ;
 481 
 482             if (debug) {
 483                 ORBUtility.dprint( this,
 484                     "Exiting destroyIfNotInitDone on poa " + this ) ;
 485             }
 486 
 487             unlock() ;
 488         }
 489     }
 490 
 491     private byte[] internalReferenceToId(
 492         org.omg.CORBA.Object reference ) throws WrongAdapter
 493     {
 494         IOR ior = ORBUtility.getIOR( reference ) ;
 495         IORTemplateList thisTemplate = ior.getIORTemplates() ;
 496 
 497         ObjectReferenceFactory orf = getCurrentFactory() ;
 498         IORTemplateList poaTemplate =
 499             IORFactories.getIORTemplateList( orf ) ;
 500 
 501         if (!poaTemplate.isEquivalent( thisTemplate ))
 502             throw new WrongAdapter();
 503 
 504         // Extract the ObjectId from the first TaggedProfile in the IOR.
 505         // If ior was created in this POA, the same ID was used for
 506         // every profile through the profile templates in the currentFactory,
 507         // so we will get the same result from any profile.
 508         Iterator iter = ior.iterator() ;
 509         if (!iter.hasNext())
 510             throw iorWrapper().noProfilesInIor() ;
 511         TaggedProfile prof = (TaggedProfile)(iter.next()) ;
 512         ObjectId oid = prof.getObjectId() ;
 513 
 514         return oid.getId();
 515     }
 516 
 517     // Converted from anonymous class to local class
 518     // so that we can call performDestroy() directly.
 519     static class DestroyThread extends sun.misc.ManagedLocalsThread {
 520         private boolean wait ;
 521         private boolean etherealize ;
 522         private boolean debug ;
 523         private POAImpl thePoa ;
 524 
 525         public DestroyThread( boolean etherealize, boolean debug )
 526         {
 527             this.etherealize = etherealize ;
 528             this.debug = debug ;
 529         }
 530 
 531         public void doIt( POAImpl thePoa, boolean wait )
 532         {
 533             if (debug) {
 534                 ORBUtility.dprint( this,
 535                     "Calling DestroyThread.doIt(thePOA=" + thePoa +
 536                     " wait=" + wait + " etherealize=" + etherealize ) ;
 537             }
 538 
 539             this.thePoa = thePoa ;
 540             this.wait = wait ;
 541 
 542             if (wait) {
 543                 run() ;
 544             } else {
 545                 // Catch exceptions since setDaemon can cause a
 546                 // security exception to be thrown under netscape
 547                 // in the Applet mode
 548                 try { setDaemon(true); } catch (Exception e) {}
 549                 start() ;
 550             }
 551         }
 552 
 553         public void run()
 554         {
 555             Set destroyedPOATemplates = new HashSet() ;
 556 
 557             performDestroy( thePoa, destroyedPOATemplates );
 558 
 559             Iterator iter = destroyedPOATemplates.iterator() ;
 560             ObjectReferenceTemplate[] orts = new ObjectReferenceTemplate[
 561                 destroyedPOATemplates.size() ] ;
 562             int index = 0 ;
 563             while (iter.hasNext())
 564                 orts[ index++ ] = (ObjectReferenceTemplate)iter.next();
 565 
 566             thePoa.getORB().getPIHandler().adapterStateChanged( orts,
 567                 NON_EXISTENT.value ) ;
 568         }
 569 
 570         // Returns true if destruction must be completed, false
 571         // if not, which means that another thread is already
 572         // destroying poa.
 573         private boolean prepareForDestruction( POAImpl poa,
 574             Set destroyedPOATemplates )
 575         {
 576             POAImpl[] childPoas = null ;
 577 
 578             // Note that we do not synchronize on this, since this is
 579             // the PerformDestroy instance, not the POA.
 580             try {
 581                 poa.lock() ;
 582 
 583                 if (debug) {
 584                     ORBUtility.dprint( this,
 585                         "Calling performDestroy on poa " + poa ) ;
 586                 }
 587 
 588                 if (poa.state <= STATE_RUN) {
 589                     poa.state = STATE_DESTROYING ;
 590                 } else {
 591                     // destroy may be called multiple times, and each call
 592                     // is allowed to proceed with its own setting of the wait
 593                     // flag, but the etherealize value is used from the first
 594                     // call to destroy.  Also all children should be destroyed
 595                     // before the parent POA.  If the poa is already destroyed,
 596                     // we can just return.  If the poa has started destruction,
 597                     // but not completed, and wait is true, we need to wait
 598                     // until destruction is complete, then just return.
 599                     if (wait)
 600                         while (poa.state != STATE_DESTROYED) {
 601                             try {
 602                                 poa.beingDestroyedCV.await() ;
 603                             } catch (InterruptedException exc) {
 604                                 // NO-OP
 605                             }
 606                         }
 607 
 608                     return false ;
 609                 }
 610 
 611                 poa.isDestroying.set(Boolean.TRUE);
 612 
 613                 // Make a copy since we can't hold the lock while destroying
 614                 // the children, and an iterator is not deletion-safe.
 615                 childPoas = (POAImpl[])poa.children.values().toArray(
 616                     new POAImpl[0] );
 617             } finally {
 618                 poa.unlock() ;
 619             }
 620 
 621             // We are not holding the POA mutex here to avoid holding it
 622             // while destroying the POA's children, since this may involve
 623             // upcalls to etherealize methods.
 624 
 625             for (int ctr=0; ctr<childPoas.length; ctr++ ) {
 626                 performDestroy( childPoas[ctr], destroyedPOATemplates ) ;
 627             }
 628 
 629             return true ;
 630         }
 631 
 632         public void performDestroy( POAImpl poa, Set destroyedPOATemplates )
 633         {
 634             if (!prepareForDestruction( poa, destroyedPOATemplates ))
 635                 return ;
 636 
 637             // NOTE: If we are here, poa is in STATE_DESTROYING state. All
 638             // other state checks are taken care of in prepareForDestruction.
 639             // No other threads may either be starting new invocations
 640             // by calling enter or starting to destroy poa.  There may
 641             // still be pending invocations.
 642 
 643             POAImpl parent = poa.parent ;
 644             boolean isRoot = parent == null ;
 645 
 646             try {
 647                 // Note that we must lock the parent before the child.
 648                 // The parent lock is required (if poa is not the root)
 649                 // to safely remove poa from parent's children Map.
 650                 if (!isRoot)
 651                     parent.lock() ;
 652 
 653                 try {
 654                     poa.lock() ;
 655 
 656                     completeDestruction( poa, parent,
 657                         destroyedPOATemplates ) ;
 658                 } finally {
 659                     poa.unlock() ;
 660 
 661                     if (isRoot)
 662                         // We have just destroyed the root POA, so we need to
 663                         // make sure that the next call to
 664                         // resolve_initial_reference( "RootPOA" )
 665                         // will recreate a valid root POA.
 666                         poa.manager.getFactory().registerRootPOA() ;
 667                 }
 668             } finally {
 669                 if (!isRoot) {
 670                     parent.unlock() ;
 671                     poa.parent = null ;
 672                 }
 673             }
 674         }
 675 
 676         private void completeDestruction( POAImpl poa, POAImpl parent,
 677             Set destroyedPOATemplates )
 678         {
 679             if (debug) {
 680                 ORBUtility.dprint( this,
 681                     "Calling completeDestruction on poa " + poa ) ;
 682             }
 683 
 684             try {
 685                 while (poa.invocationCount != 0) {
 686                     try {
 687                         poa.invokeCV.await() ;
 688                     } catch (InterruptedException ex) {
 689                         // NO-OP
 690                     }
 691                 }
 692 
 693                 if (poa.mediator != null) {
 694                     if (etherealize)
 695                         poa.mediator.etherealizeAll();
 696 
 697                     poa.mediator.clearAOM() ;
 698                 }
 699 
 700                 if (poa.manager != null)
 701                     poa.manager.removePOA(poa);
 702 
 703                 if (parent != null)
 704                     parent.children.remove( poa.name ) ;
 705 
 706                 destroyedPOATemplates.add( poa.getAdapterTemplate() ) ;
 707             } catch (Throwable thr) {
 708                 if (thr instanceof ThreadDeath)
 709                     throw (ThreadDeath)thr ;
 710 
 711                 poa.lifecycleWrapper().unexpectedException( thr, poa.toString() ) ;
 712             } finally {
 713                 poa.state = STATE_DESTROYED ;
 714                 poa.beingDestroyedCV.broadcast();
 715                 poa.isDestroying.set(Boolean.FALSE);
 716 
 717                 if (debug) {
 718                     ORBUtility.dprint( this,
 719                         "Exiting completeDestruction on poa " + poa ) ;
 720                 }
 721             }
 722         }
 723     }
 724 
 725     void etherealizeAll()
 726     {
 727         try {
 728             lock() ;
 729 
 730             if (debug) {
 731                 ORBUtility.dprint( this,
 732                     "Calling etheralizeAll on poa " + this ) ;
 733             }
 734 
 735             mediator.etherealizeAll() ;
 736         } finally {
 737             if (debug) {
 738                 ORBUtility.dprint( this,
 739                     "Exiting etheralizeAll on poa " + this ) ;
 740             }
 741 
 742             unlock() ;
 743         }
 744     }
 745 
 746  //*******************************************************************
 747  // Public POA API
 748  //*******************************************************************
 749 
 750     /**
 751      * <code>create_POA</code>
 752      * <b>Section 3.3.8.2</b>
 753      */
 754     public POA create_POA(String name, POAManager
 755         theManager, Policy[] policies) throws AdapterAlreadyExists,
 756         InvalidPolicy
 757     {
 758         try {
 759             lock() ;
 760 
 761             if (debug) {
 762                 ORBUtility.dprint( this, "Calling create_POA(name=" + name +
 763                     " theManager=" + theManager + " policies=" + policies +
 764                     ") on poa " + this ) ;
 765             }
 766 
 767             // We cannot create children of a POA that is (being) destroyed.
 768             // This has been added to the CORBA 3.0 spec.
 769             if (state > STATE_RUN)
 770                 throw omgLifecycleWrapper().createPoaDestroy() ;
 771 
 772             POAImpl poa = (POAImpl)(children.get(name)) ;
 773 
 774             if (poa == null) {
 775                 poa = new POAImpl( name, this, getORB(), STATE_START ) ;
 776             }
 777 
 778             try {
 779                 poa.lock() ;
 780 
 781                 if (debug) {
 782                     ORBUtility.dprint( this,
 783                         "Calling create_POA: new poa is " + poa ) ;
 784                 }
 785 
 786                 if ((poa.state != STATE_START) && (poa.state != STATE_INIT))
 787                     throw new AdapterAlreadyExists();
 788 
 789                 POAManagerImpl newManager = (POAManagerImpl)theManager ;
 790                 if (newManager == null)
 791                     newManager = new POAManagerImpl( manager.getFactory(),
 792                         manager.getPIHandler() );
 793 
 794                 int defaultCopierId =
 795                     getORB().getCopierManager().getDefaultId() ;
 796                 Policies POAPolicies =
 797                     new Policies( policies, defaultCopierId ) ;
 798 
 799                 poa.initialize( newManager, POAPolicies ) ;
 800 
 801                 return poa;
 802             } finally {
 803                 poa.unlock() ;
 804             }
 805         } finally {
 806             unlock() ;
 807         }
 808     }
 809 
 810     /**
 811      * <code>find_POA</code>
 812      * <b>Section 3.3.8.3</b>
 813      */
 814     public POA find_POA(String name, boolean activate)
 815         throws AdapterNonExistent
 816     {
 817         POAImpl found = null ;
 818         AdapterActivator act = null ;
 819 
 820         lock() ;
 821 
 822         if (debug) {
 823             ORBUtility.dprint( this, "Calling find_POA(name=" + name +
 824                 " activate=" + activate + ") on poa " + this ) ;
 825         }
 826 
 827         found = (POAImpl) children.get(name);
 828 
 829         if (found != null) {
 830             if (debug) {
 831                 ORBUtility.dprint( this,
 832                     "Calling find_POA: found poa " + found ) ;
 833             }
 834 
 835             try {
 836                 found.lock() ;
 837 
 838                 // Do not hold the parent POA lock while
 839                 // waiting for child to complete initialization.
 840                 unlock() ;
 841 
 842                 // Make sure that the child has completed its initialization,
 843                 // if it was created by an AdapterActivator, otherwise throw
 844                 // a standard TRANSIENT exception with minor code 4 (see
 845                 // CORBA 3.0 11.3.9.3, in reference to unknown_adapter)
 846                 if (!found.waitUntilRunning())
 847                     throw omgLifecycleWrapper().poaDestroyed() ;
 848 
 849                 // Note that found may be in state DESTROYING or DESTROYED at
 850                 // this point.  That's OK, since destruction could start at
 851                 // any time.
 852             } finally {
 853                 found.unlock() ;
 854             }
 855         } else {
 856             try {
 857                 if (debug) {
 858                     ORBUtility.dprint( this,
 859                         "Calling find_POA: no poa found" ) ;
 860                 }
 861 
 862                 if (activate && (activator != null)) {
 863                     // Create a child, but don't initialize it.  The newly
 864                     // created POA will be in state STATE_START, which will
 865                     // cause other calls to find_POA that are creating the same
 866                     // POA to block on the waitUntilRunning call above.
 867                     // Initialization must be completed by a call to create_POA
 868                     // inside the unknown_adapter upcall.  Note that
 869                     // this.poaMutex must be held here so that this.children
 870                     // can be safely updated.  The state is set to STATE_INIT
 871                     // so that initialize can make the correct state transition
 872                     // when create_POA is called inside the AdapterActivator.
 873                     // This avoids activating the new POA too soon
 874                     // by transitioning to STATE_RUN after unknown_adapter
 875                     // returns.
 876                     found = new POAImpl( name, this, getORB(), STATE_INIT ) ;
 877 
 878                     if (debug) {
 879                         ORBUtility.dprint( this,
 880                             "Calling find_POA: created poa " + found ) ;
 881                     }
 882 
 883                     act = activator ;
 884                 } else {
 885                     throw new AdapterNonExistent();
 886                 }
 887             } finally {
 888                 unlock() ;
 889             }
 890         }
 891 
 892         // assert (found != null)
 893         // assert not holding this.poaMutex OR found.poaMutex
 894 
 895         // We must not hold either this.poaMutex or found.poaMutex here while
 896         // waiting for intialization of found to complete to prevent possible
 897         // deadlocks.
 898 
 899         if (act != null) {
 900             boolean status = false ;
 901             boolean adapterResult = false ;
 902 
 903             if (debug) {
 904                 ORBUtility.dprint( this,
 905                     "Calling find_POA: calling AdapterActivator"  ) ;
 906             }
 907 
 908             try {
 909                 // Prevent more than one thread at a time from executing in act
 910                 // in case act is shared between multiple POAs.
 911                 synchronized (act) {
 912                     status = act.unknown_adapter(this, name);
 913                 }
 914             } catch (SystemException exc) {
 915                 throw omgLifecycleWrapper().adapterActivatorException( exc,
 916                     name, poaId.toString() ) ;
 917             } catch (Throwable thr) {
 918                 // ignore most non-system exceptions, but log them for
 919                 // diagnostic purposes.
 920                 lifecycleWrapper().unexpectedException( thr, this.toString() ) ;
 921 
 922                 if (thr instanceof ThreadDeath)
 923                     throw (ThreadDeath)thr ;
 924             } finally {
 925                 // At this point, we have completed adapter activation.
 926                 // Whether this was successful or not, we must call
 927                 // destroyIfNotInitDone so that calls to enter() and create_POA()
 928                 // that are waiting can execute again.  Failing to do this
 929                 // will cause the system to hang in complex tests.
 930                 adapterResult = found.destroyIfNotInitDone() ;
 931             }
 932 
 933             if (status) {
 934                 if (!adapterResult)
 935                     throw omgLifecycleWrapper().adapterActivatorException( name,
 936                         poaId.toString() ) ;
 937             } else {
 938                 if (debug) {
 939                     ORBUtility.dprint( this,
 940                         "Calling find_POA: AdapterActivator returned false"  ) ;
 941                 }
 942 
 943                 // OMG Issue 3740 is resolved to throw AdapterNonExistent if
 944                 // unknown_adapter() returns false.
 945                 throw new AdapterNonExistent();
 946             }
 947         }
 948 
 949         return found;
 950     }
 951 
 952     /**
 953      * <code>destroy</code>
 954      * <b>Section 3.3.8.4</b>
 955      */
 956     public void destroy(boolean etherealize, boolean wait_for_completion)
 957     {
 958         // This is to avoid deadlock
 959         if (wait_for_completion && getORB().isDuringDispatch()) {
 960             throw lifecycleWrapper().destroyDeadlock() ;
 961         }
 962 
 963         DestroyThread destroyer = new DestroyThread( etherealize, debug );
 964         destroyer.doIt( this, wait_for_completion ) ;
 965     }
 966 
 967     /**
 968      * <code>create_thread_policy</code>
 969      * <b>Section 3.3.8.5</b>
 970      */
 971     public ThreadPolicy create_thread_policy(
 972         ThreadPolicyValue value)
 973     {
 974         return new ThreadPolicyImpl(value);
 975     }
 976 
 977     /**
 978      * <code>create_lifespan_policy</code>
 979      * <b>Section 3.3.8.5</b>
 980      */
 981     public LifespanPolicy create_lifespan_policy(
 982         LifespanPolicyValue value)
 983     {
 984         return new LifespanPolicyImpl(value);
 985     }
 986 
 987     /**
 988      * <code>create_id_uniqueness_policy</code>
 989      * <b>Section 3.3.8.5</b>
 990      */
 991     public IdUniquenessPolicy create_id_uniqueness_policy(
 992         IdUniquenessPolicyValue value)
 993     {
 994         return new IdUniquenessPolicyImpl(value);
 995     }
 996 
 997     /**
 998      * <code>create_id_assignment_policy</code>
 999      * <b>Section 3.3.8.5</b>
1000      */
1001     public IdAssignmentPolicy create_id_assignment_policy(
1002         IdAssignmentPolicyValue value)
1003     {
1004         return new IdAssignmentPolicyImpl(value);
1005     }
1006 
1007     /**
1008      * <code>create_implicit_activation_policy</code>
1009      * <b>Section 3.3.8.5</b>
1010      */
1011     public ImplicitActivationPolicy create_implicit_activation_policy(
1012         ImplicitActivationPolicyValue value)
1013     {
1014         return new ImplicitActivationPolicyImpl(value);
1015     }
1016 
1017     /**
1018      * <code>create_servant_retention_policy</code>
1019      * <b>Section 3.3.8.5</b>
1020      */
1021     public ServantRetentionPolicy create_servant_retention_policy(
1022         ServantRetentionPolicyValue value)
1023     {
1024         return new ServantRetentionPolicyImpl(value);
1025     }
1026 
1027     /**
1028      * <code>create_request_processing_policy</code>
1029      * <b>Section 3.3.8.5</b>
1030      */
1031     public RequestProcessingPolicy create_request_processing_policy(
1032         RequestProcessingPolicyValue value)
1033     {
1034         return new RequestProcessingPolicyImpl(value);
1035     }
1036 
1037     /**
1038      * <code>the_name</code>
1039      * <b>Section 3.3.8.6</b>
1040      */
1041     public String the_name()
1042     {
1043         try {
1044             lock() ;
1045 
1046             return name;
1047         } finally {
1048             unlock() ;
1049         }
1050     }
1051 
1052     /**
1053      * <code>the_parent</code>
1054      * <b>Section 3.3.8.7</b>
1055      */
1056     public POA the_parent()
1057     {
1058         try {
1059             lock() ;
1060 
1061             return parent;
1062         } finally {
1063             unlock() ;
1064         }
1065     }
1066 
1067     /**
1068      * <code>the_children</code>
1069      */
1070     public org.omg.PortableServer.POA[] the_children()
1071     {
1072         try {
1073             lock() ;
1074 
1075             Collection coll = children.values() ;
1076             int size = coll.size() ;
1077             POA[] result = new POA[ size ] ;
1078             int index = 0 ;
1079             Iterator iter = coll.iterator() ;
1080             while (iter.hasNext()) {
1081                 POA poa = (POA)(iter.next()) ;
1082                 result[ index++ ] = poa ;
1083             }
1084 
1085             return result ;
1086         } finally {
1087             unlock() ;
1088         }
1089     }
1090 
1091     /**
1092      * <code>the_POAManager</code>
1093      * <b>Section 3.3.8.8</b>
1094      */
1095     public POAManager the_POAManager()
1096     {
1097         try {
1098             lock() ;
1099 
1100             return manager;
1101         } finally {
1102             unlock() ;
1103         }
1104     }
1105 
1106     /**
1107      * <code>the_activator</code>
1108      * <b>Section 3.3.8.9</b>
1109      */
1110     public AdapterActivator the_activator()
1111     {
1112         try {
1113             lock() ;
1114 
1115             return activator;
1116         } finally {
1117             unlock() ;
1118         }
1119     }
1120 
1121     /**
1122      * <code>the_activator</code>
1123      * <b>Section 3.3.8.9</b>
1124      */
1125     public void the_activator(AdapterActivator activator)
1126     {
1127         try {
1128             lock() ;
1129 
1130             if (debug) {
1131                 ORBUtility.dprint( this, "Calling the_activator on poa " +
1132                     this + " activator=" + activator ) ;
1133             }
1134 
1135             this.activator = activator;
1136         } finally {
1137             unlock() ;
1138         }
1139     }
1140 
1141     /**
1142      * <code>get_servant_manager</code>
1143      * <b>Section 3.3.8.10</b>
1144      */
1145     public ServantManager get_servant_manager() throws WrongPolicy
1146     {
1147         try {
1148             lock() ;
1149 
1150             return mediator.getServantManager() ;
1151         } finally {
1152             unlock() ;
1153         }
1154     }
1155 
1156     /**
1157      * <code>set_servant_manager</code>
1158      * <b>Section 3.3.8.10</b>
1159      */
1160     public void set_servant_manager(ServantManager servantManager)
1161         throws WrongPolicy
1162     {
1163         try {
1164             lock() ;
1165 
1166             if (debug) {
1167                 ORBUtility.dprint( this, "Calling set_servant_manager on poa " +
1168                     this + " servantManager=" + servantManager ) ;
1169             }
1170 
1171             mediator.setServantManager( servantManager ) ;
1172         } finally {
1173             unlock() ;
1174         }
1175     }
1176 
1177     /**
1178      * <code>get_servant</code>
1179      * <b>Section 3.3.8.12</b>
1180      */
1181     public Servant get_servant() throws NoServant, WrongPolicy
1182     {
1183         try {
1184             lock() ;
1185 
1186             return mediator.getDefaultServant() ;
1187         } finally {
1188             unlock() ;
1189         }
1190     }
1191 
1192     /**
1193      * <code>set_servant</code>
1194      * <b>Section 3.3.8.13</b>
1195      */
1196     public void set_servant(Servant defaultServant)
1197         throws WrongPolicy
1198     {
1199         try {
1200             lock() ;
1201 
1202             if (debug) {
1203                 ORBUtility.dprint( this, "Calling set_servant on poa " +
1204                     this + " defaultServant=" + defaultServant ) ;
1205             }
1206 
1207             mediator.setDefaultServant( defaultServant ) ;
1208         } finally {
1209             unlock() ;
1210         }
1211     }
1212 
1213     /**
1214      * <code>activate_object</code>
1215      * <b>Section 3.3.8.14</b>
1216      */
1217     public byte[] activate_object(Servant servant)
1218         throws ServantAlreadyActive, WrongPolicy
1219     {
1220         try {
1221             lock() ;
1222 
1223             if (debug) {
1224                 ORBUtility.dprint( this,
1225                     "Calling activate_object on poa " + this +
1226                     " (servant=" + servant + ")" ) ;
1227             }
1228 
1229             // Allocate a new system-generated object-id.
1230             // This will throw WrongPolicy if not SYSTEM_ID
1231             // policy.
1232             byte[] id = mediator.newSystemId();
1233 
1234             try {
1235                 mediator.activateObject( id, servant ) ;
1236             } catch (ObjectAlreadyActive oaa) {
1237                 // This exception can not occur in this case,
1238                 // since id is always brand new.
1239                 //
1240             }
1241 
1242             return id ;
1243         } finally {
1244             if (debug) {
1245                 ORBUtility.dprint( this,
1246                     "Exiting activate_object on poa " + this ) ;
1247             }
1248 
1249             unlock() ;
1250         }
1251     }
1252 
1253     /**
1254      * <code>activate_object_with_id</code>
1255      * <b>Section 3.3.8.15</b>
1256      */
1257     public void activate_object_with_id(byte[] id,
1258                                                      Servant servant)
1259         throws ObjectAlreadyActive, ServantAlreadyActive, WrongPolicy
1260     {
1261         try {
1262             lock() ;
1263 
1264             if (debug) {
1265                 ORBUtility.dprint( this,
1266                     "Calling activate_object_with_id on poa " + this +
1267                     " (servant=" + servant + " id=" + id + ")" ) ;
1268             }
1269 
1270             // Clone the id to avoid possible errors due to aliasing
1271             // (e.g. the client passes the id in and then changes it later).
1272             byte[] idClone = (byte[])(id.clone()) ;
1273 
1274             mediator.activateObject( idClone, servant ) ;
1275         } finally {
1276             if (debug) {
1277                 ORBUtility.dprint( this,
1278                     "Exiting activate_object_with_id on poa " + this ) ;
1279             }
1280 
1281             unlock() ;
1282         }
1283     }
1284 
1285     /**
1286      * <code>deactivate_object</code>
1287      * <b>3.3.8.16</b>
1288      */
1289     public void deactivate_object(byte[] id)
1290         throws ObjectNotActive, WrongPolicy
1291     {
1292         try {
1293             lock() ;
1294 
1295             if (debug) {
1296                 ORBUtility.dprint( this,
1297                     "Calling deactivate_object on poa " + this +
1298                     " (id=" + id + ")" ) ;
1299             }
1300 
1301             mediator.deactivateObject( id ) ;
1302         } finally {
1303             if (debug) {
1304                 ORBUtility.dprint( this,
1305                     "Exiting deactivate_object on poa " + this ) ;
1306             }
1307 
1308             unlock() ;
1309         }
1310     }
1311 
1312     /**
1313      * <code>create_reference</code>
1314      * <b>3.3.8.17</b>
1315      */
1316     public org.omg.CORBA.Object create_reference(String repId)
1317         throws WrongPolicy
1318     {
1319         try {
1320             lock() ;
1321 
1322             if (debug) {
1323                 ORBUtility.dprint( this, "Calling create_reference(repId=" +
1324                     repId + ") on poa " + this ) ;
1325             }
1326 
1327             return makeObject( repId, mediator.newSystemId()) ;
1328         } finally {
1329             unlock() ;
1330         }
1331     }
1332 
1333     /**
1334      * <code>create_reference_with_id</code>
1335      * <b>3.3.8.18</b>
1336      */
1337     public org.omg.CORBA.Object
1338         create_reference_with_id(byte[] oid, String repId)
1339     {
1340         try {
1341             lock() ;
1342 
1343             if (debug) {
1344                 ORBUtility.dprint( this,
1345                     "Calling create_reference_with_id(oid=" +
1346                     oid + " repId=" + repId + ") on poa " + this ) ;
1347             }
1348 
1349             // Clone the id to avoid possible errors due to aliasing
1350             // (e.g. the client passes the id in and then changes it later).
1351             byte[] idClone = (byte[])(oid.clone()) ;
1352 
1353             return makeObject( repId, idClone ) ;
1354         } finally {
1355             unlock() ;
1356         }
1357     }
1358 
1359     /**
1360      * <code>servant_to_id</code>
1361      * <b>3.3.8.19</b>
1362      */
1363     public byte[] servant_to_id(Servant servant)
1364         throws ServantNotActive, WrongPolicy
1365     {
1366         try {
1367             lock() ;
1368 
1369             if (debug) {
1370                 ORBUtility.dprint( this, "Calling servant_to_id(servant=" +
1371                     servant + ") on poa " + this ) ;
1372             }
1373 
1374             return mediator.servantToId( servant ) ;
1375         } finally {
1376             unlock() ;
1377         }
1378     }
1379 
1380     /**
1381      * <code>servant_to_reference</code>
1382      * <b>3.3.8.20</b>
1383      */
1384     public org.omg.CORBA.Object servant_to_reference(Servant servant)
1385         throws ServantNotActive, WrongPolicy
1386     {
1387         try {
1388             lock() ;
1389 
1390             if (debug) {
1391                 ORBUtility.dprint( this,
1392                     "Calling servant_to_reference(servant=" +
1393                     servant + ") on poa " + this ) ;
1394             }
1395 
1396             byte[] oid = mediator.servantToId(servant);
1397             String repId = servant._all_interfaces( this, oid )[0] ;
1398             return create_reference_with_id(oid, repId);
1399         } finally {
1400             unlock() ;
1401         }
1402     }
1403 
1404     /**
1405      * <code>reference_to_servant</code>
1406      * <b>3.3.8.21</b>
1407      */
1408     public Servant reference_to_servant(org.omg.CORBA.Object reference)
1409         throws ObjectNotActive, WrongPolicy, WrongAdapter
1410     {
1411         try {
1412             lock() ;
1413 
1414             if (debug) {
1415                 ORBUtility.dprint( this,
1416                     "Calling reference_to_servant(reference=" +
1417                     reference + ") on poa " + this ) ;
1418             }
1419 
1420             if ( state >= STATE_DESTROYING ) {
1421                 throw lifecycleWrapper().adapterDestroyed() ;
1422             }
1423 
1424             // reference_to_id should throw WrongAdapter
1425             // if the objref was not created by this POA
1426             byte [] id = internalReferenceToId(reference);
1427 
1428             return mediator.idToServant( id ) ;
1429         } finally {
1430             unlock() ;
1431         }
1432     }
1433 
1434     /**
1435      * <code>reference_to_id</code>
1436      * <b>3.3.8.22</b>
1437      */
1438     public byte[] reference_to_id(org.omg.CORBA.Object reference)
1439         throws WrongAdapter, WrongPolicy
1440     {
1441         try {
1442             lock() ;
1443 
1444             if (debug) {
1445                 ORBUtility.dprint( this, "Calling reference_to_id(reference=" +
1446                     reference + ") on poa " + this ) ;
1447             }
1448 
1449             if( state >= STATE_DESTROYING ) {
1450                 throw lifecycleWrapper().adapterDestroyed() ;
1451             }
1452 
1453             return internalReferenceToId( reference ) ;
1454         } finally {
1455             unlock() ;
1456         }
1457     }
1458 
1459     /**
1460      * <code>id_to_servant</code>
1461      * <b>3.3.8.23</b>
1462      */
1463     public Servant id_to_servant(byte[] id)
1464         throws ObjectNotActive, WrongPolicy
1465     {
1466         try {
1467             lock() ;
1468 
1469             if (debug) {
1470                 ORBUtility.dprint( this, "Calling id_to_servant(id=" +
1471                     id + ") on poa " + this ) ;
1472             }
1473 
1474             if( state >= STATE_DESTROYING ) {
1475                 throw lifecycleWrapper().adapterDestroyed() ;
1476             }
1477             return mediator.idToServant( id ) ;
1478         } finally {
1479             unlock() ;
1480         }
1481     }
1482 
1483     /**
1484      * <code>id_to_reference</code>
1485      * <b>3.3.8.24</b>
1486      */
1487     public org.omg.CORBA.Object id_to_reference(byte[] id)
1488         throws ObjectNotActive, WrongPolicy
1489 
1490     {
1491         try {
1492             lock() ;
1493 
1494             if (debug) {
1495                 ORBUtility.dprint( this, "Calling id_to_reference(id=" +
1496                     id + ") on poa " + this ) ;
1497             }
1498 
1499             if( state >= STATE_DESTROYING ) {
1500                 throw lifecycleWrapper().adapterDestroyed() ;
1501             }
1502 
1503             Servant s = mediator.idToServant( id ) ;
1504             String repId = s._all_interfaces( this, id )[0] ;
1505             return makeObject(repId, id );
1506         } finally {
1507             unlock() ;
1508         }
1509     }
1510 
1511     /**
1512      * <code>id</code>
1513      * <b>11.3.8.26 in ptc/00-08-06</b>
1514      */
1515     public byte[] id()
1516     {
1517         try {
1518             lock() ;
1519 
1520             return getAdapterId() ;
1521         } finally {
1522             unlock() ;
1523         }
1524     }
1525 
1526     //***************************************************************
1527     //Implementation of ObjectAdapter interface
1528     //***************************************************************
1529 
1530     public Policy getEffectivePolicy( int type )
1531     {
1532         return mediator.getPolicies().get_effective_policy( type ) ;
1533     }
1534 
1535     public int getManagerId()
1536     {
1537         return manager.getManagerId() ;
1538     }
1539 
1540     public short getState()
1541     {
1542         return manager.getORTState() ;
1543     }
1544 
1545     public String[] getInterfaces( java.lang.Object servant, byte[] objectId )
1546     {
1547         Servant serv = (Servant)servant ;
1548         return serv._all_interfaces( this, objectId ) ;
1549     }
1550 
1551     protected ObjectCopierFactory getObjectCopierFactory()
1552     {
1553         int copierId = mediator.getPolicies().getCopierId() ;
1554         CopierManager cm = getORB().getCopierManager() ;
1555         return cm.getObjectCopierFactory( copierId ) ;
1556     }
1557 
1558     public void enter() throws OADestroyed
1559     {
1560         try {
1561             lock() ;
1562 
1563             if (debug) {
1564                 ORBUtility.dprint( this, "Calling enter on poa " + this ) ;
1565             }
1566 
1567             // Avoid deadlock if this is the thread that is processing the
1568             // POA.destroy because this is the only thread that can notify
1569             // waiters on beingDestroyedCV.  This can happen if an
1570             // etherealize upcall invokes a method on a colocated object
1571             // served by this POA.
1572             while ((state == STATE_DESTROYING) &&
1573                 (isDestroying.get() == Boolean.FALSE)) {
1574                 try {
1575                     beingDestroyedCV.await();
1576                 } catch (InterruptedException ex) {
1577                     // NO-OP
1578                 }
1579             }
1580 
1581             if (!waitUntilRunning())
1582                 throw new OADestroyed() ;
1583 
1584             invocationCount++;
1585         } finally {
1586             if (debug) {
1587                 ORBUtility.dprint( this, "Exiting enter on poa " + this ) ;
1588             }
1589 
1590             unlock() ;
1591         }
1592 
1593         manager.enter();
1594     }
1595 
1596     public void exit()
1597     {
1598         try {
1599             lock() ;
1600 
1601             if (debug) {
1602                 ORBUtility.dprint( this, "Calling exit on poa " + this ) ;
1603             }
1604 
1605             invocationCount--;
1606 
1607             if ((invocationCount == 0) && (state == STATE_DESTROYING)) {
1608                 invokeCV.broadcast();
1609             }
1610         } finally {
1611             if (debug) {
1612                 ORBUtility.dprint( this, "Exiting exit on poa " + this ) ;
1613             }
1614 
1615             unlock() ;
1616         }
1617 
1618         manager.exit();
1619     }
1620 
1621     public void getInvocationServant( OAInvocationInfo info )
1622     {
1623         try {
1624             lock() ;
1625 
1626             if (debug) {
1627                 ORBUtility.dprint( this,
1628                     "Calling getInvocationServant on poa " + this ) ;
1629             }
1630 
1631             java.lang.Object servant = null ;
1632 
1633             try {
1634                 servant = mediator.getInvocationServant( info.id(),
1635                     info.getOperation() );
1636             } catch (ForwardRequest freq) {
1637                 throw new ForwardException( getORB(), freq.forward_reference ) ;
1638             }
1639 
1640             info.setServant( servant ) ;
1641         } finally {
1642             if (debug) {
1643                 ORBUtility.dprint( this,
1644                     "Exiting getInvocationServant on poa " + this ) ;
1645             }
1646 
1647             unlock() ;
1648         }
1649     }
1650 
1651     public org.omg.CORBA.Object getLocalServant( byte[] objectId )
1652     {
1653         return null ;
1654     }
1655 
1656     /** Called from the subcontract to let this POA cleanup after an
1657      *  invocation. Note: If getServant was called, then returnServant
1658      *  MUST be called, even in the case of exceptions.  This may be
1659      *  called multiple times for a single request.
1660      */
1661     public void returnServant()
1662     {
1663         try {
1664             lock() ;
1665 
1666             if (debug) {
1667                 ORBUtility.dprint( this,
1668                     "Calling returnServant on poa " + this  ) ;
1669             }
1670 
1671             mediator.returnServant();
1672         } catch (Throwable thr) {
1673             if (debug) {
1674                 ORBUtility.dprint( this,
1675                     "Exception " + thr + " in returnServant on poa " + this  ) ;
1676             }
1677 
1678             if (thr instanceof Error)
1679                 throw (Error)thr ;
1680             else if (thr instanceof RuntimeException)
1681                 throw (RuntimeException)thr ;
1682 
1683         } finally {
1684             if (debug) {
1685                 ORBUtility.dprint( this,
1686                     "Exiting returnServant on poa " + this  ) ;
1687             }
1688 
1689             unlock() ;
1690         }
1691     }
1692 }