1 /*
   2  * Copyright (c) 2017, 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  * @version $Id: FieldOrMethod.java 1750029 2016-06-23 22:14:38Z sebb $
  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 
  48     FieldOrMethod() {
  49     }
  50 
  51     /**
  52      * Initialize from another object. Note that both objects use the same
  53      * references (shallow copy). Use clone() for a physical copy.
  54      */
  55     protected FieldOrMethod(final FieldOrMethod c) {
  56         this(c.getAccessFlags(), c.getNameIndex(), c.getSignatureIndex(),
  57                 c.getAttributes(), c.getConstantPool());
  58     }
  59 
  60     /**
  61      * Construct object from file stream.
  62      *
  63      * @param file Input stream
  64      * @throws IOException
  65      * @throws ClassFormatException
  66      * @deprecated (6.0) Use
  67      * {@link #FieldOrMethod(java.io.DataInput, ConstantPool)} instead.
  68      */
  69     @java.lang.Deprecated
  70     protected FieldOrMethod(final DataInputStream file,
  71             final ConstantPool constant_pool) throws IOException,
  72             ClassFormatException {
  73         this((DataInput) file, constant_pool);
  74     }
  75 
  76     /**
  77      * Construct object from file stream.
  78      *
  79      * @param file Input stream
  80      * @throws IOException
  81      * @throws ClassFormatException
  82      */
  83     protected FieldOrMethod(final DataInput file,
  84             final ConstantPool constant_pool) throws IOException, ClassFormatException {
  85         this(file.readUnsignedShort(), file.readUnsignedShort(), file.readUnsignedShort(), null,
  86                 constant_pool);
  87         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     }
  93 
  94     /**
  95      * @param access_flags Access rights of method
  96      * @param name_index Points to field name in constant pool
  97      * @param signature_index Points to encoded signature
  98      * @param attributes Collection of attributes
  99      * @param constant_pool Array of constants
 100      */
 101     protected FieldOrMethod(final int access_flags, final int name_index, final int signature_index,
 102             final Attribute[] attributes, final ConstantPool constant_pool) {
 103         super(access_flags);
 104         this.name_index = name_index;
 105         this.signature_index = signature_index;
 106         this.constant_pool = constant_pool;
 107         setAttributes(attributes);
 108     }
 109 
 110     /**
 111      * Dump object to file stream on binary format.
 112      *
 113      * @param file Output file stream
 114      * @throws IOException
 115      */
 116     public final void dump(final DataOutputStream file) throws IOException {
 117         file.writeShort(super.getAccessFlags());
 118         file.writeShort(name_index);
 119         file.writeShort(signature_index);
 120         file.writeShort(attributes_count);
 121 
 122         for(int i=0; i < attributes_count; i++) {
 123             attributes[i].dump(file);
 124         }
 125     }
 126 
 127     /**
 128      * @return Collection of object attributes.
 129      */
 130     public final Attribute[] getAttributes() {
 131         return attributes;
 132     }
 133 
 134     /**
 135      * @param attributes Collection of object attributes.
 136      */
 137     public final void setAttributes(final Attribute[] attributes) {
 138         this.attributes = attributes;
 139         this.attributes_count = attributes != null ? attributes.length : 0;
 140     }
 141 
 142     /**
 143      * @return Constant pool used by this object.
 144      */
 145     public final ConstantPool getConstantPool() {
 146         return constant_pool;
 147     }
 148 
 149     /**
 150      * @param constant_pool Constant pool to be used for this object.
 151      */
 152     public final void setConstantPool(final ConstantPool constant_pool) {
 153         this.constant_pool = constant_pool;
 154     }
 155 
 156     /**
 157      * @return Index in constant pool of object's name.
 158      */
 159     public final int getNameIndex() {
 160         return name_index;
 161     }
 162 
 163     /**
 164      * @param name_index Index in constant pool of object's name.
 165      */
 166     public final void setNameIndex(final int name_index) {
 167         this.name_index = name_index;
 168     }
 169 
 170     /**
 171      * @return Index in constant pool of field signature.
 172      */
 173     public final int getSignatureIndex() {
 174         return signature_index;
 175     }
 176 
 177     /**
 178      * @param signature_index Index in constant pool of field signature.
 179      */
 180     public final void setSignatureIndex(final int signature_index) {
 181         this.signature_index = signature_index;
 182     }
 183 
 184     /**
 185      * @return Name of object, i.e., method name or field name
 186      */
 187     public final String getName() {
 188         ConstantUtf8 c;
 189         c = (ConstantUtf8) constant_pool.getConstant(name_index, Const.CONSTANT_Utf8);
 190         return c.getBytes();
 191     }
 192 
 193     /**
 194      * @return String representation of object's type signature (java style)
 195      */
 196     public final String getSignature() {
 197         ConstantUtf8 c;
 198         c = (ConstantUtf8) constant_pool.getConstant(signature_index, Const.CONSTANT_Utf8);
 199         return c.getBytes();
 200     }
 201 
 202     /**
 203      * @return deep copy of this field
 204      */
 205     protected FieldOrMethod copy_(final ConstantPool _constant_pool) {
 206         FieldOrMethod c = null;
 207 
 208         try {
 209             c = (FieldOrMethod) clone();
 210         } catch (final CloneNotSupportedException e) {
 211             // ignored, but will cause NPE ...
 212         }
 213 
 214         c.constant_pool = constant_pool;
 215         c.attributes = new Attribute[attributes_count];
 216         c.attributes_count = attributes_count;
 217 
 218         for (int i = 0; i < attributes_count; i++) {
 219             c.attributes[i] = attributes[i].copy(constant_pool);
 220         }
 221 
 222         return c;
 223     }
 224 
 225     /**
 226      * @return Annotations on the field or method
 227      * @since 6.0
 228      */
 229     public AnnotationEntry[] getAnnotationEntries() {
 230         if (annotationEntries == null) {
 231             annotationEntries = AnnotationEntry.createAnnotationEntries(getAttributes());
 232         }
 233 
 234         return annotationEntries;
 235     }
 236 
 237     /**
 238      * Hunts for a signature attribute on the member and returns its contents.
 239      * So where the 'regular' signature may be (Ljava/util/Vector;)V the
 240      * signature attribute may in fact say
 241      * 'Ljava/lang/Vector&lt;Ljava/lang/String&gt;;' Coded for performance -
 242      * searches for the attribute only when requested - only searches for it
 243      * once.
 244      *
 245      * @since 6.0
 246      */
 247     public final String getGenericSignature() {
 248         if (!searchedForSignatureAttribute) {
 249             boolean found = false;
 250             for (int i = 0; !found && i < attributes.length; i++) {
 251                 if (attributes[i] instanceof Signature) {
 252                     signatureAttributeString = ((Signature) attributes[i])
 253                             .getSignature();
 254                     found = true;
 255                 }
 256             }
 257             searchedForSignatureAttribute = true;
 258         }
 259         return signatureAttributeString;
 260     }
 261 }