content: /**
   * Manage rd5 diff-file creation
   *
   * @author ab
   */
  package btools.mapaccess;
  
  import java.io.BufferedInputStream;
  import java.io.File;
  import java.io.FileInputStream;
  import java.io.IOException;
  import java.security.DigestInputStream;
  import java.security.MessageDigest;
  import java.security.NoSuchAlgorithmException;
  
  final public class Rd5DiffManager {
    public static void main(String[] args) throws Exception {
      calcDiffs(new File(args[0]), new File(args[1]));
    }
  
    /**
     * Compute diffs for all RD5 files
     */
    public static void calcDiffs(File oldDir, File newDir) throws Exception {
      File oldDiffDir = new File(oldDir, "diff");
      File newDiffDir = new File(newDir, "diff");
  
      File[] filesNew = newDir.listFiles();
  
      for (File fn : filesNew) {
        String name = fn.getName();
        if (!name.endsWith(".rd5")) {
          continue;
        }
        if (fn.length() < 1024 * 1024) {
          continue; // exclude very small files from diffing
        }
        String basename = name.substring(0, name.length() - 4);
        File fo = new File(oldDir, name);
        if (!fo.isFile()) {
          continue;
        }
  
        // calculate MD5 of old file
        String md5 = getMD5(fo);
  
        String md5New = getMD5(fn);
  
        System.out.println("name=" + name + " md5=" + md5);
  
        File specificNewDiffs = new File(newDiffDir, basename);
        specificNewDiffs.mkdirs();
  
        String diffFileName = md5 + ".df5";
        File diffFile = new File(specificNewDiffs, diffFileName);
  
        String dummyDiffFileName = md5New + ".df5";
        File dummyDiffFile = new File(specificNewDiffs, dummyDiffFileName);
        dummyDiffFile.createNewFile();
  
        // calc the new diff
        Rd5DiffTool.diff2files(fo, fn, diffFile);
  
        // ... and add that to old diff files
        File specificOldDiffs = new File(oldDiffDir, basename);
        if (specificOldDiffs.isDirectory()) {
          File[] oldDiffs = specificOldDiffs.listFiles();
          for (File od : oldDiffs) {
            if (!od.getName().endsWith(".df5")) {
              continue;
            }
            if (System.currentTimeMillis() - od.lastModified() > 9 * 86400000L) {
              continue; // limit diff history to 9 days
            }
  
            File updatedDiff = new File(specificNewDiffs, od.getName());
            if (!updatedDiff.exists()) {
              Rd5DiffTool.addDeltas(od, diffFile, updatedDiff);
              updatedDiff.setLastModified(od.lastModified());
            }
          }
        }
      }
    }
  
    public static String getMD5(File f) throws IOException {
      try {
        MessageDigest md = MessageDigest.getInstance("MD5");
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream(f));
        DigestInputStream dis = new DigestInputStream(bis, md);
        byte[] buf = new byte[8192];
        for (; ; ) {
          int len = dis.read(buf);
          if (len <= 0) {
            break;
          }
        }
        dis.close();
        byte[] bytes = md.digest();
  
        StringBuilder sb = new StringBuilder();
        for (int j = 0; j < bytes.length; j++) {
          int v = bytes[j] & 0xff;
          sb.append(hexChar(v >>> 4)).append(hexChar(v & 0xf));
        }
        return sb.toString();
      } catch (NoSuchAlgorithmException e) {
        throw new IOException("MD5 algorithm not available", e);
      }
    }
  
    private static char hexChar(int v) {
      return (char) (v > 9 ? 'a' + (v - 10) : '0' + v);
    }
  }
  