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