POAImpl.java revision 758:bb6bf34f121f
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
26package com.sun.corba.se.impl.oa.poa;
27
28import java.util.Collection ;
29import java.util.Set ;
30import java.util.HashSet ;
31import java.util.Map ;
32import java.util.HashMap ;
33import java.util.Iterator ;
34
35import org.omg.CORBA.Policy ;
36import org.omg.CORBA.SystemException ;
37
38import org.omg.PortableServer.POA ;
39import org.omg.PortableServer.Servant ;
40import org.omg.PortableServer.POAManager ;
41import org.omg.PortableServer.AdapterActivator ;
42import org.omg.PortableServer.ServantManager ;
43import org.omg.PortableServer.ForwardRequest ;
44import org.omg.PortableServer.ThreadPolicy;
45import org.omg.PortableServer.LifespanPolicy;
46import org.omg.PortableServer.IdUniquenessPolicy;
47import org.omg.PortableServer.IdAssignmentPolicy;
48import org.omg.PortableServer.ImplicitActivationPolicy;
49import org.omg.PortableServer.ServantRetentionPolicy;
50import org.omg.PortableServer.RequestProcessingPolicy;
51import org.omg.PortableServer.ThreadPolicyValue ;
52import org.omg.PortableServer.LifespanPolicyValue ;
53import org.omg.PortableServer.IdUniquenessPolicyValue ;
54import org.omg.PortableServer.IdAssignmentPolicyValue ;
55import org.omg.PortableServer.ImplicitActivationPolicyValue ;
56import org.omg.PortableServer.ServantRetentionPolicyValue ;
57import org.omg.PortableServer.RequestProcessingPolicyValue ;
58import org.omg.PortableServer.POAPackage.AdapterAlreadyExists ;
59import org.omg.PortableServer.POAPackage.AdapterNonExistent ;
60import org.omg.PortableServer.POAPackage.InvalidPolicy ;
61import org.omg.PortableServer.POAPackage.WrongPolicy ;
62import org.omg.PortableServer.POAPackage.WrongAdapter ;
63import org.omg.PortableServer.POAPackage.NoServant ;
64import org.omg.PortableServer.POAPackage.ServantAlreadyActive ;
65import org.omg.PortableServer.POAPackage.ObjectAlreadyActive ;
66import org.omg.PortableServer.POAPackage.ServantNotActive ;
67import org.omg.PortableServer.POAPackage.ObjectNotActive ;
68
69import org.omg.PortableInterceptor.ObjectReferenceFactory ;
70import org.omg.PortableInterceptor.ObjectReferenceTemplate ;
71import org.omg.PortableInterceptor.NON_EXISTENT ;
72
73import org.omg.IOP.TAG_INTERNET_IOP ;
74
75import com.sun.corba.se.spi.copyobject.CopierManager ;
76import com.sun.corba.se.spi.copyobject.ObjectCopier ;
77import com.sun.corba.se.spi.copyobject.ObjectCopierFactory ;
78import com.sun.corba.se.spi.oa.OADestroyed ;
79import com.sun.corba.se.spi.oa.OAInvocationInfo ;
80import com.sun.corba.se.spi.oa.ObjectAdapter ;
81import com.sun.corba.se.spi.oa.ObjectAdapterBase ;
82import com.sun.corba.se.spi.oa.ObjectAdapterFactory ;
83import com.sun.corba.se.spi.ior.ObjectKeyTemplate ;
84import com.sun.corba.se.spi.ior.ObjectId ;
85import com.sun.corba.se.spi.ior.ObjectAdapterId ;
86import com.sun.corba.se.spi.ior.IOR ;
87import com.sun.corba.se.spi.ior.IORFactories ;
88import com.sun.corba.se.spi.ior.IORTemplate ;
89import com.sun.corba.se.spi.ior.IORTemplateList ;
90import com.sun.corba.se.spi.ior.TaggedProfile ;
91import com.sun.corba.se.spi.ior.iiop.IIOPProfile ;
92import com.sun.corba.se.spi.ior.iiop.IIOPAddress ;
93import com.sun.corba.se.spi.ior.iiop.IIOPFactories ;
94import com.sun.corba.se.spi.orb.ORB ;
95import com.sun.corba.se.spi.protocol.ForwardException ;
96import com.sun.corba.se.spi.transport.SocketOrChannelAcceptor;
97
98import com.sun.corba.se.impl.ior.POAObjectKeyTemplate ;
99import com.sun.corba.se.impl.ior.ObjectAdapterIdArray ;
100import com.sun.corba.se.impl.orbutil.ORBUtility;
101import com.sun.corba.se.impl.orbutil.ORBConstants;
102import com.sun.corba.se.impl.orbutil.concurrent.Sync ;
103import com.sun.corba.se.impl.orbutil.concurrent.SyncUtil ;
104import com.sun.corba.se.impl.orbutil.concurrent.ReentrantMutex ;
105import 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 */
116public 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}
1694