Index: lucene/tools/src/java/org/apache/lucene/validation/LicenseCheckTask.java
===================================================================
--- lucene/tools/src/java/org/apache/lucene/validation/LicenseCheckTask.java	(revision 1309019)
+++ lucene/tools/src/java/org/apache/lucene/validation/LicenseCheckTask.java	(working copy)
@@ -1,6 +1,11 @@
 package org.apache.lucene.validation;
 
 import java.io.File;
+import java.io.FileInputStream;
+import java.io.BufferedReader;
+import java.io.InputStreamReader;
+import java.io.IOException;
+
 import java.util.ArrayList;
 import java.util.Iterator;
 import java.util.LinkedHashMap;
@@ -8,6 +13,10 @@
 import java.util.Locale;
 import java.util.Map;
 
+import java.security.DigestInputStream;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+
 import org.apache.tools.ant.BuildException;
 import org.apache.tools.ant.Project;
 import org.apache.tools.ant.Task;
@@ -19,10 +28,15 @@
 import org.apache.tools.ant.util.FileNameMapper;
 
 /**
- * An ANT task that verifies if JAR file have associated <tt>LICENSE</tt>
- * and <tt>NOTICE</tt> files. 
+ * An ANT task that verifies if JAR file have associated <tt>LICENSE</tt>,
+ * <tt>NOTICE</tt>, and <tt>SHA1</tt> files. 
  */
 public class LicenseCheckTask extends Task {
+
+  public final static String CHECKSUM_TYPE = "SHA1";
+  private static final int CHECKSUM_BUFFER_SIZE = 8 * 1024;
+  private static final int CHECKSUM_BYTE_MASK = 0xFF;
+
   /**
    * All JAR files to check.
    */
@@ -103,7 +117,7 @@
       }
 
       File jarFile = ((FileResource) r).getFile();
-      if (!checkJarFile(jarFile)) {
+      if (! checkJarFile(jarFile) ) {
         errors++;
       }
       checked++;
@@ -121,6 +135,49 @@
   private boolean checkJarFile(File jarFile) {
     log("Scanning: " + jarFile.getPath(), verboseLevel);
 
+    // validate the jar matches against our expected hash
+    final File checksumFile = new File(jarFile.getParent(), 
+                                       jarFile.getName() + "." + CHECKSUM_TYPE);
+    if (! (checksumFile.exists() && checksumFile.canRead()) ) {
+      log("MISSING " +CHECKSUM_TYPE+ " checksum file for: " + jarFile.getPath(), Project.MSG_ERR);
+      return false;
+    } else {
+      final String expectedChecksum = readChecksumFile(checksumFile);
+      try {
+        final MessageDigest md = MessageDigest.getInstance(CHECKSUM_TYPE);
+        byte[] buf = new byte[CHECKSUM_BUFFER_SIZE];
+        try {
+          FileInputStream fis = new FileInputStream(jarFile);
+          try {
+            DigestInputStream dis = new DigestInputStream(fis, md);
+            try {
+              while (dis.read(buf, 0, CHECKSUM_BUFFER_SIZE) != -1) {
+                // NOOP
+              }
+            } finally {
+              dis.close();
+            }
+          } finally {
+            fis.close();
+          }
+        } catch (IOException ioe) {
+          throw new BuildException("IO error computing checksum of file: " + jarFile, ioe);
+        }
+        final byte[] checksumBytes = md.digest();
+        final String checksum = createChecksumString(checksumBytes);
+        if ( ! checksum.equals(expectedChecksum) ) {
+          log("CHECKSUM FAILED for " + jarFile.getPath() + 
+              "(expected: \"" + expectedChecksum + "\" was: \"" + checksum + "\")", 
+              Project.MSG_ERR);
+          return false;
+        }
+
+      } catch (NoSuchAlgorithmException ae) {
+        throw new BuildException("Digest type " + CHECKSUM_TYPE + " not supported by your JVM", ae);
+      }
+    }
+    
+
     // Get the expected license path base from the mapper and search for license files.
     Map<File, LicenseType> foundLicenses = new LinkedHashMap<File, LicenseType>();
     List<File> expectedLocations = new ArrayList<File>();
@@ -176,4 +233,32 @@
 
     return true;
   }
+
+  private static final String createChecksumString(byte[] digest) {
+    StringBuilder checksum = new StringBuilder();
+    for (int i = 0; i < digest.length; i++) {
+      checksum.append(String.format(Locale.ENGLISH, "%02x", 
+                                    CHECKSUM_BYTE_MASK & digest[i]));
+    }
+    return checksum.toString();
+  }
+  private static final String readChecksumFile(File f) {
+    BufferedReader reader = null;
+    try {
+      reader = new BufferedReader(new InputStreamReader
+                                  (new FileInputStream(f), "UTF-8"));
+      try {
+        String checksum = reader.readLine();
+        if (null == checksum || 0 == checksum.length()) {
+          throw new BuildException("Failed to find checksum in file: " + f);
+        }
+        return checksum;
+      } finally {
+        reader.close();
+      }
+    } catch (IOException e) {
+      throw new BuildException("IO error reading checksum file: " + f, e);
+    }
+  }
+
 }
