/* IOR.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.BufferredCdrInput;
import gnu.CORBA.CDR.BufferedCdrOutput;
import gnu.CORBA.CDR.AbstractCdrInput;
import gnu.CORBA.CDR.AbstractCdrOutput;
import gnu.CORBA.GIOP.CharSets_OSF;
import gnu.CORBA.GIOP.CodeSetServiceContext;

import gnu.java.lang.CPStringBuilder;

import org.omg.CORBA.BAD_PARAM;
import org.omg.CORBA.CompletionStatus;
import org.omg.CORBA.MARSHAL;
import org.omg.CORBA.ULongSeqHelper;
import org.omg.IOP.TAG_INTERNET_IOP;
import org.omg.IOP.TAG_MULTIPLE_COMPONENTS;
import org.omg.IOP.TaggedComponent;
import org.omg.IOP.TaggedComponentHelper;
import org.omg.IOP.TaggedProfile;
import org.omg.IOP.TaggedProfileHelper;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.zip.Adler32;

/**
 * The implementaton of the Interoperable Object Reference (IOR). IOR can be
 * compared with the Internet address for a web page, it provides means to
 * locate the CORBA service on the web. IOR contains the host address, port
 * number, the object identifier (key) inside the server, the communication
 * protocol version, supported charsets and so on.
 *
 * Ths class provides method for encoding and decoding the IOR information
 * from/to the stringified references, usually returned by
 * {@link org.omg.CORBA.ORB#String object_to_string()}.
 *
 * @author Audrius Meskauskas (AudriusA@Bioinformatics.org)
 *
 * @see org.mog.CORBA.Object.object_to_string(Object forObject)
 * @see string_to_object(String IOR)
 */
public class IOR
{
  /**
   * The code sets tagged component, normally part of the Internet profile. This
   * compone consists of the two componenets itself.
   */
  public static class CodeSets_profile
  {
    public CodeSets_profile()
    {
      int[] supported = CharSets_OSF.getSupportedCharSets();

      narrow.native_set = CharSets_OSF.NATIVE_CHARACTER;
      narrow.conversion = supported;

      wide.native_set = CharSets_OSF.NATIVE_WIDE_CHARACTER;
      wide.conversion = supported;
    }

    /**
     * The code set component.
     */
    public static class CodeSet_component
    {
      /**
       * The conversion code sets.
       */
      public int[] conversion;

      /**
       * The native code set.
       */
      public int native_set;

      /**
       * Read from the CDR stream.
       */
      public void read(org.omg.CORBA.portable.InputStream in)
      {
        native_set = in.read_ulong();
        conversion = ULongSeqHelper.read(in);
      }

      /**
       * Get a string representation.
       */
      public String toString()
      {
        CPStringBuilder b = new CPStringBuilder();
        b.append("native " + name(native_set));
        if (conversion != null && conversion.length > 0)
          {
            b.append(" conversion ");
            for (int i = 0; i < conversion.length; i++)
              {
                b.append(name(conversion[i]));
                b.append(' ');
              }
          }
        b.append(' ');
        return b.toString();
      }
      
      /**
       * Get a better formatted multiline string representation.
       */
      public String toStringFormatted()
      {
        CPStringBuilder b = new CPStringBuilder();
        b.append("\n  Native set " + name(native_set));
        if (conversion != null && conversion.length > 0)
          {
            b.append("\n  Other supported sets:\n    ");
            for (int i = 0; i < conversion.length; i++)
              {
                b.append(name(conversion[i]));
                b.append(' ');
              }
          }
        b.append("\n");
        return b.toString();
      }
      

      /**
       * Write into CDR stream.
       */
      public void write(org.omg.CORBA.portable.OutputStream out)
      {
        out.write_long(native_set);
        ULongSeqHelper.write(out, conversion);
      }

      private String name(int set)
      {
        return "0x" + Integer.toHexString(set) + " ("
               + CharSets_OSF.getName(set) + ") ";
      }
    }

