private String findFullyQualifiedSourceFileName(IClassPath classPath, ClassDescriptor classDesc)
      throws IOException, CheckedAnalysisException {
    try {
      // Open and parse the class file to attempt
      // to discover the source file name.
      ICodeBaseEntry codeBaseEntry = classPath.lookupResource(classDesc.toResourceName());

      ClassParserUsingASM classParser =
          new ClassParserUsingASM(
              new ClassReader(codeBaseEntry.openResource()), classDesc, codeBaseEntry);

      ClassInfo.Builder classInfoBuilder = new ClassInfo.Builder();
      classParser.parse(classInfoBuilder);
      ClassInfo classInfo = classInfoBuilder.build();

      // Construct the fully-qualified source file name
      // based on the package name and source file name.
      String packageName = classDesc.getPackageName();
      String sourceFile = classInfo.getSource();

      if (!packageName.equals("")) {
        packageName = packageName.replace('.', '/');
        packageName += "/";
      }

      String fullyQualifiedSourceFile = packageName + sourceFile;

      return fullyQualifiedSourceFile;
    } catch (CheckedAnalysisException e) {
      errorLogger.logError("Could scan class " + classDesc.toDottedClassName(), e);
      throw e;
    } finally {
      progress.finishClass();
    }
  }
  /**
   * Execute the search for source directories.
   *
   * @throws edu.umd.cs.findbugs.classfile.CheckedAnalysisException
   * @throws java.io.IOException
   * @throws java.lang.InterruptedException
   */
  public void execute() throws CheckedAnalysisException, IOException, InterruptedException {
    File dir = new File(rootSourceDirectory);
    if (!dir.isDirectory()) {
      throw new IOException("Path " + rootSourceDirectory + " is not a directory");
    }

    // Find all directories underneath the root source directory
    progress.startRecursiveDirectorySearch();
    RecursiveFileSearch rfs =
        new RecursiveFileSearch(
            rootSourceDirectory,
            new FileFilter() {
              @Override
              public boolean accept(File pathname) {
                return pathname.isDirectory();
              }
            });
    rfs.search();
    progress.doneRecursiveDirectorySearch();
    List<String> candidateSourceDirList = rfs.getDirectoriesScanned();

    // Build the classpath
    IClassPath classPath = null;
    try {
      IClassFactory factory = ClassFactory.instance();
      IClassPathBuilder builder = factory.createClassPathBuilder(errorLogger);

      classPath = buildClassPath(builder, factory);

      // From the application classes, find the full list of
      // fully-qualified source file names.
      List<String> fullyQualifiedSourceFileNameList =
          findFullyQualifiedSourceFileNames(builder, classPath);

      // Attempt to find source directories for all source files,
      // and add them to the discoveredSourceDirectoryList
      if (DEBUG) {
        System.out.println("looking for " + fullyQualifiedSourceFileNameList.size() + " files");
      }
      findSourceDirectoriesForAllSourceFiles(
          fullyQualifiedSourceFileNameList, candidateSourceDirList);
    } finally {
      if (classPath != null) {
        classPath.close();
      }
    }
  }