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