use of org.apache.tools.ant.util.depend.DependencyAnalyzer in project ant by apache.
the class DependScanner method scan.
/**
* Scans the base directory for files on which baseClass depends.
*
* @exception IllegalStateException when basedir was set incorrectly.
*/
@Override
public synchronized void scan() throws IllegalStateException {
included = new Vector<>();
String analyzerClassName = DEFAULT_ANALYZER_CLASS;
DependencyAnalyzer analyzer;
try {
Class<? extends DependencyAnalyzer> analyzerClass = Class.forName(analyzerClassName).asSubclass(DependencyAnalyzer.class);
analyzer = analyzerClass.newInstance();
} catch (Exception e) {
throw new BuildException("Unable to load dependency analyzer: " + analyzerClassName, e);
}
analyzer.addClassPath(new Path(null, basedir.getPath()));
additionalBaseDirs.stream().map(File::getPath).map(p -> new Path(null, p)).forEach(analyzer::addClassPath);
rootClasses.forEach(analyzer::addRootClass);
Set<String> parentSet = Stream.of(parentScanner.getIncludedFiles()).collect(Collectors.toSet());
Enumeration<String> e = analyzer.getClassDependencies();
while (e.hasMoreElements()) {
String classname = e.nextElement();
String filename = classname.replace('.', File.separatorChar) + ".class";
File depFile = new File(basedir, filename);
if (depFile.exists() && parentSet.contains(filename)) {
// This is included
included.addElement(filename);
}
}
}
use of org.apache.tools.ant.util.depend.DependencyAnalyzer in project ant by apache.
the class Depend method determineDependencies.
/**
* 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 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) {
// 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 = new ArrayList<>();
Enumeration<String> depEnum = analyzer.getClassDependencies();
while (depEnum.hasMoreElements()) {
String o = depEnum.nextElement();
dependencyList.add(o);
log("Class " + info.className + " depends on " + o, Project.MSG_DEBUG);
}
cacheDirty = true;
dependencyMap.put(info.className, dependencyList);
}
// 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);
}
}
Aggregations