View Javadoc
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: FieldOrMethod.html 1021978 2017-12-09 17:38:21Z ggregory $
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 }