/* gnuAbstractPOA.java --
   Copyright (C) 2005 Free Software Foundation, Inc.

This file is part of GNU Classpath.

GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.

GNU Classpath 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 for more details.

You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING.  If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.

Linking this library statically or dynamically with other modules is
making a combined work based on this library.  Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.

As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module.  An independent module is a module which is not derived from
or based on this library.  If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so.  If you do not wish to do so, delete this
exception statement from your version. */


package gnu.CORBA.Poa;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;

import org.omg.CORBA.BAD_INV_ORDER;
import org.omg.CORBA.BAD_PARAM;
import org.omg.CORBA.CompletionStatus;
import org.omg.CORBA.LocalObject;
import org.omg.CORBA.NO_IMPLEMENT;
import org.omg.CORBA.OBJ_ADAPTER;
import org.omg.CORBA.ORB;
import org.omg.CORBA.Object;
import org.omg.CORBA.Policy;
import org.omg.CORBA.SetOverrideType;
import org.omg.CORBA.TRANSIENT;
import org.omg.CORBA.portable.ObjectImpl;
import org.omg.PortableInterceptor.NON_EXISTENT;
import org.omg.PortableInterceptor.ObjectReferenceFactory;
import org.omg.PortableInterceptor.ObjectReferenceTemplate;
import org.omg.PortableInterceptor.ObjectReferenceTemplateHelper;
import org.omg.PortableServer.AdapterActivator;
import org.omg.PortableServer.ForwardRequest;
import org.omg.PortableServer.IdAssignmentPolicy;
import org.omg.PortableServer.IdAssignmentPolicyValue;
import org.omg.PortableServer.IdUniquenessPolicy;
import org.omg.PortableServer.IdUniquenessPolicyValue;
import org.omg.PortableServer.ImplicitActivationPolicy;
import org.omg.PortableServer.ImplicitActivationPolicyValue;
import org.omg.PortableServer.LifespanPolicy;
import org.omg.PortableServer.LifespanPolicyValue;
import org.omg.PortableServer.POA;
import org.omg.PortableServer.POAManager;
import org.omg.PortableServer.RequestProcessingPolicy;
import org.omg.PortableServer.RequestProcessingPolicyValue;
import org.omg.PortableServer.SERVANT_RETENTION_POLICY_ID;
import org.omg.PortableServer.Servant;
import org.omg.PortableServer.ServantActivator;
import org.omg.PortableServer.ServantLocator;
import org.omg.PortableServer.ServantManager;
import org.omg.PortableServer.ServantRetentionPolicy;
import org.omg.PortableServer.ServantRetentionPolicyValue;
import org.omg.PortableServer.ThreadPolicy;
import org.omg.PortableServer.ThreadPolicyValue;
import org.omg.PortableServer.POAManagerPackage.State;
import org.omg.PortableServer.POAPackage.AdapterAlreadyExists;
import org.omg.PortableServer.POAPackage.AdapterNonExistent;
import org.omg.PortableServer.POAPackage.InvalidPolicy;
import org.omg.PortableServer.POAPackage.NoServant;
import org.omg.PortableServer.POAPackage.ObjectAlreadyActive;
import org.omg.PortableServer.POAPackage.ObjectNotActive;
import org.omg.PortableServer.POAPackage.ServantAlreadyActive;
import org.omg.PortableServer.POAPackage.ServantNotActive;
import org.omg.PortableServer.POAPackage.WrongAdapter;
import org.omg.PortableServer.POAPackage.WrongPolicy;

import gnu.CORBA.OrbFunctional;
import gnu.CORBA.CDR.BufferredCdrInput;
import gnu.CORBA.CDR.BufferedCdrOutput;

/**
 * Our POA implementation.
 *
 * @author Audrius Meskauskas, Lithuania (AudriusA@Bioinformatics.org)
 */
