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 16package javassist; 17 18import 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 */ 47public 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