View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   https://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.bcel.classfile;
20  
21  import java.io.DataInput;
22  import java.io.DataInputStream;
23  import java.io.DataOutputStream;
24  import java.io.IOException;
25  import java.util.Arrays;
26  
27  import org.apache.bcel.util.Args;
28  
29  /**
30   * Abstract super class for fields and methods.
31   */
32  public abstract class FieldOrMethod extends AccessFlags implements Cloneable, Node {
33  
34      /**
35       * @deprecated (since 6.0) will be made private; do not access directly, use getter/setter.
36       */
37      @java.lang.Deprecated
38      protected int name_index; // Points to field name in constant pool
39  
40      /**
41       * @deprecated (since 6.0) will be made private; do not access directly, use getter/setter.
42       */
43      @java.lang.Deprecated
44      protected int signature_index; // Points to encoded signature
45  
46      /**
47       * @deprecated (since 6.0) will be made private; do not access directly, use getter/setter.
48       */
49      @java.lang.Deprecated
50      protected Attribute[] attributes; // Collection of attributes
51  
52      /**
53       * @deprecated (since 6.0) will be removed (not needed)
54       */
55      @java.lang.Deprecated
56      protected int attributes_count; // No. of attributes
57  
58      // @since 6.0
59      private AnnotationEntry[] annotationEntries; // annotations defined on the field or method
60  
61      /**
62       * @deprecated (since 6.0) will be made private; do not access directly, use getter/setter.
63       */
64      @java.lang.Deprecated
65      protected ConstantPool constant_pool;
66  
67      private String signatureAttributeString;
68      private boolean searchedForSignatureAttribute;
69  
70      FieldOrMethod() {
71      }
72  
73      /**
74       * Constructs object from file stream.
75       *
76       * @param file Input stream.
77       * @param constantPool The constant pool.
78       * @throws IOException Thrown if an I/O error occurs.
79       */
80      protected FieldOrMethod(final DataInput file, final ConstantPool constantPool) throws IOException {
81          this(file.readUnsignedShort(), file.readUnsignedShort(), file.readUnsignedShort(), null, constantPool);
82          final int attributesCount = file.readUnsignedShort();
83          attributes = new Attribute[attributesCount];
84          for (int i = 0; i < attributesCount; i++) {
85              attributes[i] = Attribute.readAttribute(file, constantPool);
86          }
87          this.attributes_count = attributesCount; // init deprecated field
88      }
89  
90      /**
91       * Constructs object from file stream.
92       *
93       * @param file Input stream.
94       * @param constantPool The constant pool.
95       * @throws IOException Thrown if an I/O error occurs.
96       * @deprecated (6.0) Use {@link #FieldOrMethod(java.io.DataInput, ConstantPool)} instead.
97       */
98      @java.lang.Deprecated
99      protected FieldOrMethod(final DataInputStream file, final ConstantPool constantPool) throws IOException {
100         this((DataInput) file, constantPool);
101     }
102 
103     /**
104      * Initialize from another object. Note that both objects use the same references (shallow copy). Use clone() for a
105      * physical copy.
106      *
107      * @param c Source to copy.
108      */
109     protected FieldOrMethod(final FieldOrMethod c) {
110         this(c.getAccessFlags(), c.getNameIndex(), c.getSignatureIndex(), c.getAttributes(), c.getConstantPool());
111     }
112 
113     /**
114      * Constructs a FieldOrMethod.
115      *
116      * @param accessFlags Access rights of method.
117      * @param nameIndex Points to field name in constant pool.
118      * @param signatureIndex Points to encoded signature.
119      * @param attributes Collection of attributes.
120      * @param constantPool Array of constants.
121      */
122     protected FieldOrMethod(final int accessFlags, final int nameIndex, final int signatureIndex, final Attribute[] attributes,
123         final ConstantPool constantPool) {
124         super(accessFlags);
125         this.name_index = nameIndex;
126         this.signature_index = signatureIndex;
127         this.constant_pool = constantPool;
128         setAttributes(attributes);
129     }
130 
131     /**
132      * Creates a deep copy of this field.
133      *
134      * @param constantPool The constant pool.
135      * @return deep copy of this field.
136      */
137     protected FieldOrMethod copy_(final ConstantPool constantPool) {
138         try {
139             final FieldOrMethod c = (FieldOrMethod) clone();
140             c.constant_pool = constantPool;
141             c.attributes = new Attribute[attributes.length];
142             c.attributes_count = attributes_count; // init deprecated field
143             Arrays.setAll(c.attributes, i -> attributes[i].copy(constantPool));
144             return c;
145         } catch (final CloneNotSupportedException e) {
146             throw new UnsupportedOperationException(e);
147         }
148     }
149 
150     /**
151      * Dumps object to file stream on binary format.
152      *
153      * @param file Output file stream.
154      * @throws IOException Thrown if an I/O error occurs.
155      */
156     public final void dump(final DataOutputStream file) throws IOException {
157         file.writeShort(super.getAccessFlags());
158         file.writeShort(name_index);
159         file.writeShort(signature_index);
160         file.writeShort(Args.requireU2(attributes_count, "attributes_count"));
161         for (final Attribute attribute : attributes) {
162             attribute.dump(file);
163         }
164     }
165 
166     /**
167      * Gets annotations on the field or method.
168      *
169      * @return Annotations on the field or method.
170      * @since 6.0
171      */
172     public AnnotationEntry[] getAnnotationEntries() {
173         if (annotationEntries == null) {
174             annotationEntries = AnnotationEntry.createAnnotationEntries(getAttributes());
175         }
176 
177         return annotationEntries;
178     }
179 
180     /**
181      * Gets attribute for given tag.
182      *
183      * @param <T> The attribute type.
184      * @param tag The attribute tag.
185      * @return Attribute for given tag, null if not found.
186      * Refer to {@link org.apache.bcel.Const#ATTR_UNKNOWN} constants named ATTR_* for possible values.
187      * @since 6.10.0
188      */
189     @SuppressWarnings("unchecked")
190     public final <T extends Attribute> T getAttribute(final byte tag) {
191         for (final Attribute attribute : getAttributes()) {
192             if (attribute.getTag() == tag) {
193                 return (T) attribute;
194             }
195         }
196         return null;
197     }
198 
199     /**
200      * Gets the collection of object attributes.
201      *
202      * @return Collection of object attributes.
203      */
204     public final Attribute[] getAttributes() {
205         return attributes;
206     }
207 
208     /**
209      * Gets the constant pool used by this object.
210      *
211      * @return Constant pool used by this object.
212      */
213     public final ConstantPool getConstantPool() {
214         return constant_pool;
215     }
216 
217     /**
218      * Hunts for a signature attribute on the member and returns its contents. So where the 'regular' signature may be
219      * (Ljava/util/Vector;)V the signature attribute may in fact say 'Ljava/lang/Vector&lt;Ljava/lang/String&gt;;' Coded for
220      * performance - searches for the attribute only when requested - only searches for it once.
221      *
222      * @return The generic signature.
223      * @since 6.0
224      */
225     public final String getGenericSignature() {
226         if (!searchedForSignatureAttribute) {
227             boolean found = false;
228             for (int i = 0; !found && i < attributes.length; i++) {
229                 if (attributes[i] instanceof Signature) {
230                     signatureAttributeString = ((Signature) attributes[i]).getSignature();
231                     found = true;
232                 }
233             }
234             searchedForSignatureAttribute = true;
235         }
236         return signatureAttributeString;
237     }
238 
239     /**
240      * Gets the name of object.
241      *
242      * @return Name of object, that is, method name or field name.
243      */
244     public final String getName() {
245         return constant_pool.getConstantUtf8(name_index).getBytes();
246     }
247 
248     /**
249      * Gets the index in constant pool of object's name.
250      *
251      * @return Index in constant pool of object's name.
252      */
253     public final int getNameIndex() {
254         return name_index;
255     }
256 
257     /**
258      * Gets the string representation of object's type signature.
259      *
260      * @return String representation of object's type signature (Java style).
261      */
262     public final String getSignature() {
263         return constant_pool.getConstantUtf8(signature_index).getBytes();
264     }
265 
266     /**
267      * Gets the index in constant pool of field signature.
268      *
269      * @return Index in constant pool of field signature.
270      */
271     public final int getSignatureIndex() {
272         return signature_index;
273     }
274 
275     /**
276      * Sets the collection of object attributes.
277      *
278      * @param attributes Collection of object attributes.
279      */
280     public final void setAttributes(final Attribute[] attributes) {
281         this.attributes = attributes != null ? attributes : Attribute.EMPTY_ARRAY;
282         this.attributes_count = this.attributes.length; // init deprecated field
283     }
284 
285     /**
286      * Sets the constant pool to be used for this object.
287      *
288      * @param constantPool Constant pool to be used for this object.
289      */
290     public final void setConstantPool(final ConstantPool constantPool) {
291         this.constant_pool = constantPool;
292     }
293 
294     /**
295      * Sets the index in constant pool of object's name.
296      *
297      * @param nameIndex Index in constant pool of object's name.
298      */
299     public final void setNameIndex(final int nameIndex) {
300         this.name_index = nameIndex;
301     }
302 
303     /**
304      * Sets the index in constant pool of field signature.
305      *
306      * @param signatureIndex Index in constant pool of field signature.
307      */
308     public final void setSignatureIndex(final int signatureIndex) {
309         this.signature_index = signatureIndex;
310     }
311 }