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

import gnu.CORBA.CDR.UnknownExceptionCtxHandler;
import gnu.CORBA.CDR.BufferredCdrInput;
import gnu.CORBA.CDR.BufferedCdrOutput;
import gnu.CORBA.GIOP.CloseMessage;
import gnu.CORBA.GIOP.ErrorMessage;
import gnu.CORBA.GIOP.MessageHeader;
import gnu.CORBA.GIOP.ReplyHeader;
import gnu.CORBA.GIOP.RequestHeader;
import gnu.CORBA.NamingService.NameParser;
import gnu.CORBA.NamingService.NamingServiceTransient;
import gnu.CORBA.Poa.gnuForwardRequest;
import gnu.CORBA.interfaces.SocketFactory;

import org.omg.CORBA.BAD_OPERATION;
import org.omg.CORBA.BAD_PARAM;
import org.omg.CORBA.CompletionStatus;
import org.omg.CORBA.MARSHAL;
import org.omg.CORBA.NO_RESOURCES;
import org.omg.CORBA.OBJECT_NOT_EXIST;
import org.omg.CORBA.Request;
import org.omg.CORBA.SystemException;
import org.omg.CORBA.UNKNOWN;
import org.omg.CORBA.WrongTransaction;
import org.omg.CORBA.ORBPackage.InvalidName;
import org.omg.CORBA.portable.Delegate;
import org.omg.CORBA.portable.InvokeHandler;
import org.omg.CORBA.portable.ObjectImpl;
import org.omg.CORBA.portable.UnknownException;
import org.omg.CosNaming.NamingContextExt;
import org.omg.CosNaming.NamingContextExtHelper;

import java.applet.Applet;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Map;
import java.util.Properties;
import java.util.Random;
import java.util.StringTokenizer;
import java.util.TreeMap;

/**
 * The ORB implementation, capable to handle remote invocations on the
 * registered object. This class implements all features, required till the jdk
 * 1.3 inclusive, but does not support the POA that appears since 1.4. The POA
 * is supported by {@link gnu.CORBA.Poa.ORB_1_4}.
 *
 * @author Audrius Meskauskas (AudriusA@Bioinformatics.org)
 */
public class OrbFunctional extends OrbRestricted
{
  /**
   * A server, responsible for listening on requests on some local port. The ORB
   * may listen on multiple ports and process the requests in separate threads.
   * Normally the server takes one port per object being served.
   */
  protected class portServer
    extends Thread
  {
    /**
     * The number of the currently running parallel threads.
     */
    int running_threads;

    /**
     * The port on that this portServer is listening for requests.
     */
    int s_port;

    /**
     * The server socket of this portServer.
     */
    ServerSocket service;

    /**
     * True if the serving node must shutdown due call of the close_now().
     */
    boolean terminated;

    /**
     * Create a new portServer, serving on specific port.
     */
    portServer(int _port)
    {
      s_port = _port;
      setDaemon(true);
      try
        {
          service = socketFactory.createServerSocket(s_port);
        }
      catch (IOException ex)
        {
          BAD_OPERATION bad = new BAD_OPERATION(
            "Unable to open the server socket at " + s_port);
          bad.minor = Minor.Socket;
          bad.initCause(ex);
          throw bad;
        }
    }

    /**
     * Enter the serving loop (get request/process it). All portServer normally
     * terminate thy threads when the OrbFunctional.running is set to false.
     */
    public void run()
    {
      while (running)
        {
          try
            {
              tick();
            }
          catch (SocketException ex)
            {
              // May be thrown when the service is closed by
              // the close_now().
              if (terminated)
                return;
            }
          catch (Exception iex)
            {
              // Wait. Do not terminate the
              // service due potentially transient error.
              try
                {
                  Thread.sleep(TWAIT_SERVER_ERROR_PAUSE);
                }
              catch (InterruptedException ex)
                {
                }
            }
        }
    }

    /**
     * Perform a single serving step.
     *
     * @throws java.lang.Exception
     */
    void tick()
      throws Exception
    {
      serve(this, service);
    }

    /**
     * Forcibly close the server socket and mark this port as free.
     */
    public void close_now()
    {
      try
        {
          terminated = true;
          service.close();
        }
      catch (Exception ex)
        {
          // This may happen if the service has not been opened or
          // cannot be closed. Return without action.
        }
    }

    /**
     * If the thread is no longer in use, close the socket (if opened).
     */
    protected void finalize()
    {
      close_now();
    }
  }

  /**
   * A server, responsible for listening on requests on some local port and
   * serving multiple requests (probably to the different objects) on the same
   * thread.
   */
  protected class sharedPortServer extends portServer
  {
    /**
     * Create a new portServer, serving on specific port.
     */
    sharedPortServer(int _port)
    {
      super(_port);
    }

    /**
     * Perform a single serving step.
     *
     * @throws java.lang.Exception
     */
    void tick() throws Exception
    {
      Socket request = service.accept();
      serveStep(request, false);
    }
  }

  /**
   * The default value where the first instance of this ORB will start looking
   * for a free port.
   */
  public static int DEFAULT_INITIAL_PORT = 1126;

  /**
   * When trying to open the socket on a random port, start of the interval to
   * try.
   */
  public static int RANDOM_PORT_FROM = 1024;

  /**
   * When trying to open the socket on a random port, end of the interval to
   * try.
   */
  public static int RANDOM_PORT_TO = 4024;

  /**
   * The number of attempts to try when opening random port.
   */
  public static int RANDOM_PORT_ATTEMPTS = 64;

  /**
   * The property of port, on that this ORB is listening for requests from
   * clients. This class supports one port per ORB only.
   */
  public static final String LISTEN_ON = "gnu.classpath.CORBA.ListenOn";

  /**
   * The property, defining the IOR of the intial reference to resolve.
   */
  public static final String REFERENCE = "org.omg.CORBA.ORBInitRef";

  /**
   * The property, defining the port on that the default name service is
   * running.
   */
  public static final String NS_PORT = "org.omg.CORBA.ORBInitialPort";

