/*
 * Copyright (c) 1997, 2004, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package com.sun.corba.se.impl.oa.poa;

import java.util.Collection ;
import java.util.Set ;
import java.util.HashSet ;
import java.util.Map ;
import java.util.HashMap ;
import java.util.Iterator ;

import org.omg.CORBA.Policy ;
import org.omg.CORBA.SystemException ;

import org.omg.PortableServer.POA ;
import org.omg.PortableServer.Servant ;
import org.omg.PortableServer.POAManager ;
import org.omg.PortableServer.AdapterActivator ;
import org.omg.PortableServer.ServantManager ;
import org.omg.PortableServer.ForwardRequest ;
import org.omg.PortableServer.ThreadPolicy;
import org.omg.PortableServer.LifespanPolicy;
import org.omg.PortableServer.IdUniquenessPolicy;
import org.omg.PortableServer.IdAssignmentPolicy;
import org.omg.PortableServer.ImplicitActivationPolicy;
import org.omg.PortableServer.ServantRetentionPolicy;
import org.omg.PortableServer.RequestProcessingPolicy;
import org.omg.PortableServer.ThreadPolicyValue ;
import org.omg.PortableServer.LifespanPolicyValue ;
import org.omg.PortableServer.IdUniquenessPolicyValue ;
import org.omg.PortableServer.IdAssignmentPolicyValue ;
import org.omg.PortableServer.ImplicitActivationPolicyValue ;
import org.omg.PortableServer.ServantRetentionPolicyValue ;
import org.omg.PortableServer.RequestProcessingPolicyValue ;
import org.omg.PortableServer.POAPackage.AdapterAlreadyExists ;
import org.omg.PortableServer.POAPackage.AdapterNonExistent ;
import org.omg.PortableServer.POAPackage.InvalidPolicy ;
import org.omg.PortableServer.POAPackage.WrongPolicy ;
import org.omg.PortableServer.POAPackage.WrongAdapter ;
import org.omg.PortableServer.POAPackage.NoServant ;
import org.omg.PortableServer.POAPackage.ServantAlreadyActive ;
import org.omg.PortableServer.POAPackage.ObjectAlreadyActive ;
import org.omg.PortableServer.POAPackage.ServantNotActive ;
import org.omg.PortableServer.POAPackage.ObjectNotActive ;

import org.omg.PortableInterceptor.ObjectReferenceFactory ;
import org.omg.PortableInterceptor.ObjectReferenceTemplate ;
import org.omg.PortableInterceptor.NON_EXISTENT ;

import org.omg.IOP.TAG_INTERNET_IOP ;

import com.sun.corba.se.spi.copyobject.CopierManager ;
import com.sun.corba.se.spi.copyobject.ObjectCopier ;
import com.sun.corba.se.spi.copyobject.ObjectCopierFactory ;
import com.sun.corba.se.spi.oa.OADestroyed ;
import com.sun.corba.se.spi.oa.OAInvocationInfo ;
import com.sun.corba.se.spi.oa.ObjectAdapter ;
import com.sun.corba.se.spi.oa.ObjectAdapterBase ;
import com.sun.corba.se.spi.oa.ObjectAdapterFactory ;
import com.sun.corba.se.spi.ior.ObjectKeyTemplate ;
import com.sun.corba.se.spi.ior.ObjectId ;
import com.sun.corba.se.spi.ior.ObjectAdapterId ;
import com.sun.corba.se.spi.ior.IOR ;
import com.sun.corba.se.spi.ior.IORFactories ;
import com.sun.corba.se.spi.ior.IORTemplate ;
import com.sun.corba.se.spi.ior.IORTemplateList ;
import com.sun.corba.se.spi.ior.TaggedProfile ;
import com.sun.corba.se.spi.ior.iiop.IIOPProfile ;
import com.sun.corba.se.spi.ior.iiop.IIOPAddress ;
import com.sun.corba.se.spi.ior.iiop.IIOPFactories ;
import com.sun.corba.se.spi.orb.ORB ;
import com.sun.corba.se.spi.protocol.ForwardException ;
import com.sun.corba.se.spi.transport.SocketOrChannelAcceptor;

import com.sun.corba.se.impl.ior.POAObjectKeyTemplate ;
import com.sun.corba.se.impl.ior.ObjectAdapterIdArray ;
import com.sun.corba.se.impl.orbutil.ORBUtility;
import com.sun.corba.se.impl.orbutil.ORBConstants;
import com.sun.corba.se.impl.orbutil.concurrent.Sync ;
import com.sun.corba.se.impl.orbutil.concurrent.SyncUtil ;
import com.sun.corba.se.impl.orbutil.concurrent.ReentrantMutex ;
import com.sun.corba.se.impl.orbutil.concurrent.CondVar ;

/**
 * POAImpl is the implementation of the Portable Object Adapter. It
 * contains an implementation of the POA interfaces specified in
 * COBRA 2.3.1 chapter 11 (formal/99-10-07).  This implementation
 * is moving to comply with CORBA 3.0 due to the many clarifications
 * that have been made to the POA semantics since CORBA 2.3.1.
 * Specific comments have been added where 3.0 applies, but note that
 * we do not have the new 3.0 APIs yet.
 */
public class POAImpl extends ObjectAdapterBase implements POA
{
    private boolean debug ;

    /* POA creation takes place in 2 stages: first, the POAImpl constructor is
       called, then the initialize method is called.  This separation is
       needed because an AdapterActivator does not know the POAManager or
       the policies when
       the unknown_adapter method is invoked.  However, the POA must be created
       before the unknown_adapter method is invoked, so that the parent knows
       when concurrent attempts are made to create the same POA.
       Calling the POAImpl constructor results in a new POA in state STATE_START.
       Calling initialize( POAManager, Policies ) results in state STATE_RUN.
       Calling destroy results in STATE_DESTROY, which marks the beginning of
       POA destruction.
    */

