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 * @version $Id$ 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 = null; 068 private boolean searchedForSignatureAttribute = false; 069 070 FieldOrMethod() { 071 } 072 073 074 /** 075 * Initialize from another object. Note that both objects use the same 076 * references (shallow copy). Use clone() for a physical copy. 077 */ 078 protected FieldOrMethod(final FieldOrMethod c) { 079 this(c.getAccessFlags(), c.getNameIndex(), c.getSignatureIndex(), c.getAttributes(), c 080 .getConstantPool()); 081 } 082 083 084 /** 085 * Construct object from file stream. 086 * @param file Input stream 087 * @throws IOException 088 * @throws ClassFormatException 089 * @deprecated (6.0) Use {@link #FieldOrMethod(java.io.DataInput, ConstantPool)} instead. 090 */ 091 @java.lang.Deprecated 092 protected FieldOrMethod(final DataInputStream file, final ConstantPool constant_pool) throws IOException, 093 ClassFormatException { 094 this((DataInput) file, constant_pool); 095 } 096 097 /** 098 * Construct object from file stream. 099 * @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_count); 143 if (attributes != null) { 144 for (final Attribute attribute : attributes) { 145 attribute.dump(file); 146 } 147 } 148 } 149 150 151 /** 152 * @return Collection of object attributes. 153 */ 154 public final Attribute[] getAttributes() { 155 return attributes; 156 } 157 158 159 /** 160 * @param attributes Collection of object attributes. 161 */ 162 public final void setAttributes( final Attribute[] attributes ) { 163 this.attributes = attributes; 164 this.attributes_count = attributes != null ? attributes.length : 0; // init deprecated field 165 } 166 167 168 /** 169 * @return Constant pool used by this object. 170 */ 171 public final ConstantPool getConstantPool() { 172 return constant_pool; 173 } 174 175 176 /** 177 * @param constant_pool Constant pool to be used for this object. 178 */ 179 public final void setConstantPool( final ConstantPool constant_pool ) { 180 this.constant_pool = constant_pool; 181 } 182 183 184 /** 185 * @return Index in constant pool of object's name. 186 */ 187 public final int getNameIndex() { 188 return name_index; 189 } 190 191 192 /** 193 * @param name_index Index in constant pool of object's name. 194 */ 195 public final void setNameIndex( final int name_index ) { 196 this.name_index = name_index; 197 } 198 199 200 /** 201 * @return Index in constant pool of field signature. 202 */ 203 public final int getSignatureIndex() { 204 return signature_index; 205 } 206 207 208 /** 209 * @param signature_index Index in constant pool of field signature. 210 */ 211 public final void setSignatureIndex( final int signature_index ) { 212 this.signature_index = signature_index; 213 } 214 215 216 /** 217 * @return Name of object, i.e., method name or field name 218 */ 219 public final String getName() { 220 ConstantUtf8 c; 221 c = (ConstantUtf8) constant_pool.getConstant(name_index, Const.CONSTANT_Utf8); 222 return c.getBytes(); 223 } 224 225 226 /** 227 * @return String representation of object's type signature (java style) 228 */ 229 public final String getSignature() { 230 ConstantUtf8 c; 231 c = (ConstantUtf8) constant_pool.getConstant(signature_index, Const.CONSTANT_Utf8); 232 return c.getBytes(); 233 } 234 235 236 /** 237 * @return deep copy of this field 238 */ 239 protected FieldOrMethod copy_( final ConstantPool _constant_pool ) { 240 FieldOrMethod c = null; 241 242 try { 243 c = (FieldOrMethod)clone(); 244 } catch(final CloneNotSupportedException e) { 245 // ignored, but will cause NPE ... 246 } 247 248 c.constant_pool = constant_pool; 249 c.attributes = new Attribute[attributes.length]; 250 c.attributes_count = attributes_count; // init deprecated field 251 252 for (int i = 0; i < attributes.length; i++) { 253 c.attributes[i] = attributes[i].copy(constant_pool); 254 } 255 256 return c; 257 } 258 259 /** 260 * @return Annotations on the field or method 261 * @since 6.0 262 */ 263 public AnnotationEntry[] getAnnotationEntries() { 264 if (annotationEntries == null) { 265 annotationEntries = AnnotationEntry.createAnnotationEntries(getAttributes()); 266 } 267 268 return annotationEntries; 269 } 270 271 /** 272 * Hunts for a signature attribute on the member and returns its contents. So where the 'regular' signature 273 * may be (Ljava/util/Vector;)V the signature attribute may in fact say 'Ljava/lang/Vector<Ljava/lang/String>;' 274 * Coded for performance - searches for the attribute only when requested - only searches for it once. 275 * @since 6.0 276 */ 277 public final String getGenericSignature() 278 { 279 if (!searchedForSignatureAttribute) 280 { 281 boolean found = false; 282 for (int i = 0; !found && i < attributes.length; i++) 283 { 284 if (attributes[i] instanceof Signature) 285 { 286 signatureAttributeString = ((Signature) attributes[i]) 287 .getSignature(); 288 found = true; 289 } 290 } 291 searchedForSignatureAttribute = true; 292 } 293 return signatureAttributeString; 294 } 295}