Home | History | Annotate | Download | only in generic
      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      */
     38     FieldOrMethod() {
     39     }
     40 
     41 
     42     /**
     43      * @param index to constant pool
     44      */
     45     protected FieldOrMethod(final short opcode, final int index) {
     46         super(opcode, index);
     47     }
     48 
     49 
     50     /** @return signature of referenced method/field.
     51      */
     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      */
     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
     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
    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      */
    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
    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