/* Registrator.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.Interceptor;

import gnu.CORBA.Poa.ORB_1_4;
import gnu.CORBA.ObjectCreator;
import gnu.CORBA.gnuCodecFactory;

import org.omg.CORBA.BAD_INV_ORDER;
import org.omg.CORBA.CompletionStatus;
import org.omg.CORBA.LocalObject;
import org.omg.CORBA.Object;
import org.omg.IOP.CodecFactory;
import org.omg.PortableInterceptor.ClientRequestInterceptor;
import org.omg.PortableInterceptor.IORInterceptor;
import org.omg.PortableInterceptor.Interceptor;
import org.omg.PortableInterceptor.ORBInitInfo;
import org.omg.PortableInterceptor.ORBInitInfoPackage.DuplicateName;
import org.omg.PortableInterceptor.ORBInitInfoPackage.InvalidName;
import org.omg.PortableInterceptor.ORBInitializer;
import org.omg.PortableInterceptor.ORBInitializerOperations;
import org.omg.PortableInterceptor.PolicyFactory;
import org.omg.PortableInterceptor.ServerRequestInterceptor;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;

import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Map;
import java.util.Properties;
import java.util.TreeMap;

/**
 * Collects interceptors, references and factories into arrays during
 * registration. As the class is security sensitive, the most of the fields are
 * private.
 *
 * @author Audrius Meskauskas, Lithuania (AudriusA@Bioinformatics.org)
 */
public class Registrator extends LocalObject implements ORBInitInfo
{
  /**
   * Use serialVersionUID for interoperability.
   */
  private static final long serialVersionUID = 1;

  /**
   * The agreed properties prefix.
   */
  public static final String m_prefix =
    "org.omg.PortableInterceptor.ORBInitializerClass.";

  /**
   * The initialization - time server request interceptors.
   */
  private ArrayList m_server = new ArrayList();

  /**
   * The initialization - time client request interceptors.
   */
  private ArrayList m_client = new ArrayList();

  /**
   * The initialization - time ior interceptors.
   */
  private ArrayList m_ior = new ArrayList();

  /**
   * The policy factories.
   */
  public Hashtable m_policyFactories = new Hashtable();

  /**
   * The registered references. To avoid exposing the ORB's references map, the
   * are added by ORB from inside the ORB code. The ORB is responsible for
   * taking them from this field between pre_init and post_init.
   */
  public TreeMap m_references = new TreeMap();

  /**
   * The initializers.
   */
  public ArrayList m_initializers = new ArrayList();

  /**
   * The ORB being intialised.
   */
  final ORB_1_4 orb;

  /**
   * The argument string array, passed to ORB.init.
   */
  final String[] m_args;

  /**
   * The codec factory.
   */
  final gnuCodecFactory m_codecFactory;

  /**
   * Create the interceptor collection from the given properties, using the
   * agreed naming convention.
   *
   * @param orb the ORB being initialised.
   * @param props the cumulated set of properties where the orb initializer
   * pattern is searched.
   * @param an_args the argument string array, passed to ORB.init.
   */
  public Registrator(ORB_1_4 an_orb, Properties props, String[] an_args)
  {
    orb = an_orb;
    m_args = an_args;
    m_codecFactory = new gnuCodecFactory(orb);
    checkProperties(props);
    checkProperties(System.getProperties());
    checkFile("user.home", null);
    checkFile("java.home", "lib");
  }

  /**
   * Scan the given properties for the possible interceptors.
   */
  private void checkProperties(Properties props)
  {
    if (props == null)
      {
        return;
      }

    Enumeration names = props.propertyNames();
    java.lang.Object key;
    String sk;

    while (names.hasMoreElements())
      {
        key = names.nextElement();
        if (key != null)
          {
            sk = key.toString();
            if (sk.startsWith(m_prefix))
              {
                try
                  {
                    String cn = sk.substring(m_prefix.length());
                    Class iClass = ObjectCreator.forName(cn);
                    
                    ORBInitializer initializer =
                      (ORBInitializer) iClass.newInstance();
                    m_initializers.add(initializer);
                  }
                catch (Exception exc)
                  {
                    // OMG states we should not throw an exception, but
                    // this will help the user to detect his error
                    // in initialiser properties. Should never print during
                    // normal run.
                    System.err.println(sk + " failed");
                  }
              }
          }
      }
  }

  /**
   * Check if the property is defined in the existsting file orb.properties.
   */
  private void checkFile(String dir, String subdir)
  {
    try
      {
        File f = new File(dir);
        if (!f.exists())
          {
            return;
          }

        if (subdir != null)
          {
            f = new File(f, subdir);
          }
        f = new File(f, "orb.properties");

        if (!f.exists())
          {
            return;
          }

        Properties p = new Properties();
        p.load(new BufferedInputStream(new FileInputStream(f)));

        checkProperties(p);
      }
    catch (IOException ex)
      {
      }
  }

  /**
   * Called by ORB as a pre_init for all initializers.
   */
  public void pre_init()
  {
    Iterator iter = m_initializers.iterator();
    while (iter.hasNext())
      {
        ORBInitializerOperations initializer =
          (ORBInitializerOperations) iter.next();
        initializer.pre_init(this);
      }
  }

