POAImpl.java revision 667:d0315150c39d
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 ;
106import com.sun.corba.se.impl.transport.ManagedLocalsThread;
107
108/**
109 * POAImpl is the implementation of the Portable Object Adapter. It
110 * contains an implementation of the POA interfaces specified in
111 * COBRA 2.3.1 chapter 11 (formal/99-10-07).  This implementation
112 * is moving to comply with CORBA 3.0 due to the many clarifications
113 * that have been made to the POA semantics since CORBA 2.3.1.
114 * Specific comments have been added where 3.0 applies, but note that
115 * we do not have the new 3.0 APIs yet.
116 */
117public class POAImpl extends ObjectAdapterBase implements POA
118{
119    private boolean debug ;
120
121    /* POA creation takes place in 2 stages: first, the POAImpl constructor is
122       called, then the initialize method is called.  This separation is
123       needed because an AdapterActivator does not know the POAManager or
124       the policies when
125       the unknown_adapter method is invoked.  However, the POA must be created
126       before the unknown_adapter method is invoked, so that the parent knows
127       when concurrent attempts are made to create the same POA.
128       Calling the POAImpl constructor results in a new POA in state STATE_START.
129       Calling initialize( POAManager, Policies ) results in state STATE_RUN.
130       Calling destroy results in STATE_DESTROY, which marks the beginning of
131       POA destruction.
132    */
133
134    // Notes on concurrency.
135    // The POA requires careful design for concurrency management to correctly
136    // implement the specification and avoid deadlocks.  The order of acquiring
137    // locks must respect the following locking hierarchy:
138    //
139    // 1. Lock POAs before POAManagers
140    // 2. Lock a POA before locking its child POA
141    //
142    // Also note that there are 3 separate conditions on which threads may wait
143    // in the POA, as defined by invokeCV, beingDestroyedCV, and
144    // adapterActivatorCV.  This means that (for this reason as well as others)
145    // we cannot simply use the standard Java synchronized primitive.
146    // This implementation uses a modified version of Doug Lea's
147    // util.concurrent (version 1.3.0) that supports reentrant
148    // mutexes to handle the locking.  This will all be replaced by the new JSR
149    // 166 concurrency primitives in J2SE 1.5 and later once the ORB moves to
150    // J2SE 1.5.
151
152    // POA state constants
153    //
154    // Note that ordering is important here: we must have the state defined in
155    // this order so that ordered comparison is possible.
156    // DO NOT CHANGE THE VALUES OF THE STATE CONSTANTS!!!  In particular, the
157    // initialization related states must be lower than STATE_RUN.
158    //
159    // POA is created in STATE_START
160    //
161    // Valid state transitions:
162    //
163    // START to INIT                        after find_POA constructor call
164    // START to RUN                         after initialize completes
165    // INIT to INIT_DONE                    after initialize completes
166    // INIT to DESTROYED                    after failed unknown_adapter
167    // INIT_DONE to RUN                     after successful unknown_adapter
168    // STATE_RUN to STATE_DESTROYING        after start of destruction
169    // STATE_DESTROYING to STATE_DESTROYED  after destruction completes.
170
171    private static final int STATE_START        = 0 ; // constructor complete
172    private static final int STATE_INIT         = 1 ; // waiting for adapter activator
173    private static final int STATE_INIT_DONE    = 2 ; // adapter activator called create_POA
174    private static final int STATE_RUN          = 3 ; // initialized and running
175    private static final int STATE_DESTROYING   = 4 ; // being destroyed
176    private static final int STATE_DESTROYED    = 5 ; // destruction complete
177
178    private String stateToString()
179    {
180        switch (state) {
181            case STATE_START :
182                return "START" ;
183            case STATE_INIT :
184                return "INIT" ;
185            case STATE_INIT_DONE :
186                return "INIT_DONE" ;
187            case STATE_RUN :
188                return "RUN" ;
189            case STATE_DESTROYING :
190                return "DESTROYING" ;
191            case STATE_DESTROYED :
192                return "DESTROYED" ;
193            default :
194                return "UNKNOWN(" + state + ")" ;
195        }
196    }
197
198    // Current state of the POA
199    private int state ;
200
201    // The POA request handler that performs all policy specific operations
202    // Note that POAImpl handles all synchronization, so mediator is (mostly)
203    // unsynchronized.
204    private POAPolicyMediator mediator;
205
206    // Representation of object adapter ID
207    private int numLevels;          // counts depth of tree.  Root = 1.
208    private ObjectAdapterId poaId ; // the actual object adapter ID for this POA
209    private String name;            // the name of this POA
210
211    private POAManagerImpl manager; // This POA's POAManager
212    private int uniquePOAId ;       // ID for this POA that is unique relative
213                                    // to the POAFactory, which has the same
214                                    // lifetime as the ORB.
215    private POAImpl parent;         // The POA that created this POA.
216    private Map children;           // Map from name to POA of POAs created by
217                                    // this POA.
218
219    private AdapterActivator activator;
220    private int invocationCount ; // pending invocations on this POA.
221
222    // Data used to control POA concurrency
223    // XXX revisit for JSR 166
224
225    // Master lock for all POA synchronization.  See lock and unlock.
226    // package private for access by AOMEntry.
227    Sync poaMutex ;
228
229    // Wait on this CV for AdapterActivator upcalls to complete
230    private CondVar adapterActivatorCV ;
231
232    // Wait on this CV for all active invocations to complete
233    private CondVar invokeCV ;
234
235    // Wait on this CV for the destroy method to complete doing its work
236    private CondVar beingDestroyedCV ;
237
238    // thread local variable to store a boolean to detect deadlock in
239    // POA.destroy().
240    protected ThreadLocal isDestroying ;
241
242    // This includes the most important information for debugging
243    // POA problems.
244    public String toString()
245    {
246        return "POA[" + poaId.toString() +
247            ", uniquePOAId=" + uniquePOAId +
248            ", state=" + stateToString() +
249            ", invocationCount=" + invocationCount + "]" ;
250    }
251
252    // package private for mediator implementations.
253    boolean getDebug()
254    {
255        return debug ;
256    }
257
258    // package private for access to servant to POA map
259    static POAFactory getPOAFactory( ORB orb )
260    {
261        return (POAFactory)orb.getRequestDispatcherRegistry().
262            getObjectAdapterFactory( ORBConstants.TRANSIENT_SCID ) ;
263    }
264
265    // package private so that POAFactory can access it.
266    static POAImpl makeRootPOA( ORB orb )
267    {
268        POAManagerImpl poaManager = new POAManagerImpl( getPOAFactory( orb ),
269            orb.getPIHandler() ) ;
270
271        POAImpl result = new POAImpl( ORBConstants.ROOT_POA_NAME,
272            null, orb, STATE_START ) ;
273        result.initialize( poaManager, Policies.rootPOAPolicies ) ;
274
275        return result ;
276    }
277
278    // package private so that POAPolicyMediatorBase can access it.
279    int getPOAId()
280    {
281        return uniquePOAId ;
282    }
283
284
285    // package private so that POAPolicyMediator can access it.
286    void lock()
287    {
288        SyncUtil.acquire( poaMutex ) ;
289
290        if (debug) {
291            ORBUtility.dprint( this, "LOCKED poa " + this ) ;
292        }
293    }
294
295    // package private so that POAPolicyMediator can access it.
296    void unlock()
297    {
298        if (debug) {
299            ORBUtility.dprint( this, "UNLOCKED poa " + this ) ;
300        }
301
302        poaMutex.release() ;
303    }
304
305    // package private so that DelegateImpl can access it.
306    Policies getPolicies()
307    {
308        return mediator.getPolicies() ;
309    }
310
311    // Note that the parent POA must be locked when this constructor is called.
312    private POAImpl( String name, POAImpl parent, ORB orb, int initialState )
313    {
314        super( orb ) ;
315
316        debug = orb.poaDebugFlag ;
317
318        if (debug) {
319            ORBUtility.dprint( this, "Creating POA with name=" + name +
320                " parent=" + parent ) ;
321        }
322
323        this.state     = initialState ;
324        this.name      = name ;
325        this.parent    = parent;
326        children = new HashMap();
327        activator = null ;
328
329        // This was done in initialize, but I moved it here
330        // to get better searchability when tracing.
331        uniquePOAId = getPOAFactory( orb ).newPOAId() ;
332
333        if (parent == null) {
334            // This is the root POA, which counts as 1 level
335            numLevels = 1 ;
336        } else {
337            // My level is one more than that of my parent
338            numLevels = parent.numLevels + 1 ;
339
340            parent.children.put(name, this);
341        }
342
343        // Get an array of all of the POA names in order to
344        // create the poaid.
345        String[] names = new String[ numLevels ] ;
346        POAImpl poaImpl = this ;
347        int ctr = numLevels - 1 ;
348        while (poaImpl != null) {
349            names[ctr--] = poaImpl.name ;
350            poaImpl = poaImpl.parent ;
351        }
352
353        poaId = new ObjectAdapterIdArray( names ) ;
354
355        invocationCount = 0;
356
357        poaMutex = new ReentrantMutex( orb.poaConcurrencyDebugFlag ) ;
358
359        adapterActivatorCV = new CondVar( poaMutex,
360            orb.poaConcurrencyDebugFlag ) ;
361        invokeCV           = new CondVar( poaMutex,
362            orb.poaConcurrencyDebugFlag ) ;
363        beingDestroyedCV   = new CondVar( poaMutex,
364            orb.poaConcurrencyDebugFlag ) ;
365
366        isDestroying = new ThreadLocal () {
367            protected java.lang.Object initialValue() {
368                return Boolean.FALSE;
369            }
370        };
371    }
372
373    // The POA lock must be held when this method is called.
374    private void initialize( POAManagerImpl manager, Policies policies )
375    {
376        if (debug) {
377            ORBUtility.dprint( this, "Initializing poa " + this +
378                " with POAManager=" + manager + " policies=" + policies ) ;
379        }
380
381        this.manager = manager;
382        manager.addPOA(this);
383
384        mediator = POAPolicyMediatorFactory.create( policies, this ) ;
385
386        // Construct the object key template
387        int serverid = mediator.getServerId() ;
388        int scid = mediator.getScid() ;
389        String orbId = getORB().getORBData().getORBId();
390
391        ObjectKeyTemplate oktemp = new POAObjectKeyTemplate( getORB(),
392            scid, serverid, orbId, poaId ) ;
393
394        if (debug) {
395            ORBUtility.dprint( this, "Initializing poa: oktemp=" + oktemp ) ;
396        }
397
398        // Note that parent == null iff this is the root POA.
399        // This was used to avoid executing interceptors on the RootPOA.
400        // That is no longer necessary.
401        boolean objectAdapterCreated = true; // parent != null ;
402
403        // XXX extract codebase from policies and pass into initializeTemplate
404        // after the codebase policy change is finalized.
405        initializeTemplate( oktemp, objectAdapterCreated,
406                            policies,
407                            null, // codebase
408                            null, // manager id
409                            oktemp.getObjectAdapterId()
410                            ) ;
411
412        if (state == STATE_START)
413            state = STATE_RUN ;
414        else if (state == STATE_INIT)
415            state = STATE_INIT_DONE ;
416        else
417            throw lifecycleWrapper().illegalPoaStateTrans() ;
418    }
419
420    // The poaMutex must be held when this method is called
421    private boolean waitUntilRunning()
422    {
423        if (debug) {
424            ORBUtility.dprint( this,
425                "Calling waitUntilRunning on poa " + this ) ;
426        }
427
428        while (state < STATE_RUN) {
429            try {
430                adapterActivatorCV.await() ;
431            } catch (InterruptedException exc) {
432                // NO-OP
433            }
434        }
435
436        if (debug) {
437            ORBUtility.dprint( this,
438                "Exiting waitUntilRunning on poa " + this ) ;
439        }
440
441        // Note that a POA could be destroyed while in STATE_INIT due to a
442        // failure in the AdapterActivator upcall.
443        return (state == STATE_RUN) ;
444    }
445
446    // This method checks that the AdapterActivator finished the
447    // initialization of a POA activated in find_POA.  This is
448    // determined by checking the state of the POA.  If the state is
449    // STATE_INIT, the AdapterActivator did not complete the
450    // inialization.  In this case, we destroy the POA that was
451    // partially created and return false.  Otherwise, we return true.
452    // In any case, we must wake up all threads waiting for the adapter
453    // activator, either to continue their invocations, or to return
454    // errors to their client.
455    //
456    // The poaMutex must NOT be held when this method is called.
457    private boolean destroyIfNotInitDone()
458    {
459        try {
460            lock() ;
461
462            if (debug) {
463                ORBUtility.dprint( this,
464                    "Calling destroyIfNotInitDone on poa " + this ) ;
465            }
466
467            boolean success = (state == STATE_INIT_DONE) ;
468
469            if (success)
470                state = STATE_RUN ;
471            else {
472                // Don't just use destroy, because the check for
473                // deadlock is too general, and can prevent this from
474                // functioning properly.
475                DestroyThread destroyer = new DestroyThread( false, debug );
476                destroyer.doIt( this, true ) ;
477            }
478
479            return success ;
480        } finally {
481            adapterActivatorCV.broadcast() ;
482
483            if (debug) {
484                ORBUtility.dprint( this,
485                    "Exiting destroyIfNotInitDone on poa " + this ) ;
486            }
487
488            unlock() ;
489        }
490    }
491
492    private byte[] internalReferenceToId(
493        org.omg.CORBA.Object reference ) throws WrongAdapter
494    {
495        IOR ior = ORBUtility.getIOR( reference ) ;
496        IORTemplateList thisTemplate = ior.getIORTemplates() ;
497
498        ObjectReferenceFactory orf = getCurrentFactory() ;
499        IORTemplateList poaTemplate =
500            IORFactories.getIORTemplateList( orf ) ;
501
502        if (!poaTemplate.isEquivalent( thisTemplate ))
503            throw new WrongAdapter();
504
505        // Extract the ObjectId from the first TaggedProfile in the IOR.
506        // If ior was created in this POA, the same ID was used for
507        // every profile through the profile templates in the currentFactory,
508        // so we will get the same result from any profile.
509        Iterator iter = ior.iterator() ;
510        if (!iter.hasNext())
511            throw iorWrapper().noProfilesInIor() ;
512        TaggedProfile prof = (TaggedProfile)(iter.next()) ;
513        ObjectId oid = prof.getObjectId() ;
514
515        return oid.getId();
516    }
517
518    // Converted from anonymous class to local class
519    // so that we can call performDestroy() directly.
520    static class DestroyThread extends ManagedLocalsThread {
521        private boolean wait ;
522        private boolean etherealize ;
523        private boolean debug ;
524        private POAImpl thePoa ;
525
526        public DestroyThread( boolean etherealize, boolean debug )
527        {
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