1 package serp.bytecode;
2
3 import java.io.*;
4 import java.util.*;
5
6 import serp.bytecode.lowlevel.*;
7 import serp.bytecode.visitor.*;
8 import serp.util.*;
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27 public class Project implements VisitAcceptor {
28 private final String _name;
29 private final HashMap _cache = new HashMap();
30 private final NameCache _names = new NameCache();
31
32
33
34
35 public Project() {
36 this(null);
37 }
38
39
40
41
42 public Project(String name) {
43 _name = name;
44 }
45
46
47
48
49 public String getName() {
50 return _name;
51 }
52
53
54
55
56
57 public NameCache getNameCache() {
58 return _names;
59 }
60
61
62
63
64
65
66 public BCClass loadClass(String name) {
67 return loadClass(name, null);
68 }
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85 public BCClass loadClass(String name, ClassLoader loader) {
86
87 name = _names.getExternalForm(name, false);
88
89 BCClass cached = checkCache(name);
90 if (cached != null)
91 return cached;
92
93
94 if (loader == null)
95 loader = Thread.currentThread().getContextClassLoader();
96 try {
97 return loadClass(Strings.toClass(name, loader));
98 } catch (Exception e) {
99 }
100
101 String componentName = _names.getComponentName(name);
102 BCClass ret = new BCClass(this);
103 if (componentName != null)
104 ret.setState(new ArrayState(name, componentName));
105 else {
106 ret.setState(new ObjectState(_names));
107 ret.setName(name);
108 ret.setSuperclass(Object.class);
109 }
110 cache(name, ret);
111 return ret;
112 }
113
114
115
116
117
118
119
120
121
122
123
124
125 public BCClass loadClass(Class type) {
126 BCClass cached = checkCache(type.getName());
127 if (cached != null)
128 return cached;
129
130 BCClass ret = new BCClass(this);
131 if (type.isPrimitive())
132 ret.setState(new PrimitiveState(type, _names));
133 else if (type.isArray())
134 ret.setState(new ArrayState(type.getName(), _names.getExternalForm
135 (type.getComponentType().getName(), false)));
136 else {
137 ret.setState(new ObjectState(_names));
138 try {
139 ret.read(type);
140 } catch (IOException ioe) {
141 throw new RuntimeException(ioe.toString());
142 }
143 }
144 cache(type.getName(), ret);
145 return ret;
146 }
147
148
149
150
151
152
153
154
155
156 public BCClass loadClass(File classFile) {
157 return loadClass(classFile, null);
158 }
159
160
161
162
163
164
165
166
167
168 public BCClass loadClass(File classFile, ClassLoader loader) {
169
170 BCClass ret = new BCClass(this);
171 ret.setState(new ObjectState(_names));
172 try {
173 ret.read(classFile, loader);
174 } catch (IOException ioe) {
175 throw new RuntimeException(ioe.toString());
176 }
177
178 String name = ret.getName();
179 BCClass cached = checkCache(name);
180 if (cached != null)
181 return cached;
182
183 cache(name, ret);
184 return ret;
185 }
186
187
188
189
190
191
192
193
194
195 public BCClass loadClass(InputStream in) {
196 return loadClass(in, null);
197 }
198
199
200
201
202
203
204
205
206
207 public BCClass loadClass(InputStream in, ClassLoader loader) {
208 BCClass ret = new BCClass(this);
209 ret.setState(new ObjectState(_names));
210 try {
211 ret.read(in, loader);
212 } catch (IOException ioe) {
213 throw new RuntimeException(ioe.toString());
214 }
215
216 String name = ret.getName();
217 BCClass cached = checkCache(name);
218 if (cached != null)
219 return cached;
220
221 cache(name, ret);
222 return ret;
223 }
224
225
226
227
228
229
230
231 public BCClass loadClass(BCClass bc) {
232 String name = bc.getName();
233 BCClass cached = checkCache(name);
234 if (cached != null)
235 return cached;
236
237 BCClass ret = new BCClass(this);
238 if (bc.isPrimitive())
239 ret.setState(new PrimitiveState(bc.getType(), _names));
240 else if (bc.isArray())
241 ret.setState(new ArrayState(bc.getName(), bc.getComponentName()));
242 else {
243 ret.setState(new ObjectState(_names));
244 ret.read(bc);
245 }
246
247 cache(name, ret);
248 return ret;
249 }
250
251
252
253
254 public void clear() {
255 Collection values = _cache.values();
256 BCClass bc;
257 for (Iterator itr = values.iterator(); itr.hasNext();) {
258 bc = (BCClass) itr.next();
259 itr.remove();
260 bc.invalidate();
261 }
262 _names.clear();
263 }
264
265
266
267
268
269
270
271 public boolean removeClass(String type) {
272 return removeClass(checkCache(type));
273 }
274
275
276
277
278
279
280
281 public boolean removeClass(Class type) {
282 if (type == null)
283 return false;
284 return removeClass(checkCache(type.getName()));
285 }
286
287
288
289
290
291
292
293 public boolean removeClass(BCClass type) {
294 if (type == null)
295 return false;
296 if (!removeFromCache(type.getName(), type))
297 return false;
298 type.invalidate();
299 return true;
300 }
301
302
303
304
305 public BCClass[] getClasses() {
306 Collection values = _cache.values();
307 return (BCClass[]) values.toArray(new BCClass[values.size()]);
308 }
309
310
311
312
313 public boolean containsClass(String type) {
314 return _cache.containsKey(type);
315 }
316
317
318
319
320 public boolean containsClass(Class type) {
321 return (type == null) ? false : containsClass(type.getName());
322 }
323
324
325
326
327 public boolean containsClass(BCClass type) {
328 return (type == null) ? false : containsClass(type.getName());
329 }
330
331 public void acceptVisit(BCVisitor visit) {
332 visit.enterProject(this);
333 BCClass[] classes = getClasses();
334 for (int i = 0; i < classes.length; i++)
335 classes[i].acceptVisit(visit);
336 visit.exitProject(this);
337 }
338
339
340
341
342
343
344
345 void renameClass(String oldName, String newName, BCClass bc) {
346 if (oldName.equals(newName))
347 return;
348
349 BCClass cached = (BCClass) checkCache(newName);
350 if (cached != null)
351 throw new IllegalStateException("A class with name " + newName +
352 " already exists in this project");
353
354 removeFromCache(oldName, bc);
355 cache(newName, bc);
356 }
357
358
359
360
361 private BCClass checkCache(String name) {
362 return (BCClass) _cache.get(name);
363 }
364
365
366
367
368 private void cache(String name, BCClass bc) {
369 _cache.put(name, bc);
370 }
371
372
373
374
375 private boolean removeFromCache(String name, BCClass bc) {
376 BCClass rem = (BCClass) checkCache(name);
377 if (rem != bc)
378 return false;
379 _cache.remove(name);
380 return true;
381 }
382 }