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.JavaClass;
027: import org.apache.tools.ant.util.depend.AbstractAnalyzer;
028:
029: /**
030: * A dependency analyzer which returns superclass and superinterface
031: * dependencies.
032: *
033: */
034: public class AncestorAnalyzer extends AbstractAnalyzer {
035:
036: /**
037: * Default constructor
038: *
039: * Causes the BCEL classes to load to ensure BCEL dependencies can
040: * be satisfied
041: */
042: public AncestorAnalyzer() {
043: // force BCEL classes to load now
044: try {
045: new ClassParser("force");
046: } catch (IOException e) {
047: // ignore
048: }
049: }
050:
051: /**
052: * Determine the dependencies of the configured root classes.
053: *
054: * @param files a vector to be populated with the files which contain
055: * the dependency classes
056: * @param classes a vector to be populated with the names of the
057: * depencency classes.
058: */
059: protected void determineDependencies(Vector files, Vector classes) {
060: // we get the root classes and build up a set of
061: // classes upon which they depend
062: Hashtable dependencies = new Hashtable();
063: Hashtable containers = new Hashtable();
064: Hashtable toAnalyze = new Hashtable();
065: Hashtable nextAnalyze = new Hashtable();
066: for (Enumeration e = getRootClasses(); e.hasMoreElements();) {
067: String classname = (String) e.nextElement();
068: toAnalyze.put(classname, classname);
069: }
070:
071: int count = 0;
072: int maxCount = isClosureRequired() ? MAX_LOOPS : 2;
073: while (toAnalyze.size() != 0 && count++ < maxCount) {
074: nextAnalyze.clear();
075: for (Enumeration e = toAnalyze.keys(); e.hasMoreElements();) {
076: String classname = (String) e.nextElement();
077: dependencies.put(classname, classname);
078: try {
079: File container = getClassContainer(classname);
080: if (container == null) {
081: continue;
082: }
083: containers.put(container, container);
084:
085: ClassParser parser = null;
086: if (container.getName().endsWith(".class")) {
087: parser = new ClassParser(container.getPath());
088: } else {
089: parser = new ClassParser(container.getPath(),
090: classname.replace('.', '/') + ".class");
091: }
092:
093: JavaClass javaClass = parser.parse();
094: String[] interfaces = javaClass.getInterfaceNames();
095: for (int i = 0; i < interfaces.length; ++i) {
096: String interfaceName = interfaces[i];
097: if (!dependencies.containsKey(interfaceName)) {
098: nextAnalyze.put(interfaceName,
099: interfaceName);
100: }
101: }
102:
103: if (javaClass.isClass()) {
104: String super Class = javaClass
105: .getSuperclassName();
106: if (!dependencies.containsKey(super Class)) {
107: nextAnalyze.put(super Class, super Class);
108: }
109: }
110: } catch (IOException ioe) {
111: // ignore
112: }
113: }
114:
115: Hashtable temp = toAnalyze;
116: toAnalyze = nextAnalyze;
117: nextAnalyze = temp;
118: }
119:
120: files.removeAllElements();
121: for (Enumeration e = containers.keys(); e.hasMoreElements();) {
122: files.addElement((File) e.nextElement());
123: }
124:
125: classes.removeAllElements();
126: for (Enumeration e = dependencies.keys(); e.hasMoreElements();) {
127: classes.addElement((String) e.nextElement());
128: }
129: }
130:
131: /**
132: * Indicate if this analyzer can determine dependent files.
133: *
134: * @return true if the analyzer provides dependency file information.
135: */
136: protected boolean supportsFileDependencies() {
137: return true;
138: }
139:
140: }
|