src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ClassGen.java
changeset 55496 8e0ae3830fca
parent 47216 71c04702a3d5
equal deleted inserted replaced
55495:badfa812b82a 55496:8e0ae3830fca
     1 /*
     1 /*
     2  * reserved comment block
     2  * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT REMOVE OR ALTER!
       
     4  */
     3  */
     5 /*
     4 /*
     6  * Licensed to the Apache Software Foundation (ASF) under one or more
     5  * Licensed to the Apache Software Foundation (ASF) under one or more
     7  * contributor license agreements.  See the NOTICE file distributed with
     6  * contributor license agreements.  See the NOTICE file distributed with
     8  * this work for additional information regarding copyright ownership.
     7  * this work for additional information regarding copyright ownership.
    20  */
    19  */
    21 package com.sun.org.apache.bcel.internal.generic;
    20 package com.sun.org.apache.bcel.internal.generic;
    22 
    21 
    23 import java.util.ArrayList;
    22 import java.util.ArrayList;
    24 import java.util.List;
    23 import java.util.List;
       
    24 import java.util.Objects;
    25 
    25 
    26 import com.sun.org.apache.bcel.internal.Const;
    26 import com.sun.org.apache.bcel.internal.Const;
    27 import com.sun.org.apache.bcel.internal.classfile.AccessFlags;
    27 import com.sun.org.apache.bcel.internal.classfile.AccessFlags;
    28 import com.sun.org.apache.bcel.internal.classfile.AnnotationEntry;
    28 import com.sun.org.apache.bcel.internal.classfile.AnnotationEntry;
    29 import com.sun.org.apache.bcel.internal.classfile.Annotations;
    29 import com.sun.org.apache.bcel.internal.classfile.Annotations;
    40 /**
    40 /**
    41  * Template class for building up a java class. May be initialized with an
    41  * Template class for building up a java class. May be initialized with an
    42  * existing java class (file).
    42  * existing java class (file).
    43  *
    43  *
    44  * @see JavaClass
    44  * @see JavaClass
    45  * @version $Id: ClassGen.java 1749603 2016-06-21 20:50:19Z ggregory $
    45  * @version $Id$
       
    46  * @LastModified: Jun 2019
    46  */
    47  */
    47 public class ClassGen extends AccessFlags implements Cloneable {
    48 public class ClassGen extends AccessFlags implements Cloneable {
    48 
    49 
    49     /* Corresponds to the fields found in a JavaClass object.
    50     /* Corresponds to the fields found in a JavaClass object.
    50      */
    51      */
    64     private final List<AnnotationEntryGen> annotation_vec = new ArrayList<>();
    65     private final List<AnnotationEntryGen> annotation_vec = new ArrayList<>();
    65 
    66 
    66     private static BCELComparator _cmp = new BCELComparator() {
    67     private static BCELComparator _cmp = new BCELComparator() {
    67 
    68 
    68         @Override
    69         @Override
    69         public boolean equals(final Object o1, final Object o2) {
    70         public boolean equals( final Object o1, final Object o2 ) {
    70             final ClassGen THIS = (ClassGen) o1;
    71             final ClassGen THIS = (ClassGen) o1;
    71             final ClassGen THAT = (ClassGen) o2;
    72             final ClassGen THAT = (ClassGen) o2;
    72             return THIS.getClassName().equals(THAT.getClassName());
    73             return Objects.equals(THIS.getClassName(), THAT.getClassName());
    73         }
    74         }
       
    75 
    74 
    76 
    75         @Override
    77         @Override
    76         public int hashCode(final Object o) {
    78         public int hashCode( final Object o ) {
    77             final ClassGen THIS = (ClassGen) o;
    79             final ClassGen THIS = (ClassGen) o;
    78             return THIS.getClassName().hashCode();
    80             return THIS.getClassName().hashCode();
    79         }
    81         }
    80     };
    82     };
    81 
    83 
    82     /**
    84 
    83      * Convenience constructor to set up some important values initially.
    85     /** Convenience constructor to set up some important values initially.
    84      *
    86      *
    85      * @param class_name fully qualified class name
    87      * @param class_name fully qualified class name
    86      * @param super_class_name fully qualified superclass name
    88      * @param super_class_name fully qualified superclass name
    87      * @param file_name source file name
    89      * @param file_name source file name
    88      * @param access_flags access qualifiers
    90      * @param access_flags access qualifiers
   108                 addInterface(interface1);
   110                 addInterface(interface1);
   109             }
   111             }
   110         }
   112         }
   111     }
   113     }
   112 
   114 
   113     /**
   115 
   114      * Convenience constructor to set up some important values initially.
   116     /** Convenience constructor to set up some important values initially.
   115      *
   117      *
   116      * @param class_name fully qualified class name
   118      * @param class_name fully qualified class name
   117      * @param super_class_name fully qualified superclass name
   119      * @param super_class_name fully qualified superclass name
   118      * @param file_name source file name
   120      * @param file_name source file name
   119      * @param access_flags access qualifiers
   121      * @param access_flags access qualifiers
   123             final String[] interfaces) {
   125             final String[] interfaces) {
   124         this(class_name, super_class_name, file_name, access_flags, interfaces,
   126         this(class_name, super_class_name, file_name, access_flags, interfaces,
   125                 new ConstantPoolGen());
   127                 new ConstantPoolGen());
   126     }
   128     }
   127 
   129 
       
   130 
   128     /**
   131     /**
   129      * Initialize with existing class.
   132      * Initialize with existing class.
   130      *
       
   131      * @param clazz JavaClass object (e.g. read from file)
   133      * @param clazz JavaClass object (e.g. read from file)
   132      */
   134      */
   133     public ClassGen(final JavaClass clazz) {
   135     public ClassGen(final JavaClass clazz) {
   134         super(clazz.getAccessFlags());
   136         super(clazz.getAccessFlags());
   135         class_name_index = clazz.getClassNameIndex();
   137         class_name_index = clazz.getClassNameIndex();
   166     }
   168     }
   167 
   169 
   168     /**
   170     /**
   169      * Look for attributes representing annotations and unpack them.
   171      * Look for attributes representing annotations and unpack them.
   170      */
   172      */
   171     private AnnotationEntryGen[] unpackAnnotations(final Attribute[] attrs) {
   173     private AnnotationEntryGen[] unpackAnnotations(final Attribute[] attrs)
       
   174     {
   172         final List<AnnotationEntryGen> annotationGenObjs = new ArrayList<>();
   175         final List<AnnotationEntryGen> annotationGenObjs = new ArrayList<>();
   173         for (final Attribute attr : attrs) {
   176         for (final Attribute attr : attrs) {
   174             if (attr instanceof RuntimeVisibleAnnotations) {
   177             if (attr instanceof RuntimeVisibleAnnotations)
       
   178             {
   175                 final RuntimeVisibleAnnotations rva = (RuntimeVisibleAnnotations) attr;
   179                 final RuntimeVisibleAnnotations rva = (RuntimeVisibleAnnotations) attr;
   176                 final AnnotationEntry[] annos = rva.getAnnotationEntries();
   180                 final AnnotationEntry[] annos = rva.getAnnotationEntries();
   177                 for (final AnnotationEntry a : annos) {
   181                 for (final AnnotationEntry a : annos) {
   178                     annotationGenObjs.add(new AnnotationEntryGen(a,
   182                     annotationGenObjs.add(new AnnotationEntryGen(a,
   179                             getConstantPool(), false));
   183                             getConstantPool(), false));
   180                 }
   184                 }
   181             } else if (attr instanceof RuntimeInvisibleAnnotations) {
   185             }
   182                 final RuntimeInvisibleAnnotations ria = (RuntimeInvisibleAnnotations) attr;
   186             else
   183                 final AnnotationEntry[] annos = ria.getAnnotationEntries();
   187                 if (attr instanceof RuntimeInvisibleAnnotations)
   184                 for (final AnnotationEntry a : annos) {
   188                 {
   185                     annotationGenObjs.add(new AnnotationEntryGen(a,
   189                     final RuntimeInvisibleAnnotations ria = (RuntimeInvisibleAnnotations) attr;
   186                             getConstantPool(), false));
   190                     final AnnotationEntry[] annos = ria.getAnnotationEntries();
       
   191                     for (final AnnotationEntry a : annos) {
       
   192                         annotationGenObjs.add(new AnnotationEntryGen(a,
       
   193                                 getConstantPool(), false));
       
   194                     }
   187                 }
   195                 }
   188             }
       
   189         }
   196         }
   190         return annotationGenObjs.toArray(new AnnotationEntryGen[annotationGenObjs.size()]);
   197         return annotationGenObjs.toArray(new AnnotationEntryGen[annotationGenObjs.size()]);
   191     }
   198     }
       
   199 
   192 
   200 
   193     /**
   201     /**
   194      * @return the (finally) built up Java class object.
   202      * @return the (finally) built up Java class object.
   195      */
   203      */
   196     public JavaClass getJavaClass() {
   204     public JavaClass getJavaClass() {
   197         final int[] interfaces = getInterfaces();
   205         final int[] interfaces = getInterfaces();
   198         final Field[] fields = getFields();
   206         final Field[] fields = getFields();
   199         final Method[] methods = getMethods();
   207         final Method[] methods = getMethods();
   200         Attribute[] attributes;
   208         Attribute[] attributes = null;
   201         if (annotation_vec.isEmpty()) {
   209         if (annotation_vec.isEmpty()) {
   202             attributes = getAttributes();
   210             attributes = getAttributes();
   203         } else {
   211         } else {
   204             // TODO: Sometime later, trash any attributes called 'RuntimeVisibleAnnotations' or 'RuntimeInvisibleAnnotations'
   212             // TODO: Sometime later, trash any attributes called 'RuntimeVisibleAnnotations' or 'RuntimeInvisibleAnnotations'
   205             final Attribute[] annAttributes = AnnotationEntryGen.getAnnotationAttributes(cp, getAnnotationEntries());
   213             final Attribute[] annAttributes  = AnnotationEntryGen.getAnnotationAttributes(cp, getAnnotationEntries());
   206             attributes = new Attribute[attribute_vec.size() + annAttributes.length];
   214             attributes = new Attribute[attribute_vec.size()+annAttributes.length];
   207             attribute_vec.toArray(attributes);
   215             attribute_vec.toArray(attributes);
   208             System.arraycopy(annAttributes, 0, attributes, attribute_vec.size(), annAttributes.length);
   216             System.arraycopy(annAttributes,0,attributes,attribute_vec.size(),annAttributes.length);
   209         }
   217         }
   210         // Must be last since the above calls may still add something to it
   218         // Must be last since the above calls may still add something to it
   211         final ConstantPool _cp = this.cp.getFinalConstantPool();
   219         final ConstantPool _cp = this.cp.getFinalConstantPool();
   212         return new JavaClass(class_name_index, superclass_name_index, file_name, major, minor,
   220         return new JavaClass(class_name_index, superclass_name_index, file_name, major, minor,
   213                 super.getAccessFlags(), _cp, interfaces, fields, methods, attributes);
   221                 super.getAccessFlags(), _cp, interfaces, fields, methods, attributes);
   214     }
   222     }
   215 
   223 
       
   224 
   216     /**
   225     /**
   217      * Add an interface to this class, i.e., this class has to implement it.
   226      * Add an interface to this class, i.e., this class has to implement it.
   218      *
       
   219      * @param name interface to implement (fully qualified class name)
   227      * @param name interface to implement (fully qualified class name)
   220      */
   228      */
   221     public final void addInterface(final String name) {
   229     public void addInterface( final String name ) {
   222         interface_vec.add(name);
   230         interface_vec.add(name);
   223     }
   231     }
   224 
   232 
       
   233 
   225     /**
   234     /**
   226      * Remove an interface from this class.
   235      * Remove an interface from this class.
   227      *
       
   228      * @param name interface to remove (fully qualified name)
   236      * @param name interface to remove (fully qualified name)
   229      */
   237      */
   230     public void removeInterface(final String name) {
   238     public void removeInterface( final String name ) {
   231         interface_vec.remove(name);
   239         interface_vec.remove(name);
   232     }
   240     }
       
   241 
   233 
   242 
   234     /**
   243     /**
   235      * @return major version number of class file
   244      * @return major version number of class file
   236      */
   245      */
   237     public int getMajor() {
   246     public int getMajor() {
   238         return major;
   247         return major;
   239     }
   248     }
   240 
   249 
   241     /**
   250 
   242      * Set major version number of class file, default value is 45 (JDK 1.1)
   251     /** Set major version number of class file, default value is 45 (JDK 1.1)
   243      *
       
   244      * @param major major version number
   252      * @param major major version number
   245      */
   253      */
   246     public void setMajor(final int major) { // TODO could be package-protected - only called by test code
   254     public void setMajor( final int major ) { // TODO could be package-protected - only called by test code
   247         this.major = major;
   255         this.major = major;
   248     }
   256     }
   249 
   257 
   250     /**
   258 
   251      * Set minor version number of class file, default value is 3 (JDK 1.1)
   259     /** Set minor version number of class file, default value is 3 (JDK 1.1)
   252      *
       
   253      * @param minor minor version number
   260      * @param minor minor version number
   254      */
   261      */
   255     public void setMinor(final int minor) {  // TODO could be package-protected - only called by test code
   262     public void setMinor( final int minor ) {  // TODO could be package-protected - only called by test code
   256         this.minor = minor;
   263         this.minor = minor;
   257     }
   264     }
   258 
   265 
   259     /**
   266     /**
   260      * @return minor version number of class file
   267      * @return minor version number of class file
   261      */
   268      */
   262     public int getMinor() {
   269     public int getMinor() {
   263         return minor;
   270         return minor;
   264     }
   271     }
   265 
   272 
       
   273 
   266     /**
   274     /**
   267      * Add an attribute to this class.
   275      * Add an attribute to this class.
   268      *
       
   269      * @param a attribute to add
   276      * @param a attribute to add
   270      */
   277      */
   271     public final void addAttribute(final Attribute a) {
   278     public void addAttribute( final Attribute a ) {
   272         attribute_vec.add(a);
   279         attribute_vec.add(a);
   273     }
   280     }
   274 
   281 
   275     public final void addAnnotationEntry(final AnnotationEntryGen a) {
   282     public void addAnnotationEntry(final AnnotationEntryGen a) {
   276         annotation_vec.add(a);
   283         annotation_vec.add(a);
   277     }
   284     }
   278 
   285 
       
   286 
   279     /**
   287     /**
   280      * Add a method to this class.
   288      * Add a method to this class.
   281      *
       
   282      * @param m method to add
   289      * @param m method to add
   283      */
   290      */
   284     public final void addMethod(final Method m) {
   291     public void addMethod( final Method m ) {
   285         method_vec.add(m);
   292         method_vec.add(m);
   286     }
   293     }
       
   294 
   287 
   295 
   288     /**
   296     /**
   289      * Convenience method.
   297      * Convenience method.
   290      *
   298      *
   291      * Add an empty constructor to this class that does nothing but calling
   299      * Add an empty constructor to this class that does nothing but calling super().
   292      * super().
       
   293      *
       
   294      * @param access_flags rights for constructor
   300      * @param access_flags rights for constructor
   295      */
   301      */
   296     public void addEmptyConstructor(final int access_flags) {
   302     public void addEmptyConstructor( final int access_flags ) {
   297         final InstructionList il = new InstructionList();
   303         final InstructionList il = new InstructionList();
   298         il.append(InstructionConst.THIS); // Push `this'
   304         il.append(InstructionConst.THIS); // Push `this'
   299         il.append(new INVOKESPECIAL(cp.addMethodref(super_class_name, "<init>", "()V")));
   305         il.append(new INVOKESPECIAL(cp.addMethodref(super_class_name, "<init>", "()V")));
   300         il.append(InstructionConst.RETURN);
   306         il.append(InstructionConst.RETURN);
   301         final MethodGen mg = new MethodGen(access_flags, Type.VOID, Type.NO_ARGS, null, "<init>",
   307         final MethodGen mg = new MethodGen(access_flags, Type.VOID, Type.NO_ARGS, null, "<init>",
   302                 class_name, il, cp);
   308                 class_name, il, cp);
   303         mg.setMaxStack(1);
   309         mg.setMaxStack(1);
   304         addMethod(mg.getMethod());
   310         addMethod(mg.getMethod());
   305     }
   311     }
   306 
   312 
       
   313 
   307     /**
   314     /**
   308      * Add a field to this class.
   315      * Add a field to this class.
   309      *
       
   310      * @param f field to add
   316      * @param f field to add
   311      */
   317      */
   312     public final void addField(final Field f) {
   318     public void addField( final Field f ) {
   313         field_vec.add(f);
   319         field_vec.add(f);
   314     }
   320     }
   315 
   321 
   316     public boolean containsField(final Field f) {
   322 
       
   323     public boolean containsField( final Field f ) {
   317         return field_vec.contains(f);
   324         return field_vec.contains(f);
   318     }
   325     }
   319 
   326 
   320     /**
   327 
   321      * @return field object with given name, or null
   328     /** @return field object with given name, or null
   322      */
   329      */
   323     public Field containsField(final String name) {
   330     public Field containsField( final String name ) {
   324         for (final Field f : field_vec) {
   331         for (final Field f : field_vec) {
   325             if (f.getName().equals(name)) {
   332             if (f.getName().equals(name)) {
   326                 return f;
   333                 return f;
   327             }
   334             }
   328         }
   335         }
   329         return null;
   336         return null;
   330     }
   337     }
   331 
   338 
   332     /**
   339 
   333      * @return method object with given name and signature, or null
   340     /** @return method object with given name and signature, or null
   334      */
   341      */
   335     public Method containsMethod(final String name, final String signature) {
   342     public Method containsMethod( final String name, final String signature ) {
   336         for (final Method m : method_vec) {
   343         for (final Method m : method_vec) {
   337             if (m.getName().equals(name) && m.getSignature().equals(signature)) {
   344             if (m.getName().equals(name) && m.getSignature().equals(signature)) {
   338                 return m;
   345                 return m;
   339             }
   346             }
   340         }
   347         }
   341         return null;
   348         return null;
   342     }
   349     }
   343 
   350 
       
   351 
   344     /**
   352     /**
   345      * Remove an attribute from this class.
   353      * Remove an attribute from this class.
   346      *
       
   347      * @param a attribute to remove
   354      * @param a attribute to remove
   348      */
   355      */
   349     public void removeAttribute(final Attribute a) {
   356     public void removeAttribute( final Attribute a ) {
   350         attribute_vec.remove(a);
   357         attribute_vec.remove(a);
   351     }
   358     }
   352 
   359 
       
   360 
   353     /**
   361     /**
   354      * Remove a method from this class.
   362      * Remove a method from this class.
   355      *
       
   356      * @param m method to remove
   363      * @param m method to remove
   357      */
   364      */
   358     public void removeMethod(final Method m) {
   365     public void removeMethod( final Method m ) {
   359         method_vec.remove(m);
   366         method_vec.remove(m);
   360     }
   367     }
   361 
   368 
   362     /**
   369 
   363      * Replace given method with new one. If the old one does not exist add the
   370     /** Replace given method with new one. If the old one does not exist
   364      * new_ method to the class anyway.
   371      * add the new_ method to the class anyway.
   365      */
   372      */
   366     public void replaceMethod(final Method old, final Method new_) {
   373     public void replaceMethod( final Method old, final Method new_ ) {
   367         if (new_ == null) {
   374         if (new_ == null) {
   368             throw new ClassGenException("Replacement method must not be null");
   375             throw new ClassGenException("Replacement method must not be null");
   369         }
   376         }
   370         final int i = method_vec.indexOf(old);
   377         final int i = method_vec.indexOf(old);
   371         if (i < 0) {
   378         if (i < 0) {
   373         } else {
   380         } else {
   374             method_vec.set(i, new_);
   381             method_vec.set(i, new_);
   375         }
   382         }
   376     }
   383     }
   377 
   384 
   378     /**
   385 
   379      * Replace given field with new one. If the old one does not exist add the
   386     /** Replace given field with new one. If the old one does not exist
   380      * new_ field to the class anyway.
   387      * add the new_ field to the class anyway.
   381      */
   388      */
   382     public void replaceField(final Field old, final Field new_) {
   389     public void replaceField( final Field old, final Field new_ ) {
   383         if (new_ == null) {
   390         if (new_ == null) {
   384             throw new ClassGenException("Replacement method must not be null");
   391             throw new ClassGenException("Replacement method must not be null");
   385         }
   392         }
   386         final int i = field_vec.indexOf(old);
   393         final int i = field_vec.indexOf(old);
   387         if (i < 0) {
   394         if (i < 0) {
   389         } else {
   396         } else {
   390             field_vec.set(i, new_);
   397             field_vec.set(i, new_);
   391         }
   398         }
   392     }
   399     }
   393 
   400 
       
   401 
   394     /**
   402     /**
   395      * Remove a field to this class.
   403      * Remove a field to this class.
   396      *
       
   397      * @param f field to remove
   404      * @param f field to remove
   398      */
   405      */
   399     public void removeField(final Field f) {
   406     public void removeField( final Field f ) {
   400         field_vec.remove(f);
   407         field_vec.remove(f);
   401     }
   408     }
       
   409 
   402 
   410 
   403     public String getClassName() {
   411     public String getClassName() {
   404         return class_name;
   412         return class_name;
   405     }
   413     }
   406 
   414 
       
   415 
   407     public String getSuperclassName() {
   416     public String getSuperclassName() {
   408         return super_class_name;
   417         return super_class_name;
   409     }
   418     }
   410 
   419 
       
   420 
   411     public String getFileName() {
   421     public String getFileName() {
   412         return file_name;
   422         return file_name;
   413     }
   423     }
   414 
   424 
   415     public void setClassName(final String name) {
   425 
       
   426     public void setClassName( final String name ) {
   416         class_name = name.replace('/', '.');
   427         class_name = name.replace('/', '.');
   417         class_name_index = cp.addClass(name);
   428         class_name_index = cp.addClass(name);
   418     }
   429     }
   419 
   430 
   420     public void setSuperclassName(final String name) {
   431 
       
   432     public void setSuperclassName( final String name ) {
   421         super_class_name = name.replace('/', '.');
   433         super_class_name = name.replace('/', '.');
   422         superclass_name_index = cp.addClass(name);
   434         superclass_name_index = cp.addClass(name);
   423     }
   435     }
   424 
   436 
       
   437 
   425     public Method[] getMethods() {
   438     public Method[] getMethods() {
   426         return method_vec.toArray(new Method[method_vec.size()]);
   439         return method_vec.toArray(new Method[method_vec.size()]);
   427     }
   440     }
   428 
   441 
   429     public void setMethods(final Method[] methods) {
   442 
       
   443     public void setMethods( final Method[] methods ) {
   430         method_vec.clear();
   444         method_vec.clear();
   431         for (final Method method : methods) {
   445         for (final Method method : methods) {
   432             addMethod(method);
   446             addMethod(method);
   433         }
   447         }
   434     }
   448     }
   435 
   449 
   436     public void setMethodAt(final Method method, final int pos) {
   450 
       
   451     public void setMethodAt( final Method method, final int pos ) {
   437         method_vec.set(pos, method);
   452         method_vec.set(pos, method);
   438     }
   453     }
   439 
   454 
   440     public Method getMethodAt(final int pos) {
   455 
       
   456     public Method getMethodAt( final int pos ) {
   441         return method_vec.get(pos);
   457         return method_vec.get(pos);
   442     }
   458     }
       
   459 
   443 
   460 
   444     public String[] getInterfaceNames() {
   461     public String[] getInterfaceNames() {
   445         final int size = interface_vec.size();
   462         final int size = interface_vec.size();
   446         final String[] interfaces = new String[size];
   463         final String[] interfaces = new String[size];
   447         interface_vec.toArray(interfaces);
   464         interface_vec.toArray(interfaces);
   448         return interfaces;
   465         return interfaces;
   449     }
   466     }
   450 
   467 
       
   468 
   451     public int[] getInterfaces() {
   469     public int[] getInterfaces() {
   452         final int size = interface_vec.size();
   470         final int size = interface_vec.size();
   453         final int[] interfaces = new int[size];
   471         final int[] interfaces = new int[size];
   454         for (int i = 0; i < size; i++) {
   472         for (int i = 0; i < size; i++) {
   455             interfaces[i] = cp.addClass(interface_vec.get(i));
   473             interfaces[i] = cp.addClass(interface_vec.get(i));
   456         }
   474         }
   457         return interfaces;
   475         return interfaces;
   458     }
   476     }
   459 
   477 
       
   478 
   460     public Field[] getFields() {
   479     public Field[] getFields() {
   461         return field_vec.toArray(new Field[field_vec.size()]);
   480         return field_vec.toArray(new Field[field_vec.size()]);
   462     }
   481     }
       
   482 
   463 
   483 
   464     public Attribute[] getAttributes() {
   484     public Attribute[] getAttributes() {
   465         return attribute_vec.toArray(new Attribute[attribute_vec.size()]);
   485         return attribute_vec.toArray(new Attribute[attribute_vec.size()]);
   466     }
   486     }
   467 
   487 
   468     //  J5TODO: Should we make calling unpackAnnotations() lazy and put it in here?
   488     //  J5TODO: Should we make calling unpackAnnotations() lazy and put it in here?
   469     public AnnotationEntryGen[] getAnnotationEntries() {
   489     public AnnotationEntryGen[] getAnnotationEntries() {
   470         return annotation_vec.toArray(new AnnotationEntryGen[annotation_vec.size()]);
   490         return annotation_vec.toArray(new AnnotationEntryGen[annotation_vec.size()]);
   471     }
   491     }
   472 
   492 
       
   493 
   473     public ConstantPoolGen getConstantPool() {
   494     public ConstantPoolGen getConstantPool() {
   474         return cp;
   495         return cp;
   475     }
   496     }
   476 
   497 
   477     public void setConstantPool(final ConstantPoolGen constant_pool) {
   498 
       
   499     public void setConstantPool( final ConstantPoolGen constant_pool ) {
   478         cp = constant_pool;
   500         cp = constant_pool;
   479     }
   501     }
   480 
   502 
   481     public void setClassNameIndex(final int class_name_index) {
   503 
       
   504     public void setClassNameIndex( final int class_name_index ) {
   482         this.class_name_index = class_name_index;
   505         this.class_name_index = class_name_index;
   483         class_name = cp.getConstantPool().getConstantString(class_name_index,
   506         class_name = cp.getConstantPool().getConstantString(class_name_index,
   484                 Const.CONSTANT_Class).replace('/', '.');
   507                 Const.CONSTANT_Class).replace('/', '.');
   485     }
   508     }
   486 
   509 
   487     public void setSuperclassNameIndex(final int superclass_name_index) {
   510 
       
   511     public void setSuperclassNameIndex( final int superclass_name_index ) {
   488         this.superclass_name_index = superclass_name_index;
   512         this.superclass_name_index = superclass_name_index;
   489         super_class_name = cp.getConstantPool().getConstantString(superclass_name_index,
   513         super_class_name = cp.getConstantPool().getConstantString(superclass_name_index,
   490                 Const.CONSTANT_Class).replace('/', '.');
   514                 Const.CONSTANT_Class).replace('/', '.');
   491     }
   515     }
   492 
   516 
       
   517 
   493     public int getSuperclassNameIndex() {
   518     public int getSuperclassNameIndex() {
   494         return superclass_name_index;
   519         return superclass_name_index;
   495     }
   520     }
   496 
   521 
       
   522 
   497     public int getClassNameIndex() {
   523     public int getClassNameIndex() {
   498         return class_name_index;
   524         return class_name_index;
   499     }
   525     }
   500 
   526 
   501     private List<ClassObserver> observers;
   527     private List<ClassObserver> observers;
   502 
   528 
   503     /**
   529 
   504      * Add observer for this object.
   530     /** Add observer for this object.
   505      */
   531      */
   506     public void addObserver(final ClassObserver o) {
   532     public void addObserver( final ClassObserver o ) {
   507         if (observers == null) {
   533         if (observers == null) {
   508             observers = new ArrayList<>();
   534             observers = new ArrayList<>();
   509         }
   535         }
   510         observers.add(o);
   536         observers.add(o);
   511     }
   537     }
   512 
   538 
   513     /**
   539 
   514      * Remove observer for this object.
   540     /** Remove observer for this object.
   515      */
   541      */
   516     public void removeObserver(final ClassObserver o) {
   542     public void removeObserver( final ClassObserver o ) {
   517         if (observers != null) {
   543         if (observers != null) {
   518             observers.remove(o);
   544             observers.remove(o);
   519         }
   545         }
   520     }
   546     }
   521 
   547 
   522     /**
   548 
   523      * Call notify() method on all observers. This method is not called
   549     /** Call notify() method on all observers. This method is not called
   524      * automatically whenever the state has changed, but has to be called by the
   550      * automatically whenever the state has changed, but has to be
   525      * user after he has finished editing the object.
   551      * called by the user after he has finished editing the object.
   526      */
   552      */
   527     public void update() {
   553     public void update() {
   528         if (observers != null) {
   554         if (observers != null) {
   529             for (final ClassObserver observer : observers) {
   555             for (final ClassObserver observer : observers) {
   530                 observer.notify(this);
   556                 observer.notify(this);
   531             }
   557             }
   532         }
   558         }
   533     }
   559     }
       
   560 
   534 
   561 
   535     @Override
   562     @Override
   536     public Object clone() {
   563     public Object clone() {
   537         try {
   564         try {
   538             return super.clone();
   565             return super.clone();
   539         } catch (final CloneNotSupportedException e) {
   566         } catch (final CloneNotSupportedException e) {
   540             throw new Error("Clone Not Supported"); // never happens
   567             throw new Error("Clone Not Supported"); // never happens
   541         }
   568         }
   542     }
   569     }
   543 
   570 
       
   571 
   544     /**
   572     /**
   545      * @return Comparison strategy object
   573      * @return Comparison strategy object
   546      */
   574      */
   547     public static BCELComparator getComparator() {
   575     public static BCELComparator getComparator() {
   548         return _cmp;
   576         return _cmp;
   549     }
   577     }
   550 
   578 
       
   579 
   551     /**
   580     /**
   552      * @param comparator Comparison strategy object
   581      * @param comparator Comparison strategy object
   553      */
   582      */
   554     public static void setComparator(final BCELComparator comparator) {
   583     public static void setComparator( final BCELComparator comparator ) {
   555         _cmp = comparator;
   584         _cmp = comparator;
   556     }
   585     }
   557 
   586 
   558     /**
   587 
   559      * Return value as defined by given BCELComparator strategy. By default two
   588     /**
   560      * ClassGen objects are said to be equal when their class names are equal.
   589      * Return value as defined by given BCELComparator strategy.
       
   590      * By default two ClassGen objects are said to be equal when
       
   591      * their class names are equal.
   561      *
   592      *
   562      * @see java.lang.Object#equals(java.lang.Object)
   593      * @see java.lang.Object#equals(java.lang.Object)
   563      */
   594      */
   564     @Override
   595     @Override
   565     public boolean equals(final Object obj) {
   596     public boolean equals( final Object obj ) {
   566         return _cmp.equals(this, obj);
   597         return _cmp.equals(this, obj);
   567     }
   598     }
   568 
   599 
   569     /**
   600 
   570      * Return value as defined by given BCELComparator strategy. By default
   601     /**
   571      * return the hashcode of the class name.
   602      * Return value as defined by given BCELComparator strategy.
       
   603      * By default return the hashcode of the class name.
   572      *
   604      *
   573      * @see java.lang.Object#hashCode()
   605      * @see java.lang.Object#hashCode()
   574      */
   606      */
   575     @Override
   607     @Override
   576     public int hashCode() {
   608     public int hashCode() {