    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 */
    031public abstract class FieldOrMethod extends AccessFlags implements Cloneable, Node {
    032
    033    /**
    034     * @deprecated (since 6.0) will be made private; do not access directly, use getter/setter
    035     */
    036    @java.lang.Deprecated
    037    protected int name_index; // Points to field name in constant pool
    038
    039    /**
    040     * @deprecated (since 6.0) will be made private; do not access directly, use getter/setter
    041     */
    042    @java.lang.Deprecated
    043    protected int signature_index; // Points to encoded signature
    044
    045    /**
    046     * @deprecated (since 6.0) will be made private; do not access directly, use getter/setter
    047     */
    048    @java.lang.Deprecated
    049    protected Attribute[] attributes; // Collection of attributes
    050
    051    /**
    052     * @deprecated (since 6.0) will be removed (not needed)
    053     */
    054    @java.lang.Deprecated
    055    protected int attributes_count; // No. of attributes
    056
    057    // @since 6.0
    058    private AnnotationEntry[] annotationEntries; // annotations defined on the field or method
    059
    060    /**
    061     * @deprecated (since 6.0) will be made private; do not access directly, use getter/setter
    062     */
    063    @java.lang.Deprecated
    064    protected ConstantPool constant_pool;
    065
    066    private String signatureAttributeString = null;
    067    private boolean searchedForSignatureAttribute = false;
    068
    069    FieldOrMethod() {
    070    }
    071
    072
    073    /**
    074     * Initialize from another object. Note that both objects use the same
    075     * references (shallow copy). Use clone() for a physical copy.
    076     */
    077    protected FieldOrMethod(final FieldOrMethod c) {
    078        this(c.getAccessFlags(), c.getNameIndex(), c.getSignatureIndex(), c.getAttributes(), c
    079                .getConstantPool());
    080    }
    081
    082
    083    /**
    084     * Construct object from file stream.
    085     * @param file Input stream
    086     * @throws IOException
    087     * @throws ClassFormatException
    088     * @deprecated (6.0) Use {@link #FieldOrMethod(java.io.DataInput, ConstantPool)} instead.
    089     */
    090    @java.lang.Deprecated
    091    protected FieldOrMethod(final DataInputStream file, final ConstantPool constant_pool) throws IOException,
    092            ClassFormatException {
    093        this((DataInput) file, constant_pool);
    094    }
    095
    096    /**
    097     * Construct object from file stream.
    098     * @param file Input stream
    099     * @throws IOException
    100     * @throws ClassFormatException
    101     */
    102    protected FieldOrMethod(final DataInput file, final ConstantPool constant_pool) throws IOException, ClassFormatException {
    103        this(file.readUnsignedShort(), file.readUnsignedShort(), file.readUnsignedShort(), null,
    104                constant_pool);
    105        final int attributes_count = file.readUnsignedShort();
    106        attributes = new Attribute[attributes_count];
    107        for (int i = 0; i < attributes_count; i++) {
    108            attributes[i] = Attribute.readAttribute(file, constant_pool);
    109        }
    110        this.attributes_count = attributes_count; // init deprecated field
    111    }
    112
    113
    114    /**
    115     * @param access_flags Access rights of method
    116     * @param name_index Points to field name in constant pool
    117     * @param signature_index Points to encoded signature
    118     * @param attributes Collection of attributes
    119     * @param constant_pool Array of constants
    120     */
    121    protected FieldOrMethod(final int access_flags, final int name_index, final int signature_index,
    122            final Attribute[] attributes, final ConstantPool constant_pool) {
    123        super(access_flags);
    124        this.name_index = name_index;
    125        this.signature_index = signature_index;
    126        this.constant_pool = constant_pool;
    127        setAttributes(attributes);
    128    }
    129
    130
    131    /**
    132     * Dump object to file stream on binary format.
    133     *
    134     * @param file Output file stream
    135     * @throws IOException
    136     */
    137    public final void dump(final DataOutputStream file) throws IOException {
    138        file.writeShort(super.getAccessFlags());
    139        file.writeShort(name_index);
    140        file.writeShort(signature_index);
    141        file.writeShort(attributes_count);
    142        if (attributes != null) {
    143            for (final Attribute attribute : attributes) {
    144                attribute.dump(file);
    145            }
    146        }
    147    }
    148
    149
    150    /**
    151     * @return Collection of object attributes.
    152     */
    153    public final Attribute[] getAttributes() {
    154        return attributes;
    155    }
    156
    157
    158    /**
    159     * @param attributes Collection of object attributes.
    160     */
    161    public final void setAttributes( final Attribute[] attributes ) {
    162        this.attributes = attributes;
    163        this.attributes_count = attributes != null ? attributes.length : 0; // init deprecated field
    164    }
    165
    166
    167    /**
    168     * @return Constant pool used by this object.
    169     */
    170    public final ConstantPool getConstantPool() {
    171        return constant_pool;
    172    }
    173
    174
    175    /**
    176     * @param constant_pool Constant pool to be used for this object.
    177     */
    178    public final void setConstantPool( final ConstantPool constant_pool ) {
    179        this.constant_pool = constant_pool;
    180    }
    181
    182
    183    /**
    184     * @return Index in constant pool of object's name.
    185     */
    186    public final int getNameIndex() {
    187        return name_index;
    188    }
    189
    190
    191    /**
    192     * @param name_index Index in constant pool of object's name.
    193     */
    194    public final void setNameIndex( final int name_index ) {
    195        this.name_index = name_index;
    196    }
    197
    198
    199    /**
    200     * @return Index in constant pool of field signature.
    201     */
    202    public final int getSignatureIndex() {
    203        return signature_index;
    204    }
    205
    206
    207    /**
    208     * @param signature_index Index in constant pool of field signature.
    209     */
    210    public final void setSignatureIndex( final int signature_index ) {
    211        this.signature_index = signature_index;
    212    }
    213
    214
    215    /**
    216     * @return Name of object, i.e., method name or field name
    217     */
    218    public final String getName() {
    219        ConstantUtf8 c;
    220        c = (ConstantUtf8) constant_pool.getConstant(name_index, Const.CONSTANT_Utf8);
    221        return c.getBytes();
    222    }
    223
    224
    225    /**
    226     * @return String representation of object's type signature (java style)
    227     */
    228    public final String getSignature() {
    229        ConstantUtf8 c;
    230        c = (ConstantUtf8) constant_pool.getConstant(signature_index, Const.CONSTANT_Utf8);
    231        return c.getBytes();
    232    }
    233
    234
    235    /**
    236     * @return deep copy of this field
    237     */
    238    protected FieldOrMethod copy_( final ConstantPool _constant_pool ) {
    239        FieldOrMethod c = null;
    240
    241        try {
    242          c = (FieldOrMethod)clone();
    243        } catch(final CloneNotSupportedException e) {
    244            // ignored, but will cause NPE ...
    245        }
    246
    247        c.constant_pool    = constant_pool;
    248        c.attributes       = new Attribute[attributes.length];
    249        c.attributes_count = attributes_count; // init deprecated field
    250
    251        for (int i = 0; i < attributes.length; i++) {
    252            c.attributes[i] = attributes[i].copy(constant_pool);
    253        }
    254
    255        return c;
    256    }
    257
    258    /**
    259     * @return Annotations on the field or method
    260     * @since 6.0
    261     */
    262    public AnnotationEntry[] getAnnotationEntries() {
    263        if (annotationEntries == null) {
    264            annotationEntries = AnnotationEntry.createAnnotationEntries(getAttributes());
    265        }
    266
    267        return annotationEntries;
    268    }
    269
    270    /**
    271     * Hunts for a signature attribute on the member and returns its contents.  So where the 'regular' signature
    272     * may be (Ljava/util/Vector;)V the signature attribute may in fact say 'Ljava/lang/Vector&lt;Ljava/lang/String&gt;;'
    273     * Coded for performance - searches for the attribute only when requested - only searches for it once.
    274     * @since 6.0
    275     */
    276    public final String getGenericSignature()
    277    {
    278        if (!searchedForSignatureAttribute)
    279        {
    280            boolean found = false;
    281            for (int i = 0; !found && i < attributes.length; i++)
    282            {
    283                if (attributes[i] instanceof Signature)
    284                {
    285                    signatureAttributeString = ((Signature) attributes[i])
    286                            .getSignature();
    287                    found = true;
    288                }
    289            }
    290            searchedForSignatureAttribute = true;
    291        }
    292        return signatureAttributeString;
    293    }
    294}