View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   https://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.bcel.generic;
20  
21  import org.apache.bcel.Const;
22  import org.apache.bcel.classfile.ConstantCP;
23  import org.apache.bcel.classfile.ConstantNameAndType;
24  import org.apache.bcel.classfile.ConstantPool;
25  import org.apache.bcel.classfile.ConstantUtf8;
26  import org.apache.bcel.classfile.Utility;
27  
28  /**
29   * Super class for InvokeInstruction and FieldInstruction, since they have some methods in common!
30   */
31  public abstract class FieldOrMethod extends CPInstruction implements LoadClass {
32  
33      /**
34       * Empty constructor needed for Instruction.readInstruction. Not to be used otherwise.
35       */
36      FieldOrMethod() {
37          // no init
38      }
39  
40      /**
41       * Constructs a FieldOrMethod.
42       *
43       * @param opcode the opcode.
44       * @param index to constant pool.
45       */
46      protected FieldOrMethod(final short opcode, final int index) {
47          super(opcode, index);
48      }
49  
50      /**
51       * Gets the name of the referenced class/interface.
52       *
53       * @param cpg the constant pool generator.
54       * @return name of the referenced class/interface.
55       * @deprecated If the instruction references an array class, this method will return "java.lang.Object". For code
56       *             generated by Java 1.5, this answer is sometimes wrong (for example, if the "clone()" method is called on an
57       *             array). A better idea is to use the {@link #getReferenceType(ConstantPoolGen)} method, which correctly
58       *             distinguishes between class types and array types.
59       */
60      @Deprecated
61      public String getClassName(final ConstantPoolGen cpg) {
62          final ConstantPool cp = cpg.getConstantPool();
63          final ConstantCP cmr = (ConstantCP) cp.getConstant(super.getIndex());
64          final String className = cp.getConstantString(cmr.getClassIndex(), Const.CONSTANT_Class);
65          if (className.startsWith("[")) {
66              // Turn array classes into java.lang.Object.
67              return "java.lang.Object";
68          }
69          return Utility.pathToPackage(className);
70      }
71  
72      /**
73       * Gets the type of the referenced class/interface.
74       *
75       * @param cpg the constant pool generator.
76       * @return type of the referenced class/interface.
77       * @deprecated If the instruction references an array class, the ObjectType returned will be invalid. Use
78       *             getReferenceType() instead.
79       */
80      @Deprecated
81      public ObjectType getClassType(final ConstantPoolGen cpg) {
82          return ObjectType.getInstance(getClassName(cpg));
83      }
84  
85      /**
86       * Gets the ObjectType of the method return or field.
87       *
88       * @param cpg the constant pool generator.
89       * @return type of the referenced class/interface.
90       * @throws ClassGenException when the field is (or method returns) an array.
91       */
92      @Override
93      public ObjectType getLoadClassType(final ConstantPoolGen cpg) {
94          final ReferenceType rt = getReferenceType(cpg);
95          if (rt instanceof ObjectType) {
96              return (ObjectType) rt;
97          }
98          if (rt instanceof ArrayType) {
99              return Type.OBJECT;
100         }
101         throw new ClassGenException(rt.getClass().getCanonicalName() + " " + rt.getSignature() + " does not represent an ObjectType");
102     }
103 
104     /**
105      * Gets the name of referenced method or field.
106      *
107      * @param cpg the constant pool generator.
108      * @return name of referenced method/field.
109      */
110     public String getName(final ConstantPoolGen cpg) {
111         final ConstantPool cp = cpg.getConstantPool();
112         final ConstantCP cmr = (ConstantCP) cp.getConstant(super.getIndex());
113         final ConstantNameAndType cnat = (ConstantNameAndType) cp.getConstant(cmr.getNameAndTypeIndex());
114         return ((ConstantUtf8) cp.getConstant(cnat.getNameIndex())).getBytes();
115     }
116 
117     /**
118      * Gets the reference type representing the class, interface, or array class referenced by the instruction.
119      *
120      * @param cpg the ConstantPoolGen used to create the instruction.
121      * @return an ObjectType (if the referenced class type is a class or interface), or an ArrayType (if the referenced
122      *         class type is an array class)
123      */
124     public ReferenceType getReferenceType(final ConstantPoolGen cpg) {
125         final ConstantPool cp = cpg.getConstantPool();
126         final ConstantCP cmr = (ConstantCP) cp.getConstant(super.getIndex());
127         String className = cp.getConstantString(cmr.getClassIndex(), Const.CONSTANT_Class);
128         if (className.startsWith("[")) {
129             return (ArrayType) Type.getType(className);
130         }
131         className = Utility.pathToPackage(className);
132         return ObjectType.getInstance(className);
133     }
134 
135     /**
136      * Gets the signature of referenced method or field.
137      *
138      * @param cpg the constant pool generator.
139      * @return signature of referenced method/field.
140      */
141     public String getSignature(final ConstantPoolGen cpg) {
142         final ConstantPool cp = cpg.getConstantPool();
143         final ConstantCP cmr = (ConstantCP) cp.getConstant(super.getIndex());
144         final ConstantNameAndType cnat = (ConstantNameAndType) cp.getConstant(cmr.getNameAndTypeIndex());
145         return ((ConstantUtf8) cp.getConstant(cnat.getSignatureIndex())).getBytes();
146     }
147 }