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