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