/* LocalDelegate.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.CDR.AbstractCdrOutput;
import gnu.CORBA.IOR;
import gnu.CORBA.IorProvider;
import gnu.CORBA.StreamBasedRequest;

import org.omg.CORBA.ARG_INOUT;
import org.omg.CORBA.Bounds;
import org.omg.CORBA.Context;
import org.omg.CORBA.ContextList;
import org.omg.CORBA.ExceptionList;
import org.omg.CORBA.NO_IMPLEMENT;
import org.omg.CORBA.NVList;
import org.omg.CORBA.NamedValue;
import org.omg.CORBA.OBJECT_NOT_EXIST;
import org.omg.CORBA.ORB;
import org.omg.CORBA.Request;
import org.omg.CORBA.TypeCodePackage.BadKind;
import org.omg.CORBA.UnknownUserException;
import org.omg.CORBA.portable.ApplicationException;
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.RemarshalException;
import org.omg.PortableServer.ServantLocatorPackage.CookieHolder;

import java.util.Arrays;

/**
 * A local delegate, transferring all object requests to the locally available
 * servant. This class is involved in handling the method invocations on the
 * local object, obtained by POA.create_reference_with_id.
 *
 * @author Audrius Meskauskas, Lithuania (AudriusA@Bioinformatics.org)
 */
