/**
   * Sanitize a given list of files
   *
   * @param files the list to sanitize
   * @return a new list containing no duplicates.
   * @throws DifferentLibException
   * @throws Sha1Exception
   */
  public List<File> sanitize(Collection<File> files) throws DifferentLibException, Sha1Exception {
    List<File> results = new ArrayList<File>();

    // get the cache list.
    Map<String, JarEntity> jarList = getCachedJarList();

    boolean updateJarList = false;

    // clean it up of removed files.
    // use results as a temp storage to store the files to remove as we go through the map.
    for (JarEntity entity : jarList.values()) {
      if (entity.getFile().exists() == false) {
        results.add(entity.getFile());
      }
    }

    // the actual clean up.
    if (results.size() > 0) {
      for (File f : results) {
        jarList.remove(f.getAbsolutePath());
      }

      results.clear();
      updateJarList = true;
    }

    Map<String, List<JarEntity>> nameMap = new HashMap<String, List<JarEntity>>();

    // update the current jar list if needed, while building a secondary map based on
    // filename only.
    for (File file : files) {
      String path = file.getAbsolutePath();
      JarEntity entity = jarList.get(path);

      if (entity == null) {
        entity = new JarEntity(file);
        jarList.put(path, entity);
        updateJarList = true;
      } else {
        updateJarList |= entity.checkValidity();
      }

      String filename = file.getName();
      List<JarEntity> nameList = nameMap.get(filename);
      if (nameList == null) {
        nameList = new ArrayList<JarEntity>();
        nameMap.put(filename, nameList);
      }
      nameList.add(entity);
    }

    try {
      // now look for duplicates. Each name list can have more than one file but they must
      // have the same size/sha1
      for (Entry<String, List<JarEntity>> entry : nameMap.entrySet()) {
        List<JarEntity> list = entry.getValue();
        checkEntities(entry.getKey(), list);

        // if we are here, there's no issue. Add the first of the list to the results.
        results.add(list.get(0).getFile());
      }

      // special case for android-support-v4/13
      checkSupportLibs(nameMap, results);
    } finally {
      if (updateJarList) {
        writeJarList(nameMap);
      }
    }

    return results;
  }