001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * https://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, 013 * software distributed under the License is distributed on an 014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 015 * KIND, either express or implied. See the License for the 016 * specific language governing permissions and limitations 017 * under the License. 018 */ 019package org.apache.bcel.classfile; 020 021import java.io.DataInput; 022import java.io.DataInputStream; 023import java.io.DataOutputStream; 024import java.io.IOException; 025import java.util.Arrays; 026 027import org.apache.bcel.util.Args; 028 029/** 030 * Abstract super class for fields and methods. 031 */ 032public abstract class FieldOrMethod extends AccessFlags implements Cloneable, Node { 033 034 /** 035 * @deprecated (since 6.0) will be made private; do not access directly, use getter/setter. 036 */ 037 @java.lang.Deprecated 038 protected int name_index; // Points to field name in constant pool 039 040 /** 041 * @deprecated (since 6.0) will be made private; do not access directly, use getter/setter. 042 */ 043 @java.lang.Deprecated 044 protected int signature_index; // Points to encoded signature 045 046 /** 047 * @deprecated (since 6.0) will be made private; do not access directly, use getter/setter. 048 */ 049 @java.lang.Deprecated 050 protected Attribute[] attributes; // Collection of attributes 051 052 /** 053 * @deprecated (since 6.0) will be removed (not needed) 054 */ 055 @java.lang.Deprecated 056 protected int attributes_count; // No. of attributes 057 058 // @since 6.0 059 private AnnotationEntry[] annotationEntries; // annotations defined on the field or method 060 061 /** 062 * @deprecated (since 6.0) will be made private; do not access directly, use getter/setter. 063 */ 064 @java.lang.Deprecated 065 protected ConstantPool constant_pool; 066 067 private String signatureAttributeString; 068 private boolean searchedForSignatureAttribute; 069 070 FieldOrMethod() { 071 } 072 073 /** 074 * Constructs object from file stream. 075 * 076 * @param file Input stream. 077 * @param constantPool The constant pool. 078 * @throws IOException Thrown if an I/O error occurs. 079 */ 080 protected FieldOrMethod(final DataInput file, final ConstantPool constantPool) throws IOException { 081 this(file.readUnsignedShort(), file.readUnsignedShort(), file.readUnsignedShort(), null, constantPool); 082 final int attributesCount = file.readUnsignedShort(); 083 attributes = new Attribute[attributesCount]; 084 for (int i = 0; i < attributesCount; i++) { 085 attributes[i] = Attribute.readAttribute(file, constantPool); 086 } 087 this.attributes_count = attributesCount; // init deprecated field 088 } 089 090 /** 091 * Constructs object from file stream. 092 * 093 * @param file Input stream. 094 * @param constantPool The constant pool. 095 * @throws IOException Thrown if an I/O error occurs. 096 * @deprecated (6.0) Use {@link #FieldOrMethod(java.io.DataInput, ConstantPool)} instead. 097 */ 098 @java.lang.Deprecated 099 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}