    // Notes on concurrency.
    // The POA requires careful design for concurrency management to correctly
    // implement the specification and avoid deadlocks.  The order of acquiring
    // locks must respect the following locking hierarchy:
    //
    // 1. Lock POAs before POAManagers
    // 2. Lock a POA before locking its child POA
    //
    // Also note that there are 3 separate conditions on which threads may wait
    // in the POA, as defined by invokeCV, beingDestroyedCV, and
    // adapterActivatorCV.  This means that (for this reason as well as others)
    // we cannot simply use the standard Java synchronized primitive.
    // This implementation uses a modified version of Doug Lea's
    // util.concurrent (version 1.3.0) that supports reentrant
    // mutexes to handle the locking.  This will all be replaced by the new JSR
    // 166 concurrency primitives in J2SE 1.5 and later once the ORB moves to
    // J2SE 1.5.

    // POA state constants
    //
    // Note that ordering is important here: we must have the state defined in
    // this order so that ordered comparison is possible.
    // DO NOT CHANGE THE VALUES OF THE STATE CONSTANTS!!!  In particular, the
    // initialization related states must be lower than STATE_RUN.
    //
    // POA is created in STATE_START
    //
    // Valid state transitions:
    //
    // START to INIT                        after find_POA constructor call
    // START to RUN                         after initialize completes
    // INIT to INIT_DONE                    after initialize completes
    // INIT to DESTROYED                    after failed unknown_adapter
    // INIT_DONE to RUN                     after successful unknown_adapter
    // STATE_RUN to STATE_DESTROYING        after start of destruction
    // STATE_DESTROYING to STATE_DESTROYED  after destruction completes.

    private static final int STATE_START        = 0 ; // constructor complete
    private static final int STATE_INIT         = 1 ; // waiting for adapter activator
    private static final int STATE_INIT_DONE    = 2 ; // adapter activator called create_POA
    private static final int STATE_RUN          = 3 ; // initialized and running
    private static final int STATE_DESTROYING   = 4 ; // being destroyed
    private static final int STATE_DESTROYED    = 5 ; // destruction complete

    private String stateToString()
    {
        switch (state) {
            case STATE_START :
                return "START" ;
            case STATE_INIT :
                return "INIT" ;
            case STATE_INIT_DONE :
                return "INIT_DONE" ;
            case STATE_RUN :
                return "RUN" ;
            case STATE_DESTROYING :
                return "DESTROYING" ;
            case STATE_DESTROYED :
                return "DESTROYED" ;
            default :
                return "UNKNOWN(" + state + ")" ;
        }
    }

    // Current state of the POA
    private int state ;

    // The POA request handler that performs all policy specific operations
    // Note that POAImpl handles all synchronization, so mediator is (mostly)
    // unsynchronized.
    private POAPolicyMediator mediator;

    // Representation of object adapter ID
    private int numLevels;          // counts depth of tree.  Root = 1.
    private ObjectAdapterId poaId ; // the actual object adapter ID for this POA
    private String name;            // the name of this POA

    private POAManagerImpl manager; // This POA's POAManager
    private int uniquePOAId ;       // ID for this POA that is unique relative
                                    // to the POAFactory, which has the same
                                    // lifetime as the ORB.
    private POAImpl parent;         // The POA that created this POA.
    private Map children;           // Map from name to POA of POAs created by
                                    // this POA.

    private AdapterActivator activator;
    private int invocationCount ; // pending invocations on this POA.

    // Data used to control POA concurrency
    // XXX revisit for JSR 166

    // Master lock for all POA synchronization.  See lock and unlock.
    // package private for access by AOMEntry.
    Sync poaMutex ;

    // Wait on this CV for AdapterActivator upcalls to complete
    private CondVar adapterActivatorCV ;

    // Wait on this CV for all active invocations to complete
    private CondVar invokeCV ;

    // Wait on this CV for the destroy method to complete doing its work
    private CondVar beingDestroyedCV ;

    // thread local variable to store a boolean to detect deadlock in
    // POA.destroy().
    protected ThreadLocal isDestroying ;

    // This includes the most important information for debugging
    // POA problems.
    public String toString()
    {
        return "POA[" + poaId.toString() +
            ", uniquePOAId=" + uniquePOAId +
            ", state=" + stateToString() +
            ", invocationCount=" + invocationCount + "]" ;
    }

    // package private for mediator implementations.
    boolean getDebug()
    {
        return debug ;
    }

    // package private for access to servant to POA map
    static POAFactory getPOAFactory( ORB orb )
    {
        return (POAFactory)orb.getRequestDispatcherRegistry().
            getObjectAdapterFactory( ORBConstants.TRANSIENT_SCID ) ;
    }

    // package private so that POAFactory can access it.
    static POAImpl makeRootPOA( ORB orb )
    {
        POAManagerImpl poaManager = new POAManagerImpl( getPOAFactory( orb ),
            orb.getPIHandler() ) ;

        POAImpl result = new POAImpl( ORBConstants.ROOT_POA_NAME,
            null, orb, STATE_START ) ;
        result.initialize( poaManager, Policies.rootPOAPolicies ) ;

        return result ;
    }

    // package private so that POAPolicyMediatorBase can access it.
    int getPOAId()
    {
        return uniquePOAId ;
    }


    // package private so that POAPolicyMediator can access it.
    void lock()
    {
        SyncUtil.acquire( poaMutex ) ;

        if (debug) {
            ORBUtility.dprint( this, "LOCKED poa " + this ) ;
        }
    }

    // package private so that POAPolicyMediator can access it.
    void unlock()
    {
        if (debug) {
            ORBUtility.dprint( this, "UNLOCKED poa " + this ) ;
        }

        poaMutex.release() ;
    }

    // package private so that DelegateImpl can access it.
    Policies getPolicies()
    {
        return mediator.getPolicies() ;
    }

