/*
 * Copyright 2008 Google Inc.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
package com.google.gwt.tools.apichecker;

import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.core.ext.UnableToCompleteException;
import com.google.gwt.core.ext.typeinfo.NotFoundException;
import com.google.gwt.dev.javac.Shared;
import com.google.gwt.dev.resource.Resource;
import com.google.gwt.dev.util.Util;
import com.google.gwt.dev.util.arg.SourceLevel;
import com.google.gwt.dev.util.log.AbstractTreeLogger;
import com.google.gwt.dev.util.log.PrintWriterTreeLogger;
import com.google.gwt.util.tools.ArgHandlerFlag;
import com.google.gwt.util.tools.ArgHandlerString;
import com.google.gwt.util.tools.ToolBase;

import org.apache.tools.ant.types.ZipScanner;

import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.Reader;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.List;
import java.util.Properties;
import java.util.Set;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;

/**
 * {@link ApiCompatibilityChecker} Main class to check if the new API is
 * compatible with the existing API.
 * 
 * <p>
 * To compute API diffs, follow these 2 steps:
 * <ol>
 * <li>for each of the two repositories, construct an {@link ApiContainer}
 * <li>call getApiDiff on the {@code ApiDiffGenerator}
 * </ol>
 * </p>
 * 
 * <p>
 * An {@code ApiContainer} object is a list of {@link ApiPackage} objects.
 * {@code ApiPackage} objects themselves are list of {@link ApiClass} objects.
 * {@code ApiClass} objects contain list of {@code ApiConstructor},
 * {@code ApiMethod}, and {@code JField} objects.
 * </p>
 * 
 * <p>
 * Each {@code ApiDiffGenerator} object computes the list of intersecting and
 * missing {@link ApiPackageDiffGenerator} objects. Each
 * {@code ApiPackageDiffGenerator} object in turn computes the list of
 * intersecting and missing {@link ApiClassDiffGenerator} objects. Each
 * {@code ApiClassDiffGenerator} object in turn computes the list of
 * intersecting and missing API members. The members are represented by
 * {@link ApiConstructor} for constructors, {@link ApiMethod} for methods, and
 * {@link ApiField} for fields.
 * </p>
 * 
 * <p>
 * For each intersecting API member, a list of {@link ApiChange} objects is
 * stored. Each ApiChange object encodes a specific {@code ApiChange} like
 * adding the 'final' keyword to the API member.
 * 
 */
public class ApiCompatibilityChecker extends ToolBase {

  // TODO(amitmanjhi): check gwt's dev/core/src files. Would need the ability to
  // build TypeOracle from class files

  // TODO(amitmanjhi): better handling of exceptions and exception-chaining.

  static class FileResource extends Resource {
    private final File file;
    private final String path;

    public FileResource(File file, String path) {
      this.file = file;
      this.path = path;
      assert path.endsWith(".java");
      assert file.getAbsolutePath().endsWith(path);
    }

    @Override
    public long getLastModified() {
      return file.lastModified();
    }

    @Override
    public String getLocation() {
      return file.getAbsolutePath();
    }

    @Override
    public String getPath() {
      return path;
    }

    @Override
    public InputStream openContents() {
      try {
        return new FileInputStream(file);
      } catch (FileNotFoundException e) {
        throw new RuntimeException("Unable to open file '" + file.getAbsolutePath() + "'", e);
      }
    }

    @Override
    public boolean wasRerooted() {
      return false;
    }
  }

  static class StaticResource extends Resource {

    private final long lastModified;
    private final String source;
    private final String typeName;

    public StaticResource(String typeName, String source, long lastModified) {
      this.typeName = typeName;
      this.source = source;
      this.lastModified = lastModified;
    }

    @Override
    public long getLastModified() {
      return lastModified;
    }

    @Override
    public String getLocation() {
      return "/mock/" + getPath();
    }

    @Override
    public String getPath() {
      return Shared.toPath(typeName);
    }

    @Override
    public InputStream openContents() {
      return new ByteArrayInputStream(Util.getBytes(source));
    }

    @Override
    public boolean wasRerooted() {
      return false;
    }
  }

