/*
 *  Licensed to the Apache Software Foundation (ASF) under one or more
 *  contributor license agreements.  See the NOTICE file distributed with
 *  this work for additional information regarding copyright ownership.
 *  The ASF licenses this file to You 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 org.apache.tools.ant.taskdefs.optional.depend;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.net.URL;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Vector;

import org.apache.tools.ant.AntClassLoader;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.DirectoryScanner;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.taskdefs.MatchingTask;
import org.apache.tools.ant.taskdefs.rmic.DefaultRmicAdapter;
import org.apache.tools.ant.taskdefs.rmic.WLRmic;
import org.apache.tools.ant.types.Path;
import org.apache.tools.ant.types.Reference;
import org.apache.tools.ant.util.FileUtils;
import org.apache.tools.ant.util.depend.DependencyAnalyzer;

/**
 * Generates a dependency file for a given set of classes.
 *
 */
public class Depend extends MatchingTask {
    private static final int ONE_SECOND = 1000;

    /**
     * A class (struct) user to manage information about a class
     *
     */
    private static class ClassFileInfo {
        /** The file where the class file is stored in the file system */
        private File absoluteFile;

        /** The Java class name of this class */
        private String className;

        /** The source File containing this class */
        private File sourceFile;

        /** if user has been warned about this file not having a source file */
        private boolean isUserWarned = false;
    }

    /** The path where source files exist */
    private Path srcPath;

    /** The path where compiled class files exist. */
    private Path destPath;

    /** The directory which contains the dependency cache. */
    private File cache;

    /** The list of source paths derived from the srcPath field. */
    private String[] srcPathList;

    /**
     * A map which gives for every class a list of the class which it
     * affects.
     */
    private Hashtable affectedClassMap;

    /** A map which gives information about a class */
    private Hashtable classFileInfoMap;

    /**
     * A map which gives the list of jars and classes from the classpath
     * that a class depends upon
     */
    private Hashtable classpathDependencies;

    /** The list of classes which are out of date. */
    private Hashtable outOfDateClasses;

    /**
     * indicates that the dependency relationships should be extended beyond
     * direct dependencies to include all classes. So if A directly affects
     * B and B directly affects C, then A indirectly affects C.
     */
    private boolean closure = false;

    /**
     * flag to enable warning if we encounter RMI stubs
     */
    private boolean warnOnRmiStubs = true;

    /**
     * Flag which controls whether the reversed dependencies should be
     * dumped to the log
     */
    private boolean dump = false;

    /** The classpath to look for additional dependencies */
    private Path dependClasspath;

    /** constants used with the cache file */
    private static final String CACHE_FILE_NAME = "dependencies.txt";
    /** String Used to separate classnames in the dependency file */
    private static final String CLASSNAME_PREPEND = "||:";

    /**
     * Set the classpath to be used for this dependency check.
     *
     * @param classpath the classpath to be used when checking for
     *      dependencies on elements in the classpath
     */
    public void setClasspath(Path classpath) {
        if (dependClasspath == null) {
            dependClasspath = classpath;
        } else {
            dependClasspath.append(classpath);
        }
    }

    /**
     * Gets the classpath to be used for this dependency check.
     *
     * @return the current dependency classpath
     */
    public Path getClasspath() {
        return dependClasspath;
    }

    /**
     * Adds a classpath to be used for this dependency check.
     *
     * @return A path object to be configured by Ant
     */
    public Path createClasspath() {
        if (dependClasspath == null) {
            dependClasspath = new Path(getProject());
        }
        return dependClasspath.createPath();
    }

    /**
     * Adds a reference to a classpath defined elsewhere.
     *
     * @param r a reference to a path object to be used as the depend
     *      classpath
     */
    public void setClasspathRef(Reference r) {
        createClasspath().setRefid(r);
    }

    /**
     * Flag to set to true if you want dependency issues with RMI
     * stubs to appear at warning level.
     * @param warnOnRmiStubs if true set dependency issues to appear at warning level.
     * @since Ant1.7
     */
    public void setWarnOnRmiStubs(boolean warnOnRmiStubs) {
        this.warnOnRmiStubs = warnOnRmiStubs;
    }

