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