/* Oid.java -- Object identifier class.
   Copyright (C) 2004 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.

   The documentation comments of this class are derived from the text
   of RFC 2853:  Generic Security Service API Version 2: Java Bindings.
   That document is covered under the following license notice:

Copyright (C) The Internet Society (2000).  All Rights Reserved.

This document and translations of it may be copied and furnished to
others, and derivative works that comment on or otherwise explain it
or assist in its implementation may be prepared, copied, published and
distributed, in whole or in part, without restriction of any kind,
provided that the above copyright notice and this paragraph are
included on all such copies and derivative works.  However, this
document itself may not be modified in any way, such as by removing
the copyright notice or references to the Internet Society or other
Internet organizations, except as needed for the purpose of developing
Internet standards in which case the procedures for copyrights defined
in the Internet Standards process must be followed, or as required to
translate it into languages other than English.

The limited permissions granted above are perpetual and will not be
revoked by the Internet Society or its successors or assigns.

This document and the information contained herein is provided on an
"AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT
NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION HEREIN
WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. */


package org.ietf.jgss;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.InputStream;
import java.io.IOException;
import java.io.OutputStream;

import java.math.BigInteger;

import java.util.Arrays;
import java.util.StringTokenizer;

/**
 * <p>This class represents Universal Object Identifiers (Oids) and their
 * associated operations.</p>
 *
 * <p>Oids are hierarchically globally-interpretable identifiers used
 * within the GSS-API framework to identify mechanisms and name formats.</p>
 *
 * <p>The structure and encoding of Oids is defined in ISOIEC-8824 and
 * ISOIEC-8825.  For example the Oid representation of Kerberos V5
 * mechanism is "1.2.840.113554.1.2.2".</p>
 *
 * <p>The {@link GSSName} name class contains <code>public static Oid</code>
 * objects representing the standard name types defined in GSS-API.</p>
 */
public class Oid
{

  // Constants and fields.
  // -------------------------------------------------------------------------

  private static final int OBJECT_IDENTIFIER = 0x06;
  private static final int RELATIVE_OID      = 0x0d;

  private final int[] components;
  private byte[] derOid;
  private String strOid;
  private boolean relative;

  // Constructors.
  // -------------------------------------------------------------------------

  /**
   * Creates an Oid object from a string representation of its integer
   * components (e.g. "1.2.840.113554.1.2.2").
   *
   * @param strOid The string representation for the oid.
   * @throws GSSException If the argument is badly formed.
   */
  public Oid(String strOid) throws GSSException
  {
    if (strOid == null)
      throw new NullPointerException();
    this.strOid = strOid;
    try
      {
        StringTokenizer tok = new StringTokenizer(strOid, ".");
        components = new int[tok.countTokens()];
        int i = 0;
        while (tok.hasMoreTokens() && i < components.length)
          {
            components[i++] = Integer.parseInt(tok.nextToken());
          }
      }
    catch (Exception x)
      {
        throw new GSSException(GSSException.FAILURE);
      }
    relative = false;
  }

  /**
   * Creates an Oid object from its DER encoding. This refers to the full
   * encoding including tag and length.  The structure and encoding of
   * Oids is defined in ISOIEC-8824 and ISOIEC-8825.  This method is
   * identical in functionality to its byte array counterpart.
   *
   * @param derOid Stream containing the DER encoded oid.
   * @throws GSSException If the DER stream is badly formed, or if the
   *                      input stream throws an exception.
   */
  public Oid(InputStream derOid) throws GSSException
  {
    DataInputStream in = new DataInputStream(derOid);
    try
      {
        int tag = in.read() & 0x1F;
        if (tag != OBJECT_IDENTIFIER && tag != RELATIVE_OID)
          throw new IOException();
        int len = in.read();
        if ((len & ~0x7F) != 0)
          {
            byte[] buf = new byte[len & 0x7F];
            in.readFully(buf);
            len = new BigInteger(1, buf).intValue();
          }
        if (len < 0)
          throw new IOException();
        byte[] enc = new byte[len];
        in.readFully(enc);
        int[] comp = new int[len + 1];
        int count = 0;
        int i = 0;
        relative = tag == RELATIVE_OID;
        if (!relative && i < len)
          {
            int j = (enc[i] & 0xFF);
            comp[count++] = j / 40;
            comp[count++] = j % 40;
            i++;
          }
        while (i < len)
          {
            int j = 0;
            do
              {
                j = enc[i++] & 0xFF;
                comp[count] <<= 7;
                comp[count]  |= j & 0x7F;
                if (i >= len && (j & 0x80) != 0)
                  throw new IOException();
              }
            while ((j & 0x80) != 0);
            count++;
          }
        if (count == len)
          this.components = comp;
        else
          {
            this.components = new int[count];
            System.arraycopy(comp, 0, components, 0, count);
          }
      }
    catch (IOException ioe)
      {
        throw new GSSException(GSSException.FAILURE);
      }
  }

