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