  /**
   * Class that specifies a set of
   * {@link com.google.gwt.dev.javac.CompilationUnit CompilationUnit} read from
   * jar files.
   */
  private static class JarFileResources extends Resources {
    private static final String MOCK_PREFIX = "/mock/";
    private static final int MOCK_PREFIX_LENGTH = MOCK_PREFIX.length();

    private final ZipScanner excludeScanner;
    private final Set<String> includedPaths;
    private final JarFile jarFiles[];
    private Set<Resource> resources = null;

    JarFileResources(JarFile[] jarFiles, Set<String> includedPaths, Set<String> excludedPaths,
        TreeLogger logger) {
      super(logger);
      this.jarFiles = jarFiles;
      this.includedPaths = includedPaths;

      // initialize the ant scanner
      excludeScanner = new ZipScanner();
      List<String> list = new ArrayList<String>(excludedPaths);
      excludeScanner.setIncludes(list.toArray(new String[list.size()]));
      excludeScanner.addDefaultExcludes();
      excludeScanner.setCaseSensitive(true);
      excludeScanner.init();
    }

    @Override
    public Set<Resource> getResources() throws IOException {
      if (resources != null) {
        return resources;
      }

      resources = new HashSet<Resource>();
      for (JarFile jarFile : jarFiles) {
        Enumeration<JarEntry> entries = jarFile.entries();
        while (entries.hasMoreElements()) {
          JarEntry jarEntry = entries.nextElement();
          String fileName = jarEntry.toString();
          if (fileName.startsWith(MOCK_PREFIX)) {
            fileName = fileName.substring(MOCK_PREFIX_LENGTH);
          }
          if (fileName.endsWith(".java") && isIncluded(fileName)) {
            // add this compilation unit
            String fileContent = getFileContentsFromJar(jarFile, jarEntry);
            String packageName = extractPackageName(new StringReader(fileContent));
            if (packageName == null) {
              logger.log(TreeLogger.WARN, "Not adding file = " + fileName
                  + ", because packageName = null", null);
            } else {
              if (isValidPackage(packageName, fileName)) {
                // Add if package and fileNames are okay
                long lastModified = jarEntry.getTime();
                if (lastModified < 0) {
                  lastModified = System.currentTimeMillis();
                }
                resources.add(new StaticResource(packageName + "." + getClassName(fileName),
                    fileContent, lastModified));
                logger.log(TreeLogger.DEBUG, "adding pkgName = " + packageName + ", file = "
                    + fileName, null);
              } else {
                logger.log(TreeLogger.SPAM, " not adding file " + fileName, null);
              }
            }
          }
        }
      }
      return resources;
    }

    String getFileContentsFromJar(JarFile jarFile, JarEntry jarEntry) throws IOException {
      StringBuffer fileContent = new StringBuffer();
      InputStream is = jarFile.getInputStream(jarEntry);
      BufferedInputStream bis = new BufferedInputStream(is);
      int length = 500;
      byte buf[] = new byte[length];
      int count = 0;
      while ((count = bis.read(buf, 0, length)) != -1) {
        fileContent.append(new String(buf, 0, count));
        buf = new byte[length];
      }
      bis.close();
      is.close();
      return fileContent.toString();
    }

    private String getClassName(String fileName) {
      int index = fileName.lastIndexOf("/");
      int endOffset = 0;
      if (fileName.endsWith(".java")) {
        endOffset = 5;
      }
      return fileName.substring(index + 1, fileName.length() - endOffset);
    }

    private boolean isIncluded(String fileName) {
      if (excludeScanner.match(fileName)) {
        logger.log(TreeLogger.SPAM, fileName + " is excluded");
        return false;
      }
      for (String includedPath : includedPaths) {
        if (fileName.startsWith(includedPath)) {
          logger.log(TreeLogger.SPAM, fileName + " is not excluded, and is included by "
              + includedPath);
          return true;
        }
      }
      return false;
    }
  }

  /**
   * Abstract internal class that specifies a set of
   * {@link com.google.gwt.dev.javac.CompilationUnit CompilationUnit}.
   */
  private abstract static class Resources {
    protected final TreeLogger logger;

    Resources(TreeLogger logger) {
      this.logger = logger;
    }

    public abstract Set<Resource> getResources() throws NotFoundException, IOException,
        UnableToCompleteException;

