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 */ 017package org.apache.bcel.generic; 018 019import org.apache.bcel.Const; 020import org.apache.bcel.classfile.ConstantCP; 021import org.apache.bcel.classfile.ConstantNameAndType; 022import org.apache.bcel.classfile.ConstantPool; 023import org.apache.bcel.classfile.ConstantUtf8; 024import org.apache.bcel.classfile.Utility; 025 026/** 027 * Super class for InvokeInstruction and FieldInstruction, since they have some methods in common! 028 */ 029public abstract class FieldOrMethod extends CPInstruction implements LoadClass { 030 031 /** 032 * Empty constructor needed for Instruction.readInstruction. Not to be used otherwise. 033 */ 034 FieldOrMethod() { 035 // no init 036 } 037 038 /** 039 * @param index to constant pool 040 */ 041 protected FieldOrMethod(final short opcode, final int index) { 042 super(opcode, index); 043 } 044 045 /** 046 * @return name of the referenced class/interface 047 * @deprecated If the instruction references an array class, this method will return "java.lang.Object". For code 048 * generated by Java 1.5, this answer is sometimes wrong (e.g., if the "clone()" method is called on an 049 * array). A better idea is to use the {@link #getReferenceType(ConstantPoolGen)} method, which correctly 050 * distinguishes between class types and array types. 051 */ 052 @Deprecated 053 public String getClassName(final ConstantPoolGen cpg) { 054 final ConstantPool cp = cpg.getConstantPool(); 055 final ConstantCP cmr = (ConstantCP) cp.getConstant(super.getIndex()); 056 final String className = cp.getConstantString(cmr.getClassIndex(), Const.CONSTANT_Class); 057 if (className.startsWith("[")) { 058 // Turn array classes into java.lang.Object. 059 return "java.lang.Object"; 060 } 061 return Utility.pathToPackage(className); 062 } 063 064 /** 065 * @return type of the referenced class/interface 066 * @deprecated If the instruction references an array class, the ObjectType returned will be invalid. Use 067 * getReferenceType() instead. 068 */ 069 @Deprecated 070 public ObjectType getClassType(final ConstantPoolGen cpg) { 071 return ObjectType.getInstance(getClassName(cpg)); 072 } 073 074 /** 075 * Gets the ObjectType of the method return or field. 076 * 077 * @return type of the referenced class/interface 078 * @throws ClassGenException when the field is (or method returns) an array, 079 */ 080 @Override 081 public ObjectType getLoadClassType(final ConstantPoolGen cpg) { 082 final ReferenceType rt = getReferenceType(cpg); 083 if (rt instanceof ObjectType) { 084 return (ObjectType) rt; 085 } 086 if (rt instanceof ArrayType) { 087 return Type.OBJECT; 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}