    View Javadoc
    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