    /**
     * The agreed tag for the Codesets profile.
     */
    public static final int TAG_CODE_SETS = 1;

    /**
     * Information about narrow character encoding (TCS-C).
     */
    public CodeSet_component narrow = new CodeSet_component();

    /**
     * About wide character encoding (TCS-W).
     */
    public CodeSet_component wide = new CodeSet_component();

    /**
     * The negotiated coding result for this IOR. Saves time, requred for
     * negotiation computations.
     */
    public CodeSetServiceContext negotiated;

    /**
     * Read the code set profile information from the given input stream.
     *
     * @param profile a stream to read from.
     */
    public void read(AbstractCdrInput profile)
    {
      BufferredCdrInput encapsulation = profile.read_encapsulation();
      narrow.read(encapsulation);
      wide.read(encapsulation);
    }

    /**
     * Returns a string representation.
     */
    public String toString()
    {
      return "Narrow char: " + narrow + ", Wide char: " + wide;
    }

    /**
     * Write the code set profile information into the given input stream.
     *
     * @param profile a stream to write into.
     */
    public void write(AbstractCdrOutput profile)
    {
      AbstractCdrOutput encapsulation = profile.createEncapsulation();
      narrow.write(encapsulation);
      wide.write(encapsulation);
      try
        {
          encapsulation.close();
        }
      catch (IOException ex)
        {
          throw new InternalError();
        }
    }
  }

  /**
   * The internet profile.
   */
  public class Internet_profile
  {
    /**
     * The agreed tag for the Internet profile.
     */
    public static final int TAG_INTERNET_IOP = 0;

    /**
     * The host.
     */
    public String host;

    /**
     * The IIOP version (initialised to 1.2 by default).
     */
    public Version version = new Version(1, 2);

    /**
     * The port.
     */
    public int port;

    /**
     * The code sets component in the internet profile of this IOR. This is not
     * a separate profile.
     */
    public CodeSets_profile CodeSets = new CodeSets_profile();

    /**
     * Reserved for all components of this profile, this array holds the
     * components other than code set components.
     */
    ArrayList components = new ArrayList();

    /**
     * Return the human readable representation.
     */
    public String toString()
    {
      CPStringBuilder b = new CPStringBuilder();
      b.append(host);
      b.append(":");
      b.append(port);
      b.append(" (v");
      b.append(version);
      b.append(")");
      if (components.size() > 0)
        b.append(" " + components.size() + " extra components.");
      return b.toString();
    }

    /**
     * Write the internet profile (except the heading tag.
     */
    public void write(AbstractCdrOutput out)
    {
      try
        {
          // Need to write the Internet profile into the separate
          // stream as we must know the size in advance.
          AbstractCdrOutput b = out.createEncapsulation();

          version.write(b);
          b.write_string(host);

          b.write_ushort((short) (port & 0xFFFF));

          // Write the object key.
          b.write_long(key.length);
          b.write(key);

          // Number of the tagged components.
          b.write_long(1 + components.size());

          b.write_long(CodeSets_profile.TAG_CODE_SETS);
          CodeSets.write(b);

          TaggedComponent t;

          for (int i = 0; i < components.size(); i++)
            {
              t = (TaggedComponent) components.get(i);
              TaggedComponentHelper.write(b, t);
            }

          b.close();
        }
      catch (Exception e)
        {
          MARSHAL m = new MARSHAL("Unable to write Internet profile.");
          m.minor = Minor.IOR;
          m.initCause(e);
          throw m;
        }
    }
  }

  /**
   * The standard minor code, indicating that the string to object converstio
   * has failed due non specific reasons.
   */
  public static final int FAILED = 10;

  /**
   * The internet profile of this IOR.
   */
  public Internet_profile Internet = new Internet_profile();

  /**
   * The object repository Id.
   */
  public String Id;

