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