1 /* 2 * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 package jdk.vm.ci.meta; 24 25 /** 26 * Miscellaneous collection of utility methods used by {@code jdk.vm.ci.meta} and its clients. 27 */ 28 public class MetaUtil { 29 30 /** 31 * Extends the functionality of {@link Class#getSimpleName()} to include a non-empty string for 32 * anonymous and local classes. 33 * 34 * @param clazz the class for which the simple name is being requested 35 * @param withEnclosingClass specifies if the returned name should be qualified with the name(s) 36 * of the enclosing class/classes of {@code clazz} (if any). This option is ignored 37 * if {@code clazz} denotes an anonymous or local class. 38 * @return the simple name 39 */ 40 public static String getSimpleName(Class<?> clazz, boolean withEnclosingClass) { 41 final String simpleName = clazz.getSimpleName(); 42 if (simpleName.length() != 0) { 43 if (withEnclosingClass) { 44 String prefix = ""; 45 Class<?> enclosingClass = clazz; 46 while ((enclosingClass = enclosingClass.getEnclosingClass()) != null) { 47 prefix = enclosingClass.getSimpleName() + "." + prefix; 48 } 49 return prefix + simpleName; 50 } 51 return simpleName; 52 } 53 // Must be an anonymous or local class 54 final String name = clazz.getName(); 55 int index = name.indexOf('$'); 56 if (index == -1) { 57 return name; 58 } 59 index = name.lastIndexOf('.', index); 60 if (index == -1) { 61 return name; 62 } 63 return name.substring(index + 1); 64 } 65 66 /** 67 * Converts a type name in internal form to an external form. 68 * 69 * @param name the internal name to convert 70 * @param qualified whether the returned name should be qualified with the package name 71 * @param classForNameCompatible specifies if the returned name for array types should be in 72 * {@link Class#forName(String)} format (e.g., {@code "[Ljava.lang.Object;"}, 73 * {@code "[[I"}) or in Java source code format (e.g., {@code "java.lang.Object[]"}, 74 * {@code "int[][]"} ). 75 */ 76 public static String internalNameToJava(String name, boolean qualified, boolean classForNameCompatible) { 77 switch (name.charAt(0)) { 78 case 'L': { 79 String result = name.substring(1, name.length() - 1).replace('/', '.'); 80 if (!qualified) { 81 final int lastDot = result.lastIndexOf('.'); 82 if (lastDot != -1) { 83 result = result.substring(lastDot + 1); | 1 /* 2 * Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 package jdk.vm.ci.meta; 24 25 /** 26 * Miscellaneous collection of utility methods used by {@code jdk.vm.ci.meta} and its clients. 27 */ 28 public class MetaUtil { 29 30 /** 31 * Extends the functionality of {@link Class#getSimpleName()} to include a non-empty string for 32 * anonymous and local classes. 33 * 34 * @param clazz the class for which the simple name is being requested 35 * @param withEnclosingClass specifies if the returned name should be qualified with the name(s) 36 * of the enclosing class/classes of {@code clazz} (if any). This option is ignored 37 * if {@code clazz} denotes an anonymous or local class. 38 * @return the simple name 39 */ 40 public static String getSimpleName(Class<?> clazz, boolean withEnclosingClass) { 41 final String simpleName = safeSimpleName(clazz); 42 if (simpleName.length() != 0) { 43 if (withEnclosingClass) { 44 String prefix = ""; 45 Class<?> enclosingClass = clazz; 46 while ((enclosingClass = enclosingClass.getEnclosingClass()) != null) { 47 prefix = safeSimpleName(enclosingClass) + "." + prefix; 48 } 49 return prefix + simpleName; 50 } 51 return simpleName; 52 } 53 // Must be an anonymous or local class 54 final String name = clazz.getName(); 55 int index = name.indexOf('$'); 56 if (index == -1) { 57 return name; 58 } 59 index = name.lastIndexOf('.', index); 60 if (index == -1) { 61 return name; 62 } 63 return name.substring(index + 1); 64 } 65 66 private static String safeSimpleName(Class<?> clazz) { 67 try { 68 return clazz.getSimpleName(); 69 } catch (InternalError e) { 70 // Scala inner class names do not always start with '$', 71 // causing Class.getSimpleName to throw an InternalError 72 Class<?> enclosingClass = clazz.getEnclosingClass(); 73 String fqn = clazz.getName(); 74 if (enclosingClass == null) { 75 // Should never happen given logic in 76 // Class.getSimpleName but best be safe 77 return fqn; 78 } 79 String enclosingFQN = enclosingClass.getName(); 80 int length = fqn.length(); 81 if (enclosingFQN.length() >= length) { 82 // Should also never happen 83 return fqn; 84 } 85 return fqn.substring(enclosingFQN.length()); 86 } 87 } 88 89 /** 90 * Converts a type name in internal form to an external form. 91 * 92 * @param name the internal name to convert 93 * @param qualified whether the returned name should be qualified with the package name 94 * @param classForNameCompatible specifies if the returned name for array types should be in 95 * {@link Class#forName(String)} format (e.g., {@code "[Ljava.lang.Object;"}, 96 * {@code "[[I"}) or in Java source code format (e.g., {@code "java.lang.Object[]"}, 97 * {@code "int[][]"} ). 98 */ 99 public static String internalNameToJava(String name, boolean qualified, boolean classForNameCompatible) { 100 switch (name.charAt(0)) { 101 case 'L': { 102 String result = name.substring(1, name.length() - 1).replace('/', '.'); 103 if (!qualified) { 104 final int lastDot = result.lastIndexOf('.'); 105 if (lastDot != -1) { 106 result = result.substring(lastDot + 1); |