6
|
1 |
/*
|
|
2 |
* reserved comment block
|
|
3 |
* DO NOT REMOVE OR ALTER!
|
|
4 |
*/
|
|
5 |
package com.sun.org.apache.bcel.internal.generic;
|
|
6 |
|
|
7 |
/* ====================================================================
|
|
8 |
* The Apache Software License, Version 1.1
|
|
9 |
*
|
|
10 |
* Copyright (c) 2001 The Apache Software Foundation. All rights
|
|
11 |
* reserved.
|
|
12 |
*
|
|
13 |
* Redistribution and use in source and binary forms, with or without
|
|
14 |
* modification, are permitted provided that the following conditions
|
|
15 |
* are met:
|
|
16 |
*
|
|
17 |
* 1. Redistributions of source code must retain the above copyright
|
|
18 |
* notice, this list of conditions and the following disclaimer.
|
|
19 |
*
|
|
20 |
* 2. Redistributions in binary form must reproduce the above copyright
|
|
21 |
* notice, this list of conditions and the following disclaimer in
|
|
22 |
* the documentation and/or other materials provided with the
|
|
23 |
* distribution.
|
|
24 |
*
|
|
25 |
* 3. The end-user documentation included with the redistribution,
|
|
26 |
* if any, must include the following acknowledgment:
|
|
27 |
* "This product includes software developed by the
|
|
28 |
* Apache Software Foundation (http://www.apache.org/)."
|
|
29 |
* Alternately, this acknowledgment may appear in the software itself,
|
|
30 |
* if and wherever such third-party acknowledgments normally appear.
|
|
31 |
*
|
|
32 |
* 4. The names "Apache" and "Apache Software Foundation" and
|
|
33 |
* "Apache BCEL" must not be used to endorse or promote products
|
|
34 |
* derived from this software without prior written permission. For
|
|
35 |
* written permission, please contact apache@apache.org.
|
|
36 |
*
|
|
37 |
* 5. Products derived from this software may not be called "Apache",
|
|
38 |
* "Apache BCEL", nor may "Apache" appear in their name, without
|
|
39 |
* prior written permission of the Apache Software Foundation.
|
|
40 |
*
|
|
41 |
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
|
|
42 |
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
|
43 |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
44 |
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
|
|
45 |
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
46 |
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
47 |
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
|
|
48 |
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
|
49 |
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
50 |
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
|
51 |
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
52 |
* SUCH DAMAGE.
|
|
53 |
* ====================================================================
|
|
54 |
*
|
|
55 |
* This software consists of voluntary contributions made by many
|
|
56 |
* individuals on behalf of the Apache Software Foundation. For more
|
|
57 |
* information on the Apache Software Foundation, please see
|
|
58 |
* <http://www.apache.org/>.
|
|
59 |
*/
|
|
60 |
|
|
61 |
import com.sun.org.apache.bcel.internal.Constants;
|
|
62 |
import com.sun.org.apache.bcel.internal.classfile.*;
|
|
63 |
import java.util.ArrayList;
|
|
64 |
import java.util.Iterator;
|
|
65 |
|
|
66 |
/**
|
|
67 |
* Template class for building up a java class. May be initialized with an
|
|
68 |
* existing java class (file).
|
|
69 |
*
|
|
70 |
* @see JavaClass
|
|
71 |
* @author <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A>
|
|
72 |
*/
|
|
73 |
public class ClassGen extends AccessFlags implements Cloneable {
|
|
74 |
/* Corresponds to the fields found in a JavaClass object.
|
|
75 |
*/
|
|
76 |
private String class_name, super_class_name, file_name;
|
|
77 |
private int class_name_index = -1, superclass_name_index = -1;
|
|
78 |
private int major = Constants.MAJOR_1_1, minor = Constants.MINOR_1_1;
|
|
79 |
|
|
80 |
private ConstantPoolGen cp; // Template for building up constant pool
|
|
81 |
|
|
82 |
// ArrayLists instead of arrays to gather fields, methods, etc.
|
|
83 |
private ArrayList field_vec = new ArrayList();
|
|
84 |
private ArrayList method_vec = new ArrayList();
|
|
85 |
private ArrayList attribute_vec = new ArrayList();
|
|
86 |
private ArrayList interface_vec = new ArrayList();
|
|
87 |
|
|
88 |
/** Convenience constructor to set up some important values initially.
|
|
89 |
*
|
|
90 |
* @param class_name fully qualified class name
|
|
91 |
* @param super_class_name fully qualified superclass name
|
|
92 |
* @param file_name source file name
|
|
93 |
* @param access_flags access qualifiers
|
|
94 |
* @param interfaces implemented interfaces
|
|
95 |
* @param cp constant pool to use
|
|
96 |
*/
|
|
97 |
public ClassGen(String class_name, String super_class_name, String file_name,
|
|
98 |
int access_flags, String[] interfaces, ConstantPoolGen cp) {
|
|
99 |
this.class_name = class_name;
|
|
100 |
this.super_class_name = super_class_name;
|
|
101 |
this.file_name = file_name;
|
|
102 |
this.access_flags = access_flags;
|
|
103 |
this.cp = cp;
|
|
104 |
|
|
105 |
// Put everything needed by default into the constant pool and the vectors
|
|
106 |
if(file_name != null)
|
|
107 |
addAttribute(new SourceFile(cp.addUtf8("SourceFile"), 2,
|
|
108 |
cp.addUtf8(file_name), cp.getConstantPool()));
|
|
109 |
|
|
110 |
class_name_index = cp.addClass(class_name);
|
|
111 |
superclass_name_index = cp.addClass(super_class_name);
|
|
112 |
|
|
113 |
if(interfaces != null)
|
|
114 |
for(int i=0; i < interfaces.length; i++)
|
|
115 |
addInterface(interfaces[i]);
|
|
116 |
}
|
|
117 |
|
|
118 |
/** Convenience constructor to set up some important values initially.
|
|
119 |
*
|
|
120 |
* @param class_name fully qualified class name
|
|
121 |
* @param super_class_name fully qualified superclass name
|
|
122 |
* @param file_name source file name
|
|
123 |
* @param access_flags access qualifiers
|
|
124 |
* @param interfaces implemented interfaces
|
|
125 |
*/
|
|
126 |
public ClassGen(String class_name, String super_class_name, String file_name,
|
|
127 |
int access_flags, String[] interfaces) {
|
|
128 |
this(class_name, super_class_name, file_name, access_flags, interfaces,
|
|
129 |
new ConstantPoolGen());
|
|
130 |
}
|
|
131 |
|
|
132 |
/**
|
|
133 |
* Initialize with existing class.
|
|
134 |
* @param clazz JavaClass object (e.g. read from file)
|
|
135 |
*/
|
|
136 |
public ClassGen(JavaClass clazz) {
|
|
137 |
class_name_index = clazz.getClassNameIndex();
|
|
138 |
superclass_name_index = clazz.getSuperclassNameIndex();
|
|
139 |
class_name = clazz.getClassName();
|
|
140 |
super_class_name = clazz.getSuperclassName();
|
|
141 |
file_name = clazz.getSourceFileName();
|
|
142 |
access_flags = clazz.getAccessFlags();
|
|
143 |
cp = new ConstantPoolGen(clazz.getConstantPool());
|
|
144 |
major = clazz.getMajor();
|
|
145 |
minor = clazz.getMinor();
|
|
146 |
|
|
147 |
Attribute[] attributes = clazz.getAttributes();
|
|
148 |
Method[] methods = clazz.getMethods();
|
|
149 |
Field[] fields = clazz.getFields();
|
|
150 |
String[] interfaces = clazz.getInterfaceNames();
|
|
151 |
|
|
152 |
for(int i=0; i < interfaces.length; i++)
|
|
153 |
addInterface(interfaces[i]);
|
|
154 |
|
|
155 |
for(int i=0; i < attributes.length; i++)
|
|
156 |
addAttribute(attributes[i]);
|
|
157 |
|
|
158 |
for(int i=0; i < methods.length; i++)
|
|
159 |
addMethod(methods[i]);
|
|
160 |
|
|
161 |
for(int i=0; i < fields.length; i++)
|
|
162 |
addField(fields[i]);
|
|
163 |
}
|
|
164 |
|
|
165 |
/**
|
|
166 |
* @return the (finally) built up Java class object.
|
|
167 |
*/
|
|
168 |
public JavaClass getJavaClass() {
|
|
169 |
int[] interfaces = getInterfaces();
|
|
170 |
Field[] fields = getFields();
|
|
171 |
Method[] methods = getMethods();
|
|
172 |
Attribute[] attributes = getAttributes();
|
|
173 |
|
|
174 |
// Must be last since the above calls may still add something to it
|
|
175 |
ConstantPool cp = this.cp.getFinalConstantPool();
|
|
176 |
|
|
177 |
return new JavaClass(class_name_index, superclass_name_index,
|
|
178 |
file_name, major, minor, access_flags,
|
|
179 |
cp, interfaces, fields, methods, attributes);
|
|
180 |
}
|
|
181 |
|
|
182 |
/**
|
|
183 |
* Add an interface to this class, i.e., this class has to implement it.
|
|
184 |
* @param name interface to implement (fully qualified class name)
|
|
185 |
*/
|
|
186 |
public void addInterface(String name) {
|
|
187 |
interface_vec.add(name);
|
|
188 |
}
|
|
189 |
|
|
190 |
/**
|
|
191 |
* Remove an interface from this class.
|
|
192 |
* @param name interface to remove (fully qualified name)
|
|
193 |
*/
|
|
194 |
public void removeInterface(String name) {
|
|
195 |
interface_vec.remove(name);
|
|
196 |
}
|
|
197 |
|
|
198 |
/**
|
|
199 |
* @return major version number of class file
|
|
200 |
*/
|
|
201 |
public int getMajor() { return major; }
|
|
202 |
|
|
203 |
/** Set major version number of class file, default value is 45 (JDK 1.1)
|
|
204 |
* @param major major version number
|
|
205 |
*/
|
|
206 |
public void setMajor(int major) {
|
|
207 |
this.major = major;
|
|
208 |
}
|
|
209 |
|
|
210 |
/** Set minor version number of class file, default value is 3 (JDK 1.1)
|
|
211 |
* @param minor minor version number
|
|
212 |
*/
|
|
213 |
public void setMinor(int minor) {
|
|
214 |
this.minor = minor;
|
|
215 |
}
|
|
216 |
|
|
217 |
/**
|
|
218 |
* @return minor version number of class file
|
|
219 |
*/
|
|
220 |
public int getMinor() { return minor; }
|
|
221 |
|
|
222 |
/**
|
|
223 |
* Add an attribute to this class.
|
|
224 |
* @param a attribute to add
|
|
225 |
*/
|
|
226 |
public void addAttribute(Attribute a) { attribute_vec.add(a); }
|
|
227 |
|
|
228 |
/**
|
|
229 |
* Add a method to this class.
|
|
230 |
* @param m method to add
|
|
231 |
*/
|
|
232 |
public void addMethod(Method m) { method_vec.add(m); }
|
|
233 |
|
|
234 |
/**
|
|
235 |
* Convenience method.
|
|
236 |
*
|
|
237 |
* Add an empty constructor to this class that does nothing but calling super().
|
|
238 |
* @param access rights for constructor
|
|
239 |
*/
|
|
240 |
public void addEmptyConstructor(int access_flags) {
|
|
241 |
InstructionList il = new InstructionList();
|
|
242 |
il.append(InstructionConstants.THIS); // Push `this'
|
|
243 |
il.append(new INVOKESPECIAL(cp.addMethodref(super_class_name,
|
|
244 |
"<init>", "()V")));
|
|
245 |
il.append(InstructionConstants.RETURN);
|
|
246 |
|
|
247 |
MethodGen mg = new MethodGen(access_flags, Type.VOID, Type.NO_ARGS, null,
|
|
248 |
"<init>", class_name, il, cp);
|
|
249 |
mg.setMaxStack(1);
|
|
250 |
addMethod(mg.getMethod());
|
|
251 |
}
|
|
252 |
|
|
253 |
/**
|
|
254 |
* Add a field to this class.
|
|
255 |
* @param f field to add
|
|
256 |
*/
|
|
257 |
public void addField(Field f) { field_vec.add(f); }
|
|
258 |
|
|
259 |
public boolean containsField(Field f) { return field_vec.contains(f); }
|
|
260 |
|
|
261 |
/** @return field object with given name, or null
|
|
262 |
*/
|
|
263 |
public Field containsField(String name) {
|
|
264 |
for(Iterator e=field_vec.iterator(); e.hasNext(); ) {
|
|
265 |
Field f = (Field)e.next();
|
|
266 |
if(f.getName().equals(name))
|
|
267 |
return f;
|
|
268 |
}
|
|
269 |
|
|
270 |
return null;
|
|
271 |
}
|
|
272 |
|
|
273 |
/** @return method object with given name and signature, or null
|
|
274 |
*/
|
|
275 |
public Method containsMethod(String name, String signature) {
|
|
276 |
for(Iterator e=method_vec.iterator(); e.hasNext();) {
|
|
277 |
Method m = (Method)e.next();
|
|
278 |
if(m.getName().equals(name) && m.getSignature().equals(signature))
|
|
279 |
return m;
|
|
280 |
}
|
|
281 |
|
|
282 |
return null;
|
|
283 |
}
|
|
284 |
|
|
285 |
/**
|
|
286 |
* Remove an attribute from this class.
|
|
287 |
* @param a attribute to remove
|
|
288 |
*/
|
|
289 |
public void removeAttribute(Attribute a) { attribute_vec.remove(a); }
|
|
290 |
|
|
291 |
/**
|
|
292 |
* Remove a method from this class.
|
|
293 |
* @param m method to remove
|
|
294 |
*/
|
|
295 |
public void removeMethod(Method m) { method_vec.remove(m); }
|
|
296 |
|
|
297 |
/** Replace given method with new one. If the old one does not exist
|
|
298 |
* add the new_ method to the class anyway.
|
|
299 |
*/
|
|
300 |
public void replaceMethod(Method old, Method new_) {
|
|
301 |
if(new_ == null)
|
|
302 |
throw new ClassGenException("Replacement method must not be null");
|
|
303 |
|
|
304 |
int i = method_vec.indexOf(old);
|
|
305 |
|
|
306 |
if(i < 0)
|
|
307 |
method_vec.add(new_);
|
|
308 |
else
|
|
309 |
method_vec.set(i, new_);
|
|
310 |
}
|
|
311 |
|
|
312 |
/** Replace given field with new one. If the old one does not exist
|
|
313 |
* add the new_ field to the class anyway.
|
|
314 |
*/
|
|
315 |
public void replaceField(Field old, Field new_) {
|
|
316 |
if(new_ == null)
|
|
317 |
throw new ClassGenException("Replacement method must not be null");
|
|
318 |
|
|
319 |
int i = field_vec.indexOf(old);
|
|
320 |
|
|
321 |
if(i < 0)
|
|
322 |
field_vec.add(new_);
|
|
323 |
else
|
|
324 |
field_vec.set(i, new_);
|
|
325 |
}
|
|
326 |
|
|
327 |
/**
|
|
328 |
* Remove a field to this class.
|
|
329 |
* @param f field to remove
|
|
330 |
*/
|
|
331 |
public void removeField(Field f) { field_vec.remove(f); }
|
|
332 |
|
|
333 |
public String getClassName() { return class_name; }
|
|
334 |
public String getSuperclassName() { return super_class_name; }
|
|
335 |
public String getFileName() { return file_name; }
|
|
336 |
|
|
337 |
public void setClassName(String name) {
|
|
338 |
class_name = name.replace('/', '.');
|
|
339 |
class_name_index = cp.addClass(name);
|
|
340 |
}
|
|
341 |
|
|
342 |
public void setSuperclassName(String name) {
|
|
343 |
super_class_name = name.replace('/', '.');
|
|
344 |
superclass_name_index = cp.addClass(name);
|
|
345 |
}
|
|
346 |
|
|
347 |
public Method[] getMethods() {
|
|
348 |
Method[] methods = new Method[method_vec.size()];
|
|
349 |
method_vec.toArray(methods);
|
|
350 |
return methods;
|
|
351 |
}
|
|
352 |
|
|
353 |
public void setMethods(Method[] methods) {
|
|
354 |
method_vec.clear();
|
|
355 |
for(int m=0; m<methods.length; m++)
|
|
356 |
addMethod(methods[m]);
|
|
357 |
}
|
|
358 |
|
|
359 |
public void setMethodAt(Method method, int pos) {
|
|
360 |
method_vec.set(pos, method);
|
|
361 |
}
|
|
362 |
|
|
363 |
public Method getMethodAt(int pos) {
|
|
364 |
return (Method)method_vec.get(pos);
|
|
365 |
}
|
|
366 |
|
|
367 |
public String[] getInterfaceNames() {
|
|
368 |
int size = interface_vec.size();
|
|
369 |
String[] interfaces = new String[size];
|
|
370 |
|
|
371 |
interface_vec.toArray(interfaces);
|
|
372 |
return interfaces;
|
|
373 |
}
|
|
374 |
|
|
375 |
public int[] getInterfaces() {
|
|
376 |
int size = interface_vec.size();
|
|
377 |
int[] interfaces = new int[size];
|
|
378 |
|
|
379 |
for(int i=0; i < size; i++)
|
|
380 |
interfaces[i] = cp.addClass((String)interface_vec.get(i));
|
|
381 |
|
|
382 |
return interfaces;
|
|
383 |
}
|
|
384 |
|
|
385 |
public Field[] getFields() {
|
|
386 |
Field[] fields = new Field[field_vec.size()];
|
|
387 |
field_vec.toArray(fields);
|
|
388 |
return fields;
|
|
389 |
}
|
|
390 |
|
|
391 |
public Attribute[] getAttributes() {
|
|
392 |
Attribute[] attributes = new Attribute[attribute_vec.size()];
|
|
393 |
attribute_vec.toArray(attributes);
|
|
394 |
return attributes;
|
|
395 |
}
|
|
396 |
|
|
397 |
public ConstantPoolGen getConstantPool() { return cp; }
|
|
398 |
public void setConstantPool(ConstantPoolGen constant_pool) {
|
|
399 |
cp = constant_pool;
|
|
400 |
}
|
|
401 |
|
|
402 |
public void setClassNameIndex(int class_name_index) {
|
|
403 |
this.class_name_index = class_name_index;
|
|
404 |
class_name = cp.getConstantPool().
|
|
405 |
getConstantString(class_name_index, Constants.CONSTANT_Class).replace('/', '.');
|
|
406 |
}
|
|
407 |
|
|
408 |
public void setSuperclassNameIndex(int superclass_name_index) {
|
|
409 |
this.superclass_name_index = superclass_name_index;
|
|
410 |
super_class_name = cp.getConstantPool().
|
|
411 |
getConstantString(superclass_name_index, Constants.CONSTANT_Class).replace('/', '.');
|
|
412 |
}
|
|
413 |
|
|
414 |
public int getSuperclassNameIndex() { return superclass_name_index; }
|
|
415 |
|
|
416 |
public int getClassNameIndex() { return class_name_index; }
|
|
417 |
|
|
418 |
private ArrayList observers;
|
|
419 |
|
|
420 |
/** Add observer for this object.
|
|
421 |
*/
|
|
422 |
public void addObserver(ClassObserver o) {
|
|
423 |
if(observers == null)
|
|
424 |
observers = new ArrayList();
|
|
425 |
|
|
426 |
observers.add(o);
|
|
427 |
}
|
|
428 |
|
|
429 |
/** Remove observer for this object.
|
|
430 |
*/
|
|
431 |
public void removeObserver(ClassObserver o) {
|
|
432 |
if(observers != null)
|
|
433 |
observers.remove(o);
|
|
434 |
}
|
|
435 |
|
|
436 |
/** Call notify() method on all observers. This method is not called
|
|
437 |
* automatically whenever the state has changed, but has to be
|
|
438 |
* called by the user after he has finished editing the object.
|
|
439 |
*/
|
|
440 |
public void update() {
|
|
441 |
if(observers != null)
|
|
442 |
for(Iterator e = observers.iterator(); e.hasNext(); )
|
|
443 |
((ClassObserver)e.next()).notify(this);
|
|
444 |
}
|
|
445 |
|
|
446 |
public Object clone() {
|
|
447 |
try {
|
|
448 |
return super.clone();
|
|
449 |
} catch(CloneNotSupportedException e) {
|
|
450 |
System.err.println(e);
|
|
451 |
return null;
|
|
452 |
}
|
|
453 |
}
|
|
454 |
}
|