    // TODO (amitmanjhi): remove this code. use TypeOracle functionality
    // instead.
    protected String extractPackageName(Reader reader) throws IOException {
      BufferedReader br = new BufferedReader(reader);
      String str = null;
      while ((str = br.readLine()) != null) {
        if (str.indexOf("package") != 0) {
          continue;
        }
        String parts[] = str.split("[\b\t\n\r ]+");
        if ((parts.length == 2) && parts[0].equals("package")) {
          return parts[1].substring(0, parts[1].length() - 1); // the ; char
        }
      }
      return null;
    }

    protected File getFileFromName(String tag, String pathName) throws FileNotFoundException {
      File file = new File(pathName);
      if (!file.exists()) {
        throw new FileNotFoundException(tag + "file " + pathName + " not found");
      }
      return file;
    }

    // TODO (amitmanjhi): remove this code. use TypeOracle functionality
    // instead.
    protected boolean isValidPackage(String packageName, String filePath) {
      logger
          .log(TreeLogger.SPAM, "packageName = " + packageName + ", filePath = " + filePath, null);
      if (packageName == null) {
        return false;
      }
      int lastSlashPosition = filePath.lastIndexOf("/");
      if (lastSlashPosition == -1) {
        return false;
      }
      String dirPath = filePath.substring(0, lastSlashPosition);
      String packageNameAsPath = packageName.replace('.', '/');
      logger.log(TreeLogger.SPAM, "packageNameAsPath " + packageNameAsPath + ", dirPath = "
          + dirPath, null);
      return dirPath.endsWith(packageNameAsPath);
    }
  }

  /**
   * Class that specifies a set of
   * {@link com.google.gwt.dev.javac.CompilationUnit CompilationUnit} read from
   * the file-system.
   */
  private static class SourceFileResources extends Resources {
    private final ZipScanner excludeScanner;
    private final Set<File> includedPaths;
    private Set<Resource> units = null;

    SourceFileResources(String dirRoot, Set<String> includedPathsAsString,
        Set<String> excludedPathsAsString, TreeLogger logger) throws FileNotFoundException,
        IOException {
      super(logger);
      if (dirRoot == null) {
        dirRoot = "";
      }
      includedPaths = new HashSet<File>();
      for (String includedPath : includedPathsAsString) {
        includedPaths.add(getFileFromName("source file: ", dirRoot + includedPath));
      }

      String fullExcludedPaths[] = new String[excludedPathsAsString.size()];
      int count = 0;
      String dirRootAbsolutePath = getFileFromName("dirRoot: ", dirRoot).getAbsolutePath();
      if (dirRootAbsolutePath.startsWith("/") || dirRootAbsolutePath.startsWith("\\")) {
        // Remove initial File.Separator to work with ant versions above and below 1.8.1.
        dirRootAbsolutePath = dirRootAbsolutePath.substring(1);
      }
      for (String excludedPath : excludedPathsAsString) {
        fullExcludedPaths[count++] = dirRootAbsolutePath + "/" + excludedPath;
      }

      // initialize the ant scanner
      excludeScanner = new ZipScanner();
      if (fullExcludedPaths.length > 0) {
        excludeScanner.setIncludes(fullExcludedPaths);
      }
      excludeScanner.addDefaultExcludes();
      excludeScanner.setCaseSensitive(true);
      excludeScanner.init();
    }

    @Override
    public Set<Resource> getResources() throws NotFoundException, IOException,
        UnableToCompleteException {
      if (units != null) {
        return units;
      }

      units = new HashSet<Resource>();
      for (File sourceFile : includedPaths) {
        updateCompilationUnitsInPath(sourceFile);
      }
      return units;
    }

    private boolean isExcludedFile(String fileName) {
      String pattern = "file:";
      if (fileName.indexOf(pattern) == 0) {
        fileName = fileName.substring(pattern.length());
      }
      if (fileName.startsWith("/") || fileName.startsWith("\\")) {
        // Remove initial File.Separator to work with ant versions above and below 1.8.1.
        fileName = fileName.substring(1);
      }
      return excludeScanner.match(fileName);
    }