    // Note that the parent POA must be locked when this constructor is called.
    private POAImpl( String name, POAImpl parent, ORB orb, int initialState )
    {
        super( orb ) ;

        debug = orb.poaDebugFlag ;

        if (debug) {
            ORBUtility.dprint( this, "Creating POA with name=" + name +
                " parent=" + parent ) ;
        }

        this.state     = initialState ;
        this.name      = name ;
        this.parent    = parent;
        children = new HashMap();
        activator = null ;

        // This was done in initialize, but I moved it here
        // to get better searchability when tracing.
        uniquePOAId = getPOAFactory( orb ).newPOAId() ;

        if (parent == null) {
            // This is the root POA, which counts as 1 level
            numLevels = 1 ;
        } else {
            // My level is one more than that of my parent
            numLevels = parent.numLevels + 1 ;

            parent.children.put(name, this);
        }

        // Get an array of all of the POA names in order to
        // create the poaid.
        String[] names = new String[ numLevels ] ;
        POAImpl poaImpl = this ;
        int ctr = numLevels - 1 ;
        while (poaImpl != null) {
            names[ctr--] = poaImpl.name ;
            poaImpl = poaImpl.parent ;
        }

        poaId = new ObjectAdapterIdArray( names ) ;

        invocationCount = 0;

        poaMutex = new ReentrantMutex( orb.poaConcurrencyDebugFlag ) ;

        adapterActivatorCV = new CondVar( poaMutex,
            orb.poaConcurrencyDebugFlag ) ;
        invokeCV           = new CondVar( poaMutex,
            orb.poaConcurrencyDebugFlag ) ;
        beingDestroyedCV   = new CondVar( poaMutex,
            orb.poaConcurrencyDebugFlag ) ;

        isDestroying = new ThreadLocal () {
            protected java.lang.Object initialValue() {
                return Boolean.FALSE;
            }
        };
    }

    // The POA lock must be held when this method is called.
    private void initialize( POAManagerImpl manager, Policies policies )
    {
        if (debug) {
            ORBUtility.dprint( this, "Initializing poa " + this +
                " with POAManager=" + manager + " policies=" + policies ) ;
        }

        this.manager = manager;
        manager.addPOA(this);

        mediator = POAPolicyMediatorFactory.create( policies, this ) ;

        // Construct the object key template
        int serverid = mediator.getServerId() ;
        int scid = mediator.getScid() ;
        String orbId = getORB().getORBData().getORBId();

        ObjectKeyTemplate oktemp = new POAObjectKeyTemplate( getORB(),
            scid, serverid, orbId, poaId ) ;

        if (debug) {
            ORBUtility.dprint( this, "Initializing poa: oktemp=" + oktemp ) ;
        }

        // Note that parent == null iff this is the root POA.
        // This was used to avoid executing interceptors on the RootPOA.
        // That is no longer necessary.
        boolean objectAdapterCreated = true; // parent != null ;

        // XXX extract codebase from policies and pass into initializeTemplate
        // after the codebase policy change is finalized.
        initializeTemplate( oktemp, objectAdapterCreated,
                            policies,
                            null, // codebase
                            null, // manager id
                            oktemp.getObjectAdapterId()
                            ) ;

        if (state == STATE_START)
            state = STATE_RUN ;
        else if (state == STATE_INIT)
            state = STATE_INIT_DONE ;
        else
            throw lifecycleWrapper().illegalPoaStateTrans() ;
    }

    // The poaMutex must be held when this method is called
    private boolean waitUntilRunning()
    {
        if (debug) {
            ORBUtility.dprint( this,
                "Calling waitUntilRunning on poa " + this ) ;
        }

        while (state < STATE_RUN) {
            try {
                adapterActivatorCV.await() ;
            } catch (InterruptedException exc) {
                // NO-OP
            }
        }

        if (debug) {
            ORBUtility.dprint( this,
                "Exiting waitUntilRunning on poa " + this ) ;
        }

        // Note that a POA could be destroyed while in STATE_INIT due to a
        // failure in the AdapterActivator upcall.
        return (state == STATE_RUN) ;
    }

    // This method checks that the AdapterActivator finished the
    // initialization of a POA activated in find_POA.  This is
    // determined by checking the state of the POA.  If the state is
    // STATE_INIT, the AdapterActivator did not complete the
    // inialization.  In this case, we destroy the POA that was
    // partially created and return false.  Otherwise, we return true.
    // In any case, we must wake up all threads waiting for the adapter
    // activator, either to continue their invocations, or to return
    // errors to their client.
    //
    // The poaMutex must NOT be held when this method is called.
    private boolean destroyIfNotInitDone()
    {
        try {
            lock() ;

            if (debug) {
                ORBUtility.dprint( this,
                    "Calling destroyIfNotInitDone on poa " + this ) ;
            }

            boolean success = (state == STATE_INIT_DONE) ;

            if (success)
                state = STATE_RUN ;
            else {
                // Don't just use destroy, because the check for
                // deadlock is too general, and can prevent this from
                // functioning properly.
                DestroyThread destroyer = new DestroyThread( false, debug );
                destroyer.doIt( this, true ) ;
            }

            return success ;
        } finally {
            adapterActivatorCV.broadcast() ;

            if (debug) {
                ORBUtility.dprint( this,
                    "Exiting destroyIfNotInitDone on poa " + this ) ;
            }

            unlock() ;
        }
    }

    private byte[] internalReferenceToId(
        org.omg.CORBA.Object reference ) throws WrongAdapter
    {
        IOR ior = ORBUtility.getIOR( reference ) ;
        IORTemplateList thisTemplate = ior.getIORTemplates() ;

        ObjectReferenceFactory orf = getCurrentFactory() ;
        IORTemplateList poaTemplate =
            IORFactories.getIORTemplateList( orf ) ;

        if (!poaTemplate.isEquivalent( thisTemplate ))
            throw new WrongAdapter();

        // Extract the ObjectId from the first TaggedProfile in the IOR.
        // If ior was created in this POA, the same ID was used for
        // every profile through the profile templates in the currentFactory,
        // so we will get the same result from any profile.
        Iterator iter = ior.iterator() ;
        if (!iter.hasNext())
            throw iorWrapper().noProfilesInIor() ;
        TaggedProfile prof = (TaggedProfile)(iter.next()) ;
        ObjectId oid = prof.getObjectId() ;

        return oid.getId();
    }