  /**
   * Creates an Oid object from its DER encoding. This refers to the full
   * encoding including tag and length.  The structure and encoding of
   * Oids is defined in ISOIEC-8824 and ISOIEC-8825.  This method is
   * identical in functionality to its streaming counterpart.
   *
   * @param derOid Byte array storing a DER encoded oid.
   * @throws GSSException If the DER bytes are badly formed.
   */
  public Oid(byte[] derOid) throws GSSException
  {
    this(new ByteArrayInputStream(derOid));
    this.derOid = (byte[]) derOid.clone();
  }

  Oid(int[] components)
  {
    this.components = components;
    relative = false;
  }

  // Instance methods.
  // -------------------------------------------------------------------------

  /**
   * Returns a string representation of the oid's integer components in
   * dot separated notation (e.g. "1.2.840.113554.1.2.2").
   *
   * @return The string representation of this oid.
   */
  public String toString()
  {
    if (strOid == null)
      {
        StringBuffer buf = new StringBuffer();
        for (int i = 0; i < components.length; i++)
          {
            buf.append(components[i]);
            if (i < components.length - 1)
              buf.append('.');
          }
        strOid = buf.toString();
      }
    return strOid;
  }

  /**
   * Returns the full ASN.1 DER encoding for this oid object, which
   * includes the tag and length.
   *
   * @return The ASN.1 DER encoding for this oid.
   * @throws GSSException If encoding fails.
   */
  public byte[] getDER() throws GSSException
  {
    if (derOid == null)
      {
        ByteArrayOutputStream out = new ByteArrayOutputStream(256);
        try
          {
            int i = 0;
            if (!relative)
              {
                int b = components[i++] * 40 + (components.length > 1
                                                ? components[i++] : 0);
                encodeSubId(out, b);
              }
            for ( ; i < components.length; i++)
              encodeSubId(out, components[i]);
            byte[] oid = out.toByteArray();
            out.reset();
            if (relative)
              out.write(RELATIVE_OID);
            else
              out.write(OBJECT_IDENTIFIER);
            if (oid.length < 128)
              out.write(oid.length);
            else if (oid.length < 256)
              {
                out.write(0x81);
                out.write(oid.length);
              }
            else if (oid.length < 65536)
              {
                out.write(0x82);
                out.write((oid.length >>> 8) & 0xFF);
                out.write(oid.length & 0xFF);
              }
            else if (oid.length < 16777216)
              {
                out.write(0x83);
                out.write((oid.length >>> 16) & 0xFF);
                out.write((oid.length >>>  8) & 0xFF);
                out.write(oid.length & 0xFF);
              }
            else
              {
                out.write(0x84);
                out.write((oid.length >>> 24) & 0xFF);
                out.write((oid.length >>> 16) & 0xFF);
                out.write((oid.length >>>  8) & 0xFF);
                out.write(oid.length & 0xFF);
              }
            out.write(oid);
          }
        catch (IOException ioe)
          {
            throw new GSSException(GSSException.FAILURE);
          }
        derOid = out.toByteArray();
      }
    return (byte[]) derOid.clone();
  }

  /**
   * A utility method to test if an Oid object is contained within the
   * supplied Oid object array.
   *
   * @param oids An array of oids to search.
   * @return True if this oid is contained in the given array.
   */
  public boolean containedIn(Oid[] oids)
  {
    for (int i = 0; i < oids.length; i++)
      {
        if (equals(oids[i]))
          return true;
      }
    return false;
  }

  public boolean equals(Object o)
  {
    if (!(o instanceof Oid))
      return false;
    Oid that = (Oid) o;
    return Arrays.equals(components, that.components);
  }

  public int hashCode()
  {
    int code = 0;
    for (int i = 0; i < components.length; i++)
      code += components[i];
    return code;
  }

  // Own methods.
  // -------------------------------------------------------------------------

  private static void encodeSubId(OutputStream out, int id) throws IOException
  {
    if (id < 128)
      {
        out.write(id);
      }
    else if (id < 16384)
      {
        out.write((id >>> 7) | 0x80);
        out.write(id & 0x7F);
      }
    else if (id < 2097152)
      {
        out.write((id >>> 14) | 0x80);
        out.write(((id >>> 7) | 0x80) & 0xFF);
        out.write(id & 0x7F);
      }
    else if (id < 268435456)
      {
        out.write( (id >>> 21) | 0x80);
        out.write(((id >>> 14) | 0x80) & 0xFF);
        out.write(((id >>>  7) | 0x80) & 0xFF);
        out.write(id & 0x7F);
      }
  }
}
