KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > batik > util > ClassFileUtilities


1 /*
2
3    Copyright 2001,2003 The Apache Software Foundation
4
5    Licensed under the Apache License, Version 2.0 (the "License");
6    you may not use this file except in compliance with the License.
7    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.batik.util;
19
20 import java.io.DataInputStream JavaDoc;
21 import java.io.File JavaDoc;
22 import java.io.FileInputStream JavaDoc;
23 import java.io.IOException JavaDoc;
24 import java.io.InputStream JavaDoc;
25 import java.util.HashSet JavaDoc;
26 import java.util.Iterator JavaDoc;
27 import java.util.Set JavaDoc;
28
29 /**
30  * This class contains utility methods to manipulate Java classes.
31  *
32  * @author <a HREF="mailto:stephane@hillion.org">Stephane Hillion</a>
33  * @version $Id: ClassFileUtilities.java,v 1.4 2004/08/18 07:15:48 vhardy Exp $
34  */

35 public class ClassFileUtilities {
36
37     // Constant pool info tags
38
public final static byte CONSTANT_UTF8_INFO = 1;
39     public final static byte CONSTANT_INTEGER_INFO = 3;
40     public final static byte CONSTANT_FLOAT_INFO = 4;
41     public final static byte CONSTANT_LONG_INFO = 5;
42     public final static byte CONSTANT_DOUBLE_INFO = 6;
43     public final static byte CONSTANT_CLASS_INFO = 7;
44     public final static byte CONSTANT_STRING_INFO = 8;
45     public final static byte CONSTANT_FIELDREF_INFO = 9;
46     public final static byte CONSTANT_METHODREF_INFO = 10;
47     public final static byte CONSTANT_INTERFACEMETHODREF_INFO = 11;
48     public final static byte CONSTANT_NAMEANDTYPE_INFO = 12;
49
50     /**
51      * This class does not need to be instantiated.
52      */

53     protected ClassFileUtilities() {
54     }
55
56     /**
57      * Returns the dependencies of the given class.
58      * @param path The root class path.
59      * @param classpath The set of directories (Strings) to scan.
60      * @return a list of paths representing the used classes.
61      */

62     public static Set JavaDoc getClassDependencies(String JavaDoc path, Set JavaDoc classpath)
63         throws IOException JavaDoc {
64         InputStream JavaDoc is = new FileInputStream JavaDoc(path);
65
66         Set JavaDoc result = new HashSet JavaDoc();
67         Set JavaDoc done = new HashSet JavaDoc();
68
69         computeClassDependencies(is, classpath, done, result);
70
71         return result;
72     }
73
74     private static void computeClassDependencies(InputStream JavaDoc is,
75                                                  Set JavaDoc classpath,
76                                                  Set JavaDoc done,
77                                                  Set JavaDoc result) throws IOException JavaDoc {
78         Iterator JavaDoc it = getClassDependencies(is).iterator();
79         while (it.hasNext()) {
80             String JavaDoc s = (String JavaDoc)it.next();
81             if (!done.contains(s)) {
82                 done.add(s);
83
84                 Iterator JavaDoc cpit = classpath.iterator();
85                 while (cpit.hasNext()) {
86                     String JavaDoc root = (String JavaDoc)cpit.next();
87                     StringBuffer JavaDoc sb = new StringBuffer JavaDoc(root);
88                     sb.append('/').append(s).append(".class");
89                     String JavaDoc path = sb.toString();
90
91                     File JavaDoc f = new File JavaDoc(path);
92                     if (f.isFile()) {
93                         result.add(path);
94                         
95                         computeClassDependencies(new FileInputStream JavaDoc(f),
96                                                  classpath,
97                                                  done,
98                                                  result);
99                     }
100                 }
101             }
102         }
103     }
104
105     /**
106      * Returns the dependencies of the given class.
107      * @return a list of strings representing the used classes.
108      */

109     public static Set JavaDoc getClassDependencies(InputStream JavaDoc is) throws IOException JavaDoc {
110         DataInputStream JavaDoc dis = new DataInputStream JavaDoc(is);
111
112         if (dis.readInt() != 0xcafebabe) {
113             throw new IOException JavaDoc("Invalid classfile");
114         }
115         
116         dis.readInt();
117         
118         int len = dis.readShort();
119         String JavaDoc[] strs = new String JavaDoc[len];
120         Set JavaDoc classes = new HashSet JavaDoc();
121         Set JavaDoc desc = new HashSet JavaDoc();
122
123         for (int i = 1; i < len; i++) {
124             switch (dis.readByte() & 0xff) {
125             case CONSTANT_LONG_INFO:
126             case CONSTANT_DOUBLE_INFO:
127                 dis.readLong();
128                 i++;
129                 break;
130
131             case CONSTANT_FIELDREF_INFO:
132             case CONSTANT_METHODREF_INFO:
133             case CONSTANT_INTERFACEMETHODREF_INFO:
134             case CONSTANT_INTEGER_INFO:
135             case CONSTANT_FLOAT_INFO:
136                 dis.readInt();
137                 break;
138
139             case CONSTANT_CLASS_INFO:
140                 classes.add(new Integer JavaDoc(dis.readShort() & 0xffff));
141                 break;
142
143             case CONSTANT_STRING_INFO:
144                 dis.readShort();
145                 break;
146                 
147             case CONSTANT_NAMEANDTYPE_INFO:
148                 dis.readShort();
149                 desc.add(new Integer JavaDoc(dis.readShort() & 0xffff));
150                 break;
151
152             case CONSTANT_UTF8_INFO:
153                 strs[i] = dis.readUTF();
154                 break;
155                 
156             default:
157                 throw new RuntimeException JavaDoc();
158             }
159         }
160
161         Set JavaDoc result = new HashSet JavaDoc();
162
163         Iterator JavaDoc it = classes.iterator();
164         while (it.hasNext()) {
165             result.add(strs[((Integer JavaDoc)it.next()).intValue()]);
166         }
167
168         it = desc.iterator();
169         while (it.hasNext()) {
170             result.addAll(getDescriptorClasses(strs[((Integer JavaDoc)it.next()).intValue()]));
171         }
172
173         return result;
174     }
175
176     /**
177      * Returns the classes contained in a field or method desciptor.
178      */

179     protected static Set JavaDoc getDescriptorClasses(String JavaDoc desc) {
180         Set JavaDoc result = new HashSet JavaDoc();
181         int i = 0;
182         char c = desc.charAt(i);
183         switch (c) {
184         case '(':
185             loop: for (;;) {
186                 c = desc.charAt(++i);
187                 switch (c) {
188                 case '[':
189                     do {
190                         c = desc.charAt(++i);
191                     } while (c == '[');
192                     if (c != 'L') {
193                         break;
194                     }
195
196                 case 'L':
197                     c = desc.charAt(++i);
198                     StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
199                     while (c != ';') {
200                         sb.append(c);
201                         c = desc.charAt(++i);
202                     }
203                     result.add(sb.toString());
204                     break;
205                     
206                 default:
207                     break;
208                     
209                 case ')':
210                     break loop;
211                 }
212             }
213             c = desc.charAt(++i);
214             switch (c) {
215             case '[':
216                 do {
217                     c = desc.charAt(++i);
218                 } while (c == '[');
219                 if (c != 'L') {
220                     break;
221                 }
222
223             case 'L':
224                 c = desc.charAt(++i);
225                 StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
226                 while (c != ';') {
227                     sb.append(c);
228                     c = desc.charAt(++i);
229                 }
230                 result.add(sb.toString());
231                 break;
232
233             default:
234             case 'V':
235             }
236             break;
237
238         case '[':
239             do {
240                 c = desc.charAt(++i);
241             } while (c == '[');
242             if (c != 'L') {
243                 break;
244             }
245
246         case 'L':
247             c = desc.charAt(++i);
248             StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
249             while (c != ';') {
250                 sb.append(c);
251                 c = desc.charAt(++i);
252             }
253             result.add(sb.toString());
254             break;
255
256         default:
257         }
258
259         return result;
260     }
261 }
262
Popular Tags