/*
 *  Copyright (c) 2006 by Know-Center, Graz, Austria 
 * 
 * This software is the confidential and proprietary information of Know-Center,
 * Graz, Austria. You shall not disclose such Confidential Information and shall
 * use it only in accordance with the terms of the license agreement you entered
 * into with Know-Center.
 * 
 * KNOW-CENTER MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF
 * THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
 * NON-INFRINGEMENT. KNOW-CENTER SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY
 * LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS
 * DERIVATIVES.
 * 
 * $Id: SignatureResponse.java,v 1.4 2006/08/03 07:43:04 wprinz Exp $
 */
package at.knowcenter.wag.egov.egiz.sig;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import org.apache.log4j.Logger;
import at.gv.egiz.pdfas.api.exceptions.PdfAsException;
import at.knowcenter.wag.egov.egiz.cfg.ConfigLogger;
import at.knowcenter.wag.egov.egiz.cfg.PropertyTree;
import at.knowcenter.wag.egov.egiz.cfg.SettingsReader;
import at.knowcenter.wag.egov.egiz.exceptions.SettingNotFoundException;
import at.knowcenter.wag.egov.egiz.exceptions.SettingsException;
import at.knowcenter.wag.egov.egiz.exceptions.SignatureException;
/**
 * The response of a verification.
 * 
 * @author wlackner
 */
public class SignatureResponse
{
  /**
   * The siganture response config key
   */
  private static String SIG_RESP_KEY = "signature.response.";
  /**
   * Default response message
   */
  private static String SIG_RESP_DEFAULT_INFO = "Es ist leider keine nähere Information verfügbar:";
  /**
   * Response value for x509SubjectName_
   */
  private String x509SubjectName_ = null;
  /**
   * Response value for x509IssuerName
   */
  private String x509IssuerName = null;
  /**
   * Response value for x509SerialNumber
   */
  private String x509SerialNumber = null;
  /**
   * Response value for signatureCheckCode_
   */
  private String signatureCheckCode_ = null;
  /**
   * Response value for signatureCheckInfo_
   */
  private String signatureCheckInfo_ = null;
  /**
   * Response value for signatureManifestCheckCode_
   */
  private String signatureManifestCheckCode_ = null;
  /**
   * Response value for signatureManifestCheckInfo_
   */
  private String signatureManifestCheckInfo_ = null;
  /**
   * Response value for certificateCheckCode_
   */
  private String certificateCheckCode_ = null;
  /**
   * Response value for certificateCheckInfo_
   */
  private String certificateCheckInfo_ = null;
  /**
   * The X.509 certificated parsed from the response string.
   */
  protected X509Cert certificate_ = null;
  // [tknall] start qualified certificate
  private boolean qualifiedCertificate = false;
  // [tknall] stop qualified certificate
  
  private boolean publicAuthority = false;
  private String publicAuthorityCode = null;
  
  protected String hashInputData = null;
  
  private PdfAsException verificationImpossibleEx = null;
  
  // /**
  // * Flag the marks that the response is an error response
  // */
  // private boolean isError_ = false;
  //
  // /**
  // * The error code of an external application
  // */
  // private String errorCode_ = null;
  /**
   * The SettingsReader instance
   */
  private SettingsReader settings_ = null;
  /**
   * The logger definition.
   */
  private static final Logger logger_ = ConfigLogger.getLogger(SignatureResponse.class);
  /**
   * 
   * 
   */
  public SignatureResponse()
  {
    try
    {
      loadSettings();
    }
    catch (SignatureException e)
    {
      logger_.warn(e.getMessage(), e);
    }
  }
  /**
   * load the inital signature settings
   * 
   * @throws SignatureException
   * @see SettingsReader
   */
  private void loadSettings() throws SignatureException
  {
    if (settings_ == null)
    {
      try
      {
        settings_ = SettingsReader.getInstance();
      }
      catch (SettingsException e)
      {
        String log_message = "Can not load signature settings. Cause:\n" + e.getMessage();
        logger_.error(log_message);
        throw new SignatureException(101, log_message, e);
      }
    }
  }
  /**
   * @return Returns the certificateCheckCode.
   */
  public String getCertificateCheckCode()
  {
    return certificateCheckCode_;
  }
  /**
   * @param certificateCheckCode
   *          The certificateCheckCode to set.
   */
  public void setCertificateCheckCode(String certificateCheckCode)
  {
    if (logger_.isDebugEnabled())
    {
      logger_.debug("setCertificateCheckCode:" + certificateCheckCode);
    }
    certificateCheckCode_ = certificateCheckCode;
  }
  /**
   * @return Returns the signatureCheckCode.
   */
  public String getSignatureCheckCode()
  {
    return signatureCheckCode_;
  }
  /**
   * @param signatureCheckCode
   *          The signatureCheckCode to set.
   */
  public void setSignatureCheckCode(String signatureCheckCode)
  {
    if (logger_.isDebugEnabled())
    {
      logger_.debug("setSignatureCheckCode:" + signatureCheckCode);
    }
    signatureCheckCode_ = signatureCheckCode;
  }
  /**
   * @return Returns the signatureManifestCheckCode.
   */
  public String getSignatureManifestCheckCode()
  {
    return signatureManifestCheckCode_;
  }
  /**
   * Returns {@code true} if the underlying certificate indicates public authority.
   * @return {@code true} if public authority, {@code false} if not.
   */
  public boolean isPublicAuthority() {
   return this.publicAuthority;
  }
  /**
   * Sets the public authority flag.
   * @param publicAuthority The public authority flag.
   */
   public void setPublicAuthority(boolean publicAuthority) {
      this.publicAuthority = publicAuthority;
   }
   