  /**
   * The property, defining the host on that the default name service is
   * running.
   */
  public static final String NS_HOST = "org.omg.CORBA.ORBInitialHost";

  /**
   * The string, defining the naming service initial reference.
   */
  public static final String NAME_SERVICE = "NameService";

  /**
   * Defines the ORB ID that is accessible by IOR interceptors.
   */
  public static final String ORB_ID = "org.omg.CORBA.ORBid";


  /**
   * Defines the SERVER ID that is accessible by IOR interceptors.
   */
  public static final String SERVER_ID = "org.omg.CORBA.ServerId";

  /**
   * The if the client has once opened a socket, it should start sending the
   * message header in a given time. Otherwise the server will close the socket.
   * This prevents server hang when the client opens the socket, but does not
   * send any message, usually due crash on the client side.
   */
  public static String START_READING_MESSAGE =
    "gnu.classpath.CORBA.TOUT_START_READING_MESSAGE";

  /**
   * If the client has started to send the request message, the socket time out
   * changes to the specified value.
   */
  public static String WHILE_READING =
    "gnu.classpath.CORBA.TOUT_WHILE_READING";

  /**
   * If the message body is received, the time out changes to the specifice
   * value. This must be longer, as includes time, required to process the
   * received task. We make it 40 minutes.
   */
  public static String AFTER_RECEIVING =
    "gnu.classpath.CORBA.TOUT_AFTER_RECEIVING";

  /**
   * The server waits for this duration after the potentially transient error
   * during its servicing cycle.
   */
  public static String SERVER_ERROR_PAUSE =
    "gnu.classpath.CORBA.SERVER_ERROR_PAUSE";

  /**
   * The address of the local host.
   */
  public final String LOCAL_HOST;

  /**
   * The if the client has once opened a socket, it should start sending the
   * message header in a given time. Otherwise the server will close the socket.
   * This prevents server hang when the client opens the socket, but does not
   * send any message, usually due crash on the client side.
   */
  public int TOUT_START_READING_MESSAGE = 20 * 1000;

  // (Here and below, we use * to make the meaning of the constant clearler).

  /**
   * If the client has started to send the request message, the socket time out
   * changes to the specified value.
   */
  public int TOUT_WHILE_READING = 2 * 60 * 1000;

  /**
   * If the message body is received, the time out changes to the specifice
   * value. This must be longer, as includes time, required to process the
   * received task. We make it 40 minutes.
   */
  public int TOUT_AFTER_RECEIVING = 40 * 60 * 1000;

  /**
   * The server waits for this duration after the potentially transient error
   * during its servicing cycle.
   */
  public int TWAIT_SERVER_ERROR_PAUSE = 5000;

  /**
   * Some clients tend to submit multiple requests over the same socket. The
   * server waits for the next request on the same socket for the duration,
   * specified below. In additions, the request of this implementation also
   * waits for the same duration before closing the socket. The default time is
   * seven seconds.
   */
  public static int TANDEM_REQUESTS = 7000;

  /**
   * The Id of this ORB.
   */
  public String orb_id = "orb_"+hashCode();

  /**
   * The Id of this Server. This field is defined static to ensure it has
   * the same value over all ORB's in this machine.
   */
  public static String server_id = "server_"+OrbFunctional.class.hashCode();

  /**
   * The map of the already conncted objects.
   */
  protected final Connected_objects connected_objects =
    new Connected_objects();

  /**
   * The maximal CORBA version, supported by this ORB. The default value 0 means
   * that the ORB will not check the request version while trying to respond.
   */
  protected Version max_version;

  /**
   * Setting this value to false causes the ORB to shutdown after the latest
   * serving operation is complete.
   */
  protected boolean running;

  /**
   * The map of the initial references.
   */
  protected Map initial_references = new TreeMap();

  /**
   * The currently active portServers.
   */
  protected ArrayList portServers = new ArrayList();

  /**
   * The host, on that the name service is expected to be running.
   */
  private String ns_host;

  /**
   * Probably free port, under that the ORB will try listening for remote
   * requests first. When the new object is connected, this port is used first,
   * then it is incremented by 1, etc. If the given port is not available, up to
   * 20 subsequent values are tried and then the parameterless server socket
   * contructor is called. The constant is shared between multiple instances of
   * this ORB.
   */
  private static int Port = DEFAULT_INITIAL_PORT;

  /**
   * The port, on that the name service is expected to be running.
   */
  private int ns_port = 900;

  /**
   * The name parser.
   */
  NameParser nameParser = new NameParser();

  /**
   * The instance, stored in this field, handles the asynchronous dynamic
   * invocations.
   */
  protected Asynchron asynchron = new Asynchron();

  /**
   * The list of the freed ports. The ORB reuses ports, when possible.
   */
  protected LinkedList freed_ports = new LinkedList();

  /**
   * Maps a single-threaded POAs to they sharedPortServants.
   */
  protected Hashtable identities = new Hashtable();

  /**
   * The maximal allowed number of the currently running parallel threads per
   * object. For security reasons, this is made private and unchangeable. After
   * exceeding this limit, the NO_RESOURCES is thrown back to the client.
   */
  private int MAX_RUNNING_THREADS = 256;

  /**
   * The producer of the client and server sockets for this ORB.
   */
  public SocketFactory socketFactory = DefaultSocketFactory.Singleton;

  /**
   * Create the instance of the Functional ORB.
   */
  public OrbFunctional()
  {
    try
      {
        LOCAL_HOST = ns_host = InetAddress.getLocalHost().getHostAddress();
        initial_references.put("CodecFactory", new gnuCodecFactory(this));
      }
    catch (UnknownHostException ex)
      {
        BAD_OPERATION bad =
          new BAD_OPERATION("Unable to open the server socket.");
        bad.initCause(ex);
        throw bad;
      }
  }

  /**
   * If the max version is assigned, the orb replies with the error message if
   * the request version is above the supported 1.2 version. This behavior is
   * recommended by OMG, but not all implementations respond that error message
   * by re-sending the request, encoded in the older version.
   */
  public void setMaxVersion(Version max_supported)
  {
    max_version = max_supported;
  }

