1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 * 17 */ 18 package org.apache.bcel.generic; 19 20 import org.apache.bcel.Const; 21 import org.apache.bcel.classfile.ConstantCP; 22 import org.apache.bcel.classfile.ConstantNameAndType; 23 import org.apache.bcel.classfile.ConstantPool; 24 import org.apache.bcel.classfile.ConstantUtf8; 25 26 /** 27 * Super class for InvokeInstruction and FieldInstruction, since they have 28 * some methods in common! 29 * 30 * @version $Id$ 31 */ 32 public abstract class FieldOrMethod extends CPInstruction implements LoadClass { 33 34 /** 35 * Empty constructor needed for Instruction.readInstruction. 36 * Not to be used otherwise. 37 */ FieldOrMethod()38 FieldOrMethod() { 39 } 40 41 42 /** 43 * @param index to constant pool 44 */ FieldOrMethod(final short opcode, final int index)45 protected FieldOrMethod(final short opcode, final int index) { 46 super(opcode, index); 47 } 48 49 50 /** @return signature of referenced method/field. 51 */ getSignature( final ConstantPoolGen cpg )52 public String getSignature( final ConstantPoolGen cpg ) { 53 final ConstantPool cp = cpg.getConstantPool(); 54 final ConstantCP cmr = (ConstantCP) cp.getConstant(super.getIndex()); 55 final ConstantNameAndType cnat = (ConstantNameAndType) cp.getConstant(cmr.getNameAndTypeIndex()); 56 return ((ConstantUtf8) cp.getConstant(cnat.getSignatureIndex())).getBytes(); 57 } 58 59 60 /** @return name of referenced method/field. 61 */ getName( final ConstantPoolGen cpg )62 public String getName( final ConstantPoolGen cpg ) { 63 final ConstantPool cp = cpg.getConstantPool(); 64 final ConstantCP cmr = (ConstantCP) cp.getConstant(super.getIndex()); 65 final ConstantNameAndType cnat = (ConstantNameAndType) cp.getConstant(cmr.getNameAndTypeIndex()); 66 return ((ConstantUtf8) cp.getConstant(cnat.getNameIndex())).getBytes(); 67 } 68 69 70 /** 71 * @return name of the referenced class/interface 72 * @deprecated If the instruction references an array class, 73 * this method will return "java.lang.Object". 74 * For code generated by Java 1.5, this answer is 75 * sometimes wrong (e.g., if the "clone()" method is 76 * called on an array). A better idea is to use 77 * the {@link #getReferenceType(ConstantPoolGen)} method, which correctly distinguishes 78 * between class types and array types. 79 * 80 */ 81 @Deprecated getClassName( final ConstantPoolGen cpg )82 public String getClassName( final ConstantPoolGen cpg ) { 83 final ConstantPool cp = cpg.getConstantPool(); 84 final ConstantCP cmr = (ConstantCP) cp.getConstant(super.getIndex()); 85 final String className = cp.getConstantString(cmr.getClassIndex(), Const.CONSTANT_Class); 86 if (className.startsWith("[")) { 87 // Turn array classes into java.lang.Object. 88 return "java.lang.Object"; 89 } 90 return className.replace('/', '.'); 91 } 92 93 94 /** @return type of the referenced class/interface 95 * @deprecated If the instruction references an array class, 96 * the ObjectType returned will be invalid. Use 97 * getReferenceType() instead. 98 */ 99 @Deprecated getClassType( final ConstantPoolGen cpg )100 public ObjectType getClassType( final ConstantPoolGen cpg ) { 101 return ObjectType.getInstance(getClassName(cpg)); 102 } 103 104 105 /** 106 * Return 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 */ getReferenceType( final ConstantPoolGen cpg )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 * Get 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 getLoadClassType( final ConstantPoolGen cpg )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(rt.getSignature() + " does not represent an ObjectType"); 138 } 139 } 140