/*
 * The Apache Software License, Version 1.1
 *
 *
 * Copyright (c) 1999 The Apache Software Foundation.  All rights
 * reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. The end-user documentation included with the redistribution,
 *    if any, must include the following acknowledgment:
 *       "This product includes software developed by the
 *        Apache Software Foundation (http://www.apache.org/)."
 *    Alternately, this acknowledgment may appear in the software itself,
 *    if and wherever such third-party acknowledgments normally appear.
 *
 * 4. The names "<WebSig>" and "Apache Software Foundation" must
 *    not be used to endorse or promote products derived from this
 *    software without prior written permission. For written
 *    permission, please contact apache@apache.org.
 *
 * 5. Products derived from this software may not be called "Apache",
 *    nor may "Apache" appear in their name, without prior written
 *    permission of the Apache Software Foundation.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation and was
 * originally based on software copyright (c) 2001, Institute for
 * Data Communications Systems, <http://www.nue.et-inf.uni-siegen.de/>.
 * The development of this software was partly funded by the European
 * Commission in the <WebSig> project in the ISIS Programme.
 * For more information on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 */
package ant;



import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;

import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.Task;


/**
 * Class Md5Task
 *
 * @author $Author: geuerp $
 * @version $Revision: 1.3 $
 */
public class Md5Task extends Task {

   /** Field _md5Str */
   private byte[] _md5Str = null;

   /** Field _sha1Str */
   private byte[] _sha1Str = null;

   /** Field _filename */
   private String _filename = null;

   /**
    * Method execute
    *
    * @throws BuildException
    */
   public void execute() throws BuildException {

      if ((this._md5Str == null) && (this._sha1Str == null)) {
         throw new BuildException(
            "You must supply either a SHA1 or MD5 hash value or both, using the Sha1=\"\" and Md5=\"\" attributes");
      }

      if (this._filename == null) {
         throw new BuildException(
            "You must supply a file name using the file=\"\" attribute");
      }

      File f = new File(this._filename);

      if (!f.isFile() ||!f.canRead() ||!f.exists()) {
         throw new BuildException("Could not open " + this._filename
                                  + " for reading");
      }

      try {
         byte[] bytes = Md5Task.getBytesFromFile(this._filename);
         MessageDigest sha1 = MessageDigest.getInstance("SHA-1", "SUN");
         MessageDigest md5 = MessageDigest.getInstance("MD5", "SUN");

         sha1.update(bytes);
         md5.update(bytes);

         byte[] sha1dig = sha1.digest();
         byte[] md5dig = md5.digest();

         if (!MessageDigest.isEqual(this._sha1Str, sha1dig)
                 ||!MessageDigest.isEqual(this._md5Str, md5dig)) {
            System.out.println("Warning!!!");

            if (!MessageDigest.isEqual(this._sha1Str, sha1dig)) {
               System.out.println("The SHA1 hash value of " + this._filename
                                  + " is corrupted:");
               System.out.println("   was           "
                                  + HexDump.byteArrayToHexString(sha1dig));
               System.out
                  .println("   but should be "
                           + HexDump.byteArrayToHexString(this._sha1Str));
               System.out.println("");
            }

            if (!MessageDigest.isEqual(this._md5Str, md5dig)) {
               System.out.println("The MD5 hash value of " + this._filename
                                  + " is corrupted:");
               System.out.println("   was           "
                                  + HexDump.byteArrayToHexString(md5dig));
               System.out.println("   but should be "
                                  + HexDump.byteArrayToHexString(this._md5Str));
               System.out.println("");
            }

            throw new BuildException(
               "The digest values don't match; possibly the file "
               + this._filename + " was modified during download");
         }

         System.out.println("The hash values of " + this._filename + " are OK");
      } catch (FileNotFoundException ex) {
         throw new BuildException(ex.getMessage(), ex);
      } catch (IOException ex) {
         throw new BuildException(ex.getMessage(), ex);
      } catch (NoSuchAlgorithmException ex) {
         throw new BuildException(ex.getMessage(), ex);
      } catch (NoSuchProviderException ex) {
         throw new BuildException(ex.getMessage(), ex);
      }
   }

   /**
    * Method getBytesFromFile
    *
    * @param fileName
    *
    * @throws FileNotFoundException
    * @throws IOException
    */
   public static byte[] getBytesFromFile(String fileName)
           throws FileNotFoundException, IOException {

      byte refBytes[] = null;

      {
         FileInputStream fisRef = new FileInputStream(fileName);
         ByteArrayOutputStream baos = new ByteArrayOutputStream();
         byte buf[] = new byte[1024];
         int len;

         while ((len = fisRef.read(buf)) > 0) {
            baos.write(buf, 0, len);
         }

         refBytes = baos.toByteArray();
      }

      return refBytes;
   }

   /**
    * Method setMd5
    *
    * @param md5Str
    */
   public void setMd5(String md5Str) {
      this._md5Str = HexDump.hexStringToByteArray(md5Str);
   }

   /**
    * Method setSha1
    *
    * @param sha1Str
    */
   public void setSha1(String sha1Str) {
      this._sha1Str = HexDump.hexStringToByteArray(sha1Str);
   }

   /**
    * Method setFile
    *
    * @param fileStr
    */
   public void setFile(String fileStr) {
      this._filename = fileStr;
   }
}
