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 */ 18 package org.apache.bcel.classfile; 19 20 import java.io.DataInput; 21 import java.io.DataInputStream; 22 import java.io.DataOutputStream; 23 import java.io.IOException; 24 25 import org.apache.bcel.Const; 26 27 /** 28 * Abstract super class for fields and methods. 29 * 30 * @version $Id$ 31 */ 32 public abstract class FieldOrMethod extends AccessFlags implements Cloneable, Node { 33 34 /** 35 * @deprecated (since 6.0) will be made private; do not access directly, use getter/setter 36 */ 37 @java.lang.Deprecated 38 protected int name_index; // Points to field name in constant pool 39 40 /** 41 * @deprecated (since 6.0) will be made private; do not access directly, use getter/setter 42 */ 43 @java.lang.Deprecated 44 protected int signature_index; // Points to encoded signature 45 46 /** 47 * @deprecated (since 6.0) will be made private; do not access directly, use getter/setter 48 */ 49 @java.lang.Deprecated 50 protected Attribute[] attributes; // Collection of attributes 51 52 /** 53 * @deprecated (since 6.0) will be removed (not needed) 54 */ 55 @java.lang.Deprecated 56 protected int attributes_count; // No. of attributes 57 58 // @since 6.0 59 private AnnotationEntry[] annotationEntries; // annotations defined on the field or method 60 61 /** 62 * @deprecated (since 6.0) will be made private; do not access directly, use getter/setter 63 */ 64 @java.lang.Deprecated 65 protected ConstantPool constant_pool; 66 67 private String signatureAttributeString = null; 68 private boolean searchedForSignatureAttribute = false; 69 70 FieldOrMethod() { 71 } 72 73 74 /** 75 * Initialize from another object. Note that both objects use the same 76 * references (shallow copy). Use clone() for a physical copy. 77 */ 78 protected FieldOrMethod(final FieldOrMethod c) { 79 this(c.getAccessFlags(), c.getNameIndex(), c.getSignatureIndex(), c.getAttributes(), c 80 .getConstantPool()); 81 } 82 83 84 /** 85 * Construct object from file stream. 86 * @param file Input stream 87 * @throws IOException 88 * @throws ClassFormatException 89 * @deprecated (6.0) Use {@link #FieldOrMethod(java.io.DataInput, ConstantPool)} instead. 90 */ 91 @java.lang.Deprecated 92 protected FieldOrMethod(final DataInputStream file, final ConstantPool constant_pool) throws IOException, 93 ClassFormatException { 94 this((DataInput) file, constant_pool); 95 } 96 97 /** 98 * Construct object from file stream. 99 * @param file Input stream 100 * @throws IOException 101 * @throws ClassFormatException 102 */ 103 protected FieldOrMethod(final DataInput file, final ConstantPool constant_pool) throws IOException, ClassFormatException { 104 this(file.readUnsignedShort(), file.readUnsignedShort(), file.readUnsignedShort(), null, 105 constant_pool); 106 final int attributes_count = file.readUnsignedShort(); 107 attributes = new Attribute[attributes_count]; 108 for (int i = 0; i < attributes_count; i++) { 109 attributes[i] = Attribute.readAttribute(file, constant_pool); 110 } 111 this.attributes_count = attributes_count; // init deprecated field 112 } 113 114 115 /** 116 * @param access_flags Access rights of method 117 * @param name_index Points to field name in constant pool 118 * @param signature_index Points to encoded signature 119 * @param attributes Collection of attributes 120 * @param constant_pool Array of constants 121 */ 122 protected FieldOrMethod(final int access_flags, final int name_index, final int signature_index, 123 final Attribute[] attributes, final ConstantPool constant_pool) { 124 super(access_flags); 125 this.name_index = name_index; 126 this.signature_index = signature_index; 127 this.constant_pool = constant_pool; 128 setAttributes(attributes); 129 } 130 131 132 /** 133 * Dump object to file stream on binary format. 134 * 135 * @param file Output file stream 136 * @throws IOException 137 */ 138 public final void dump( final DataOutputStream file ) throws IOException { 139 file.writeShort(super.getAccessFlags()); 140 file.writeShort(name_index); 141 file.writeShort(signature_index); 142 file.writeShort(attributes.length); 143 for (final Attribute attribute : attributes) { 144 attribute.dump(file); 145 } 146 } 147 148 149 /** 150 * @return Collection of object attributes. 151 */ 152 public final Attribute[] getAttributes() { 153 return attributes; 154 } 155 156 157 /** 158 * @param attributes Collection of object attributes. 159 */ 160 public final void setAttributes( final Attribute[] attributes ) { 161 this.attributes = attributes; 162 this.attributes_count = attributes != null ? attributes.length : 0; // init deprecated field 163 } 164 165 166 /** 167 * @return Constant pool used by this object. 168 */ 169 public final ConstantPool getConstantPool() { 170 return constant_pool; 171 } 172 173 174 /** 175 * @param constant_pool Constant pool to be used for this object. 176 */ 177 public final void setConstantPool( final ConstantPool constant_pool ) { 178 this.constant_pool = constant_pool; 179 } 180 181 182 /** 183 * @return Index in constant pool of object's name. 184 */ 185 public final int getNameIndex() { 186 return name_index; 187 } 188 189 190 /** 191 * @param name_index Index in constant pool of object's name. 192 */ 193 public final void setNameIndex( final int name_index ) { 194 this.name_index = name_index; 195 } 196 197 198 /** 199 * @return Index in constant pool of field signature. 200 */ 201 public final int getSignatureIndex() { 202 return signature_index; 203 } 204 205 206 /** 207 * @param signature_index Index in constant pool of field signature. 208 */ 209 public final void setSignatureIndex( final int signature_index ) { 210 this.signature_index = signature_index; 211 } 212 213 214 /** 215 * @return Name of object, i.e., method name or field name 216 */ 217 public final String getName() { 218 ConstantUtf8 c; 219 c = (ConstantUtf8) constant_pool.getConstant(name_index, Const.CONSTANT_Utf8); 220 return c.getBytes(); 221 } 222 223 224 /** 225 * @return String representation of object's type signature (java style) 226 */ 227 public final String getSignature() { 228 ConstantUtf8 c; 229 c = (ConstantUtf8) constant_pool.getConstant(signature_index, Const.CONSTANT_Utf8); 230 return c.getBytes(); 231 } 232 233 234 /** 235 * @return deep copy of this field 236 */ 237 protected FieldOrMethod copy_( final ConstantPool _constant_pool ) { 238 FieldOrMethod c = null; 239 240 try { 241 c = (FieldOrMethod)clone(); 242 } catch(final CloneNotSupportedException e) { 243 // ignored, but will cause NPE ... 244 } 245 246 c.constant_pool = constant_pool; 247 c.attributes = new Attribute[attributes.length]; 248 c.attributes_count = attributes_count; // init deprecated field 249 250 for (int i = 0; i < attributes.length; i++) { 251 c.attributes[i] = attributes[i].copy(constant_pool); 252 } 253 254 return c; 255 } 256 257 /** 258 * @return Annotations on the field or method 259 * @since 6.0 260 */ 261 public AnnotationEntry[] getAnnotationEntries() { 262 if (annotationEntries == null) { 263 annotationEntries = AnnotationEntry.createAnnotationEntries(getAttributes()); 264 } 265 266 return annotationEntries; 267 } 268 269 /** 270 * Hunts for a signature attribute on the member and returns its contents. So where the 'regular' signature 271 * may be (Ljava/util/Vector;)V the signature attribute may in fact say 'Ljava/lang/Vector<Ljava/lang/String>;' 272 * Coded for performance - searches for the attribute only when requested - only searches for it once. 273 * @since 6.0 274 */ 275 public final String getGenericSignature() 276 { 277 if (!searchedForSignatureAttribute) 278 { 279 boolean found = false; 280 for (int i = 0; !found && i < attributes.length; i++) 281 { 282 if (attributes[i] instanceof Signature) 283 { 284 signatureAttributeString = ((Signature) attributes[i]) 285 .getSignature(); 286 found = true; 287 } 288 } 289 searchedForSignatureAttribute = true; 290 } 291 return signatureAttributeString; 292 } 293 } 294