  /**
   * Get the maximal supported GIOP version or null if the version is not
   * checked.
   */
  public Version getMaxVersion()
  {
    return max_version;
  }

  /**
   * Get the currently free port, starting from the initially set port and going
   * up max 20 steps, then trying to bind into any free address.
   *
   * @return the currently available free port.
   *
   * @throws NO_RESOURCES if the server socked cannot be opened on the local
   * host.
   */
  public int getFreePort()
    throws BAD_OPERATION
  {
    ServerSocket s;
    int a_port;

    try
      {
        // If there are some previously freed ports, use them first.
        if (!freed_ports.isEmpty())
          {
            Integer free = (Integer) freed_ports.getLast();
            freed_ports.removeLast();
            s = socketFactory.createServerSocket(free.intValue());
            s.close();
            return free.intValue();
          }
      }
    catch (Exception ex)
      {
        // This may be thrown if the request for the new port has arrived
        // before the current service is completly shutdown.
        // OK then, use a new port.
      }

    for (a_port = Port; a_port < Port + 20; a_port++)
      {
        try
          {
            s = socketFactory.createServerSocket(a_port);
            s.close();
            Port = a_port + 1;
            return a_port;
          }
        catch (IOException ex)
          {
            // Repeat the loop if this exception has been thrown.
          }
      }

    Random rand = new Random();
    // Try any random port in the interval RANDOM_PORT_FROM.RANDOM_PORT_TO.
    int range = RANDOM_PORT_TO - RANDOM_PORT_FROM;
    IOException ioex = null;
    for (int i = 0; i < RANDOM_PORT_ATTEMPTS; i++)
      {
        try
          {
            a_port = RANDOM_PORT_FROM + rand.nextInt(range);
            s = socketFactory.createServerSocket(a_port);
            s.close();
            return a_port;
          }
        catch (IOException ex)
          {
            // Repeat the loop if this exception has been thrown.
            ioex = ex;
          }
      }

    NO_RESOURCES bad = new NO_RESOURCES("Unable to open the server socket.");
    bad.minor = Minor.Ports;
    if (ioex != null)
      bad.initCause(ioex);
    throw bad;
  }

  /**
   * Set the port, on that the server is listening for the client requests. If
   * only one object is connected to the orb, the server will be try listening
   * on this port first. It the port is busy, or if more objects are connected,
   * the subsequent object will receive a larger port values, skipping
   * unavailable ports, if required. The change applies globally.
   *
   * @param a_Port a port, on that the server is listening for requests.
   */
  public static void setPort(int a_Port)
  {
    Port = a_Port;
  }

  /**
   * Connect the given CORBA object to this ORB. After the object is connected,
   * it starts receiving remote invocations via this ORB.
   *
   * The ORB tries to connect the object to the port, that has been previously
   * set by {@link setPort(int)}. On failure, it tries 20 subsequent larger
   * values and then calls the parameterless server socked constructor to get
   * any free local port. If this fails, the {@link NO_RESOURCES} is thrown.
   *
   * @param object the object, must implement the {@link InvokeHandler})
   * interface.
   *
   * @throws BAD_PARAM if the object does not implement the
   * {@link InvokeHandler}).
   */
  public void connect(org.omg.CORBA.Object object)
  {
    int a_port = getFreePort();

    Connected_objects.cObject ref = connected_objects.add(object, a_port);
    IOR ior = createIOR(ref);
    prepareObject(object, ior);
    if (running)
      startService(ior);
  }

  /**
   * Connect the given CORBA object to this ORB, explicitly specifying the
   * object key.
   *
   * The ORB tries to connect the object to the port, that has been previously
   * set by {@link setPort(int)}. On failure, it tries 20 subsequent larger
   * values and then calls the parameterless server socked constructor to get
   * any free local port. If this fails, the {@link NO_RESOURCES} is thrown.
   *
   * @param object the object, must implement the {@link InvokeHandler})
   * interface.
   * @param key the object key, usually used to identify the object from remote
   * side.
   *
   * @throws BAD_PARAM if the object does not implement the
   * {@link InvokeHandler}).
   */
  public void connect(org.omg.CORBA.Object object, byte[] key)
  {
    int a_port = getFreePort();

    Connected_objects.cObject ref =
      connected_objects.add(key, object, a_port, null);
    IOR ior = createIOR(ref);
    prepareObject(object, ior);
    if (running)
      startService(ior);
  }

  /**
   * Connect the given CORBA object to this ORB, explicitly specifying the
   * object key and the identity of the thread (and port), where the object must
   * be served. The identity is normally the POA.
   *
   * The new port server will be started only if there is no one already running
   * for the same identity. Otherwise, the task of the existing port server will
   * be widened, including duty to serve the given object. All objects,
   * connected to a single identity by this method, will process they requests
   * subsequently in the same thread. The method is used when the expected
   * number of the objects is too large to have a single port and thread per
   * object. This method is used by POAs, having a single thread policy.
   *
   * @param object the object, must implement the {@link InvokeHandler})
   * interface.
   * @param key the object key, usually used to identify the object from remote
   * side.
   * @param port the port, where the object must be connected.
   *
   * @throws BAD_PARAM if the object does not implement the
   * {@link InvokeHandler}).
   */
  public void connect_1_thread(org.omg.CORBA.Object object, byte[] key,
    java.lang.Object identity
  )
  {
    sharedPortServer shared = (sharedPortServer) identities.get(identity);
    if (shared == null)
      {
        int a_port = getFreePort();
        shared = new sharedPortServer(a_port);
        identities.put(identity, shared);
        if (running)
          {
            portServers.add(shared);
            shared.start();
          }
      }

    Connected_objects.cObject ref =
      connected_objects.add(key, object, shared.s_port, identity);
    IOR ior = createIOR(ref);
    prepareObject(object, ior);
  }

