1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 * 17 */ 18 package org.apache.bcel.classfile; 19 20 import java.io.DataInput; 21 import java.io.DataOutputStream; 22 import java.io.IOException; 23 24 import org.apache.bcel.Const; 25 import org.apache.bcel.util.BCELComparator; 26 27 /** 28 * Abstract superclass for classes to represent the different constant types 29 * in the constant pool of a class file. The classes keep closely to 30 * the JVM specification. 31 * 32 * @version $Id$ 33 */ 34 public abstract class Constant implements Cloneable, Node { 35 36 private static BCELComparator bcelComparator = new BCELComparator() { 37 38 @Override 39 public boolean equals( final Object o1, final Object o2 ) { 40 final Constant THIS = (Constant) o1; 41 final Constant THAT = (Constant) o2; 42 return THIS.toString().equals(THAT.toString()); 43 } 44 45 46 @Override 47 public int hashCode( final Object o ) { 48 final Constant THIS = (Constant) o; 49 return THIS.toString().hashCode(); 50 } 51 }; 52 /* In fact this tag is redundant since we can distinguish different 53 * `Constant' objects by their type, i.e., via `instanceof'. In some 54 * places we will use the tag for switch()es anyway. 55 * 56 * First, we want match the specification as closely as possible. Second we 57 * need the tag as an index to select the corresponding class name from the 58 * `CONSTANT_NAMES' array. 59 */ 60 /** 61 * @deprecated (since 6.0) will be made private; do not access directly, use getter/setter 62 */ 63 @java.lang.Deprecated 64 protected byte tag; // TODO should be private & final 65 66 Constant(final byte tag)67 Constant(final byte tag) { 68 this.tag = tag; 69 } 70 71 72 /** 73 * Called by objects that are traversing the nodes of the tree implicitely 74 * defined by the contents of a Java class. I.e., the hierarchy of methods, 75 * fields, attributes, etc. spawns a tree of objects. 76 * 77 * @param v Visitor object 78 */ 79 @Override accept( Visitor v )80 public abstract void accept( Visitor v ); 81 82 dump( DataOutputStream file )83 public abstract void dump( DataOutputStream file ) throws IOException; 84 85 86 /** 87 * @return Tag of constant, i.e., its type. No setTag() method to avoid 88 * confusion. 89 */ getTag()90 public final byte getTag() { 91 return tag; 92 } 93 94 95 /** 96 * @return String representation. 97 */ 98 @Override toString()99 public String toString() { 100 return Const.getConstantName(tag) + "[" + tag + "]"; 101 } 102 103 104 /** 105 * @return deep copy of this constant 106 */ copy()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 clone()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 dataInput Input stream 131 * @return Constant object 132 * @throws IOException if an I/O error occurs reading from the given {@code dataInput}. 133 * @throws ClassFormatException if the next byte is not recognized 134 * @since 6.0 made public 135 */ readConstant(final DataInput dataInput)136 public static Constant readConstant(final DataInput dataInput) throws IOException, ClassFormatException { 137 final byte b = dataInput.readByte(); // Read tag byte 138 switch (b) { 139 case Const.CONSTANT_Class: 140 return new ConstantClass(dataInput); 141 case Const.CONSTANT_Fieldref: 142 return new ConstantFieldref(dataInput); 143 case Const.CONSTANT_Methodref: 144 return new ConstantMethodref(dataInput); 145 case Const.CONSTANT_InterfaceMethodref: 146 return new ConstantInterfaceMethodref(dataInput); 147 case Const.CONSTANT_String: 148 return new ConstantString(dataInput); 149 case Const.CONSTANT_Integer: 150 return new ConstantInteger(dataInput); 151 case Const.CONSTANT_Float: 152 return new ConstantFloat(dataInput); 153 case Const.CONSTANT_Long: 154 return new ConstantLong(dataInput); 155 case Const.CONSTANT_Double: 156 return new ConstantDouble(dataInput); 157 case Const.CONSTANT_NameAndType: 158 return new ConstantNameAndType(dataInput); 159 case Const.CONSTANT_Utf8: 160 return ConstantUtf8.getInstance(dataInput); 161 case Const.CONSTANT_MethodHandle: 162 return new ConstantMethodHandle(dataInput); 163 case Const.CONSTANT_MethodType: 164 return new ConstantMethodType(dataInput); 165 case Const.CONSTANT_Dynamic: 166 return new ConstantDynamic(dataInput); 167 case Const.CONSTANT_InvokeDynamic: 168 return new ConstantInvokeDynamic(dataInput); 169 case Const.CONSTANT_Module: 170 return new ConstantModule(dataInput); 171 case Const.CONSTANT_Package: 172 return new ConstantPackage(dataInput); 173 default: 174 throw new ClassFormatException("Invalid byte tag in constant pool: " + b); 175 } 176 } 177 178 /** 179 * @return Comparison strategy object 180 */ getComparator()181 public static BCELComparator getComparator() { 182 return bcelComparator; 183 } 184 185 186 /** 187 * @param comparator Comparison strategy object 188 */ setComparator( final BCELComparator comparator )189 public static void setComparator( final BCELComparator comparator ) { 190 bcelComparator = comparator; 191 } 192 193 194 /** 195 * Return value as defined by given BCELComparator strategy. 196 * By default two Constant objects are said to be equal when 197 * the result of toString() is equal. 198 * 199 * @see java.lang.Object#equals(java.lang.Object) 200 */ 201 @Override equals( final Object obj )202 public boolean equals( final Object obj ) { 203 return bcelComparator.equals(this, obj); 204 } 205 206 207 /** 208 * Return value as defined by given BCELComparator strategy. 209 * By default return the hashcode of the result of toString(). 210 * 211 * @see java.lang.Object#hashCode() 212 */ 213 @Override hashCode()214 public int hashCode() { 215 return bcelComparator.hashCode(this); 216 } 217 } 218