    /**
     * Read the dependencies from cache file
     *
     * @return a collection of class dependencies
     * @exception IOException if the dependency file cannot be read
     */
    private Hashtable readCachedDependencies(File depFile) throws IOException {
        Hashtable dependencyMap = new Hashtable();

        BufferedReader in = null;
        try {
            in = new BufferedReader(new FileReader(depFile));
            String line = null;
            Vector dependencyList = null;
            String className = null;
            int prependLength = CLASSNAME_PREPEND.length();
            while ((line = in.readLine()) != null) {
                if (line.startsWith(CLASSNAME_PREPEND)) {
                    dependencyList = new Vector();
                    className = line.substring(prependLength);
                    dependencyMap.put(className, dependencyList);
                } else {
                    dependencyList.addElement(line);
                }
            }
        } finally {
            FileUtils.close(in);
        }

        return dependencyMap;
    }

    /**
     * Write the dependencies to cache file
     *
     * @param dependencyMap the map of dependencies to be written out.
     * @exception IOException if the dependency file cannot be written out.
     */
    private void writeCachedDependencies(Hashtable dependencyMap)
        throws IOException {
        if (cache != null) {
            BufferedWriter pw = null;
            try {
                cache.mkdirs();
                File depFile = new File(cache, CACHE_FILE_NAME);

                pw = new BufferedWriter(new FileWriter(depFile));
                Enumeration e = dependencyMap.keys();
                while (e.hasMoreElements()) {
                    String className = (String) e.nextElement();

                    pw.write(CLASSNAME_PREPEND + className);
                    pw.newLine();

                    Vector dependencyList
                        = (Vector) dependencyMap.get(className);
                    int size = dependencyList.size();
                    for (int x = 0; x < size; x++) {
                        pw.write(String.valueOf(dependencyList.elementAt(x)));
                        pw.newLine();
                    }
                }
            } finally {
                FileUtils.close(pw);
            }
        }
    }

    /**
     * Get the classpath for dependency checking.
     *
     * This method removes the dest dirs if it is given from the dependency classpath
     */
    private Path getCheckClassPath() {
        if (dependClasspath == null) {
            return null;
        }

        String[] destPathElements = destPath.list();
        String[] classpathElements = dependClasspath.list();
        String checkPath = "";
        for (int i = 0; i < classpathElements.length; ++i) {
            String element = classpathElements[i];
            boolean inDestPath = false;
            for (int j = 0; j < destPathElements.length && !inDestPath; ++j) {
                inDestPath = destPathElements[j].equals(element);
            }
            if (!inDestPath) {
                if (checkPath.length() == 0) {
                    checkPath = element;
                } else {
                    checkPath += ":" + element;
                }
            }
        }

        Path p = null;
        if (checkPath.length() > 0) {
            p = new Path(getProject(), checkPath);
        }

        log("Classpath without dest dir is " + p, Project.MSG_DEBUG);
        return p;
    }