  /**
   * Start the service on the given port of this IOR.
   *
   * @param ior the ior (only Internet.port is used).
   */
  public void startService(IOR ior)
  {
    portServer p = new portServer(ior.Internet.port);
    portServers.add(p);
    p.start();
  }

  /**
   * Destroy this server, releasing the occupied resources.
   */
  public void destroy()
  {
    portServer p;
    for (int i = 0; i < portServers.size(); i++)
      {
        p = (portServer) portServers.get(i);
        p.close_now();
      }
    super.destroy();
  }

  /**
   * Disconnect the given CORBA object from this ORB. The object will be no
   * longer receiving the remote invocations. In response to the remote
   * invocation on this object, the ORB will send the exception
   * {@link OBJECT_NOT_EXIST}. The object, however, is not destroyed and can
   * receive the local invocations.
   *
   * @param object the object to disconnect.
   */
  public void disconnect(org.omg.CORBA.Object object)
  {
    Connected_objects.cObject rmKey = null;

    // Handle the case when it is possible to get the object key.
    // Handle the case when the object is known, but not local.
    if (object instanceof ObjectImpl)
      {
        Delegate delegate = ((ObjectImpl) object)._get_delegate();
        if (delegate instanceof SimpleDelegate)
          {
            byte[] key = ((SimpleDelegate) delegate).getIor().key;
            rmKey = connected_objects.get(key);
          }
      }

    // Try to find and disconned the object that is not an instance of the
    // object implementation.
    if (rmKey == null)
      rmKey = connected_objects.getKey(object);
    if (rmKey != null)
      {
        // Find and stop the corresponding portServer.
        portServer p;
        StopService:
        for (int i = 0; i < portServers.size(); i++)
          {
            p = (portServer) portServers.get(i);
            if (p.s_port == rmKey.port && !(p instanceof sharedPortServer))
              {
                p.close_now();
                freed_ports.addFirst(new Integer(rmKey.port));
                break StopService;
              }
            connected_objects.remove(rmKey.key);
          }
      }
  }

  /**
   * Notifies ORB that the shared service indentity (usually POA) is destroyed.
   * The matching shared port server is terminated and the identity table entry
   * is deleted. If this identity is not known for this ORB, the method returns
   * without action.
   *
   * @param identity the identity that has been destroyed.
   */
  public void identityDestroyed(java.lang.Object identity)
  {
    if (identity == null)
      return;

    sharedPortServer ise = (sharedPortServer) identities.get(identity);
    if (ise != null)
      {
        synchronized (connected_objects)
          {
            ise.close_now();
            identities.remove(identity);

            Connected_objects.cObject obj;
            Map.Entry m;
            Iterator iter = connected_objects.entrySet().iterator();
            while (iter.hasNext())
              {
                m = (Map.Entry) iter.next();
                obj = (Connected_objects.cObject) m.getValue();
                if (obj.identity == identity)
                  iter.remove();
              }
          }
      }
  }

  /**
   * Find the local object, connected to this ORB.
   *
   * @param ior the ior of the potentially local object.
   *
   * @return the local object, represented by the given IOR, or null if this is
   * not a local connected object.
   */
  public org.omg.CORBA.Object find_local_object(IOR ior)
  {
    // Must be the same host.
    if (!ior.Internet.host.equals(LOCAL_HOST))
      return null;

    return find_connected_object(ior.key, ior.Internet.port);
  }

  /**
   * List the initially available CORBA objects (services).
   *
   * @return a list of services.
   *
   * @see resolve_initial_references(String)
   */
  public String[] list_initial_services()
  {
    String[] refs = new String[ initial_references.size() ];
    int p = 0;

    Iterator iter = initial_references.keySet().iterator();
    while (iter.hasNext())
      {
        refs [ p++ ] = (String) iter.next();
      }
    return refs;
  }

  /**
   * Get the IOR reference string for the given object. The string embeds
   * information about the object repository Id, its access key and the server
   * internet address and port. With this information, the object can be found
   * by another ORB, possibly located on remote computer.
   *
   * @param forObject CORBA object
   * @return the object IOR representation.
   *
   * @throws BAD_PARAM if the object has not been previously connected to this
   * ORB.
   *
   * @throws BAD_OPERATION in the unlikely case if the local host address cannot
   * be resolved.
   *
   * @see string_to_object(String)
   */
  public String object_to_string(org.omg.CORBA.Object forObject)
  {
    // Handle the case when the object is known, but not local.
    if (forObject instanceof ObjectImpl)
      {
        Delegate delegate = ((ObjectImpl) forObject)._get_delegate();
        if (delegate instanceof SimpleDelegate)
          return ((SimpleDelegate) delegate).getIor().toStringifiedReference();
      }

    // Handle the case when the object is local.
    Connected_objects.cObject rec = connected_objects.getKey(forObject);

    if (rec == null)
      throw new BAD_PARAM("The object " + forObject +
        " has not been previously connected to this ORB"
      );

    IOR ior = createIOR(rec);

    return ior.toStringifiedReference();
  }

  /**
   * Get the local IOR for the given object, null if the object is not local.
   */
  public IOR getLocalIor(org.omg.CORBA.Object forObject)
  {
    Connected_objects.cObject rec = connected_objects.getKey(forObject);
    if (rec == null)
      return null;
    else
      return createIOR(rec);
  }

  /**
   * Find and return the easily accessible CORBA object, addressed by name.
   *
   * @param name the object name.
   * @return the object
   *
   * @throws org.omg.CORBA.ORBPackage.InvalidName if the given name is not
   * associated with the known object.
   */
  public org.omg.CORBA.Object resolve_initial_references(String name)
    throws InvalidName
  {
    org.omg.CORBA.Object object = null;
    try
      {
        object = (org.omg.CORBA.Object) initial_references.get(name);
        if (object == null && name.equals(NAME_SERVICE))
          {
            object = getDefaultNameService();
            if (object != null)
              initial_references.put(NAME_SERVICE, object);
          }
      }
    catch (Exception ex)
      {
        InvalidName err = new InvalidName(name);
        err.initCause(ex);
        throw err;
      }
    if (object != null)
      return object;
    else
      throw new InvalidName("Not found: '" + name + "'");
  }

