/* * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package com.sun.corba.se.impl.oa.poa; import java.util.Collection ; import java.util.Set ; import java.util.HashSet ; import java.util.Map ; import java.util.HashMap ; import java.util.Iterator ; import org.omg.CORBA.Policy ; import org.omg.CORBA.SystemException ; import org.omg.PortableServer.POA ; import org.omg.PortableServer.Servant ; import org.omg.PortableServer.POAManager ; import org.omg.PortableServer.AdapterActivator ; import org.omg.PortableServer.ServantManager ; import org.omg.PortableServer.ForwardRequest ; import org.omg.PortableServer.ThreadPolicy; import org.omg.PortableServer.LifespanPolicy; import org.omg.PortableServer.IdUniquenessPolicy; import org.omg.PortableServer.IdAssignmentPolicy; import org.omg.PortableServer.ImplicitActivationPolicy; import org.omg.PortableServer.ServantRetentionPolicy; import org.omg.PortableServer.RequestProcessingPolicy; import org.omg.PortableServer.ThreadPolicyValue ; import org.omg.PortableServer.LifespanPolicyValue ; import org.omg.PortableServer.IdUniquenessPolicyValue ; import org.omg.PortableServer.IdAssignmentPolicyValue ; import org.omg.PortableServer.ImplicitActivationPolicyValue ; import org.omg.PortableServer.ServantRetentionPolicyValue ; import org.omg.PortableServer.RequestProcessingPolicyValue ; import org.omg.PortableServer.POAPackage.AdapterAlreadyExists ; import org.omg.PortableServer.POAPackage.AdapterNonExistent ; import org.omg.PortableServer.POAPackage.InvalidPolicy ; import org.omg.PortableServer.POAPackage.WrongPolicy ; import org.omg.PortableServer.POAPackage.WrongAdapter ; import org.omg.PortableServer.POAPackage.NoServant ; import org.omg.PortableServer.POAPackage.ServantAlreadyActive ; import org.omg.PortableServer.POAPackage.ObjectAlreadyActive ; import org.omg.PortableServer.POAPackage.ServantNotActive ; import org.omg.PortableServer.POAPackage.ObjectNotActive ; import org.omg.PortableInterceptor.ObjectReferenceFactory ; import org.omg.PortableInterceptor.ObjectReferenceTemplate ; import org.omg.PortableInterceptor.NON_EXISTENT ; import org.omg.IOP.TAG_INTERNET_IOP ; import com.sun.corba.se.spi.copyobject.CopierManager ; import com.sun.corba.se.spi.copyobject.ObjectCopier ; import com.sun.corba.se.spi.copyobject.ObjectCopierFactory ; import com.sun.corba.se.spi.oa.OADestroyed ; import com.sun.corba.se.spi.oa.OAInvocationInfo ; import com.sun.corba.se.spi.oa.ObjectAdapter ; import com.sun.corba.se.spi.oa.ObjectAdapterBase ; import com.sun.corba.se.spi.oa.ObjectAdapterFactory ; import com.sun.corba.se.spi.ior.ObjectKeyTemplate ; import com.sun.corba.se.spi.ior.ObjectId ; import com.sun.corba.se.spi.ior.ObjectAdapterId ; import com.sun.corba.se.spi.ior.IOR ; import com.sun.corba.se.spi.ior.IORFactories ; import com.sun.corba.se.spi.ior.IORTemplate ; import com.sun.corba.se.spi.ior.IORTemplateList ; import com.sun.corba.se.spi.ior.TaggedProfile ; import com.sun.corba.se.spi.ior.iiop.IIOPProfile ; import com.sun.corba.se.spi.ior.iiop.IIOPAddress ; import com.sun.corba.se.spi.ior.iiop.IIOPFactories ; import com.sun.corba.se.spi.orb.ORB ; import com.sun.corba.se.spi.protocol.ForwardException ; import com.sun.corba.se.spi.transport.SocketOrChannelAcceptor; import com.sun.corba.se.impl.ior.POAObjectKeyTemplate ; import com.sun.corba.se.impl.ior.ObjectAdapterIdArray ; import com.sun.corba.se.impl.orbutil.ORBUtility; import com.sun.corba.se.impl.orbutil.ORBConstants; import com.sun.corba.se.impl.orbutil.concurrent.Sync ; import com.sun.corba.se.impl.orbutil.concurrent.SyncUtil ; import com.sun.corba.se.impl.orbutil.concurrent.ReentrantMutex ; import com.sun.corba.se.impl.orbutil.concurrent.CondVar ; /** * POAImpl is the implementation of the Portable Object Adapter. It * contains an implementation of the POA interfaces specified in * COBRA 2.3.1 chapter 11 (formal/99-10-07). This implementation * is moving to comply with CORBA 3.0 due to the many clarifications * that have been made to the POA semantics since CORBA 2.3.1. * Specific comments have been added where 3.0 applies, but note that * we do not have the new 3.0 APIs yet. */ public class POAImpl extends ObjectAdapterBase implements POA { private boolean debug ; /* POA creation takes place in 2 stages: first, the POAImpl constructor is called, then the initialize method is called. This separation is needed because an AdapterActivator does not know the POAManager or the policies when the unknown_adapter method is invoked. However, the POA must be created before the unknown_adapter method is invoked, so that the parent knows when concurrent attempts are made to create the same POA. Calling the POAImpl constructor results in a new POA in state STATE_START. Calling initialize( POAManager, Policies ) results in state STATE_RUN. Calling destroy results in STATE_DESTROY, which marks the beginning of POA destruction. */ // Notes on concurrency. // The POA requires careful design for concurrency management to correctly // implement the specification and avoid deadlocks. The order of acquiring // locks must respect the following locking hierarchy: // // 1. Lock POAs before POAManagers // 2. Lock a POA before locking its child POA // // Also note that there are 3 separate conditions on which threads may wait // in the POA, as defined by invokeCV, beingDestroyedCV, and // adapterActivatorCV. This means that (for this reason as well as others) // we cannot simply use the standard Java synchronized primitive. // This implementation uses a modified version of Doug Lea's // util.concurrent (version 1.3.0) that supports reentrant // mutexes to handle the locking. This will all be replaced by the new JSR // 166 concurrency primitives in J2SE 1.5 and later once the ORB moves to // J2SE 1.5. // POA state constants // // Note that ordering is important here: we must have the state defined in // this order so that ordered comparison is possible. // DO NOT CHANGE THE VALUES OF THE STATE CONSTANTS!!! In particular, the // initialization related states must be lower than STATE_RUN. // // POA is created in STATE_START // // Valid state transitions: // // START to INIT after find_POA constructor call // START to RUN after initialize completes // INIT to INIT_DONE after initialize completes // INIT to DESTROYED after failed unknown_adapter // INIT_DONE to RUN after successful unknown_adapter // STATE_RUN to STATE_DESTROYING after start of destruction // STATE_DESTROYING to STATE_DESTROYED after destruction completes. private static final int STATE_START = 0 ; // constructor complete private static final int STATE_INIT = 1 ; // waiting for adapter activator private static final int STATE_INIT_DONE = 2 ; // adapter activator called create_POA private static final int STATE_RUN = 3 ; // initialized and running private static final int STATE_DESTROYING = 4 ; // being destroyed private static final int STATE_DESTROYED = 5 ; // destruction complete private String stateToString() { switch (state) { case STATE_START : return "START" ; case STATE_INIT : return "INIT" ; case STATE_INIT_DONE : return "INIT_DONE" ; case STATE_RUN : return "RUN" ; case STATE_DESTROYING : return "DESTROYING" ; case STATE_DESTROYED : return "DESTROYED" ; default : return "UNKNOWN(" + state + ")" ; } } // Current state of the POA private int state ; // The POA request handler that performs all policy specific operations // Note that POAImpl handles all synchronization, so mediator is (mostly) // unsynchronized. private POAPolicyMediator mediator; // Representation of object adapter ID private int numLevels; // counts depth of tree. Root = 1. private ObjectAdapterId poaId ; // the actual object adapter ID for this POA private String name; // the name of this POA private POAManagerImpl manager; // This POA's POAManager private int uniquePOAId ; // ID for this POA that is unique relative // to the POAFactory, which has the same // lifetime as the ORB. private POAImpl parent; // The POA that created this POA. private Map children; // Map from name to POA of POAs created by // this POA. private AdapterActivator activator; private int invocationCount ; // pending invocations on this POA. // Data used to control POA concurrency // XXX revisit for JSR 166 // Master lock for all POA synchronization. See lock and unlock. // package private for access by AOMEntry. Sync poaMutex ; // Wait on this CV for AdapterActivator upcalls to complete private CondVar adapterActivatorCV ; // Wait on this CV for all active invocations to complete private CondVar invokeCV ; // Wait on this CV for the destroy method to complete doing its work private CondVar beingDestroyedCV ; // thread local variable to store a boolean to detect deadlock in // POA.destroy(). protected ThreadLocal isDestroying ; // This includes the most important information for debugging // POA problems. public String toString() { return "POA[" + poaId.toString() + ", uniquePOAId=" + uniquePOAId + ", state=" + stateToString() + ", invocationCount=" + invocationCount + "]" ; } // package private for mediator implementations. boolean getDebug() { return debug ; } // package private for access to servant to POA map static POAFactory getPOAFactory( ORB orb ) { return (POAFactory)orb.getRequestDispatcherRegistry(). getObjectAdapterFactory( ORBConstants.TRANSIENT_SCID ) ; } // package private so that POAFactory can access it. static POAImpl makeRootPOA( ORB orb ) { POAManagerImpl poaManager = new POAManagerImpl( getPOAFactory( orb ), orb.getPIHandler() ) ; POAImpl result = new POAImpl( ORBConstants.ROOT_POA_NAME, null, orb, STATE_START ) ; result.initialize( poaManager, Policies.rootPOAPolicies ) ; return result ; } // package private so that POAPolicyMediatorBase can access it. int getPOAId() { return uniquePOAId ; } // package private so that POAPolicyMediator can access it. void lock() { SyncUtil.acquire( poaMutex ) ; if (debug) { ORBUtility.dprint( this, "LOCKED poa " + this ) ; } } // package private so that POAPolicyMediator can access it. void unlock() { if (debug) { ORBUtility.dprint( this, "UNLOCKED poa " + this ) ; } poaMutex.release() ; } // package private so that DelegateImpl can access it. Policies getPolicies() { return mediator.getPolicies() ; } // Note that the parent POA must be locked when this constructor is called. private POAImpl( String name, POAImpl parent, ORB orb, int initialState ) { super( orb ) ; debug = orb.poaDebugFlag ; if (debug) { ORBUtility.dprint( this, "Creating POA with name=" + name + " parent=" + parent ) ; } this.state = initialState ; this.name = name ; this.parent = parent; children = new HashMap(); activator = null ; // This was done in initialize, but I moved it here // to get better searchability when tracing. uniquePOAId = getPOAFactory( orb ).newPOAId() ; if (parent == null) { // This is the root POA, which counts as 1 level numLevels = 1 ; } else { // My level is one more than that of my parent numLevels = parent.numLevels + 1 ; parent.children.put(name, this); } // Get an array of all of the POA names in order to // create the poaid. String[] names = new String[ numLevels ] ; POAImpl poaImpl = this ; int ctr = numLevels - 1 ; while (poaImpl != null) { names[ctr--] = poaImpl.name ; poaImpl = poaImpl.parent ; } poaId = new ObjectAdapterIdArray( names ) ; invocationCount = 0; poaMutex = new ReentrantMutex( orb.poaConcurrencyDebugFlag ) ; adapterActivatorCV = new CondVar( poaMutex, orb.poaConcurrencyDebugFlag ) ; invokeCV = new CondVar( poaMutex, orb.poaConcurrencyDebugFlag ) ; beingDestroyedCV = new CondVar( poaMutex, orb.poaConcurrencyDebugFlag ) ; isDestroying = new ThreadLocal () { protected java.lang.Object initialValue() { return Boolean.FALSE; } }; } // The POA lock must be held when this method is called. private void initialize( POAManagerImpl manager, Policies policies ) { if (debug) { ORBUtility.dprint( this, "Initializing poa " + this + " with POAManager=" + manager + " policies=" + policies ) ; } this.manager = manager; manager.addPOA(this); mediator = POAPolicyMediatorFactory.create( policies, this ) ; // Construct the object key template int serverid = mediator.getServerId() ; int scid = mediator.getScid() ; String orbId = getORB().getORBData().getORBId(); ObjectKeyTemplate oktemp = new POAObjectKeyTemplate( getORB(), scid, serverid, orbId, poaId ) ; if (debug) { ORBUtility.dprint( this, "Initializing poa: oktemp=" + oktemp ) ; } // Note that parent == null iff this is the root POA. // This was used to avoid executing interceptors on the RootPOA. // That is no longer necessary. boolean objectAdapterCreated = true; // parent != null ; // XXX extract codebase from policies and pass into initializeTemplate // after the codebase policy change is finalized. initializeTemplate( oktemp, objectAdapterCreated, policies, null, // codebase null, // manager id oktemp.getObjectAdapterId() ) ; if (state == STATE_START) state = STATE_RUN ; else if (state == STATE_INIT) state = STATE_INIT_DONE ; else throw lifecycleWrapper().illegalPoaStateTrans() ; } // The poaMutex must be held when this method is called private boolean waitUntilRunning() { if (debug) { ORBUtility.dprint( this, "Calling waitUntilRunning on poa " + this ) ; } while (state < STATE_RUN) { try { adapterActivatorCV.await() ; } catch (InterruptedException exc) { // NO-OP } } if (debug) { ORBUtility.dprint( this, "Exiting waitUntilRunning on poa " + this ) ; } // Note that a POA could be destroyed while in STATE_INIT due to a // failure in the AdapterActivator upcall. return (state == STATE_RUN) ; } // This method checks that the AdapterActivator finished the // initialization of a POA activated in find_POA. This is // determined by checking the state of the POA. If the state is // STATE_INIT, the AdapterActivator did not complete the // inialization. In this case, we destroy the POA that was // partially created and return false. Otherwise, we return true. // In any case, we must wake up all threads waiting for the adapter // activator, either to continue their invocations, or to return // errors to their client. // // The poaMutex must NOT be held when this method is called. private boolean destroyIfNotInitDone() { try { lock() ; if (debug) { ORBUtility.dprint( this, "Calling destroyIfNotInitDone on poa " + this ) ; } boolean success = (state == STATE_INIT_DONE) ; if (success) state = STATE_RUN ; else { // Don't just use destroy, because the check for // deadlock is too general, and can prevent this from // functioning properly. DestroyThread destroyer = new DestroyThread( false, debug ); destroyer.doIt( this, true ) ; } return success ; } finally { adapterActivatorCV.broadcast() ; if (debug) { ORBUtility.dprint( this, "Exiting destroyIfNotInitDone on poa " + this ) ; } unlock() ; } } private byte[] internalReferenceToId( org.omg.CORBA.Object reference ) throws WrongAdapter { IOR ior = ORBUtility.getIOR( reference ) ; IORTemplateList thisTemplate = ior.getIORTemplates() ; ObjectReferenceFactory orf = getCurrentFactory() ; IORTemplateList poaTemplate = IORFactories.getIORTemplateList( orf ) ; if (!poaTemplate.isEquivalent( thisTemplate )) throw new WrongAdapter(); // Extract the ObjectId from the first TaggedProfile in the IOR. // If ior was created in this POA, the same ID was used for // every profile through the profile templates in the currentFactory, // so we will get the same result from any profile. Iterator iter = ior.iterator() ; if (!iter.hasNext()) throw iorWrapper().noProfilesInIor() ; TaggedProfile prof = (TaggedProfile)(iter.next()) ; ObjectId oid = prof.getObjectId() ; return oid.getId(); } // Converted from anonymous class to local class // so that we can call performDestroy() directly. static class DestroyThread extends Thread { private boolean wait ; private boolean etherealize ; private boolean debug ; private POAImpl thePoa ; public DestroyThread( boolean etherealize, boolean debug ) { super(null, null, "POA-Destroy-Thread", 0, false); this.etherealize = etherealize ; this.debug = debug ; } public void doIt( POAImpl thePoa, boolean wait ) { if (debug) { ORBUtility.dprint( this, "Calling DestroyThread.doIt(thePOA=" + thePoa + " wait=" + wait + " etherealize=" + etherealize ) ; } this.thePoa = thePoa ; this.wait = wait ; if (wait) { run() ; } else { // Catch exceptions since setDaemon can cause a // security exception to be thrown under netscape // in the Applet mode try { setDaemon(true); } catch (Exception e) {} start() ; } } public void run() { Set destroyedPOATemplates = new HashSet() ; performDestroy( thePoa, destroyedPOATemplates ); Iterator iter = destroyedPOATemplates.iterator() ; ObjectReferenceTemplate[] orts = new ObjectReferenceTemplate[ destroyedPOATemplates.size() ] ; int index = 0 ; while (iter.hasNext()) orts[ index++ ] = (ObjectReferenceTemplate)iter.next(); thePoa.getORB().getPIHandler().adapterStateChanged( orts, NON_EXISTENT.value ) ; } // Returns true if destruction must be completed, false // if not, which means that another thread is already // destroying poa. private boolean prepareForDestruction( POAImpl poa, Set destroyedPOATemplates ) { POAImpl[] childPoas = null ; // Note that we do not synchronize on this, since this is // the PerformDestroy instance, not the POA. try { poa.lock() ; if (debug) { ORBUtility.dprint( this, "Calling performDestroy on poa " + poa ) ; } if (poa.state <= STATE_RUN) { poa.state = STATE_DESTROYING ; } else { // destroy may be called multiple times, and each call // is allowed to proceed with its own setting of the wait // flag, but the etherealize value is used from the first // call to destroy. Also all children should be destroyed // before the parent POA. If the poa is already destroyed, // we can just return. If the poa has started destruction, // but not completed, and wait is true, we need to wait // until destruction is complete, then just return. if (wait) while (poa.state != STATE_DESTROYED) { try { poa.beingDestroyedCV.await() ; } catch (InterruptedException exc) { // NO-OP } } return false ; } poa.isDestroying.set(Boolean.TRUE); // Make a copy since we can't hold the lock while destroying // the children, and an iterator is not deletion-safe. childPoas = (POAImpl[])poa.children.values().toArray( new POAImpl[0] ); } finally { poa.unlock() ; } // We are not holding the POA mutex here to avoid holding it // while destroying the POA's children, since this may involve // upcalls to etherealize methods. for (int ctr=0; ctrcreate_POA * Section 3.3.8.2 */ public POA create_POA(String name, POAManager theManager, Policy[] policies) throws AdapterAlreadyExists, InvalidPolicy { try { lock() ; if (debug) { ORBUtility.dprint( this, "Calling create_POA(name=" + name + " theManager=" + theManager + " policies=" + policies + ") on poa " + this ) ; } // We cannot create children of a POA that is (being) destroyed. // This has been added to the CORBA 3.0 spec. if (state > STATE_RUN) throw omgLifecycleWrapper().createPoaDestroy() ; POAImpl poa = (POAImpl)(children.get(name)) ; if (poa == null) { poa = new POAImpl( name, this, getORB(), STATE_START ) ; } try { poa.lock() ; if (debug) { ORBUtility.dprint( this, "Calling create_POA: new poa is " + poa ) ; } if ((poa.state != STATE_START) && (poa.state != STATE_INIT)) throw new AdapterAlreadyExists(); POAManagerImpl newManager = (POAManagerImpl)theManager ; if (newManager == null) newManager = new POAManagerImpl( manager.getFactory(), manager.getPIHandler() ); int defaultCopierId = getORB().getCopierManager().getDefaultId() ; Policies POAPolicies = new Policies( policies, defaultCopierId ) ; poa.initialize( newManager, POAPolicies ) ; return poa; } finally { poa.unlock() ; } } finally { unlock() ; } } /** * find_POA * Section 3.3.8.3 */ public POA find_POA(String name, boolean activate) throws AdapterNonExistent { POAImpl found = null ; AdapterActivator act = null ; lock() ; if (debug) { ORBUtility.dprint( this, "Calling find_POA(name=" + name + " activate=" + activate + ") on poa " + this ) ; } found = (POAImpl) children.get(name); if (found != null) { if (debug) { ORBUtility.dprint( this, "Calling find_POA: found poa " + found ) ; } try { found.lock() ; // Do not hold the parent POA lock while // waiting for child to complete initialization. unlock() ; // Make sure that the child has completed its initialization, // if it was created by an AdapterActivator, otherwise throw // a standard TRANSIENT exception with minor code 4 (see // CORBA 3.0 11.3.9.3, in reference to unknown_adapter) if (!found.waitUntilRunning()) throw omgLifecycleWrapper().poaDestroyed() ; // Note that found may be in state DESTROYING or DESTROYED at // this point. That's OK, since destruction could start at // any time. } finally { found.unlock() ; } } else { try { if (debug) { ORBUtility.dprint( this, "Calling find_POA: no poa found" ) ; } if (activate && (activator != null)) { // Create a child, but don't initialize it. The newly // created POA will be in state STATE_START, which will // cause other calls to find_POA that are creating the same // POA to block on the waitUntilRunning call above. // Initialization must be completed by a call to create_POA // inside the unknown_adapter upcall. Note that // this.poaMutex must be held here so that this.children // can be safely updated. The state is set to STATE_INIT // so that initialize can make the correct state transition // when create_POA is called inside the AdapterActivator. // This avoids activating the new POA too soon // by transitioning to STATE_RUN after unknown_adapter // returns. found = new POAImpl( name, this, getORB(), STATE_INIT ) ; if (debug) { ORBUtility.dprint( this, "Calling find_POA: created poa " + found ) ; } act = activator ; } else { throw new AdapterNonExistent(); } } finally { unlock() ; } } // assert (found != null) // assert not holding this.poaMutex OR found.poaMutex // We must not hold either this.poaMutex or found.poaMutex here while // waiting for intialization of found to complete to prevent possible // deadlocks. if (act != null) { boolean status = false ; boolean adapterResult = false ; if (debug) { ORBUtility.dprint( this, "Calling find_POA: calling AdapterActivator" ) ; } try { // Prevent more than one thread at a time from executing in act // in case act is shared between multiple POAs. synchronized (act) { status = act.unknown_adapter(this, name); } } catch (SystemException exc) { throw omgLifecycleWrapper().adapterActivatorException( exc, name, poaId.toString() ) ; } catch (Throwable thr) { // ignore most non-system exceptions, but log them for // diagnostic purposes. lifecycleWrapper().unexpectedException( thr, this.toString() ) ; if (thr instanceof ThreadDeath) throw (ThreadDeath)thr ; } finally { // At this point, we have completed adapter activation. // Whether this was successful or not, we must call // destroyIfNotInitDone so that calls to enter() and create_POA() // that are waiting can execute again. Failing to do this // will cause the system to hang in complex tests. adapterResult = found.destroyIfNotInitDone() ; } if (status) { if (!adapterResult) throw omgLifecycleWrapper().adapterActivatorException( name, poaId.toString() ) ; } else { if (debug) { ORBUtility.dprint( this, "Calling find_POA: AdapterActivator returned false" ) ; } // OMG Issue 3740 is resolved to throw AdapterNonExistent if // unknown_adapter() returns false. throw new AdapterNonExistent(); } } return found; } /** * destroy * Section 3.3.8.4 */ public void destroy(boolean etherealize, boolean wait_for_completion) { // This is to avoid deadlock if (wait_for_completion && getORB().isDuringDispatch()) { throw lifecycleWrapper().destroyDeadlock() ; } DestroyThread destroyer = new DestroyThread( etherealize, debug ); destroyer.doIt( this, wait_for_completion ) ; } /** * create_thread_policy * Section 3.3.8.5 */ public ThreadPolicy create_thread_policy( ThreadPolicyValue value) { return new ThreadPolicyImpl(value); } /** * create_lifespan_policy * Section 3.3.8.5 */ public LifespanPolicy create_lifespan_policy( LifespanPolicyValue value) { return new LifespanPolicyImpl(value); } /** * create_id_uniqueness_policy * Section 3.3.8.5 */ public IdUniquenessPolicy create_id_uniqueness_policy( IdUniquenessPolicyValue value) { return new IdUniquenessPolicyImpl(value); } /** * create_id_assignment_policy * Section 3.3.8.5 */ public IdAssignmentPolicy create_id_assignment_policy( IdAssignmentPolicyValue value) { return new IdAssignmentPolicyImpl(value); } /** * create_implicit_activation_policy * Section 3.3.8.5 */ public ImplicitActivationPolicy create_implicit_activation_policy( ImplicitActivationPolicyValue value) { return new ImplicitActivationPolicyImpl(value); } /** * create_servant_retention_policy * Section 3.3.8.5 */ public ServantRetentionPolicy create_servant_retention_policy( ServantRetentionPolicyValue value) { return new ServantRetentionPolicyImpl(value); } /** * create_request_processing_policy * Section 3.3.8.5 */ public RequestProcessingPolicy create_request_processing_policy( RequestProcessingPolicyValue value) { return new RequestProcessingPolicyImpl(value); } /** * the_name * Section 3.3.8.6 */ public String the_name() { try { lock() ; return name; } finally { unlock() ; } } /** * the_parent * Section 3.3.8.7 */ public POA the_parent() { try { lock() ; return parent; } finally { unlock() ; } } /** * the_children */ public org.omg.PortableServer.POA[] the_children() { try { lock() ; Collection coll = children.values() ; int size = coll.size() ; POA[] result = new POA[ size ] ; int index = 0 ; Iterator iter = coll.iterator() ; while (iter.hasNext()) { POA poa = (POA)(iter.next()) ; result[ index++ ] = poa ; } return result ; } finally { unlock() ; } } /** * the_POAManager * Section 3.3.8.8 */ public POAManager the_POAManager() { try { lock() ; return manager; } finally { unlock() ; } } /** * the_activator * Section 3.3.8.9 */ public AdapterActivator the_activator() { try { lock() ; return activator; } finally { unlock() ; } } /** * the_activator * Section 3.3.8.9 */ public void the_activator(AdapterActivator activator) { try { lock() ; if (debug) { ORBUtility.dprint( this, "Calling the_activator on poa " + this + " activator=" + activator ) ; } this.activator = activator; } finally { unlock() ; } } /** * get_servant_manager * Section 3.3.8.10 */ public ServantManager get_servant_manager() throws WrongPolicy { try { lock() ; return mediator.getServantManager() ; } finally { unlock() ; } } /** * set_servant_manager * Section 3.3.8.10 */ public void set_servant_manager(ServantManager servantManager) throws WrongPolicy { try { lock() ; if (debug) { ORBUtility.dprint( this, "Calling set_servant_manager on poa " + this + " servantManager=" + servantManager ) ; } mediator.setServantManager( servantManager ) ; } finally { unlock() ; } } /** * get_servant * Section 3.3.8.12 */ public Servant get_servant() throws NoServant, WrongPolicy { try { lock() ; return mediator.getDefaultServant() ; } finally { unlock() ; } } /** * set_servant * Section 3.3.8.13 */ public void set_servant(Servant defaultServant) throws WrongPolicy { try { lock() ; if (debug) { ORBUtility.dprint( this, "Calling set_servant on poa " + this + " defaultServant=" + defaultServant ) ; } mediator.setDefaultServant( defaultServant ) ; } finally { unlock() ; } } /** * activate_object * Section 3.3.8.14 */ public byte[] activate_object(Servant servant) throws ServantAlreadyActive, WrongPolicy { try { lock() ; if (debug) { ORBUtility.dprint( this, "Calling activate_object on poa " + this + " (servant=" + servant + ")" ) ; } // Allocate a new system-generated object-id. // This will throw WrongPolicy if not SYSTEM_ID // policy. byte[] id = mediator.newSystemId(); try { mediator.activateObject( id, servant ) ; } catch (ObjectAlreadyActive oaa) { // This exception can not occur in this case, // since id is always brand new. // } return id ; } finally { if (debug) { ORBUtility.dprint( this, "Exiting activate_object on poa " + this ) ; } unlock() ; } } /** * activate_object_with_id * Section 3.3.8.15 */ public void activate_object_with_id(byte[] id, Servant servant) throws ObjectAlreadyActive, ServantAlreadyActive, WrongPolicy { try { lock() ; if (debug) { ORBUtility.dprint( this, "Calling activate_object_with_id on poa " + this + " (servant=" + servant + " id=" + id + ")" ) ; } // Clone the id to avoid possible errors due to aliasing // (e.g. the client passes the id in and then changes it later). byte[] idClone = (byte[])(id.clone()) ; mediator.activateObject( idClone, servant ) ; } finally { if (debug) { ORBUtility.dprint( this, "Exiting activate_object_with_id on poa " + this ) ; } unlock() ; } } /** * deactivate_object * 3.3.8.16 */ public void deactivate_object(byte[] id) throws ObjectNotActive, WrongPolicy { try { lock() ; if (debug) { ORBUtility.dprint( this, "Calling deactivate_object on poa " + this + " (id=" + id + ")" ) ; } mediator.deactivateObject( id ) ; } finally { if (debug) { ORBUtility.dprint( this, "Exiting deactivate_object on poa " + this ) ; } unlock() ; } } /** * create_reference * 3.3.8.17 */ public org.omg.CORBA.Object create_reference(String repId) throws WrongPolicy { try { lock() ; if (debug) { ORBUtility.dprint( this, "Calling create_reference(repId=" + repId + ") on poa " + this ) ; } return makeObject( repId, mediator.newSystemId()) ; } finally { unlock() ; } } /** * create_reference_with_id * 3.3.8.18 */ public org.omg.CORBA.Object create_reference_with_id(byte[] oid, String repId) { try { lock() ; if (debug) { ORBUtility.dprint( this, "Calling create_reference_with_id(oid=" + oid + " repId=" + repId + ") on poa " + this ) ; } // Clone the id to avoid possible errors due to aliasing // (e.g. the client passes the id in and then changes it later). byte[] idClone = (byte[])(oid.clone()) ; return makeObject( repId, idClone ) ; } finally { unlock() ; } } /** * servant_to_id * 3.3.8.19 */ public byte[] servant_to_id(Servant servant) throws ServantNotActive, WrongPolicy { try { lock() ; if (debug) { ORBUtility.dprint( this, "Calling servant_to_id(servant=" + servant + ") on poa " + this ) ; } return mediator.servantToId( servant ) ; } finally { unlock() ; } } /** * servant_to_reference * 3.3.8.20 */ public org.omg.CORBA.Object servant_to_reference(Servant servant) throws ServantNotActive, WrongPolicy { try { lock() ; if (debug) { ORBUtility.dprint( this, "Calling servant_to_reference(servant=" + servant + ") on poa " + this ) ; } byte[] oid = mediator.servantToId(servant); String repId = servant._all_interfaces( this, oid )[0] ; return create_reference_with_id(oid, repId); } finally { unlock() ; } } /** * reference_to_servant * 3.3.8.21 */ public Servant reference_to_servant(org.omg.CORBA.Object reference) throws ObjectNotActive, WrongPolicy, WrongAdapter { try { lock() ; if (debug) { ORBUtility.dprint( this, "Calling reference_to_servant(reference=" + reference + ") on poa " + this ) ; } if ( state >= STATE_DESTROYING ) { throw lifecycleWrapper().adapterDestroyed() ; } // reference_to_id should throw WrongAdapter // if the objref was not created by this POA byte [] id = internalReferenceToId(reference); return mediator.idToServant( id ) ; } finally { unlock() ; } } /** * reference_to_id * 3.3.8.22 */ public byte[] reference_to_id(org.omg.CORBA.Object reference) throws WrongAdapter, WrongPolicy { try { lock() ; if (debug) { ORBUtility.dprint( this, "Calling reference_to_id(reference=" + reference + ") on poa " + this ) ; } if( state >= STATE_DESTROYING ) { throw lifecycleWrapper().adapterDestroyed() ; } return internalReferenceToId( reference ) ; } finally { unlock() ; } } /** * id_to_servant * 3.3.8.23 */ public Servant id_to_servant(byte[] id) throws ObjectNotActive, WrongPolicy { try { lock() ; if (debug) { ORBUtility.dprint( this, "Calling id_to_servant(id=" + id + ") on poa " + this ) ; } if( state >= STATE_DESTROYING ) { throw lifecycleWrapper().adapterDestroyed() ; } return mediator.idToServant( id ) ; } finally { unlock() ; } } /** * id_to_reference * 3.3.8.24 */ public org.omg.CORBA.Object id_to_reference(byte[] id) throws ObjectNotActive, WrongPolicy { try { lock() ; if (debug) { ORBUtility.dprint( this, "Calling id_to_reference(id=" + id + ") on poa " + this ) ; } if( state >= STATE_DESTROYING ) { throw lifecycleWrapper().adapterDestroyed() ; } Servant s = mediator.idToServant( id ) ; String repId = s._all_interfaces( this, id )[0] ; return makeObject(repId, id ); } finally { unlock() ; } } /** * id * 11.3.8.26 in ptc/00-08-06 */ public byte[] id() { try { lock() ; return getAdapterId() ; } finally { unlock() ; } } //*************************************************************** //Implementation of ObjectAdapter interface //*************************************************************** public Policy getEffectivePolicy( int type ) { return mediator.getPolicies().get_effective_policy( type ) ; } public int getManagerId() { return manager.getManagerId() ; } public short getState() { return manager.getORTState() ; } public String[] getInterfaces( java.lang.Object servant, byte[] objectId ) { Servant serv = (Servant)servant ; return serv._all_interfaces( this, objectId ) ; } protected ObjectCopierFactory getObjectCopierFactory() { int copierId = mediator.getPolicies().getCopierId() ; CopierManager cm = getORB().getCopierManager() ; return cm.getObjectCopierFactory( copierId ) ; } public void enter() throws OADestroyed { try { lock() ; if (debug) { ORBUtility.dprint( this, "Calling enter on poa " + this ) ; } // Avoid deadlock if this is the thread that is processing the // POA.destroy because this is the only thread that can notify // waiters on beingDestroyedCV. This can happen if an // etherealize upcall invokes a method on a colocated object // served by this POA. while ((state == STATE_DESTROYING) && (isDestroying.get() == Boolean.FALSE)) { try { beingDestroyedCV.await(); } catch (InterruptedException ex) { // NO-OP } } if (!waitUntilRunning()) throw new OADestroyed() ; invocationCount++; } finally { if (debug) { ORBUtility.dprint( this, "Exiting enter on poa " + this ) ; } unlock() ; } manager.enter(); } public void exit() { try { lock() ; if (debug) { ORBUtility.dprint( this, "Calling exit on poa " + this ) ; } invocationCount--; if ((invocationCount == 0) && (state == STATE_DESTROYING)) { invokeCV.broadcast(); } } finally { if (debug) { ORBUtility.dprint( this, "Exiting exit on poa " + this ) ; } unlock() ; } manager.exit(); } public void getInvocationServant( OAInvocationInfo info ) { try { lock() ; if (debug) { ORBUtility.dprint( this, "Calling getInvocationServant on poa " + this ) ; } java.lang.Object servant = null ; try { servant = mediator.getInvocationServant( info.id(), info.getOperation() ); } catch (ForwardRequest freq) { throw new ForwardException( getORB(), freq.forward_reference ) ; } info.setServant( servant ) ; } finally { if (debug) { ORBUtility.dprint( this, "Exiting getInvocationServant on poa " + this ) ; } unlock() ; } } public org.omg.CORBA.Object getLocalServant( byte[] objectId ) { return null ; } /** Called from the subcontract to let this POA cleanup after an * invocation. Note: If getServant was called, then returnServant * MUST be called, even in the case of exceptions. This may be * called multiple times for a single request. */ public void returnServant() { try { lock() ; if (debug) { ORBUtility.dprint( this, "Calling returnServant on poa " + this ) ; } mediator.returnServant(); } catch (Throwable thr) { if (debug) { ORBUtility.dprint( this, "Exception " + thr + " in returnServant on poa " + this ) ; } if (thr instanceof Error) throw (Error)thr ; else if (thr instanceof RuntimeException) throw (RuntimeException)thr ; } finally { if (debug) { ORBUtility.dprint( this, "Exiting returnServant on poa " + this ) ; } unlock() ; } } }