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);
}
}