  /**
   * Start the ORBs main working cycle (receive invocation - invoke on the local
   * object - send response - wait for another invocation). The method only
   * returns after calling {@link #shutdown(boolean)}.
   */
  public void run()
  {
    CollocatedOrbs.registerOrb(this);
    try
      {
        running = true;

        // Instantiate the port server for each socket.
        Iterator iter = connected_objects.entrySet().iterator();
        Map.Entry m;
        Connected_objects.cObject obj;

        while (iter.hasNext())
          {
            m = (Map.Entry) iter.next();
            obj = (Connected_objects.cObject) m.getValue();

            portServer subserver;

            if (obj.identity == null)
              {
                subserver = new portServer(obj.port);
                portServers.add(subserver);
              }
            else
              subserver = (portServer) identities.get(obj.identity);

            if (! subserver.isAlive())
              {
                // Reuse the current thread for the last portServer.
                if (! iter.hasNext())
                  {
                    // Discard the iterator, eliminating lock checks.
                    iter = null;
                    subserver.run();
                    return;
                  }
                else
                  subserver.start();
              }
          }
      }
    finally
      {
        CollocatedOrbs.unregisterOrb(this);
      }
  }

  /**
   * Start the server in a new thread, if not already running. This method is
   * used to ensure that the objects being transfered will be served from the
   * remote side, if required. If the ORB is started using this method, it
   * starts as a daemon thread.
   */
  public void ensureRunning()
  {
    final OrbFunctional THIS = this;

    if (!running)
      {
        Thread t = new Thread()
        {
          public void run()
          {
            THIS.run();
          }
        };
        t.setDaemon(true);
        t.start();
      }
  }

  /**
   * Shutdown the ORB server.
   *
   * @param wait_for_completion if true, the current thread is suspended until
   * the shutdown process is complete.
   */
  public void shutdown(boolean wait_for_completion)
  {
    super.shutdown(wait_for_completion);
    running = false;

    if (!wait_for_completion)
      {
        for (int i = 0; i < portServers.size(); i++)
          {
            portServer p = (portServer) portServers.get(i);
            p.close_now();
          }
      }
  }

  /**
   * Find and return the CORBA object, addressed by the given IOR string
   * representation. The object can (an usually is) located on a remote
   * computer, possibly running a different (not necessary java) CORBA
   * implementation.
   *
   * @param an_ior the object IOR representation string.
   *
   * @return the found CORBA object.
   * @see object_to_string(org.omg.CORBA.Object)
   */
  public org.omg.CORBA.Object string_to_object(String an_ior)
  {
    return nameParser.corbaloc(an_ior, this);
  }

  /**
   * Convert ior reference to CORBA object.
   */
  public org.omg.CORBA.Object ior_to_object(IOR ior)
  {
    org.omg.CORBA.Object object = find_local_object(ior);
    if (object == null)
      {
        // Check maybe the local object on another ORB, but same VM.
        object = CollocatedOrbs.searchLocalObject(ior);
        if (object == null)
          {
            // Surely remote object.
            ObjectImpl impl = StubLocator.search(this, ior);
            try
              {
                if (impl._get_delegate() == null)
                  impl._set_delegate(new IorDelegate(this, ior));
              }
            catch (BAD_OPERATION ex)
              {
                // Some colaborants may throw this exception
                // in response to the attempt to get the unset delegate.
                impl._set_delegate(new IorDelegate(this, ior));
              }

            object = impl;
          }
      }
    return object;
  }

  /**
   * Get the default naming service for the case when there no NameService
   * entries.
   */
  protected org.omg.CORBA.Object getDefaultNameService()
  {
    if (initial_references.containsKey(NAME_SERVICE))
      return (org.omg.CORBA.Object) initial_references.get(NAME_SERVICE);

    IOR ior = new IOR();
    ior.Id = NamingContextExtHelper.id();
    ior.Internet.host = ns_host;
    ior.Internet.port = ns_port;
    ior.key = NamingServiceTransient.getDefaultKey();

    IorObject iorc = new IorObject(this, ior);
    NamingContextExt namer = NamingContextExtHelper.narrow(iorc);
    initial_references.put(NAME_SERVICE, namer);
    return namer;
  }

  /**
   * Find and return the object, that must be previously connected to this ORB.
   * Return null if no such object is available.
   *
   * @param key the object key.
   * @param port the port where the object is connected.
   *
   * @return the connected object, null if none.
   */
  protected org.omg.CORBA.Object find_connected_object(byte[] key, int port)
  {
    Connected_objects.cObject ref = connected_objects.get(key);
    if (ref == null)
      return null;
    if (port >= 0 && ref.port != port)
      return null;
    else
      return ref.object;
  }

  /**
   * Set the ORB parameters. This method is normally called from
   * {@link #init(Applet, Properties)}.
   *
   * @param app the current applet.
   *
   * @param props application specific properties, passed as the second
   * parameter in {@link #init(Applet, Properties)}. Can be <code>null</code>.
   */
  protected void set_parameters(Applet app, Properties props)
  {
    useProperties(props);

    String[][] para = app.getParameterInfo();
    if (para != null)
      {
        for (int i = 0; i < para.length; i++)
          {
            if (para[i][0].equals(LISTEN_ON))
              Port = Integer.parseInt(para[i][1]);
            if (para[i][0].equals(REFERENCE))
              {
                StringTokenizer st = new StringTokenizer(para[i][1], "=");
                initial_references.put(st.nextToken(),
                  string_to_object(st.nextToken()));
              }

            if (para[i][0].equals(ORB_ID))
              orb_id = para[i][1];

            if (para[i][0].equals(SERVER_ID))
              server_id = para[i][1];

            if (para[i][0].equals(NS_HOST))
              ns_host = para[i][1];
            if (para[i][0].equals(START_READING_MESSAGE))
              TOUT_START_READING_MESSAGE = Integer.parseInt(para[i][1]);
            if (para[i][0].equals(WHILE_READING))
              TOUT_WHILE_READING = Integer.parseInt(para[i][1]);
            if (para[i][0].equals(AFTER_RECEIVING))
              TOUT_AFTER_RECEIVING = Integer.parseInt(para[i][1]);
            try
              {
                if (para[i][0].equals(NS_PORT))
                  ns_port = Integer.parseInt(para[i][1]);
              }
            catch (NumberFormatException ex)
              {
                BAD_PARAM bad = new BAD_PARAM("Invalid " + NS_PORT
                  + "property, unable to parse '" + props.getProperty(NS_PORT)
                  + "'");
                bad.initCause(ex);
                throw bad;
              }
          }
      }
  }