  /**
   * The object key.
   */
  public byte[] key;

  /**
   * All tagged profiles of this IOR, except the separately defined Internet
   * profile.
   */
  ArrayList profiles = new ArrayList();

  /**
   * True if the profile was encoded using the Big Endian or the encoding is not
   * known.
   *
   * false if it was encoded using the Little Endian.
   */
  public boolean Big_Endian = true;

  /**
   * Create an empty instance, initialising the code sets to default values.
   */
  public IOR()
  {
  }

  /**
   * Parse the provided stringifed reference.
   *
   * @param stringified_reference in the form of IOR:nnnnnn.....
   *
   * @return the parsed IOR
   *
   * @throws BAD_PARAM, minor code 10, if the IOR cannot be parsed.
   *
   * TODO corballoc and other alternative formats.
   */
  public static IOR parse(String stringified_reference)
    throws BAD_PARAM
  {
    try
      {
        if (!stringified_reference.startsWith("IOR:"))
          throw new BAD_PARAM("The string refernce must start with IOR:",
                              FAILED, CompletionStatus.COMPLETED_NO);

        IOR r = new IOR();

        ByteArrayOutputStream buf = new ByteArrayOutputStream();
        String x = stringified_reference;
        x = x.substring(x.indexOf(":") + 1);

        char cx;

        for (int i = 0; i < x.length(); i = i + 2)
          {
            cx = (char) Integer.parseInt(x.substring(i, i + 2), 16);
            buf.write(cx);
          }

        BufferredCdrInput cdr = new BufferredCdrInput(buf.toByteArray());

        r._read(cdr);
        return r;
      }
    catch (Exception ex)
      {
        ex.printStackTrace();
        throw new BAD_PARAM(ex + " while parsing " + stringified_reference,
                            FAILED, CompletionStatus.COMPLETED_NO);
      }
  }

  /**
   * Read the IOR from the provided input stream.
   *
   * @param c a stream to read from.
   * @throws IOException if the stream throws it.
   */
  public void _read(AbstractCdrInput c)
    throws IOException, BAD_PARAM
  {
    int endian;

    endian = c.read_long();
    if (endian != 0)
      {
        Big_Endian = false;
        c.setBigEndian(false);
      }
    _read_no_endian(c);
  }

  /**
   * Read the IOR from the provided input stream, not reading the endian data at
   * the beginning of the stream. The IOR is thansferred in this form in
   * {@link write_Object(org.omg.CORBA.Object)}.
   *
   * If the stream contains a null value, the Id and Internet fields become
   * equal to null. Otherwise Id contains some string (possibly empty).
   *
   * Id is checked for null in AbstractCdrInput that then returns null instead of
   * object.
   *
   * @param c a stream to read from.
   * @throws IOException if the stream throws it.
   */
  public void _read_no_endian(AbstractCdrInput c)
    throws IOException, BAD_PARAM
  {
    Id = c.read_string();

    int n_profiles = c.read_long();

    if (n_profiles == 0)
      {
        Id = null;
        Internet = null;
        return;
      }

    for (int i = 0; i < n_profiles; i++)
      {
        int tag = c.read_long();
        BufferredCdrInput profile = c.read_encapsulation();

        if (tag == Internet_profile.TAG_INTERNET_IOP)
          {
            Internet = new Internet_profile();
            Internet.version = Version.read_version(profile);
            Internet.host = profile.read_string();
            Internet.port = profile.gnu_read_ushort();

            key = profile.read_sequence();

            // Read tagged components.
            int n_components = 0;

            try
              {
                if (Internet.version.since_inclusive(1, 1))
                  n_components = profile.read_long();

                for (int t = 0; t < n_components; t++)
                  {
                    int ctag = profile.read_long();

                    if (ctag == CodeSets_profile.TAG_CODE_SETS)
                      {
                        Internet.CodeSets.read(profile);
                      }
                    else
                      {
                        // Construct a generic component for codesets
                        // profile.
                        TaggedComponent pc = new TaggedComponent();
                        pc.tag = ctag;
                        pc.component_data = profile.read_sequence();
                        Internet.components.add(pc);
                      }
                  }
              }
            catch (Unexpected ex)
              {
                ex.printStackTrace();
              }
          }
        else
          {
            // Construct a generic profile.
            TaggedProfile p = new TaggedProfile();
            p.tag = tag;
            p.profile_data = profile.buffer.getBuffer();

            profiles.add(p);
          }
      }
  }

