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<Ljava/lang/String>;' 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 }