//////////////////////////////////////////////////////////////////////////// 
// 
// 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.gssapi;

/**
 * This exception is thrown whenever a fatal GSS-API error occurs
 * including mechanism specific errors. It may contain both, the major
 * and minor, GSS-API status codes. The mechanism implementers are
 * responsible for setting appropriate minor status codes when throwing
 * this exception. Aside from delivering the numeric error code(s) to
 * the caller, this class performs the mapping from their numeric values
 * to textual representations.  All Java GSS-API methods are declared
 * throwing this exception.
 *
 * @author Anthony Ho
 */
public class GSSException extends Exception
{
  public static final int BAD_MECH = 1;
  public static final int BAD_NAME = 2;
  public static final int BAD_NAMETYPE = 3;
  public static final int BAD_BINDINGS = 4;
  public static final int BAD_STATUS = 5;
  public static final int BAD_MIC = 6;
  public static final int NO_CRED = 7;
  public static final int NO_CONTEXT = 8;
  public static final int DEFECTIVE_TOKEN = 9;
  public static final int DEFECTIVE_CREDENTIAL = 10;
  public static final int CREDENTIALS_EXPIRED = 11;
  public static final int CONTEXT_EXPIRED = 12;
  public static final int FAILURE = 13;
  public static final int BAD_QOP = 14;
  public static final int UNAUTHORIZED = 15;
  public static final int UNAVAILABLE = 16;
  public static final int DUPLICATE_ELEMENT = 17;
  public static final int NAME_NOT_MN = 18;

  private int majorCode;
  private int minorCode;
  private String minorString = "";
  
  /** 
   * Creates a GSSException object with a specified major code.
   */
  public GSSException(int majorCode)
  {
    this.majorCode = majorCode;  
  }
  
  /** 
   * Creates a GSSException object with the specified major code, minor
   * code, and minor code textual explanation. This constructor is to be
   * used when the exception is originating from the security mechanism.
   * It allows to specify the GSS code and the mechanism code.
   */
  public GSSException(int majorCode, int minorCode, String minorString)
  {
    this.majorCode = majorCode;
    this.minorCode = minorCode;
    this.minorString = minorString;
  }

  /**
   * Returns the major code representing the GSS error code that caused
   * this exception to be thrown.
   */
  public int getMajor()
  {
    return this.majorCode;
  }

  /**
   * Returns the mechanism error code that caused this exception. The
   * minor code is set by the underlying mechanism. Value of 0 indicates
   * that mechanism error code is not set.
   */
  public int getMinor()
  {
    return this.minorCode;
  }

  /**
   * Returns a string explaining the GSS major error code causing this
   * exception to be thrown.
   */
  public String getMajorString()
  {
    String majorString = "";
    
    // Get error string corresponding to given error code
    switch (majorCode)
    {
      case BAD_MECH:
        majorString =
          "An unsupported mechanism was requested.\n";
        break;
      case BAD_NAME:
        majorString =
          "An invalid name was supplied.\n";
        break;
      case BAD_NAMETYPE:
        majorString =
          "A supplied name was of an unsupported type.\n";
        break;
      case BAD_BINDINGS:
        majorString =
          "Incorrect channel bindings were supplied.\n";
        break;
      case BAD_STATUS:
        majorString =
          "An invalid status code was supplied.\n";
        break;
      case BAD_MIC:
        majorString =
          "A token had an invalid MIC.\n";
        break;
      case NO_CRED:
        majorString =
          "No credentials were supplied, "
          + "or the credentials were unavailable or inaccessible.\n";
        break;
      case NO_CONTEXT:
        majorString =
          "Invalid context has been supplied.\n";
        break;
      case DEFECTIVE_TOKEN:
        majorString =
          "A supplied token was invalid.\n";
        break;
      case DEFECTIVE_CREDENTIAL:
        majorString =
          "A supplied credential was invalid.\n";
        break;
      case CREDENTIALS_EXPIRED:
        majorString =
          "The referenced credentials have expired.\n";
        break;
      case CONTEXT_EXPIRED:
        majorString =
          "The context has expired.\n";
        break;
      case FAILURE:
        majorString =
          "Miscellaneous failure, unspecified at the GSS-API level.\n";
        break;
      case BAD_QOP:
        majorString =
          "The quality-of-protection requested could not be provided.\n";
        break;
      case UNAUTHORIZED:
        majorString =
          "The operation is forbidden by local security policy.\n";
        break;
      case UNAVAILABLE:
        majorString =
          "The operation or option is unavailable.\n";
        break;
      case DUPLICATE_ELEMENT:
        majorString =
          "The requested credential element already exists.\n";
        break;
      case NAME_NOT_MN:
        majorString =
         "The provided name was not a mechanism name.\n";
        break;
    }
    return majorString;
  }
  
   /**
    * Returns a string explaining the mechanism specific error code.  An
    * empty string will be returned when no mechanism error code has been
    * set.
    */
  public String getMinorString()
  {
    return this.minorString;
  }

  /**
   * Used internally by the GSS-API implementation and the underlying
   * mechanisms to set the minor code and its textual representation.
   */
  public void setMinor(int minorCode, String message)
  {
    this.minorCode = minorCode;
    this.minorString = message;
  }

  /**
   * Returns a textual representation of both the major and minor status
   * codes.
   */
  public String toString()
  {
    return (getMajorString() + this.minorString);
  }

  /**
   * Returns a detailed message of this exception.  Overrides
   * Throwable.getMessage.  It is customary in Java to use this method to
   * obtain exception information.
   */
  public String getMessage()
  {
    return this.toString();
  }
}
