/**
 *
 */

import org.mozilla.jss.CryptoManager;
import org.mozilla.jss.crypto.X509Certificate;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.security.cert.CertificateEncodingException;
import java.util.Arrays;
import java.util.Comparator;
import java.text.Collator;

public class dumpCerts
{
  /**
   * <code>getCertificatePEM</code>
   * Returns a PEM representation of the passed in certificate.
   *
   * @return a <code>String</code> value.
   * @exception CertificateEncodingException if the presented certificate is not valid.
   */
  public static String getCertificatePEM(X509Certificate cert) throws CertificateEncodingException
  {
    if(cert == null) {
      return (null);
    }

    byte[] certBytes = cert.getEncoded();

    return (PEM_BEGIN_HEADER +
            '\n' +
            new sun.misc.BASE64Encoder().encode(certBytes) +
            '\n' +
            PEM_END_HEADER +
            '\n');
  }/* *** end *** getCertificatePEM() */


  public static void main(String args[])
  {

    try {

      if(args.length != 2) {
        System.out.println("Usage: dumpCerts <sec db dir> <output file>");
        return;
      }
      String dir = args[0];
      String bundleFileName = args[1];

      CryptoManager.initialize(dir);

      CryptoManager cm = CryptoManager.getInstance();

      X509Certificate[] certs = cm.getCACerts();

      // sort the certs alphabetically by nickname
      Arrays.sort(certs, new cmprtr());

      System.out.println("Generating " + bundleFileName + " with " + certs.length + " certificates");

      FileWriter bundle = new FileWriter(bundleFileName);

      for(int i = 0; i < certs.length; i++) {
        File tf = File.createTempFile(TEMP_PREFIX, null);
        String tempFileName = tf.getAbsolutePath(); //+File.pathSeparator+tf.getName();
        FileWriter tmpFile = new FileWriter(tf);
        tmpFile.write(getCertificatePEM(certs[i]));
        tmpFile.close();

        String nick = certs[i].getNickname();
        String name;

        if(nick.startsWith(NICK_START)) {
          name = nick.substring(NICK_START.length());
        } else {
          name = certs[i].getSubjectDN().getName();
        }

        String CMD[] = {CREATE_SHELL_SCRIPT, name, tempFileName};

        Process cmd = Runtime.getRuntime().exec(CMD);

        cmd.waitFor(); // wait for the command to finish executing

        writeInputStreamTo(cmd.getInputStream(), bundle);
      }

      bundle.close();

    } catch(Exception e) {
      e.printStackTrace();
    }
  }


  private static void writeInputStreamTo(InputStream inputStream, FileWriter fw) throws IOException
  {
    int ch;
    while((ch = inputStream.read()) != -1) {
      fw.write(ch);
    }
  }


  private static final String PEM_BEGIN_HEADER = "-----BEGIN CERTIFICATE-----";
  private static final String PEM_END_HEADER = "-----END CERTIFICATE-----";
  private static final String NICK_START = "Builtin Object Token:";
  private static final String TEMP_PREFIX = "CertCaBundleUtil";
  private static final String CREATE_SHELL_SCRIPT = "./create_bundle.sh";
}

class cmprtr implements Comparator
{
  private Collator collator = Collator.getInstance();

  public int compare(Object o1, Object o2)
  {
    return (collator.compare(
            ((X509Certificate) o1).getNickname(),
            ((X509Certificate) o2).getNickname()));
  }
}