    private void updateCompilationUnitsInPath(File sourcePathEntry) throws NotFoundException,
        IOException, UnableToCompleteException {
      logger.log(TreeLogger.SPAM, "entering addCompilationUnitsInPath, file = " + sourcePathEntry,
          null);
      File[] files = sourcePathEntry.listFiles();
      if (files == null) { // No files found.
        return;
      }

      for (int i = 0; i < files.length; i++) {
        final File file = files[i];
        logger.log(TreeLogger.SPAM, "deciding the fate of file " + file, null);
        // Ignore files like .svn and .cvs
        if (file.getName().startsWith(".") || file.getName().equals("CVS")) {
          continue;
        }
        if (isExcludedFile(file.getAbsolutePath())) {
          // do not process the subtree
          logger.log(TreeLogger.DEBUG, "not traversing " + file.toURI().toURL(), null);
          continue;
        }
        if (file.isFile()) {
          String fileName = file.getName();
          if (file.getName().endsWith("java")) {
            String className = file.getName().substring(0, fileName.length() - 5);
            String pkgName = extractPackageName(new FileReader(file));
            if (pkgName == null) {
              logger.log(TreeLogger.WARN, "Not adding file = " + file.toString()
                  + ", because packageName = null", null);
            } else {
              if (isValidPackage(pkgName, sourcePathEntry.toURI().toURL().toString())) {
                // Add if the package and fileNames are okay
                String typeName = Shared.makeTypeName(pkgName, className);
                units.add(new FileResource(file, Shared.toPath(typeName)));
                logger.log(TreeLogger.DEBUG, "adding pkgName = " + pkgName + ", file = "
                    + file.toString(), null);
              } else {
                logger.log(TreeLogger.SPAM, " not adding file " + file.toURI().toURL(), null);
              }
            }
          }
        } else {
          // Recurse into subDirs
          updateCompilationUnitsInPath(file);
        }
      }
    }
  }

  // currently doing only source_compatibility. true by default.
  public static final boolean API_SOURCE_COMPATIBILITY = true;

  /**
   * Prints which class the member was declared in plus the string message in
   * ApiChange, false by default.
   */
  public static boolean DEBUG = false;

  public static final boolean DEBUG_DUPLICATE_REMOVAL = false;

  /**
   * Flag for filtering duplicates, true by default. Just for debugging in rare
   * cases.
   */
  public static final boolean FILTER_DUPLICATES = true;

  /**
   * Print APIs common in the two repositories. Should be false by default.
   */
  public static final boolean PRINT_COMPATIBLE = false;
  /**
   * Print APIs common in the two repositories. Should be false by default.
   */
  public static final boolean PRINT_COMPATIBLE_WITH = false;

  /**
   * Flag for debugging whether typeOracle builds.
   */
  public static final boolean PROCESS_EXISTING_API = true;

  /**
   * Flag for debugging whether typeOracle builds.
   */
  public static final boolean PROCESS_NEW_API = true;

  // true by default
  public static final boolean REMOVE_NON_SUBCLASSABLE_ABSTRACT_CLASS_FROM_API = true;

  // remove duplicates by default
  public static Collection<ApiChange> getApiDiff(ApiContainer newApi, ApiContainer existingApi,
      Set<String> whiteList) throws NotFoundException {
    ApiDiffGenerator apiDiff = new ApiDiffGenerator(newApi, existingApi);
    return getApiDiff(apiDiff, whiteList, FILTER_DUPLICATES);
  }

