1 /* 2 * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. 3 */ 4 /* 5 * Licensed to the Apache Software Foundation (ASF) under one or more 6 * contributor license agreements. See the NOTICE file distributed with 7 * this work for additional information regarding copyright ownership. 8 * The ASF licenses this file to You under the Apache License, Version 2.0 9 * (the "License"); you may not use this file except in compliance with 10 * the License. You may obtain a copy of the License at 11 * 12 * http://www.apache.org/licenses/LICENSE-2.0 13 * 14 * Unless required by applicable law or agreed to in writing, software 15 * distributed under the License is distributed on an "AS IS" BASIS, 16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 * See the License for the specific language governing permissions and 18 * limitations under the License. 19 */ 20 package com.sun.org.apache.bcel.internal.classfile; 21 22 import java.io.DataInput; 23 import java.io.DataOutputStream; 24 import java.io.IOException; 25 26 import com.sun.org.apache.bcel.internal.Const; 27 import com.sun.org.apache.bcel.internal.util.BCELComparator; 28 29 /** 30 * Abstract superclass for classes to represent the different constant types in 31 * the constant pool of a class file. The classes keep closely to the JVM 32 * specification. 33 * 34 * @version $Id: Constant.java 1749603 2016-06-21 20:50:19Z ggregory $ 35 */ 36 public abstract class Constant implements Cloneable, Node { 37 38 private static BCELComparator bcelComparator = new BCELComparator() { 39 40 @Override 41 public boolean equals(final Object o1, final Object o2) { 42 final Constant THIS = (Constant) o1; 43 final Constant THAT = (Constant) o2; 44 return THIS.toString().equals(THAT.toString()); 45 } 46 47 @Override 48 public int hashCode(final Object o) { 49 final Constant THIS = (Constant) o; 50 return THIS.toString().hashCode(); 51 } 52 }; 53 54 /* In fact this tag is redundant since we can distinguish different 55 * `Constant' objects by their type, i.e., via `instanceof'. In some 56 * places we will use the tag for switch()es anyway. 57 * 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; 63 64 Constant(final byte tag) { 65 this.tag = tag; 66 } 67 68 /** 69 * Called by objects that are traversing the nodes of the tree implicitely 70 * defined by the contents of a Java class. I.e., the hierarchy of methods, 71 * fields, attributes, etc. spawns a tree of objects. 72 * 73 * @param v Visitor object 74 */ 75 @Override 76 public abstract void accept(Visitor v); 77 78 public abstract void dump(DataOutputStream file) throws IOException; 79 80 /** 81 * @return Tag of constant, i.e., its type. No setTag() method to avoid 82 * confusion. 83 */ 84 public final byte getTag() { 85 return tag; 86 } 87 88 /** 89 * @return String representation. 90 */ 91 @Override 92 public String toString() { 93 return Const.getConstantName(tag) + "[" + tag + "]"; 94 } 95 96 /** 97 * @return deep copy of this constant 98 */ 99 public Constant copy() { 100 try { 101 return (Constant) super.clone(); 102 } catch (final CloneNotSupportedException e) { 103 // TODO should this throw? 104 } 105 return null; 106 } 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 } 197 }