001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: *
017: */
018: package org.apache.tools.ant.util.depend.bcel;
019:
020: import java.io.File;
021: import java.io.IOException;
022: import java.util.Enumeration;
023: import java.util.Hashtable;
024: import java.util.Vector;
025: import org.apache.bcel.classfile.ClassParser;
026: import org.apache.bcel.classfile.DescendingVisitor;
027: import org.apache.bcel.classfile.JavaClass;
028: import org.apache.tools.ant.util.depend.AbstractAnalyzer;
029:
030: /**
031: * An analyzer capable fo traversing all class - class relationships.
032: *
033: */
034: public class FullAnalyzer extends AbstractAnalyzer {
035: /**
036: * Default constructor
037: *
038: * Causes the BCEL classes to load to ensure BCEL dependencies can
039: * be satisfied
040: */
041: public FullAnalyzer() {
042: // force BCEL classes to load now
043: try {
044: new ClassParser("force");
045: } catch (IOException e) {
046: // ignore
047: }
048: }
049:
050: /**
051: * Determine the dependencies of the configured root classes.
052: *
053: * @param files a vector to be populated with the files which contain
054: * the dependency classes
055: * @param classes a vector to be populated with the names of the
056: * depencency classes.
057: */
058: protected void determineDependencies(Vector files, Vector classes) {
059: // we get the root classes and build up a set of
060: // classes upon which they depend
061: Hashtable dependencies = new Hashtable();
062: Hashtable containers = new Hashtable();
063: Hashtable toAnalyze = new Hashtable();
064: for (Enumeration e = getRootClasses(); e.hasMoreElements();) {
065: String classname = (String) e.nextElement();
066: toAnalyze.put(classname, classname);
067: }
068:
069: int count = 0;
070: int maxCount = isClosureRequired() ? MAX_LOOPS : 2;
071: while (toAnalyze.size() != 0 && count++ < maxCount) {
072: DependencyVisitor dependencyVisitor = new DependencyVisitor();
073: for (Enumeration e = toAnalyze.keys(); e.hasMoreElements();) {
074: String classname = (String) e.nextElement();
075: dependencies.put(classname, classname);
076: try {
077: File container = getClassContainer(classname);
078: if (container == null) {
079: continue;
080: }
081: containers.put(container, container);
082:
083: ClassParser parser = null;
084: if (container.getName().endsWith(".class")) {
085: parser = new ClassParser(container.getPath());
086: } else {
087: parser = new ClassParser(container.getPath(),
088: classname.replace('.', '/') + ".class");
089: }
090:
091: JavaClass javaClass = parser.parse();
092: DescendingVisitor traverser = new DescendingVisitor(
093: javaClass, dependencyVisitor);
094: traverser.visit();
095: } catch (IOException ioe) {
096: // ignore
097: }
098: }
099:
100: toAnalyze.clear();
101:
102: // now recover all the dependencies collected and add to the list.
103: Enumeration depsEnum = dependencyVisitor.getDependencies();
104: while (depsEnum.hasMoreElements()) {
105: String className = (String) depsEnum.nextElement();
106: if (!dependencies.containsKey(className)) {
107: toAnalyze.put(className, className);
108: }
109: }
110: }
111:
112: files.removeAllElements();
113: for (Enumeration e = containers.keys(); e.hasMoreElements();) {
114: files.addElement((File) e.nextElement());
115: }
116:
117: classes.removeAllElements();
118: for (Enumeration e = dependencies.keys(); e.hasMoreElements();) {
119: classes.addElement((String) e.nextElement());
120: }
121: }
122:
123: /**
124: * Indicate if this analyzer can determine dependent files.
125: *
126: * @return true if the analyzer provides dependency file information.
127: */
128: protected boolean supportsFileDependencies() {
129: return true;
130: }
131: }
|