/*
 * Copyright 
 *   2008 axYus - www.axyus.com
 *   2008 L.Meckert - laurent.meckert@axyus.com
 * 
 * This file is part of XEMELIOS.
 * 
 * XEMELIOS is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 * 
 * XEMELIOS is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with XEMELIOS; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */
package fr.gouv.finances.cp.xemelios.plugin.signature;

import java.security.cert.X509Certificate;// juste pour main
/**
 *   classe pour encapsuler la verification d'une signature
 *  Implementation avec la librarie xmlsec / libxml en JNI (d'ou le prefixe LXJNI)
 */
public class LXJNISignatureVerifier extends SignatureVerifier {

    /**
     *  Constructeur sans parametre
     */
    public LXJNISignatureVerifier() {
      

    }

    /**
     *  Appelle au besoin les initialisations necessaires
     * @throws java.lang.Exception 
     */
    public void initialize() throws Exception {
        int resinit = nativeInitialize();
        if (resinit < 0) {
            status = -1;
        }
    }

   public boolean hasCertificatesValidation() {
      return false;
   }

 public boolean hasPostTrait() {
      return false;
   }
   public   boolean postTraitement(String outfilename) throws Exception {
      return false;
   }



    /**
     *  Verifie la signature de la chaine Xml passee en parametre
     *  le statut complet ( de type bitmask)  sera accessible par getStatus()
     *  si succes = la signature proprement dite sera recuperable
     *  en appelant getSignatureAsXmlString()
     *@return  true si le digest est OK false sinon
     *@throws java.lang.Exception 
     * @param s une chaine xml signee
     */
    public boolean verifyXml(String s) throws Exception {
        return false; // TODO

    }

    /**
     * Verifie la signature du fichier passee en parametre
     *@return  true si le digest est OK false sinon
     *@throws java.lang.Exception 
     * @param signatureFileName un fichier xml signe
     */
    public boolean verifyFile(String signatureFileName) throws Exception {
        if (isDoSchemaValidation()) {
            nativeDoSchemaValidation(1);
        } else {
            nativeDoSchemaValidation(0);
        }
        status = testFromJava(signatureFileName, isDoSchemaValidation() ? getExternalDTD() : "");
        //System.out.println("Status =" + status);
        if (signatureFound()) {
            // on ne sait gerer qu'une signature je fais les incrementations ici
            int istatus = 0;
            incrFoundSignatures();
            if (digestValid()) {
                incrValidatedSignatures();
                istatus = setDigestValid(true, istatus);
            }
            addSignatureAsXmlString(getSignature());
            CertificateExtractor cext = new CertificateExtractor(getSignatureAsXmlString());
            X509Certificate certif = cext.getCertificate();
             addCert(certif);
            if (certif != null) {
                setIsX509Cert(true);
                 istatus = setIsX509Cert(true, istatus);
            }
             this.addindividualStatus(istatus);
            return true;
        } else {
            return false;
        }
    }

    /**
     * Procede au besoin aux nettoyages apres execution
     * @throws java.lang.Exception 
     */
    public void terminate() throws Exception {
        nativeTerminate();
    }

    static {
        try {
            // System.out.println("Chargement de VerifyXmlsec");
            // Charger la DLL en C elle doit etre sur place ou dans les emplacements standard    
            // (PATH windows etc ) ainsi que les dlls qu'elle appelle
           // ici ca craint il faut que la dll soit toujours chargee dans le meme lass loader
           // (en fait elle ne peut pas etre dechargee)
           // sinon
           //      [java] java.lang.UnsatisfiedLinkError: Native Library C:\devel\XEMELIOS\src
           // \xemelios-core\lib\VerifyXmlsec.dll already loaded in another classloader
           //      [java]     at java.lang.ClassLoader.loadLibrary0(ClassLoader.java:1716)
           //      [java]     at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1676)
           //      [java]     at java.lang.Runtime.loadLibrary0(Runtime.java:823)
           //      [java]     at java.lang.System.loadLibrary(System.java:1030)
           // d'ou l'emplacement de la presente classe dans le jar de signature-verify
           //
         
            System.loadLibrary("VerifyXmlsec");
            System.out.println("Chargement de VerifyXmlsec OK");

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

    //Methodes appelle en C 
    /**
     * 
     * @param filename
     * @param dtdfilename
     * @return 1/0 succes/echec
     */
    public native int testFromJava(String filename, String dtdfilename);

    /**
     * 
     * @return la signature trouvee (ne sait pas en trouver plusieurs)
     */
    public native String getSignature();

    /**
     * 
     * @param doIt
     * @return 1/0 succes/echec
     */
    public native int nativeDoSchemaValidation(int doIt);

    /**
     * 
     * @return 1/0 succes/echec
     */
    public native int nativeInitialize();

    /**
     * 
     */
    public native void nativeTerminate();

    /**
     * 
     * @param args
     */
    public static void main(String args[]) {
        // check args
        String fileToVerify = null;
        String optionalDTD = null;
        if (args.length > 0) {
            fileToVerify = args[0];
            if (args.length > 1) {
                optionalDTD = args[1];
            }
        } else {

            System.err.println("Usage java LXJNIGlobalSignatureVerifier <fichier_a_verifier> [<fichierDTD>]");
            System.exit(1);
        }



        LXJNISignatureVerifier verifier = new LXJNISignatureVerifier();
        try {
            verifier.initialize();
            if (optionalDTD != null) {
                verifier.setExternalDTD(optionalDTD);
                verifier.setDoSchemaValidation(true);
            }
            if (verifier.getStatus() == 0) {
                verifier.verifyFile(fileToVerify);

                System.out.println("Element signature as xmlString =" + verifier.getSignatureAsXmlString());
                for (int i = 0; i < verifier.getCertVectorSize(); ++i) {
                    X509Certificate cert = verifier.getCert(i);
                    if (cert != null) {
                        System.out.println("PRINTING CERT=");
                        System.out.println(cert);
                    }
                }
                System.out.println(verifier.getStatusAsString());
            }
            verifier.terminate();
        } catch (Exception e) {
            e.printStackTrace();
        }

    }
}