   /**
    * Returns the public authority code of {@code null} if no code was provided.
    * @return The public authority code.
    */
   public String getPublicAuthorityCode() {
      return this.publicAuthorityCode;
   }
   
   /**
    * Sets the public authority code.
    * @param publicAuthorityCode The public authority code.
    */
   public void setPublicAuthorityCode(String publicAuthorityCode) {
      this.publicAuthorityCode = publicAuthorityCode;
   }
/**
   * @param signatureManifestCheckCode
   *          The signatureManifestCheckCode to set.
   */
  public void setSignatureManifestCheckCode(String signatureManifestCheckCode)
  {
    if (logger_.isDebugEnabled())
    {
      logger_.debug("setSignatureManifestCheckCode:" + signatureManifestCheckCode);
    }
    signatureManifestCheckCode_ = signatureManifestCheckCode;
  }
  /**
   * @return Returns the x509IssuerName.
   */
  public String getX509IssuerName()
  {
    return x509IssuerName;
  }
  /**
   * @param issuerName
   *          The x509IssuerName to set.
   */
  public void setX509IssuerName(String issuerName)
  {
    if (logger_.isDebugEnabled())
    {
      logger_.debug("setX509IssuerName:" + issuerName);
    }
    x509IssuerName = issuerName;
  }
  /**
   * @return Returns the x509SerialNumber.
   */
  public String getX509SerialNumber()
  {
    return x509SerialNumber;
  }
  /**
   * @param serialNumber
   *          The x509SerialNumber to set.
   */
  public void setX509SerialNumber(String serialNumber)
  {
    if (logger_.isDebugEnabled())
    {
      logger_.debug("setX509SerialNumber:" + serialNumber);
    }
    x509SerialNumber = serialNumber;
  }
  /**
   * @return Returns the x509SubjectName.
   */
  public String getX509SubjectName()
  {
    return x509SubjectName_;
  }
  /**
   * @param subjectName
   *          The x509SubjectName to set.
   */
  public void setX509SubjectName(String subjectName)
  {
    if (logger_.isDebugEnabled())
    {
      logger_.debug("setX509SubjectName:" + subjectName);
    }
    x509SubjectName_ = subjectName;
  }
  /**
   * @return Returns the certificateCheckInfo.
   */
  public String getCertificateCheckInfo()
  {
    if (certificateCheckInfo_ == null)
    {
      if (settings_ != null)
      {
        certificateCheckInfo_ = settings_.getValueFromKey(SIG_RESP_KEY + "certificateCheckInfo." + getCertificateCheckCode());
      }
    }
    if (certificateCheckInfo_ == null)
    {
      certificateCheckInfo_ = SIG_RESP_DEFAULT_INFO + getCertificateCheckCode();
    }
    return certificateCheckInfo_;
  }
  /**
   * @param certificateCheckInfo
   *          The certificateCheckInfo to set.
   */
  public void setCertificateCheckInfo(String certificateCheckInfo)
  {
    if (logger_.isDebugEnabled())
    {
      logger_.debug("setCertificateCheckInfo:" + certificateCheckInfo);
    }
    certificateCheckInfo_ = certificateCheckInfo;
  }
  // [tknall] start qualified certificate
  
