001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 * 017 */ 018package org.apache.bcel.generic; 019 020import org.apache.bcel.Const; 021import org.apache.bcel.classfile.ConstantCP; 022import org.apache.bcel.classfile.ConstantNameAndType; 023import org.apache.bcel.classfile.ConstantPool; 024import org.apache.bcel.classfile.ConstantUtf8; 025import org.apache.bcel.classfile.Utility; 026 027/** 028 * Super class for InvokeInstruction and FieldInstruction, since they have some methods in common! 029 * 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 (e.g., 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 */ 055 @Deprecated 056 public String getClassName(final ConstantPoolGen cpg) { 057 final ConstantPool cp = cpg.getConstantPool(); 058 final ConstantCP cmr = (ConstantCP) cp.getConstant(super.getIndex()); 059 final String className = cp.getConstantString(cmr.getClassIndex(), Const.CONSTANT_Class); 060 if (className.startsWith("[")) { 061 // Turn array classes into java.lang.Object. 062 return "java.lang.Object"; 063 } 064 return Utility.pathToPackage(className); 065 } 066 067 /** 068 * @return type of the referenced class/interface 069 * @deprecated If the instruction references an array class, the ObjectType returned will be invalid. Use 070 * getReferenceType() instead. 071 */ 072 @Deprecated 073 public ObjectType getClassType(final ConstantPoolGen cpg) { 074 return ObjectType.getInstance(getClassName(cpg)); 075 } 076 077 /** 078 * Gets the ObjectType of the method return or field. 079 * 080 * @return type of the referenced class/interface 081 * @throws ClassGenException when the field is (or method returns) an array, 082 */ 083 @Override 084 public ObjectType getLoadClassType(final ConstantPoolGen cpg) { 085 final ReferenceType rt = getReferenceType(cpg); 086 if (rt instanceof ObjectType) { 087 return (ObjectType) rt; 088 } 089 throw new ClassGenException(rt.getClass().getCanonicalName() + " " + rt.getSignature() + " does not represent an ObjectType"); 090 } 091 092 /** 093 * @return name of referenced method/field. 094 */ 095 public String getName(final ConstantPoolGen cpg) { 096 final ConstantPool cp = cpg.getConstantPool(); 097 final ConstantCP cmr = (ConstantCP) cp.getConstant(super.getIndex()); 098 final ConstantNameAndType cnat = (ConstantNameAndType) cp.getConstant(cmr.getNameAndTypeIndex()); 099 return ((ConstantUtf8) cp.getConstant(cnat.getNameIndex())).getBytes(); 100 } 101 102 /** 103 * Gets the reference type representing the class, interface, or array class referenced by the instruction. 104 * 105 * @param cpg the ConstantPoolGen used to create the instruction 106 * @return an ObjectType (if the referenced class type is a class or interface), or an ArrayType (if the referenced 107 * class type is an array class) 108 */ 109 public ReferenceType getReferenceType(final ConstantPoolGen cpg) { 110 final ConstantPool cp = cpg.getConstantPool(); 111 final ConstantCP cmr = (ConstantCP) cp.getConstant(super.getIndex()); 112 String className = cp.getConstantString(cmr.getClassIndex(), Const.CONSTANT_Class); 113 if (className.startsWith("[")) { 114 return (ArrayType) Type.getType(className); 115 } 116 className = Utility.pathToPackage(className); 117 return ObjectType.getInstance(className); 118 } 119 120 /** 121 * @return signature of referenced method/field. 122 */ 123 public String getSignature(final ConstantPoolGen cpg) { 124 final ConstantPool cp = cpg.getConstantPool(); 125 final ConstantCP cmr = (ConstantCP) cp.getConstant(super.getIndex()); 126 final ConstantNameAndType cnat = (ConstantNameAndType) cp.getConstant(cmr.getNameAndTypeIndex()); 127 return ((ConstantUtf8) cp.getConstant(cnat.getSignatureIndex())).getBytes(); 128 } 129}