FieldOrMethod.java

  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. package org.apache.bcel.generic;

  18. import org.apache.bcel.Const;
  19. import org.apache.bcel.classfile.ConstantCP;
  20. import org.apache.bcel.classfile.ConstantNameAndType;
  21. import org.apache.bcel.classfile.ConstantPool;
  22. import org.apache.bcel.classfile.ConstantUtf8;
  23. import org.apache.bcel.classfile.Utility;

  24. /**
  25.  * Super class for InvokeInstruction and FieldInstruction, since they have some methods in common!
  26.  */
  27. public abstract class FieldOrMethod extends CPInstruction implements LoadClass {

  28.     /**
  29.      * Empty constructor needed for Instruction.readInstruction. Not to be used otherwise.
  30.      */
  31.     FieldOrMethod() {
  32.         // no init
  33.     }

  34.     /**
  35.      * @param index to constant pool
  36.      */
  37.     protected FieldOrMethod(final short opcode, final int index) {
  38.         super(opcode, index);
  39.     }

  40.     /**
  41.      * @return name of the referenced class/interface
  42.      * @deprecated If the instruction references an array class, this method will return "java.lang.Object". For code
  43.      *             generated by Java 1.5, this answer is sometimes wrong (e.g., if the "clone()" method is called on an
  44.      *             array). A better idea is to use the {@link #getReferenceType(ConstantPoolGen)} method, which correctly
  45.      *             distinguishes between class types and array types.
  46.      */
  47.     @Deprecated
  48.     public String getClassName(final ConstantPoolGen cpg) {
  49.         final ConstantPool cp = cpg.getConstantPool();
  50.         final ConstantCP cmr = (ConstantCP) cp.getConstant(super.getIndex());
  51.         final String className = cp.getConstantString(cmr.getClassIndex(), Const.CONSTANT_Class);
  52.         if (className.startsWith("[")) {
  53.             // Turn array classes into java.lang.Object.
  54.             return "java.lang.Object";
  55.         }
  56.         return Utility.pathToPackage(className);
  57.     }

  58.     /**
  59.      * @return type of the referenced class/interface
  60.      * @deprecated If the instruction references an array class, the ObjectType returned will be invalid. Use
  61.      *             getReferenceType() instead.
  62.      */
  63.     @Deprecated
  64.     public ObjectType getClassType(final ConstantPoolGen cpg) {
  65.         return ObjectType.getInstance(getClassName(cpg));
  66.     }

  67.     /**
  68.      * Gets the ObjectType of the method return or field.
  69.      *
  70.      * @return type of the referenced class/interface
  71.      * @throws ClassGenException when the field is (or method returns) an array,
  72.      */
  73.     @Override
  74.     public ObjectType getLoadClassType(final ConstantPoolGen cpg) {
  75.         final ReferenceType rt = getReferenceType(cpg);
  76.         if (rt instanceof ObjectType) {
  77.             return (ObjectType) rt;
  78.         }
  79.         if (rt instanceof ArrayType) {
  80.             return Type.OBJECT;
  81.         }
  82.         throw new ClassGenException(rt.getClass().getCanonicalName() + " " + rt.getSignature() + " does not represent an ObjectType");
  83.     }

  84.     /**
  85.      * @return name of referenced method/field.
  86.      */
  87.     public String getName(final ConstantPoolGen cpg) {
  88.         final ConstantPool cp = cpg.getConstantPool();
  89.         final ConstantCP cmr = (ConstantCP) cp.getConstant(super.getIndex());
  90.         final ConstantNameAndType cnat = (ConstantNameAndType) cp.getConstant(cmr.getNameAndTypeIndex());
  91.         return ((ConstantUtf8) cp.getConstant(cnat.getNameIndex())).getBytes();
  92.     }

  93.     /**
  94.      * Gets the reference type representing the class, interface, or array class referenced by the instruction.
  95.      *
  96.      * @param cpg the ConstantPoolGen used to create the instruction
  97.      * @return an ObjectType (if the referenced class type is a class or interface), or an ArrayType (if the referenced
  98.      *         class type is an array class)
  99.      */
  100.     public ReferenceType getReferenceType(final ConstantPoolGen cpg) {
  101.         final ConstantPool cp = cpg.getConstantPool();
  102.         final ConstantCP cmr = (ConstantCP) cp.getConstant(super.getIndex());
  103.         String className = cp.getConstantString(cmr.getClassIndex(), Const.CONSTANT_Class);
  104.         if (className.startsWith("[")) {
  105.             return (ArrayType) Type.getType(className);
  106.         }
  107.         className = Utility.pathToPackage(className);
  108.         return ObjectType.getInstance(className);
  109.     }

  110.     /**
  111.      * @return signature of referenced method/field.
  112.      */
  113.     public String getSignature(final ConstantPoolGen cpg) {
  114.         final ConstantPool cp = cpg.getConstantPool();
  115.         final ConstantCP cmr = (ConstantCP) cp.getConstant(super.getIndex());
  116.         final ConstantNameAndType cnat = (ConstantNameAndType) cp.getConstant(cmr.getNameAndTypeIndex());
  117.         return ((ConstantUtf8) cp.getConstant(cnat.getSignatureIndex())).getBytes();
  118.     }
  119. }