/* 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);
  }
}
