//////////////////////////////////////////////////////////////////////////// 
// 
// Copyright (C) DSTC Pty Ltd (ACN 052 372 577) 1993, 1994, 1995.
// Unpublished work.  All Rights Reserved.
// 
// The software contained on this media is the property of the
// DSTC Pty Ltd.  Use of this software is strictly in accordance
// with the license agreement in the accompanying LICENSE.DOC 
// file. If your distribution of this software does not contain 
// a LICENSE.DOC file then you have no rights to use this 
// software in any manner and should contact DSTC at the address 
// below to determine an appropriate licensing arrangement.
// 
//      DSTC Pty Ltd
//      Level 7, GP South
//      University of Queensland
//      St Lucia, 4072
//      Australia
//      Tel: +61 7 3365 4310
//      Fax: +61 7 3365 4311
//      Email: jcsi@dstc.qut.edu.au
// 
// This software is being provided "AS IS" without warranty of
// any kind.  In no event shall DSTC Pty Ltd be liable for
// damage of any kind arising out of or in connection with
// the use or performance of this software.
// 
//////////////////////////////////////////////////////////////////////////// 

package com.dstc.security.kerberos.v5;

import java.util.Vector;
import java.util.Enumeration;

import com.dstc.security.kerberos.v5.base.*;

import com.dstc.security.asn1.Asn1Exception;
import com.dstc.security.asn1.Sequence;
import com.dstc.security.asn1.Asn1;
import com.dstc.security.asn1.Explicit;

/**
 * <p>A class representing the Kerberos ASN.1 structure KDC-REQ.
 *
 * <pre>
 *   KDC-REQ ::=  SEQUENCE {
 *                  pvno[1]               INTEGER,
 *                  msg-type[2]           INTEGER,
 *                  padata[3]             SEQUENCE OF PA-DATA OPTIONAL,
 *                  req-body[4]           KDC-REQ-BODY
 *                }
 * </pre>
 *
 * @version 0.98, 98/07/01
 * @author Ming Yung
 */
public final class KDCReq extends Sequence
{
  private static final int pvno = 5;
  private int msgType;
  private PaDataSeq paDataSeq;
  private KDCReqBody reqBody;

  /**
   * Constructs a KDCReq from a msgType, KDCReqBody and a Vector of PaData
   */
  public KDCReq(int msgType, KDCReqBody reqBody, Vector paDatas)
  {
    Explicit exp = new Explicit(Asn1.TAG_CLASS_CONTEXT, 1);
    exp.addComponent(new com.dstc.security.asn1.Integer(pvno));
    addComponent(exp);

    this.msgType = msgType;
    exp = new Explicit(Asn1.TAG_CLASS_CONTEXT, 2);
    exp.addComponent(new com.dstc.security.asn1.Integer(msgType));
    addComponent(exp);

    if (paDatas != null)
    {
      this.paDataSeq = new PaDataSeq(paDatas);
      exp = new Explicit(Asn1.TAG_CLASS_CONTEXT, 3);
      exp.addComponent(paDataSeq);
      addComponent(exp);
    }
      
    this.reqBody = reqBody;
    exp = new Explicit(Asn1.TAG_CLASS_CONTEXT, 4);
    exp.addComponent(reqBody);
    addComponent(exp);
  }

  /**
   * Constructs a KDCReq from a DER encoding.
   */
  public KDCReq(byte[] encoded) throws Asn1Exception, BadVersionException 
  {
    doDecode(encoded);

    Enumeration comps = getComponents().elements();

    Explicit exp = (Explicit)comps.nextElement();
    if (exp.getTagNumber() != 1) 
      throw new Asn1Exception("Bad tag number");
    if (((com.dstc.security.asn1.Integer)exp.getComponent()).getInt() != pvno)
      throw new BadVersionException("Bad version number");

    exp = (Explicit)comps.nextElement();
    if (exp.getTagNumber() != 2)
      throw new Asn1Exception("Bad tag number");
    msgType = ((com.dstc.security.asn1.Integer)exp.getComponent()).getInt();

    exp = (Explicit)comps.nextElement();
    if (exp.getTagNumber() == 3) 
    {
      this.paDataSeq = new PaDataSeq(exp.getComponent().encode());
      exp = (Explicit)comps.nextElement();
    }

    if (exp.getTagNumber() != 4)
      throw new Asn1Exception("Bad tag number");
    reqBody = new KDCReqBody(exp.getComponent().encode());
  }

  /**
   * Returns the msgType for this KDCReq
   */
  public int getMsgType()
  {
    return this.msgType;
  }

  /**
   * Returns a Vector of PaData for this KDCReq.
   */
  public Vector getPadatas()
  {
    return this.paDataSeq.padatas;
  }

  /**
   * <p> An inner class representing an ASN.1 Sequence of PaData.
   */
  protected class PaDataSeq extends Sequence
  {
    private Vector padatas = new Vector();

    /**
     * Constructs a PaDatatSeq from a Vector of PaData.
     */
    protected PaDataSeq(Vector padatas)
    {
      this.padatas = padatas;

      for (int i=0; i<padatas.size(); i++)
      {
        addComponent((Asn1)padatas.elementAt(i));
      }
    }

    /**
     * Constructs a PaDataSeq from a DER encoding.
     */
    protected PaDataSeq(byte[] encoded) throws Asn1Exception
    {
      doDecode(encoded);
      
      for (int i=0; i<components.size(); i++)
      {
        this.padatas.addElement(
          new PaData(((Asn1)components.elementAt(i)).encode()));
      }
    }
  }
}