    /**
     * Determine the dependencies between classes. Class dependencies are
     * determined by examining the class references in a class file to other
     * classes.
     *
     * This method sets up the following fields
     * <ul>
     *   <li>affectedClassMap - the list of classes each class affects</li>
     *   <li>classFileInfoMap - information about each class</li>
     *   <li>classpathDependencies - the list of jars and classes from the
     *                             classpath that each class depends upon.</li>
     * </ul>
     *
     * If required, the dependencies are written to the cache.
     *
     * @exception IOException if either the dependencies cache or the class
     *      files cannot be read or written
     */
    private void determineDependencies() throws IOException {
        affectedClassMap = new Hashtable();
        classFileInfoMap = new Hashtable();
        boolean cacheDirty = false;

        Hashtable dependencyMap = new Hashtable();
        File cacheFile = null;
        boolean cacheFileExists = true;
        long cacheLastModified = Long.MAX_VALUE;

        // read the dependency cache from the disk
        if (cache != null) {
            cacheFile = new File(cache, CACHE_FILE_NAME);
            cacheFileExists = cacheFile.exists();
            cacheLastModified = cacheFile.lastModified();
            if (cacheFileExists) {
                dependencyMap = readCachedDependencies(cacheFile);
            }
        }
        Enumeration classfileEnum = getClassFiles(destPath).elements();
        while (classfileEnum.hasMoreElements()) {
            ClassFileInfo info = (ClassFileInfo) classfileEnum.nextElement();
            log("Adding class info for " + info.className, Project.MSG_DEBUG);
            classFileInfoMap.put(info.className, info);

            Vector dependencyList = null;

            if (cache != null) {
                // try to read the dependency info from the map if it is
                // not out of date
                if (cacheFileExists
                    && cacheLastModified > info.absoluteFile.lastModified()) {
                    // depFile exists and is newer than the class file
                    // need to get dependency list from the map.
                    dependencyList = (Vector) dependencyMap.get(info.className);
                }
            }

            if (dependencyList == null) {
                // not cached - so need to read directly from the class file
                DependencyAnalyzer analyzer = new AntAnalyzer();
                analyzer.addRootClass(info.className);
                analyzer.addClassPath(destPath);
                analyzer.setClosure(false);
                dependencyList = new Vector();
                Enumeration depEnum = analyzer.getClassDependencies();
                while (depEnum.hasMoreElements()) {
                    Object o = depEnum.nextElement();
                    dependencyList.addElement(o);
                    log("Class " + info.className + " depends on " + o,
                        Project.MSG_DEBUG);
                }
                cacheDirty = true;
                dependencyMap.put(info.className, dependencyList);
            }

            // This class depends on each class in the dependency list. For each
            // one of those, add this class into their affected classes list
            Enumeration depEnum = dependencyList.elements();
            while (depEnum.hasMoreElements()) {
                String dependentClass = (String) depEnum.nextElement();

                Hashtable affectedClasses
                    = (Hashtable) affectedClassMap.get(dependentClass);
                if (affectedClasses == null) {
                    affectedClasses = new Hashtable();
                    affectedClassMap.put(dependentClass, affectedClasses);
                }

                affectedClasses.put(info.className, info);
                log(dependentClass + " affects " + info.className,
                    Project.MSG_DEBUG);
            }
        }

        classpathDependencies = null;
        Path checkPath = getCheckClassPath();
        if (checkPath != null) {
            // now determine which jars each class depends upon
            classpathDependencies = new Hashtable();
            try (AntClassLoader loader = getProject().createClassLoader(checkPath)) {

                Hashtable classpathFileCache = new Hashtable();
                Object nullFileMarker = new Object();
                for (Enumeration e = dependencyMap.keys(); e.hasMoreElements();) {
                    String className = (String) e.nextElement();
                    log("Determining classpath dependencies for " + className,
                        Project.MSG_DEBUG);
                    Vector dependencyList = (Vector) dependencyMap.get(className);
                    Hashtable dependencies = new Hashtable();
                    classpathDependencies.put(className, dependencies);
                    Enumeration e2 = dependencyList.elements();
                    while (e2.hasMoreElements()) {
                        String dependency = (String) e2.nextElement();
                        log("Looking for " + dependency, Project.MSG_DEBUG);
                        Object classpathFileObject
                            = classpathFileCache.get(dependency);
                        if (classpathFileObject == null) {
                            classpathFileObject = nullFileMarker;

                            if (!dependency.startsWith("java.")
                                && !dependency.startsWith("javax.")) {
                                URL classURL
                                    = loader.getResource(dependency.replace('.', '/') + ".class");
                                log("URL is " + classURL, Project.MSG_DEBUG);
                                if (classURL != null) {
                                    if (classURL.getProtocol().equals("jar")) {
                                        String jarFilePath = classURL.getFile();
                                        int classMarker = jarFilePath.indexOf('!');
                                        jarFilePath = jarFilePath.substring(0, classMarker);
                                        if (jarFilePath.startsWith("file:")) {
                                            classpathFileObject = new File(
                                                                           FileUtils.getFileUtils().fromURI(jarFilePath));
                                        } else {
                                            throw new IOException(
                                                                  "Bizarre nested path in jar: protocol: "
                                                                  + jarFilePath);
                                        }
                                    } else if (classURL.getProtocol().equals("file")) {
                                        classpathFileObject = new File(
                                                                       FileUtils.getFileUtils()
                                                                       .fromURI(classURL.toExternalForm()));
                                    }
                                    log("Class " + className
                                        + " depends on " + classpathFileObject
                                        + " due to " + dependency, Project.MSG_DEBUG);
                                }
                            } else {
                                log("Ignoring base classlib dependency "
                                    + dependency, Project.MSG_DEBUG);
                            }
                            classpathFileCache.put(dependency, classpathFileObject);
                        }
                        if (classpathFileObject != nullFileMarker) {
                            // we need to add this jar to the list for this class.
                            File jarFile = (File) classpathFileObject;
                            log("Adding a classpath dependency on " + jarFile,
                                Project.MSG_DEBUG);
                            dependencies.put(jarFile, jarFile);
                        }
                    }
                }
            }
        } else {
            log("No classpath to check", Project.MSG_DEBUG);
        }

        // write the dependency cache to the disk
        if (cache != null && cacheDirty) {
            writeCachedDependencies(dependencyMap);
        }
    }