  public static void main(String args[]) {
    try {
      ApiCompatibilityChecker checker = new ApiCompatibilityChecker();
      if (!checker.processArgs(args)) {
        // if we couldn't parse arguments, return non-zero so the build breaks
        System.exit(1);
      }

      ApiContainer newApi = null, existingApi = null;

      AbstractTreeLogger logger = new PrintWriterTreeLogger();
      logger.setMaxDetail(checker.type);
      logger.log(TreeLogger.INFO, "gwtDevJar = " + checker.gwtDevJar + ", userJar = "
          + checker.gwtUserJar + ", refjars = " + Arrays.toString(checker.refJars)
          + ", logLevel = " + checker.type + ", printAllApi = " + checker.printAllApi, null);

      Set<String> excludedPackages = checker.getSetOfExcludedPackages(checker.configProperties);
      if (PROCESS_NEW_API) {
        Set<Resource> resources = new HashSet<Resource>();
        resources.addAll(new SourceFileResources(checker.configProperties
            .getProperty("dirRoot_new"), checker.getConfigPropertyAsSet("sourceFiles_new"), checker
            .getConfigPropertyAsSet("excludedFiles_new"), logger).getResources());
        resources.addAll(checker.getJavaxValidationCompilationUnits(logger));
        resources.addAll(checker.getGwtCompilationUnits(logger));
        SourceLevel newSourceLevel =
            SourceLevel.fromString(checker.configProperties.getProperty("sourceLevel_new"));
        newApi =
            new ApiContainer(checker.configProperties.getProperty("name_new"), resources,
                excludedPackages, logger, newSourceLevel);
        if (checker.printAllApi) {
          logger.log(TreeLogger.INFO, newApi.getApiAsString());
        }
      }
      if (PROCESS_EXISTING_API) {
        Set<Resource> resources = new HashSet<Resource>();
        if (checker.refJars == null) {
          resources.addAll(new SourceFileResources(checker.configProperties
              .getProperty("dirRoot_old"), checker.getConfigPropertyAsSet("sourceFiles_old"),
              checker.getConfigPropertyAsSet("excludedFiles_old"), logger).getResources());
        } else {
          resources.addAll(new JarFileResources(checker.refJars, checker
              .getConfigPropertyAsSet("sourceFiles_old"), checker
              .getConfigPropertyAsSet("excludedFiles_old"), logger).getResources());
        }
        resources.addAll(checker.getJavaxValidationCompilationUnits(logger));
        resources.addAll(checker.getGwtCompilationUnits(logger));
        SourceLevel oldSourceLevel =
            SourceLevel.fromString(checker.configProperties.getProperty("sourceLevel_old"));
        existingApi =
            new ApiContainer(checker.configProperties.getProperty("name_old"), resources,
                excludedPackages, logger, oldSourceLevel);
        if (checker.printAllApi) {
          logger.log(TreeLogger.INFO, existingApi.getApiAsString());
        }
      }

      if (PROCESS_NEW_API && PROCESS_EXISTING_API) {
        Collection<ApiChange> apiDifferences = getApiDiff(newApi, existingApi, checker.whiteList);
        for (ApiChange apiChange : apiDifferences) {
          System.out.println(apiChange);
        }
        if (apiDifferences.size() == 0) {
          System.out.println("API compatibility check SUCCESSFUL");
        } else {
          System.out.println("API compatibility check FAILED");
        }
        System.exit(apiDifferences.size() == 0 ? 0 : 1);
      }

    } catch (Throwable t) {
      // intercepting all exceptions in main, because I have to exit with -1 so
      // that the build breaks.
      try {
        t.printStackTrace();
        System.err
            .println("To view the help for this tool, execute this tool without any arguments");
      } finally {
        System.exit(-1);
      }
    }
  }

  // interface for testing, since do not want to build ApiDiff frequently
  static Collection<ApiChange> getApiDiff(ApiDiffGenerator apiDiff, Set<String> whiteList,
      boolean removeDuplicates) throws NotFoundException {
    Collection<ApiChange> collection = apiDiff.getApiDiff();
    if (removeDuplicates) {
      collection = apiDiff.removeDuplicates(collection);
    }
    Set<String> matchedWhiteList = new HashSet<String>();

    Collection<ApiChange> prunedCollection = new ArrayList<ApiChange>();
    for (ApiChange apiChange : collection) {
      String apiChangeAsString = apiChange.getStringRepresentationWithoutMessage();
      apiChangeAsString = apiChangeAsString.trim();
      if (whiteList.contains(apiChangeAsString)) {
        matchedWhiteList.add(apiChangeAsString);
        continue;
      }
      // check for Status.Compatible and Status.Compatible_with
      if (!PRINT_COMPATIBLE && apiChange.getStatus().equals(ApiChange.Status.COMPATIBLE)) {
        continue;
      }
      if (!PRINT_COMPATIBLE_WITH && apiChange.getStatus().equals(ApiChange.Status.COMPATIBLE_WITH)) {
        continue;
      }
      prunedCollection.add(apiChange);
    }
    whiteList.removeAll(matchedWhiteList);
    if (whiteList.size() > 0) {
      List<String> al = new ArrayList<String>(whiteList);
      Collections.sort(al);
      System.err.println("ApiChanges [");
      for (String apiChange : al) {
        System.err.println(apiChange);
      }
      System.err.println("],  not found. Are you using a properly formatted configuration file?");
    }
    List<ApiChange> apiChangeList = new ArrayList<ApiChange>(prunedCollection);
    Collections.sort(apiChangeList);
    return apiChangeList;
  }

