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}