  /**
   * Get the map of the registered references. The ORB calls this method to
   * import the references into its references map.
   */
  public Map getRegisteredReferences()
  {
    return m_references;
  }

  /**
   * Called by ORB as a post-init for all initializers. After this call, the
   * interceptor sets are fixed and redundant information is discarded.
   */
  public void post_init()
  {
    Iterator iter = m_initializers.iterator();
    while (iter.hasNext())
      {
        ORBInitializerOperations initializer =
          (ORBInitializerOperations) iter.next();
        initializer.post_init(this);
      }
  }

  public ServerRequestInterceptor[] getServerRequestInterceptors()
  {
    ServerRequestInterceptor[] iServer =
      new ServerRequestInterceptor[ m_server.size() ];
    for (int i = 0; i < iServer.length; i++)
      {
        iServer [ i ] = (ServerRequestInterceptor) m_server.get(i);
      }
    return iServer;
  }

  public ClientRequestInterceptor[] getClientRequestInterceptors()
  {
    ClientRequestInterceptor[] iClient =
      new ClientRequestInterceptor[ m_client.size() ];
    for (int i = 0; i < iClient.length; i++)
      {
        iClient [ i ] = (ClientRequestInterceptor) m_client.get(i);
      }
    return iClient;
  }

  public IORInterceptor[] getIORInterceptors()
  {
    IORInterceptor[] iIor = new IORInterceptor[ m_ior.size() ];
    for (int i = 0; i < iIor.length; i++)
      {
        iIor [ i ] = (IORInterceptor) m_ior.get(i);
      }
    return iIor;
  }

  public void add_client_request_interceptor(
    ClientRequestInterceptor interceptor
  ) throws DuplicateName
  {
    add(m_client, interceptor);
  }

  public void add_ior_interceptor(IORInterceptor interceptor)
    throws DuplicateName
  {
    add(m_ior, interceptor);
  }

  public void add_server_request_interceptor(
    ServerRequestInterceptor interceptor
  ) throws DuplicateName
  {
    add(m_server, interceptor);
  }

  /**
   * Allocate a new slot for request - specific records.
   */
  public int allocate_slot_id()
  {
    return orb.icSlotSize++;
  }

  /**
   * Add the interceptor to the given collection.
   *
   * @param list the collection to add.
   * @param interceptor the interceptor to add.
   */
  private void add(ArrayList list, Interceptor interceptor)
    throws DuplicateName
  {
    if (interceptor.name().length() > 0)
      {
        Iterator iter = list.iterator();
        Interceptor ic;

        while (iter.hasNext())
          {
            ic = (Interceptor) iter.next();
            if (ic.name().equals(interceptor.name()))
              {
                throw new DuplicateName(interceptor.name());
              }
          }
      }
    list.add(interceptor);
  }

  /**
   * Get string array, passed to ORB.init.
   */
  public String[] arguments()
  {
    return m_args;
  }

  /**
   * Get the codec factory.
   */
  public CodecFactory codec_factory()
  {
    return m_codecFactory;
  }

  /**
   * Get the ORB's id, currently using .toString.
   */
  public String orb_id()
  {
    return "orb_" + orb;
  }

  /**
   * Register reference.
   */
  public void register_initial_reference(String object_name, Object object)
    throws InvalidName
  {
    if (object_name == null)
      {
        throw new InvalidName("null");
      }
    else if (object_name.length() == 0)
      {
        throw new InvalidName("Empty string");
      }
    else if (m_references.containsKey(object_name))
      {
        throw new InvalidName(object_name);
      }
    else
      {
        m_references.put(object_name, object);
      }
  }

  /**
   * Accumulates the policy factory map.
   */
  public void register_policy_factory(int policy_type,
    PolicyFactory policy_factory
  )
  {
    Integer it = new Integer(policy_type);
    if (m_policyFactories.containsKey(it))
      {
        throw new BAD_INV_ORDER(
          "Repetetive registration of the policy factory for type " +
          policy_type,
          16,
          CompletionStatus.COMPLETED_NO
        );
      }
    m_policyFactories.put(it, policy_factory);
  }

  /**
   * Delegates to ORB.
   */
  public org.omg.CORBA.Object resolve_initial_references(String object_name)
    throws InvalidName
  {
    try
      {
        return orb.resolve_initial_references(object_name);
      }
    catch (org.omg.CORBA.ORBPackage.InvalidName e)
      {
        InvalidName in = new InvalidName(e.getMessage());
        in.initCause(e);
        throw in;
      }
  }

  /**
   * Check if any interceptors of this type were registered.
   */
  public boolean hasClientRequestInterceptors()
  {
    return m_client.size() > 0;
  }

  /**
   * Check if any interceptors of this type were registered.
   */
  public boolean hasServerRequestInterceptors()
  {
    return m_server.size() > 0;
  }

  /**
   * Check if any interceptors of this type were registered.
   */
  public boolean hasIorInterceptors()
  {
    return m_ior.size() > 0;
  }
}