KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > tools > ant > util > depend > bcel > DependencyVisitor


1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one or more
3  * contributor license agreements. See the NOTICE file distributed with
4  * this work for additional information regarding copyright ownership.
5  * The ASF licenses this file to You under the Apache License, Version 2.0
6  * (the "License"); you may not use this file except in compliance with
7  * the License. You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  */

18 package org.apache.tools.ant.util.depend.bcel;
19
20 import java.util.Enumeration JavaDoc;
21 import java.util.Hashtable JavaDoc;
22 import java.util.StringTokenizer JavaDoc;
23 import org.apache.bcel.classfile.ConstantClass;
24 import org.apache.bcel.classfile.ConstantPool;
25 import org.apache.bcel.classfile.EmptyVisitor;
26 import org.apache.bcel.classfile.Field;
27 import org.apache.bcel.classfile.JavaClass;
28 import org.apache.bcel.classfile.Method;
29 import org.apache.bcel.classfile.ConstantNameAndType;
30
31 /**
32  * A BCEL visitor implementation to collect class dependency information
33  *
34  */

35 public class DependencyVisitor extends EmptyVisitor {
36     /** The collectd dependencies */
37     private Hashtable JavaDoc dependencies = new Hashtable JavaDoc();
38     /**
39      * The current class's constant pool - used to determine class names
40      * from class references.
41      */

42     private ConstantPool constantPool;
43
44     /**
45      * Get the dependencies collected by this visitor
46      *
47      * @return a Enumeration of classnames, being the classes upon which the
48      * visited classes depend.
49      */

50     public Enumeration JavaDoc getDependencies() {
51         return dependencies.keys();
52     }
53
54     /** Clear the curretn set of collected dependencies. */
55     public void clearDependencies() {
56         dependencies.clear();
57     }
58
59     /**
60      * Visit the constant pool of a class
61      *
62      * @param constantPool the constant pool of the class being visited.
63      */

64     public void visitConstantPool(ConstantPool constantPool) {
65         this.constantPool = constantPool;
66     }
67
68     /**
69      * Visit a class reference
70      *
71      * @param constantClass the constantClass entry for the class reference
72      */

73     public void visitConstantClass(ConstantClass constantClass) {
74         String JavaDoc classname
75              = constantClass.getConstantValue(constantPool).toString();
76         addSlashClass(classname);
77     }
78
79     /**
80      * Visit a name and type ref
81      *
82      * Look for class references in this
83      *
84      * @param obj the name and type reference being visited.
85      */

86     public void visitConstantNameAndType(ConstantNameAndType obj) {
87         String JavaDoc name = obj.getName(constantPool);
88         if (obj.getSignature(constantPool).equals("Ljava/lang/Class;")
89                 && name.startsWith("class$")) {
90             String JavaDoc classname = name.substring(6).replace('$', '.');
91             // does the class have a package structure
92
int index = classname.lastIndexOf(".");
93             if (index > 0) {
94                 char start;
95                 // check if the package structure is more than 1 level deep
96
int index2 = classname.lastIndexOf(".", index - 1);
97                 if (index2 != -1) {
98                     // class name has more than 1 package level 'com.company.Class'
99
start = classname.charAt(index2 + 1);
100                 } else {
101                     // class name has only 1 package level 'package.Class'
102
start = classname.charAt(0);
103                 }
104                 // Check to see if it's an inner class 'com.company.Class$Inner'
105
if ((start > 0x40) && (start < 0x5B)) {
106                     // first letter of the previous segment of the class name 'Class'
107
// is upper case ascii. so according to the spec it's an inner class
108
classname = classname.substring(0, index) + "$"
109                         + classname.substring(index + 1);
110                     addClass(classname);
111                 } else {
112                     // Add the class in dotted notation 'com.company.Class'
113
addClass(classname);
114                 }
115             } else {
116                 // Add a class with no package 'Class'
117
addClass(classname);
118             }
119         }
120     }
121
122     /**
123      * Visit a field of the class.
124      *
125      * @param field the field being visited
126      */

127     public void visitField(Field field) {
128         addClasses(field.getSignature());
129     }
130
131     /**
132      * Visit a Java class
133      *
134      * @param javaClass the class being visited.
135      */

136     public void visitJavaClass(JavaClass javaClass) {
137         addClass(javaClass.getClassName());
138     }
139
140     /**
141      * Visit a method of the current class
142      *
143      * @param method the method being visited.
144      */

145     public void visitMethod(Method method) {
146         String JavaDoc signature = method.getSignature();
147         int pos = signature.indexOf(")");
148         addClasses(signature.substring(1, pos));
149         addClasses(signature.substring(pos + 1));
150     }
151
152     /**
153      * Add a classname to the list of dependency classes
154      *
155      * @param classname the class to be added to the list of dependencies.
156      */

157     void addClass(String JavaDoc classname) {
158         dependencies.put(classname, classname);
159     }
160
161     /**
162      * Add all the classes from a descriptor string.
163      *
164      * @param string the descriptor string, being descriptors separated by
165      * ';' characters.
166      */

167     private void addClasses(String JavaDoc string) {
168         StringTokenizer JavaDoc tokens = new StringTokenizer JavaDoc(string, ";");
169         while (tokens.hasMoreTokens()) {
170             String JavaDoc descriptor = tokens.nextToken();
171             int pos = descriptor.indexOf('L');
172             if (pos != -1) {
173                 addSlashClass(descriptor.substring(pos + 1));
174             }
175         }
176     }
177
178     /**
179      * Adds a class name in slash format
180      * (for example org/apache/tools/ant/Main).
181      *
182      * @param classname the class name in slash format
183      */

184     private void addSlashClass(String JavaDoc classname) {
185         addClass(classname.replace('/', '.'));
186     }
187 }
188
189
Popular Tags