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       * @param index to constant pool
42       */
43      protected FieldOrMethod(final short opcode, final int index) {
44          super(opcode, index);
45      }
46  
47      /**
48       * @return name of the referenced class/interface
49       * @deprecated If the instruction references an array class, this method will return "java.lang.Object". For code
50       *             generated by Java 1.5, this answer is sometimes wrong (for example, if the "clone()" method is called on an
51       *             array). A better idea is to use the {@link #getReferenceType(ConstantPoolGen)} method, which correctly
52       *             distinguishes between class types and array types.
53       */
54      @Deprecated
55      public String getClassName(final ConstantPoolGen cpg) {
56          final ConstantPool cp = cpg.getConstantPool();
57          final ConstantCP cmr = (ConstantCP) cp.getConstant(super.getIndex());
58          final String className = cp.getConstantString(cmr.getClassIndex(), Const.CONSTANT_Class);
59          if (className.startsWith("[")) {
60              // Turn array classes into java.lang.Object.
61              return "java.lang.Object";
62          }
63          return Utility.pathToPackage(className);
64      }
65  
66      /**
67       * @return type of the referenced class/interface
68       * @deprecated If the instruction references an array class, the ObjectType returned will be invalid. Use
69       *             getReferenceType() instead.
70       */
71      @Deprecated
72      public ObjectType getClassType(final ConstantPoolGen cpg) {
73          return ObjectType.getInstance(getClassName(cpg));
74      }
75  
76      /**
77       * Gets the ObjectType of the method return or field.
78       *
79       * @return type of the referenced class/interface
80       * @throws ClassGenException when the field is (or method returns) an array,
81       */
82      @Override
83      public ObjectType getLoadClassType(final ConstantPoolGen cpg) {
84          final ReferenceType rt = getReferenceType(cpg);
85          if (rt instanceof ObjectType) {
86              return (ObjectType) rt;
87          }
88          if (rt instanceof ArrayType) {
89              return Type.OBJECT;
90          }
91          throw new ClassGenException(rt.getClass().getCanonicalName() + " " + rt.getSignature() + " does not represent an ObjectType");
92      }
93  
94      /**
95       * @return name of referenced method/field.
96       */
97      public String getName(final ConstantPoolGen cpg) {
98          final ConstantPool cp = cpg.getConstantPool();
99          final ConstantCP cmr = (ConstantCP) cp.getConstant(super.getIndex());
100         final ConstantNameAndType cnat = (ConstantNameAndType) cp.getConstant(cmr.getNameAndTypeIndex());
101         return ((ConstantUtf8) cp.getConstant(cnat.getNameIndex())).getBytes();
102     }
103 
104     /**
105      * Gets the reference type representing the class, interface, or array class referenced by the instruction.
106      *
107      * @param cpg the ConstantPoolGen used to create the instruction
108      * @return an ObjectType (if the referenced class type is a class or interface), or an ArrayType (if the referenced
109      *         class type is an array class)
110      */
111     public ReferenceType getReferenceType(final ConstantPoolGen cpg) {
112         final ConstantPool cp = cpg.getConstantPool();
113         final ConstantCP cmr = (ConstantCP) cp.getConstant(super.getIndex());
114         String className = cp.getConstantString(cmr.getClassIndex(), Const.CONSTANT_Class);
115         if (className.startsWith("[")) {
116             return (ArrayType) Type.getType(className);
117         }
118         className = Utility.pathToPackage(className);
119         return ObjectType.getInstance(className);
120     }
121 
122     /**
123      * @return signature of referenced method/field.
124      */
125     public String getSignature(final ConstantPoolGen cpg) {
126         final ConstantPool cp = cpg.getConstantPool();
127         final ConstantCP cmr = (ConstantCP) cp.getConstant(super.getIndex());
128         final ConstantNameAndType cnat = (ConstantNameAndType) cp.getConstant(cmr.getNameAndTypeIndex());
129         return ((ConstantUtf8) cp.getConstant(cnat.getSignatureIndex())).getBytes();
130     }
131 }