    /**
     * Delete all the class files which are out of date, by way of their
     * dependency on a class which is out of date
     *
     * @return the number of files deleted.
     */
    private int deleteAllAffectedFiles() {
        int count = 0;
        for (Enumeration e = outOfDateClasses.elements(); e.hasMoreElements();) {
            String className = (String) e.nextElement();
            count += deleteAffectedFiles(className);
            ClassFileInfo classInfo
                = (ClassFileInfo) classFileInfoMap.get(className);
            if (classInfo != null && classInfo.absoluteFile.exists()) {
                if (classInfo.sourceFile == null) {
                    warnOutOfDateButNotDeleted(classInfo, className, className);
                } else {
                    classInfo.absoluteFile.delete();
                    count++;
                }
            }
        }
        return count;
    }

    /**
     * Delete all the class files of classes which depend on the given class
     *
     * @param className the name of the class whose dependent classes will be
     *      deleted
     * @return the number of class files removed
     */
    private int deleteAffectedFiles(String className) {
        int count = 0;

        Hashtable affectedClasses = (Hashtable) affectedClassMap.get(className);
        if (affectedClasses == null) {
            return count;
        }
        for (Enumeration e = affectedClasses.keys(); e.hasMoreElements();) {
            String affectedClass = (String) e.nextElement();
            ClassFileInfo affectedClassInfo
                = (ClassFileInfo) affectedClasses.get(affectedClass);

            if (!affectedClassInfo.absoluteFile.exists()) {
                continue;
            }

            if (affectedClassInfo.sourceFile == null) {
                warnOutOfDateButNotDeleted(affectedClassInfo, affectedClass, className);
                continue;
            }

            log("Deleting file " + affectedClassInfo.absoluteFile.getPath()
                + " since " + className + " out of date", Project.MSG_VERBOSE);

            affectedClassInfo.absoluteFile.delete();
            count++;
            if (closure) {
                count += deleteAffectedFiles(affectedClass);
            } else {
                // without closure we may delete an inner class but not the
                // top level class which would not trigger a recompile.

                if (affectedClass.indexOf("$") == -1) {
                    continue;
                }
                // need to delete the main class
                String topLevelClassName
                    = affectedClass.substring(0, affectedClass.indexOf("$"));
                log("Top level class = " + topLevelClassName,
                    Project.MSG_VERBOSE);
                ClassFileInfo topLevelClassInfo
                    = (ClassFileInfo) classFileInfoMap.get(topLevelClassName);
                if (topLevelClassInfo != null
                    && topLevelClassInfo.absoluteFile.exists()) {
                    log("Deleting file "
                        + topLevelClassInfo.absoluteFile.getPath()
                        + " since one of its inner classes was removed",
                        Project.MSG_VERBOSE);
                    topLevelClassInfo.absoluteFile.delete();
                    count++;
                    if (closure) {
                        count += deleteAffectedFiles(topLevelClassName);
                    }
                }
            }
        }
        return count;
    }

