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