1 /* 2 * reserved comment block 3 * DO NOT REMOVE OR ALTER! 4 */ 5 package com.sun.org.apache.bcel.internal.generic; 6 7 /* ==================================================================== 8 * The Apache Software License, Version 1.1 9 * 10 * Copyright (c) 2001 The Apache Software Foundation. All rights 11 * reserved. 12 * 13 * Redistribution and use in source and binary forms, with or without 14 * modification, are permitted provided that the following conditions 15 * are met: 16 * 17 * 1. Redistributions of source code must retain the above copyright 18 * notice, this list of conditions and the following disclaimer. 19 * 20 * 2. Redistributions in binary form must reproduce the above copyright 21 * notice, this list of conditions and the following disclaimer in 22 * the documentation and/or other materials provided with the 23 * distribution. 24 * 25 * 3. The end-user documentation included with the redistribution, 26 * if any, must include the following acknowledgment: 27 * "This product includes software developed by the 28 * Apache Software Foundation (http://www.apache.org/)." 29 * Alternately, this acknowledgment may appear in the software itself, 30 * if and wherever such third-party acknowledgments normally appear. 31 * 32 * 4. The names "Apache" and "Apache Software Foundation" and 33 * "Apache BCEL" must not be used to endorse or promote products 34 * derived from this software without prior written permission. For 35 * written permission, please contact apache@apache.org. 36 * 37 * 5. Products derived from this software may not be called "Apache", 38 * "Apache BCEL", nor may "Apache" appear in their name, without 39 * prior written permission of the Apache Software Foundation. 40 * 41 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED 42 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 43 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 44 * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR 45 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 46 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 47 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 48 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 49 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 50 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 51 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 52 * SUCH DAMAGE. 53 * ==================================================================== 54 * 55 * This software consists of voluntary contributions made by many 56 * individuals on behalf of the Apache Software Foundation. For more 57 * information on the Apache Software Foundation, please see 58 * <http://www.apache.org/>. 59 */ 60 61 import com.sun.org.apache.bcel.internal.Constants; 62 import com.sun.org.apache.bcel.internal.classfile.*; 63 import java.util.ArrayList; 64 import java.util.Iterator; 65 66 /** 67 * Template class for building up a field. The only extraordinary thing 68 * one can do is to add a constant value attribute to a field (which must of 69 * course be compatible with to the declared type). 70 * 71 * @author <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A> 72 * @see Field 73 */ 74 public class FieldGen extends FieldGenOrMethodGen { 75 private Object value = null; 76 77 /** 78 * Declare a field. If it is static (isStatic() == true) and has a 79 * basic type like int or String it may have an initial value 80 * associated with it as defined by setInitValue(). 81 * 82 * @param access_flags access qualifiers 83 * @param type field type 84 * @param name field name 85 * @param cp constant pool 86 */ 87 public FieldGen(int access_flags, Type type, String name, ConstantPoolGen cp) { 88 setAccessFlags(access_flags); 89 setType(type); 90 setName(name); 91 setConstantPool(cp); 92 } 93 94 /** 95 * Instantiate from existing field. 96 * 97 * @param field Field object 98 * @param cp constant pool (must contain the same entries as the field's constant pool) 99 */ 100 public FieldGen(Field field, ConstantPoolGen cp) { 101 this(field.getAccessFlags(), Type.getType(field.getSignature()), field.getName(), cp); 102 103 Attribute[] attrs = field.getAttributes(); 104 105 for(int i=0; i < attrs.length; i++) { 106 if(attrs[i] instanceof ConstantValue) 107 setValue(((ConstantValue)attrs[i]).getConstantValueIndex()); 108 else 109 addAttribute(attrs[i]); 110 } 111 } 112 113 private void setValue(int index) { 114 ConstantPool cp = this.cp.getConstantPool(); 115 Constant c = cp.getConstant(index); 116 value = ((ConstantObject)c).getConstantValue(cp); 117 } 118 119 /** 120 * Set (optional) initial value of field, otherwise it will be set to null/0/false 121 * by the JVM automatically. 122 */ 123 public void setInitValue(String str) { 124 checkType(new ObjectType("java.lang.String")); 125 126 if(str != null) 127 value = str; 128 } 129 130 public void setInitValue(long l) { 131 checkType(Type.LONG); 132 133 if(l != 0L) 134 value = new Long(l); 135 } 136 137 public void setInitValue(int i) { 138 checkType(Type.INT); 139 140 if(i != 0) 141 value = new Integer(i); 142 } 143 144 public void setInitValue(short s) { 145 checkType(Type.SHORT); 146 147 if(s != 0) 148 value = new Integer(s); 149 } 150 151 public void setInitValue(char c) { 152 checkType(Type.CHAR); 153 154 if(c != 0) 155 value = new Integer(c); 156 } 157 158 public void setInitValue(byte b) { 159 checkType(Type.BYTE); 160 161 if(b != 0) 162 value = new Integer(b); 163 } 164 165 public void setInitValue(boolean b) { 166 checkType(Type.BOOLEAN); 167 168 if(b) 169 value = new Integer(1); 170 } 171 172 public void setInitValue(float f) { 173 checkType(Type.FLOAT); 174 175 if(f != 0.0) 176 value = new Float(f); 177 } 178 179 public void setInitValue(double d) { 180 checkType(Type.DOUBLE); 181 182 if(d != 0.0) 183 value = new Double(d); 184 } 185 186 /** Remove any initial value. 187 */ 188 public void cancelInitValue() { 189 value = null; 190 } 191 192 private void checkType(Type atype) { 193 if(type == null) 194 throw new ClassGenException("You haven't defined the type of the field yet"); 195 196 if(!isFinal()) 197 throw new ClassGenException("Only final fields may have an initial value!"); 198 199 if(!type.equals(atype)) 200 throw new ClassGenException("Types are not compatible: " + type + " vs. " + atype); 201 } 202 203 /** 204 * Get field object after having set up all necessary values. 205 */ 206 public Field getField() { 207 String signature = getSignature(); 208 int name_index = cp.addUtf8(name); 209 int signature_index = cp.addUtf8(signature); 210 211 if(value != null) { 212 checkType(type); 213 int index = addConstant(); 214 addAttribute(new ConstantValue(cp.addUtf8("ConstantValue"), 215 2, index, cp.getConstantPool())); 216 } 217 218 return new Field(access_flags, name_index, signature_index, getAttributes(), 219 cp.getConstantPool()); 220 } 221 222 private int addConstant() { 223 switch(type.getType()) { 224 case Constants.T_INT: case Constants.T_CHAR: case Constants.T_BYTE: 225 case Constants.T_BOOLEAN: case Constants.T_SHORT: 226 return cp.addInteger(((Integer)value).intValue()); 227 228 case Constants.T_FLOAT: 229 return cp.addFloat(((Float)value).floatValue()); 230 231 case Constants.T_DOUBLE: 232 return cp.addDouble(((Double)value).doubleValue()); 233 234 case Constants.T_LONG: 235 return cp.addLong(((Long)value).longValue()); 236 237 case Constants.T_REFERENCE: 238 return cp.addString(((String)value)); 239 240 default: 241 throw new RuntimeException("Oops: Unhandled : " + type.getType()); 242 } 243 } 244 245 public String getSignature() { return type.getSignature(); } 246 247 private ArrayList observers; 248 249 /** Add observer for this object. 250 */ 251 public void addObserver(FieldObserver o) { 252 if(observers == null) 253 observers = new ArrayList(); 254 255 observers.add(o); 256 } 257 258 /** Remove observer for this object. 259 */ 260 public void removeObserver(FieldObserver o) { 261 if(observers != null) 262 observers.remove(o); 263 } 264 265 /** Call notify() method on all observers. This method is not called 266 * automatically whenever the state has changed, but has to be 267 * called by the user after he has finished editing the object. 268 */ 269 public void update() { 270 if(observers != null) 271 for(Iterator e = observers.iterator(); e.hasNext(); ) 272 ((FieldObserver)e.next()).notify(this); 273 } 274 275 public String getInitValue() { 276 if(value != null) { 277 return value.toString(); 278 } else 279 return null; 280 } 281 282 /** 283 * Return string representation close to declaration format, 284 * `public static final short MAX = 100', e.g.. 285 * 286 * @return String representation of field 287 */ 288 public final String toString() { 289 String name, signature, access; // Short cuts to constant pool 290 291 access = Utility.accessToString(access_flags); 292 access = access.equals("")? "" : (access + " "); 293 signature = type.toString(); 294 name = getName(); 295 296 StringBuffer buf = new StringBuffer(access + signature + " " + name); 297 String value = getInitValue(); 298 299 if(value != null) 300 buf.append(" = " + value); 301 302 return buf.toString(); 303 } 304 305 /** @return deep copy of this field 306 */ 307 public FieldGen copy(ConstantPoolGen cp) { 308 FieldGen fg = (FieldGen)clone(); 309 310 fg.setConstantPool(cp); 311 return fg; 312 } 313 }