public class LocalDelegate
  extends org.omg.CORBA_2_3.portable.Delegate
  implements IorProvider
{
  /**
   * The same servant as an invocation handler.
   */
  gnuServantObject object;

  String operation;

  public final gnuPOA poa;

  final byte[] Id;

  /**
   * Create a local delegate, forwarding requests to the servant that must also
   * be an invocation handler.
   */
  public LocalDelegate(gnuServantObject an_object, gnuPOA a_poa, byte[] an_id)
  {
    object = an_object;
    poa = a_poa;
    Id = an_id;
  }

  /**
   * Get the IOR of the connected object.
   */
  public IOR getIor()
  {
    return object.getIor();
  }

  public Request request(org.omg.CORBA.Object target, String method)
  {
    operation = method;

    LocalRequest rq = new LocalRequest(object, poa, Id);
    rq.setOperation(method);
    rq.setORB(orb(target));
    return rq;
  }

  public void release(org.omg.CORBA.Object target)
  {
  }

  public boolean is_equivalent(org.omg.CORBA.Object target,
    org.omg.CORBA.Object other)
  {
    if (target == other)
      return true;
    else if (target instanceof ObjectImpl && other instanceof ObjectImpl)
      {
        org.omg.CORBA.portable.Delegate a = null;
        org.omg.CORBA.portable.Delegate b = null;
        try
          {
            a = ((ObjectImpl) target)._get_delegate();
            b = ((ObjectImpl) other)._get_delegate();
          }
        catch (Exception ex)
          {
            // Unable to get one of the delegates.
            return false;
          }
        if (a instanceof LocalDelegate && b instanceof LocalDelegate)
          {
            byte[] k1 = ((LocalDelegate) a).Id;
            byte[] k2 = ((LocalDelegate) b).Id;
            return Arrays.equals(k1, k2);
          }
        else
          return false;
      }
    else
      return false;
  }

  /**
   * Always return false.
   */
  public boolean non_existent(org.omg.CORBA.Object target)
  {
    return false;
  }

  /**
   * Get hash code.
   */
  public int hash(org.omg.CORBA.Object target, int maximum)
  {
    return hashCode() % maximum;
  }

  /**
   * 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(org.omg.CORBA.Object a_servant, String idl_id)
  {
    String[] maybe = object._ids();
    for (int i = 0; i < maybe.length; i++)
      {
        if (maybe[i].equals(idl_id))
          return true;
      }
    return false;
  }

  /**
   * Return <code>this</code>.
   */
  public org.omg.CORBA.Object duplicate(org.omg.CORBA.Object target)
  {
    return target;
  }

  /**
   * Create request for using with DII.
   */
  public Request create_request(org.omg.CORBA.Object target, Context context,
    String method, NVList parameters, NamedValue returns,
    ExceptionList exceptions, ContextList ctx_list)
  {
    operation = method;

    LocalRequest rq = new LocalRequest(object, poa, Id);
    rq.setOperation(method);
    rq.set_args(parameters);
    rq.set_result(returns);
    rq.set_exceptions(exceptions);
    rq.set_context_list(ctx_list);
    return rq;
  }

  /**
   * Create request for using with DII.
   */
  public Request create_request(org.omg.CORBA.Object target, Context context,
    String method, NVList parameters, NamedValue returns)
  {
    operation = method;

    LocalRequest rq = new LocalRequest(object, poa, Id);
    rq.setOperation(method);
    rq.set_args(parameters);
    rq.set_result(returns);
    return rq;
  }

  /**
   * Not in use.
   */
  public org.omg.CORBA.Object get_interface_def(org.omg.CORBA.Object target)
  {
    throw new NO_IMPLEMENT();
  }

  /**
   * Create a request to invoke the method of this CORBA object.
   *
   * @param operation the name of the method to invoke.
   * @param response_expected specifies if this is one way message or the
   * response to the message is expected.
   *
   * @return the stream where the method arguments should be written.
   */
  public org.omg.CORBA.portable.OutputStream request(
    org.omg.CORBA.Object target, String method, boolean response_expected)
  {
    operation = method;

    // Check if the object is not explicitly deactivated.
    AOM.Obj e = poa.aom.get(Id);
    if (e != null && e.isDeactiveted())
      {
        if (poa.servant_activator != null || poa.servant_locator != null)
          {
            // This will force the subsequent activation.
            object.setServant(null);
            e.setServant(null);
            e.setDeactivated(false);
          }
        else
          throw new OBJECT_NOT_EXIST("Deactivated");
      }

    LocalRequest rq = new LocalRequest(object, poa, Id);
    rq.setOperation(method);
    rq.setORB(orb(target));
    return rq.getParameterStream();
  }

  /**
   * Return the associated invocation handler.
   */
  public InvokeHandler getHandler(String method, CookieHolder cookie)
  {
    return object.getHandler(method, cookie, false);
  }

  /**
   * Return the ORB of the associated POA. The parameter is not in use.
   */
  public ORB orb(org.omg.CORBA.Object target)
  {
    return poa.orb();
  }

  /**
   * Make an invocation.
   *
   * @param target not in use.
   * @param output the stream request that should be returned by
   * {@link #m_request} in this method.
   * @throws ApplicationException if the use exception is thrown by the servant
   * method.
   */
  public InputStream invoke(org.omg.CORBA.Object target, OutputStream output)
    throws ApplicationException
  {
    try
      {
        StreamBasedRequest sr = (StreamBasedRequest) output;

        LocalRequest lr = (LocalRequest) sr.request;
        InvokeHandler handler = lr.object.getHandler(lr.operation(), lr.cookie,
          false);

        if (handler instanceof DynamicImpHandler)
          {
            // The local request known how to handle it, but the different
            // method must be called.
            lr.invoke();

            // The encapsulation will inherit orb, endian, charsets, etc.
            AbstractCdrOutput buf = sr.createEncapsulation();

            // Write all request parameters to the buffer stream.
            if (lr.env().exception() != null)
              {
                try
                  {
                    UnknownUserException uex = (UnknownUserException) lr.env().exception();
                    throw new ApplicationException(uex.except.type().id(),
                      uex.except.create_input_stream());
                  }
                catch (BadKind ex)
                  {
                    InternalError ierr = new InternalError();
                    ierr.initCause(ex);
                    throw ierr;
                  }
              }
            if (lr.return_value() != null)
              lr.return_value().write_value(buf);

            NamedValue a;
            try
              {
                for (int i = 0; i < lr.arguments().count(); i++)
                  {
                    a = lr.arguments().item(i);
                    if (a.flags() == ARG_INOUT.value
                      || a.flags() == ARG_INOUT.value)
                      {
                        a.value().write_value(buf);
                      }
                  }
              }
            catch (Bounds ex)
              {
                InternalError ierr = new InternalError();
                ierr.initCause(ex);
                throw ierr;
              }

            return buf.create_input_stream();
          }
        else
          {
            LocalRequest lrq = (LocalRequest) sr.request;
            return lrq.s_invoke(handler);
          }
      }
    catch (gnuForwardRequest f)
      {
        try
          {
            return ((ObjectImpl) f.forward_reference)._invoke(f.forward_reference._request(
              operation, true));
          }
        catch (RemarshalException e)
          {
            // Never thrown in this place by Classpath implementation.
            throw new NO_IMPLEMENT();
          }
      }
  }

  public void releaseReply(org.omg.CORBA.Object target, InputStream input)
  {
    release(target);
  }
}
