001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 * 017 */ 018package org.apache.bcel.classfile; 019 020import java.io.DataInput; 021import java.io.DataOutputStream; 022import java.io.IOException; 023 024import org.apache.bcel.Const; 025import org.apache.bcel.util.BCELComparator; 026 027/** 028 * Abstract superclass for classes to represent the different constant types 029 * in the constant pool of a class file. The classes keep closely to 030 * the JVM specification. 031 * 032 * @version $Id: Constant.java 1749603 2016-06-21 20:50:19Z ggregory $ 033 */ 034public abstract class Constant implements Cloneable, Node { 035 036 private static BCELComparator bcelComparator = new BCELComparator() { 037 038 @Override 039 public boolean equals( final Object o1, final Object o2 ) { 040 final Constant THIS = (Constant) o1; 041 final Constant THAT = (Constant) o2; 042 return THIS.toString().equals(THAT.toString()); 043 } 044 045 046 @Override 047 public int hashCode( final Object o ) { 048 final Constant THIS = (Constant) o; 049 return THIS.toString().hashCode(); 050 } 051 }; 052 /* In fact this tag is redundant since we can distinguish different 053 * `Constant' objects by their type, i.e., via `instanceof'. In some 054 * places we will use the tag for switch()es anyway. 055 * 056 * First, we want match the specification as closely as possible. Second we 057 * need the tag as an index to select the corresponding class name from the 058 * `CONSTANT_NAMES' array. 059 */ 060 /** 061 * @deprecated (since 6.0) will be made private; do not access directly, use getter/setter 062 */ 063 @java.lang.Deprecated 064 protected byte tag; // TODO should be private & final 065 066 067 Constant(final byte tag) { 068 this.tag = tag; 069 } 070 071 072 /** 073 * Called by objects that are traversing the nodes of the tree implicitely 074 * defined by the contents of a Java class. I.e., the hierarchy of methods, 075 * fields, attributes, etc. spawns a tree of objects. 076 * 077 * @param v Visitor object 078 */ 079 @Override 080 public abstract void accept( Visitor v ); 081 082 083 public abstract void dump( DataOutputStream file ) throws IOException; 084 085 086 /** 087 * @return Tag of constant, i.e., its type. No setTag() method to avoid 088 * confusion. 089 */ 090 public final byte getTag() { 091 return tag; 092 } 093 094 095 /** 096 * @return String representation. 097 */ 098 @Override 099 public String toString() { 100 return Const.getConstantName(tag) + "[" + tag + "]"; 101 } 102 103 104 /** 105 * @return deep copy of this constant 106 */ 107 public Constant copy() { 108 try { 109 return (Constant) super.clone(); 110 } catch (final CloneNotSupportedException e) { 111 // TODO should this throw? 112 } 113 return null; 114 } 115 116 117 @Override 118 public Object clone() { 119 try { 120 return super.clone(); 121 } catch (final CloneNotSupportedException e) { 122 throw new Error("Clone Not Supported"); // never happens 123 } 124 } 125 126 127 /** 128 * Read one constant from the given input, the type depends on a tag byte. 129 * 130 * @param input Input stream 131 * @return Constant object 132 * @since 6.0 made public 133 */ 134 public static Constant readConstant( final DataInput input ) throws IOException, 135 ClassFormatException { 136 final byte b = input.readByte(); // Read tag byte 137 switch (b) { 138 case Const.CONSTANT_Class: 139 return new ConstantClass(input); 140 case Const.CONSTANT_Fieldref: 141 return new ConstantFieldref(input); 142 case Const.CONSTANT_Methodref: 143 return new ConstantMethodref(input); 144 case Const.CONSTANT_InterfaceMethodref: 145 return new ConstantInterfaceMethodref(input); 146 case Const.CONSTANT_String: 147 return new ConstantString(input); 148 case Const.CONSTANT_Integer: 149 return new ConstantInteger(input); 150 case Const.CONSTANT_Float: 151 return new ConstantFloat(input); 152 case Const.CONSTANT_Long: 153 return new ConstantLong(input); 154 case Const.CONSTANT_Double: 155 return new ConstantDouble(input); 156 case Const.CONSTANT_NameAndType: 157 return new ConstantNameAndType(input); 158 case Const.CONSTANT_Utf8: 159 return ConstantUtf8.getInstance(input); 160 case Const.CONSTANT_MethodHandle: 161 return new ConstantMethodHandle(input); 162 case Const.CONSTANT_MethodType: 163 return new ConstantMethodType(input); 164 case Const.CONSTANT_InvokeDynamic: 165 return new ConstantInvokeDynamic(input); 166 default: 167 throw new ClassFormatException("Invalid byte tag in constant pool: " + b); 168 } 169 } 170 171 172 /** 173 * @return Comparison strategy object 174 */ 175 public static BCELComparator getComparator() { 176 return bcelComparator; 177 } 178 179 180 /** 181 * @param comparator Comparison strategy object 182 */ 183 public static void setComparator( final BCELComparator comparator ) { 184 bcelComparator = comparator; 185 } 186 187 188 /** 189 * Return value as defined by given BCELComparator strategy. 190 * By default two Constant objects are said to be equal when 191 * the result of toString() is equal. 192 * 193 * @see java.lang.Object#equals(java.lang.Object) 194 */ 195 @Override 196 public boolean equals( final Object obj ) { 197 return bcelComparator.equals(this, obj); 198 } 199 200 201 /** 202 * Return value as defined by given BCELComparator strategy. 203 * By default return the hashcode of the result of toString(). 204 * 205 * @see java.lang.Object#hashCode() 206 */ 207 @Override 208 public int hashCode() { 209 return bcelComparator.hashCode(this); 210 } 211}