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 * @param index to constant pool 042 */ 043 protected FieldOrMethod(final short opcode, final int index) { 044 super(opcode, index); 045 } 046 047 /** 048 * @return name of the referenced class/interface 049 * @deprecated If the instruction references an array class, this method will return "java.lang.Object". For code 050 * generated by Java 1.5, this answer is sometimes wrong (for example, if the "clone()" method is called on an 051 * array). A better idea is to use the {@link #getReferenceType(ConstantPoolGen)} method, which correctly 052 * distinguishes between class types and array types. 053 */ 054 @Deprecated 055 public String getClassName(final ConstantPoolGen cpg) { 056 final ConstantPool cp = cpg.getConstantPool(); 057 final ConstantCP cmr = (ConstantCP) cp.getConstant(super.getIndex()); 058 final String className = cp.getConstantString(cmr.getClassIndex(), Const.CONSTANT_Class); 059 if (className.startsWith("[")) { 060 // Turn array classes into java.lang.Object. 061 return "java.lang.Object"; 062 } 063 return Utility.pathToPackage(className); 064 } 065 066 /** 067 * @return type of the referenced class/interface 068 * @deprecated If the instruction references an array class, the ObjectType returned will be invalid. Use 069 * getReferenceType() instead. 070 */ 071 @Deprecated 072 public ObjectType getClassType(final ConstantPoolGen cpg) { 073 return ObjectType.getInstance(getClassName(cpg)); 074 } 075 076 /** 077 * Gets the ObjectType of the method return or field. 078 * 079 * @return type of the referenced class/interface 080 * @throws ClassGenException when the field is (or method returns) an array, 081 */ 082 @Override 083 public ObjectType getLoadClassType(final ConstantPoolGen cpg) { 084 final ReferenceType rt = getReferenceType(cpg); 085 if (rt instanceof ObjectType) { 086 return (ObjectType) rt; 087 } 088 if (rt instanceof ArrayType) { 089 return Type.OBJECT; 090 } 091 throw new ClassGenException(rt.getClass().getCanonicalName() + " " + rt.getSignature() + " does not represent an ObjectType"); 092 } 093 094 /** 095 * @return name of referenced method/field. 096 */ 097 public String getName(final ConstantPoolGen cpg) { 098 final ConstantPool cp = cpg.getConstantPool(); 099 final ConstantCP cmr = (ConstantCP) cp.getConstant(super.getIndex()); 100 final ConstantNameAndType cnat = (ConstantNameAndType) cp.getConstant(cmr.getNameAndTypeIndex()); 101 return ((ConstantUtf8) cp.getConstant(cnat.getNameIndex())).getBytes(); 102 } 103 104 /** 105 * Gets the reference type representing the class, interface, or array class referenced by the instruction. 106 * 107 * @param cpg the ConstantPoolGen used to create the instruction 108 * @return an ObjectType (if the referenced class type is a class or interface), or an ArrayType (if the referenced 109 * class type is an array class) 110 */ 111 public ReferenceType getReferenceType(final ConstantPoolGen cpg) { 112 final ConstantPool cp = cpg.getConstantPool(); 113 final ConstantCP cmr = (ConstantCP) cp.getConstant(super.getIndex()); 114 String className = cp.getConstantString(cmr.getClassIndex(), Const.CONSTANT_Class); 115 if (className.startsWith("[")) { 116 return (ArrayType) Type.getType(className); 117 } 118 className = Utility.pathToPackage(className); 119 return ObjectType.getInstance(className); 120 } 121 122 /** 123 * @return signature of referenced method/field. 124 */ 125 public String getSignature(final ConstantPoolGen cpg) { 126 final ConstantPool cp = cpg.getConstantPool(); 127 final ConstantCP cmr = (ConstantCP) cp.getConstant(super.getIndex()); 128 final ConstantNameAndType cnat = (ConstantNameAndType) cp.getConstant(cmr.getNameAndTypeIndex()); 129 return ((ConstantUtf8) cp.getConstant(cnat.getSignatureIndex())).getBytes(); 130 } 131}