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 027/** 028 * Abstract super class for fields and methods. 029 */ 030public abstract class FieldOrMethod extends AccessFlags implements Cloneable, Node { 031 032 /** 033 * @deprecated (since 6.0) will be made private; do not access directly, use getter/setter 034 */ 035 @java.lang.Deprecated 036 protected int name_index; // Points to field name in constant pool 037 038 /** 039 * @deprecated (since 6.0) will be made private; do not access directly, use getter/setter 040 */ 041 @java.lang.Deprecated 042 protected int signature_index; // Points to encoded signature 043 044 /** 045 * @deprecated (since 6.0) will be made private; do not access directly, use getter/setter 046 */ 047 @java.lang.Deprecated 048 protected Attribute[] attributes; // Collection of attributes 049 050 /** 051 * @deprecated (since 6.0) will be removed (not needed) 052 */ 053 @java.lang.Deprecated 054 protected int attributes_count; // No. of attributes 055 056 // @since 6.0 057 private AnnotationEntry[] annotationEntries; // annotations defined on the field or method 058 059 /** 060 * @deprecated (since 6.0) will be made private; do not access directly, use getter/setter 061 */ 062 @java.lang.Deprecated 063 protected ConstantPool constant_pool; 064 065 private String signatureAttributeString; 066 private boolean searchedForSignatureAttribute; 067 068 FieldOrMethod() { 069 } 070 071 /** 072 * Constructs object from file stream. 073 * 074 * @param file Input stream 075 * @throws IOException if an I/O error occurs. 076 */ 077 protected FieldOrMethod(final DataInput file, final ConstantPool constantPool) throws IOException { 078 this(file.readUnsignedShort(), file.readUnsignedShort(), file.readUnsignedShort(), null, constantPool); 079 final int attributesCount = file.readUnsignedShort(); 080 attributes = new Attribute[attributesCount]; 081 for (int i = 0; i < attributesCount; i++) { 082 attributes[i] = Attribute.readAttribute(file, constantPool); 083 } 084 this.attributes_count = attributesCount; // init deprecated field 085 } 086 087 /** 088 * Constructs object from file stream. 089 * 090 * @param file Input stream 091 * @throws IOException if an I/O error occurs. 092 * @deprecated (6.0) Use {@link #FieldOrMethod(java.io.DataInput, ConstantPool)} instead. 093 */ 094 @java.lang.Deprecated 095 protected FieldOrMethod(final DataInputStream file, final ConstantPool constantPool) throws IOException { 096 this((DataInput) file, constantPool); 097 } 098 099 /** 100 * Initialize from another object. Note that both objects use the same references (shallow copy). Use clone() for a 101 * physical copy. 102 * 103 * @param c Source to copy. 104 */ 105 protected FieldOrMethod(final FieldOrMethod c) { 106 this(c.getAccessFlags(), c.getNameIndex(), c.getSignatureIndex(), c.getAttributes(), c.getConstantPool()); 107 } 108 109 /** 110 * @param accessFlags Access rights of method 111 * @param nameIndex Points to field name in constant pool 112 * @param signatureIndex Points to encoded signature 113 * @param attributes Collection of attributes 114 * @param constantPool Array of constants 115 */ 116 protected FieldOrMethod(final int accessFlags, final int nameIndex, final int signatureIndex, final Attribute[] attributes, 117 final ConstantPool constantPool) { 118 super(accessFlags); 119 this.name_index = nameIndex; 120 this.signature_index = signatureIndex; 121 this.constant_pool = constantPool; 122 setAttributes(attributes); 123 } 124 125 /** 126 * @return deep copy of this field 127 */ 128 protected FieldOrMethod copy_(final ConstantPool constantPool) { 129 try { 130 final FieldOrMethod c = (FieldOrMethod) clone(); 131 c.constant_pool = constantPool; 132 c.attributes = new Attribute[attributes.length]; 133 c.attributes_count = attributes_count; // init deprecated field 134 Arrays.setAll(c.attributes, i -> attributes[i].copy(constantPool)); 135 return c; 136 } catch (final CloneNotSupportedException e) { 137 throw new UnsupportedOperationException(e); 138 } 139 } 140 141 /** 142 * Dump object to file stream on binary format. 143 * 144 * @param file Output file stream 145 * @throws IOException if an I/O error occurs. 146 */ 147 public final void dump(final DataOutputStream file) throws IOException { 148 file.writeShort(super.getAccessFlags()); 149 file.writeShort(name_index); 150 file.writeShort(signature_index); 151 file.writeShort(attributes_count); 152 for (final Attribute attribute : attributes) { 153 attribute.dump(file); 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 * Gets attribute for given tag. 171 * @return Attribute for given tag, null if not found. 172 * Refer to {@link org.apache.bcel.Const#ATTR_UNKNOWN} constants named ATTR_* for possible values. 173 * @since 6.10.0 174 */ 175 @SuppressWarnings("unchecked") 176 public final <T extends Attribute> T getAttribute(final byte tag) { 177 for (final Attribute attribute : getAttributes()) { 178 if (attribute.getTag() == tag) { 179 return (T) attribute; 180 } 181 } 182 return null; 183 } 184 185 /** 186 * @return Collection of object attributes. 187 */ 188 public final Attribute[] getAttributes() { 189 return attributes; 190 } 191 192 /** 193 * @return Constant pool used by this object. 194 */ 195 public final ConstantPool getConstantPool() { 196 return constant_pool; 197 } 198 199 /** 200 * Hunts for a signature attribute on the member and returns its contents. So where the 'regular' signature may be 201 * (Ljava/util/Vector;)V the signature attribute may in fact say 'Ljava/lang/Vector<Ljava/lang/String>;' Coded for 202 * performance - searches for the attribute only when requested - only searches for it once. 203 * 204 * @since 6.0 205 */ 206 public final String getGenericSignature() { 207 if (!searchedForSignatureAttribute) { 208 boolean found = false; 209 for (int i = 0; !found && i < attributes.length; i++) { 210 if (attributes[i] instanceof Signature) { 211 signatureAttributeString = ((Signature) attributes[i]).getSignature(); 212 found = true; 213 } 214 } 215 searchedForSignatureAttribute = true; 216 } 217 return signatureAttributeString; 218 } 219 220 /** 221 * @return Name of object, i.e., method name or field name 222 */ 223 public final String getName() { 224 return constant_pool.getConstantUtf8(name_index).getBytes(); 225 } 226 227 /** 228 * @return Index in constant pool of object's name. 229 */ 230 public final int getNameIndex() { 231 return name_index; 232 } 233 234 /** 235 * @return String representation of object's type signature (Java style) 236 */ 237 public final String getSignature() { 238 return constant_pool.getConstantUtf8(signature_index).getBytes(); 239 } 240 241 /** 242 * @return Index in constant pool of field signature. 243 */ 244 public final int getSignatureIndex() { 245 return signature_index; 246 } 247 248 /** 249 * @param attributes Collection of object attributes. 250 */ 251 public final void setAttributes(final Attribute[] attributes) { 252 this.attributes = attributes != null ? attributes : Attribute.EMPTY_ARRAY; 253 this.attributes_count = this.attributes.length; // init deprecated field 254 } 255 256 /** 257 * @param constantPool Constant pool to be used for this object. 258 */ 259 public final void setConstantPool(final ConstantPool constantPool) { 260 this.constant_pool = constantPool; 261 } 262 263 /** 264 * @param nameIndex Index in constant pool of object's name. 265 */ 266 public final void setNameIndex(final int nameIndex) { 267 this.name_index = nameIndex; 268 } 269 270 /** 271 * @param signatureIndex Index in constant pool of field signature. 272 */ 273 public final void setSignatureIndex(final int signatureIndex) { 274 this.signature_index = signatureIndex; 275 } 276}