    // Converted from anonymous class to local class
    // so that we can call performDestroy() directly.
    static class DestroyThread extends Thread {
        private boolean wait ;
        private boolean etherealize ;
        private boolean debug ;
        private POAImpl thePoa ;

        public DestroyThread( boolean etherealize, boolean debug )
        {
            this.etherealize = etherealize ;
            this.debug = debug ;
        }

        public void doIt( POAImpl thePoa, boolean wait )
        {
            if (debug) {
                ORBUtility.dprint( this,
                    "Calling DestroyThread.doIt(thePOA=" + thePoa +
                    " wait=" + wait + " etherealize=" + etherealize ) ;
            }

            this.thePoa = thePoa ;
            this.wait = wait ;

            if (wait) {
                run() ;
            } else {
                // Catch exceptions since setDaemon can cause a
                // security exception to be thrown under netscape
                // in the Applet mode
                try { setDaemon(true); } catch (Exception e) {}
                start() ;
            }
        }

        public void run()
        {
            Set destroyedPOATemplates = new HashSet() ;

            performDestroy( thePoa, destroyedPOATemplates );

            Iterator iter = destroyedPOATemplates.iterator() ;
            ObjectReferenceTemplate[] orts = new ObjectReferenceTemplate[
                destroyedPOATemplates.size() ] ;
            int index = 0 ;
            while (iter.hasNext())
                orts[ index++ ] = (ObjectReferenceTemplate)iter.next();

            thePoa.getORB().getPIHandler().adapterStateChanged( orts,
                NON_EXISTENT.value ) ;
        }

        // Returns true if destruction must be completed, false
        // if not, which means that another thread is already
        // destroying poa.
        private boolean prepareForDestruction( POAImpl poa,
            Set destroyedPOATemplates )
        {
            POAImpl[] childPoas = null ;

            // Note that we do not synchronize on this, since this is
            // the PerformDestroy instance, not the POA.
            try {
                poa.lock() ;

                if (debug) {
                    ORBUtility.dprint( this,
                        "Calling performDestroy on poa " + poa ) ;
                }

                if (poa.state <= STATE_RUN) {
                    poa.state = STATE_DESTROYING ;
                } else {
                    // destroy may be called multiple times, and each call
                    // is allowed to proceed with its own setting of the wait
                    // flag, but the etherealize value is used from the first
                    // call to destroy.  Also all children should be destroyed
                    // before the parent POA.  If the poa is already destroyed,
                    // we can just return.  If the poa has started destruction,
                    // but not completed, and wait is true, we need to wait
                    // until destruction is complete, then just return.
                    if (wait)
                        while (poa.state != STATE_DESTROYED) {
                            try {
                                poa.beingDestroyedCV.await() ;
                            } catch (InterruptedException exc) {
                                // NO-OP
                            }
                        }

                    return false ;
                }

                poa.isDestroying.set(Boolean.TRUE);

                // Make a copy since we can't hold the lock while destroying
                // the children, and an iterator is not deletion-safe.
                childPoas = (POAImpl[])poa.children.values().toArray(
                    new POAImpl[0] );
            } finally {
                poa.unlock() ;
            }

            // We are not holding the POA mutex here to avoid holding it
            // while destroying the POA's children, since this may involve
            // upcalls to etherealize methods.

            for (int ctr=0; ctr<childPoas.length; ctr++ ) {
                performDestroy( childPoas[ctr], destroyedPOATemplates ) ;
            }

            return true ;
        }

        public void performDestroy( POAImpl poa, Set destroyedPOATemplates )
        {
            if (!prepareForDestruction( poa, destroyedPOATemplates ))
                return ;

            // NOTE: If we are here, poa is in STATE_DESTROYING state. All
            // other state checks are taken care of in prepareForDestruction.
            // No other threads may either be starting new invocations
            // by calling enter or starting to destroy poa.  There may
            // still be pending invocations.

            POAImpl parent = poa.parent ;
            boolean isRoot = parent == null ;

            try {
                // Note that we must lock the parent before the child.
                // The parent lock is required (if poa is not the root)
                // to safely remove poa from parent's children Map.
                if (!isRoot)
                    parent.lock() ;

                try {
                    poa.lock() ;

                    completeDestruction( poa, parent,
                        destroyedPOATemplates ) ;
                } finally {
                    poa.unlock() ;

                    if (isRoot)
                        // We have just destroyed the root POA, so we need to
                        // make sure that the next call to
                        // resolve_initial_reference( "RootPOA" )
                        // will recreate a valid root POA.
                        poa.manager.getFactory().registerRootPOA() ;
                }
            } finally {
                if (!isRoot) {
                    parent.unlock() ;
                    poa.parent = null ;
                }
            }
        }

        private void completeDestruction( POAImpl poa, POAImpl parent,
            Set destroyedPOATemplates )
        {
            if (debug) {
                ORBUtility.dprint( this,
                    "Calling completeDestruction on poa " + poa ) ;
            }

            try {
                while (poa.invocationCount != 0) {
                    try {
                        poa.invokeCV.await() ;
                    } catch (InterruptedException ex) {
                        // NO-OP
                    }
                }

                if (poa.mediator != null) {
                    if (etherealize)
                        poa.mediator.etherealizeAll();

                    poa.mediator.clearAOM() ;
                }

                if (poa.manager != null)
                    poa.manager.removePOA(poa);

                if (parent != null)
                    parent.children.remove( poa.name ) ;

                destroyedPOATemplates.add( poa.getAdapterTemplate() ) ;
            } catch (Throwable thr) {
                if (thr instanceof ThreadDeath)
                    throw (ThreadDeath)thr ;

                poa.lifecycleWrapper().unexpectedException( thr, poa.toString() ) ;
            } finally {
                poa.state = STATE_DESTROYED ;
                poa.beingDestroyedCV.broadcast();
                poa.isDestroying.set(Boolean.FALSE);

                if (debug) {
                    ORBUtility.dprint( this,
                        "Exiting completeDestruction on poa " + poa ) ;
                }
            }
        }
    }