  private Properties configProperties;
  private JarFile[] extraSourceJars;
  private JarFile gwtDevJar;
  private JarFile gwtUserJar;

  // prints the API of the two containers, false by default.
  private boolean printAllApi = false;
  private JarFile refJars[];
  // default log output
  private TreeLogger.Type type = TreeLogger.WARN;
  private Set<String> whiteList;

  protected ApiCompatibilityChecker() {

    /*
     * register handlers for gwtDevJar, gwtUserJar, refJar, logLevel,
     * printAllApi, configProperties
     */

    // handler for gwtDevJar
    registerHandler(new ArgHandlerString() {

      @Override
      public String getPurpose() {
        return "Path of the gwt dev jar";
      }

      @Override
      public String getTag() {
        return "-gwtDevJar";
      }

      @Override
      public String[] getTagArgs() {
        return new String[] {"gwt_dev_jar_path"};
      }

      @Override
      public boolean setString(String str) {
        gwtDevJar = getJarFromString(str);
        return gwtDevJar != null;
      }
    });

    // handler for gwtUserJar
    registerHandler(new ArgHandlerString() {

      @Override
      public String getPurpose() {
        return "Path of the gwt user jar";
      }

      @Override
      public String getTag() {
        return "-gwtUserJar";
      }

      @Override
      public String[] getTagArgs() {
        return new String[] {"gwt_user_jar_path"};
      }

      @Override
      public boolean setString(String str) {
        gwtUserJar = getJarFromString(str);
        return gwtUserJar != null;
      }
    });

    // handler for refJar
    registerHandler(new ArgHandlerString() {
      @Override
      public String getPurpose() {
        return "Path of the reference jar";
      }

      @Override
      public String getTag() {
        return "-refJar";
      }

      @Override
      public String[] getTagArgs() {
        return new String[] {"reference_jar_path"};
      }

      @Override
      public boolean setString(String str) {
        String refJarStrings[] = str.split(System.getProperty("path.separator"));
        refJars = new JarFile[refJarStrings.length];
        int count = 0;
        for (String refJarString : refJarStrings) {
          refJars[count++] = getJarFromString(refJarString);
          if (refJars[count - 1] == null) {
            return false; // bail-out early
          }
        }
        return refJars != null;
      }
    });

    // handler for logLevel
    registerHandler(new ArgHandlerString() {

      @Override
      public String getPurpose() {
        return "Sets the log level of the TreeLogger";
      }

      @Override
      public String getTag() {
        return "-logLevel";
      }

      @Override
      public String[] getTagArgs() {
        String values[] = new String[TreeLogger.Type.values().length];
        int count = 0;
        for (TreeLogger.Type tempType : TreeLogger.Type.values()) {
          values[count++] = tempType.name();
        }
        return values;
      }

      @Override
      public boolean setString(String str) {
        for (TreeLogger.Type tempType : TreeLogger.Type.values()) {
          if (tempType.name().equals(str)) {
            type = tempType;
            return true;
          }
        }
        return false;
      }

    });

    // handler for printAllApi
    registerHandler(new ArgHandlerFlag() {

      @Override
      public String getPurposeSnippet() {
        return "Prints all api.";
      }

      @Override
      public String getLabel() {
        return "printAllApi";
      }

      @Override
      public boolean setFlag(boolean enabled) {
        printAllApi = enabled;
        return true;
      }

      @Override
      public boolean getDefaultValue() {
        return printAllApi;
      }
    });

    // handler for configFile
    registerHandler(new ArgHandlerString() {

      @Override
      public String getPurpose() {
        return "Path of the configuration file";
      }

      @Override
      public String getTag() {
        return "-configFile";
      }

      @Override
      public String[] getTagArgs() {
        return new String[] {"config_file_path"};
      }

      @Override
      public boolean isRequired() {
        return true;
      }

      @Override
      public boolean setString(String str) {
        setPropertiesAndWhitelist(str);
        return configProperties != null && whiteList != null;
      }
    });

    registerHandler(new ArgHandlerString() {

      @Override
      public String getPurpose() {
        return "The location of the javax.validation sources";
      }

      @Override
      public String getTag() {
        return "-validationSourceJars";
      }

      @Override
      public String[] getTagArgs() {
        return new String[] {"jar1.jar:jar2.jar"};
      }

      @Override
      public boolean setString(String str) {
        boolean success = true;
        String[] parts = str.split(System.getProperty("path.separator"));
        extraSourceJars = new JarFile[parts.length];
        for (int i = 0, j = parts.length; i < j; i++) {
          extraSourceJars[i] = getJarFromString(parts[i]);
        }
        return success;
      }
    });
  }

