diff options
Diffstat (limited to 'framework/src/ant/apache-ant-1.9.6/src/main/org/apache/tools/ant/util/depend/AbstractAnalyzer.java')
-rw-r--r-- | framework/src/ant/apache-ant-1.9.6/src/main/org/apache/tools/ant/util/depend/AbstractAnalyzer.java | 286 |
1 files changed, 286 insertions, 0 deletions
diff --git a/framework/src/ant/apache-ant-1.9.6/src/main/org/apache/tools/ant/util/depend/AbstractAnalyzer.java b/framework/src/ant/apache-ant-1.9.6/src/main/org/apache/tools/ant/util/depend/AbstractAnalyzer.java new file mode 100644 index 00000000..5c95d75b --- /dev/null +++ b/framework/src/ant/apache-ant-1.9.6/src/main/org/apache/tools/ant/util/depend/AbstractAnalyzer.java @@ -0,0 +1,286 @@ +/* + * 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.util.depend; +import java.io.File; +import java.io.IOException; +import java.util.Enumeration; +import java.util.Vector; +import java.util.zip.ZipFile; + +import org.apache.tools.ant.types.Path; +import org.apache.tools.ant.util.VectorSet; + +/** + * An abstract implementation of the analyzer interface providing support + * for the bulk of interface methods. + * + */ +public abstract class AbstractAnalyzer implements DependencyAnalyzer { + /** Maximum number of loops for looking for indirect dependencies. */ + public static final int MAX_LOOPS = 1000; + + /** The source path for the source files */ + private Path sourcePath = new Path(null); + + /** The classpath containg dirs and jars of class files */ + private Path classPath = new Path(null); + + /** The list of root classes */ + private final Vector<String> rootClasses = new VectorSet<String>(); + + /** true if dependencies have been determined */ + private boolean determined = false; + + /** the list of File objects that the root classes depend upon */ + private Vector<File> fileDependencies; + /** the list of java classes the root classes depend upon */ + private Vector<String> classDependencies; + + /** true if indirect dependencies should be gathered */ + private boolean closure = true; + + /** Setup the analyzer */ + protected AbstractAnalyzer() { + reset(); + } + + /** + * Set the closure flag. If this flag is true the analyzer will traverse + * all class relationships until it has collected the entire set of + * direct and indirect dependencies + * + * @param closure true if dependencies should be traversed to determine + * indirect dependencies. + */ + public void setClosure(boolean closure) { + this.closure = closure; + } + + /** + * Get the list of files in the file system upon which the root classes + * depend. The files will be either the classfiles or jar files upon + * which the root classes depend. + * + * @return an enumeration of File instances. + */ + public Enumeration<File> getFileDependencies() { + if (!supportsFileDependencies()) { + throw new RuntimeException("File dependencies are not supported " + + "by this analyzer"); + } + if (!determined) { + determineDependencies(fileDependencies, classDependencies); + } + return fileDependencies.elements(); + } + + /** + * Get the list of classes upon which root classes depend. This is a + * list of Java classnames in dot notation. + * + * @return an enumeration of Strings, each being the name of a Java + * class in dot notation. + */ + public Enumeration<String> getClassDependencies() { + if (!determined) { + determineDependencies(fileDependencies, classDependencies); + } + return classDependencies.elements(); + } + + /** + * Get the file that contains the class definition + * + * @param classname the name of the required class + * @return the file instance, zip or class, containing the + * class or null if the class could not be found. + * @exception IOException if the files in the classpath cannot be read. + */ + public File getClassContainer(String classname) throws IOException { + String classLocation = classname.replace('.', '/') + ".class"; + // we look through the classpath elements. If the element is a dir + // we look for the file. IF it is a zip, we look for the zip entry + return getResourceContainer(classLocation, classPath.list()); + } + + /** + * Get the file that contains the class source. + * + * @param classname the name of the required class + * @return the file instance, zip or java, containing the + * source or null if the source for the class could not be found. + * @exception IOException if the files in the sourcepath cannot be read. + */ + public File getSourceContainer(String classname) throws IOException { + String sourceLocation = classname.replace('.', '/') + ".java"; + + // we look through the source path elements. If the element is a dir + // we look for the file. If it is a zip, we look for the zip entry. + // This isn't normal for source paths but we get it for free + return getResourceContainer(sourceLocation, sourcePath.list()); + } + + /** + * Add a source path to the source path used by this analyzer. The + * elements in the given path contain the source files for the classes + * being analyzed. Not all analyzers will use this information. + * + * @param sourcePath The Path instance specifying the source path + * elements. + */ + public void addSourcePath(Path sourcePath) { + if (sourcePath == null) { + return; + } + this.sourcePath.append(sourcePath); + this.sourcePath.setProject(sourcePath.getProject()); + } + + /** + * Add a classpath to the classpath being used by the analyzer. The + * classpath contains the binary classfiles for the classes being + * analyzed The elements may either be the directories or jar files.Not + * all analyzers will use this information. + * + * @param classPath the Path instance specifying the classpath elements + */ + public void addClassPath(Path classPath) { + if (classPath == null) { + return; + } + + this.classPath.append(classPath); + this.classPath.setProject(classPath.getProject()); + } + + /** + * Add a root class. The root classes are used to drive the + * determination of dependency information. The analyzer will start at + * the root classes and add dependencies from there. + * + * @param className the name of the class in Java dot notation. + */ + public void addRootClass(String className) { + if (className == null) { + return; + } + if (!rootClasses.contains(className)) { + rootClasses.addElement(className); + } + } + + /** + * Configure an aspect of the analyzer. The set of aspects that are + * supported is specific to each analyzer instance. + * + * @param name the name of the aspect being configured + * @param info the configuration info. + */ + public void config(String name, Object info) { + // do nothing by default + } + + /** + * Reset the dependency list. This will reset the determined + * dependencies and the also list of root classes. + */ + public void reset() { + rootClasses.removeAllElements(); + determined = false; + fileDependencies = new Vector<File>(); + classDependencies = new Vector<String>(); + } + + /** + * Get an enumeration of the root classes + * + * @return an enumeration of Strings, each of which is a class name + * for a root class. + */ + protected Enumeration<String> getRootClasses() { + return rootClasses.elements(); + } + + /** + * Indicate if the analyzer is required to follow + * indirect class relationships. + * + * @return true if indirect relationships should be followed. + */ + protected boolean isClosureRequired() { + return closure; + } + + /** + * Determine the dependencies of the current set of root classes + * + * @param files a vector into which Files upon which the root classes + * depend should be placed. + * @param classes a vector of Strings into which the names of classes + * upon which the root classes depend should be placed. + */ + protected abstract void determineDependencies(Vector<File> files, Vector<String> classes); + + /** + * Indicate if the particular subclass supports file dependency + * information. + * + * @return true if file dependencies are supported. + */ + protected abstract boolean supportsFileDependencies(); + + /** + * Get the file that contains the resource + * + * @param resourceLocation the name of the required resource. + * @param paths the paths which will be searched for the resource. + * @return the file instance, zip or class, containing the + * class or null if the class could not be found. + * @exception IOException if the files in the given paths cannot be read. + */ + private File getResourceContainer(String resourceLocation, String[] paths) + throws IOException { + for (int i = 0; i < paths.length; ++i) { + File element = new File(paths[i]); + if (!element.exists()) { + continue; + } + if (element.isDirectory()) { + File resource = new File(element, resourceLocation); + if (resource.exists()) { + return resource; + } + } else { + // must be a zip of some sort + ZipFile zipFile = null; + try { + zipFile = new ZipFile(element); + if (zipFile.getEntry(resourceLocation) != null) { + return element; + } + } finally { + if (zipFile != null) { + zipFile.close(); + } + } + } + } + return null; + } +} + |