    001/*
    002 * Licensed to the Apache Software Foundation (ASF) under one or more
    003 * contributor license agreements.  See the NOTICE file distributed with
    004 * this work for additional information regarding copyright ownership.
    005 * The ASF licenses this file to You under the Apache License, Version 2.0
    006 * (the "License"); you may not use this file except in compliance with
    007 * the License.  You may obtain a copy of the License at
    008 *
    009 *      http://www.apache.org/licenses/LICENSE-2.0
    010 *
    011 *  Unless required by applicable law or agreed to in writing, software
    012 *  distributed under the License is distributed on an "AS IS" BASIS,
    013 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    014 *  See the License for the specific language governing permissions and
    015 *  limitations under the License.
    016 *
    017 */
    018package org.apache.bcel.classfile;
    019
    020import java.io.DataInput;
    021import java.io.DataInputStream;
    022import java.io.DataOutputStream;
    023import java.io.IOException;
    024
    025import org.apache.bcel.Const;
    026
    027/**
    028 * Abstract super class for fields and methods.
    029 *
    030 * @version $Id: FieldOrMethod.java 1806200 2017-08-25 16:33:06Z ggregory $
    031 */
    032public abstract class FieldOrMethod extends AccessFlags implements Cloneable, Node {
    033
    034    /**
    035     * @deprecated (since 6.0) will be made private; do not access directly, use getter/setter
    036     */
    037    @java.lang.Deprecated
    038    protected int name_index; // Points to field name in constant pool
    039
    040    /**
    041     * @deprecated (since 6.0) will be made private; do not access directly, use getter/setter
    042     */
    043    @java.lang.Deprecated
    044    protected int signature_index; // Points to encoded signature
    045
    046    /**
    047     * @deprecated (since 6.0) will be made private; do not access directly, use getter/setter
    048     */
    049    @java.lang.Deprecated
    050    protected Attribute[] attributes; // Collection of attributes
    051
    052    /**
    053     * @deprecated (since 6.0) will be removed (not needed)
    054     */
    055    @java.lang.Deprecated
    056    protected int attributes_count; // No. of attributes
    057
    058    // @since 6.0
    059    private AnnotationEntry[] annotationEntries; // annotations defined on the field or method
    060
    061    /**
    062     * @deprecated (since 6.0) will be made private; do not access directly, use getter/setter
    063     */
    064    @java.lang.Deprecated
    065    protected ConstantPool constant_pool;
    066
    067    private String signatureAttributeString = null;
    068    private boolean searchedForSignatureAttribute = false;
    069
    070    FieldOrMethod() {
    071    }
    072
    073
    074    /**
    075     * Initialize from another object. Note that both objects use the same
    076     * references (shallow copy). Use clone() for a physical copy.
    077     */
    078    protected FieldOrMethod(final FieldOrMethod c) {
    079        this(c.getAccessFlags(), c.getNameIndex(), c.getSignatureIndex(), c.getAttributes(), c
    080                .getConstantPool());
    081    }
    082
    083
    084    /**
    085     * Construct object from file stream.
    086     * @param file Input stream
    087     * @throws IOException
    088     * @throws ClassFormatException
    089     * @deprecated (6.0) Use {@link #FieldOrMethod(java.io.DataInput, ConstantPool)} instead.
    090     */
    091    @java.lang.Deprecated
    092    protected FieldOrMethod(final DataInputStream file, final ConstantPool constant_pool) throws IOException,
    093            ClassFormatException {
    094        this((DataInput) file, constant_pool);
    095    }
    096
    097    /**
    098     * Construct object from file stream.
    099     * @param file Input stream
    100     * @throws IOException
    101     * @throws ClassFormatException
    102     */
    103    protected FieldOrMethod(final DataInput file, final ConstantPool constant_pool) throws IOException, ClassFormatException {
    104        this(file.readUnsignedShort(), file.readUnsignedShort(), file.readUnsignedShort(), null,
    105                constant_pool);
    106        final int attributes_count = file.readUnsignedShort();
    107        attributes = new Attribute[attributes_count];
    108        for (int i = 0; i < attributes_count; i++) {
    109            attributes[i] = Attribute.readAttribute(file, constant_pool);
    110        }
    111        this.attributes_count = attributes_count; // init deprecated field
    112    }
    113
    114
    115    /**
    116     * @param access_flags Access rights of method
    117     * @param name_index Points to field name in constant pool
    118     * @param signature_index Points to encoded signature
    119     * @param attributes Collection of attributes
    120     * @param constant_pool Array of constants
    121     */
    122    protected FieldOrMethod(final int access_flags, final int name_index, final int signature_index,
    123            final Attribute[] attributes, final ConstantPool constant_pool) {
    124        super(access_flags);
    125        this.name_index = name_index;
    126        this.signature_index = signature_index;
    127        this.constant_pool = constant_pool;
    128        setAttributes(attributes);
    129    }
    130
    131
    132    /**
    133     * Dump object to file stream on binary format.
    134     *
    135     * @param file Output file stream
    136     * @throws IOException
    137     */
    138    public final void dump( final DataOutputStream file ) throws IOException {
    139        file.writeShort(super.getAccessFlags());
    140        file.writeShort(name_index);
    141        file.writeShort(signature_index);
    142        file.writeShort(attributes.length);
    143        for (final Attribute attribute : attributes) {
    144            attribute.dump(file);
    145        }
    146    }
    147
    148
    149    /**
    150     * @return Collection of object attributes.
    151     */
    152    public final Attribute[] getAttributes() {
    153        return attributes;
    154    }
    155
    156
    157    /**
    158     * @param attributes Collection of object attributes.
    159     */
    160    public final void setAttributes( final Attribute[] attributes ) {
    161        this.attributes = attributes;
    162        this.attributes_count = attributes != null ? attributes.length : 0; // init deprecated field
    163    }
    164
    165
    166    /**
    167     * @return Constant pool used by this object.
    168     */
    169    public final ConstantPool getConstantPool() {
    170        return constant_pool;
    171    }
    172
    173
    174    /**
    175     * @param constant_pool Constant pool to be used for this object.
    176     */
    177    public final void setConstantPool( final ConstantPool constant_pool ) {
    178        this.constant_pool = constant_pool;
    179    }
    180
    181
    182    /**
    183     * @return Index in constant pool of object's name.
    184     */
    185    public final int getNameIndex() {
    186        return name_index;
    187    }
    188
    189
    190    /**
    191     * @param name_index Index in constant pool of object's name.
    192     */
    193    public final void setNameIndex( final int name_index ) {
    194        this.name_index = name_index;
    195    }
    196
    197
    198    /**
    199     * @return Index in constant pool of field signature.
    200     */
    201    public final int getSignatureIndex() {
    202        return signature_index;
    203    }
    204
    205
    206    /**
    207     * @param signature_index Index in constant pool of field signature.
    208     */
    209    public final void setSignatureIndex( final int signature_index ) {
    210        this.signature_index = signature_index;
    211    }
    212
    213
    214    /**
    215     * @return Name of object, i.e., method name or field name
    216     */
    217    public final String getName() {
    218        ConstantUtf8 c;
    219        c = (ConstantUtf8) constant_pool.getConstant(name_index, Const.CONSTANT_Utf8);
    220        return c.getBytes();
    221    }
    222
    223
    224    /**
    225     * @return String representation of object's type signature (java style)
    226     */
    227    public final String getSignature() {
    228        ConstantUtf8 c;
    229        c = (ConstantUtf8) constant_pool.getConstant(signature_index, Const.CONSTANT_Utf8);
    230        return c.getBytes();
    231    }
    232
    233
    234    /**
    235     * @return deep copy of this field
    236     */
    237    protected FieldOrMethod copy_( final ConstantPool _constant_pool ) {
    238        FieldOrMethod c = null;
    239
    240        try {
    241          c = (FieldOrMethod)clone();
    242        } catch(final CloneNotSupportedException e) {
    243            // ignored, but will cause NPE ...
    244        }
    245
    246        c.constant_pool    = constant_pool;
    247        c.attributes       = new Attribute[attributes.length];
    248        c.attributes_count = attributes_count; // init deprecated field
    249
    250        for (int i = 0; i < attributes.length; i++) {
    251            c.attributes[i] = attributes[i].copy(constant_pool);
    252        }
    253
    254        return c;
    255    }
    256
    257    /**
    258     * @return Annotations on the field or method
    259     * @since 6.0
    260     */
    261    public AnnotationEntry[] getAnnotationEntries() {
    262        if (annotationEntries == null) {
    263            annotationEntries = AnnotationEntry.createAnnotationEntries(getAttributes());
    264        }
    265
    266        return annotationEntries;
    267    }
    268
    269    /**
    270     * Hunts for a signature attribute on the member and returns its contents.  So where the 'regular' signature
    271     * may be (Ljava/util/Vector;)V the signature attribute may in fact say 'Ljava/lang/Vector&lt;Ljava/lang/String&gt;;'
    272     * Coded for performance - searches for the attribute only when requested - only searches for it once.
    273     * @since 6.0
    274     */
    275    public final String getGenericSignature()
    276    {
    277        if (!searchedForSignatureAttribute)
    278        {
    279            boolean found = false;
    280            for (int i = 0; !found && i < attributes.length; i++)
    281            {
    282                if (attributes[i] instanceof Signature)
    283                {
    284                    signatureAttributeString = ((Signature) attributes[i])
    285                            .getSignature();
    286                    found = true;
    287                }
    288            }
    289            searchedForSignatureAttribute = true;
    290        }
    291        return signatureAttributeString;
    292    }
    293}