/* MessageHeader.java -- GIOP message header.
   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.GIOP;

import gnu.CORBA.Minor;
import gnu.CORBA.Version;
import gnu.CORBA.CDR.BigEndianInputStream;
import gnu.CORBA.CDR.BigEndianOutputStream;
import gnu.CORBA.CDR.LittleEndianInputStream;
import gnu.CORBA.CDR.LittleEndianOutputStream;
import gnu.CORBA.CDR.AbstractDataInput;
import gnu.CORBA.CDR.AbstractDataOutput;

import org.omg.CORBA.MARSHAL;
import org.omg.CORBA.portable.IDLEntity;

import java.io.ByteArrayOutputStream;
import java.io.EOFException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.util.Arrays;

/**
 * The GIOP message header.
 * 
 * @author Audrius Meskauskas (AudriusA@Bioinformatics.org)
 */
public class MessageHeader
  implements IDLEntity
{
  /**
   * Use serialVersionUID for interoperability.
   */
  private static final long serialVersionUID = 1;

  /**
   * Request message.
   */
  public static final byte REQUEST = 0;

  /**
   * Reply message
   */
  public static final byte REPLY = 1;

  /**
   * Cancel request message.
   */
  public static final byte CANCEL_REQUEST = 2;

  /**
   * Locate request message, used to check the server ability to process
   * requests for the object reference. This message is also used to get the
   * address where the object reference should be sent.
   */
  public static final byte LOCATE_REQUEST = 3;

  /**
   * Locate reply message, sent in response to the {@link #LocateRequest}
   * message.
   */
  public static final byte LOCATE_REPLY = 4;

  /**
   * Instruction to close the connection.
   */
  public static final byte CLOSE_CONNECTION = 5;

  /**
   * Error report.
   */
  public static final byte MESSAGE_ERROR = 6;

  /**
   * The fragment messge, following the previous message that has more fragments
   * flag set. Added in GIOP 1.1
   */
  public static final byte FRAGMENT = 7;

  /**
   * This must always be "GIOP".
   */
  public static final byte[] MAGIC = new byte[] { 'G', 'I', 'O', 'P' };

  /**
   * The message type names.
   */
  protected static String[] types = new String[] { "Request", "Reply",
    "Cancel", "Locate request", "Locate reply", "Close connection", "Error",
    "Fragment" };

  /**
   * The GIOP version. Initialised to 1.0 .
   */
  public Version version;

  /**
   * The flags field, introduced since GIOP 1.1.
   */
  public byte flags = 0;

  /**
   * The message type.
   */
  public byte message_type = REQUEST;

  /**
   * The message size, excluding the message header.
   */
  public int message_size = 0;

  /**
   * Create an empty message header, corresponding version 1.0.
   */
  public MessageHeader()
  {
    version = new Version(1, 0);
  }

  /**
   * Create an empty message header, corresponding the given version.
   * 
   * @param major the major message header version.
   * @param minor the minot message header version.
   */
  public MessageHeader(int major, int minor)
  {
    version = new Version(major, minor);
  }

  /**
   * Checks if the message is encoded in the Big Endian, most significant byte
   * first.
   */
  public boolean isBigEndian()
  {
    return (flags & 0x1) == 0;
  }

  /**
   * Checks if the message is partial, and more subsequent fragments follow.
   */
  public boolean moreFragmentsFollow()
  {
    return (flags & 0x2) != 0;
  }

  /**
   * Set the encoding to use.
   * 
   * @param use_big_endian if true (default), the Big Endian encoding is used.
   * If false, the Little Endian encoding is used.
   */
  public void setBigEndian(boolean use_big_endian)
  {
    if (use_big_endian)
      flags = (byte) (flags & ~1);
    else
      flags = (byte) (flags | 1);
  }

  /**
   * Get the size of the message header itself. So far, it is always 12 bytes.
   */
  public int getHeaderSize()
  {
    return 12;
  }

  /**
   * Get the message type as string.
   * 
   * @param type the message type as int (the field {@link message_type}).
   * 
   * @return the message type as string.
   */
  public String getTypeString(int type)
  {
    try
      {
        return types[type];
      }
    catch (ArrayIndexOutOfBoundsException ex)
      {
        return "unknown type (" + type + ")";
      }
  }

  /**
   * Creates reply header, matching the message header version number.
   * 
   * @return one of {@link gnu.CORBA.GIOP.v1_0.ReplyHeader},
   * {@link gnu.CORBA.GIOP.v1_2.ReplyHeader}, etc - depending on the version
   * number in this header.
   */
  public ReplyHeader create_reply_header()
  {
    if (version.since_inclusive(1, 2))
      return new gnu.CORBA.GIOP.v1_2.ReplyHeader();
    else
      return new gnu.CORBA.GIOP.v1_0.ReplyHeader();
  }

  /**
   * Creates request header, matching the message header version number.
   * 
   * @return one of {@link gnu.CORBA.GIOP.v1_0.RequestHeader},
   * {@link gnu.CORBA.GIOP.v1_2.RequestHeader}, etc - depending on the version
   * number in this header.
   */
  public RequestHeader create_request_header()
  {
    if (version.since_inclusive(1, 2))
      return new gnu.CORBA.GIOP.v1_2.RequestHeader();
    else
      return new gnu.CORBA.GIOP.v1_0.RequestHeader();
  }

  /**
   * Create the cancel header, matching the message header version number.
   */
  public CancelHeader create_cancel_header()
  {
    return new gnu.CORBA.GIOP.v1_0.CancelHeader();
  }

  /**
   * Create the error message.
   */
  public ErrorMessage create_error_message()
  {
    return new ErrorMessage(version);
  }

  /**
   * Read the header from the stream.
   * 
   * @param istream a stream to read from.
   * @throws MARSHAL if this is not a GIOP 1.0 header.
   */
  public void read(java.io.InputStream istream) 
    throws MARSHAL, EOFException
  {
    try
      {
        byte[] xMagic = new byte[MAGIC.length];
        int r = istream.read(xMagic);
        int minor;
        if (! Arrays.equals(xMagic, MAGIC))
          {
            StringBuffer b = new StringBuffer();
            if (r == - 1)
              {
                b.append("Immediate EOF");
                minor = Minor.EOF;
              }
            else
              {
                minor = Minor.Giop;
                b.append(r + " bytes: ");
                for (int i = 0; i < xMagic.length; i++)
                  {
                    b.append(Integer.toHexString(xMagic[i] & 0xFF));
                    b.append(' ');
                  }
              }
            MARSHAL m = new MARSHAL("Not a GIOP message: " + b);
            m.minor = minor;
            throw m;
          }

        version = Version.read_version(istream);

        AbstractDataInput din;

        flags = (byte) istream.read();

        // This checks the bit in the byte we have just received.
        if (isBigEndian())
          din = new BigEndianInputStream(istream);
        else
          din = new LittleEndianInputStream(istream);

        message_type = (byte) din.read();

        message_size = din.readInt();
      }
    catch (IOException ex)
      {
        MARSHAL t = new MARSHAL();
        t.minor = Minor.Header;
        t.initCause(ex);
        throw t;
      }
  }

  /**
   * Get the short string summary of the message.
   * 
   * @return a short message summary.
   */
  public String toString()
  {
    return "GIOP " + version + ", " + (isBigEndian() ? "Big" : "Little")
      + " endian, " + getTypeString(message_type) + ", " + message_size
      + " bytes. ";
  }

  /**
   * Write the header to stream.
   * 
   * @param out a stream to write into.
   */
  public void write(java.io.OutputStream out)
  {
    try
      {
        AbstractDataOutput dout;

        if (isBigEndian())
          dout = new BigEndianOutputStream(out);
        else
          dout = new LittleEndianOutputStream(out);

        // Write magic sequence.
        dout.write(MAGIC);

        // Write version number.
        version.write((OutputStream) dout);
        dout.write(flags);
        dout.write(message_type);
        dout.writeInt(message_size);
      }
    catch (IOException ex)
      {
        MARSHAL t = new MARSHAL(ex.getMessage());
        t.minor = Minor.Header;
        t.initCause(ex);
        throw t;
      }
  }

  /**
   * Read data, followed by the message header. Handle fragmented messages.
   * 
   * @param source the data source to read from.
   * @param service the socket on that the time outs are set. Can be null (no
   * timeouts are set).
   * @param to_read the timeout while reading the message.
   * @param to_pause the timeout for pauses between the message parts.
   */
  public byte[] readMessage(InputStream source, Socket service, int to_read,
    int to_pause)
  {
    try
      {
        byte[] r = new byte[message_size];

        int n = 0;
        if (service != null)
          service.setSoTimeout(to_read);

        reading: while (n < r.length)
          {
            n += source.read(r, n, r.length - n);
          }
        if (service != null)
          service.setSoTimeout(to_pause);

        // Read the message remainder if the message is fragmented.
        if (moreFragmentsFollow())
          {
            ByteArrayOutputStream buffer = new ByteArrayOutputStream(
              2 * r.length);
            buffer.write(r);

            if (r.length < 10)
              // Increase the buffer size if the default value (size of the
              // previous message) is really too small.
              r = new byte[1024];

            MessageHeader h2 = new MessageHeader();

            do
              {
                h2.read(source);

                int dn;

                n = 0;
                reading: while (n < h2.message_size)
                  {
                    dn = source.read(r, 0, h2.message_size - n);

                    if (n == 0 && service != null)
                      service.setSoTimeout(to_read);

                    if (n == 0 && version.since_inclusive(1, 2))
                      {
                        // Skip the four byte request id.
                        buffer.write(r, 4, dn - 4);
                      }
                    else
                      buffer.write(r, 0, dn);
                    n = +dn;
                  }

                if (service != null)
                  service.setSoTimeout(to_pause);
              }
            while (h2.moreFragmentsFollow());
            return buffer.toByteArray();
          }
        else
          return r;
      }
    catch (IOException ioex)
      {
        MARSHAL m = new MARSHAL("Unable to read the message continuation.");
        m.minor = Minor.Header;
        m.initCause(ioex);
        throw m;
      }
  }
}