  /**
   * Set the ORB parameters. This method is normally called from
   * {@link #init(String[], Properties)}.
   *
   * @param para the parameters, that were passed as the parameters to the
   * <code>main(String[] args)</code> method of the current standalone
   * application.
   *
   * @param props application specific properties that were passed as a second
   * parameter in {@link init(String[], Properties)}). Can be <code>null</code>.
   */
  protected void set_parameters(String[] para, Properties props)
  {
    if ((para != null) && para.length > 1)
      {
        for (int i = 0; i < para.length - 1; i++)
          {
            if (para[i].endsWith("ListenOn"))
              Port = Integer.parseInt(para[i + 1]);
            if (para[i].endsWith("ORBInitRef"))
              {
                StringTokenizer st = new StringTokenizer(para[i + 1], "=");
                initial_references.put(st.nextToken(),
                  string_to_object(st.nextToken()));
              }

            if (para[i].endsWith("ORBInitialHost"))
              ns_host = para[i + 1];

            if (para[i].endsWith("ServerId"))
              server_id = para[i++];
            else if (para[i].endsWith("ORBid"))
              orb_id = para[i++];

            try
              {
                if (para[i].endsWith("ORBInitialPort"))
                  ns_port = Integer.parseInt(para[i + 1]);
              }
            catch (NumberFormatException ex)
              {
                throw new BAD_PARAM("Invalid " + para[i]
                  + "parameter, unable to parse '"
                  + props.getProperty(para[i + 1]) + "'");
              }
          }
      }

    useProperties(props);
  }

  /**
   * Create IOR for the given object references.
   */
  protected IOR createIOR(Connected_objects.cObject ref)
    throws BAD_OPERATION
  {
    IOR ior = new IOR();
    ior.key = ref.key;
    ior.Internet.port = ref.port;

    if (ref.object instanceof ObjectImpl)
      {
        ObjectImpl imp = (ObjectImpl) ref.object;
        if (imp._ids().length > 0)
          ior.Id = imp._ids() [ 0 ];
      }
    if (ior.Id == null)
      ior.Id = ref.object.getClass().getName();

    ior.Internet.host = CollocatedOrbs.localHost;
    ior.Internet.port = ref.port;

    return ior;
  }

  /**
   * Prepare object for connecting it to this ORB.
   *
   * @param object the object being connected.
   *
   * @throws BAD_PARAM if the object does not implement the
   * {@link InvokeHandler}).
   */
  protected void prepareObject(org.omg.CORBA.Object object, IOR ior)
    throws BAD_PARAM
  {
    /*
     * if (!(object instanceof InvokeHandler)) throw new
     * BAD_PARAM(object.getClass().getName() + " does not implement
     * InvokeHandler. " );
     */

    // If no delegate is set, set the default delegate.
    if (object instanceof ObjectImpl)
      {
        ObjectImpl impl = (ObjectImpl) object;
        try
          {
            if (impl._get_delegate() == null)
              impl._set_delegate(new SimpleDelegate(this, ior));
          }
        catch (BAD_OPERATION ex)
          {
            // Some colaborants may throw this exception.
            impl._set_delegate(new SimpleDelegate(this, ior));
          }
      }
  }

  /**
   * Write the response message.
   *
   * @param net_out the stream to write response into
   * @param msh_request the request message header
   * @param rh_request the request header
   * @param handler the invocation handler that has been used to invoke the
   * operation
   * @param sysEx the system exception, thrown during the invocation, null if
   * none.
   *
   * @throws IOException
   */
  private void respond_to_client(OutputStream net_out,
    MessageHeader msh_request, RequestHeader rh_request,
    ResponseHandlerImpl handler, SystemException sysEx
  ) throws IOException
  {
    // Set the reply header properties.
    ReplyHeader reply = handler.reply_header;

    if (sysEx != null)
      reply.reply_status = ReplyHeader.SYSTEM_EXCEPTION;
    else if (handler.isExceptionReply())
      reply.reply_status = ReplyHeader.USER_EXCEPTION;
    else
      reply.reply_status = ReplyHeader.NO_EXCEPTION;
    reply.request_id = rh_request.request_id;

    BufferedCdrOutput out =
      new BufferedCdrOutput(50 + handler.getBuffer().buffer.size());
    out.setOrb(this);

    out.setOffset(msh_request.getHeaderSize());

    reply.write(out);

    if (msh_request.version.since_inclusive(1, 2))
      {
        out.align(8);

        // Write the reply data from the handler. The handler data already
        // include the necessary heading zeroes for alignment.
      }
    handler.getBuffer().buffer.writeTo(out);

    MessageHeader msh_reply = new MessageHeader();

    msh_reply.version = msh_request.version;
    msh_reply.message_type = MessageHeader.REPLY;
    msh_reply.message_size = out.buffer.size();

    // Write the reply.
    msh_reply.write(net_out);
    out.buffer.writeTo(net_out);
    net_out.flush();
  }

