FieldOrMethod.java

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

  18. import java.io.DataInput;
  19. import java.io.DataInputStream;
  20. import java.io.DataOutputStream;
  21. import java.io.IOException;
  22. import java.util.Arrays;

  23. /**
  24.  * Abstract super class for fields and methods.
  25.  */
  26. public abstract class FieldOrMethod extends AccessFlags implements Cloneable, Node {

  27.     /**
  28.      * @deprecated (since 6.0) will be made private; do not access directly, use getter/setter
  29.      */
  30.     @java.lang.Deprecated
  31.     protected int name_index; // Points to field name in constant pool

  32.     /**
  33.      * @deprecated (since 6.0) will be made private; do not access directly, use getter/setter
  34.      */
  35.     @java.lang.Deprecated
  36.     protected int signature_index; // Points to encoded signature

  37.     /**
  38.      * @deprecated (since 6.0) will be made private; do not access directly, use getter/setter
  39.      */
  40.     @java.lang.Deprecated
  41.     protected Attribute[] attributes; // Collection of attributes

  42.     /**
  43.      * @deprecated (since 6.0) will be removed (not needed)
  44.      */
  45.     @java.lang.Deprecated
  46.     protected int attributes_count; // No. of attributes

  47.     // @since 6.0
  48.     private AnnotationEntry[] annotationEntries; // annotations defined on the field or method

  49.     /**
  50.      * @deprecated (since 6.0) will be made private; do not access directly, use getter/setter
  51.      */
  52.     @java.lang.Deprecated
  53.     protected ConstantPool constant_pool;

  54.     private String signatureAttributeString;
  55.     private boolean searchedForSignatureAttribute;

  56.     FieldOrMethod() {
  57.     }

  58.     /**
  59.      * Constructs object from file stream.
  60.      *
  61.      * @param file Input stream
  62.      * @throws IOException if an I/O error occurs.
  63.      */
  64.     protected FieldOrMethod(final DataInput file, final ConstantPool constantPool) throws IOException {
  65.         this(file.readUnsignedShort(), file.readUnsignedShort(), file.readUnsignedShort(), null, constantPool);
  66.         final int attributesCount = file.readUnsignedShort();
  67.         attributes = new Attribute[attributesCount];
  68.         for (int i = 0; i < attributesCount; i++) {
  69.             attributes[i] = Attribute.readAttribute(file, constantPool);
  70.         }
  71.         this.attributes_count = attributesCount; // init deprecated field
  72.     }

  73.     /**
  74.      * Constructs object from file stream.
  75.      *
  76.      * @param file Input stream
  77.      * @throws IOException if an I/O error occurs.
  78.      * @deprecated (6.0) Use {@link #FieldOrMethod(java.io.DataInput, ConstantPool)} instead.
  79.      */
  80.     @java.lang.Deprecated
  81.     protected FieldOrMethod(final DataInputStream file, final ConstantPool constantPool) throws IOException {
  82.         this((DataInput) file, constantPool);
  83.     }

  84.     /**
  85.      * Initialize from another object. Note that both objects use the same references (shallow copy). Use clone() for a
  86.      * physical copy.
  87.      *
  88.      * @param c Source to copy.
  89.      */
  90.     protected FieldOrMethod(final FieldOrMethod c) {
  91.         this(c.getAccessFlags(), c.getNameIndex(), c.getSignatureIndex(), c.getAttributes(), c.getConstantPool());
  92.     }

  93.     /**
  94.      * @param accessFlags Access rights of method
  95.      * @param nameIndex Points to field name in constant pool
  96.      * @param signatureIndex Points to encoded signature
  97.      * @param attributes Collection of attributes
  98.      * @param constantPool Array of constants
  99.      */
  100.     protected FieldOrMethod(final int accessFlags, final int nameIndex, final int signatureIndex, final Attribute[] attributes,
  101.         final ConstantPool constantPool) {
  102.         super(accessFlags);
  103.         this.name_index = nameIndex;
  104.         this.signature_index = signatureIndex;
  105.         this.constant_pool = constantPool;
  106.         setAttributes(attributes);
  107.     }

  108.     /**
  109.      * @return deep copy of this field
  110.      */
  111.     protected FieldOrMethod copy_(final ConstantPool constantPool) {
  112.         try {
  113.             final FieldOrMethod c = (FieldOrMethod) clone();
  114.             c.constant_pool = constantPool;
  115.             c.attributes = new Attribute[attributes.length];
  116.             c.attributes_count = attributes_count; // init deprecated field
  117.             Arrays.setAll(c.attributes, i -> attributes[i].copy(constantPool));
  118.             return c;
  119.         } catch (final CloneNotSupportedException e) {
  120.             throw new UnsupportedOperationException(e);
  121.         }
  122.     }

  123.     /**
  124.      * Dump object to file stream on binary format.
  125.      *
  126.      * @param file Output file stream
  127.      * @throws IOException if an I/O error occurs.
  128.      */
  129.     public final void dump(final DataOutputStream file) throws IOException {
  130.         file.writeShort(super.getAccessFlags());
  131.         file.writeShort(name_index);
  132.         file.writeShort(signature_index);
  133.         file.writeShort(attributes_count);
  134.         for (final Attribute attribute : attributes) {
  135.             attribute.dump(file);
  136.         }
  137.     }

  138.     /**
  139.      * @return Annotations on the field or method
  140.      * @since 6.0
  141.      */
  142.     public AnnotationEntry[] getAnnotationEntries() {
  143.         if (annotationEntries == null) {
  144.             annotationEntries = AnnotationEntry.createAnnotationEntries(getAttributes());
  145.         }

  146.         return annotationEntries;
  147.     }

  148.     /**
  149.      * Gets attribute for given tag.
  150.      * @return Attribute for given tag, null if not found.
  151.      * Refer to {@link org.apache.bcel.Const#ATTR_UNKNOWN} constants named ATTR_* for possible values.
  152.      * @since 6.10.0
  153.      */
  154.     @SuppressWarnings("unchecked")
  155.     public final <T extends Attribute> T getAttribute(final byte tag) {
  156.         for (final Attribute attribute : getAttributes()) {
  157.             if (attribute.getTag() == tag) {
  158.                 return (T) attribute;
  159.             }
  160.         }
  161.         return null;
  162.     }

  163.     /**
  164.      * @return Collection of object attributes.
  165.      */
  166.     public final Attribute[] getAttributes() {
  167.         return attributes;
  168.     }

  169.     /**
  170.      * @return Constant pool used by this object.
  171.      */
  172.     public final ConstantPool getConstantPool() {
  173.         return constant_pool;
  174.     }

  175.     /**
  176.      * Hunts for a signature attribute on the member and returns its contents. So where the 'regular' signature may be
  177.      * (Ljava/util/Vector;)V the signature attribute may in fact say 'Ljava/lang/Vector&lt;Ljava/lang/String&gt;;' Coded for
  178.      * performance - searches for the attribute only when requested - only searches for it once.
  179.      *
  180.      * @since 6.0
  181.      */
  182.     public final String getGenericSignature() {
  183.         if (!searchedForSignatureAttribute) {
  184.             boolean found = false;
  185.             for (int i = 0; !found && i < attributes.length; i++) {
  186.                 if (attributes[i] instanceof Signature) {
  187.                     signatureAttributeString = ((Signature) attributes[i]).getSignature();
  188.                     found = true;
  189.                 }
  190.             }
  191.             searchedForSignatureAttribute = true;
  192.         }
  193.         return signatureAttributeString;
  194.     }

  195.     /**
  196.      * @return Name of object, i.e., method name or field name
  197.      */
  198.     public final String getName() {
  199.         return constant_pool.getConstantUtf8(name_index).getBytes();
  200.     }

  201.     /**
  202.      * @return Index in constant pool of object's name.
  203.      */
  204.     public final int getNameIndex() {
  205.         return name_index;
  206.     }

  207.     /**
  208.      * @return String representation of object's type signature (Java style)
  209.      */
  210.     public final String getSignature() {
  211.         return constant_pool.getConstantUtf8(signature_index).getBytes();
  212.     }

  213.     /**
  214.      * @return Index in constant pool of field signature.
  215.      */
  216.     public final int getSignatureIndex() {
  217.         return signature_index;
  218.     }

  219.     /**
  220.      * @param attributes Collection of object attributes.
  221.      */
  222.     public final void setAttributes(final Attribute[] attributes) {
  223.         this.attributes = attributes != null ? attributes : Attribute.EMPTY_ARRAY;
  224.         this.attributes_count = this.attributes.length; // init deprecated field
  225.     }

  226.     /**
  227.      * @param constantPool Constant pool to be used for this object.
  228.      */
  229.     public final void setConstantPool(final ConstantPool constantPool) {
  230.         this.constant_pool = constantPool;
  231.     }

  232.     /**
  233.      * @param nameIndex Index in constant pool of object's name.
  234.      */
  235.     public final void setNameIndex(final int nameIndex) {
  236.         this.name_index = nameIndex;
  237.     }

  238.     /**
  239.      * @param signatureIndex Index in constant pool of field signature.
  240.      */
  241.     public final void setSignatureIndex(final int signatureIndex) {
  242.         this.signature_index = signatureIndex;
  243.     }
  244. }