  /**
   * Returns true if certificate is qualified, false if not.
   * @return true if certificate is qualified, false if not.
   */
  public boolean isQualifiedCertificate() {
	return this.qualifiedCertificate;
  }
  /**
   * Sets the flag for qualified certificate.
   * @param qualifiedCertificate The new qualified certificate status.
   */
  public void setQualifiedCertificate(boolean qualifiedCertificate) {
	  this.qualifiedCertificate = qualifiedCertificate;
  }
  // [tknall] stop qualified certificate
  /**
   * @return Returns the signatureCheckInfo.
   */
  public String getSignatureCheckInfo()
  {
    if (signatureCheckInfo_ == null)
    {
      if (settings_ != null)
      {
        signatureCheckInfo_ = settings_.getValueFromKey(SIG_RESP_KEY + "signatureCheckInfo." + getSignatureCheckCode());
      }
    }
    if (signatureCheckInfo_ == null)
    {
      signatureCheckInfo_ = SIG_RESP_DEFAULT_INFO + getSignatureCheckCode();
    }
    return signatureCheckInfo_;
  }
  /**
   * @param signatureCheckInfo
   *          The signatureCheckInfo to set.
   */
  public void setSignatureCheckInfo(String signatureCheckInfo)
  {
    if (logger_.isDebugEnabled())
    {
      logger_.debug("setSignatureCheckInfo:" + signatureCheckInfo);
    }
    signatureCheckInfo_ = signatureCheckInfo;
  }
  /**
   * @return Returns the signatureManifestCheckInfo.
   */
  public String getSignatureManifestCheckInfo()
  {
    if (signatureManifestCheckInfo_ == null)
    {
      if (settings_ != null)
      {
        signatureManifestCheckInfo_ = settings_.getValueFromKey(SIG_RESP_KEY + "signatureManifestCheckInfo." + getSignatureManifestCheckCode());
      }
    }
    if (signatureManifestCheckInfo_ == null)
    {
      signatureManifestCheckInfo_ = SIG_RESP_DEFAULT_INFO + getSignatureManifestCheckCode();
    }
    return signatureManifestCheckInfo_;
  }
  /**
   * @param signatureManifestCheckInfo
   *          The signatureManifestCheckInfo to set.
   */
  public void setSignatureManifestCheckInfo(String signatureManifestCheckInfo)
  {
    if (logger_.isDebugEnabled())
    {
      logger_.debug("setSignatureManifestCheckInfo:" + signatureManifestCheckInfo);
    }
    signatureManifestCheckInfo_ = signatureManifestCheckInfo;
  }
  /**
   * Returns the X.509 certificate of this response.
   * 
   * @return Returns the X.509 certificate of this response.
   */
  public X509Cert getCertificate()
  {
    return certificate_;
  }
  /**
   * Sets the X.509 certificate of this response.
   * 
   * @param certificate
   *          The X.509 certificate to be set.
   */
  public void setCertificate(X509Cert certificate)
  {
    this.certificate_ = certificate;
  }
  public String getHashInputData()
  {
    return this.hashInputData;
  }
  public void setHashInputData(String hashInputData)
  {
    this.hashInputData = hashInputData;
  }
  public PdfAsException getVerificationImpossibleEx() {
     return verificationImpossibleEx;
  }
  public void setVerificationImpossibleEx(PdfAsException verificationImpossibleEx) {
     this.verificationImpossibleEx = verificationImpossibleEx;
  }
/**
   * Returns a list of Strings each stating one public property of the
   * certificate.
   * 
   * 
   * Such public properties are certificate extensions each being assigned an
   * own OID. For example the public property "Verwaltungseigenschaft" has the
   * OID "1.2.40.0.10.1.1.1".
   * 
   * 
   * This methods reads out the list of possible properties from the config file
   * and compares these to the extensions defined on the certificate. If they
   * match, a String containing useful information about the property is added
   * to the list returned.
   * 
   * 
   * @return Returns the list of Strings representing the public properties of
   *         this certificate, if any.
   * @throws SettingNotFoundException
   */
  public List getPublicProperties() throws SettingNotFoundException
  {
    List props = new ArrayList();
    SettingsReader settings = this.settings_;
    String root_oid = settings.getSetting("oid.root");
    PropertyTree oids = settings.getPTree().getSubTree("oid");
    Set non_critial_oids = this.certificate_.getX509Certificate().getNonCriticalExtensionOIDs();
    Iterator ext_it = non_critial_oids.iterator();
    while (ext_it.hasNext())
    {
      String oid = (String) ext_it.next();
      if (oid.startsWith(root_oid))
      {
        String key = oid.replaceAll("\\.", "_");
        String value = oids.getLastValue(key);
        if (value == null)
        {
          value = oid;
        }
        props.add(value);
      }
    }
    return props;
  }
  /**
   * The toString method
   */
  public String toString()
  {
    String str = "";
    str += "\nSignator:" + getX509SubjectName();
    str += "\nAusteller:" + getX509IssuerName();
    str += "\nSeriennummer:" + getX509SerialNumber();
    str += "\nZertifikat-Code:" + getCertificateCheckCode() + "=" + getCertificateCheckInfo();
    str += "\nSignatur-Check-Code:" + getSignatureCheckCode() + "=" + getSignatureCheckInfo();
    str += "\nManifest-Check-Code:" + getSignatureManifestCheckCode() + "=" + getSignatureManifestCheckInfo();
    return str;
  }
}