  @Override
  public void printHelp() {
    super.printHelp();
    StringBuffer sb = new StringBuffer();
    sb.append("\n");
    sb.append("The config file must specify two repositories of java source files: ");
    sb.append("'_old' and '_new', which are to be compared for API source compatibility.\n");
    sb.append("An optional whitelist is present at the end of ");
    sb.append("the config file. The format of the whitelist is same as the output of ");
    sb.append("the tool without the whitelist.\n");
    sb.append("Each repository is specified by the following four properties:\n");
    sb.append("name             specifies how the api should be refered to in the output\n");
    sb.append("dirRoot          optional argument that specifies the base directory of all other file/directory names\n");
    sb.append("sourceFiles      a colon-separated list of files/directories that specify the roots of the filesystem trees to be included.\n");
    sb.append("excludeFiles     a colon-separated lists of ant patterns to exclude");
    sb.append("sourceLevel      Java source level compatibility");

    sb.append("\n\n");
    sb.append("Example api.conf file:\n");
    sb.append("name_old         gwtEmulator");
    sb.append("\n");
    sb.append("dirRoot_old      ./");
    sb.append("\n");
    sb.append("sourceFiles_old  dev/core/super:user/super:user/src");
    sb.append("\n");
    sb.append("excludeFiles_old user/super/com/google/gwt/junit/*.java");
    sb.append("\n\n");

    sb.append("name_new         gwtEmulatorCopy");
    sb.append("\n");
    sb.append("dirRoot_new      ../gwt-14/");
    sb.append("\n");
    sb.append("sourceFiles_new  dev/core:user/super:user/src");
    sb.append("\n");
    sb.append("excludeFiles_new user/super/com/google/gwt/junit/*.java");
    sb.append("\n\n");

    System.err.println(sb.toString());
  }

  protected JarFile getJarFromString(String str) {
    try {
      return new JarFile(str);
    } catch (IOException ex) {
      System.err.println("exception in getting jar from fileName: " + str + ", message: "
          + ex.getMessage());
      return null;
    }
  }

  protected void setPropertiesAndWhitelist(String fileName) throws IllegalArgumentException {
    try {
      // load config properties
      FileInputStream fis = new FileInputStream(fileName);
      configProperties = new Properties();
      configProperties.load(fis);
      fis.close();

      // load whitelist
      FileReader fr = new FileReader(fileName);
      whiteList = readWhiteListFromFile(fr);
      fr.close();
    } catch (IOException ex) {
      System.err.println("Have you specified the path of the config file correctly?");
      throw new IllegalArgumentException(ex);
    }
  }

  private Set<String> getConfigPropertyAsSet(String key) {
    Set<String> set = new HashSet<String>();
    String propertyValue = configProperties.getProperty(key);
    if (propertyValue == null) {
      return set;
    }
    for (String element : propertyValue.split(":")) {
      element = element.trim();
      set.add(element);
    }
    return set;
  }

