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