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