001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * https://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, 013 * software distributed under the License is distributed on an 014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 015 * KIND, either express or implied. See the License for the 016 * specific language governing permissions and limitations 017 * under the License. 018 */ 019package org.apache.bcel.generic; 020 021import org.apache.bcel.Const; 022import org.apache.bcel.classfile.ConstantCP; 023import org.apache.bcel.classfile.ConstantNameAndType; 024import org.apache.bcel.classfile.ConstantPool; 025import org.apache.bcel.classfile.ConstantUtf8; 026import org.apache.bcel.classfile.Utility; 027 028/** 029 * Super class for InvokeInstruction and FieldInstruction, since they have some methods in common! 030 */ 031public abstract class FieldOrMethod extends CPInstruction implements LoadClass { 032 033 /** 034 * Empty constructor needed for Instruction.readInstruction. Not to be used otherwise. 035 */ 036 FieldOrMethod() { 037 // no init 038 } 039 040 /** 041 * Constructs a FieldOrMethod. 042 * 043 * @param opcode the opcode. 044 * @param index to constant pool. 045 */ 046 protected FieldOrMethod(final short opcode, final int index) { 047 super(opcode, index); 048 } 049 050 /** 051 * Gets the name of the referenced class/interface. 052 * 053 * @param cpg the constant pool generator. 054 * @return name of the referenced class/interface. 055 * @deprecated If the instruction references an array class, this method will return "java.lang.Object". For code 056 * generated by Java 1.5, this answer is sometimes wrong (for example, if the "clone()" method is called on an 057 * array). A better idea is to use the {@link #getReferenceType(ConstantPoolGen)} method, which correctly 058 * distinguishes between class types and array types. 059 */ 060 @Deprecated 061 public String getClassName(final ConstantPoolGen cpg) { 062 final ConstantPool cp = cpg.getConstantPool(); 063 final ConstantCP cmr = (ConstantCP) cp.getConstant(super.getIndex()); 064 final String className = cp.getConstantString(cmr.getClassIndex(), Const.CONSTANT_Class); 065 if (className.startsWith("[")) { 066 // Turn array classes into java.lang.Object. 067 return "java.lang.Object"; 068 } 069 return Utility.pathToPackage(className); 070 } 071 072 /** 073 * Gets the type of the referenced class/interface. 074 * 075 * @param cpg the constant pool generator. 076 * @return type of the referenced class/interface. 077 * @deprecated If the instruction references an array class, the ObjectType returned will be invalid. Use 078 * getReferenceType() instead. 079 */ 080 @Deprecated 081 public ObjectType getClassType(final ConstantPoolGen cpg) { 082 return ObjectType.getInstance(getClassName(cpg)); 083 } 084 085 /** 086 * Gets the ObjectType of the method return or field. 087 * 088 * @param cpg the constant pool generator. 089 * @return type of the referenced class/interface. 090 * @throws ClassGenException when the field is (or method returns) an array. 091 */ 092 @Override 093 public ObjectType getLoadClassType(final ConstantPoolGen cpg) { 094 final ReferenceType rt = getReferenceType(cpg); 095 if (rt instanceof ObjectType) { 096 return (ObjectType) rt; 097 } 098 if (rt instanceof ArrayType) { 099 return Type.OBJECT; 100 } 101 throw new ClassGenException(rt.getClass().getCanonicalName() + " " + rt.getSignature() + " does not represent an ObjectType"); 102 } 103 104 /** 105 * Gets the name of referenced method or field. 106 * 107 * @param cpg the constant pool generator. 108 * @return name of referenced method/field. 109 */ 110 public String getName(final ConstantPoolGen cpg) { 111 final ConstantPool cp = cpg.getConstantPool(); 112 final ConstantCP cmr = (ConstantCP) cp.getConstant(super.getIndex()); 113 final ConstantNameAndType cnat = (ConstantNameAndType) cp.getConstant(cmr.getNameAndTypeIndex()); 114 return ((ConstantUtf8) cp.getConstant(cnat.getNameIndex())).getBytes(); 115 } 116 117 /** 118 * Gets the reference type representing the class, interface, or array class referenced by the instruction. 119 * 120 * @param cpg the ConstantPoolGen used to create the instruction. 121 * @return an ObjectType (if the referenced class type is a class or interface), or an ArrayType (if the referenced 122 * class type is an array class) 123 */ 124 public ReferenceType getReferenceType(final ConstantPoolGen cpg) { 125 final ConstantPool cp = cpg.getConstantPool(); 126 final ConstantCP cmr = (ConstantCP) cp.getConstant(super.getIndex()); 127 String className = cp.getConstantString(cmr.getClassIndex(), Const.CONSTANT_Class); 128 if (className.startsWith("[")) { 129 return (ArrayType) Type.getType(className); 130 } 131 className = Utility.pathToPackage(className); 132 return ObjectType.getInstance(className); 133 } 134 135 /** 136 * Gets the signature of referenced method or field. 137 * 138 * @param cpg the constant pool generator. 139 * @return signature of referenced method/field. 140 */ 141 public String getSignature(final ConstantPoolGen cpg) { 142 final ConstantPool cp = cpg.getConstantPool(); 143 final ConstantCP cmr = (ConstantCP) cp.getConstant(super.getIndex()); 144 final ConstantNameAndType cnat = (ConstantNameAndType) cp.getConstant(cmr.getNameAndTypeIndex()); 145 return ((ConstantUtf8) cp.getConstant(cnat.getSignatureIndex())).getBytes(); 146 } 147}