    /**
     * warn when a class is out of date, but not deleted as its source is unknown.
     * MSG_WARN is the normal level, but we downgrade to MSG_VERBOSE for RMI files
     * if {@link #warnOnRmiStubs is false}
     * @param affectedClassInfo info about the affectd class
     * @param affectedClass the name of the affected .class file
     * @param className the file that is triggering the out of dateness
     */
    private void warnOutOfDateButNotDeleted(
                                            ClassFileInfo affectedClassInfo, String affectedClass,
                                            String className) {
        if (affectedClassInfo.isUserWarned) {
            return;
        }
        int level = Project.MSG_WARN;
        if (!warnOnRmiStubs) {
            //downgrade warnings on RMI stublike classes, as they are generated
            //by rmic, so there is no need to tell the user that their source is
            //missing.
            if (isRmiStub(affectedClass, className)) {
                level = Project.MSG_VERBOSE;
            }
        }
        log("The class " + affectedClass + " in file "
            + affectedClassInfo.absoluteFile.getPath()
            + " is out of date due to " + className
            + " but has not been deleted because its source file"
            + " could not be determined", level);
        affectedClassInfo.isUserWarned = true;
    }

    /**
     * test for being an RMI stub
     * @param affectedClass  class being tested
     * @param className      possible origin of the RMI stub
     * @return whether the class affectedClass is a RMI stub
     */
    private boolean isRmiStub(String affectedClass, String className) {
        return isStub(affectedClass, className, DefaultRmicAdapter.RMI_STUB_SUFFIX)
            || isStub(affectedClass, className, DefaultRmicAdapter.RMI_SKEL_SUFFIX)
            || isStub(affectedClass, className, WLRmic.RMI_STUB_SUFFIX)
            || isStub(affectedClass, className, WLRmic.RMI_SKEL_SUFFIX);
    }

    private boolean isStub(String affectedClass, String baseClass, String suffix) {
        return (baseClass + suffix).equals(affectedClass);
    }

    /**
     * Dump the dependency information loaded from the classes to the Ant log
     */
    private void dumpDependencies() {
        log("Reverse Dependency Dump for " + affectedClassMap.size()
            + " classes:", Project.MSG_DEBUG);

        Enumeration classEnum = affectedClassMap.keys();
        while (classEnum.hasMoreElements()) {
            String className = (String) classEnum.nextElement();
            log(" Class " + className + " affects:", Project.MSG_DEBUG);
            Hashtable affectedClasses
                = (Hashtable) affectedClassMap.get(className);
            Enumeration affectedClassEnum = affectedClasses.keys();
            while (affectedClassEnum.hasMoreElements()) {
                String affectedClass = (String) affectedClassEnum.nextElement();
                ClassFileInfo info
                    = (ClassFileInfo) affectedClasses.get(affectedClass);
                log("    " + affectedClass + " in "
                    + info.absoluteFile.getPath(), Project.MSG_DEBUG);
            }
        }

        if (classpathDependencies != null) {
            log("Classpath file dependencies (Forward):", Project.MSG_DEBUG);

            Enumeration classpathEnum = classpathDependencies.keys();
            while (classpathEnum.hasMoreElements()) {
                String className = (String) classpathEnum.nextElement();
                log(" Class " + className + " depends on:", Project.MSG_DEBUG);
                Hashtable dependencies
                    = (Hashtable) classpathDependencies.get(className);

                Enumeration classpathFileEnum = dependencies.elements();
                while (classpathFileEnum.hasMoreElements()) {
                    File classpathFile = (File) classpathFileEnum.nextElement();
                    log("    " + classpathFile.getPath(), Project.MSG_DEBUG);
                }
            }
        }
    }

