Home | History | Annotate | Download | only in classfile
      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 
     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
     80     public abstract void accept( Visitor v );
     81 
     82 
     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      */
     90     public final byte getTag() {
     91         return tag;
     92     }
     93 
     94 
     95     /**
     96      * @return String representation.
     97      */
     98     @Override
     99     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             case Const.CONSTANT_Module:
    167                 return new ConstantModule(input);
    168             case Const.CONSTANT_Package:
    169                 return new ConstantPackage(input);
    170             default:
    171                 throw new ClassFormatException("Invalid byte tag in constant pool: " + b);
    172         }
    173     }
    174 
    175 
    176     /**
    177      * @return Comparison strategy object
    178      */
    179     public static BCELComparator getComparator() {
    180         return bcelComparator;
    181     }
    182 
    183 
    184     /**
    185      * @param comparator Comparison strategy object
    186      */
    187     public static void setComparator( final BCELComparator comparator ) {
    188         bcelComparator = comparator;
    189     }
    190 
    191 
    192     /**
    193      * Return value as defined by given BCELComparator strategy.
    194      * By default two Constant objects are said to be equal when
    195      * the result of toString() is equal.
    196      *
    197      * @see java.lang.Object#equals(java.lang.Object)
    198      */
    199     @Override
    200     public boolean equals( final Object obj ) {
    201         return bcelComparator.equals(this, obj);
    202     }
    203 
    204 
    205     /**
    206      * Return value as defined by given BCELComparator strategy.
    207      * By default return the hashcode of the result of toString().
    208      *
    209      * @see java.lang.Object#hashCode()
    210      */
    211     @Override
    212     public int hashCode() {
    213         return bcelComparator.hashCode(this);
    214     }
    215 }
    216