/* gnuServantObject.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 gnu.CORBA.GIOP.ReplyHeader;
import gnu.CORBA.IorDelegate;
import gnu.CORBA.IorObject;
import gnu.CORBA.Interceptor.gnuServerRequestInfo;
import gnu.CORBA.typecodes.RecordTypeCode;
import gnu.CORBA.IOR;
import gnu.CORBA.IorProvider;
import gnu.CORBA.Minor;
import gnu.CORBA.ObjectCreator;
import gnu.CORBA.Unexpected;
import gnu.CORBA.ResponseHandlerImpl;
import gnu.CORBA.StreamHolder;

import gnu.java.lang.CPStringBuilder;

import org.omg.CORBA.Any;
import org.omg.CORBA.BAD_OPERATION;
import org.omg.CORBA.BAD_PARAM;
import org.omg.CORBA.CompletionStatus;
import org.omg.CORBA.OBJECT_NOT_EXIST;
import org.omg.CORBA.OBJ_ADAPTER;
import org.omg.CORBA.ORB;
import org.omg.CORBA.SystemException;
import org.omg.CORBA.TCKind;
import org.omg.CORBA.TRANSIENT;
import org.omg.CORBA.UserException;
import org.omg.CORBA.portable.InputStream;
import org.omg.CORBA.portable.InvokeHandler;
import org.omg.CORBA.portable.ObjectImpl;
import org.omg.CORBA.portable.OutputStream;
import org.omg.CORBA.portable.ResponseHandler;
import org.omg.PortableInterceptor.ForwardRequest;
import org.omg.PortableInterceptor.ServerRequestInterceptorOperations;
import org.omg.PortableServer.CurrentOperations;
import org.omg.PortableServer.DynamicImplementation;
import org.omg.PortableServer.ImplicitActivationPolicyValue;
import org.omg.PortableServer.POA;
import org.omg.PortableServer.POAManager;
import org.omg.PortableServer.POAManagerPackage.State;
import org.omg.PortableServer.Servant;
import org.omg.PortableServer.ServantLocatorPackage.CookieHolder;
import org.omg.PortableServer.ServantRetentionPolicyValue;
import org.omg.PortableServer.portable.Delegate;

import java.io.IOException;

import java.util.Arrays;

/**
 * Represents a CORBA object, being locally served by the associated servant.
 * The calls to the object are forwarded to the calls to the servant.
 *
 * @author Audrius Meskauskas, Lithuania (AudriusA@Bioinformatics.org)
 */
