16 * distributed under the License is distributed on an "AS IS" BASIS, |
15 * distributed under the License is distributed on an "AS IS" BASIS, |
17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
18 * See the License for the specific language governing permissions and |
17 * See the License for the specific language governing permissions and |
19 * limitations under the License. |
18 * limitations under the License. |
20 */ |
19 */ |
21 |
|
22 package com.sun.org.apache.bcel.internal.classfile; |
20 package com.sun.org.apache.bcel.internal.classfile; |
23 |
21 |
|
22 import java.io.DataInput; |
|
23 import java.io.DataOutputStream; |
|
24 import java.io.IOException; |
24 |
25 |
25 import com.sun.org.apache.bcel.internal.Constants; |
26 import com.sun.org.apache.bcel.internal.Const; |
26 import java.io.*; |
27 import com.sun.org.apache.bcel.internal.util.BCELComparator; |
27 |
28 |
28 /** |
29 /** |
29 * Abstract superclass for classes to represent the different constant types |
30 * Abstract superclass for classes to represent the different constant types in |
30 * in the constant pool of a class file. The classes keep closely to |
31 * the constant pool of a class file. The classes keep closely to the JVM |
31 * the JVM specification. |
32 * specification. |
32 * |
33 * |
33 * @author <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A> |
34 * @version $Id: Constant.java 1749603 2016-06-21 20:50:19Z ggregory $ |
34 */ |
35 */ |
35 public abstract class Constant implements Cloneable, Node, Serializable { |
36 public abstract class Constant implements Cloneable, Node { |
36 /* In fact this tag is redundant since we can distinguish different |
|
37 * `Constant' objects by their type, i.e., via `instanceof'. In some |
|
38 * places we will use the tag for switch()es anyway. |
|
39 * |
|
40 * First, we want match the specification as closely as possible. Second we |
|
41 * need the tag as an index to select the corresponding class name from the |
|
42 * `CONSTANT_NAMES' array. |
|
43 */ |
|
44 protected byte tag; |
|
45 |
37 |
46 Constant(byte tag) { this.tag = tag; } |
38 private static BCELComparator bcelComparator = new BCELComparator() { |
47 |
39 |
48 /** |
40 @Override |
49 * Called by objects that are traversing the nodes of the tree implicitely |
41 public boolean equals(final Object o1, final Object o2) { |
50 * defined by the contents of a Java class. I.e., the hierarchy of methods, |
42 final Constant THIS = (Constant) o1; |
51 * fields, attributes, etc. spawns a tree of objects. |
43 final Constant THAT = (Constant) o2; |
52 * |
44 return THIS.toString().equals(THAT.toString()); |
53 * @param v Visitor object |
45 } |
54 */ |
|
55 public abstract void accept(Visitor v); |
|
56 |
46 |
57 public abstract void dump(DataOutputStream file) throws IOException; |
47 @Override |
|
48 public int hashCode(final Object o) { |
|
49 final Constant THIS = (Constant) o; |
|
50 return THIS.toString().hashCode(); |
|
51 } |
|
52 }; |
58 |
53 |
59 /** |
54 /* In fact this tag is redundant since we can distinguish different |
60 * @return Tag of constant, i.e., its type. No setTag() method to avoid |
55 * `Constant' objects by their type, i.e., via `instanceof'. In some |
61 * confusion. |
56 * places we will use the tag for switch()es anyway. |
62 */ |
57 * |
63 public final byte getTag() { return tag; } |
58 * First, we want match the specification as closely as possible. Second we |
|
59 * need the tag as an index to select the corresponding class name from the |
|
60 * `CONSTANT_NAMES' array. |
|
61 */ |
|
62 private byte tag; |
64 |
63 |
65 /** |
64 Constant(final byte tag) { |
66 * @return String representation. |
65 this.tag = tag; |
67 */ |
66 } |
68 public String toString() { |
|
69 return Constants.CONSTANT_NAMES[tag] + "[" + tag + "]"; |
|
70 } |
|
71 |
67 |
72 /** |
68 /** |
73 * @return deep copy of this constant |
69 * Called by objects that are traversing the nodes of the tree implicitely |
74 */ |
70 * defined by the contents of a Java class. I.e., the hierarchy of methods, |
75 public Constant copy() { |
71 * fields, attributes, etc. spawns a tree of objects. |
76 try { |
72 * |
77 return (Constant)super.clone(); |
73 * @param v Visitor object |
78 } catch(CloneNotSupportedException e) {} |
74 */ |
|
75 @Override |
|
76 public abstract void accept(Visitor v); |
79 |
77 |
80 return null; |
78 public abstract void dump(DataOutputStream file) throws IOException; |
81 } |
|
82 |
79 |
83 public Object clone() throws CloneNotSupportedException { |
80 /** |
84 return super.clone(); |
81 * @return Tag of constant, i.e., its type. No setTag() method to avoid |
85 } |
82 * confusion. |
|
83 */ |
|
84 public final byte getTag() { |
|
85 return tag; |
|
86 } |
86 |
87 |
87 /** |
88 /** |
88 * Read one constant from the given file, the type depends on a tag byte. |
89 * @return String representation. |
89 * |
90 */ |
90 * @param file Input stream |
91 @Override |
91 * @return Constant object |
92 public String toString() { |
92 */ |
93 return Const.getConstantName(tag) + "[" + tag + "]"; |
93 static final Constant readConstant(DataInputStream file) |
94 } |
94 throws IOException, ClassFormatException |
|
95 { |
|
96 byte b = file.readByte(); // Read tag byte |
|
97 |
95 |
98 switch(b) { |
96 /** |
99 case Constants.CONSTANT_Class: return new ConstantClass(file); |
97 * @return deep copy of this constant |
100 case Constants.CONSTANT_Fieldref: return new ConstantFieldref(file); |
98 */ |
101 case Constants.CONSTANT_Methodref: return new ConstantMethodref(file); |
99 public Constant copy() { |
102 case Constants.CONSTANT_InterfaceMethodref: return new |
100 try { |
103 ConstantInterfaceMethodref(file); |
101 return (Constant) super.clone(); |
104 case Constants.CONSTANT_String: return new ConstantString(file); |
102 } catch (final CloneNotSupportedException e) { |
105 case Constants.CONSTANT_Integer: return new ConstantInteger(file); |
103 // TODO should this throw? |
106 case Constants.CONSTANT_Float: return new ConstantFloat(file); |
104 } |
107 case Constants.CONSTANT_Long: return new ConstantLong(file); |
105 return null; |
108 case Constants.CONSTANT_Double: return new ConstantDouble(file); |
|
109 case Constants.CONSTANT_NameAndType: return new ConstantNameAndType(file); |
|
110 case Constants.CONSTANT_Utf8: return new ConstantUtf8(file); |
|
111 default: |
|
112 throw new ClassFormatException("Invalid byte tag in constant pool: " + b); |
|
113 } |
106 } |
114 } |
107 |
|
108 @Override |
|
109 public Object clone() { |
|
110 try { |
|
111 return super.clone(); |
|
112 } catch (final CloneNotSupportedException e) { |
|
113 throw new Error("Clone Not Supported"); // never happens |
|
114 } |
|
115 } |
|
116 |
|
117 /** |
|
118 * Read one constant from the given input, the type depends on a tag byte. |
|
119 * |
|
120 * @param input Input stream |
|
121 * @return Constant object |
|
122 * @since 6.0 made public |
|
123 */ |
|
124 public static Constant readConstant(final DataInput input) throws IOException, |
|
125 ClassFormatException { |
|
126 final byte b = input.readByte(); // Read tag byte |
|
127 switch (b) { |
|
128 case Const.CONSTANT_Class: |
|
129 return new ConstantClass(input); |
|
130 case Const.CONSTANT_Fieldref: |
|
131 return new ConstantFieldref(input); |
|
132 case Const.CONSTANT_Methodref: |
|
133 return new ConstantMethodref(input); |
|
134 case Const.CONSTANT_InterfaceMethodref: |
|
135 return new ConstantInterfaceMethodref(input); |
|
136 case Const.CONSTANT_String: |
|
137 return new ConstantString(input); |
|
138 case Const.CONSTANT_Integer: |
|
139 return new ConstantInteger(input); |
|
140 case Const.CONSTANT_Float: |
|
141 return new ConstantFloat(input); |
|
142 case Const.CONSTANT_Long: |
|
143 return new ConstantLong(input); |
|
144 case Const.CONSTANT_Double: |
|
145 return new ConstantDouble(input); |
|
146 case Const.CONSTANT_NameAndType: |
|
147 return new ConstantNameAndType(input); |
|
148 case Const.CONSTANT_Utf8: |
|
149 return ConstantUtf8.getInstance(input); |
|
150 case Const.CONSTANT_MethodHandle: |
|
151 return new ConstantMethodHandle(input); |
|
152 case Const.CONSTANT_MethodType: |
|
153 return new ConstantMethodType(input); |
|
154 case Const.CONSTANT_InvokeDynamic: |
|
155 return new ConstantInvokeDynamic(input); |
|
156 default: |
|
157 throw new ClassFormatException("Invalid byte tag in constant pool: " + b); |
|
158 } |
|
159 } |
|
160 |
|
161 /** |
|
162 * @return Comparison strategy object |
|
163 */ |
|
164 public static BCELComparator getComparator() { |
|
165 return bcelComparator; |
|
166 } |
|
167 |
|
168 /** |
|
169 * @param comparator Comparison strategy object |
|
170 */ |
|
171 public static void setComparator(final BCELComparator comparator) { |
|
172 bcelComparator = comparator; |
|
173 } |
|
174 |
|
175 /** |
|
176 * Return value as defined by given BCELComparator strategy. By default two |
|
177 * Constant objects are said to be equal when the result of toString() is |
|
178 * equal. |
|
179 * |
|
180 * @see java.lang.Object#equals(java.lang.Object) |
|
181 */ |
|
182 @Override |
|
183 public boolean equals(final Object obj) { |
|
184 return bcelComparator.equals(this, obj); |
|
185 } |
|
186 |
|
187 /** |
|
188 * Return value as defined by given BCELComparator strategy. By default |
|
189 * return the hashcode of the result of toString(). |
|
190 * |
|
191 * @see java.lang.Object#hashCode() |
|
192 */ |
|
193 @Override |
|
194 public int hashCode() { |
|
195 return bcelComparator.hashCode(this); |
|
196 } |
115 } |
197 } |