  /**
   * Write this IOR record to the provided CDR stream. This procedure writes the
   * zero (Big Endian) marker first.
   */
  public void _write(AbstractCdrOutput out)
  {
    // Always use Big Endian.
    out.write(0);
    _write_no_endian(out);
  }

  /**
   * Write a null value to the CDR output stream.
   *
   * The null value is written as defined in OMG specification (zero length
   * string, followed by an empty set of profiles).
   */
  public static void write_null(AbstractCdrOutput out)
  {
    // Empty Id string.
    out.write_string("");

    // Empty set of profiles.
    out.write_long(0);
  }

  /**
   * Write this IOR record to the provided CDR stream. The procedure writed data
   * in Big Endian, but does NOT add any endian marker to the beginning.
   */
  public void _write_no_endian(AbstractCdrOutput out)
  {
    // Write repository id.
    out.write_string(Id);

    out.write_long(1 + profiles.size());

    // Write the Internet profile.
    out.write_long(Internet_profile.TAG_INTERNET_IOP);
    Internet.write(out);

    // Write other profiles.
    TaggedProfile tp;

    for (int i = 0; i < profiles.size(); i++)
      {
        tp = (TaggedProfile) profiles.get(i);
        TaggedProfileHelper.write(out, tp);
      }
  }

  /**
   * Returns a human readable string representation of this IOR object.
   */
  public String toString()
  {
    CPStringBuilder b = new CPStringBuilder();
    b.append(Id);
    b.append(" at ");
    b.append(Internet);

    if (!Big_Endian)
      b.append(" (Little endian) ");

    b.append(" Key ");

    for (int i = 0; i < key.length; i++)
      {
        b.append(Integer.toHexString(key[i] & 0xFF));
      }

    b.append(" ");
    b.append(Internet.CodeSets);

    return b.toString();
  }
  
  /**
   * Returns a multiline formatted human readable string representation of 
   * this IOR object.
   */
  public String toStringFormatted()
  {
    CPStringBuilder b = new CPStringBuilder();
    b.append("\nObject Id:\n  ");
    b.append(Id);
    b.append("\nObject is accessible at:\n  ");
    b.append(Internet);

    if (Big_Endian)
      b.append("\n  Big endian encoding");
    else
      b.append("\n  Little endian encoding.");      

    b.append("\nObject Key\n  ");

    for (int i = 0; i < key.length; i++)
      {
        b.append(Integer.toHexString(key[i] & 0xFF));
      }

    b.append("\nSupported code sets:");
    b.append("\n Wide:");
    b.append(Internet.CodeSets.wide.toStringFormatted());
    b.append(" Narrow:");
    b.append(Internet.CodeSets.wide.toStringFormatted());

    return b.toString();
  }  

  /**
   * Returs a stringified reference.
   *
   * @return a newly constructed stringified reference.
   */
  public String toStringifiedReference()
  {
    BufferedCdrOutput out = new BufferedCdrOutput();

    _write(out);

    CPStringBuilder b = new CPStringBuilder("IOR:");

    byte[] binary = out.buffer.toByteArray();
    String s;

    for (int i = 0; i < binary.length; i++)
      {
        s = Integer.toHexString(binary[i] & 0xFF);
        if (s.length() == 1)
          b.append('0');
        b.append(s);
      }

    return b.toString();
  }

