| /* |
| * reserved comment block |
| * DO NOT REMOVE OR ALTER! |
| */ |
| package com.sun.org.apache.bcel.internal.generic; |
| |
| /* ==================================================================== |
| * The Apache Software License, Version 1.1 |
| * |
| * Copyright (c) 2001 The Apache Software Foundation. All rights |
| * reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions |
| * are met: |
| * |
| * 1. Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * |
| * 2. Redistributions in binary form must reproduce the above copyright |
| * notice, this list of conditions and the following disclaimer in |
| * the documentation and/or other materials provided with the |
| * distribution. |
| * |
| * 3. The end-user documentation included with the redistribution, |
| * if any, must include the following acknowledgment: |
| * "This product includes software developed by the |
| * Apache Software Foundation (http://www.apache.org/)." |
| * Alternately, this acknowledgment may appear in the software itself, |
| * if and wherever such third-party acknowledgments normally appear. |
| * |
| * 4. The names "Apache" and "Apache Software Foundation" and |
| * "Apache BCEL" must not be used to endorse or promote products |
| * derived from this software without prior written permission. For |
| * written permission, please contact apache@apache.org. |
| * |
| * 5. Products derived from this software may not be called "Apache", |
| * "Apache BCEL", nor may "Apache" appear in their name, without |
| * prior written permission of the Apache Software Foundation. |
| * |
| * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED |
| * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
| * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
| * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR |
| * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF |
| * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
| * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, |
| * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT |
| * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
| * SUCH DAMAGE. |
| * ==================================================================== |
| * |
| * This software consists of voluntary contributions made by many |
| * individuals on behalf of the Apache Software Foundation. For more |
| * information on the Apache Software Foundation, please see |
| * <http://www.apache.org/>. |
| */ |
| |
| import com.sun.org.apache.bcel.internal.Constants; |
| import com.sun.org.apache.bcel.internal.classfile.*; |
| import java.util.ArrayList; |
| import java.util.Iterator; |
| |
| /** |
| * Template class for building up a java class. May be initialized with an |
| * existing java class (file). |
| * |
| * @see JavaClass |
| * @author <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A> |
| */ |
| public class ClassGen extends AccessFlags implements Cloneable { |
| /* Corresponds to the fields found in a JavaClass object. |
| */ |
| private String class_name, super_class_name, file_name; |
| private int class_name_index = -1, superclass_name_index = -1; |
| private int major = Constants.MAJOR_1_1, minor = Constants.MINOR_1_1; |
| |
| private ConstantPoolGen cp; // Template for building up constant pool |
| |
| // ArrayLists instead of arrays to gather fields, methods, etc. |
| private ArrayList field_vec = new ArrayList(); |
| private ArrayList method_vec = new ArrayList(); |
| private ArrayList attribute_vec = new ArrayList(); |
| private ArrayList interface_vec = new ArrayList(); |
| |
| /** Convenience constructor to set up some important values initially. |
| * |
| * @param class_name fully qualified class name |
| * @param super_class_name fully qualified superclass name |
| * @param file_name source file name |
| * @param access_flags access qualifiers |
| * @param interfaces implemented interfaces |
| * @param cp constant pool to use |
| */ |
| public ClassGen(String class_name, String super_class_name, String file_name, |
| int access_flags, String[] interfaces, ConstantPoolGen cp) { |
| this.class_name = class_name; |
| this.super_class_name = super_class_name; |
| this.file_name = file_name; |
| this.access_flags = access_flags; |
| this.cp = cp; |
| |
| // Put everything needed by default into the constant pool and the vectors |
| if(file_name != null) |
| addAttribute(new SourceFile(cp.addUtf8("SourceFile"), 2, |
| cp.addUtf8(file_name), cp.getConstantPool())); |
| |
| class_name_index = cp.addClass(class_name); |
| superclass_name_index = cp.addClass(super_class_name); |
| |
| if(interfaces != null) |
| for(int i=0; i < interfaces.length; i++) |
| addInterface(interfaces[i]); |
| } |
| |
| /** Convenience constructor to set up some important values initially. |
| * |
| * @param class_name fully qualified class name |
| * @param super_class_name fully qualified superclass name |
| * @param file_name source file name |
| * @param access_flags access qualifiers |
| * @param interfaces implemented interfaces |
| */ |
| public ClassGen(String class_name, String super_class_name, String file_name, |
| int access_flags, String[] interfaces) { |
| this(class_name, super_class_name, file_name, access_flags, interfaces, |
| new ConstantPoolGen()); |
| } |
| |
| /** |
| * Initialize with existing class. |
| * @param clazz JavaClass object (e.g. read from file) |
| */ |
| public ClassGen(JavaClass clazz) { |
| class_name_index = clazz.getClassNameIndex(); |
| superclass_name_index = clazz.getSuperclassNameIndex(); |
| class_name = clazz.getClassName(); |
| super_class_name = clazz.getSuperclassName(); |
| file_name = clazz.getSourceFileName(); |
| access_flags = clazz.getAccessFlags(); |
| cp = new ConstantPoolGen(clazz.getConstantPool()); |
| major = clazz.getMajor(); |
| minor = clazz.getMinor(); |
| |
| Attribute[] attributes = clazz.getAttributes(); |
| Method[] methods = clazz.getMethods(); |
| Field[] fields = clazz.getFields(); |
| String[] interfaces = clazz.getInterfaceNames(); |
| |
| for(int i=0; i < interfaces.length; i++) |
| addInterface(interfaces[i]); |
| |
| for(int i=0; i < attributes.length; i++) |
| addAttribute(attributes[i]); |
| |
| for(int i=0; i < methods.length; i++) |
| addMethod(methods[i]); |
| |
| for(int i=0; i < fields.length; i++) |
| addField(fields[i]); |
| } |
| |
| /** |
| * @return the (finally) built up Java class object. |
| */ |
| public JavaClass getJavaClass() { |
| int[] interfaces = getInterfaces(); |
| Field[] fields = getFields(); |
| Method[] methods = getMethods(); |
| Attribute[] attributes = getAttributes(); |
| |
| // Must be last since the above calls may still add something to it |
| ConstantPool cp = this.cp.getFinalConstantPool(); |
| |
| return new JavaClass(class_name_index, superclass_name_index, |
| file_name, major, minor, access_flags, |
| cp, interfaces, fields, methods, attributes); |
| } |
| |
| /** |
| * Add an interface to this class, i.e., this class has to implement it. |
| * @param name interface to implement (fully qualified class name) |
| */ |
| public void addInterface(String name) { |
| interface_vec.add(name); |
| } |
| |
| /** |
| * Remove an interface from this class. |
| * @param name interface to remove (fully qualified name) |
| */ |
| public void removeInterface(String name) { |
| interface_vec.remove(name); |
| } |
| |
| /** |
| * @return major version number of class file |
| */ |
| public int getMajor() { return major; } |
| |
| /** Set major version number of class file, default value is 45 (JDK 1.1) |
| * @param major major version number |
| */ |
| public void setMajor(int major) { |
| this.major = major; |
| } |
| |
| /** Set minor version number of class file, default value is 3 (JDK 1.1) |
| * @param minor minor version number |
| */ |
| public void setMinor(int minor) { |
| this.minor = minor; |
| } |
| |
| /** |
| * @return minor version number of class file |
| */ |
| public int getMinor() { return minor; } |
| |
| /** |
| * Add an attribute to this class. |
| * @param a attribute to add |
| */ |
| public void addAttribute(Attribute a) { attribute_vec.add(a); } |
| |
| /** |
| * Add a method to this class. |
| * @param m method to add |
| */ |
| public void addMethod(Method m) { method_vec.add(m); } |
| |
| /** |
| * Convenience method. |
| * |
| * Add an empty constructor to this class that does nothing but calling super(). |
| * @param access rights for constructor |
| */ |
| public void addEmptyConstructor(int access_flags) { |
| InstructionList il = new InstructionList(); |
| il.append(InstructionConstants.THIS); // Push `this' |
| il.append(new INVOKESPECIAL(cp.addMethodref(super_class_name, |
| "<init>", "()V"))); |
| il.append(InstructionConstants.RETURN); |
| |
| MethodGen mg = new MethodGen(access_flags, Type.VOID, Type.NO_ARGS, null, |
| "<init>", class_name, il, cp); |
| mg.setMaxStack(1); |
| addMethod(mg.getMethod()); |
| } |
| |
| /** |
| * Add a field to this class. |
| * @param f field to add |
| */ |
| public void addField(Field f) { field_vec.add(f); } |
| |
| public boolean containsField(Field f) { return field_vec.contains(f); } |
| |
| /** @return field object with given name, or null |
| */ |
| public Field containsField(String name) { |
| for(Iterator e=field_vec.iterator(); e.hasNext(); ) { |
| Field f = (Field)e.next(); |
| if(f.getName().equals(name)) |
| return f; |
| } |
| |
| return null; |
| } |
| |
| /** @return method object with given name and signature, or null |
| */ |
| public Method containsMethod(String name, String signature) { |
| for(Iterator e=method_vec.iterator(); e.hasNext();) { |
| Method m = (Method)e.next(); |
| if(m.getName().equals(name) && m.getSignature().equals(signature)) |
| return m; |
| } |
| |
| return null; |
| } |
| |
| /** |
| * Remove an attribute from this class. |
| * @param a attribute to remove |
| */ |
| public void removeAttribute(Attribute a) { attribute_vec.remove(a); } |
| |
| /** |
| * Remove a method from this class. |
| * @param m method to remove |
| */ |
| public void removeMethod(Method m) { method_vec.remove(m); } |
| |
| /** Replace given method with new one. If the old one does not exist |
| * add the new_ method to the class anyway. |
| */ |
| public void replaceMethod(Method old, Method new_) { |
| if(new_ == null) |
| throw new ClassGenException("Replacement method must not be null"); |
| |
| int i = method_vec.indexOf(old); |
| |
| if(i < 0) |
| method_vec.add(new_); |
| else |
| method_vec.set(i, new_); |
| } |
| |
| /** Replace given field with new one. If the old one does not exist |
| * add the new_ field to the class anyway. |
| */ |
| public void replaceField(Field old, Field new_) { |
| if(new_ == null) |
| throw new ClassGenException("Replacement method must not be null"); |
| |
| int i = field_vec.indexOf(old); |
| |
| if(i < 0) |
| field_vec.add(new_); |
| else |
| field_vec.set(i, new_); |
| } |
| |
| /** |
| * Remove a field to this class. |
| * @param f field to remove |
| */ |
| public void removeField(Field f) { field_vec.remove(f); } |
| |
| public String getClassName() { return class_name; } |
| public String getSuperclassName() { return super_class_name; } |
| public String getFileName() { return file_name; } |
| |
| public void setClassName(String name) { |
| class_name = name.replace('/', '.'); |
| class_name_index = cp.addClass(name); |
| } |
| |
| public void setSuperclassName(String name) { |
| super_class_name = name.replace('/', '.'); |
| superclass_name_index = cp.addClass(name); |
| } |
| |
| public Method[] getMethods() { |
| Method[] methods = new Method[method_vec.size()]; |
| method_vec.toArray(methods); |
| return methods; |
| } |
| |
| public void setMethods(Method[] methods) { |
| method_vec.clear(); |
| for(int m=0; m<methods.length; m++) |
| addMethod(methods[m]); |
| } |
| |
| public void setMethodAt(Method method, int pos) { |
| method_vec.set(pos, method); |
| } |
| |
| public Method getMethodAt(int pos) { |
| return (Method)method_vec.get(pos); |
| } |
| |
| public String[] getInterfaceNames() { |
| int size = interface_vec.size(); |
| String[] interfaces = new String[size]; |
| |
| interface_vec.toArray(interfaces); |
| return interfaces; |
| } |
| |
| public int[] getInterfaces() { |
| int size = interface_vec.size(); |
| int[] interfaces = new int[size]; |
| |
| for(int i=0; i < size; i++) |
| interfaces[i] = cp.addClass((String)interface_vec.get(i)); |
| |
| return interfaces; |
| } |
| |
| public Field[] getFields() { |
| Field[] fields = new Field[field_vec.size()]; |
| field_vec.toArray(fields); |
| return fields; |
| } |
| |
| public Attribute[] getAttributes() { |
| Attribute[] attributes = new Attribute[attribute_vec.size()]; |
| attribute_vec.toArray(attributes); |
| return attributes; |
| } |
| |
| public ConstantPoolGen getConstantPool() { return cp; } |
| public void setConstantPool(ConstantPoolGen constant_pool) { |
| cp = constant_pool; |
| } |
| |
| public void setClassNameIndex(int class_name_index) { |
| this.class_name_index = class_name_index; |
| class_name = cp.getConstantPool(). |
| getConstantString(class_name_index, Constants.CONSTANT_Class).replace('/', '.'); |
| } |
| |
| public void setSuperclassNameIndex(int superclass_name_index) { |
| this.superclass_name_index = superclass_name_index; |
| super_class_name = cp.getConstantPool(). |
| getConstantString(superclass_name_index, Constants.CONSTANT_Class).replace('/', '.'); |
| } |
| |
| public int getSuperclassNameIndex() { return superclass_name_index; } |
| |
| public int getClassNameIndex() { return class_name_index; } |
| |
| private ArrayList observers; |
| |
| /** Add observer for this object. |
| */ |
| public void addObserver(ClassObserver o) { |
| if(observers == null) |
| observers = new ArrayList(); |
| |
| observers.add(o); |
| } |
| |
| /** Remove observer for this object. |
| */ |
| public void removeObserver(ClassObserver o) { |
| if(observers != null) |
| observers.remove(o); |
| } |
| |
| /** Call notify() method on all observers. This method is not called |
| * automatically whenever the state has changed, but has to be |
| * called by the user after he has finished editing the object. |
| */ |
| public void update() { |
| if(observers != null) |
| for(Iterator e = observers.iterator(); e.hasNext(); ) |
| ((ClassObserver)e.next()).notify(this); |
| } |
| |
| public Object clone() { |
| try { |
| return super.clone(); |
| } catch(CloneNotSupportedException e) { |
| System.err.println(e); |
| return null; |
| } |
| } |
| } |