001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 * 017 */ 018package org.apache.bcel.classfile; 019 020import java.io.DataInput; 021import java.io.DataInputStream; 022import java.io.DataOutputStream; 023import java.io.IOException; 024import java.util.Arrays; 025 026/** 027 * Abstract super class for fields and methods. 028 * 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 * Construct 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 attributes_count = file.readUnsignedShort(); 080 attributes = new Attribute[attributes_count]; 081 for (int i = 0; i < attributes_count; i++) { 082 attributes[i] = Attribute.readAttribute(file, constantPool); 083 } 084 this.attributes_count = attributes_count; // init deprecated field 085 } 086 087 /** 088 * Construct 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 protected FieldOrMethod(final FieldOrMethod c) { 104 this(c.getAccessFlags(), c.getNameIndex(), c.getSignatureIndex(), c.getAttributes(), c.getConstantPool()); 105 } 106 107 /** 108 * @param access_flags Access rights of method 109 * @param name_index Points to field name in constant pool 110 * @param signature_index Points to encoded signature 111 * @param attributes Collection of attributes 112 * @param constant_pool Array of constants 113 */ 114 protected FieldOrMethod(final int access_flags, final int name_index, final int signature_index, final Attribute[] attributes, 115 final ConstantPool constant_pool) { 116 super(access_flags); 117 this.name_index = name_index; 118 this.signature_index = signature_index; 119 this.constant_pool = constant_pool; 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 = constant_pool; 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(constant_pool)); 133 return c; 134 } catch (final CloneNotSupportedException e) { 135 throw new IllegalStateException(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<Ljava/lang/String>;' 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 constant_pool Constant pool to be used for this object. 242 */ 243 public final void setConstantPool(final ConstantPool constant_pool) { 244 this.constant_pool = constant_pool; 245 } 246 247 /** 248 * @param name_index Index in constant pool of object's name. 249 */ 250 public final void setNameIndex(final int name_index) { 251 this.name_index = name_index; 252 } 253 254 /** 255 * @param signature_index Index in constant pool of field signature. 256 */ 257 public final void setSignatureIndex(final int signature_index) { 258 this.signature_index = signature_index; 259 } 260}