    void etherealizeAll()
    {
        try {
            lock() ;

            if (debug) {
                ORBUtility.dprint( this,
                    "Calling etheralizeAll on poa " + this ) ;
            }

            mediator.etherealizeAll() ;
        } finally {
            if (debug) {
                ORBUtility.dprint( this,
                    "Exiting etheralizeAll on poa " + this ) ;
            }

            unlock() ;
        }
    }

 //*******************************************************************
 // Public POA API
 //*******************************************************************

    /**
     * <code>create_POA</code>
     * <b>Section 3.3.8.2</b>
     */
    public POA create_POA(String name, POAManager
        theManager, Policy[] policies) throws AdapterAlreadyExists,
        InvalidPolicy
    {
        try {
            lock() ;

            if (debug) {
                ORBUtility.dprint( this, "Calling create_POA(name=" + name +
                    " theManager=" + theManager + " policies=" + policies +
                    ") on poa " + this ) ;
            }

            // We cannot create children of a POA that is (being) destroyed.
            // This has been added to the CORBA 3.0 spec.
            if (state > STATE_RUN)
                throw omgLifecycleWrapper().createPoaDestroy() ;

            POAImpl poa = (POAImpl)(children.get(name)) ;

            if (poa == null) {
                poa = new POAImpl( name, this, getORB(), STATE_START ) ;
            }

            try {
                poa.lock() ;

                if (debug) {
                    ORBUtility.dprint( this,
                        "Calling create_POA: new poa is " + poa ) ;
                }

                if ((poa.state != STATE_START) && (poa.state != STATE_INIT))
                    throw new AdapterAlreadyExists();

                POAManagerImpl newManager = (POAManagerImpl)theManager ;
                if (newManager == null)
                    newManager = new POAManagerImpl( manager.getFactory(),
                        manager.getPIHandler() );

                int defaultCopierId =
                    getORB().getCopierManager().getDefaultId() ;
                Policies POAPolicies =
                    new Policies( policies, defaultCopierId ) ;

                poa.initialize( newManager, POAPolicies ) ;

                return poa;
            } finally {
                poa.unlock() ;
            }
        } finally {
            unlock() ;
        }
    }

    /**
     * <code>find_POA</code>
     * <b>Section 3.3.8.3</b>
     */
    public POA find_POA(String name, boolean activate)
        throws AdapterNonExistent
    {
        POAImpl found = null ;
        AdapterActivator act = null ;

        lock() ;

        if (debug) {
            ORBUtility.dprint( this, "Calling find_POA(name=" + name +
                " activate=" + activate + ") on poa " + this ) ;
        }

        found = (POAImpl) children.get(name);

        if (found != null) {
            if (debug) {
                ORBUtility.dprint( this,
                    "Calling find_POA: found poa " + found ) ;
            }

            try {
                found.lock() ;

                // Do not hold the parent POA lock while
                // waiting for child to complete initialization.
                unlock() ;

                // Make sure that the child has completed its initialization,
                // if it was created by an AdapterActivator, otherwise throw
                // a standard TRANSIENT exception with minor code 4 (see
                // CORBA 3.0 11.3.9.3, in reference to unknown_adapter)
                if (!found.waitUntilRunning())
                    throw omgLifecycleWrapper().poaDestroyed() ;

                // Note that found may be in state DESTROYING or DESTROYED at
                // this point.  That's OK, since destruction could start at
                // any time.
            } finally {
                found.unlock() ;
            }
        } else {
            try {
                if (debug) {
                    ORBUtility.dprint( this,
                        "Calling find_POA: no poa found" ) ;
                }

                if (activate && (activator != null)) {
                    // Create a child, but don't initialize it.  The newly
                    // created POA will be in state STATE_START, which will
                    // cause other calls to find_POA that are creating the same
                    // POA to block on the waitUntilRunning call above.
                    // Initialization must be completed by a call to create_POA
                    // inside the unknown_adapter upcall.  Note that
                    // this.poaMutex must be held here so that this.children
                    // can be safely updated.  The state is set to STATE_INIT
                    // so that initialize can make the correct state transition
                    // when create_POA is called inside the AdapterActivator.
                    // This avoids activating the new POA too soon
                    // by transitioning to STATE_RUN after unknown_adapter
                    // returns.
                    found = new POAImpl( name, this, getORB(), STATE_INIT ) ;

                    if (debug) {
                        ORBUtility.dprint( this,
                            "Calling find_POA: created poa " + found ) ;
                    }

                    act = activator ;
                } else {
                    throw new AdapterNonExistent();
                }
            } finally {
                unlock() ;
            }
        }

        // assert (found != null)
        // assert not holding this.poaMutex OR found.poaMutex

        // We must not hold either this.poaMutex or found.poaMutex here while
        // waiting for intialization of found to complete to prevent possible
        // deadlocks.

        if (act != null) {
            boolean status = false ;
            boolean adapterResult = false ;

            if (debug) {
                ORBUtility.dprint( this,
                    "Calling find_POA: calling AdapterActivator"  ) ;
            }

            try {
                // Prevent more than one thread at a time from executing in act
                // in case act is shared between multiple POAs.
                synchronized (act) {
                    status = act.unknown_adapter(this, name);
                }
            } catch (SystemException exc) {
                throw omgLifecycleWrapper().adapterActivatorException( exc,
                    name, poaId.toString() ) ;
            } catch (Throwable thr) {
                // ignore most non-system exceptions, but log them for
                // diagnostic purposes.
                lifecycleWrapper().unexpectedException( thr, this.toString() ) ;

                if (thr instanceof ThreadDeath)
                    throw (ThreadDeath)thr ;
            } finally {
                // At this point, we have completed adapter activation.
                // Whether this was successful or not, we must call
                // destroyIfNotInitDone so that calls to enter() and create_POA()
                // that are waiting can execute again.  Failing to do this
                // will cause the system to hang in complex tests.
                adapterResult = found.destroyIfNotInitDone() ;
            }

            if (status) {
                if (!adapterResult)
                    throw omgLifecycleWrapper().adapterActivatorException( name,
                        poaId.toString() ) ;
            } else {
                if (debug) {
                    ORBUtility.dprint( this,
                        "Calling find_POA: AdapterActivator returned false"  ) ;
                }

                // OMG Issue 3740 is resolved to throw AdapterNonExistent if
                // unknown_adapter() returns false.
                throw new AdapterNonExistent();
            }
        }

        return found;
    }

