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 Thread {
 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             super(null, null, "POA-Destroy-Thread", 0, false);
 528             this.etherealize = etherealize ;
 529             this.debug = debug ;
 530         }
 531 
 532         public void doIt( POAImpl thePoa, boolean wait )
 533         {
 534             if (debug) {
 535                 ORBUtility.dprint( this,
 536                     "Calling DestroyThread.doIt(thePOA=" + thePoa +
 537                     " wait=" + wait + " etherealize=" + etherealize ) ;
 538             }
 539 
 540             this.thePoa = thePoa ;
 541             this.wait = wait ;
 542 
 543             if (wait) {
 544                 run() ;
 545             } else {
 546                 // Catch exceptions since setDaemon can cause a
 547                 // security exception to be thrown under netscape
 548                 // in the Applet mode
 549                 try { setDaemon(true); } catch (Exception e) {}
 550                 start() ;
 551             }
 552         }
 553 
 554         public void run()
 555         {
 556             Set destroyedPOATemplates = new HashSet() ;
 557 
 558             performDestroy( thePoa, destroyedPOATemplates );
 559 
 560             Iterator iter = destroyedPOATemplates.iterator() ;
 561             ObjectReferenceTemplate[] orts = new ObjectReferenceTemplate[
 562                 destroyedPOATemplates.size() ] ;
 563             int index = 0 ;
 564             while (iter.hasNext())
 565                 orts[ index++ ] = (ObjectReferenceTemplate)iter.next();
 566 
 567             thePoa.getORB().getPIHandler().adapterStateChanged( orts,
 568                 NON_EXISTENT.value ) ;
 569         }
 570 
 571         // Returns true if destruction must be completed, false
 572         // if not, which means that another thread is already
 573         // destroying poa.
 574         private boolean prepareForDestruction( POAImpl poa,
 575             Set destroyedPOATemplates )
 576         {
 577             POAImpl[] childPoas = null ;
 578 
 579             // Note that we do not synchronize on this, since this is
 580             // the PerformDestroy instance, not the POA.
 581             try {
 582                 poa.lock() ;
 583 
 584                 if (debug) {
 585                     ORBUtility.dprint( this,
 586                         "Calling performDestroy on poa " + poa ) ;
 587                 }
 588 
 589                 if (poa.state <= STATE_RUN) {
 590                     poa.state = STATE_DESTROYING ;
 591                 } else {
 592                     // destroy may be called multiple times, and each call
 593                     // is allowed to proceed with its own setting of the wait
 594                     // flag, but the etherealize value is used from the first
 595                     // call to destroy.  Also all children should be destroyed
 596                     // before the parent POA.  If the poa is already destroyed,
 597                     // we can just return.  If the poa has started destruction,
 598                     // but not completed, and wait is true, we need to wait
 599                     // until destruction is complete, then just return.
 600                     if (wait)
 601                         while (poa.state != STATE_DESTROYED) {
 602                             try {
 603                                 poa.beingDestroyedCV.await() ;
 604                             } catch (InterruptedException exc) {
 605                                 // NO-OP
 606                             }
 607                         }
 608 
 609                     return false ;
 610                 }
 611 
 612                 poa.isDestroying.set(Boolean.TRUE);
 613 
 614                 // Make a copy since we can't hold the lock while destroying
 615                 // the children, and an iterator is not deletion-safe.
 616                 childPoas = (POAImpl[])poa.children.values().toArray(
 617                     new POAImpl[0] );
 618             } finally {
 619                 poa.unlock() ;
 620             }
 621 
 622             // We are not holding the POA mutex here to avoid holding it
 623             // while destroying the POA's children, since this may involve
 624             // upcalls to etherealize methods.
 625 
 626             for (int ctr=0; ctr<childPoas.length; ctr++ ) {
 627                 performDestroy( childPoas[ctr], destroyedPOATemplates ) ;
 628             }
 629 
 630             return true ;
 631         }
 632 
 633         public void performDestroy( POAImpl poa, Set destroyedPOATemplates )
 634         {
 635             if (!prepareForDestruction( poa, destroyedPOATemplates ))
 636                 return ;
 637 
 638             // NOTE: If we are here, poa is in STATE_DESTROYING state. All
 639             // other state checks are taken care of in prepareForDestruction.
 640             // No other threads may either be starting new invocations
 641             // by calling enter or starting to destroy poa.  There may
 642             // still be pending invocations.
 643 
 644             POAImpl parent = poa.parent ;
 645             boolean isRoot = parent == null ;
 646 
 647             try {
 648                 // Note that we must lock the parent before the child.
 649                 // The parent lock is required (if poa is not the root)
 650                 // to safely remove poa from parent's children Map.
 651                 if (!isRoot)
 652                     parent.lock() ;
 653 
 654                 try {
 655                     poa.lock() ;
 656 
 657                     completeDestruction( poa, parent,
 658                         destroyedPOATemplates ) ;
 659                 } finally {
 660                     poa.unlock() ;
 661 
 662                     if (isRoot)
 663                         // We have just destroyed the root POA, so we need to
 664                         // make sure that the next call to
 665                         // resolve_initial_reference( "RootPOA" )
 666                         // will recreate a valid root POA.
 667                         poa.manager.getFactory().registerRootPOA() ;
 668                 }
 669             } finally {
 670                 if (!isRoot) {
 671                     parent.unlock() ;
 672                     poa.parent = null ;
 673                 }
 674             }
 675         }
 676 
 677         private void completeDestruction( POAImpl poa, POAImpl parent,
 678             Set destroyedPOATemplates )
 679         {
 680             if (debug) {
 681                 ORBUtility.dprint( this,
 682                     "Calling completeDestruction on poa " + poa ) ;
 683             }
 684 
 685             try {
 686                 while (poa.invocationCount != 0) {
 687                     try {
 688                         poa.invokeCV.await() ;
 689                     } catch (InterruptedException ex) {
 690                         // NO-OP
 691                     }
 692                 }
 693 
 694                 if (poa.mediator != null) {
 695                     if (etherealize)
 696                         poa.mediator.etherealizeAll();
 697 
 698                     poa.mediator.clearAOM() ;
 699                 }
 700 
 701                 if (poa.manager != null)
 702                     poa.manager.removePOA(poa);
 703 
 704                 if (parent != null)
 705                     parent.children.remove( poa.name ) ;
 706 
 707                 destroyedPOATemplates.add( poa.getAdapterTemplate() ) ;
 708             } catch (Throwable thr) {
 709                 if (thr instanceof ThreadDeath)
 710                     throw (ThreadDeath)thr ;
 711 
 712                 poa.lifecycleWrapper().unexpectedException( thr, poa.toString() ) ;
 713             } finally {
 714                 poa.state = STATE_DESTROYED ;
 715                 poa.beingDestroyedCV.broadcast();
 716                 poa.isDestroying.set(Boolean.FALSE);
 717 
 718                 if (debug) {
 719                     ORBUtility.dprint( this,
 720                         "Exiting completeDestruction on poa " + poa ) ;
 721                 }
 722             }
 723         }
 724     }
 725 
 726     void etherealizeAll()
 727     {
 728         try {
 729             lock() ;
 730 
 731             if (debug) {
 732                 ORBUtility.dprint( this,
 733                     "Calling etheralizeAll on poa " + this ) ;
 734             }
 735 
 736             mediator.etherealizeAll() ;
 737         } finally {
 738             if (debug) {
 739                 ORBUtility.dprint( this,
 740                     "Exiting etheralizeAll on poa " + this ) ;
 741             }
 742 
 743             unlock() ;
 744         }
 745     }
 746 
 747  //*******************************************************************
 748  // Public POA API
 749  //*******************************************************************
 750 
 751     /**
 752      * <code>create_POA</code>
 753      * <b>Section 3.3.8.2</b>
 754      */
 755     public POA create_POA(String name, POAManager
 756         theManager, Policy[] policies) throws AdapterAlreadyExists,
 757         InvalidPolicy
 758     {
 759         try {
 760             lock() ;
 761 
 762             if (debug) {
 763                 ORBUtility.dprint( this, "Calling create_POA(name=" + name +
 764                     " theManager=" + theManager + " policies=" + policies +
 765                     ") on poa " + this ) ;
 766             }
 767 
 768             // We cannot create children of a POA that is (being) destroyed.
 769             // This has been added to the CORBA 3.0 spec.
 770             if (state > STATE_RUN)
 771                 throw omgLifecycleWrapper().createPoaDestroy() ;
 772 
 773             POAImpl poa = (POAImpl)(children.get(name)) ;
 774 
 775             if (poa == null) {
 776                 poa = new POAImpl( name, this, getORB(), STATE_START ) ;
 777             }
 778 
 779             try {
 780                 poa.lock() ;
 781 
 782                 if (debug) {
 783                     ORBUtility.dprint( this,
 784                         "Calling create_POA: new poa is " + poa ) ;
 785                 }
 786 
 787                 if ((poa.state != STATE_START) && (poa.state != STATE_INIT))
 788                     throw new AdapterAlreadyExists();
 789 
 790                 POAManagerImpl newManager = (POAManagerImpl)theManager ;
 791                 if (newManager == null)
 792                     newManager = new POAManagerImpl( manager.getFactory(),
 793                         manager.getPIHandler() );
 794 
 795                 int defaultCopierId =
 796                     getORB().getCopierManager().getDefaultId() ;
 797                 Policies POAPolicies =
 798                     new Policies( policies, defaultCopierId ) ;
 799 
 800                 poa.initialize( newManager, POAPolicies ) ;
 801 
 802                 return poa;
 803             } finally {
 804                 poa.unlock() ;
 805             }
 806         } finally {
 807             unlock() ;
 808         }
 809     }
 810 
 811     /**
 812      * <code>find_POA</code>
 813      * <b>Section 3.3.8.3</b>
 814      */
 815     public POA find_POA(String name, boolean activate)
 816         throws AdapterNonExistent
 817     {
 818         POAImpl found = null ;
 819         AdapterActivator act = null ;
 820 
 821         lock() ;
 822 
 823         if (debug) {
 824             ORBUtility.dprint( this, "Calling find_POA(name=" + name +
 825                 " activate=" + activate + ") on poa " + this ) ;
 826         }
 827 
 828         found = (POAImpl) children.get(name);
 829 
 830         if (found != null) {
 831             if (debug) {
 832                 ORBUtility.dprint( this,
 833                     "Calling find_POA: found poa " + found ) ;
 834             }
 835 
 836             try {
 837                 found.lock() ;
 838 
 839                 // Do not hold the parent POA lock while
 840                 // waiting for child to complete initialization.
 841                 unlock() ;
 842 
 843                 // Make sure that the child has completed its initialization,
 844                 // if it was created by an AdapterActivator, otherwise throw
 845                 // a standard TRANSIENT exception with minor code 4 (see
 846                 // CORBA 3.0 11.3.9.3, in reference to unknown_adapter)
 847                 if (!found.waitUntilRunning())
 848                     throw omgLifecycleWrapper().poaDestroyed() ;
 849 
 850                 // Note that found may be in state DESTROYING or DESTROYED at
 851                 // this point.  That's OK, since destruction could start at
 852                 // any time.
 853             } finally {
 854                 found.unlock() ;
 855             }
 856         } else {
 857             try {
 858                 if (debug) {
 859                     ORBUtility.dprint( this,
 860                         "Calling find_POA: no poa found" ) ;
 861                 }
 862 
 863                 if (activate && (activator != null)) {
 864                     // Create a child, but don't initialize it.  The newly
 865                     // created POA will be in state STATE_START, which will
 866                     // cause other calls to find_POA that are creating the same
 867                     // POA to block on the waitUntilRunning call above.
 868                     // Initialization must be completed by a call to create_POA
 869                     // inside the unknown_adapter upcall.  Note that
 870                     // this.poaMutex must be held here so that this.children
 871                     // can be safely updated.  The state is set to STATE_INIT
 872                     // so that initialize can make the correct state transition
 873                     // when create_POA is called inside the AdapterActivator.
 874                     // This avoids activating the new POA too soon
 875                     // by transitioning to STATE_RUN after unknown_adapter
 876                     // returns.
 877                     found = new POAImpl( name, this, getORB(), STATE_INIT ) ;
 878 
 879                     if (debug) {
 880                         ORBUtility.dprint( this,
 881                             "Calling find_POA: created poa " + found ) ;
 882                     }
 883 
 884                     act = activator ;
 885                 } else {
 886                     throw new AdapterNonExistent();
 887                 }
 888             } finally {
 889                 unlock() ;
 890             }
 891         }
 892 
 893         // assert (found != null)
 894         // assert not holding this.poaMutex OR found.poaMutex
 895 
 896         // We must not hold either this.poaMutex or found.poaMutex here while
 897         // waiting for intialization of found to complete to prevent possible
 898         // deadlocks.
 899 
 900         if (act != null) {
 901             boolean status = false ;
 902             boolean adapterResult = false ;
 903 
 904             if (debug) {
 905                 ORBUtility.dprint( this,
 906                     "Calling find_POA: calling AdapterActivator"  ) ;
 907             }
 908 
 909             try {
 910                 // Prevent more than one thread at a time from executing in act
 911                 // in case act is shared between multiple POAs.
 912                 synchronized (act) {
 913                     status = act.unknown_adapter(this, name);
 914                 }
 915             } catch (SystemException exc) {
 916                 throw omgLifecycleWrapper().adapterActivatorException( exc,
 917                     name, poaId.toString() ) ;
 918             } catch (Throwable thr) {
 919                 // ignore most non-system exceptions, but log them for
 920                 // diagnostic purposes.
 921                 lifecycleWrapper().unexpectedException( thr, this.toString() ) ;
 922 
 923                 if (thr instanceof ThreadDeath)
 924                     throw (ThreadDeath)thr ;
 925             } finally {
 926                 // At this point, we have completed adapter activation.
 927                 // Whether this was successful or not, we must call
 928                 // destroyIfNotInitDone so that calls to enter() and create_POA()
 929                 // that are waiting can execute again.  Failing to do this
 930                 // will cause the system to hang in complex tests.
 931                 adapterResult = found.destroyIfNotInitDone() ;
 932             }
 933 
 934             if (status) {
 935                 if (!adapterResult)
 936                     throw omgLifecycleWrapper().adapterActivatorException( name,
 937                         poaId.toString() ) ;
 938             } else {
 939                 if (debug) {
 940                     ORBUtility.dprint( this,
 941                         "Calling find_POA: AdapterActivator returned false"  ) ;
 942                 }
 943 
 944                 // OMG Issue 3740 is resolved to throw AdapterNonExistent if
 945                 // unknown_adapter() returns false.
 946                 throw new AdapterNonExistent();
 947             }
 948         }
 949 
 950         return found;
 951     }
 952 
 953     /**
 954      * <code>destroy</code>
 955      * <b>Section 3.3.8.4</b>
 956      */
 957     public void destroy(boolean etherealize, boolean wait_for_completion)
 958     {
 959         // This is to avoid deadlock
 960         if (wait_for_completion && getORB().isDuringDispatch()) {
 961             throw lifecycleWrapper().destroyDeadlock() ;
 962         }
 963 
 964         DestroyThread destroyer = new DestroyThread( etherealize, debug );
 965         destroyer.doIt( this, wait_for_completion ) ;
 966     }
 967 
 968     /**
 969      * <code>create_thread_policy</code>
 970      * <b>Section 3.3.8.5</b>
 971      */
 972     public ThreadPolicy create_thread_policy(
 973         ThreadPolicyValue value)
 974     {
 975         return new ThreadPolicyImpl(value);
 976     }
 977 
 978     /**
 979      * <code>create_lifespan_policy</code>
 980      * <b>Section 3.3.8.5</b>
 981      */
 982     public LifespanPolicy create_lifespan_policy(
 983         LifespanPolicyValue value)
 984     {
 985         return new LifespanPolicyImpl(value);
 986     }
 987 
 988     /**
 989      * <code>create_id_uniqueness_policy</code>
 990      * <b>Section 3.3.8.5</b>
 991      */
 992     public IdUniquenessPolicy create_id_uniqueness_policy(
 993         IdUniquenessPolicyValue value)
 994     {
 995         return new IdUniquenessPolicyImpl(value);
 996     }
 997 
 998     /**
 999      * <code>create_id_assignment_policy</code>
1000      * <b>Section 3.3.8.5</b>
1001      */
1002     public IdAssignmentPolicy create_id_assignment_policy(
1003         IdAssignmentPolicyValue value)
1004     {
1005         return new IdAssignmentPolicyImpl(value);
1006     }
1007 
1008     /**
1009      * <code>create_implicit_activation_policy</code>
1010      * <b>Section 3.3.8.5</b>
1011      */
1012     public ImplicitActivationPolicy create_implicit_activation_policy(
1013         ImplicitActivationPolicyValue value)
1014     {
1015         return new ImplicitActivationPolicyImpl(value);
1016     }
1017 
1018     /**
1019      * <code>create_servant_retention_policy</code>
1020      * <b>Section 3.3.8.5</b>
1021      */
1022     public ServantRetentionPolicy create_servant_retention_policy(
1023         ServantRetentionPolicyValue value)
1024     {
1025         return new ServantRetentionPolicyImpl(value);
1026     }
1027 
1028     /**
1029      * <code>create_request_processing_policy</code>
1030      * <b>Section 3.3.8.5</b>
1031      */
1032     public RequestProcessingPolicy create_request_processing_policy(
1033         RequestProcessingPolicyValue value)
1034     {
1035         return new RequestProcessingPolicyImpl(value);
1036     }
1037 
1038     /**
1039      * <code>the_name</code>
1040      * <b>Section 3.3.8.6</b>
1041      */
1042     public String the_name()
1043     {
1044         try {
1045             lock() ;
1046 
1047             return name;
1048         } finally {
1049             unlock() ;
1050         }
1051     }
1052 
1053     /**
1054      * <code>the_parent</code>
1055      * <b>Section 3.3.8.7</b>
1056      */
1057     public POA the_parent()
1058     {
1059         try {
1060             lock() ;
1061 
1062             return parent;
1063         } finally {
1064             unlock() ;
1065         }
1066     }
1067 
1068     /**
1069      * <code>the_children</code>
1070      */
1071     public org.omg.PortableServer.POA[] the_children()
1072     {
1073         try {
1074             lock() ;
1075 
1076             Collection coll = children.values() ;
1077             int size = coll.size() ;
1078             POA[] result = new POA[ size ] ;
1079             int index = 0 ;
1080             Iterator iter = coll.iterator() ;
1081             while (iter.hasNext()) {
1082                 POA poa = (POA)(iter.next()) ;
1083                 result[ index++ ] = poa ;
1084             }
1085 
1086             return result ;
1087         } finally {
1088             unlock() ;
1089         }
1090     }
1091 
1092     /**
1093      * <code>the_POAManager</code>
1094      * <b>Section 3.3.8.8</b>
1095      */
1096     public POAManager the_POAManager()
1097     {
1098         try {
1099             lock() ;
1100 
1101             return manager;
1102         } finally {
1103             unlock() ;
1104         }
1105     }
1106 
1107     /**
1108      * <code>the_activator</code>
1109      * <b>Section 3.3.8.9</b>
1110      */
1111     public AdapterActivator the_activator()
1112     {
1113         try {
1114             lock() ;
1115 
1116             return activator;
1117         } finally {
1118             unlock() ;
1119         }
1120     }
1121 
1122     /**
1123      * <code>the_activator</code>
1124      * <b>Section 3.3.8.9</b>
1125      */
1126     public void the_activator(AdapterActivator activator)
1127     {
1128         try {
1129             lock() ;
1130 
1131             if (debug) {
1132                 ORBUtility.dprint( this, "Calling the_activator on poa " +
1133                     this + " activator=" + activator ) ;
1134             }
1135 
1136             this.activator = activator;
1137         } finally {
1138             unlock() ;
1139         }
1140     }
1141 
1142     /**
1143      * <code>get_servant_manager</code>
1144      * <b>Section 3.3.8.10</b>
1145      */
1146     public ServantManager get_servant_manager() throws WrongPolicy
1147     {
1148         try {
1149             lock() ;
1150 
1151             return mediator.getServantManager() ;
1152         } finally {
1153             unlock() ;
1154         }
1155     }
1156 
1157     /**
1158      * <code>set_servant_manager</code>
1159      * <b>Section 3.3.8.10</b>
1160      */
1161     public void set_servant_manager(ServantManager servantManager)
1162         throws WrongPolicy
1163     {
1164         try {
1165             lock() ;
1166 
1167             if (debug) {
1168                 ORBUtility.dprint( this, "Calling set_servant_manager on poa " +
1169                     this + " servantManager=" + servantManager ) ;
1170             }
1171 
1172             mediator.setServantManager( servantManager ) ;
1173         } finally {
1174             unlock() ;
1175         }
1176     }
1177 
1178     /**
1179      * <code>get_servant</code>
1180      * <b>Section 3.3.8.12</b>
1181      */
1182     public Servant get_servant() throws NoServant, WrongPolicy
1183     {
1184         try {
1185             lock() ;
1186 
1187             return mediator.getDefaultServant() ;
1188         } finally {
1189             unlock() ;
1190         }
1191     }
1192 
1193     /**
1194      * <code>set_servant</code>
1195      * <b>Section 3.3.8.13</b>
1196      */
1197     public void set_servant(Servant defaultServant)
1198         throws WrongPolicy
1199     {
1200         try {
1201             lock() ;
1202 
1203             if (debug) {
1204                 ORBUtility.dprint( this, "Calling set_servant on poa " +
1205                     this + " defaultServant=" + defaultServant ) ;
1206             }
1207 
1208             mediator.setDefaultServant( defaultServant ) ;
1209         } finally {
1210             unlock() ;
1211         }
1212     }
1213 
1214     /**
1215      * <code>activate_object</code>
1216      * <b>Section 3.3.8.14</b>
1217      */
1218     public byte[] activate_object(Servant servant)
1219         throws ServantAlreadyActive, WrongPolicy
1220     {
1221         try {
1222             lock() ;
1223 
1224             if (debug) {
1225                 ORBUtility.dprint( this,
1226                     "Calling activate_object on poa " + this +
1227                     " (servant=" + servant + ")" ) ;
1228             }
1229 
1230             // Allocate a new system-generated object-id.
1231             // This will throw WrongPolicy if not SYSTEM_ID
1232             // policy.
1233             byte[] id = mediator.newSystemId();
1234 
1235             try {
1236                 mediator.activateObject( id, servant ) ;
1237             } catch (ObjectAlreadyActive oaa) {
1238                 // This exception can not occur in this case,
1239                 // since id is always brand new.
1240                 //
1241             }
1242 
1243             return id ;
1244         } finally {
1245             if (debug) {
1246                 ORBUtility.dprint( this,
1247                     "Exiting activate_object on poa " + this ) ;
1248             }
1249 
1250             unlock() ;
1251         }
1252     }
1253 
1254     /**
1255      * <code>activate_object_with_id</code>
1256      * <b>Section 3.3.8.15</b>
1257      */
1258     public void activate_object_with_id(byte[] id,
1259                                                      Servant servant)
1260         throws ObjectAlreadyActive, ServantAlreadyActive, WrongPolicy
1261     {
1262         try {
1263             lock() ;
1264 
1265             if (debug) {
1266                 ORBUtility.dprint( this,
1267                     "Calling activate_object_with_id on poa " + this +
1268                     " (servant=" + servant + " id=" + id + ")" ) ;
1269             }
1270 
1271             // Clone the id to avoid possible errors due to aliasing
1272             // (e.g. the client passes the id in and then changes it later).
1273             byte[] idClone = (byte[])(id.clone()) ;
1274 
1275             mediator.activateObject( idClone, servant ) ;
1276         } finally {
1277             if (debug) {
1278                 ORBUtility.dprint( this,
1279                     "Exiting activate_object_with_id on poa " + this ) ;
1280             }
1281 
1282             unlock() ;
1283         }
1284     }
1285 
1286     /**
1287      * <code>deactivate_object</code>
1288      * <b>3.3.8.16</b>
1289      */
1290     public void deactivate_object(byte[] id)
1291         throws ObjectNotActive, WrongPolicy
1292     {
1293         try {
1294             lock() ;
1295 
1296             if (debug) {
1297                 ORBUtility.dprint( this,
1298                     "Calling deactivate_object on poa " + this +
1299                     " (id=" + id + ")" ) ;
1300             }
1301 
1302             mediator.deactivateObject( id ) ;
1303         } finally {
1304             if (debug) {
1305                 ORBUtility.dprint( this,
1306                     "Exiting deactivate_object on poa " + this ) ;
1307             }
1308 
1309             unlock() ;
1310         }
1311     }
1312 
1313     /**
1314      * <code>create_reference</code>
1315      * <b>3.3.8.17</b>
1316      */
1317     public org.omg.CORBA.Object create_reference(String repId)
1318         throws WrongPolicy
1319     {
1320         try {
1321             lock() ;
1322 
1323             if (debug) {
1324                 ORBUtility.dprint( this, "Calling create_reference(repId=" +
1325                     repId + ") on poa " + this ) ;
1326             }
1327 
1328             return makeObject( repId, mediator.newSystemId()) ;
1329         } finally {
1330             unlock() ;
1331         }
1332     }
1333 
1334     /**
1335      * <code>create_reference_with_id</code>
1336      * <b>3.3.8.18</b>
1337      */
1338     public org.omg.CORBA.Object
1339         create_reference_with_id(byte[] oid, String repId)
1340     {
1341         try {
1342             lock() ;
1343 
1344             if (debug) {
1345                 ORBUtility.dprint( this,
1346                     "Calling create_reference_with_id(oid=" +
1347                     oid + " repId=" + repId + ") on poa " + this ) ;
1348             }
1349 
1350             // Clone the id to avoid possible errors due to aliasing
1351             // (e.g. the client passes the id in and then changes it later).
1352             byte[] idClone = (byte[])(oid.clone()) ;
1353 
1354             return makeObject( repId, idClone ) ;
1355         } finally {
1356             unlock() ;
1357         }
1358     }
1359 
1360     /**
1361      * <code>servant_to_id</code>
1362      * <b>3.3.8.19</b>
1363      */
1364     public byte[] servant_to_id(Servant servant)
1365         throws ServantNotActive, WrongPolicy
1366     {
1367         try {
1368             lock() ;
1369 
1370             if (debug) {
1371                 ORBUtility.dprint( this, "Calling servant_to_id(servant=" +
1372                     servant + ") on poa " + this ) ;
1373             }
1374 
1375             return mediator.servantToId( servant ) ;
1376         } finally {
1377             unlock() ;
1378         }
1379     }
1380 
1381     /**
1382      * <code>servant_to_reference</code>
1383      * <b>3.3.8.20</b>
1384      */
1385     public org.omg.CORBA.Object servant_to_reference(Servant servant)
1386         throws ServantNotActive, WrongPolicy
1387     {
1388         try {
1389             lock() ;
1390 
1391             if (debug) {
1392                 ORBUtility.dprint( this,
1393                     "Calling servant_to_reference(servant=" +
1394                     servant + ") on poa " + this ) ;
1395             }
1396 
1397             byte[] oid = mediator.servantToId(servant);
1398             String repId = servant._all_interfaces( this, oid )[0] ;
1399             return create_reference_with_id(oid, repId);
1400         } finally {
1401             unlock() ;
1402         }
1403     }
1404 
1405     /**
1406      * <code>reference_to_servant</code>
1407      * <b>3.3.8.21</b>
1408      */
1409     public Servant reference_to_servant(org.omg.CORBA.Object reference)
1410         throws ObjectNotActive, WrongPolicy, WrongAdapter
1411     {
1412         try {
1413             lock() ;
1414 
1415             if (debug) {
1416                 ORBUtility.dprint( this,
1417                     "Calling reference_to_servant(reference=" +
1418                     reference + ") on poa " + this ) ;
1419             }
1420 
1421             if ( state >= STATE_DESTROYING ) {
1422                 throw lifecycleWrapper().adapterDestroyed() ;
1423             }
1424 
1425             // reference_to_id should throw WrongAdapter
1426             // if the objref was not created by this POA
1427             byte [] id = internalReferenceToId(reference);
1428 
1429             return mediator.idToServant( id ) ;
1430         } finally {
1431             unlock() ;
1432         }
1433     }
1434 
1435     /**
1436      * <code>reference_to_id</code>
1437      * <b>3.3.8.22</b>
1438      */
1439     public byte[] reference_to_id(org.omg.CORBA.Object reference)
1440         throws WrongAdapter, WrongPolicy
1441     {
1442         try {
1443             lock() ;
1444 
1445             if (debug) {
1446                 ORBUtility.dprint( this, "Calling reference_to_id(reference=" +
1447                     reference + ") on poa " + this ) ;
1448             }
1449 
1450             if( state >= STATE_DESTROYING ) {
1451                 throw lifecycleWrapper().adapterDestroyed() ;
1452             }
1453 
1454             return internalReferenceToId( reference ) ;
1455         } finally {
1456             unlock() ;
1457         }
1458     }
1459 
1460     /**
1461      * <code>id_to_servant</code>
1462      * <b>3.3.8.23</b>
1463      */
1464     public Servant id_to_servant(byte[] id)
1465         throws ObjectNotActive, WrongPolicy
1466     {
1467         try {
1468             lock() ;
1469 
1470             if (debug) {
1471                 ORBUtility.dprint( this, "Calling id_to_servant(id=" +
1472                     id + ") on poa " + this ) ;
1473             }
1474 
1475             if( state >= STATE_DESTROYING ) {
1476                 throw lifecycleWrapper().adapterDestroyed() ;
1477             }
1478             return mediator.idToServant( id ) ;
1479         } finally {
1480             unlock() ;
1481         }
1482     }
1483 
1484     /**
1485      * <code>id_to_reference</code>
1486      * <b>3.3.8.24</b>
1487      */
1488     public org.omg.CORBA.Object id_to_reference(byte[] id)
1489         throws ObjectNotActive, WrongPolicy
1490 
1491     {
1492         try {
1493             lock() ;
1494 
1495             if (debug) {
1496                 ORBUtility.dprint( this, "Calling id_to_reference(id=" +
1497                     id + ") on poa " + this ) ;
1498             }
1499 
1500             if( state >= STATE_DESTROYING ) {
1501                 throw lifecycleWrapper().adapterDestroyed() ;
1502             }
1503 
1504             Servant s = mediator.idToServant( id ) ;
1505             String repId = s._all_interfaces( this, id )[0] ;
1506             return makeObject(repId, id );
1507         } finally {
1508             unlock() ;
1509         }
1510     }
1511 
1512     /**
1513      * <code>id</code>
1514      * <b>11.3.8.26 in ptc/00-08-06</b>
1515      */
1516     public byte[] id()
1517     {
1518         try {
1519             lock() ;
1520 
1521             return getAdapterId() ;
1522         } finally {
1523             unlock() ;
1524         }
1525     }
1526 
1527     //***************************************************************
1528     //Implementation of ObjectAdapter interface
1529     //***************************************************************
1530 
1531     public Policy getEffectivePolicy( int type )
1532     {
1533         return mediator.getPolicies().get_effective_policy( type ) ;
1534     }
1535 
1536     public int getManagerId()
1537     {
1538         return manager.getManagerId() ;
1539     }
1540 
1541     public short getState()
1542     {
1543         return manager.getORTState() ;
1544     }
1545 
1546     public String[] getInterfaces( java.lang.Object servant, byte[] objectId )
1547     {
1548         Servant serv = (Servant)servant ;
1549         return serv._all_interfaces( this, objectId ) ;
1550     }
1551 
1552     protected ObjectCopierFactory getObjectCopierFactory()
1553     {
1554         int copierId = mediator.getPolicies().getCopierId() ;
1555         CopierManager cm = getORB().getCopierManager() ;
1556         return cm.getObjectCopierFactory( copierId ) ;
1557     }
1558 
1559     public void enter() throws OADestroyed
1560     {
1561         try {
1562             lock() ;
1563 
1564             if (debug) {
1565                 ORBUtility.dprint( this, "Calling enter on poa " + this ) ;
1566             }
1567 
1568             // Avoid deadlock if this is the thread that is processing the
1569             // POA.destroy because this is the only thread that can notify
1570             // waiters on beingDestroyedCV.  This can happen if an
1571             // etherealize upcall invokes a method on a colocated object
1572             // served by this POA.
1573             while ((state == STATE_DESTROYING) &&
1574                 (isDestroying.get() == Boolean.FALSE)) {
1575                 try {
1576                     beingDestroyedCV.await();
1577                 } catch (InterruptedException ex) {
1578                     // NO-OP
1579                 }
1580             }
1581 
1582             if (!waitUntilRunning())
1583                 throw new OADestroyed() ;
1584 
1585             invocationCount++;
1586         } finally {
1587             if (debug) {
1588                 ORBUtility.dprint( this, "Exiting enter on poa " + this ) ;
1589             }
1590 
1591             unlock() ;
1592         }
1593 
1594         manager.enter();
1595     }
1596 
1597     public void exit()
1598     {
1599         try {
1600             lock() ;
1601 
1602             if (debug) {
1603                 ORBUtility.dprint( this, "Calling exit on poa " + this ) ;
1604             }
1605 
1606             invocationCount--;
1607 
1608             if ((invocationCount == 0) && (state == STATE_DESTROYING)) {
1609                 invokeCV.broadcast();
1610             }
1611         } finally {
1612             if (debug) {
1613                 ORBUtility.dprint( this, "Exiting exit on poa " + this ) ;
1614             }
1615 
1616             unlock() ;
1617         }
1618 
1619         manager.exit();
1620     }
1621 
1622     public void getInvocationServant( OAInvocationInfo info )
1623     {
1624         try {
1625             lock() ;
1626 
1627             if (debug) {
1628                 ORBUtility.dprint( this,
1629                     "Calling getInvocationServant on poa " + this ) ;
1630             }
1631 
1632             java.lang.Object servant = null ;
1633 
1634             try {
1635                 servant = mediator.getInvocationServant( info.id(),
1636                     info.getOperation() );
1637             } catch (ForwardRequest freq) {
1638                 throw new ForwardException( getORB(), freq.forward_reference ) ;
1639             }
1640 
1641             info.setServant( servant ) ;
1642         } finally {
1643             if (debug) {
1644                 ORBUtility.dprint( this,
1645                     "Exiting getInvocationServant on poa " + this ) ;
1646             }
1647 
1648             unlock() ;
1649         }
1650     }
1651 
1652     public org.omg.CORBA.Object getLocalServant( byte[] objectId )
1653     {
1654         return null ;
1655     }
1656 
1657     /** Called from the subcontract to let this POA cleanup after an
1658      *  invocation. Note: If getServant was called, then returnServant
1659      *  MUST be called, even in the case of exceptions.  This may be
1660      *  called multiple times for a single request.
1661      */
1662     public void returnServant()
1663     {
1664         try {
1665             lock() ;
1666 
1667             if (debug) {
1668                 ORBUtility.dprint( this,
1669                     "Calling returnServant on poa " + this  ) ;
1670             }
1671 
1672             mediator.returnServant();
1673         } catch (Throwable thr) {
1674             if (debug) {
1675                 ORBUtility.dprint( this,
1676                     "Exception " + thr + " in returnServant on poa " + this  ) ;
1677             }
1678 
1679             if (thr instanceof Error)
1680                 throw (Error)thr ;
1681             else if (thr instanceof RuntimeException)
1682                 throw (RuntimeException)thr ;
1683 
1684         } finally {
1685             if (debug) {
1686                 ORBUtility.dprint( this,
1687                     "Exiting returnServant on poa " + this  ) ;
1688             }
1689 
1690             unlock() ;
1691         }
1692     }
1693 }