public class gnuPOA
  extends LocalObject
  implements POA, ObjectReferenceFactory
{
  /**
   * The object reference template, associated with this POA.
   * 
   * @since 1.5
   */
  class RefTemplate implements ObjectReferenceTemplate
  {
    /** 
     * Use serialVersionUID for interoperability. 
     */
    private static final long serialVersionUID = 1;
    
    RefTemplate()
    {
      // The adapter name is computed once.
      ArrayList names = new ArrayList();
      names.add(the_name());

      POA poa = the_parent();
      while (poa != null)
        {
          names.add(poa.the_name());
          poa = poa.the_parent();
        }

      // Fill in the string array in reverse (more natural) order,
      // root POA first.
      m_adapter_name = new String[names.size()];

      for (int i = 0; i < m_adapter_name.length; i++)
        m_adapter_name[i] = (String) names.get(m_adapter_name.length - i - 1);
    }
    
    /**
     * The adapter name
     */
    final String[] m_adapter_name;
    
    /**
     * Get the name of this POA.
     */
    public String[] adapter_name()
    {
      return (String[]) m_adapter_name.clone();
    }

    /**
     * Get the ORB id.
     */
    public String orb_id()
    {
      return m_orb.orb_id;
    }

    /**
     * Get the server id.
     */
    public String server_id()
    {
      return OrbFunctional.server_id;
    }

    /**
     * Create the object.
     */
    public Object make_object(String repositoryId, byte[] objectId)
    {
      return create_reference_with_id(objectId, repositoryId);
    }

    /**
     * Get the array of truncatible repository ids.
     */
    public String[] _truncatable_ids()
    {
      return ref_template_ids;
    }
  }
  
  /** 
   * Use serialVersionUID for interoperability. 
   */
  private static final long serialVersionUID = 1;
  
  /**
   * The adapter reference template.
   */
  ObjectReferenceTemplate refTemplate;
  
  /**
   * The reference template repository ids. Defined outside the class as it
   * cannot have static members.
   */
  final static String[] ref_template_ids = 
    new String[] { ObjectReferenceTemplateHelper.id() };
  
  /**
   * The active object map, mapping between object keys, objects and servants.
   */
  public final AOM aom = new AOM();

  /**
   * The children of this POA.
   */
  final ArrayList children = new ArrayList();

  /**
   * The name of this POA.
   */
  final String name;

  /**
   * The parent of this POA (null for the root POA).
   */
  final POA parent;

  /**
   * The ior key signature, indicating, that the ior key is encoded using
   * internal agreements of this implementation (0x'free').
   */
  static final int SIGNATURE = 0x66726565;

  /**
   * The adapter activator for this POA, null if no activator is set.
   */
  AdapterActivator m_activator;

  /**
   * The POA manager for this POA.
   */
  POAManager m_manager;

  /**
   * The servant manager (servant activator) for this POA.
   */
  ServantActivator servant_activator;

  /**
   * The servant manager (servant locator) for this POA.
   */
  ServantLocator servant_locator;

  /**
   * The default servant, if on is in use.
   */
  Servant default_servant;

  /**
   * The cached poa id value, computed once.
   */
  private byte[] m_poa_id;

  /**
   * The all policy values that apply to this POA.
   * The used policy values are singletons, unique between policies.
   */
  private final HashSet m_policies;

  /**
   * An array of the set policies.
   */
  Policy[] s_policies;

  /**
   * The ORB, where the POA is connected.
   */
  final ORB_1_4 m_orb;

  /**
   * When true, the POA is being destroyed or is destroyed.
   */
  boolean m_inDestruction;

  /**
   * True if the active object map is used by this POA.
   * The value is moved into separate boolean value due
   * necessity of the frequent checks.
   */
  public final boolean retain_servant;
  
  /**
   * The object reference factory, used to create the new object
   * references.
   */
  ObjectReferenceFactory m_object_factory = this;

  /**
   * Create a new abstract POA.
   *
   * @param a_parent the parent of this POA.
   * @param a_name a name for this POA.
   * @param a_manager a manager for this POA. If null, a new
   * {@link gnuPOAManager} will be instantiated.
   * @param a_policies an array of policies that apply to this POA.
   * @param an_orb an ORB for this POA.
   */
  public gnuPOA(gnuPOA a_parent, String a_name, POAManager a_manager,
                Policy[] a_policies, ORB_1_4 an_orb
               )
         throws InvalidPolicy
  {
    // Add default policies.
    Policy[] all_policies = StandardPolicies.withDefault(a_policies);

    name = a_name;
    parent = a_parent;
    m_orb = an_orb;

    if (a_manager != null)
      m_manager = a_manager;
    else
      m_manager = new gnuPOAManager();

    if (m_manager instanceof gnuPOAManager)
      {
        gnuPOAManager g = (gnuPOAManager) m_manager;
        g.addPoa(this);
      }

    m_policies = new HashSet(all_policies.length);

    s_policies = new Policy[ all_policies.length ];
    for (int i = 0; i < s_policies.length; i++)
      {
        s_policies [ i ] = all_policies [ i ].copy();
        m_policies.add(((AccessiblePolicy) s_policies [ i ]).getValue());
      }

    retain_servant = applies(ServantRetentionPolicyValue.RETAIN);

    validatePolicies(a_policies);
    
    refTemplate = new RefTemplate();
  }

  /**
   * Wait while at least one of the threads in this POA is actively
   * processing one of requests.
   */
  public void waitWhileRunning()
  {
    // First pause.
    long time = 1;

    // Maximal duration between checks.
    long max = 500;

    boolean runs;

    do
      {
        runs = m_orb.currents.has(this);

        if (runs)
          {
            // Avoid taking CPU resources
            // from the thread that is running.
            try
              {
                Thread.sleep(time);
                time = time * 2;
                if (time > max)
                  time = max;
              }
            catch (InterruptedException ex)
              {
              }
          }
      }
    while (runs);
  }

  /**
   * Etherealize all objects, associated with this POA. Invoked from the
   * {@link gnuPOAManager} only if it is known that the servant_activator
   * holds non-null value.
   */
  protected void etherealizeAll()
  {
    if (servant_activator == null)
      return;

    ArrayList keys = new ArrayList();
    keys.addAll(aom.keySet());

    byte[] key;
    AOM.Obj obj;
    boolean last;
    for (int i = 0; i < keys.size(); i++)
      {
        key = (byte[]) keys.get(i);
        obj = aom.get(key);

        if (obj.poa == this)
          {
            aom.remove(key);

            if (!obj.isDeactiveted())
              {
                // Check if the servant still stays under the other key.
                last = aom.findServant(obj.servant) == null;
                servant_activator.etherealize(obj.key, this, obj.servant, true,
                                              last
                                             );
              }
          }
      }
  }

  /**
   * Create an instance of the POA with the given features.
   * This method is not responsible for duplicate checking
   * or adding the returned instance to any possible table.
   *
   * @param child_name the name of the poa being created.
   * @param manager the poa manager (never null).
   * @param policies the array of policies.
   * @param an_orb the ORB for this POA.
   *
   * @return the created POA.
   *
   * @throws InvalidPolicy for conflicting or otherwise invalid policies.|
   */
  protected POA createPoaInstance(String child_name, POAManager a_manager,
                                  Policy[] policies, ORB_1_4 an_orb
                                 )
                           throws InvalidPolicy
  {
    POAManager some_manager =
      a_manager == null ? new gnuPOAManager() : a_manager;

    if (some_manager instanceof gnuPOAManager)
      {
        ((gnuPOAManager) some_manager).addPoa(this);
      }

    return new gnuPOA(this, child_name, some_manager, policies, an_orb);
  }

  /**
   * Check if the given policy value applies to this POA.
   *
   * @param policy_value a policy value to check. The policy values are
   * singletons and unique between the different policies, so the policy
   * type is not passed.
   *
   * @return true if the policy value applies, false otherwise.
   */
  public final boolean applies(java.lang.Object policy_value)
  {
    return m_policies.contains(policy_value);
  }

  /**
   * Check for the presence of the required policy.
   *
   * @param policy_value a policy value to check.
   *
   * @throws WrongPolicy if the required policy value is not applicable.
   */
  public final void required(java.lang.Object policy_value)
                      throws WrongPolicy
  {
    if (!applies(policy_value))
      throw new WrongPolicy(policy_value + " policy required.");
  }

  /**
   * Check for the absence of the given policy.
   *
   * @param policy_value a policy value to check.
   *
   * @throws WrongPolicy if the passed policy value is applicable.
   */
  public final void excluding(java.lang.Object policy_value)
                       throws WrongPolicy
  {
    if (applies(policy_value))
      throw new WrongPolicy(policy_value + " policy applies.");
  }

  /**
  * Find and optionally activate the child POA with the given name.
  *
  * @param poa_name the name of the POA to find.
  * @param activate_it if the child with the specified name is not found
  * or inactive and this parameter is true, the target POA activator is
  * invoked to activate that child. If this succeeds, that child POA
  * is returned.
  *
  * @throws AdapterNonExistent if no active child with the given name
  * is found and one of the following is true:
  * a) the target POA has no associated
  * {@link AdapterActivator}. b) that activator fails to activate the
  * child POA. c) <code>activate_id</code> = false.
  */
  public POA find_POA(String poa_name, boolean activate_it)
               throws AdapterNonExistent
  {
    POA child;
    for (int i = 0; i < children.size(); i++)
      {
        child = (POA) children.get(i);
        if (child.the_name().equals(poa_name))
          return child;
      }

    if (activate_it && m_activator != null)
      {
        boolean activated = m_activator.unknown_adapter(this, poa_name);
        if (!activated)
          throw new AdapterNonExistent(poa_name + " activation failed.");

        // Tha activator should add the child to the childrent table.
        for (int i = 0; i < children.size(); i++)
          {
            child = (POA) children.get(i);
            if (child.the_name().equals(poa_name))
              return child;
          }
        throw new AdapterNonExistent(poa_name + " not created. ");
      }
    else
      throw new AdapterNonExistent(poa_name);
  }

  /**
   * Generate the Object Id for the given servant and add the servant to the
   * Active Object Map using this Id a a key. If the servant activator is set,
   * its incarnate method will be called.
   * 
   * @param a_servant a servant that would serve the object with the returned
   * Object Id. If null is passed, under apporoprate policies the servant
   * activator is invoked.
   * 
   * @return the generated objert Id for the given servant.
   * 
   * @throws ServantAlreadyActive if this servant is already in the Active
   * Object Map and the UNIQUE_ID policy applies.
   * 
   * @throws WrongPolicy if the required policies SYSTEM_ID and RETAIN do not
   * apply to this POA.
   */
  public byte[] activate_object(Servant a_servant)
    throws ServantAlreadyActive, WrongPolicy
  {
    checkDiscarding();
    required(ServantRetentionPolicyValue.RETAIN);
    required(IdAssignmentPolicyValue.SYSTEM_ID);

    AOM.Obj exists = aom.findServant(a_servant);

    if (exists != null)
      {
        if (exists.isDeactiveted())
          {
            // If exists but deactivated, activate and return
            // the existing key.
            exists.setDeactivated(false);
            incarnate(exists, exists.key, a_servant, false);
            return exists.key;
          }
        else if (applies(IdUniquenessPolicyValue.UNIQUE_ID))
          throw new ServantAlreadyActive();

        // It multiple ids are allowed, exit block allowing repetetive
        // activations.
      }

    byte[] object_key = AOM.getFreeId();
    ServantDelegateImpl delegate = new ServantDelegateImpl(a_servant, this,
      object_key);
    create_and_connect(object_key,
      a_servant._all_interfaces(this, object_key)[0], delegate);
    return object_key;
  }

  /**
   * Add the given servant to the Active Object Map as a servant for the object
   * with the provided Object Id. If the servant activator is set, its incarnate
   * method will be called.
   * 
   * @param an_Object_Id an object id for the given object.
   * @param a_servant a servant that will serve the object with the given Object
   * Id. If null is passed, under apporoprate policies the servant activator is
   * invoked.
   * 
   * @throws ObjectAlreadyActive if the given object id is already in the Active
   * Object Map.
   * @throws ServantAlreadyActive if the UNIQUE_ID policy applies and this
   * servant is already in use.
   * @throws WrongPolicy if the required RETAIN policy does not apply to this
   * POA.
   * @throws BAD_PARAM if the passed object id is invalid due any reason.
   */
  public void activate_object_with_id(byte[] an_Object_Id, Servant a_servant)
                               throws ServantAlreadyActive, ObjectAlreadyActive,
                                      WrongPolicy
  {
    activate_object_with_id(an_Object_Id, a_servant, false);
  }

  /**
   * Same as activate_object_with_id, but permits gnuForwardRequest forwarding
   * exception. This is used when the activation is called from the remote
   * invocation context and we have possibility to return the forwarding
   * message.
   */
  public void activate_object_with_id(byte[] an_Object_Id, Servant a_servant,
    boolean use_forwarding)
    throws ServantAlreadyActive, ObjectAlreadyActive, WrongPolicy
  {
    checkDiscarding();
    required(ServantRetentionPolicyValue.RETAIN);

    // If the UNIQUE_ID applies, the servant being passed must not be
    // already active.
    if (applies(IdUniquenessPolicyValue.UNIQUE_ID))
      {
        AOM.Obj sx = aom.findServant(a_servant, false);
        if (sx != null)
          throw new ServantAlreadyActive();
      }

    AOM.Obj exists = aom.get(an_Object_Id);
    if (exists != null)
      {
        if (exists.servant == null)
          {
            locateServant(an_Object_Id, a_servant, exists, use_forwarding);
            exists.setDeactivated(false);
          }
        else if (exists.isDeactiveted())
          {
            exists.setDeactivated(false);
            incarnate(exists, an_Object_Id, a_servant, use_forwarding);
          }
        else
          throw new ObjectAlreadyActive();
      }
    else
      {
        ServantDelegateImpl delegate = new ServantDelegateImpl(a_servant, this,
          an_Object_Id);
        create_and_connect(an_Object_Id, a_servant._all_interfaces(this,
          an_Object_Id)[0], delegate);
      }
  }

  /**
   * Locate the servant for this object Id and connect it to ORB.
   * 
   * @param an_Object_Id the object id.
   * @param a_servant the servant (may be null).
   * @param exists an existing active object map entry.
   * @param use_forwarding allow to throw the gnuForwardRequest if the activator
   * throws ForwardRequest.
   * 
   * @throws OBJ_ADAPTER minor 4 if the servant cannot be located (the required
   * servant manager may be missing).
   */
  private void locateServant(byte[] an_Object_Id, Servant a_servant,
                             AOM.Obj exists, boolean use_forwarding
                            )
                      throws InternalError
  {
    // An object was created with create_reference.
    gnuServantObject object = (gnuServantObject) exists.object;
    if (servant_activator != null)
      {
        exists.setServant(incarnate(exists, an_Object_Id, a_servant,
                                    use_forwarding
                                   )
                         );
      }
    else if (default_servant != null)
      {
        exists.setServant(default_servant);
      }
    if (exists.servant == null)
      {
        exists.setServant(a_servant);
      }
    if (exists.servant == null)
      {
        throw new OBJ_ADAPTER("no servant", 4, CompletionStatus.COMPLETED_NO);
      }

    ServantDelegateImpl delegate =
      new ServantDelegateImpl(exists.servant, this, an_Object_Id);
    exists.servant._set_delegate(delegate);
    object.setServant(exists.servant);
    connect_to_orb(an_Object_Id, delegate.object);
  }

  /**
   * Deactivate object with the given id.
   *
   * The deactivated object will continue to process requests that arrived
   * before decativation. If this POA has the associated
   * servant manager, a {@link ServantActivatorOperations#etherealize} is
   * immediately invoked on the passed id.
   *
   * @throws WrongPolicy if the required RETAIN policy does not apply to
   * this POA.
   */
  public void deactivate_object(byte[] the_Object_Id)
                         throws ObjectNotActive, WrongPolicy
  {
    required(ServantRetentionPolicyValue.RETAIN);

    AOM.Obj exists = aom.get(the_Object_Id);

    if (exists == null || exists.isDeactiveted())
      throw new ObjectNotActive();

    exists.setDeactivated(true);

    // Check if this servant is serving something else.
    aom.remove(the_Object_Id);

    AOM.Obj other = aom.findServant(exists.servant, false);

    boolean remaining = other != null;

    aom.put(exists);

    if (servant_activator != null)
      servant_activator.etherealize(the_Object_Id, this, exists.servant, false,
                                    remaining
                                   );
  }

  /**
  * Create the object reference, encapsulating the given repository Id and
  * the Object Id, generated by this POA. The returned object will not be
  * activated by default and may be activated on the first invocation by
  * the servant manager (if it is set and if policies are applicable).
  *
  * @param a_repository_id the repository id for the given object, can
  * be null if to be requested from the servant later.
  *
  * @throws WrongPolicy if the required SYSTEM_ID policy does not apply to
  * this POA.
  */
  public org.omg.CORBA.Object create_reference(String a_repository_id)
                                        throws WrongPolicy
  {
    required(IdAssignmentPolicyValue.SYSTEM_ID);
    return create_reference_with_id(AOM.getFreeId(), a_repository_id);
  }

  /**
   * <p>
   * Create the object reference, encapsulating the given repository Id and
   * the given Object Id. The returned object will <i>not</i> be
   * activated by default and may be activated on the first invocation by
   * the servant manager (if the IMPLICIT_ACTIVATION policy applies).
   *
   * @param an_object_id the object id for the object being created. If this
   * POA uses the SYSTEM_ID policy, the portable application should only
   * pass the ids, generated by this POA.
   *
   * @param a_repository_id the repository id for the object being created,
   * can be null if this information should be later requested from the
   * servant.
   */
  public org.omg.CORBA.Object create_reference_with_id(byte[] an_object_id,
    String a_repository_id
   )
  {
    String[] ids;
    if (a_repository_id == null)
      ids = null;
    else
      ids = new String[] { a_repository_id };

    // Check maybe such object is already activated.
    AOM.Obj e = aom.get(an_object_id);

    Servant servant;
    if (e == null)
      {
        servant = null;
      }
    else
      {
        servant = e.servant;
        e.setDeactivated(false);
      }

    gnuServantObject object =
      new gnuServantObject(ids, an_object_id, this, m_orb);
    object._set_delegate(new LocalDelegate(object, this, an_object_id));
    aom.add(object.Id, object, servant, this);
    connect_to_orb(an_object_id, object);

    return object;
  }

  /**
   * Creates a new POA as a child of the target POA.
   *
   * @param child_name the name of the child POA being created.
   * @param manager the manager that will control the new POA. If this parameter
   * is null, a new POA manager is created and associated with the new POA.
   *
   * @param policies the policies, applicable for the parent POA. Policies
   * are <i>not</i> inherited from the parent POA.
   *
   * @return an newly created POA. The POA will be intially in the holding
   * state and must be activated to start processing requests.
   *
   * @throws AdapterAlreadyExists if the child with the given child_name
   * already exists for the current POA.
   * @throws InvalidPolicy if the policies conflict with each other or are
   * otherwise inappropriate.
   *
   * @see #the_children()
   */
  public POA create_POA(String child_name, POAManager manager, Policy[] policies)
                 throws AdapterAlreadyExists, InvalidPolicy
  {
    POA child;
    for (int i = 0; i < children.size(); i++)
      {
        child = (POA) children.get(i);
        if (child.the_name().equals(child_name))
          throw new AdapterAlreadyExists(name + "/" + child_name);
      }

    POA poa = createPoaInstance(child_name, manager, policies, m_orb);
    children.add(poa);
    return poa;
  }

  /**
   * Returns a default servant for this POA.
   *
   * @return a servant that will be used for requests for
   * which no servant is found in the Active Object Map.
   *
   * @throws NoServant if there is no default servant associated with this POA.
   * @throws WrongPolicy if the USE_DEFAULT_SERVANT policy is not active.
   */
  public Servant get_servant()
                      throws NoServant, WrongPolicy
  {
    required(RequestProcessingPolicyValue.USE_DEFAULT_SERVANT);
    if (default_servant == null)
      throw new NoServant();
    return default_servant;
  }

  /**
   * Sets the default servant for this POA.
   *
   * @param a_servant a servant that will be used for requests for
   * which no servant is found in the Active Object Map.
   *
   * @throws WrongPolicy if the USE_DEFAULT_SERVANT policy is not active.
   */
  public void set_servant(Servant a_servant)
                   throws WrongPolicy
  {
    required(RequestProcessingPolicyValue.USE_DEFAULT_SERVANT);
    default_servant = a_servant;
  }

  /**
   * Set a servant manager for this POA.
   *
   * @param a servant manager being set. If the RETAIN policy applies, the
   * manager must implement a {@link ServantActivator}. If the NON_RETAIN
   * policy applies, the manager must implement a {@link ServantLocator}.
   *
   * @throws WrongPolicy if the required USE_SERVANT_MANAGER policy does not
   * apply to this POA.
   *
   * @throws OBJ_ADAPTER minor code 4 if the passed manager does not
   * implement the required interface ({@link ServantActivator},
   * {@link ServantLocator}). The POA, that has the RETAIN policy uses
   * servant managers that are ServantActivators. When the POA has the
   * NON_RETAIN policy it uses servant managers that are ServantLoacators.
   *
   * @throws BAD_INV_ORDER minor code 6 if the method is called more than once
   * on the same POA. The manager can be set only once.
   */
  public void set_servant_manager(ServantManager a_manager)
                           throws WrongPolicy
  {
    required(RequestProcessingPolicyValue.USE_SERVANT_MANAGER);
    if (servant_activator != null || servant_locator != null)
      throw new BAD_INV_ORDER("Setting manager twice for " + name, 6,
                              CompletionStatus.COMPLETED_NO
                             );

    if (applies(ServantRetentionPolicyValue.RETAIN))
      {
        if (a_manager instanceof ServantActivator)
          servant_activator = (ServantActivator) a_manager;
        else
          throw new OBJ_ADAPTER("RETAIN requires ServantActivator", 4,
                                CompletionStatus.COMPLETED_NO
                               );
      }
    else if (applies(ServantRetentionPolicyValue.NON_RETAIN))
      {
        if (a_manager instanceof ServantLocator)
          servant_locator = (ServantLocator) a_manager;
        else
          throw new OBJ_ADAPTER("NON_RETAIN requires ServantLocator", 4,
                                CompletionStatus.COMPLETED_NO
                               );
      }
    else
      throw new WrongPolicy("No servant retention policy is specified.");
  }

  /**
   * Get the servant manager, associated with this POA.
   *
   * @return the associated servant manager or null if it has
   * been previously set.
   *
   * @throws WrongPolicy if the required USE_SERVANT_MANAGER policy does not
   * apply to this POA.
   */
  public ServantManager get_servant_manager()
                                     throws WrongPolicy
  {
    required(RequestProcessingPolicyValue.USE_SERVANT_MANAGER);

    if (servant_activator != null)
      return servant_activator;
    else
      return servant_locator;
  }

  /**
   * Get the unique Id of the POA in the process in which it is created.
   * This Id is needed by portable interceptors. The id is unique
   * for the life span of the POA in the process. For persistent
   * POAs, if a POA is created in the same path with the same name as
   * another POA, these POAs are identical have the same id. All transient
   * POAs are assumed unique.
   */
  public byte[] id()
  {
    if (m_poa_id != null)
      return m_poa_id;
    else
      {
        BufferedCdrOutput buffer = new BufferedCdrOutput();
        POA p = this;
        while (p != null)
          {
            buffer.write_string(p.the_name());
            p = p.the_parent();
          }
        m_poa_id = buffer.buffer.toByteArray();
        return m_poa_id;
      }
  }

  /**
   * Returns the reference to the active object with the given Id.
   *
   * @param the_Object_Id the object id.
   *
   * @throws ObjectNotActive if there is no active object with such Id
   * in the scope of this POA.
   * @throws WrongPolicy if the required RETAIN policy does not apply to
   * this POA.
   */
  public org.omg.CORBA.Object id_to_reference(byte[] the_Object_Id)
                                       throws ObjectNotActive, WrongPolicy
  {
    required(ServantRetentionPolicyValue.RETAIN);

    AOM.Obj ref = aom.get(the_Object_Id);
    if (ref == null)
      throw new ObjectNotActive();
    else
      return ref.object;
  }

  /**
   * Returns the servant that serves the active object with the given Id.
   *
   * @param the_Object_Id the object id.
   *
   * @throws ObjectNotActive if there is no active object with such Id or
   * it is not currently active.
   * @throws WrongPolicy. This method requires either RETAIN or
   * USE_DEFAULT_SERVANT policies and reaises the WrongPolicy if none of them
   * apply to this POA.
   */
  public Servant id_to_servant(byte[] the_Object_Id)
                        throws ObjectNotActive, WrongPolicy
  {
    if (applies(ServantRetentionPolicyValue.RETAIN))
      {
        AOM.Obj ref = aom.get(the_Object_Id);
        if (ref == null || ref.isDeactiveted())
          {
            if (default_servant != null)
              return default_servant;
            else
              throw new ObjectNotActive();
          }
        else if (ref.servant != null)
          return ref.servant;
        else if (default_servant != null)
          return default_servant;
        else
          throw new ObjectNotActive();
      }
    else if (default_servant != null)
      {
        return default_servant;
      }
    else
      throw new WrongPolicy("Either RETAIN or USE_DEFAULT_SERVANT required.");
  }

  /**
   * Returns the Object Id, encapsulated in the given object reference.
   *
   * @param the_Object the object that has been previously created with this
   * POA. It need not be active.
   *
   * @throws WrongAdapter if the passed object is not known for this POA.
   * @throws WrongPolicy never (declared for the future extensions only).
   */
  public byte[] reference_to_id(org.omg.CORBA.Object the_Object)
                         throws WrongAdapter, WrongPolicy
  {
    AOM.Obj ref = aom.findObject(the_Object);
    if (ref == null)
      throw new WrongAdapter();
    return ref.key;
  }

  /**
   * Returns the servant that is serving this object.
   * 
   * @return if the RETAIN policy applies and the object is in the Active Object
   * Map, the method returns the servant, associated with this object.
   * Otherwise, if the USE_DEFAULT_SERVANT policy applies, the method returns
   * the default servant (if one was set).
   * 
   * @throws ObjectNotActive if none of the conditions above are satisfied.
   * @throws WrongAdapter if the object reference was not created with this POA.
   * @throws WrongPolicy. This method requires either RETAIN or
   * USE_DEFAULT_SERVANT policies and reaises the WrongPolicy if none of them
   * apply to this POA.
   */
  public Servant reference_to_servant(org.omg.CORBA.Object the_Object)
    throws ObjectNotActive, WrongPolicy, WrongAdapter
  {
    if (applies(ServantRetentionPolicyValue.RETAIN))
      {
        AOM.Obj ref = aom.findObject(the_Object);
        if (ref == null)
          {
            String object;
            if (the_Object == null)
              object = "null passed"; 
            else if (the_Object instanceof gnuServantObject)
              {
                gnuServantObject gs = (gnuServantObject) the_Object;
                object = "Wrong owner POA " + gs.poa.the_name();
              }
            else
              object = "Unknown " + the_Object.getClass().getName();

            throw new WrongAdapter(object + " for '" + the_name() + "'");
          }
        else if (ref.isDeactiveted() || ref.servant == null)
          {
            if (default_servant != null)
              return default_servant;
            else
              throw new ObjectNotActive();
          }
        else
          return ref.servant;
      }
    else if (default_servant != null)
      {
        return default_servant;
      }
    else
      throw new WrongPolicy("Either RETAIN or USE_DEFAULT_SERVANT required.");
  }

  /**
   * Returns the id of the object, served by the given servant (assuming that
   * the servant serves only one object). The id is found in one of the
   * following ways.
   * <ul>
   * <li>If the POA has both the RETAIN and the UNIQUE_ID policy and the
   * specified servant is active, the method return the Object Id associated
   * with that servant. </li>
   * <li> If the POA has both the RETAIN and the IMPLICIT_ACTIVATION policy and
   * either the POA has the MULTIPLE_ID policy or the specified servant is
   * inactive, the method activates the servant using a POA-generated Object Id
   * and the Interface Id associated with the servant, and returns that Object
   * Id. </li>
   * <li>If the POA has the USE_DEFAULT_SERVANT policy, the servant specified
   * is the default servant, and the method is being invoked in the context of
   * executing a request on the default servant, the method returns the ObjectId
   * associated with the current invocation. </li>
   * </ul>
   * 
   * @throws ServantNotActive in all cases, not listed in the list above.
   * @throws WrongPolicy The method requres USE_DEFAULT_SERVANT policy or a
   * combination of the RETAIN policy and either the UNIQUE_ID or
   * IMPLICIT_ACTIVATION policies and throws the WrongPolicy if these conditions
   * are not satisfied.
   */
  public byte[] servant_to_id(Servant the_Servant)
                       throws ServantNotActive, WrongPolicy
  {
    if (applies(RequestProcessingPolicyValue.USE_DEFAULT_SERVANT) ||
        applies(ServantRetentionPolicyValue.RETAIN) &&
        (
          applies(IdUniquenessPolicyValue.UNIQUE_ID) ||
          applies(ImplicitActivationPolicyValue.IMPLICIT_ACTIVATION)
        )
       )
      {
        AOM.Obj ref = null;
        if (!applies(IdUniquenessPolicyValue.MULTIPLE_ID))
          ref = aom.findServant(the_Servant);
        if (ref == null &&
            applies(ImplicitActivationPolicyValue.IMPLICIT_ACTIVATION)
           )
          {
            // Try to activate.
            try
              {
                return activate_object(the_Servant);
              }
            catch (ServantAlreadyActive ex)
              {
                // Either it shuld not be or the policy allows multiple ids.
                throw new InternalError();
              }
          }
        if (ref == null)
          throw new ServantNotActive();
        else
          return ref.key;
      }
    else
      throw new WrongPolicy("(RETAIN and UNIQUE ID) " +
                            "or USE_DEFAULT_SERVANT required."
                           );
  }

  /**
   * <p>
   * Converts the given servant to the object reference. The servant will serve
   * all methods, invoked on the returned object. The returned object reference
   * can be passed to the remote client, enabling remote invocations.
   * </p>
   * <p>
   * If the specified servant is active, it is returned. Otherwise, if the POA
   * has the IMPLICIT_ACTIVATION policy the method activates the servant. In
   * this case, if the servant activator is set, the
   * {@link ServantActivatorOperations#incarnate} method will be called.
   * </p>
   * 
   * @throws ServantNotActive if the servant is inactive and no
   * IMPLICIT_ACTIVATION policy applies.
   * @throws WrongPolicy This method needs the RETAIN policy and either the
   * UNIQUE_ID or IMPLICIT_ACTIVATION policies.
   * 
   * @return the object, exposing the given servant in the context of this POA.
   */
  public org.omg.CORBA.Object servant_to_reference(Servant the_Servant)
    throws ServantNotActive, WrongPolicy
  {
    required(ServantRetentionPolicyValue.RETAIN);

    AOM.Obj exists = null;

    if (!applies(IdUniquenessPolicyValue.MULTIPLE_ID))
      exists = aom.findServant(the_Servant);

    if (exists != null)
      {
        if (exists.isDeactiveted())
          {
            if (applies(ImplicitActivationPolicyValue.IMPLICIT_ACTIVATION))
              {
                checkDiscarding();
                exists.setDeactivated(false);
                incarnate(exists, exists.key, the_Servant, false);
              }
            else
              throw new ServantNotActive();
          }
        else
          return exists.object;
      }
    if (exists == null
      && applies(ImplicitActivationPolicyValue.IMPLICIT_ACTIVATION))
      {
        checkDiscarding();

        byte[] object_key = AOM.getFreeId();

        ServantDelegateImpl delegate = new ServantDelegateImpl(the_Servant,
          this, object_key);
        create_and_connect(object_key, the_Servant._all_interfaces(this,
          object_key)[0], delegate);

        return delegate.object;
      }
    else
      throw new ServantNotActive();
  }

  /**
   * Incarnate in cases when request forwarding is not expected because the
   * servant must be provided by the servant activator.
   * 
   * @param x the aom entry, where the object is replaced by value, returned by
   * servant activator (if not null).
   * 
   * @param key the object key.
   * 
   * @param a_servant the servant that was passed as a parameter in the
   * activation method.
   * 
   * @param use_forwarding if true, the gnuForwardRequest is throw under the
   * forwarding exception (for remote client). Otherwise, the request is
   * internally redirected (for local invocation).
   */
  private Servant incarnate(AOM.Obj x, byte[] object_key,
                            Servant a_servant, boolean use_forwarding
                           )
  {
    if (servant_activator != null)
      {
        Servant servant;
        try
          {
            servant = servant_activator.incarnate(object_key, this);
          }
        catch (ForwardRequest ex)
          {
            if (use_forwarding)
              throw new gnuForwardRequest(ex.forward_reference);
            else
              servant =
                ForwardedServant.create((ObjectImpl) ex.forward_reference);
          }
        if (servant != null && x != null)
          x.setServant(servant);
        if (servant == null && x != null)
          servant = x.servant;
        return servant;
      }
    else if (a_servant != null)
      {
        x.setServant(a_servant);
        return a_servant;
      }
    else if (x.servant != null)
      {
        return x.servant;
      }
    else if (default_servant != null)
      {
        x.setServant(default_servant);
        return x.servant;
      }
    else
      throw new BAD_INV_ORDER("No servant given and the servant activator not set");
  }

  /**
   * Return the POA manager, associated with this POA.
   *
   * @return the associated POA manager (always available).
   */
  public POAManager the_POAManager()
  {
    return m_manager;
  }

  /**
   * Returns the adapter activator, associated with this POA.
   * The newly created POA has no activator (null would be
   * returned). The ORB root POA also initially has no activator.
   *
   * @return tha adapter activator or null if this POA has no
   * associated adapter activator.
   */
  public AdapterActivator the_activator()
  {
    return m_activator;
  }

  /**
  * Set the adapter activator for this POA.
  *
  * @param the activator being set.
  */
  public void the_activator(AdapterActivator an_activator)
  {
    m_activator = an_activator;
  }

  /**
  * The children of this POA.
  *
  * @return the array of all childs for this POA.
  */
  public POA[] the_children()
  {
    POA[] poas = new POA[ children.size() ];
    for (int i = 0; i < poas.length; i++)
      {
        poas [ i ] = (POA) children.get(i);
      }
    return poas;
  }

  /**
   * Return the name of this POA.
   *
   * @return the name of POA, relative to its parent.
   */
  public String the_name()
  {
    return name;
  }
  ;

  /**
   * Return the parent of this POA.
   *
   * @return the parent POA or <code>null</code> if this is a root POA.
   */
  public POA the_parent()
  {
    return parent;
  }

  /** {@inheritDoc} */
  public IdAssignmentPolicy create_id_assignment_policy(IdAssignmentPolicyValue a_value)
  {
    return new gnuIdAssignmentPolicy(a_value);
  }

  /** {@inheritDoc} */
  public IdUniquenessPolicy create_id_uniqueness_policy(IdUniquenessPolicyValue a_value)
  {
    return new gnuIdUniquenessPolicy(a_value);
  }

  /** {@inheritDoc} */
  public ImplicitActivationPolicy create_implicit_activation_policy(ImplicitActivationPolicyValue a_value)
  {
    return new gnuImplicitActivationPolicy(a_value);
  }

  /** {@inheritDoc} */
  public LifespanPolicy create_lifespan_policy(LifespanPolicyValue a_value)
  {
    return new gnuLifespanPolicy(a_value);
  }

  /** {@inheritDoc} */
  public RequestProcessingPolicy create_request_processing_policy(RequestProcessingPolicyValue a_value)
  {
    return new gnuRequestProcessingPolicy(a_value);
  }

  /** {@inheritDoc} */
  public ServantRetentionPolicy create_servant_retention_policy(ServantRetentionPolicyValue a_value)
  {
    return new gnuServantRetentionPolicy(a_value);
  }

  /** {@inheritDoc} */
  public ThreadPolicy create_thread_policy(ThreadPolicyValue a_value)
  {
    return new gnuThreadPolicy(a_value);
  }

  /**
   * <p>
   * Destroy this POA and all descendant POAs. The destroyed POAs can be later
   * re-created via {@link AdapterActivator} or by invoking {@link #create_POA}.
   * This differs from {@link PoaManagerOperations#deactivate} that does not
   * allow recreation of the deactivated POAs. After deactivation, recreation is
   * only possible if the POAs were later destroyed.
   * </p>
   * <p>
   * The remote invocation on the target, belonging to the POA that is currently
   * destroyed return the remote exception ({@link TRANSIENT}, minor code 4).
   * </p>
   * 
   * @param etherealize_objects if true, and POA has RETAIN policy, and the
   * servant manager is available, the servant manager method
   * {@link ServantActivatorOperations#etherealize} is called for each <i>active</i>
   * object in the Active Object Map. This method should not try to access POA
   * being destroyed. If <code>destroy</code> is called multiple times before
   * the destruction completes, the etherialization should be invoked only once.
   * 
   * @param wait_for_completion if true, the method waits till the POA being
   * destroyed completes all current requests and etherialization. If false, the
   * method returns immediately.
   */
  public void destroy(boolean etherealize_objects, boolean wait_for_completion)
  {
    // Notify the IOR interceptors about that the POA is destroyed.
    if (m_orb.iIor != null)
      m_orb.iIor.adapter_state_changed(
        new ObjectReferenceTemplate[] { getReferenceTemplate() },
        NON_EXISTENT.value);

    if (wait_for_completion)
      waitWhileRunning();

    // Nofify the IOR interceptors that the POA is destroyed.
    if (m_manager instanceof gnuPOAManager)
      {
        ((gnuPOAManager) m_manager).poaDestroyed(this);
      }

    // Put the brake instead of manager, preventing the subsequent
    // requests.
    gnuPOAManager g = new gnuPOAManager();
    g.state = State.INACTIVE;
    m_manager = g;

    // Disconnect from parent.
    if (parent instanceof gnuPOA)
      {
        ((gnuPOA) parent).children.remove(this);
      }

    unregisterFromManager();

    // Disconnect from the ORB all objects, registered with this POA.
    ArrayList keys = new ArrayList();
    keys.addAll(aom.keySet());

    byte[] key;
    AOM.Obj obj;
    for (int i = 0; i < keys.size(); i++)
      {
        key = (byte[]) keys.get(i);
        obj = aom.get(key);
        if (obj.poa == this)
          m_orb.disconnect(obj.object);
      }

    m_orb.identityDestroyed(this);

    if (etherealize_objects && servant_activator != null && !m_inDestruction)
      {
        etherealizeAll();
      }
    m_inDestruction = true;

    POA[] ch = the_children();
    for (int i = 0; i < ch.length; i++)
      {
        ch[i].destroy(etherealize_objects, wait_for_completion);
      }
  }

  /**
   * Destroy this POA if it has not been destroyed, destroys it.
   */
  protected void finalize()
                   throws java.lang.Throwable
  {
    if (!m_inDestruction)
      destroy(false, false);
  }

  /**
   * Remove self from the manager list.
   */
  private void unregisterFromManager()
  {
    if (m_manager instanceof gnuPOAManager)
      {
        gnuPOAManager p = (gnuPOAManager) m_manager;
        p.removePOA(this);
      }
  }

  /**
   * Get the policy of the given type, associated with this POA.
   *
   * @param a_policy_type a type of the requested policy.
   * @return a policy of the given type, applyting to this POA.
   *
   * @throws org.omg.CORBA.BAD_PARAM if the policy of this type has not
   * been specified for this POA.
   */
  public Policy _get_policy(int a_policy_type)
                     throws org.omg.CORBA.BAD_PARAM
  {
    for (int i = 0; i < s_policies.length; i++)
      {
        if (s_policies [ i ].policy_type() == a_policy_type)
          return s_policies [ i ].copy();
      }
    throw new BAD_PARAM("No policy type " + a_policy_type);
  }

  /**
   * Get the copy of the policy array.
   */
  public Policy[] getPolicyArray()
  {
    Policy[] r = new Policy[ s_policies.length ];
    for (int i = 0; i < s_policies.length; i++)
      {
        r [ i ] = s_policies [ i ].copy();
      }
    return r;
  }

  /**
   * The POAs cannot be created by this method.
   *
   * @specnote this is also not possible in Suns jdk at least till 1.4.
   *
   * @throws NO_IMPLEMENT always.
   */
  public org.omg.CORBA.Object _set_policy_override(Policy[] policies,
                                                   SetOverrideType how
                                                  )
  {
    throw new NO_IMPLEMENT("Use createPOA instead.");
  }

  /**
   * Get the ORB, where this POA is connected.
   */
  public ORB orb()
  {
    return m_orb;
  }

  /**
   * Connect the given delegate under the given key, also calling incarnate.
   */
  private void create_and_connect(byte[] object_key, String repository_id,
    ServantDelegateImpl delegate)
  {
    aom.add(delegate);
    connect_to_orb(object_key, getReferenceFactory().make_object(repository_id,
      object_key));
    if (servant_activator != null)
      incarnate(null, object_key, delegate.servant, false);
  }

  /**
   * Check if the POA is not in a discarding mode. The activation
   * operations are forbidded in discarding mode.
   *
   * @throws TRANSIENT if the POA is in discarding mode.
   */
  private void checkDiscarding()
                        throws TRANSIENT
  {
    if (m_manager.get_state() == State.DISCARDING)
      throw new TRANSIENT("Discarding mode", 1, CompletionStatus.COMPLETED_MAYBE);
  }

  /**
   * Connect the given delegate object to orb.
   */
  protected void connect_to_orb(byte[] an_Object_Id, org.omg.CORBA.Object object)
  {
    if (applies(ThreadPolicyValue.SINGLE_THREAD_MODEL))
      m_orb.connect_1_thread(object, toIORKey(an_Object_Id), this);
    else
      m_orb.connect(object, toIORKey(an_Object_Id));
  }

  /**
   * Returns the representation of this POA tree.
   */
  public String toString()
  {
    StringBuffer b = new StringBuffer(name);

    if (children.size() != 0)
      {
        b.append(" (");

        for (int i = 0; i < children.size(); i++)
          {
            b.append(children.get(i));
            if (i < children.size() - 2)
              b.append(", ");
          }
        b.append(")");
      }
    return b.toString();
  }

  /**
   * Check if the policy set is valid.
   */
  protected boolean validatePolicies(Policy[] a)
                              throws InvalidPolicy
  {
    if (applies(ServantRetentionPolicyValue.NON_RETAIN))
      {
        if (!applies(RequestProcessingPolicyValue.USE_DEFAULT_SERVANT) &&
            !applies(RequestProcessingPolicyValue.USE_SERVANT_MANAGER)
           )
          {
            short p = 0;
            for (short i = 0; i < a.length; i++)
              {
                if (a [ i ].policy_type() == SERVANT_RETENTION_POLICY_ID.value)
                  p = i;
              }
            throw new InvalidPolicy("NON_RETAIN requires either " +
                                    "USE_DEFAULT_SERVANT or USE_SERVANT_MANAGER",
                                    p
                                   );
          }
      }
    return true;
  }

  /**
   * Recursively searches for the given object in the POA tree.
   */
  public AOM.Obj findObject(org.omg.CORBA.Object object)
  {
    AOM.Obj h = aom.findObject(object);
    if (h != null)
      return h;
    else
      {
        for (int i = 0; i < children.size(); i++)
          {
            h = ((gnuPOA) children.get(i)).findObject(object);
            if (h != null)
              return h;
          }
      }
    return h;
  }
  
  /**
   * Recursively searches for the given key in the POA tree.
   * @param ior_key the key, ecapsulating both object
   * and poa ids.
   * @return
   */
  public AOM.Obj findKey(byte[] object_id, byte[] poa_id)
  {
    AOM.Obj h = null;
    if (Arrays.equals(poa_id, id()))
      h = aom.get(object_id);
    if (h != null)
      return h;
    else
      {
        for (int i = 0; i < children.size(); i++)
          {
            h = ((gnuPOA) children.get(i)).findKey(object_id, poa_id);
            if (h != null)
              return h;
          }
      }
    return h;
  }

  /**
   * Parses the given key, extracts poa and object id and searches
   * for such reference.
   */
  public AOM.Obj findIorKey(byte[] ior_key)
  {
    BufferredCdrInput in = new BufferredCdrInput(ior_key);
    int signature = in.read_long();
    if (signature != SIGNATURE)
      return null;

    byte[] id = in.read_sequence();
    byte[] poa = in.read_sequence();
    return findKey(id, poa);
  }

  /**
   * Converts the object Id into the IOR key. IOR key must be
   * unique in the scope of the ORB, and Ids only in the scope of POA.
   * Hence the IOR key includes the POA identifiers.
   */
  public byte[] toIORKey(byte[] object_id)
  {
    BufferedCdrOutput buffer = new BufferedCdrOutput();
    buffer.write_long(SIGNATURE);
    buffer.write_sequence(object_id);
    buffer.write_sequence(id());
    return buffer.buffer.toByteArray();
  }

  /**
   * Extracts the object id from the ior key.
   *
   * @param ior_key
   *
   * @return the encapsulated object ior key or null if
   * this ior key either refers a different POA or encoding signature
   * mismatch.
   */
  public byte[] idFormIor(byte[] ior_key)
  {
    BufferredCdrInput in = new BufferredCdrInput(ior_key);
    int signature = in.read_long();
    if (signature != SIGNATURE)
      return null;

    byte[] object_id = in.read_sequence();
    byte[] poa_id = in.read_sequence();
    if (Arrays.equals(poa_id, id()))
      return object_id;
    else
      return null;
  }
  
  /**
   * Recursively searches for the given servant in the POA tree.
   */
  public AOM.Obj findServant(Servant servant)
  {
    AOM.Obj h = aom.findServant(servant);
    if (h != null)
      return h;
    else
      {
        for (int i = 0; i < children.size(); i++)
          {
            h = ((gnuPOA) children.get(i)).findServant(servant);
            if (h != null)
              return h;
          }
      }
    return h;
  }
  
  /**
   * Get the object reference template of this POA.
   * Instantiate a singleton instance, if required.
   */
  public ObjectReferenceTemplate getReferenceTemplate()
  {
    if (refTemplate == null)
      refTemplate = new RefTemplate();
    
    return refTemplate;
  }
  
  public ObjectReferenceFactory getReferenceFactory()
  {
    return m_object_factory;
  }
  
  public void setReferenceFactory(ObjectReferenceFactory factory)
  {
    m_object_factory = factory;
  }

  /**
   * Create the object (needed by the factory interface).
   */
  public Object make_object(String a_repository_id, byte[] an_object_id)
  {
    AOM.Obj existing = aom.get(an_object_id);
    // The object may already exist. In this case, it is just returned.
    if (existing != null && existing.object != null)
      return existing.object;
    else
      {
        return new gnuServantObject(new String[] { a_repository_id },
          an_object_id, this, m_orb);
      }
  }

  /**
   * Required by object reference factory ops.
   */
  public String[] _truncatable_ids()
  {
    return ref_template_ids;
  }
}