    private void determineOutOfDateClasses() {
        outOfDateClasses = new Hashtable();
        for (int i = 0; i < srcPathList.length; i++) {
            File srcDir = getProject().resolveFile(srcPathList[i]);
            if (srcDir.exists()) {
                DirectoryScanner ds = this.getDirectoryScanner(srcDir);
                String[] files = ds.getIncludedFiles();
                scanDir(srcDir, files);
            }
        }

        // now check classpath file dependencies
        if (classpathDependencies == null) {
            return;
        }

        Enumeration classpathDepsEnum = classpathDependencies.keys();
        while (classpathDepsEnum.hasMoreElements()) {
            String className = (String) classpathDepsEnum.nextElement();
            if (outOfDateClasses.containsKey(className)) {
                continue;
            }
            ClassFileInfo info
                = (ClassFileInfo) classFileInfoMap.get(className);

            // if we have no info about the class - it may have been deleted already and we
            // are using cached info.
            if (info != null) {
                Hashtable dependencies
                    = (Hashtable) classpathDependencies.get(className);
                for (Enumeration e2 = dependencies.elements(); e2.hasMoreElements();) {
                    File classpathFile = (File) e2.nextElement();
                    if (classpathFile.lastModified()
                        > info.absoluteFile.lastModified()) {
                        log("Class " + className
                            + " is out of date with respect to "
                            + classpathFile, Project.MSG_DEBUG);
                        outOfDateClasses.put(className, className);
                        break;
                    }
                }
            }
        }
    }

    /**
     * Does the work.
     *
     * @exception BuildException Thrown in case of an unrecoverable error.
     */
    public void execute() throws BuildException {
        try {
            long start = System.currentTimeMillis();
            if (srcPath == null) {
                throw new BuildException("srcdir attribute must be set",
                                         getLocation());
            }

            srcPathList = srcPath.list();
            if (srcPathList.length == 0) {
                throw new BuildException("srcdir attribute must be non-empty",
                                         getLocation());
            }

            if (destPath == null) {
                destPath = srcPath;
            }

            if (cache != null && cache.exists() && !cache.isDirectory()) {
                throw new BuildException("The cache, if specified, must "
                                         + "point to a directory");
            }

            if (cache != null && !cache.exists()) {
                cache.mkdirs();
            }

            determineDependencies();
            if (dump) {
                dumpDependencies();
            }
            determineOutOfDateClasses();
            int count = deleteAllAffectedFiles();

            long duration = (System.currentTimeMillis() - start) / ONE_SECOND;

            final int summaryLogLevel;
            if (count > 0) {
                summaryLogLevel = Project.MSG_INFO;
            }  else {
                summaryLogLevel = Project.MSG_DEBUG;
            }

            log("Deleted " + count + " out of date files in "
                + duration + " seconds", summaryLogLevel);
        } catch (Exception e) {
            throw new BuildException(e);
        }
    }

    /**
     * Scans the directory looking for source files that are newer than
     * their class files. The results are returned in the class variable
     * compileList
     *
     * @param srcDir the source directory
     * @param files the names of the files in the source dir which are to be
     *      checked.
     */
    protected void scanDir(File srcDir, String[] files) {

        for (int i = 0; i < files.length; i++) {
            File srcFile = new File(srcDir, files[i]);
            if (files[i].endsWith(".java")) {
                String filePath = srcFile.getPath();
                String className
                    = filePath.substring(srcDir.getPath().length() + 1,
                                         filePath.length() - ".java".length());
                className = ClassFileUtils.convertSlashName(className);
                ClassFileInfo info
                    = (ClassFileInfo) classFileInfoMap.get(className);
                if (info == null) {
                    // there was no class file. add this class to the list
                    outOfDateClasses.put(className, className);
                } else {
                    if (srcFile.lastModified()
                        > info.absoluteFile.lastModified()) {
                        outOfDateClasses.put(className, className);
                    }
                }
            }
        }
    }