public class gnuServantObject extends ObjectImpl
  implements org.omg.CORBA.Object,
    InvokeHandler,
    CurrentOperations,
    IorProvider
{
  /**
   * The associated servant that must also implement the {@link InvokeHandler}
       * interface. This value can be temporary null if the object was created using
   * POA.create_reference or POA.create_reference_with_id, private to force
   * always to use {@link setServant}.
   */
  private Servant servant;

  /**
   * The Id of this object.
   */
  public final byte[] Id;

  /**
   * The poa that takes care about this object.
   */
  public final gnuPOA poa;

  /**
   * The POA manager, used to control the work of this object.
   */
  public final POAManager manager;

  /**
   * The orb.
   */
  public final ORB_1_4 orb;

  /**
   * The object repository ids, if they were specified separately. Normally, the
   * ids are requested from the servant.
   */
  public final String[] repository_ids;

  /**
   * True indicates that the NO_RETAIN policy applies for the servant.
   * The servant must be discarded after the each call.
   */
  boolean noRetain;

  /**
   * Create an object with no connected servant. The servant must be set later.
   *
   * @param a_repository_ids an array of repository ids, can be null (then ids
   * will be requested from the servant).
   * @param an_id the object id.
   * @param a_poa the POA.
   */
  public gnuServantObject(String[] a_repository_ids, byte[] an_id,
    gnuPOA a_poa, ORB_1_4 an_orb
  )
  {
    repository_ids = a_repository_ids;
    Id = an_id;
    manager = a_poa.the_POAManager();
    poa = a_poa;
    orb = an_orb;

    noRetain = poa.applies(ServantRetentionPolicyValue.NON_RETAIN);
  }

  /**
   * Get the IOR as it would be for this object.
   */
  public IOR getIor()
  {
    return orb.getLocalIor(this);
  }

  /**
   * Create a servant object, associated with the passed servant.
   *
   * @param a_servant a servant, serving this object.
   * @param an_id an Object Id for this object.
   *
   * @throws BAD_PARAM if the passed servant is not an {@link InvokeHandler}.
   */
  public gnuServantObject(Servant a_servant, byte[] an_id, ORB_1_4 an_orb,
    gnuPOA a_poa
  )
  {
    Id = an_id;
    setServant(a_servant);
    poa = a_poa;
    if (poa != null)
      {
        manager = poa.the_POAManager();
      }
    else
      {
        manager = null;
      }
    repository_ids = null;
    orb = an_orb;

    noRetain = poa != null && poa.applies(ServantRetentionPolicyValue.NON_RETAIN);
  }

  /**
   * Set a servant, if it has not been previously set.
   *
   * @param a_servant a servant to set, can be null to indicate the necessity
   * for the subsequent activation.
   *
   * @throws BAD_PARAM if the passed servant is not an {@link InvokeHandler} or
   * {@link DynamicImplementation} and also not null.
   */
  public void setServant(Servant a_servant)
  {
    if (a_servant != null &&
      !(a_servant instanceof InvokeHandler) &&
      !(a_servant instanceof DynamicImplementation)
    )
      {
        throw new BAD_PARAM("Must be either InvokeHandler or " +
          "DynamicImplementation, but is " + a_servant
        );
      }
    servant = a_servant;
  }

  /**
   * Returns the associated servant.
   */
  public Servant getServant()
  {
    return servant;
  }

  /**
   * Return the associated invocation handler.
   */
  public InvokeHandler getHandler(String operation, CookieHolder cookie,
    boolean forwarding_allowed
  ) throws gnuForwardRequest
  {
    if (servant != null && !noRetain)
      {
        return servantToHandler(servant);
      }
    else
      {
        // Use servant locator to locate the servant.
        if (poa.servant_locator != null)
          {
            try
              {
                servant =
                  poa.servant_locator.preinvoke(Id, poa, operation, cookie);
                return servantToHandler(servant);
              }
            catch (org.omg.PortableServer.ForwardRequest forw_ex)
              {
                if (forwarding_allowed)
                  {
                    throw new gnuForwardRequest(forw_ex.forward_reference);
                  }
                else
                  {
                    servant =
                      ForwardedServant.create(forw_ex.forward_reference);
                    return servantToHandler(servant);
                  }
              }
          }
        else
        // Use servant activator to locate the servant.
        if (poa.applies(ImplicitActivationPolicyValue.IMPLICIT_ACTIVATION) &&
          poa.applies(ServantRetentionPolicyValue.RETAIN)
        )
          {
            try
              {
                poa.activate_object_with_id(Id, servant, forwarding_allowed);
                servant = poa.id_to_servant(Id);
                return servantToHandler(servant);
              }
            catch (gnuForwardRequest forwarded)
              {
                throw forwarded;
              }
            catch (Exception ex)
              {
                BAD_OPERATION bad =
                  new BAD_OPERATION("Unable to activate", Minor.Activation,
                    CompletionStatus.COMPLETED_NO
                  );
                bad.initCause(ex);
                throw bad;
              }
          }
        else if (poa.default_servant != null)
          {
            servant = poa.default_servant;
            return servantToHandler(servant);
          }

        // No servant and no servant manager - throw exception.
        else
          {
            throw new BAD_OPERATION("Unable to activate", Minor.Activation,
              CompletionStatus.COMPLETED_NO
            );
          }
      }
  }

  /**
   * Convert the servant to invocation handler.
   */
  public InvokeHandler servantToHandler(Servant a_servant)
  {
    if (a_servant instanceof InvokeHandler)
      {
        return (InvokeHandler) a_servant;
      }
    else if (a_servant instanceof DynamicImplementation)
      {
        return new DynamicImpHandler((DynamicImplementation) a_servant);
      }
    else
      {
        throw new BAD_OPERATION(a_servant +
          " must be either InvokeHandler or " + "POA DynamicImplementation"
        );
      }
  }

  /**
   * Create a servant object, associated with the passed servant. Requests the
   * object id from the servant. Depending on the policies of the servants POA,
   * the calls are eithe not synchronized or synchronized on POA or ORB.
   *
   * @param a_servant a servant, serving this object.
   * @param an_id an Object Id for this object.
   */
  public gnuServantObject(Servant a_servant, gnuPOA a_poa)
  {
    this(a_servant, a_servant._object_id(), (ORB_1_4) a_servant._orb(), a_poa);
  }

  /**
   * Delegates call to servant, passing the poa and Id.
   */
  public String[] _ids()
  {
    if (repository_ids == null)
      {
        return getServant()._all_interfaces(poa, Id);
      }
    else
      {
        return repository_ids;
      }
  }

  /**
   * Gets a string representation.
   */
  public String toString()
  {
    CPStringBuilder b = new CPStringBuilder("Servant object (");
    for (int i = 0; i < Id.length; i++)
      {
        b.append(Integer.toHexString(Id [ i ] & 0xFF));
        b.append(' ');
      }
    b.append(')');
    return b.toString();
  }

  /**
   * Always returns true.
   */
  public boolean _is_local()
  {
    return true;
  }

  /**
   * Check if this object could be named by the given repository id.
   *
   * @param idl_id the repository id to check.
   *
   * @return true if it is one of the possible repository ids of this object.
   */
  public boolean _is_a(String idl_id)
  {
    String[] maybe = _ids();
    for (int i = 0; i < maybe.length; i++)
      {
        if (maybe [ i ].equals(idl_id))
          {
            return true;
          }
      }
    return false;
  }

  /**
   * Get an ORB, associated with the servant of this object.
   *
   * @return
   */
  public ORB _orb()
  {
    return getServant()._orb();
  }

  /**
   * Handle the invocation (delegates to servant).
   *
   * @throws TRANSIENT minor 0x535503e9 if the POA is in discarding mode.
   * @throws OBJ_ADAPTER minor 0x535503ea if the POA is inactivated.
   * @throws OBJECT_NOT_EXISTS minor 0x535503ec if this object is inactivated.
   *
   * @specnote see {@link POAManagerOperations} for specnotes about the minor
   * codes.
   */
  public OutputStream _invoke(String method, InputStream input,
    ResponseHandler r_handler
  ) throws SystemException
  {
    boolean intercept = false;
    ServerRequestInterceptorOperations interceptor = null;
    gnuServerRequestInfo info = null;
    ResponseHandlerImpl i_handler = null;

    try
      {
        if (orb.iServer != null &&
          r_handler instanceof ResponseHandlerImpl
        )
          {
            interceptor = orb.iServer;

            i_handler = (ResponseHandlerImpl) r_handler;

            info =
              new gnuServerRequestInfo(this, i_handler.request_header,
                i_handler.reply_header
              );
            intercept = true;

            interceptor.receive_request_service_contexts(info);
          }

        try
          {
            CookieHolder cookie = null;
            AOM.Obj self = poa.aom.get(Id);

            if (poa.servant_locator != null)
              {
                // If the servant locator is in use, it is always responsible
                // for providing the servant.
                self.servant = servant = null;
                cookie = new CookieHolder();
              }
            else if (self != null && self.isDeactiveted())
              {
                if (poa.applies(
                    ImplicitActivationPolicyValue.IMPLICIT_ACTIVATION
                  ) &&
                  poa.servant_activator != null
                )
                  {
                    // Reset the servant, forcing the subsequent activation.
                    servant = null;
                  }
                else
                  {
                    throw new OBJECT_NOT_EXIST("Object deactivated",
                      0x535503ec, CompletionStatus.COMPLETED_NO
                    );
                  }
              }

            InvokeHandler handler = getHandler(method, cookie, true);

            Delegate d = null;

            try
              {
                d = servant._get_delegate();
                orb.currents.put(Thread.currentThread(), this);
              }
            catch (Exception ex)
              {
                // In some cases exception is thrown if the delegate is not set.
              }
            if (d instanceof ServantDelegateImpl)
              {
                // If the delegate is already set, check maybe we can
                // reuse the existing instance.
                if (((ServantDelegateImpl) d).object != this)
                  {
                    servant._set_delegate(new ServantDelegateImpl(servant, poa, Id));
                  }
              }
            else
              {
                servant._set_delegate(new ServantDelegateImpl(servant, poa, Id));
              }

            try
              {
                switch (manager.get_state().value())
                  {
                    case State._ACTIVE :

                      OutputStream rt;
                      try
                        {
                          if (intercept)
                            {
                              interceptor.receive_request(info);
                            }

                          rt = handler._invoke(method, input, r_handler);

                          if (intercept)
                            {
                              // Handler is casted into i_handler.
                              if (i_handler.isExceptionReply())
                                {
                                  info.m_reply_header.reply_status =
                                    ReplyHeader.USER_EXCEPTION;

                                  // Make Any, holding the user exception.
                                  Any a = orb.create_any();
                                  OutputStream buf = i_handler.getBuffer();
                                  InputStream in = buf.create_input_stream();
                                  String uex_idl = "unknown";
                                  try
                                    {
                                      in.mark(Integer.MAX_VALUE);
                                      uex_idl = in.read_string();
                                      in.reset();
                                    }
                                  catch (IOException e)
                                    {
                                      throw new Unexpected(e);
                                    }

                                  try
                                    {
                                      UserException exception =
                                        ObjectCreator.readUserException(uex_idl,
                                          in
                                        );

                                      ObjectCreator.insertWithHelper(a,
                                        exception
                                      );
                                    }
                                  catch (Exception e)
                                    {
                                      // Failed due any reason, insert without
                                      // helper.
                                      a.insert_Streamable(new StreamHolder(
                                          buf.create_input_stream()
                                        )
                                      );

                                      RecordTypeCode r =
                                        new RecordTypeCode(TCKind.tk_except);
                                      r.setId(uex_idl);
                                      r.setName(ObjectCreator.getDefaultName(
                                          uex_idl
                                        )
                                      );
                                    }

                                  info.m_usr_exception = a;
                                  interceptor.send_exception(info);
                                }
                              else
                                {
                                  info.m_reply_header.reply_status =
                                    ReplyHeader.NO_EXCEPTION;
                                  interceptor.send_reply(info);
                                }
                            }
                        }
                      catch (SystemException sys_ex)
                        {
                          if (intercept)
                            {
                              info.m_reply_header.reply_status =
                                ReplyHeader.SYSTEM_EXCEPTION;
                              info.m_sys_exception = sys_ex;
                              interceptor.send_exception(info);
                            }
                          throw sys_ex;
                        }

                      return rt;

                    case State._HOLDING :

                      // The holding mode is implemented
                      // relying on the holding capabilites of the network
                      // support (if any).
                      // TODO FIXME in more recent CORBA applications, the
                      // client
                      // ORB can free the connection and wait for a server side
                      // notification about the completed request. Implement
                      // this
                      // as soon as JDK specification would allow bidirectional
                      // policy.
                      int sleep = 5;
                      int max = 500;

                      // Wait till the state will be switched into some other
                      // mode.
                      while (manager.get_state().value() == State._HOLDING)
                        {
                          try
                            {
                              Thread.sleep(sleep);
                              if (sleep < max)
                                {
                                  sleep = max;
                                }
                            }
                          catch (InterruptedException ex)
                            {
                            }
                        }

                      // Handle another mode.
                      return _invoke(method, input, r_handler);

                    case State._DISCARDING :
                      throw new TRANSIENT("Discarding mode", 0x535503e9,
                        CompletionStatus.COMPLETED_NO
                      );

                    case State._INACTIVE :
                      throw new OBJ_ADAPTER("POA deactivated", 0x535503ea,
                        CompletionStatus.COMPLETED_NO
                      );

                    default :
                      throw new InternalError(); // No more states.
                  }
              }
            finally
              {
                if (poa.servant_locator != null)
                  {
                    poa.servant_locator.postinvoke(Id, poa, method,
                      cookie.value, servant
                    );
                  }
              }
          }
        finally
          {
            orb.currents.remove(Thread.currentThread());
            if (noRetain)
              servant = null;
          }
      }
    catch (ForwardRequest fex)
      {
        // May be thrown by interceptor.
        if (intercept)
          {
            Forwarding:
            while (true)
              {
                info.m_reply_header.reply_status =
                  ReplyHeader.LOCATION_FORWARD;
                info.m_forward_reference = fex.forward;
                try
                  {
                    interceptor.send_other(info);
                    break Forwarding;
                  }
                catch (ForwardRequest fex2)
                  {
                    info.m_forward_reference = fex2.forward;
                    fex.forward = info.m_forward_reference;
                  }
              }
          }
        throw new gnuForwardRequest(fex.forward);
      }
    catch (gnuForwardRequest fex)
      {
        // May be thrown during activation.
        if (intercept)
          {
            Forwarding:
            while (true)
              {
                info.m_reply_header.reply_status =
                  ReplyHeader.LOCATION_FORWARD;
                info.m_forward_reference = fex.forward_reference;
                try
                  {
                    interceptor.send_other(info);
                    break Forwarding;
                  }
                catch (ForwardRequest fex2)
                  {
                    info.m_forward_reference = fex2.forward;
                    fex.forward_reference = (ObjectImpl) fex2.forward;
                  }
              }
          }
        throw fex;
      }
  }

  /**
   * Compare with another object for equality, comparing the object keys.
   */
  public boolean equals(java.lang.Object other)
  {
    if (other instanceof gnuServantObject)
      {
        gnuServantObject o = (gnuServantObject) other;

        return Arrays.equals(o.Id, Id);
      }
    else
      {
        return false;
      }
  }

  /**
   * Get the hash code, based on the object key.
   */
  public int hashCode()
  {
    long s = 0;
    int v = 1;
    for (int i = 0; i < Id.length; i++)
      {
        s += Id [ i ] * v;
        if (s > Integer.MAX_VALUE)
          {
            s = s % Integer.MAX_VALUE;
            v = 1;
          }
        v = v * 8;
      }
    return (int) (s % Integer.MAX_VALUE);
  }

  /**
   * Get the object id.
   */
  public byte[] get_object_id()
  {
    return Id;
  }

  /**
   * Get POA.
   */
  public POA get_POA()
  {
    return poa;
  }

  /**
   * Returns without action.
   */
  public void _release()
  {
  }

  /**
   * Returns without action.
   */
  public void _releaseReply(InputStream stream)
  {
  }

  /**
   * Checks if this object is equivalent to another instance. These objects are
   * assumed equal if they are connected to the same orb and poa under the same
   * Id, regardless of they delegates.
   *
   * @param other instance to check.
   * @return
   */
  public boolean _is_equivalent(org.omg.CORBA.Object other)
  {
    if (other instanceof gnuServantObject)
      {
        gnuServantObject g = (gnuServantObject) other;
        return orb == g.orb && poa == g.poa && Arrays.equals(Id, g.Id);
      }
    else if (other instanceof IorObject)
      {
        IorObject ir = ((IorObject) other);
        try
          {
            IorDelegate ird = (IorDelegate) ir._get_delegate();
            byte[] ior_id = poa.idFormIor(ird.getIor().key);
            if (ior_id != null && Arrays.equals(ior_id, Id))
              {
                return true;
              }
            else
              {
                return false;
              }
          }
        catch (Exception ex)
          {
            // Non - typical delegate or very specific subclass of
            // IOR_constructed_object.
            return super._is_equivalent(other);
          }
      }
    return super._is_equivalent(other);
  }
}
