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