    /**
     * <code>destroy</code>
     * <b>Section 3.3.8.4</b>
     */
    public void destroy(boolean etherealize, boolean wait_for_completion)
    {
        // This is to avoid deadlock
        if (wait_for_completion && getORB().isDuringDispatch()) {
            throw lifecycleWrapper().destroyDeadlock() ;
        }

        DestroyThread destroyer = new DestroyThread( etherealize, debug );
        destroyer.doIt( this, wait_for_completion ) ;
    }

    /**
     * <code>create_thread_policy</code>
     * <b>Section 3.3.8.5</b>
     */
    public ThreadPolicy create_thread_policy(
        ThreadPolicyValue value)
    {
        return new ThreadPolicyImpl(value);
    }

    /**
     * <code>create_lifespan_policy</code>
     * <b>Section 3.3.8.5</b>
     */
    public LifespanPolicy create_lifespan_policy(
        LifespanPolicyValue value)
    {
        return new LifespanPolicyImpl(value);
    }

    /**
     * <code>create_id_uniqueness_policy</code>
     * <b>Section 3.3.8.5</b>
     */
    public IdUniquenessPolicy create_id_uniqueness_policy(
        IdUniquenessPolicyValue value)
    {
        return new IdUniquenessPolicyImpl(value);
    }

    /**
     * <code>create_id_assignment_policy</code>
     * <b>Section 3.3.8.5</b>
     */
    public IdAssignmentPolicy create_id_assignment_policy(
        IdAssignmentPolicyValue value)
    {
        return new IdAssignmentPolicyImpl(value);
    }

    /**
     * <code>create_implicit_activation_policy</code>
     * <b>Section 3.3.8.5</b>
     */
    public ImplicitActivationPolicy create_implicit_activation_policy(
        ImplicitActivationPolicyValue value)
    {
        return new ImplicitActivationPolicyImpl(value);
    }

    /**
     * <code>create_servant_retention_policy</code>
     * <b>Section 3.3.8.5</b>
     */
    public ServantRetentionPolicy create_servant_retention_policy(
        ServantRetentionPolicyValue value)
    {
        return new ServantRetentionPolicyImpl(value);
    }

    /**
     * <code>create_request_processing_policy</code>
     * <b>Section 3.3.8.5</b>
     */
    public RequestProcessingPolicy create_request_processing_policy(
        RequestProcessingPolicyValue value)
    {
        return new RequestProcessingPolicyImpl(value);
    }

    /**
     * <code>the_name</code>
     * <b>Section 3.3.8.6</b>
     */
    public String the_name()
    {
        try {
            lock() ;

            return name;
        } finally {
            unlock() ;
        }
    }

    /**
     * <code>the_parent</code>
     * <b>Section 3.3.8.7</b>
     */
    public POA the_parent()
    {
        try {
            lock() ;

            return parent;
        } finally {
            unlock() ;
        }
    }

    /**
     * <code>the_children</code>
     */
    public org.omg.PortableServer.POA[] the_children()
    {
        try {
            lock() ;

            Collection coll = children.values() ;
            int size = coll.size() ;
            POA[] result = new POA[ size ] ;
            int index = 0 ;
            Iterator iter = coll.iterator() ;
            while (iter.hasNext()) {
                POA poa = (POA)(iter.next()) ;
                result[ index++ ] = poa ;
            }

            return result ;
        } finally {
            unlock() ;
        }
    }

    /**
     * <code>the_POAManager</code>
     * <b>Section 3.3.8.8</b>
     */
    public POAManager the_POAManager()
    {
        try {
            lock() ;

            return manager;
        } finally {
            unlock() ;
        }
    }

    /**
     * <code>the_activator</code>
     * <b>Section 3.3.8.9</b>
     */
    public AdapterActivator the_activator()
    {
        try {
            lock() ;

            return activator;
        } finally {
            unlock() ;
        }
    }

    /**
     * <code>the_activator</code>
     * <b>Section 3.3.8.9</b>
     */
    public void the_activator(AdapterActivator activator)
    {
        try {
            lock() ;

            if (debug) {
                ORBUtility.dprint( this, "Calling the_activator on poa " +
                    this + " activator=" + activator ) ;
            }

            this.activator = activator;
        } finally {
            unlock() ;
        }
    }

    /**
     * <code>get_servant_manager</code>
     * <b>Section 3.3.8.10</b>
     */
    public ServantManager get_servant_manager() throws WrongPolicy
    {
        try {
            lock() ;

            return mediator.getServantManager() ;
        } finally {
            unlock() ;
        }
    }

    /**
     * <code>set_servant_manager</code>
     * <b>Section 3.3.8.10</b>
     */
    public void set_servant_manager(ServantManager servantManager)
        throws WrongPolicy
    {
        try {
            lock() ;

            if (debug) {
                ORBUtility.dprint( this, "Calling set_servant_manager on poa " +
                    this + " servantManager=" + servantManager ) ;
            }

            mediator.setServantManager( servantManager ) ;
        } finally {
            unlock() ;
        }
    }

    /**
     * <code>get_servant</code>
     * <b>Section 3.3.8.12</b>
     */
    public Servant get_servant() throws NoServant, WrongPolicy
    {
        try {
            lock() ;

            return mediator.getDefaultServant() ;
        } finally {
            unlock() ;
        }
    }