  private Set<Resource> getGwtCompilationUnits(TreeLogger logger) throws FileNotFoundException,
      IOException, NotFoundException, UnableToCompleteException {
    Set<Resource> resources = new HashSet<Resource>();
    if (gwtDevJar == null || gwtUserJar == null) {
      if (gwtDevJar != null) {
        System.err.println("Argument gwtUserJar must be provided for gwtDevJar to be used");
      }
      if (gwtUserJar != null) {
        System.err.println("Argument gwtDevJar must be provided for gwtUserJar to be used");
      }
      return resources;
    }
    // gwt-user.jar
    Set<String> gwtIncludedPaths =
        new HashSet<String>(Arrays.asList(new String[] {"com/google/gwt", "com/google/web"}));
    Set<String> gwtExcludedPaths =
        new HashSet<String>(
            Arrays
                .asList(new String[] {
                    "com/google/gwt/benchmarks",
                    "com/google/gwt/i18n/rebind",
                    "com/google/gwt/i18n/tools",
                    "com/google/gwt/json",
                    "com/google/gwt/junit",
                    "com/google/gwt/user/client/rpc/core/java/util/LinkedHashMap_CustomFieldSerializer.java",
                    "com/google/gwt/user/rebind", "com/google/gwt/user/server",
                    "com/google/gwt/user/tools",}));
    Resources cu =
        new JarFileResources(new JarFile[] {gwtUserJar}, gwtIncludedPaths, gwtExcludedPaths, logger);
    resources.addAll(cu.getResources());

    // gwt-dev-*.jar
    gwtIncludedPaths =
        new HashSet<String>(Arrays.asList(new String[] {
            "com/google/gwt/core/client", "com/google/gwt/dev/jjs/intrinsic/com/google/gwt/lang",
            "com/google/gwt/lang",}));
    cu =
        new JarFileResources(new JarFile[] {gwtDevJar}, gwtIncludedPaths, new HashSet<String>(),
            logger);
    resources.addAll(cu.getResources());
    return resources;
  }

  /**
   * This is a hack to make the ApiChecker able to find the javax.validation
   * sources, which we include through an external jar file.
   */
  private Set<Resource> getJavaxValidationCompilationUnits(TreeLogger logger)
      throws UnableToCompleteException, NotFoundException, IOException {
    Set<Resource> resources = new HashSet<Resource>();
    if (extraSourceJars != null) {
      Resources extra = new JarFileResources(
          extraSourceJars,
          Collections.singleton(""), 
          new HashSet<String>(Arrays.asList(
              "javax/validation/Configuration.java",
              "javax/validation/MessageInterpolator.java",
              "javax/validation/Validation.java",
              "javax/validation/ValidatorContext.java",
              "javax/validation/ValidatorFactory.java",
              "javax/validation/ValidationProviderResolver.java",
              "javax/validation/bootstrap/GenericBootstrap.java",
              "javax/validation/bootstrap/ProviderSpecificBootstrap.java",
              "javax/validation/constraints/Pattern.java",
              "javax/validation/spi/BootstrapState.java",
              "javax/validation/spi/ConfigurationState.java",
              "javax/validation/spi/ValidationProvider.java")), 
          logger);
      Set<Resource> loaded = extra.getResources();
      System.out.println("Found " + loaded.size() + " new resources");
      resources.addAll(loaded);
    }
    return resources;
  }

  /*
   * excludedPackages is used in only one place: to determine whether some class
   * is an api class or not
   */
  private Set<String> getSetOfExcludedPackages(Properties config) {
    String allExcludedPackages = config.getProperty("excludedPackages");
    if (allExcludedPackages == null) {
      allExcludedPackages = "";
    }
    String excludedPackagesArray[] = allExcludedPackages.split(":");
    return new HashSet<String>(Arrays.asList(excludedPackagesArray));
  }

  /**
   * Each whiteList element is an {@link ApiElement} and
   * {@link ApiChange.Status} separated by space. For example,
   * "java.util.ArrayList::size() MISSING". The {@code ApiElement} is
   * represented as the string obtained by invoking the getRelativeSignature()
   * method on {@link ApiElement}.
   */
  private Set<String> readWhiteListFromFile(FileReader fr) throws IOException {
    Set<String> hashSet = new HashSet<String>();
    BufferedReader br = new BufferedReader(fr);
    String str = null;
    while ((str = br.readLine()) != null) {
      str = str.trim();
      // ignore comments
      if (str.startsWith("#")) {
        continue;
      }
      String splits[] = str.split(" ");
      if (splits.length > 1 && ApiChange.contains(splits[1])) {
        String identifier = splits[0] + ApiDiffGenerator.DELIMITER + splits[1];
        hashSet.add(identifier.trim());
      }
    }
    return hashSet;
  }

}
