< prev index next >

src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/FieldGen.java

Print this page


   1 /*
   2  * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
   3  */
   4 /*
   5  * Licensed to the Apache Software Foundation (ASF) under one or more
   6  * contributor license agreements.  See the NOTICE file distributed with
   7  * this work for additional information regarding copyright ownership.
   8  * The ASF licenses this file to You under the Apache License, Version 2.0
   9  * (the "License"); you may not use this file except in compliance with
  10  * the License.  You may obtain a copy of the License at
  11  *
  12  *      http://www.apache.org/licenses/LICENSE-2.0
  13  *
  14  * Unless required by applicable law or agreed to in writing, software
  15  * distributed under the License is distributed on an "AS IS" BASIS,
  16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  17  * See the License for the specific language governing permissions and
  18  * limitations under the License.
  19  */
  20 
  21 package com.sun.org.apache.bcel.internal.generic;
  22 
  23 
  24 import com.sun.org.apache.bcel.internal.Constants;
  25 import com.sun.org.apache.bcel.internal.classfile.*;
  26 import java.util.ArrayList;
  27 import java.util.Iterator;












  28 
  29 /**
  30  * Template class for building up a field.  The only extraordinary thing
  31  * one can do is to add a constant value attribute to a field (which must of
  32  * course be compatible with to the declared type).
  33  *
  34  * @author  <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A>
  35  * @see Field
  36  */
  37 public class FieldGen extends FieldGenOrMethodGen {

  38   private Object value = null;
















  39 
  40   /**
  41    * Declare a field. If it is static (isStatic() == true) and has a
  42    * basic type like int or String it may have an initial value
  43    * associated with it as defined by setInitValue().
  44    *
  45    * @param access_flags access qualifiers
  46    * @param type  field type
  47    * @param name field name
  48    * @param cp constant pool
  49    */
  50   public FieldGen(int access_flags, Type type, String name, ConstantPoolGen cp) {
  51     setAccessFlags(access_flags);
  52     setType(type);
  53     setName(name);
  54     setConstantPool(cp);
  55   }
  56 
  57   /**
  58    * Instantiate from existing field.
  59    *
  60    * @param field Field object
  61    * @param cp constant pool (must contain the same entries as the field's constant pool)

  62    */
  63   public FieldGen(Field field, ConstantPoolGen cp) {
  64     this(field.getAccessFlags(), Type.getType(field.getSignature()), field.getName(), cp);
  65 
  66     Attribute[] attrs = field.getAttributes();
  67 
  68     for(int i=0; i < attrs.length; i++) {
  69       if(attrs[i] instanceof ConstantValue)
  70         setValue(((ConstantValue)attrs[i]).getConstantValueIndex());
  71       else
  72         addAttribute(attrs[i]);





  73     }
  74   }
  75 
  76   private void setValue(int index) {
  77     ConstantPool cp  = this.cp.getConstantPool();
  78     Constant     c   = cp.getConstant(index);
  79     value = ((ConstantObject)c).getConstantValue(cp);
  80   }
  81 
  82   /**
  83    * Set (optional) initial value of field, otherwise it will be set to null/0/false
  84    * by the JVM automatically.
  85    */
  86   public void setInitValue(String str) {
  87     checkType(new ObjectType("java.lang.String"));
  88 
  89     if(str != null)
  90       value = str;
  91   }

  92 
  93   public void setInitValue(long l) {
  94     checkType(Type.LONG);
  95 
  96     if(l != 0L)
  97       value = Long.valueOf(l);
  98   }
  99 
 100   public void setInitValue(int i) {
 101     checkType(Type.INT);
 102 
 103     if(i != 0)
 104       value = Integer.valueOf(i);
 105   }
 106 
 107   public void setInitValue(short s) {
 108     checkType(Type.SHORT);
 109 
 110     if(s != 0)
 111       value = Integer.valueOf(s);
 112   }
 113 
 114   public void setInitValue(char c) {
 115     checkType(Type.CHAR);
 116 
 117     if(c != 0)
 118       value = Integer.valueOf(c);
 119   }
 120 
 121   public void setInitValue(byte b) {
 122     checkType(Type.BYTE);
 123 
 124     if(b != 0)
 125       value = Integer.valueOf(b);
 126   }
 127 
 128   public void setInitValue(boolean b) {
 129     checkType(Type.BOOLEAN);
 130 
 131     if(b)
 132       value = Integer.valueOf(1);
 133   }
 134 
 135   public void setInitValue(float f) {
 136     checkType(Type.FLOAT);
 137 
 138     if(f != 0.0)
 139       value = Float.valueOf(f);
 140   }
 141 
 142   public void setInitValue(double d) {
 143     checkType(Type.DOUBLE);
 144 
 145     if(d != 0.0)
 146       value = Double.valueOf(d);
 147   }
 148 
 149   /** Remove any initial value.

 150    */
 151   public void cancelInitValue() {
 152     value = null;
 153   }
 154 
 155   private void checkType(Type atype) {
 156     if(type == null)

 157       throw new ClassGenException("You haven't defined the type of the field yet");
 158 
 159     if(!isFinal())
 160       throw new ClassGenException("Only final fields may have an initial value!");
 161 
 162     if(!type.equals(atype))
 163       throw new ClassGenException("Types are not compatible: " + type + " vs. " + atype);

 164   }
 165 
 166   /**
 167    * Get field object after having set up all necessary values.
 168    */
 169   public Field getField() {
 170     String      signature       = getSignature();
 171     int         name_index      = cp.addUtf8(name);
 172     int         signature_index = cp.addUtf8(signature);
 173 
 174     if(value != null) {
 175       checkType(type);
 176       int index = addConstant();
 177       addAttribute(new ConstantValue(cp.addUtf8("ConstantValue"),
 178                                      2, index, cp.getConstantPool()));









 179     }
 180 
 181     return new Field(access_flags, name_index, signature_index, getAttributes(),
 182                      cp.getConstantPool());
 183   }
 184 
 185   private int addConstant() {
 186     switch(type.getType()) {
 187     case Constants.T_INT: case Constants.T_CHAR: case Constants.T_BYTE:
 188     case Constants.T_BOOLEAN: case Constants.T_SHORT:
 189       return cp.addInteger(((Integer)value).intValue());
 190 
 191     case Constants.T_FLOAT:
 192       return cp.addFloat(((Float)value).floatValue());
 193 
 194     case Constants.T_DOUBLE:
 195       return cp.addDouble(((Double)value).doubleValue());
 196 
 197     case Constants.T_LONG:
 198       return cp.addLong(((Long)value).longValue());
 199 
 200     case Constants.T_REFERENCE:
 201       return cp.addString(((String)value));
 202 
 203     default:
 204       throw new RuntimeException("Oops: Unhandled : " + type.getType());
 205     }
 206   }
 207 
 208   public String  getSignature()  { return type.getSignature(); }



 209 
 210   private ArrayList observers;
 211 
 212   /** Add observer for this object.

 213    */
 214   public void addObserver(FieldObserver o) {
 215     if(observers == null)
 216       observers = new ArrayList();
 217 
 218     observers.add(o);
 219   }
 220 
 221   /** Remove observer for this object.

 222    */
 223   public void removeObserver(FieldObserver o) {
 224     if(observers != null)
 225       observers.remove(o);
 226   }

 227 
 228   /** Call notify() method on all observers. This method is not called
 229    * automatically whenever the state has changed, but has to be
 230    * called by the user after he has finished editing the object.

 231    */
 232   public void update() {
 233     if(observers != null)
 234       for(Iterator e = observers.iterator(); e.hasNext(); )
 235         ((FieldObserver)e.next()).notify(this);


 236   }
 237 
 238   public String getInitValue() {
 239     if(value != null) {
 240       return value.toString();
 241     } else
 242       return null;
 243   }
 244 
 245   /**
 246    * Return string representation close to declaration format,
 247    * `public static final short MAX = 100', e.g..
 248    *
 249    * @return String representation of field
 250    */

 251   public final String toString() {
 252     String name, signature, access; // Short cuts to constant pool
 253 
 254     access    = Utility.accessToString(access_flags);
 255     access    = access.equals("")? "" : (access + " ");
 256     signature = type.toString();

 257     name      = getName();








 258 
 259     StringBuffer buf = new StringBuffer(access + signature + " " + name);
 260     String value = getInitValue();






 261 
 262     if(value != null)
 263       buf.append(" = " + value);




 264 
 265     return buf.toString();




 266   }
 267 
 268   /** @return deep copy of this field





 269    */
 270   public FieldGen copy(ConstantPoolGen cp) {
 271     FieldGen fg = (FieldGen)clone();


 272 
 273     fg.setConstantPool(cp);
 274     return fg;







 275   }
 276 }
   1 /*
   2  * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
   3  */
   4 /*
   5  * Licensed to the Apache Software Foundation (ASF) under one or more
   6  * contributor license agreements.  See the NOTICE file distributed with
   7  * this work for additional information regarding copyright ownership.
   8  * The ASF licenses this file to You under the Apache License, Version 2.0
   9  * (the "License"); you may not use this file except in compliance with
  10  * the License.  You may obtain a copy of the License at
  11  *
  12  *      http://www.apache.org/licenses/LICENSE-2.0
  13  *
  14  * Unless required by applicable law or agreed to in writing, software
  15  * distributed under the License is distributed on an "AS IS" BASIS,
  16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  17  * See the License for the specific language governing permissions and
  18  * limitations under the License.
  19  */

  20 package com.sun.org.apache.bcel.internal.generic;
  21 



  22 import java.util.ArrayList;
  23 import java.util.List;
  24 
  25 import com.sun.org.apache.bcel.internal.Const;
  26 import com.sun.org.apache.bcel.internal.classfile.AnnotationEntry;
  27 import com.sun.org.apache.bcel.internal.classfile.Annotations;
  28 import com.sun.org.apache.bcel.internal.classfile.Attribute;
  29 import com.sun.org.apache.bcel.internal.classfile.Constant;
  30 import com.sun.org.apache.bcel.internal.classfile.ConstantObject;
  31 import com.sun.org.apache.bcel.internal.classfile.ConstantPool;
  32 import com.sun.org.apache.bcel.internal.classfile.ConstantValue;
  33 import com.sun.org.apache.bcel.internal.classfile.Field;
  34 import com.sun.org.apache.bcel.internal.classfile.Utility;
  35 import com.sun.org.apache.bcel.internal.util.BCELComparator;
  36 
  37 /**
  38  * Template class for building up a field. The only extraordinary thing one can
  39  * do is to add a constant value attribute to a field (which must of course be
  40  * compatible with to the declared type).
  41  *
  42  * @version $Id: FieldGen.java 1749603 2016-06-21 20:50:19Z ggregory $
  43  * @see Field
  44  */
  45 public class FieldGen extends FieldGenOrMethodGen {
  46 
  47     private Object value = null;
  48     private static BCELComparator bcelComparator = new BCELComparator() {
  49 
  50         @Override
  51         public boolean equals(final Object o1, final Object o2) {
  52             final FieldGen THIS = (FieldGen) o1;
  53             final FieldGen THAT = (FieldGen) o2;
  54             return THIS.getName().equals(THAT.getName())
  55                     && THIS.getSignature().equals(THAT.getSignature());
  56         }
  57 
  58         @Override
  59         public int hashCode(final Object o) {
  60             final FieldGen THIS = (FieldGen) o;
  61             return THIS.getSignature().hashCode() ^ THIS.getName().hashCode();
  62         }
  63     };
  64 
  65     /**
  66      * Declare a field. If it is static (isStatic() == true) and has a basic
  67      * type like int or String it may have an initial value associated with it
  68      * as defined by setInitValue().
  69      *
  70      * @param access_flags access qualifiers
  71      * @param type field type
  72      * @param name field name
  73      * @param cp constant pool
  74      */
  75     public FieldGen(final int access_flags, final Type type, final String name, final ConstantPoolGen cp) {
  76         super(access_flags);
  77         setType(type);
  78         setName(name);
  79         setConstantPool(cp);
  80     }
  81 
  82     /**
  83      * Instantiate from existing field.
  84      *
  85      * @param field Field object
  86      * @param cp constant pool (must contain the same entries as the field's
  87      * constant pool)
  88      */
  89     public FieldGen(final Field field, final ConstantPoolGen cp) {
  90         this(field.getAccessFlags(), Type.getType(field.getSignature()), field.getName(), cp);
  91         final Attribute[] attrs = field.getAttributes();
  92         for (final Attribute attr : attrs) {
  93             if (attr instanceof ConstantValue) {
  94                 setValue(((ConstantValue) attr).getConstantValueIndex());
  95             } else if (attr instanceof Annotations) {
  96                 final Annotations runtimeAnnotations = (Annotations) attr;
  97                 final AnnotationEntry[] annotationEntries = runtimeAnnotations.getAnnotationEntries();
  98                 for (final AnnotationEntry element : annotationEntries) {
  99                     addAnnotationEntry(new AnnotationEntryGen(element, cp, false));
 100                 }
 101             } else {
 102                 addAttribute(attr);
 103             }
 104         }
 105     }
 106 
 107     private void setValue(final int index) {
 108         final ConstantPool cp = super.getConstantPool().getConstantPool();
 109         final Constant c = cp.getConstant(index);
 110         value = ((ConstantObject) c).getConstantValue(cp);
 111     }
 112 
 113     /**
 114      * Set (optional) initial value of field, otherwise it will be set to
 115      * null/0/false by the JVM automatically.
 116      */
 117     public void setInitValue(final String str) {
 118         checkType(ObjectType.getInstance("java.lang.String"));
 119         if (str != null) {

 120             value = str;
 121         }
 122     }
 123 
 124     public void setInitValue(final long l) {
 125         checkType(Type.LONG);
 126         if (l != 0L) {
 127             value = l;
 128         }
 129     }
 130 
 131     public void setInitValue(final int i) {
 132         checkType(Type.INT);
 133         if (i != 0) {
 134             value = i;
 135         }
 136     }
 137 
 138     public void setInitValue(final short s) {
 139         checkType(Type.SHORT);
 140         if (s != 0) {
 141             value = (int) s;
 142         }
 143     }
 144 
 145     public void setInitValue(final char c) {
 146         checkType(Type.CHAR);
 147         if (c != 0) {
 148             value = (int) c;
 149         }
 150     }
 151 
 152     public void setInitValue(final byte b) {
 153         checkType(Type.BYTE);
 154         if (b != 0) {
 155             value = (int) b;
 156         }
 157     }
 158 
 159     public void setInitValue(final boolean b) {
 160         checkType(Type.BOOLEAN);
 161         if (b) {
 162             value = 1;
 163         }
 164     }
 165 
 166     public void setInitValue(final float f) {
 167         checkType(Type.FLOAT);
 168         if (f != 0.0) {
 169             value = f;
 170         }
 171     }
 172 
 173     public void setInitValue(final double d) {
 174         checkType(Type.DOUBLE);
 175         if (d != 0.0) {
 176             value = d;
 177         }
 178     }
 179 
 180     /**
 181      * Remove any initial value.
 182      */
 183     public void cancelInitValue() {
 184         value = null;
 185     }
 186 
 187     private void checkType(final Type atype) {
 188         final Type superType = super.getType();
 189         if (superType == null) {
 190             throw new ClassGenException("You haven't defined the type of the field yet");
 191         }
 192         if (!isFinal()) {
 193             throw new ClassGenException("Only final fields may have an initial value!");
 194         }
 195         if (!superType.equals(atype)) {
 196             throw new ClassGenException("Types are not compatible: " + superType + " vs. " + atype);
 197         }
 198     }
 199 
 200     /**
 201      * Get field object after having set up all necessary values.
 202      */
 203     public Field getField() {
 204         final String signature = getSignature();
 205         final int name_index = super.getConstantPool().addUtf8(super.getName());
 206         final int signature_index = super.getConstantPool().addUtf8(signature);
 207         if (value != null) {
 208             checkType(super.getType());
 209             final int index = addConstant();
 210             addAttribute(new ConstantValue(super.getConstantPool().addUtf8("ConstantValue"), 2, index,
 211                     super.getConstantPool().getConstantPool())); // sic
 212         }
 213         addAnnotationsAsAttribute(super.getConstantPool());
 214         return new Field(super.getAccessFlags(), name_index, signature_index, getAttributes(),
 215                 super.getConstantPool().getConstantPool()); // sic
 216     }
 217 
 218     private void addAnnotationsAsAttribute(final ConstantPoolGen cp) {
 219         final Attribute[] attrs = AnnotationEntryGen.getAnnotationAttributes(cp, super.getAnnotationEntries());
 220         for (final Attribute attr : attrs) {
 221             addAttribute(attr);
 222         }



 223     }
 224 
 225     private int addConstant() {
 226         switch (super.getType().getType()) { // sic
 227             case Const.T_INT:
 228             case Const.T_CHAR:
 229             case Const.T_BYTE:
 230             case Const.T_BOOLEAN:
 231             case Const.T_SHORT:
 232                 return super.getConstantPool().addInteger(((Integer) value));
 233             case Const.T_FLOAT:
 234                 return super.getConstantPool().addFloat(((Float) value));
 235             case Const.T_DOUBLE:
 236                 return super.getConstantPool().addDouble(((Double) value));
 237             case Const.T_LONG:
 238                 return super.getConstantPool().addLong(((Long) value));
 239             case Const.T_REFERENCE:
 240                 return super.getConstantPool().addString((String) value);


 241             default:
 242                 throw new RuntimeException("Oops: Unhandled : " + super.getType().getType()); // sic
 243         }
 244     }
 245 
 246     @Override
 247     public String getSignature() {
 248         return super.getType().getSignature();
 249     }
 250 
 251     private List<FieldObserver> observers;
 252 
 253     /**
 254      * Add observer for this object.
 255      */
 256     public void addObserver(final FieldObserver o) {
 257         if (observers == null) {
 258             observers = new ArrayList<>();
 259         }
 260         observers.add(o);
 261     }
 262 
 263     /**
 264      * Remove observer for this object.
 265      */
 266     public void removeObserver(final FieldObserver o) {
 267         if (observers != null) {
 268             observers.remove(o);
 269         }
 270     }
 271 
 272     /**
 273      * Call notify() method on all observers. This method is not called
 274      * automatically whenever the state has changed, but has to be called by the
 275      * user after he has finished editing the object.
 276      */
 277     public void update() {
 278         if (observers != null) {
 279             for (final FieldObserver observer : observers) {
 280                 observer.notify(this);
 281             }
 282         }
 283     }
 284 
 285     public String getInitValue() {
 286         if (value != null) {
 287             return value.toString();
 288         }
 289         return null;
 290     }
 291 
 292     /**
 293      * Return string representation close to declaration format, `public static
 294      * final short MAX = 100', e.g..
 295      *
 296      * @return String representation of field
 297      */
 298     @Override
 299     public final String toString() {
 300         String name;
 301         String signature;
 302         String access; // Short cuts to constant pool
 303         access = Utility.accessToString(super.getAccessFlags());
 304         access = access.isEmpty() ? "" : (access + " ");
 305         signature = super.getType().toString();
 306         name = getName();
 307         final StringBuilder buf = new StringBuilder(32); // CHECKSTYLE IGNORE MagicNumber
 308         buf.append(access).append(signature).append(" ").append(name);
 309         final String value = getInitValue();
 310         if (value != null) {
 311             buf.append(" = ").append(value);
 312         }
 313         return buf.toString();
 314     }
 315 
 316     /**
 317      * @return deep copy of this field
 318      */
 319     public FieldGen copy(final ConstantPoolGen cp) {
 320         final FieldGen fg = (FieldGen) clone();
 321         fg.setConstantPool(cp);
 322         return fg;
 323     }
 324 
 325     /**
 326      * @return Comparison strategy object
 327      */
 328     public static BCELComparator getComparator() {
 329         return bcelComparator;
 330     }
 331 
 332     /**
 333      * @param comparator Comparison strategy object
 334      */
 335     public static void setComparator(final BCELComparator comparator) {
 336         bcelComparator = comparator;
 337     }
 338 
 339     /**
 340      * Return value as defined by given BCELComparator strategy. By default two
 341      * FieldGen objects are said to be equal when their names and signatures are
 342      * equal.
 343      *
 344      * @see java.lang.Object#equals(java.lang.Object)
 345      */
 346     @Override
 347     public boolean equals(final Object obj) {
 348         return bcelComparator.equals(this, obj);
 349     }
 350 
 351     /**
 352      * Return value as defined by given BCELComparator strategy. By default
 353      * return the hashcode of the field's name XOR signature.
 354      *
 355      * @see java.lang.Object#hashCode()
 356      */
 357     @Override
 358     public int hashCode() {
 359         return bcelComparator.hashCode(this);
 360     }
 361 }
< prev index next >