  /**
   * Adds a service-specific component to the IOR profile. The specified
   * component will be included in all profiles, present in the IOR.
   *
   * @param tagged_component a tagged component being added.
   */
  public void add_ior_component(TaggedComponent tagged_component)
  {
    // Add to the Internet profile.
    Internet.components.add(tagged_component);

    // Add to others.
    for (int i = 0; i < profiles.size(); i++)
      {
        TaggedProfile profile = (TaggedProfile) profiles.get(i);
        addComponentTo(profile, tagged_component);
      }
  }

  /**
   * Adds a service-specific component to the IOR profile.
   *
   * @param tagged_component a tagged component being added.
   *
   * @param profile_id the IOR profile to that the component must be added. The
   * 0 value ({@link org.omg.IOP.TAG_INTERNET_IOP#value}) adds to the Internet
   * profile where host and port are stored by default.
   */
  public void add_ior_component_to_profile(TaggedComponent tagged_component,
                                           int profile_id)
  {
    if (profile_id == TAG_INTERNET_IOP.value)
      // Add to the Internet profile
      Internet.components.add(tagged_component);
    else
      {
        // Add to others.
        for (int i = 0; i < profiles.size(); i++)
          {
            TaggedProfile profile = (TaggedProfile) profiles.get(i);
            if (profile.tag == profile_id)
              addComponentTo(profile, tagged_component);
          }
      }
  }

  /**
   * Add given component to the given profile that is NOT an Internet profile.
   *
   * @param profile the profile, where the component should be added.
   * @param component the component to add.
   */
  private static void addComponentTo(TaggedProfile profile,
                                     TaggedComponent component)
  {
    if (profile.tag == TAG_MULTIPLE_COMPONENTS.value)
      {
        TaggedComponent[] present;
        if (profile.profile_data.length > 0)
          {
            BufferredCdrInput in = new BufferredCdrInput(profile.profile_data);

            present = new TaggedComponent[in.read_long()];

            for (int i = 0; i < present.length; i++)
              {
                present[i] = TaggedComponentHelper.read(in);
              }
          }
        else
          present = new TaggedComponent[0];

        BufferedCdrOutput out = new BufferedCdrOutput(profile.profile_data.length
                                            + component.component_data.length
                                            + 8);

        // Write new amount of components.
        out.write_long(present.length + 1);

        // Write other components.
        for (int i = 0; i < present.length; i++)
          TaggedComponentHelper.write(out, present[i]);

        // Write the passed component.
        TaggedComponentHelper.write(out, component);

        try
          {
            out.close();
          }
        catch (IOException e)
          {
            throw new Unexpected(e);
          }
        profile.profile_data = out.buffer.toByteArray();
      }
    else
      // The future supported tagged profiles should be added here.
      throw new BAD_PARAM("Unsupported profile type " + profile.tag);
  }
  
  /**
   * Checks for equality.
   */
  public boolean equals(Object x)
  {
    if (x instanceof IOR)
      {
        boolean keys;
        boolean hosts = true;

        IOR other = (IOR) x;
        
        if (Internet==null || other.Internet==null)
          return Internet == other.Internet;
        
        if (key != null && other.key != null)
          keys = Arrays.equals(key, other.key);
        else
          keys = key == other.key;

        if (Internet != null && Internet.host != null)
          if (other.Internet != null && other.Internet.host != null)
            hosts = other.Internet.host.equals(Internet.host);

        return keys & hosts && Internet.port==other.Internet.port;
      }
    else
      return false;
  }
  
  /**
   * Get the hashcode of this IOR.
   */
  public int hashCode()
  {
    Adler32 adler = new Adler32();
    if (key != null)
      adler.update(key);
    if (Internet != null)
      {
        if (Internet.host != null)
          adler.update(Internet.host.getBytes());
        adler.update(Internet.port);
      }
    return (int) adler.getValue();
  }
}