    /**
     * <code>set_servant</code>
     * <b>Section 3.3.8.13</b>
     */
    public void set_servant(Servant defaultServant)
        throws WrongPolicy
    {
        try {
            lock() ;

            if (debug) {
                ORBUtility.dprint( this, "Calling set_servant on poa " +
                    this + " defaultServant=" + defaultServant ) ;
            }

            mediator.setDefaultServant( defaultServant ) ;
        } finally {
            unlock() ;
        }
    }

    /**
     * <code>activate_object</code>
     * <b>Section 3.3.8.14</b>
     */
    public byte[] activate_object(Servant servant)
        throws ServantAlreadyActive, WrongPolicy
    {
        try {
            lock() ;

            if (debug) {
                ORBUtility.dprint( this,
                    "Calling activate_object on poa " + this +
                    " (servant=" + servant + ")" ) ;
            }

            // Allocate a new system-generated object-id.
            // This will throw WrongPolicy if not SYSTEM_ID
            // policy.
            byte[] id = mediator.newSystemId();

            try {
                mediator.activateObject( id, servant ) ;
            } catch (ObjectAlreadyActive oaa) {
                // This exception can not occur in this case,
                // since id is always brand new.
                //
            }

            return id ;
        } finally {
            if (debug) {
                ORBUtility.dprint( this,
                    "Exiting activate_object on poa " + this ) ;
            }

            unlock() ;
        }
    }

    /**
     * <code>activate_object_with_id</code>
     * <b>Section 3.3.8.15</b>
     */
    public void activate_object_with_id(byte[] id,
                                                     Servant servant)
        throws ObjectAlreadyActive, ServantAlreadyActive, WrongPolicy
    {
        try {
            lock() ;

            if (debug) {
                ORBUtility.dprint( this,
                    "Calling activate_object_with_id on poa " + this +
                    " (servant=" + servant + " id=" + id + ")" ) ;
            }

            // Clone the id to avoid possible errors due to aliasing
            // (e.g. the client passes the id in and then changes it later).
            byte[] idClone = (byte[])(id.clone()) ;

            mediator.activateObject( idClone, servant ) ;
        } finally {
            if (debug) {
                ORBUtility.dprint( this,
                    "Exiting activate_object_with_id on poa " + this ) ;
            }

            unlock() ;
        }
    }

    /**
     * <code>deactivate_object</code>
     * <b>3.3.8.16</b>
     */
    public void deactivate_object(byte[] id)
        throws ObjectNotActive, WrongPolicy
    {
        try {
            lock() ;

            if (debug) {
                ORBUtility.dprint( this,
                    "Calling deactivate_object on poa " + this +
                    " (id=" + id + ")" ) ;
            }

            mediator.deactivateObject( id ) ;
        } finally {
            if (debug) {
                ORBUtility.dprint( this,
                    "Exiting deactivate_object on poa " + this ) ;
            }

            unlock() ;
        }
    }

    /**
     * <code>create_reference</code>
     * <b>3.3.8.17</b>
     */
    public org.omg.CORBA.Object create_reference(String repId)
        throws WrongPolicy
    {
        try {
            lock() ;

            if (debug) {
                ORBUtility.dprint( this, "Calling create_reference(repId=" +
                    repId + ") on poa " + this ) ;
            }

            return makeObject( repId, mediator.newSystemId()) ;
        } finally {
            unlock() ;
        }
    }

    /**
     * <code>create_reference_with_id</code>
     * <b>3.3.8.18</b>
     */
    public org.omg.CORBA.Object
        create_reference_with_id(byte[] oid, String repId)
    {
        try {
            lock() ;

            if (debug) {
                ORBUtility.dprint( this,
                    "Calling create_reference_with_id(oid=" +
                    oid + " repId=" + repId + ") on poa " + this ) ;
            }

            // Clone the id to avoid possible errors due to aliasing
            // (e.g. the client passes the id in and then changes it later).
            byte[] idClone = (byte[])(oid.clone()) ;

            return makeObject( repId, idClone ) ;
        } finally {
            unlock() ;
        }
    }

    /**
     * <code>servant_to_id</code>
     * <b>3.3.8.19</b>
     */
    public byte[] servant_to_id(Servant servant)
        throws ServantNotActive, WrongPolicy
    {
        try {
            lock() ;

            if (debug) {
                ORBUtility.dprint( this, "Calling servant_to_id(servant=" +
                    servant + ") on poa " + this ) ;
            }

            return mediator.servantToId( servant ) ;
        } finally {
            unlock() ;
        }
    }

    /**
     * <code>servant_to_reference</code>
     * <b>3.3.8.20</b>
     */
    public org.omg.CORBA.Object servant_to_reference(Servant servant)
        throws ServantNotActive, WrongPolicy
    {
        try {
            lock() ;

            if (debug) {
                ORBUtility.dprint( this,
                    "Calling servant_to_reference(servant=" +
                    servant + ") on poa " + this ) ;
            }

            byte[] oid = mediator.servantToId(servant);
            String repId = servant._all_interfaces( this, oid )[0] ;
            return create_reference_with_id(oid, repId);
        } finally {
            unlock() ;
        }
    }

    /**
     * <code>reference_to_servant</code>
     * <b>3.3.8.21</b>
     */
    public Servant reference_to_servant(org.omg.CORBA.Object reference)
        throws ObjectNotActive, WrongPolicy, WrongAdapter
    {
        try {
            lock() ;

            if (debug) {
                ORBUtility.dprint( this,
                    "Calling reference_to_servant(reference=" +
                    reference + ") on poa " + this ) ;
            }

            if ( state >= STATE_DESTROYING ) {
                throw lifecycleWrapper().adapterDestroyed() ;
            }

            // reference_to_id should throw WrongAdapter
            // if the objref was not created by this POA
            byte [] id = internalReferenceToId(reference);

            return mediator.idToServant( id ) ;
        } finally {
            unlock() ;
        }
    }

