source: other-projects/trunk/gs3-release-maker/apache-ant-1.6.5/src/main/org/apache/tools/ant/util/depend/bcel/DependencyVisitor.java@ 14627

Last change on this file since 14627 was 14627, checked in by oranfry, 17 years ago

initial import of the gs3-release-maker

File size: 6.2 KB
Line 
1/*
2 * Copyright 2001-2004 The Apache Software Foundation
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *
16 */
17package org.apache.tools.ant.util.depend.bcel;
18
19import java.util.Enumeration;
20import java.util.Hashtable;
21import java.util.StringTokenizer;
22import org.apache.bcel.classfile.ConstantClass;
23import org.apache.bcel.classfile.ConstantPool;
24import org.apache.bcel.classfile.EmptyVisitor;
25import org.apache.bcel.classfile.Field;
26import org.apache.bcel.classfile.JavaClass;
27import org.apache.bcel.classfile.Method;
28import org.apache.bcel.classfile.ConstantNameAndType;
29
30/**
31 * A BCEL visitor implementation to collect class dependency information
32 *
33 */
34public class DependencyVisitor extends EmptyVisitor {
35 /** The collectd dependencies */
36 private Hashtable dependencies = new Hashtable();
37 /**
38 * The current class's constant pool - used to determine class names
39 * from class references.
40 */
41 private ConstantPool constantPool;
42
43 /**
44 * Get the dependencies collected by this visitor
45 *
46 * @return a Enumeration of classnames, being the classes upon which the
47 * visited classes depend.
48 */
49 public Enumeration getDependencies() {
50 return dependencies.keys();
51 }
52
53 /** Clear the curretn set of collected dependencies. */
54 public void clearDependencies() {
55 dependencies.clear();
56 }
57
58 /**
59 * Visit the constant pool of a class
60 *
61 * @param constantPool the constant pool of the class being visited.
62 */
63 public void visitConstantPool(ConstantPool constantPool) {
64 this.constantPool = constantPool;
65 }
66
67 /**
68 * Visit a class reference
69 *
70 * @param constantClass the constantClass entry for the class reference
71 */
72 public void visitConstantClass(ConstantClass constantClass) {
73 String classname
74 = constantClass.getConstantValue(constantPool).toString();
75 addSlashClass(classname);
76 }
77
78 /**
79 * Visit a name and type ref
80 *
81 * Look for class references in this
82 *
83 * @param obj the name and type reference being visited.
84 */
85 public void visitConstantNameAndType(ConstantNameAndType obj) {
86 String name = obj.getName(constantPool);
87 if (obj.getSignature(constantPool).equals("Ljava/lang/Class;")
88 && name.startsWith("class$")) {
89 String classname = name.substring(6).replace('$', '.');
90 // does the class have a package structure
91 int index = classname.lastIndexOf(".");
92 if (index > 0) {
93 char start;
94 // check if the package structure is more than 1 level deep
95 int index2 = classname.lastIndexOf(".", index - 1);
96 if (index2 != -1) {
97 // class name has more than 1 package level 'com.company.Class'
98 start = classname.charAt(index2 + 1);
99 } else {
100 // class name has only 1 package level 'package.Class'
101 start = classname.charAt(0);
102 }
103 // Check to see if it's an inner class 'com.company.Class$Inner'
104 if ((start > 0x40) && (start < 0x5B)) {
105 // first letter of the previous segment of the class name 'Class'
106 // is upper case ascii. so according to the spec it's an inner class
107 classname = classname.substring(0, index) + "$"
108 + classname.substring(index + 1);
109 addClass(classname);
110 } else {
111 // Add the class in dotted notation 'com.company.Class'
112 addClass(classname);
113 }
114 } else {
115 // Add a class with no package 'Class'
116 addClass(classname);
117 }
118 }
119 }
120
121 /**
122 * Visit a field of the class.
123 *
124 * @param field the field being visited
125 */
126 public void visitField(Field field) {
127 addClasses(field.getSignature());
128 }
129
130 /**
131 * Visit a Java class
132 *
133 * @param javaClass the class being visited.
134 */
135 public void visitJavaClass(JavaClass javaClass) {
136 addClass(javaClass.getClassName());
137 }
138
139 /**
140 * Visit a method of the current class
141 *
142 * @param method the method being visited.
143 */
144 public void visitMethod(Method method) {
145 String signature = method.getSignature();
146 int pos = signature.indexOf(")");
147 addClasses(signature.substring(1, pos));
148 addClasses(signature.substring(pos + 1));
149 }
150
151 /**
152 * Add a classname to the list of dependency classes
153 *
154 * @param classname the class to be added to the list of dependencies.
155 */
156 void addClass(String classname) {
157 dependencies.put(classname, classname);
158 }
159
160 /**
161 * Add all the classes from a descriptor string.
162 *
163 * @param string the descriptor string, being descriptors separated by
164 * ';' characters.
165 */
166 private void addClasses(String string) {
167 StringTokenizer tokens = new StringTokenizer(string, ";");
168 while (tokens.hasMoreTokens()) {
169 String descriptor = tokens.nextToken();
170 int pos = descriptor.indexOf('L');
171 if (pos != -1) {
172 addSlashClass(descriptor.substring(pos + 1));
173 }
174 }
175 }
176
177 /**
178 * Adds a class name in slash format
179 * (for example org/apache/tools/ant/Main).
180 *
181 * @param classname the class name in slash format
182 */
183 private void addSlashClass(String classname) {
184 addClass(classname.replace('/', '.'));
185 }
186}
187
Note: See TracBrowser for help on using the repository browser.