Search in sources :

Example 1 with DependencyAnalyzer

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);
        }
    }
}
Also used : Path(org.apache.tools.ant.types.Path) Vector(java.util.Vector) Stream(java.util.stream.Stream) Enumeration(java.util.Enumeration) Set(java.util.Set) BuildException(org.apache.tools.ant.BuildException) DependencyAnalyzer(org.apache.tools.ant.util.depend.DependencyAnalyzer) DirectoryScanner(org.apache.tools.ant.DirectoryScanner) Collectors(java.util.stream.Collectors) File(java.io.File) Path(org.apache.tools.ant.types.Path) DependencyAnalyzer(org.apache.tools.ant.util.depend.DependencyAnalyzer) BuildException(org.apache.tools.ant.BuildException) File(java.io.File) BuildException(org.apache.tools.ant.BuildException)

Example 2 with DependencyAnalyzer

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);
    }
}
Also used : AntClassLoader(org.apache.tools.ant.AntClassLoader) DefaultRmicAdapter(org.apache.tools.ant.taskdefs.rmic.DefaultRmicAdapter) Enumeration(java.util.Enumeration) URL(java.net.URL) HashMap(java.util.HashMap) ResourceCollection(org.apache.tools.ant.types.ResourceCollection) ArrayList(java.util.ArrayList) Path(org.apache.tools.ant.types.Path) HashSet(java.util.HashSet) Map(java.util.Map) Project(org.apache.tools.ant.Project) LinkedHashSet(java.util.LinkedHashSet) FileUtils(org.apache.tools.ant.util.FileUtils) WLRmic(org.apache.tools.ant.taskdefs.rmic.WLRmic) Resource(org.apache.tools.ant.types.Resource) BufferedWriter(java.io.BufferedWriter) Predicate(java.util.function.Predicate) FileWriter(java.io.FileWriter) Set(java.util.Set) IOException(java.io.IOException) BuildException(org.apache.tools.ant.BuildException) DependencyAnalyzer(org.apache.tools.ant.util.depend.DependencyAnalyzer) DirectoryScanner(org.apache.tools.ant.DirectoryScanner) MatchingTask(org.apache.tools.ant.taskdefs.MatchingTask) File(java.io.File) Objects(java.util.Objects) List(java.util.List) Stream(java.util.stream.Stream) FileProvider(org.apache.tools.ant.types.resources.FileProvider) BufferedReader(java.io.BufferedReader) FileReader(java.io.FileReader) Reference(org.apache.tools.ant.types.Reference) HashMap(java.util.HashMap) AntClassLoader(org.apache.tools.ant.AntClassLoader) URL(java.net.URL) ArrayList(java.util.ArrayList) List(java.util.List) HashSet(java.util.HashSet) LinkedHashSet(java.util.LinkedHashSet) Path(org.apache.tools.ant.types.Path) IOException(java.io.IOException) DependencyAnalyzer(org.apache.tools.ant.util.depend.DependencyAnalyzer) File(java.io.File) HashMap(java.util.HashMap) Map(java.util.Map)

Aggregations

File (java.io.File)2 Enumeration (java.util.Enumeration)2 Set (java.util.Set)2 Stream (java.util.stream.Stream)2 BuildException (org.apache.tools.ant.BuildException)2 DirectoryScanner (org.apache.tools.ant.DirectoryScanner)2 Path (org.apache.tools.ant.types.Path)2 DependencyAnalyzer (org.apache.tools.ant.util.depend.DependencyAnalyzer)2 BufferedReader (java.io.BufferedReader)1 BufferedWriter (java.io.BufferedWriter)1 FileReader (java.io.FileReader)1 FileWriter (java.io.FileWriter)1 IOException (java.io.IOException)1 URL (java.net.URL)1 ArrayList (java.util.ArrayList)1 HashMap (java.util.HashMap)1 HashSet (java.util.HashSet)1 LinkedHashSet (java.util.LinkedHashSet)1 List (java.util.List)1 Map (java.util.Map)1