  /**
   * Forward request to another target, as indicated by the passed exception.
   */
  private void forward_request(OutputStream net_out,
    MessageHeader msh_request, RequestHeader rh_request, gnuForwardRequest info
  ) throws IOException
  {
    MessageHeader msh_forward = new MessageHeader();
    msh_forward.version = msh_request.version;

    ReplyHeader rh_forward = msh_forward.create_reply_header();
    msh_forward.message_type = MessageHeader.REPLY;
    rh_forward.reply_status = info.forwarding_code;
    rh_forward.request_id = rh_request.request_id;

    // The forwarding code is either LOCATION_FORWARD or LOCATION_FORWARD_PERM.
    BufferedCdrOutput out = new BufferedCdrOutput();
    out.setOrb(this);
    out.setOffset(msh_forward.getHeaderSize());

    rh_forward.write(out);

    if (msh_forward.version.since_inclusive(1, 2))
      out.align(8);
    out.write_Object(info.forward_reference);

    msh_forward.message_size = out.buffer.size();

    // Write the forwarding instruction.
    msh_forward.write(net_out);
    out.buffer.writeTo(net_out);
    net_out.flush();
  }

  /**
   * Contains a single servicing task.
   *
   * Normally, each task matches a single remote invocation. However under
   * frequent tandem submissions the same task may span over several
   * invocations.
   *
   * @param serverSocket the ORB server socket.
   *
   * @throws MARSHAL
   * @throws IOException
   */
  void serve(final portServer p, ServerSocket serverSocket)
    throws MARSHAL, IOException
  {
    final Socket service;
    service = serverSocket.accept();

    // Tell the server there are no more resources.
    if (p.running_threads >= MAX_RUNNING_THREADS)
      {
        serveStep(service, true);
        return;
      }

    new Thread()
      {
        public void run()
        {
          try
            {
              synchronized (p)
                {
                  p.running_threads++;
                }
              serveStep(service, false);
            }
          finally
            {
              synchronized (p)
                {
                  p.running_threads--;
                }
            }
        }
      }.start();
  }

  /**
   * A single servicing step, when the client socket is alrady open.
   *
   * Normally, each task matches a single remote invocation. However under
   * frequent tandem submissions the same task may span over several
   * invocations.
   *
   * @param service the opened client socket.
   * @param no_resources if true, the "NO RESOURCES" exception is thrown to the
   * client.
   */
  void serveStep(Socket service, boolean no_resources)
  {
    try
      {
        Serving: while (true)
          {
            InputStream in = service.getInputStream();
            service.setSoTimeout(TOUT_START_READING_MESSAGE);

            MessageHeader msh_request = new MessageHeader();

            try
              {
                msh_request.read(in);
              }
            catch (MARSHAL ex)
              {
                // This exception may be thrown due closing the connection.
                return;
              }

            if (max_version != null)
              {
                if (!msh_request.version.until_inclusive(max_version.major,
                  max_version.minor))
                  {
                    OutputStream out = service.getOutputStream();
                    new ErrorMessage(max_version).write(out);
                    return;
                  }
              }

            byte[] r = msh_request.readMessage(in, service, TOUT_WHILE_READING,
              TOUT_AFTER_RECEIVING);

            if (msh_request.message_type == MessageHeader.REQUEST)
              {
                RequestHeader rh_request;

                BufferredCdrInput cin = new BufferredCdrInput(r);
                cin.setOrb(this);
                cin.setVersion(msh_request.version);
                cin.setOffset(msh_request.getHeaderSize());
                cin.setBigEndian(msh_request.isBigEndian());

                rh_request = msh_request.create_request_header();

                // Read header and auto set the charset.
                rh_request.read(cin);

                // in 1.2 and higher, align the current position at
                // 8 octet boundary.
                if (msh_request.version.since_inclusive(1, 2))
                  {
                    cin.align(8);

                    // find the target object.
                  }

                InvokeHandler target = (InvokeHandler) find_connected_object(
                  rh_request.object_key, -1);

                // Prepare the reply header. This must be done in advance,
                // as the size must be known for handler to set alignments
                // correctly.
                ReplyHeader rh_reply = msh_request.create_reply_header();

                // TODO log errors about not existing objects and methods.
                ResponseHandlerImpl handler = new ResponseHandlerImpl(
                  this, msh_request, rh_reply, rh_request);

                SystemException sysEx = null;

                try
                  {
                    if (no_resources)
                      {
                        NO_RESOURCES no = new NO_RESOURCES("Too many parallel calls");
                        no.minor = Minor.Threads;
                        throw no;
                      }
                    if (target == null)
                      throw new OBJECT_NOT_EXIST();
                    target._invoke(rh_request.operation, cin, handler);
                  }
                catch (gnuForwardRequest forwarded)
                  {
                    OutputStream sou = service.getOutputStream();
                    forward_request(sou, msh_request, rh_request, forwarded);
                    if (service != null && !service.isClosed())
                      {
                        // Wait for the subsequent invocations on the
                        // same socket for the TANDEM_REQUEST duration.
                        service.setSoTimeout(TANDEM_REQUESTS);
                        continue Serving;
                      }
                  }
                catch (UnknownException uex)
                  {
                    sysEx = new UNKNOWN("Unknown", 2,
                      CompletionStatus.COMPLETED_MAYBE);
                    sysEx.initCause(uex.originalEx);

                    org.omg.CORBA.portable.OutputStream ech = handler.createExceptionReply();

                    rh_reply.service_context = UnknownExceptionCtxHandler.addExceptionContext(
                      rh_reply.service_context, uex.originalEx, ech);

                    ObjectCreator.writeSystemException(ech, sysEx);
                  }
                catch (SystemException ex)
                  {
                    sysEx = ex;

                    org.omg.CORBA.portable.OutputStream ech = handler.createExceptionReply();

                    rh_reply.service_context = UnknownExceptionCtxHandler.addExceptionContext(
                      rh_reply.service_context, ex, ech);

                    ObjectCreator.writeSystemException(ech, ex);
                  }
                catch (Exception except)
                  {
                    // This should never happen under normal operation and
                    // can only indicate errors in user object implementation.
                    // We inform the user.
                    except.printStackTrace();

                    sysEx = new UNKNOWN("Unknown", 2,
                      CompletionStatus.COMPLETED_MAYBE);
                    sysEx.initCause(except);

                    org.omg.CORBA.portable.OutputStream ech = handler.createExceptionReply();

                    rh_reply.service_context = UnknownExceptionCtxHandler.addExceptionContext(
                      rh_reply.service_context, except, ech);

                    ObjectCreator.writeSystemException(ech, sysEx);
                  }

                // Write the response.
                if (rh_request.isResponseExpected())
                  {
                    OutputStream sou = service.getOutputStream();
                    respond_to_client(sou, msh_request, rh_request, handler,
                      sysEx);
                  }
              }
            else if (msh_request.message_type == MessageHeader.CLOSE_CONNECTION
              || msh_request.message_type == MessageHeader.MESSAGE_ERROR)
              {
                CloseMessage.close(service.getOutputStream());
                service.close();
                return;
              }

            if (service != null && !service.isClosed())

              // Wait for the subsequent invocations on the
              // same socket for the TANDEM_REQUEST duration.
              service.setSoTimeout(TANDEM_REQUESTS);
            else
              return;
          }
      }
    catch (SocketException ex)
      {
        // OK.
        return;
      }
    catch (IOException ioex)
      {
        // Network error, probably transient.
        // TODO log it.
        return;
      }
    finally
      {
        try
          {
            if (service!=null && !service.isClosed())
              service.close();
          }
        catch (IOException ioex)
          {
            // OK.
          }
      }
  }

