1 /* ClassHelper.java -- Utility methods to augment java.lang.Class 2 Copyright (C) 1998, 2002 Free Software Foundation, Inc. 3 4 This file is part of GNU Classpath. 5 6 GNU Classpath is free software; you can redistribute it and/or modify 7 it under the terms of the GNU General Public License as published by 8 the Free Software Foundation; either version 2, or (at your option) 9 any later version. 10 11 GNU Classpath is distributed in the hope that it will be useful, but 12 WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 General Public License for more details. 15 16 You should have received a copy of the GNU General Public License 17 along with GNU Classpath; see the file COPYING. If not, write to the 18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 19 02110-1301 USA. 20 21 Linking this library statically or dynamically with other modules is 22 making a combined work based on this library. Thus, the terms and 23 conditions of the GNU General Public License cover the whole 24 combination. 25 26 As a special exception, the copyright holders of this library give you 27 permission to link this library with independent modules to produce an 28 executable, regardless of the license terms of these independent 29 modules, and to copy and distribute the resulting executable under 30 terms of your choice, provided that you also meet, for each linked 31 independent module, the terms and conditions of the license of that 32 module. An independent module is a module which is not derived from 33 or based on this library. If you modify this library, you may extend 34 this exception to your version of the library, but you are not 35 obligated to do so. If you do not wish to do so, delete this 36 exception statement from your version. */ 37 38 39 package gnu.java.lang; 40 41 import java.lang.reflect.Field; 42 import java.lang.reflect.Method; 43 import java.util.Arrays; 44 import java.util.HashMap; 45 import java.util.HashSet; 46 import java.util.Iterator; 47 import java.util.Map; 48 import java.util.Set; 49 50 /** 51 * ClassHelper has various methods that ought to have been in Class. 52 * 53 * @author John Keiser 54 * @author Eric Blake (ebb9@email.byu.edu) 55 */ 56 public class ClassHelper 57 { 58 /** 59 * Strip the package part from the class name. 60 * 61 * @param clazz the class to get the truncated name from 62 * @return the truncated class name 63 */ getTruncatedClassName(Class clazz)64 public static String getTruncatedClassName(Class clazz) 65 { 66 return getTruncatedName(clazz.getName()); 67 } 68 69 /** 70 * Strip the package part from the class name, or the class part from 71 * the method or field name. 72 * 73 * @param name the name to truncate 74 * @return the truncated name 75 */ getTruncatedName(String name)76 public static String getTruncatedName(String name) 77 { 78 int lastInd = name.lastIndexOf('.'); 79 if (lastInd == -1) 80 return name; 81 return name.substring(lastInd + 1); 82 } 83 84 /** 85 * Return the name of the class as written by the user. 86 * This is used by the various reflection toString methods. 87 * It differs from {@link Class#getName()} in that it prints 88 * arrays with trailing "[]"s. Note that it does not treat 89 * member classes specially, so a dollar sign may still appear 90 * in the result. This is intentional. 91 * @param klass the class 92 * @return a pretty form of the class' name 93 */ getUserName(Class klass)94 public static String getUserName(Class klass) 95 { 96 int arrayCount = 0; 97 while (klass.isArray()) 98 { 99 ++arrayCount; 100 klass = klass.getComponentType(); 101 } 102 String name = klass.getName(); 103 if (arrayCount == 0) 104 return name; 105 CPStringBuilder b = new CPStringBuilder(name.length() + 2 * arrayCount); 106 b.append(name); 107 for (int i = 0; i < arrayCount; ++i) 108 b.append("[]"); 109 return b.toString(); 110 } 111 112 /** Cache of methods found in getAllMethods(). */ 113 private static Map allMethods = new HashMap(); 114 115 /** 116 * Get all the methods, public, private and otherwise, from the class, 117 * getting them from the most recent class to find them. This may not 118 * be quite the correct approach, as this includes methods that are not 119 * inherited or accessible from clazz, so beware. 120 * 121 * @param clazz the class to start at 122 * @return all methods declared or inherited in clazz 123 */ getAllMethods(Class clazz)124 public static Method[] getAllMethods(Class clazz) 125 { 126 Method[] retval = (Method[]) allMethods.get(clazz); 127 if (retval == null) 128 { 129 Set methods = new HashSet(); 130 Class c = clazz; 131 while (c != null) 132 { 133 Method[] currentMethods = c.getDeclaredMethods(); 134 loop: 135 for (int i = 0; i < currentMethods.length; i++) 136 { 137 Method current = currentMethods[i]; 138 int size = methods.size(); 139 Iterator iter = methods.iterator(); 140 while (--size >= 0) 141 { 142 Method override = (Method) iter.next(); 143 if (current.getName().equals(override.getName()) 144 && Arrays.equals(current.getParameterTypes(), 145 override.getParameterTypes()) 146 && current.getReturnType() == override.getReturnType()) 147 continue loop; 148 } 149 methods.add(current); 150 } 151 c = c.getSuperclass(); 152 } 153 retval = new Method[methods.size()]; 154 methods.toArray(retval); 155 allMethods.put(clazz, retval); 156 } 157 return retval; 158 } 159 160 /** Cache of fields found in getAllFields(). */ 161 private static Map allFields = new HashMap(); 162 163 /** 164 * Get all the fields, public, private and otherwise, from the class, 165 * getting them from the most recent class to find them. This may not 166 * be quite the correct approach, as this includes fields that are not 167 * inherited or accessible from clazz, so beware. 168 * 169 * @param clazz the class to start at 170 * @return all fields declared or inherited in clazz 171 */ getAllFields(Class clazz)172 public static Field[] getAllFields(Class clazz) 173 { 174 Field[] retval = (Field[]) allFields.get(clazz); 175 if (retval == null) 176 { 177 Set fields = new HashSet(); 178 Class c = clazz; 179 while (c != null) 180 { 181 Field[] currentFields = c.getDeclaredFields(); 182 loop: 183 for (int i = 0; i < currentFields.length; i++) 184 { 185 Field current = currentFields[i]; 186 int size = fields.size(); 187 Iterator iter = fields.iterator(); 188 while (--size >= 0) 189 { 190 Field override = (Field) iter.next(); 191 if (current.getName().equals(override.getName()) 192 && current.getType() == override.getType()) 193 continue loop; 194 } 195 fields.add(current); 196 } 197 c = c.getSuperclass(); 198 } 199 retval = new Field[fields.size()]; 200 fields.toArray(retval); 201 allFields.put(clazz, retval); 202 } 203 return retval; 204 } 205 } 206