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