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