    /**
     * Get the list of class files we are going to analyse.
     *
     * @param classLocations a path structure containing all the directories
     *      where classes can be found.
     * @return a vector containing the classes to analyse.
     */
    private Vector getClassFiles(Path classLocations) {
        // break the classLocations into its components.
        String[] classLocationsList = classLocations.list();

        Vector classFileList = new Vector();

        for (int i = 0; i < classLocationsList.length; ++i) {
            File dir = new File(classLocationsList[i]);
            if (dir.isDirectory()) {
                addClassFiles(classFileList, dir, dir);
            }
        }

        return classFileList;
    }

    /**
     * Find the source file for a given class
     *
     * @param classname the classname in slash format.
     * @param sourceFileKnownToExist if not null, a file already known to exist
     *                               (saves call to .exists())
     */
    private File findSourceFile(String classname, File sourceFileKnownToExist) {
        String sourceFilename;
        int innerIndex = classname.indexOf("$");
        if (innerIndex != -1) {
            sourceFilename = classname.substring(0, innerIndex) + ".java";
        } else {
            sourceFilename = classname + ".java";
        }

        // search the various source path entries
        for (int i = 0; i < srcPathList.length; ++i) {
            File sourceFile = new File(srcPathList[i], sourceFilename);
            if (sourceFile.equals(sourceFileKnownToExist) || sourceFile.exists()) {
                return sourceFile;
            }
        }
        return null;
    }

    /**
     * Add the list of class files from the given directory to the class
     * file vector, including any subdirectories.
     *
     * @param classFileList a list of ClassFileInfo objects for all the
     *      files in the directory tree
     * @param dir the directory tree to be searched, recursively, for class
     *      files
     * @param root the root of the source tree. This is used to determine
     *      the absolute class name from the relative position in the
     *      source tree
     */
    private void addClassFiles(Vector classFileList, File dir, File root) {
        String[] filesInDir = dir.list();

        if (filesInDir == null) {
            return;
        }
        int length = filesInDir.length;

        int rootLength = root.getPath().length();
        File sourceFileKnownToExist = null; // speed optimization
        for (int i = 0; i < length; ++i) {
            File file = new File(dir, filesInDir[i]);
            if (filesInDir[i].endsWith(".class")) {
                ClassFileInfo info = new ClassFileInfo();
                info.absoluteFile = file;
                String relativeName = file.getPath().substring(
                                                               rootLength + 1,
                                                               file.getPath().length() - ".class".length());
                info.className
                    = ClassFileUtils.convertSlashName(relativeName);
                info.sourceFile = sourceFileKnownToExist = findSourceFile(
                                                                          relativeName, sourceFileKnownToExist);
                classFileList.addElement(info);
            } else {
                addClassFiles(classFileList, file, root);
            }
        }
    }


    /**
     * Set the directories path to find the Java source files.
     *
     * @param srcPath the source path
     */
    public void setSrcdir(Path srcPath) {
        this.srcPath = srcPath;
    }

    /**
     * Set the destination directory where the compiled Java files exist.
     *
     * @param destPath the destination areas where build files are written
     */
    public void setDestDir(Path destPath) {
        this.destPath = destPath;
    }

    /**
     * Sets the dependency cache file.
     *
     * @param cache the dependency cache file
     */
    public void setCache(File cache) {
        this.cache = cache;
    }

    /**
     * If true, transitive dependencies are followed until the
     * closure of the dependency set if reached.
     * When not set, the depend task will only follow
     * direct dependencies between classes.
     *
     * @param closure indicate if dependency closure is required.
     */
    public void setClosure(boolean closure) {
        this.closure = closure;
    }

    /**
     * If true, the dependency information will be written
     * to the debug level log.
     *
     * @param dump set to true to dump dependency information to the log
     */
    public void setDump(boolean dump) {
        this.dump = dump;
    }
}

