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         for (final Attribute attribute : attributes) {
151             attribute.dump(file);
152         }
153     }
154 
155     /**
156      * @return Annotations on the field or method
157      * @since 6.0
158      */
159     public AnnotationEntry[] getAnnotationEntries() {
160         if (annotationEntries == null) {
161             annotationEntries = AnnotationEntry.createAnnotationEntries(getAttributes());
162         }
163 
164         return annotationEntries;
165     }
166 
167     /**
168      * @return Collection of object attributes.
169      */
170     public final Attribute[] getAttributes() {
171         return attributes;
172     }
173 
174     /**
175      * @return Constant pool used by this object.
176      */
177     public final ConstantPool getConstantPool() {
178         return constant_pool;
179     }
180 
181     /**
182      * Hunts for a signature attribute on the member and returns its contents. So where the 'regular' signature may be
183      * (Ljava/util/Vector;)V the signature attribute may in fact say 'Ljava/lang/Vector&lt;Ljava/lang/String&gt;;' Coded for
184      * performance - searches for the attribute only when requested - only searches for it once.
185      *
186      * @since 6.0
187      */
188     public final String getGenericSignature() {
189         if (!searchedForSignatureAttribute) {
190             boolean found = false;
191             for (int i = 0; !found && i < attributes.length; i++) {
192                 if (attributes[i] instanceof Signature) {
193                     signatureAttributeString = ((Signature) attributes[i]).getSignature();
194                     found = true;
195                 }
196             }
197             searchedForSignatureAttribute = true;
198         }
199         return signatureAttributeString;
200     }
201 
202     /**
203      * @return Name of object, i.e., method name or field name
204      */
205     public final String getName() {
206         return constant_pool.getConstantUtf8(name_index).getBytes();
207     }
208 
209     /**
210      * @return Index in constant pool of object's name.
211      */
212     public final int getNameIndex() {
213         return name_index;
214     }
215 
216     /**
217      * @return String representation of object's type signature (Java style)
218      */
219     public final String getSignature() {
220         return constant_pool.getConstantUtf8(signature_index).getBytes();
221     }
222 
223     /**
224      * @return Index in constant pool of field signature.
225      */
226     public final int getSignatureIndex() {
227         return signature_index;
228     }
229 
230     /**
231      * @param attributes Collection of object attributes.
232      */
233     public final void setAttributes(final Attribute[] attributes) {
234         this.attributes = attributes != null ? attributes : Attribute.EMPTY_ARRAY;
235         this.attributes_count = this.attributes.length; // init deprecated field
236     }
237 
238     /**
239      * @param constantPool Constant pool to be used for this object.
240      */
241     public final void setConstantPool(final ConstantPool constantPool) {
242         this.constant_pool = constantPool;
243     }
244 
245     /**
246      * @param nameIndex Index in constant pool of object's name.
247      */
248     public final void setNameIndex(final int nameIndex) {
249         this.name_index = nameIndex;
250     }
251 
252     /**
253      * @param signatureIndex Index in constant pool of field signature.
254      */
255     public final void setSignatureIndex(final int signatureIndex) {
256         this.signature_index = signatureIndex;
257     }
258 }