  /**
   * Set the ORB parameters from the properties that were accumulated
   * from several locations.
   */
  protected void useProperties(Properties props)
  {
    if (props != null)
      {
        if (props.containsKey(LISTEN_ON))
          Port = Integer.parseInt(props.getProperty(LISTEN_ON));
        if (props.containsKey(NS_HOST))
          ns_host = props.getProperty(NS_HOST);
        try
          {
            if (props.containsKey(NS_PORT))
              ns_port = Integer.parseInt(props.getProperty(NS_PORT));
            if (props.containsKey(START_READING_MESSAGE))
              TOUT_START_READING_MESSAGE =
                Integer.parseInt(props.getProperty(START_READING_MESSAGE));
            if (props.containsKey(WHILE_READING))
              TOUT_WHILE_READING =
                Integer.parseInt(props.getProperty(WHILE_READING));
            if (props.containsKey(AFTER_RECEIVING))
              TOUT_AFTER_RECEIVING =
                Integer.parseInt(props.getProperty(AFTER_RECEIVING));
            if (props.containsKey(SERVER_ERROR_PAUSE))
              TWAIT_SERVER_ERROR_PAUSE =
                Integer.parseInt(props.getProperty(SERVER_ERROR_PAUSE));
          }
        catch (NumberFormatException ex)
          {
            throw new BAD_PARAM("Invalid " + NS_PORT +
              "property, unable to parse '" + props.getProperty(NS_PORT) +
              "'"
            );
          }

        if (props.containsKey(SocketFactory.PROPERTY))
          {
            String factory = null;
            try
              {
                factory = props.getProperty(SocketFactory.PROPERTY);
                if (factory!=null)
                  socketFactory = (SocketFactory)
                    ObjectCreator.forName(factory).newInstance();
              }
            catch (Exception ex)
              {
                BAD_PARAM p = new BAD_PARAM("Bad socket factory "+factory);
                p.initCause(ex);
                throw p;
              }
          }

        if (props.containsKey(ORB_ID))
          orb_id = props.getProperty(ORB_ID);

        if (props.containsKey(SERVER_ID))
          server_id = props.getProperty(SERVER_ID);

        Enumeration en = props.elements();
        while (en.hasMoreElements())
          {
            String item = (String) en.nextElement();
            if (item.equals(REFERENCE))
              initial_references.put(item,
                string_to_object(props.getProperty(item))
              );
          }
      }
  }

  /**
   * Get the next instance with a response being received. If all currently sent
   * responses not yet processed, this method pauses till at least one of them
   * is complete. If there are no requests currently sent, the method pauses
   * till some request is submitted and the response is received. This strategy
   * is identical to the one accepted by Suns 1.4 ORB implementation.
   *
   * The returned response is removed from the list of the currently submitted
   * responses and is never returned again.
   *
   * @return the previously sent request that now contains the received
   * response.
   *
   * @throws WrongTransaction If the method was called from the transaction
   * scope different than the one, used to send the request. The exception can
   * be raised only if the request is implicitly associated with some particular
   * transaction.
   */
  public Request get_next_response() throws org.omg.CORBA.WrongTransaction
  {
    return asynchron.get_next_response();
  }

  /**
   * Find if any of the requests that have been previously sent with
   * {@link #send_multiple_requests_deferred}, have a response yet.
   *
   * @return true if there is at least one response to the previously sent
   * request, false otherwise.
   */
  public boolean poll_next_response()
  {
    return asynchron.poll_next_response();
  }

  /**
   * Send multiple prepared requests expecting to get a reply. All requests are
   * send in parallel, each in its own separate thread. When the reply arrives,
   * it is stored in the agreed fields of the corresponing request data
   * structure. If this method is called repeatedly, the new requests are added
   * to the set of the currently sent requests, but the old set is not
   * discarded.
   *
   * @param requests the prepared array of requests.
   *
   * @see #poll_next_response()
   * @see #get_next_response()
   * @see Request#send_deferred()
   */
  public void send_multiple_requests_deferred(Request[] requests)
  {
    asynchron.send_multiple_requests_deferred(requests);
  }

  /**
   * Send multiple prepared requests one way, do not caring about the answer.
   * The messages, containing requests, will be marked, indicating that the
   * sender is not expecting to get a reply.
   *
   * @param requests the prepared array of requests.
   *
   * @see Request#send_oneway()
   */
  public void send_multiple_requests_oneway(Request[] requests)
  {
    asynchron.send_multiple_requests_oneway(requests);
  }

  /**
   * Set the flag, forcing all server threads to terminate.
   */
  protected void finalize() throws java.lang.Throwable
  {
    running = false;
    super.finalize();
  }

  /**
   * Get the number of objects that are connected to this ORB.
   *
   * @return the number of objects, connected to this ORB.
   */
  public int countConnectedObjects()
  {
    return connected_objects.size();
  }
}
