Home | History | Annotate | Download | only in javassist
      1 /*
      2  * Javassist, a Java-bytecode translator toolkit.
      3  * Copyright (C) 1999-2007 Shigeru Chiba. All Rights Reserved.
      4  *
      5  * The contents of this file are subject to the Mozilla Public License Version
      6  * 1.1 (the "License"); you may not use this file except in compliance with
      7  * the License.  Alternatively, the contents of this file may be used under
      8  * the terms of the GNU Lesser General Public License Version 2.1 or later.
      9  *
     10  * Software distributed under the License is distributed on an "AS IS" basis,
     11  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
     12  * for the specific language governing rights and limitations under the
     13  * License.
     14  */
     15 
     16 package javassist;
     17 
     18 import javassist.bytecode.Descriptor;
     19 
     20 /**
     21  * A hash table associating class names with different names.
     22  *
     23  * <p>This hashtable is used for replacing class names in a class
     24  * definition or a method body.  Define a subclass of this class
     25  * if a more complex mapping algorithm is needed.  For example,
     26  *
     27  * <ul><pre>class MyClassMap extends ClassMap {
     28  *   public Object get(Object jvmClassName) {
     29  *     String name = toJavaName((String)jvmClassName);
     30  *     if (name.startsWith("java."))
     31  *         return toJvmName("java2." + name.substring(5));
     32  *     else
     33  *         return super.get(jvmClassName);
     34  *   }
     35  * }</pre></ul>
     36  *
     37  * <p>This subclass maps <code>java.lang.String</code> to
     38  * <code>java2.lang.String</code>.  Note that <code>get()</code>
     39  * receives and returns the internal representation of a class name.
     40  * For example, the internal representation of <code>java.lang.String</code>
     41  * is <code>java/lang/String</code>.
     42  *
     43  * @see #get(Object)
     44  * @see CtClass#replaceClassName(ClassMap)
     45  * @see CtNewMethod#copy(CtMethod,String,CtClass,ClassMap)
     46  */
     47 public class ClassMap extends java.util.HashMap {
     48     private ClassMap parent;
     49 
     50     /**
     51      * Constructs a hash table.
     52      */
     53     public ClassMap() { parent = null; }
     54 
     55     ClassMap(ClassMap map) { parent = map; }
     56 
     57     /**
     58      * Maps a class name to another name in this hashtable.
     59      * The names are obtained with calling <code>Class.getName()</code>.
     60      * This method translates the given class names into the
     61      * internal form used in the JVM before putting it in
     62      * the hashtable.
     63      *
     64      * @param oldname   the original class name
     65      * @param newname   the substituted class name.
     66      */
     67     public void put(CtClass oldname, CtClass newname) {
     68         put(oldname.getName(), newname.getName());
     69     }
     70 
     71     /**
     72      * Maps a class name to another name in this hashtable.
     73      * If the hashtable contains another mapping from the same
     74      * class name, the old mapping is replaced.
     75      * This method translates the given class names into the
     76      * internal form used in the JVM before putting it in
     77      * the hashtable.
     78      *
     79      * <p>If <code>oldname</code> is identical to
     80      * <code>newname</code>, then this method does not
     81      * perform anything; it does not record the mapping from
     82      * <code>oldname</code> to <code>newname</code>.  See
     83      * <code>fix</code> method.
     84      *
     85      * @param oldname   the original class name.
     86      * @param newname   the substituted class name.
     87      * @see #fix(String)
     88      */
     89     public void put(String oldname, String newname) {
     90         if (oldname == newname)
     91             return;
     92 
     93         String oldname2 = toJvmName(oldname);
     94         String s = (String)get(oldname2);
     95         if (s == null || !s.equals(oldname2))
     96             super.put(oldname2, toJvmName(newname));
     97     }
     98 
     99     /**
    100      * Is equivalent to <code>put()</code> except that
    101      * the given mapping is not recorded into the hashtable
    102      * if another mapping from <code>oldname</code> is
    103      * already included.
    104      *
    105      * @param oldname       the original class name.
    106      * @param newname       the substituted class name.
    107      */
    108     public void putIfNone(String oldname, String newname) {
    109         if (oldname == newname)
    110             return;
    111 
    112         String oldname2 = toJvmName(oldname);
    113         String s = (String)get(oldname2);
    114         if (s == null)
    115             super.put(oldname2, toJvmName(newname));
    116     }
    117 
    118     protected final void put0(Object oldname, Object newname) {
    119         super.put(oldname, newname);
    120     }
    121 
    122     /**
    123      * Returns the class name to wihch the given <code>jvmClassName</code>
    124      * is mapped.  A subclass of this class should override this method.
    125      *
    126      * <p>This method receives and returns the internal representation of
    127      * class name used in the JVM.
    128      *
    129      * @see #toJvmName(String)
    130      * @see #toJavaName(String)
    131      */
    132     public Object get(Object jvmClassName) {
    133         Object found = super.get(jvmClassName);
    134         if (found == null && parent != null)
    135             return parent.get(jvmClassName);
    136         else
    137             return found;
    138     }
    139 
    140     /**
    141      * Prevents a mapping from the specified class name to another name.
    142      */
    143     public void fix(CtClass clazz) {
    144         fix(clazz.getName());
    145     }
    146 
    147     /**
    148      * Prevents a mapping from the specified class name to another name.
    149      */
    150     public void fix(String name) {
    151         String name2 = toJvmName(name);
    152         super.put(name2, name2);
    153     }
    154 
    155     /**
    156      * Converts a class name into the internal representation used in
    157      * the JVM.
    158      */
    159     public static String toJvmName(String classname) {
    160         return Descriptor.toJvmName(classname);
    161     }
    162 
    163     /**
    164      * Converts a class name from the internal representation used in
    165      * the JVM to the normal one used in Java.
    166      */
    167     public static String toJavaName(String classname) {
    168         return Descriptor.toJavaName(classname);
    169     }
    170 }
    171