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