private void determineDependencies()

in src/main/org/apache/tools/ant/taskdefs/optional/depend/Depend.java [283:418]


    private void determineDependencies() throws IOException {
        affectedClassMap = new HashMap<>();
        classFileInfoMap = new HashMap<>();
        boolean cacheDirty = false;

        Map<String, List<String>> dependencyMap = new HashMap<>();
        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);
            }
        }
        for (ClassFileInfo info : getClassFiles()) {
            log("Adding class info for " + info.className, Project.MSG_DEBUG);
            classFileInfoMap.put(info.className, info);

            List<String> 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 = 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 = Collections.list(analyzer.getClassDependencies());
                dependencyList.forEach(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
            for (String dependentClass : dependencyList) {
                affectedClassMap
                    .computeIfAbsent(dependentClass, k -> new HashMap<>())
                    .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 HashMap<>();
            try (AntClassLoader loader = getProject().createClassLoader(checkPath)) {

                Map<String, Object> classpathFileCache = new HashMap<>();
                Object nullFileMarker = new Object();
                for (Map.Entry<String, List<String>> e : dependencyMap.entrySet()) {
                    String className = e.getKey();
                    log("Determining classpath dependencies for " + className,
                        Project.MSG_DEBUG);
                    List<String> dependencyList = e.getValue();
                    Set<File> dependencies = new HashSet<>();
                    classpathDependencies.put(className, dependencies);
                    for (String dependency : dependencyList) {
                        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 ("jar".equals(classURL.getProtocol())) {
                                        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 ("file".equals(classURL.getProtocol())) {
                                        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.add(jarFile);
                        }
                    }
                }
            }
        } else {
            log("No classpath to check", Project.MSG_DEBUG);
        }

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