    /**
     * <code>reference_to_id</code>
     * <b>3.3.8.22</b>
     */
    public byte[] reference_to_id(org.omg.CORBA.Object reference)
        throws WrongAdapter, WrongPolicy
    {
        try {
            lock() ;

            if (debug) {
                ORBUtility.dprint( this, "Calling reference_to_id(reference=" +
                    reference + ") on poa " + this ) ;
            }

            if( state >= STATE_DESTROYING ) {
                throw lifecycleWrapper().adapterDestroyed() ;
            }

            return internalReferenceToId( reference ) ;
        } finally {
            unlock() ;
        }
    }

    /**
     * <code>id_to_servant</code>
     * <b>3.3.8.23</b>
     */
    public Servant id_to_servant(byte[] id)
        throws ObjectNotActive, WrongPolicy
    {
        try {
            lock() ;

            if (debug) {
                ORBUtility.dprint( this, "Calling id_to_servant(id=" +
                    id + ") on poa " + this ) ;
            }

            if( state >= STATE_DESTROYING ) {
                throw lifecycleWrapper().adapterDestroyed() ;
            }
            return mediator.idToServant( id ) ;
        } finally {
            unlock() ;
        }
    }

    /**
     * <code>id_to_reference</code>
     * <b>3.3.8.24</b>
     */
    public org.omg.CORBA.Object id_to_reference(byte[] id)
        throws ObjectNotActive, WrongPolicy

    {
        try {
            lock() ;

            if (debug) {
                ORBUtility.dprint( this, "Calling id_to_reference(id=" +
                    id + ") on poa " + this ) ;
            }

            if( state >= STATE_DESTROYING ) {
                throw lifecycleWrapper().adapterDestroyed() ;
            }

            Servant s = mediator.idToServant( id ) ;
            String repId = s._all_interfaces( this, id )[0] ;
            return makeObject(repId, id );
        } finally {
            unlock() ;
        }
    }

    /**
     * <code>id</code>
     * <b>11.3.8.26 in ptc/00-08-06</b>
     */
    public byte[] id()
    {
        try {
            lock() ;

            return getAdapterId() ;
        } finally {
            unlock() ;
        }
    }

    //***************************************************************
    //Implementation of ObjectAdapter interface
    //***************************************************************

    public Policy getEffectivePolicy( int type )
    {
        return mediator.getPolicies().get_effective_policy( type ) ;
    }

    public int getManagerId()
    {
        return manager.getManagerId() ;
    }

    public short getState()
    {
        return manager.getORTState() ;
    }

    public String[] getInterfaces( java.lang.Object servant, byte[] objectId )
    {
        Servant serv = (Servant)servant ;
        return serv._all_interfaces( this, objectId ) ;
    }

    protected ObjectCopierFactory getObjectCopierFactory()
    {
        int copierId = mediator.getPolicies().getCopierId() ;
        CopierManager cm = getORB().getCopierManager() ;
        return cm.getObjectCopierFactory( copierId ) ;
    }

    public void enter() throws OADestroyed
    {
        try {
            lock() ;

            if (debug) {
                ORBUtility.dprint( this, "Calling enter on poa " + this ) ;
            }

            // Avoid deadlock if this is the thread that is processing the
            // POA.destroy because this is the only thread that can notify
            // waiters on beingDestroyedCV.  This can happen if an
            // etherealize upcall invokes a method on a colocated object
            // served by this POA.
            while ((state == STATE_DESTROYING) &&
                (isDestroying.get() == Boolean.FALSE)) {
                try {
                    beingDestroyedCV.await();
                } catch (InterruptedException ex) {
                    // NO-OP
                }
            }

            if (!waitUntilRunning())
                throw new OADestroyed() ;

            invocationCount++;
        } finally {
            if (debug) {
                ORBUtility.dprint( this, "Exiting enter on poa " + this ) ;
            }

            unlock() ;
        }

        manager.enter();
    }

    public void exit()
    {
        try {
            lock() ;

            if (debug) {
                ORBUtility.dprint( this, "Calling exit on poa " + this ) ;
            }

            invocationCount--;

            if ((invocationCount == 0) && (state == STATE_DESTROYING)) {
                invokeCV.broadcast();
            }
        } finally {
            if (debug) {
                ORBUtility.dprint( this, "Exiting exit on poa " + this ) ;
            }

            unlock() ;
        }

        manager.exit();
    }

    public void getInvocationServant( OAInvocationInfo info )
    {
        try {
            lock() ;

            if (debug) {
                ORBUtility.dprint( this,
                    "Calling getInvocationServant on poa " + this ) ;
            }

            java.lang.Object servant = null ;

            try {
                servant = mediator.getInvocationServant( info.id(),
                    info.getOperation() );
            } catch (ForwardRequest freq) {
                throw new ForwardException( getORB(), freq.forward_reference ) ;
            }

            info.setServant( servant ) ;
        } finally {
            if (debug) {
                ORBUtility.dprint( this,
                    "Exiting getInvocationServant on poa " + this ) ;
            }

            unlock() ;
        }
    }

    public org.omg.CORBA.Object getLocalServant( byte[] objectId )
    {
        return null ;
    }

    /** Called from the subcontract to let this POA cleanup after an
     *  invocation. Note: If getServant was called, then returnServant
     *  MUST be called, even in the case of exceptions.  This may be
     *  called multiple times for a single request.
     */
    public void returnServant()
    {
        try {
            lock() ;

            if (debug) {
                ORBUtility.dprint( this,
                    "Calling returnServant on poa " + this  ) ;
            }

            mediator.returnServant();
        } catch (Throwable thr) {
            if (debug) {
                ORBUtility.dprint( this,
                    "Exception " + thr + " in returnServant on poa " + this  ) ;
            }

            if (thr instanceof Error)
                throw (Error)thr ;
            else if (thr instanceof RuntimeException)
                throw (RuntimeException)thr ;

        } finally {
            if (debug) {
                ORBUtility.dprint( this,
                    "Exiting returnServant on poa " + this  ) ;
            }

            unlock() ;
        }
    }
}
