#include <com_mysaifu_jvm_java_security_provider_WCEKeyStoreSpi.h>
#include "wcesecurity.h"
#include "KeyStore.h"
#include <assert.h>


/*
 * Class:     com_mysaifu_jvm_java_security_provider_WCEKeyStoreSpi
 * Method:    getNativeCertContext
 * Signature: (ILjava/lang/String;)I
 */
JNIEXPORT jint JNICALL Java_com_mysaifu_jvm_java_security_provider_WCEKeyStoreSpi_getNativeCertContext
  (JNIEnv *env, jobject, jint nativePointer, jstring alias)
{
  if (! nativePointer)
  {
    return 0;
  }
  KeyStore* pKeyStore = reinterpret_cast<KeyStore*>(nativePointer);
  assert(pKeyStore);
  _TCHAR* name = getString(env, alias);
  PCCERT_CONTEXT result = pKeyStore->getCertContext(name);
  free(name);
  return reinterpret_cast<jint>(result);
}

/*
 * Class:     com_mysaifu_jvm_java_security_provider_WCEKeyStoreSpi
 * Method:    engineNativeGetCertificateChain
 * Signature: (ILjava/lang/String;)[[B
 */
JNIEXPORT jobjectArray JNICALL Java_com_mysaifu_jvm_java_security_provider_WCEKeyStoreSpi_engineNativeGetCertificateChain
  (JNIEnv *env, jobject, jint nativePointer, jstring alias)
{
  if (! nativePointer)
  {
    return NULL;
  }
  KeyStore* pKeyStore = reinterpret_cast<KeyStore*>(nativePointer);

  _TCHAR* name = getString(env, alias);
  PCCERT_CONTEXT certificate = pKeyStore->getCertContext(name);
  free(name);

  if (! certificate)
  {
    return NULL;
  }

  // 証明書チェーンを得る
  static LPSTR usage[] =
  {
    // サーバ証明書用
    szOID_PKIX_KP_SERVER_AUTH,
    szOID_SERVER_GATED_CRYPTO,
    szOID_SGC_NETSCAPE,

    // クライアント証明書用
    szOID_PKIX_KP_CLIENT_AUTH
  };

  CERT_CHAIN_PARA chain_para = { sizeof(CERT_CHAIN_PARA) };
  chain_para.RequestedUsage.dwType = USAGE_MATCH_TYPE_OR;
  chain_para.RequestedUsage.Usage.rgpszUsageIdentifier = usage;
  chain_para.RequestedUsage.Usage.cUsageIdentifier = sizeof (usage) / sizeof (LPSTR);
  PCCERT_CHAIN_CONTEXT pChain;
  BOOL success = ::CertGetCertificateChain(NULL,                    // hChainEngine
                                        certificate,             // pCertContext
                                        NULL,                    // pTime
                                        certificate->hCertStore, // hAdditionalStore
                                        &chain_para,             // pChainPara
                                        0,                       // dwFlags
                                        NULL,                    // pvReserved
                                        &pChain);
  jobjectArray result = NULL;
  if (success)
  {
    result = ::createEncodedCertificates(env, pChain);
    ::CertFreeCertificateChain(pChain);
  }
  
  return result;
}

/*
 * Class:     com_mysaifu_jvm_java_security_provider_WCEKeyStoreSpi
 * Method:    getNativeAliases
 * Signature: (I)Ljava/util/Vector;
 */
JNIEXPORT jobject JNICALL Java_com_mysaifu_jvm_java_security_provider_WCEKeyStoreSpi_getNativeAliases
  (JNIEnv *env, jobject, jint nativePointer)
{
  if (! nativePointer)
  {
    return NULL;
  }

  KeyStore* pKeyStore = reinterpret_cast<KeyStore*>(nativePointer);
  
  jclass clazz = env->FindClass("java/util/Vector");
  if (! clazz)
  {
    return NULL;
  }
  jmethodID constructor_mid = env->GetMethodID(clazz, "<init>", "()V");
  if (! constructor_mid)
  {
    return NULL;
  }
  
  jobject result = env->NewObject(clazz, constructor_mid);
  jmethodID mid = env->GetMethodID(clazz, "add", "(Ljava/lang/Object;)Z");
  if (! mid)
  {
    return NULL;
  }

  for (int i = 0; i < pKeyStore->getElementCount(); ++i)
  {
    const _TCHAR* name = pKeyStore->getAlias(i);
    jstring alias = env->NewString(reinterpret_cast<const jchar*>(name), _tcslen(name));
    env->CallBooleanMethod(result, mid, alias);
  }
  return result;
}
